Commit 44bd9db194e87d71b4d7573a2f84c6894256427c

Authored by m-holger
1 parent c290a82f

Refactor: replace `BaseDictionary::replaceKey` method with `BaseHandle::replace`…

… for clarity and consistency across dictionary operations.
include/qpdf/ObjectHandle.hh
... ... @@ -85,6 +85,7 @@ namespace qpdf
85 85  
86 86 bool contains(std::string const& key) const;
87 87 size_t erase(std::string const& key);
  88 + bool replace(std::string const& key, QPDFObjectHandle value);
88 89 QPDFObjectHandle const& operator[](std::string const& key) const;
89 90  
90 91 std::shared_ptr<QPDFObject> copy(bool shallow = false) const;
... ...
libqpdf/NNTree.cc
... ... @@ -168,7 +168,7 @@ NNTreeIterator::resetLimits(Dictionary a_node, std::list&lt;PathElement&gt;::iterator
168 168 }
169 169 }
170 170 if (a_node != path.begin()->node) {
171   - a_node.replaceKey("/Limits", Array({first, last}));
  171 + a_node.replace("/Limits", Array({first, last}));
172 172 }
173 173 }
174 174  
... ... @@ -266,7 +266,7 @@ NNTreeIterator::split(Dictionary to_split, std::list&lt;PathElement&gt;::iterator pare
266 266 new_kids.push_back(first_node);
267 267 to_split.erase("/Limits"); // already shouldn't be there for root
268 268 to_split.erase(impl.itemsKey());
269   - to_split.replaceKey("/Kids", new_kids);
  269 + to_split.replace("/Kids", new_kids);
270 270 if (is_leaf) {
271 271 node = first_node;
272 272 } else {
... ... @@ -446,7 +446,7 @@ NNTreeIterator::remove()
446 446 if (parent == path.end()) {
447 447 // We erased the very last item. Convert the root to an empty items array.
448 448 element->node.erase("/Kids");
449   - element->node.replaceKey(impl.itemsKey(), Array::empty());
  449 + element->node.replace(impl.itemsKey(), Array::empty());
450 450 path.clear();
451 451 setItemNumber(impl.tree_root, -1);
452 452 return;
... ... @@ -673,8 +673,8 @@ NNTreeImpl::repair()
673 673 for (auto const& [key, value]: items) {
674 674 repl.insert(key, value);
675 675 }
676   - tree_root.replaceKey("/Kids", new_node["/Kids"]);
677   - tree_root.replaceKey(itemsKey(), new_node[itemsKey()]);
  676 + tree_root.replace("/Kids", new_node["/Kids"]);
  677 + tree_root.replace(itemsKey(), new_node[itemsKey()]);
678 678 }
679 679  
680 680 NNTreeImpl::iterator
... ...
libqpdf/QPDF.cc
... ... @@ -572,7 +572,7 @@ Objects::Foreign::Copier::replace_indirect_object(QPDFObjectHandle const&amp; foreig
572 572 auto result = Dictionary::empty();
573 573 for (auto const& [key, value]: Dictionary(foreign)) {
574 574 if (!value.null()) {
575   - result.replaceKey(key, replace_indirect_object(value));
  575 + result.replace(key, replace_indirect_object(value));
576 576 }
577 577 }
578 578 return result;
... ... @@ -584,7 +584,7 @@ Objects::Foreign::Copier::replace_indirect_object(QPDFObjectHandle const&amp; foreig
584 584 auto dict = result.getDict();
585 585 for (auto const& [key, value]: stream.getDict()) {
586 586 if (!value.null()) {
587   - dict.replaceKey(key, replace_indirect_object(value));
  587 + dict.replace(key, replace_indirect_object(value));
588 588 }
589 589 }
590 590 stream.copy_data_to(result);
... ... @@ -658,7 +658,7 @@ QPDF::getRoot()
658 658 // approach to more extensive checks and warning levels.
659 659 if (m->cf.check_mode() && Name(Root["/Type"]) != "/Catalog") {
660 660 warn(m->c.damagedPDF("", -1, "catalog /Type entry missing or invalid"));
661   - Root.replaceKey("/Type", Name("/Catalog"));
  661 + Root.replace("/Type", Name("/Catalog"));
662 662 }
663 663 return Root.oh();
664 664 }
... ...
libqpdf/QPDFAcroFormDocumentHelper.cc
... ... @@ -799,7 +799,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
799 799 }
800 800 QPDFObjectHandle(dr).makeResourcesIndirect(qpdf);
801 801 if (!dr.indirect()) {
802   - acroform.replaceKey("/DR", qpdf.makeIndirectObject(dr));
  802 + acroform.replace("/DR", qpdf.makeIndirectObject(dr));
803 803 dr = acroform["/DR"];
804 804 }
805 805 // Merge the other document's /DR, creating a conflict map. mergeResources checks to
... ... @@ -839,7 +839,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
839 839 if (parent.indirect()) {
840 840 auto parent_og = parent.id_gen();
841 841 if (orig_to_copy.contains(parent_og)) {
842   - obj.replaceKey("/Parent", orig_to_copy[parent_og]);
  842 + obj.replace("/Parent", orig_to_copy[parent_og]);
843 843 } else {
844 844 parent.warn(
845 845 "while traversing field " + obj.id_gen().unparse(',') +
... ... @@ -869,7 +869,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
869 869 // chrome, firefox, the mac Preview application, and several of the free
870 870 // readers on Linux all ignore /DR at the field level.
871 871 if (obj.contains("/DR")) {
872   - obj.replaceKey("/DR", dr);
  872 + obj.replace("/DR", dr);
873 873 }
874 874 if (obj["/DA"].isString() && !dr_map.empty()) {
875 875 adjustDefaultAppearances(obj, dr_map);
... ... @@ -988,7 +988,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
988 988 Dictionary apdict = ah.getAppearanceDictionary();
989 989 std::vector<QPDFObjectHandle> streams;
990 990 auto replace_stream = [](auto& dict, auto& key, auto& old) {
991   - dict.replaceKey(key, old.copyStream());
  991 + dict.replace(key, old.copyStream());
992 992 return dict[key];
993 993 };
994 994  
... ... @@ -1015,7 +1015,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
1015 1015 }
1016 1016 apcm.concat(cm);
1017 1017 if (omatrix || apcm != QPDFMatrix()) {
1018   - dict.replaceKey("/Matrix", QPDFObjectHandle::newFromMatrix(apcm));
  1018 + dict.replace("/Matrix", QPDFObjectHandle::newFromMatrix(apcm));
1019 1019 }
1020 1020 Dictionary resources = dict["/Resources"];
1021 1021 if (!dr_map.empty() && resources) {
... ...
libqpdf/QPDFEFStreamObjectHelper.cc
... ... @@ -31,7 +31,7 @@ void
31 31 QPDFEFStreamObjectHelper::setParam(std::string const& pkey, QPDFObjectHandle const& pval)
32 32 {
33 33 if (Dictionary Params = oh().getDict()["/Params"]) {
34   - Params.replaceKey(pkey, pval);
  34 + Params.replace(pkey, pval);
35 35 return;
36 36 }
37 37 oh().getDict().replaceKey("/Params", Dictionary({{pkey, pval}}));
... ...
libqpdf/QPDFFormFieldObjectHelper.cc
... ... @@ -956,7 +956,7 @@ FormField::generateTextAppearance(QPDFAnnotationObjectHelper&amp; aoh)
956 956 aoh.getObjectHandle().replaceKey("/AP", Dictionary::empty());
957 957 AP = aoh.getAppearanceDictionary();
958 958 }
959   - AP.replaceKey("/N", AS);
  959 + AP.replace("/N", AS);
960 960 }
961 961 if (!AS.isStream()) {
962 962 aoh.warn("unable to get normal appearance stream for update");
... ...
libqpdf/QPDF_Dictionary.cc
... ... @@ -63,18 +63,29 @@ BaseHandle::erase(const std::string&amp; key)
63 63 return 0;
64 64 }
65 65  
  66 +bool
  67 +BaseHandle::replace(std::string const& key, QPDFObjectHandle value)
  68 +{
  69 + if (auto d = as<QPDF_Dictionary>()) {
  70 + if (value.null() && !value.indirect()) {
  71 + // The PDF spec doesn't distinguish between keys with null values and missing keys.
  72 + // Allow indirect nulls which are equivalent to a dangling reference, which is permitted
  73 + // by the spec.
  74 + d->items.erase(key);
  75 + } else {
  76 + // add or replace value
  77 + d->items[key] = value;
  78 + }
  79 + return true;
  80 + }
  81 + return false;
  82 +}
  83 +
66 84 void
67   -BaseDictionary::replaceKey(std::string const& key, QPDFObjectHandle value)
68   -{
69   - auto d = dict();
70   - if (value.null() && !value.indirect()) {
71   - // The PDF spec doesn't distinguish between keys with null values and missing keys.
72   - // Allow indirect nulls which are equivalent to a dangling reference, which is
73   - // permitted by the spec.
74   - d->items.erase(key);
75   - } else {
76   - // add or replace value
77   - d->items[key] = value;
  85 +BaseDictionary::replace(std::string const& key, QPDFObjectHandle value)
  86 +{
  87 + if (!BaseHandle::replace(key, value)) {
  88 + (void)dict();
78 89 }
79 90 }
80 91  
... ... @@ -166,11 +177,10 @@ QPDFObjectHandle::replaceKey(std::string const&amp; key, QPDFObjectHandle const&amp; val
166 177 {
167 178 if (auto dict = as_dictionary(strict)) {
168 179 checkOwnership(value);
169   - dict.replaceKey(key, value);
  180 + dict.replace(key, value);
170 181 return;
171 182 }
172 183 typeWarning("dictionary", "ignoring key replacement request");
173   - QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey");
174 184 }
175 185  
176 186 QPDFObjectHandle
... ...
libqpdf/qpdf/QPDFObjectHandle_private.hh
... ... @@ -127,7 +127,7 @@ namespace qpdf
127 127 // The following methods are not part of the public API.
128 128 std::set<std::string> getKeys();
129 129 std::map<std::string, QPDFObjectHandle> const& getAsMap() const;
130   - void replaceKey(std::string const& key, QPDFObjectHandle value);
  130 + void replace(std::string const& key, QPDFObjectHandle value);
131 131  
132 132 using iterator = std::map<std::string, QPDFObjectHandle>::iterator;
133 133 using const_iterator = std::map<std::string, QPDFObjectHandle>::const_iterator;
... ...
qpdf/qpdf.testcov
... ... @@ -171,7 +171,6 @@ QPDFObjectHandle array ignoring erase item 0
171 171 QPDFObjectHandle dictionary false for hasKey 0
172 172 QPDFObjectHandle dictionary empty set for getKeys 0
173 173 QPDFObjectHandle dictionary empty map for asMap 0
174   -QPDFObjectHandle dictionary ignoring replaceKey 0
175 174 QPDFObjectHandle numeric non-numeric 0
176 175 QPDFObjectHandle erase array bounds 0
177 176 qpdf-c called qpdf_check_pdf 0
... ...