diff --git a/ChangeLog b/ChangeLog index 0c9cb388..8ab6f4da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-04-24 Jay Berkenbilt + + * Deprecate QPDFObjectHandle::replaceOrRemoveKey -- it does and + always has done the same thing as replaceKey. + 2022-04-23 Jay Berkenbilt * Add a new QPDF::warn method that takes the parameters of diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index ffffe523..3beab3f5 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1023,13 +1023,16 @@ class QPDFObjectHandle // Mutator methods for dictionary objects - // Replace value of key, adding it if it does not exist + // Replace value of key, adding it if it does not exist. If value + // is null, remove the key. QPDF_DLL - void replaceKey(std::string const& key, QPDFObjectHandle const&); + void replaceKey(std::string const& key, QPDFObjectHandle const& value); // Remove key, doing nothing if key does not exist QPDF_DLL void removeKey(std::string const& key); - // If the object is null, remove the key. Otherwise, replace it. + + // ABI: Remove in qpdf 12 + [[deprecated("use replaceKey -- it does the same thing")]] QPDF_DLL void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle const&); diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 516e38b9..297221df 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -1295,14 +1295,7 @@ void QPDFObjectHandle::replaceOrRemoveKey( std::string const& key, QPDFObjectHandle const& value) { - if (isDictionary()) { - checkOwnership(value); - dynamic_cast(obj.get())->replaceOrRemoveKey( - key, value); - } else { - typeWarning("dictionary", "ignoring key removal/replacement request"); - QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removereplace"); - } + replaceKey(key, value); } // Stream accessors diff --git a/libqpdf/QPDFPageLabelDocumentHelper.cc b/libqpdf/QPDFPageLabelDocumentHelper.cc index 5b2d4358..babfd5aa 100644 --- a/libqpdf/QPDFPageLabelDocumentHelper.cc +++ b/libqpdf/QPDFPageLabelDocumentHelper.cc @@ -44,9 +44,9 @@ QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx) QIntC::range_check(start, offset); start += offset; result = QPDFObjectHandle::newDictionary(); - result.replaceOrRemoveKey("/S", S); - result.replaceOrRemoveKey("/P", P); - result.replaceOrRemoveKey("/St", QPDFObjectHandle::newInteger(start)); + result.replaceKey("/S", S); + result.replaceKey("/P", P); + result.replaceKey("/St", QPDFObjectHandle::newInteger(start)); return result; } diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc index 1655f53a..0423f41f 100644 --- a/libqpdf/QPDF_Dictionary.cc +++ b/libqpdf/QPDF_Dictionary.cc @@ -115,11 +115,16 @@ QPDF_Dictionary::getAsMap() const } void -QPDF_Dictionary::replaceKey( - std::string const& key, QPDFObjectHandle const& value) +QPDF_Dictionary::replaceKey(std::string const& key, QPDFObjectHandle value) { - // add or replace value - this->items[key] = value; + if (value.isNull()) { + // The PDF spec doesn't distinguish between keys with null + // values and missing keys. + removeKey(key); + } else { + // add or replace value + this->items[key] = value; + } } void @@ -128,14 +133,3 @@ QPDF_Dictionary::removeKey(std::string const& key) // no-op if key does not exist this->items.erase(key); } - -void -QPDF_Dictionary::replaceOrRemoveKey( - std::string const& key, QPDFObjectHandle value) -{ - if (value.isNull()) { - removeKey(key); - } else { - replaceKey(key, value); - } -} diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index cbc65611..2d0554b9 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -604,8 +604,8 @@ QPDF_Stream::replaceFilterData( QPDFObjectHandle const& decode_parms, size_t length) { - this->stream_dict.replaceOrRemoveKey("/Filter", filter); - this->stream_dict.replaceOrRemoveKey("/DecodeParms", decode_parms); + this->stream_dict.replaceKey("/Filter", filter); + this->stream_dict.replaceKey("/DecodeParms", decode_parms); if (length == 0) { QTC::TC("qpdf", "QPDF_Stream unknown stream length"); this->stream_dict.removeKey("/Length"); diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index 9ced5b12..926768ad 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -438,7 +438,7 @@ qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value) } QPDFObjectHandle info = trailer.getKey("/Info"); - info.replaceOrRemoveKey(key, value_object); + info.replaceKey(key, value_object); } QPDF_BOOL @@ -1919,7 +1919,7 @@ qpdf_oh_replace_or_remove_key( { do_with_oh_void(qpdf, oh, [qpdf, key, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_or_remove_key"); - o.replaceOrRemoveKey(key, qpdf_oh_item_internal(qpdf, item)); + o.replaceKey(key, qpdf_oh_item_internal(qpdf, item)); }); } diff --git a/libqpdf/qpdf/QPDF_Dictionary.hh b/libqpdf/qpdf/QPDF_Dictionary.hh index 42ee6cf9..3c42cc0e 100644 --- a/libqpdf/qpdf/QPDF_Dictionary.hh +++ b/libqpdf/qpdf/QPDF_Dictionary.hh @@ -27,12 +27,11 @@ class QPDF_Dictionary: public QPDFObject std::set getKeys(); std::map const& getAsMap() const; - // Replace value of key, adding it if it does not exist - void replaceKey(std::string const& key, QPDFObjectHandle const&); + // If value is null, remove key; otherwise, replace the value of + // key, adding it if it does not exist. + void replaceKey(std::string const& key, QPDFObjectHandle value); // Remove key, doing nothing if key does not exist void removeKey(std::string const& key); - // If object is null, remove key; otherwise, replace key - void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle); protected: virtual void releaseResolved(); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 5e0f939c..d679fa25 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -322,7 +322,6 @@ QPDFObjectHandle dictionary empty set for getKeys 0 QPDFObjectHandle dictionary empty map for asMap 0 QPDFObjectHandle dictionary ignoring replaceKey 0 QPDFObjectHandle dictionary ignoring removeKey 0 -QPDFObjectHandle dictionary ignoring removereplace 0 QPDFObjectHandle numeric non-numeric 0 QPDFObjectHandle erase array bounds 0 qpdf-c called qpdf_check_pdf 0 diff --git a/qpdf/qtest/qpdf/object-types-os.out b/qpdf/qtest/qpdf/object-types-os.out index 5aedc1ee..a95fa4d8 100644 --- a/qpdf/qtest/qpdf/object-types-os.out +++ b/qpdf/qtest/qpdf/object-types-os.out @@ -16,8 +16,7 @@ WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operatio WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: treating as empty WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: returning false for a key containment request WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: ignoring key removal request -WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: ignoring key removal/replacement request -WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: ignoring key removal/replacement request +WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: ignoring key replacement request WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: ignoring key replacement request WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: returning null for attempted key retrieval WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for dictionary attempted on object of type integer: returning null for attempted key retrieval diff --git a/qpdf/qtest/qpdf/object-types.out b/qpdf/qtest/qpdf/object-types.out index 01a8e7c7..718105db 100644 --- a/qpdf/qtest/qpdf/object-types.out +++ b/qpdf/qtest/qpdf/object-types.out @@ -16,8 +16,7 @@ WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary at WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: treating as empty WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: returning false for a key containment request WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: ignoring key removal request -WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: ignoring key removal/replacement request -WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: ignoring key removal/replacement request +WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: ignoring key replacement request WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: ignoring key replacement request WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: returning null for attempted key retrieval WARNING: object-types.pdf, object 8 0 at offset 669: operation for dictionary attempted on object of type integer: returning null for attempted key retrieval diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 14c6c316..0245e0f5 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1481,8 +1481,7 @@ test_42(QPDF& pdf, char const* arg2) assert(integer.getKeys().empty()); assert(false == integer.hasKey("/Potato")); integer.removeKey("/Potato"); - integer.replaceOrRemoveKey("/Potato", null); - integer.replaceOrRemoveKey("/Potato", QPDFObjectHandle::newInteger(1)); + integer.replaceKey("/Potato", null); integer.replaceKey("/Potato", QPDFObjectHandle::newInteger(1)); null.getKeyIfDict("/Integer").getKeyIfDict("/Potato").assertNull(); qtest.getKey("/Integer").getKeyIfDict("/Potato");