blob: db1e4b5ca32c9d2bd213d1cae79dd5a25f553e26 [file]
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef THIRD_PARTY_CREDENTIO_FORMATS_PDF_READER_H_
#define THIRD_PARTY_CREDENTIO_FORMATS_PDF_READER_H_
#include <cstdint>
#include <memory>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/status/statusor.h"
#include "formats/pdf/objects.h"
#include "riegeli/bytes/reader.h"
namespace credentio {
// PDF reader for C2PA, holds onto a reference to a `riegeli::Reader` which
// must outlive the reader.
class PdfReader {
public:
// Creates and initializes a PdfReader.
static absl::StatusOr<std::unique_ptr<PdfReader>> Create(
riegeli::Reader* absl_nonnull input);
// Returns true if there is a next PDF object to read.
bool HasNext();
// Reads the next PDF object from the input.
absl::StatusOr<IndirectObject> Next();
// Returns the file trailer dictionary.
const Object::Dictionary& file_trailer_dictionary() const {
return file_trailer_dictionary_;
}
// Returns the ordered set of free object entries in the cross-reference
// table.
const absl::btree_set<Object::IndirectReference>& free_entries() const {
return free_entries_;
}
// Returns the byte offset of the PDF object with the given object number and
// generation number. If the object is not found, returns a NOT_FOUND error.
absl::StatusOr<uint64_t> GetObjectOffset(uint32_t object_number,
uint32_t generation_number);
// Returns the PDF object with the given object number and generation number.
// If the object is not found, returns a NOT_FOUND error.
absl::StatusOr<IndirectObject> GetObject(uint32_t object_number,
uint32_t generation_number);
private:
explicit PdfReader(
riegeli::Reader* absl_nonnull input,
absl::btree_map<Object::IndirectReference, uint64_t>&& xref_table,
absl::btree_set<Object::IndirectReference>&& free_entries,
Object::Dictionary&& file_trailer_dict)
: input_(*input),
xref_table_(std::move(xref_table)),
current_it_(xref_table_.begin()),
free_entries_(std::move(free_entries)),
file_trailer_dictionary_(std::move(file_trailer_dict)) {}
riegeli::Reader& input_;
// Cross-reference table mapping in-use object references to their byte
// offsets in the input stream.
const absl::btree_map<Object::IndirectReference, uint64_t> xref_table_;
absl::btree_map<Object::IndirectReference, uint64_t>::const_iterator
current_it_;
// Set of free object entries in the cross-reference table.
const absl::btree_set<Object::IndirectReference> free_entries_;
// File trailer dictionary.
const Object::Dictionary file_trailer_dictionary_;
// Active objects during indirect reference resolution to detect cycles.
absl::btree_set<Object::IndirectReference> active_objects_;
};
} // namespace credentio
#endif // THIRD_PARTY_CREDENTIO_FORMATS_PDF_READER_H_