Commit 44bd9db194e87d71b4d7573a2f84c6894256427c
1 parent
c290a82f
Refactor: replace `BaseDictionary::replaceKey` method with `BaseHandle::replace`…
… for clarity and consistency across dictionary operations.
Showing
9 changed files
with
40 additions
and
30 deletions
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<PathElement>::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<PathElement>::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& 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& 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& 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& 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& key, QPDFObjectHandle const& 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 | ... | ... |