From cbeaf5a89e75f883a10bbad1a491969000b552c6 Mon Sep 17 00:00:00 2001 From: m-holger Date: Tue, 19 Aug 2025 15:44:52 +0100 Subject: [PATCH] Refactor `BaseDictionary` and `Dictionary` constructors, add `operator[]` for dictionary key access, and simplify null handling logic. --- include/qpdf/ObjectHandle.hh | 2 ++ libqpdf/QPDF_Dictionary.cc | 30 +++++++++++++++++++++++++++++- libqpdf/qpdf/QPDFObjectHandle_private.hh | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- qpdf/qpdf.testcov | 1 - 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/include/qpdf/ObjectHandle.hh b/include/qpdf/ObjectHandle.hh index 1966cd3..7eb0a64 100644 --- a/include/qpdf/ObjectHandle.hh +++ b/include/qpdf/ObjectHandle.hh @@ -83,6 +83,8 @@ namespace qpdf QPDFObjectHandle operator[](size_t n) const; QPDFObjectHandle operator[](int n) const; + QPDFObjectHandle const& operator[](std::string const& key) const; + std::shared_ptr copy(bool shallow = false) const; // Recursively remove association with any QPDF object. This method may only be called // during final destruction. diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc index d34d309..659f676 100644 --- a/libqpdf/QPDF_Dictionary.cc +++ b/libqpdf/QPDF_Dictionary.cc @@ -16,6 +16,19 @@ BaseDictionary::dict() const return nullptr; // unreachable } +QPDFObjectHandle const& +BaseHandle::operator[](std::string const& key) const +{ + if (auto d = as()) { + auto it = d->items.find(key); + if (it != d->items.end()) { + return it->second; + } + } + static const QPDFObjectHandle null_obj; + return null_obj; +} + bool BaseDictionary::hasKey(std::string const& key) const { @@ -78,13 +91,28 @@ BaseDictionary::replaceKey(std::string const& key, QPDFObjectHandle value) } } +Dictionary::Dictionary(std::map&& dict) : + BaseDictionary(std::move(dict)) +{ +} + +Dictionary::Dictionary(std::shared_ptr const& obj) : + BaseDictionary(obj) +{ +} + +Dictionary +Dictionary::empty() +{ + return Dictionary(std::map()); +} + void QPDFObjectHandle::checkOwnership(QPDFObjectHandle const& item) const { auto qpdf = getOwningQPDF(); auto item_qpdf = item.getOwningQPDF(); if (qpdf && item_qpdf && qpdf != item_qpdf) { - QTC::TC("qpdf", "QPDFObjectHandle check ownership"); throw std::logic_error( "Attempting to add an object from a different QPDF. Use " "QPDF::copyForeignObject to add objects from another file."); diff --git a/libqpdf/qpdf/QPDFObjectHandle_private.hh b/libqpdf/qpdf/QPDFObjectHandle_private.hh index b0d5a04..0e6789e 100644 --- a/libqpdf/qpdf/QPDFObjectHandle_private.hh +++ b/libqpdf/qpdf/QPDFObjectHandle_private.hh @@ -119,6 +119,14 @@ namespace qpdf class BaseDictionary: public BaseHandle { public: + // The following methods are not part of the public API. + bool hasKey(std::string const& key) const; + QPDFObjectHandle getKey(std::string const& key) const; + std::set getKeys(); + std::map const& getAsMap() const; + void removeKey(std::string const& key); + void replaceKey(std::string const& key, QPDFObjectHandle value); + using iterator = std::map::iterator; using const_iterator = std::map::const_iterator; using reverse_iterator = std::map::reverse_iterator; @@ -197,41 +205,87 @@ namespace qpdf return {}; } - // The following methods are not part of the public API. - bool hasKey(std::string const& key) const; - QPDFObjectHandle getKey(std::string const& key) const; - std::set getKeys(); - std::map const& getAsMap() const; - void removeKey(std::string const& key); - void replaceKey(std::string const& key, QPDFObjectHandle value); - protected: BaseDictionary() = default; - BaseDictionary(std::shared_ptr const& obj) : - BaseHandle(obj) {}; - BaseDictionary(std::shared_ptr&& obj) : - BaseHandle(std::move(obj)) {}; + + explicit BaseDictionary(std::map const& dict) : + BaseHandle(QPDFObject::create(dict)) + { + } + + explicit BaseDictionary(std::map&& dict) : + BaseHandle(QPDFObject::create(std::move(dict))) + { + } + + explicit BaseDictionary(std::shared_ptr const& obj) : + BaseHandle(obj) + { + } + explicit BaseDictionary(std::shared_ptr&& obj) : + BaseHandle(std::move(obj)) + { + } BaseDictionary(BaseDictionary const&) = default; BaseDictionary& operator=(BaseDictionary const&) = default; BaseDictionary(BaseDictionary&&) = default; BaseDictionary& operator=(BaseDictionary&&) = default; + + explicit BaseDictionary(QPDFObjectHandle const& oh) : + BaseHandle(oh.resolved_type_code() == ::ot_dictionary ? oh : QPDFObjectHandle()) + { + } + + explicit BaseDictionary(QPDFObjectHandle&& oh) : + BaseHandle( + oh.resolved_type_code() == ::ot_dictionary ? std::move(oh) : QPDFObjectHandle()) + { + } ~BaseDictionary() = default; QPDF_Dictionary* dict() const; }; + // Dictionary only defines con/destructors. All other methods are inherited from BaseDictionary. class Dictionary final: public BaseDictionary { public: - explicit Dictionary(std::shared_ptr const& obj) : - BaseDictionary(obj) + Dictionary() = default; + explicit Dictionary(std::map&& dict); + explicit Dictionary(std::shared_ptr const& obj); + + static Dictionary empty(); + + Dictionary(Dictionary const&) = default; + Dictionary& operator=(Dictionary const&) = default; + Dictionary(Dictionary&&) = default; + Dictionary& operator=(Dictionary&&) = default; + + Dictionary(QPDFObjectHandle const& oh) : + BaseDictionary(oh) + { + } + + Dictionary& + operator=(QPDFObjectHandle const& oh) + { + assign(::ot_dictionary, oh); + return *this; + } + + Dictionary(QPDFObjectHandle&& oh) : + BaseDictionary(std::move(oh)) { } - explicit Dictionary(std::shared_ptr&& obj) : - BaseDictionary(std::move(obj)) + Dictionary& + operator=(QPDFObjectHandle&& oh) { + assign(::ot_dictionary, std::move(oh)); + return *this; } + + ~Dictionary() = default; }; class Name final: public BaseHandle diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 4ef9125..3cfd74a 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -537,7 +537,6 @@ QPDFWriter preserve object streams 0 QPDFWriter preserve object streams preserve unreferenced 0 QPDFWriter exclude from object stream 0 QPDF_pages findPage not found 0 -QPDFObjectHandle check ownership 0 QPDFJob weak crypto error 0 qpdf-c called qpdf_oh_is_initialized 0 qpdf-c registered progress reporter 0 -- libgit2 0.21.4