From 56f1b411feeb58b55e92ee77daffaa49c51b7dad Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 17 May 2022 18:28:50 -0400 Subject: [PATCH] Back out fluent QPDFObjectHandle methods. Keep the andGet methods. I decided these were confusing and inconsistent with how JSON works. They muddle the API rather than improving it. --- ChangeLog | 15 ++--- examples/pdf-attach-file.cc | 8 +-- examples/pdf-create.cc | 15 ++--- include/qpdf/QPDFObjectHandle.hh | 26 ++++----- libqpdf/NNTree.cc | 17 +++--- libqpdf/QPDFAcroFormDocumentHelper.cc | 3 +- libqpdf/QPDFFileSpecObjectHelper.cc | 4 +- libqpdf/QPDFObjectHandle.cc | 15 ++--- libqpdf/QPDFPageLabelDocumentHelper.cc | 5 +- libqpdf/QPDFPageObjectHelper.cc | 14 ++--- libqpdf/QPDF_Stream.cc | 4 +- libtests/nntree.cc | 37 ++++++------ manual/release-notes.rst | 9 +-- qpdf/pdf_from_scratch.cc | 11 ++-- qpdf/test_driver.cc | 80 +++++++++++++------------- qpdf/test_large_file.cc | 50 ++++++++-------- 16 files changed, 149 insertions(+), 164 deletions(-) diff --git a/ChangeLog b/ChangeLog index a194440a..41c4671b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -86,15 +86,12 @@ 2022-04-29 Jay Berkenbilt * QPDFObjectHandle: for the methods insertItem, appendItem, - eraseItem, replaceKey, and removeKey, have the methods return a - reference to the original object, making a fluent interface to - initializing or modifying QPDFObjectHandle possible. Also, for - each one, add a corresponding "AndGet" method (insertItemAndGet, - appendItemAndGet, eraseItemAndGet, replaceKeyAndGet, and - removeKeyAndGet) that returns the newly inserted, replaced, or - removed item. This makes it possible to create a new object, add - it to an array or dictionary, and get a handle to it all in one - line. + eraseItem, replaceKey, and removeKey, add a corresponding "AndGet" + method (insertItemAndGet, appendItemAndGet, eraseItemAndGet, + replaceKeyAndGet, and removeKeyAndGet) that returns the newly + inserted, replaced, or removed item. This makes it possible to + create a new object, add it to an array or dictionary, and get a + handle to it all in one line. 2022-04-24 Jay Berkenbilt diff --git a/examples/pdf-attach-file.cc b/examples/pdf-attach-file.cc index 0d15122f..eb12a002 100644 --- a/examples/pdf-attach-file.cc +++ b/examples/pdf-attach-file.cc @@ -106,10 +106,10 @@ process( // apdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject")); // apdict.replaceKey("/Subtype", QPDFObjectHandle::newName("/Form")); // apdict.replaceKey("/BBox", QPDFObjectHandle::parse("[ 0 0 20 20 ]")); - apdict.replaceKey("/Resources", "<< >>"_qpdf) - .replaceKey("/Type", "/XObject"_qpdf) - .replaceKey("/Subtype", "/Form"_qpdf) - .replaceKey("/BBox", "[ 0 0 20 20 ]"_qpdf); + apdict.replaceKey("/Resources", "<< >>"_qpdf); + apdict.replaceKey("/Type", "/XObject"_qpdf); + apdict.replaceKey("/Subtype", "/Form"_qpdf); + apdict.replaceKey("/BBox", "[ 0 0 20 20 ]"_qpdf); auto annot = q.makeIndirectObject(QPDFObjectHandle::parse( &q, ("<<" diff --git a/examples/pdf-create.cc b/examples/pdf-create.cc index 493b0d3d..5e9e4239 100644 --- a/examples/pdf-create.cc +++ b/examples/pdf-create.cc @@ -181,9 +181,9 @@ add_page( " /Subtype /Image" " /BitsPerComponent 8" ">>"_qpdf; - image_dict.replaceKey("/ColorSpace", newName(color_space)) - .replaceKey("/Width", newInteger(width)) - .replaceKey("/Height", newInteger(height)); + image_dict.replaceKey("/ColorSpace", newName(color_space)); + image_dict.replaceKey("/Width", newInteger(width)); + image_dict.replaceKey("/Height", newInteger(height)); image.replaceDict(image_dict); // Provide the stream data. @@ -200,9 +200,9 @@ add_page( xobject.replaceKey("/Im1", image); QPDFObjectHandle resources = QPDFObjectHandle::newDictionary(); - resources.replaceKey("/ProcSet", procset) - .replaceKey("/Font", rfont) - .replaceKey("/XObject", xobject); + resources.replaceKey("/ProcSet", procset); + resources.replaceKey("/Font", rfont); + resources.replaceKey("/XObject", xobject); // Create the page content stream QPDFObjectHandle contents = @@ -213,7 +213,8 @@ add_page( " /Type /Page" " /MediaBox [0 0 612 392]" ">>"_qpdf); - page.replaceKey("/Contents", contents).replaceKey("/Resources", resources); + page.replaceKey("/Contents", contents); + page.replaceKey("/Resources", resources); // Add the page to the PDF file dh.addPage(page, false); diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 5bdafb31..2265459d 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1024,25 +1024,22 @@ class QPDFObjectHandle void setArrayFromVector(std::vector const& items); // Insert an item before the item at the given position ("at") so // that it has that position after insertion. If "at" is equal to - // the size of the array, insert the item at the end. Return a - // reference to the array (not the new item). + // the size of the array, insert the item at the end. QPDF_DLL - QPDFObjectHandle& insertItem(int at, QPDFObjectHandle const& item); + void insertItem(int at, QPDFObjectHandle const& item); // Like insertItem but return the item that was inserted. QPDF_DLL QPDFObjectHandle insertItemAndGet(int at, QPDFObjectHandle const& item); - // Append an item, and return a reference to the original array - // (not the new item). + // Append an item to an array. QPDF_DLL - QPDFObjectHandle& appendItem(QPDFObjectHandle const& item); + void appendItem(QPDFObjectHandle const& item); // Append an item, and return the newly added item. QPDF_DLL QPDFObjectHandle appendItemAndGet(QPDFObjectHandle const& item); // Remove the item at that position, reducing the size of the - // array by one. Return a reference the original array (not the - // item that was removed). + // array by one. QPDF_DLL - QPDFObjectHandle& eraseItem(int at); + void eraseItem(int at); // Erase and item and return the item that was removed. QPDF_DLL QPDFObjectHandle eraseItemAndGet(int at); @@ -1050,19 +1047,16 @@ class QPDFObjectHandle // Mutator methods for dictionary objects // Replace value of key, adding it if it does not exist. If value - // is null, remove the key. Return a reference to the original - // dictionary (not the new item). + // is null, remove the key. QPDF_DLL - QPDFObjectHandle& - replaceKey(std::string const& key, QPDFObjectHandle const& value); + void replaceKey(std::string const& key, QPDFObjectHandle const& value); // Replace value of key and return the value. QPDF_DLL QPDFObjectHandle replaceKeyAndGet(std::string const& key, QPDFObjectHandle const& value); - // Remove key, doing nothing if key does not exist. Return the - // original dictionary (not the removed item). + // Remove key, doing nothing if key does not exist. QPDF_DLL - QPDFObjectHandle& removeKey(std::string const& key); + void removeKey(std::string const& key); // Remove key and return the old value. If the old value didn't // exist, return a null object. QPDF_DLL diff --git a/libqpdf/NNTree.cc b/libqpdf/NNTree.cc index bfeb15a1..a5df209d 100644 --- a/libqpdf/NNTree.cc +++ b/libqpdf/NNTree.cc @@ -208,8 +208,9 @@ NNTreeIterator::resetLimits( } } if (first.isInitialized() && last.isInitialized()) { - auto limits = - QPDFObjectHandle::newArray().appendItem(first).appendItem(last); + auto limits = QPDFObjectHandle::newArray(); + limits.appendItem(first); + limits.appendItem(last); auto olimits = node.getKey("/Limits"); if (olimits.isArray() && (olimits.getArrayNItems() == 2)) { auto ofirst = olimits.getArrayItem(0); @@ -340,10 +341,9 @@ NNTreeIterator::split( first_node.replaceKey(key, first_half); QPDFObjectHandle new_kids = QPDFObjectHandle::newArray(); new_kids.appendItem(first_node); - to_split - .removeKey("/Limits") // already shouldn't be there for root - .removeKey(impl.details.itemsKey()) - .replaceKey("/Kids", new_kids); + to_split.removeKey("/Limits"); // already shouldn't be there for root + to_split.removeKey(impl.details.itemsKey()); + to_split.replaceKey("/Kids", new_kids); if (is_leaf) { QTC::TC("qpdf", "NNTree split root + leaf"); this->node = first_node; @@ -884,8 +884,9 @@ NNTreeImpl::repair() for (auto const& i: *this) { repl.insert(i.first, i.second); } - this->oh.replaceKey("/Kids", new_node.getKey("/Kids")) - .replaceKey(details.itemsKey(), new_node.getKey(details.itemsKey())); + this->oh.replaceKey("/Kids", new_node.getKey("/Kids")); + this->oh.replaceKey( + details.itemsKey(), new_node.getKey(details.itemsKey())); } NNTreeImpl::iterator diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index 4e9f08b9..70d01b30 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -733,7 +733,8 @@ QPDFAcroFormDocumentHelper::adjustAppearanceStream( auto existing_old = subdict.getKey(old_key); if (!existing_old.isNull()) { QTC::TC("qpdf", "QPDFAcroFormDocumentHelper ap rename"); - subdict.replaceKey(new_key, existing_old).removeKey(old_key); + subdict.replaceKey(new_key, existing_old); + subdict.removeKey(old_key); } } } diff --git a/libqpdf/QPDFFileSpecObjectHelper.cc b/libqpdf/QPDFFileSpecObjectHelper.cc index f9c19e3c..fcc19b45 100644 --- a/libqpdf/QPDFFileSpecObjectHelper.cc +++ b/libqpdf/QPDFFileSpecObjectHelper.cc @@ -103,8 +103,8 @@ QPDFFileSpecObjectHelper::createFileSpec( QPDFFileSpecObjectHelper result(oh); result.setFilename(filename); auto ef = QPDFObjectHandle::newDictionary(); - ef.replaceKey("/F", efsoh.getObjectHandle()) - .replaceKey("/UF", efsoh.getObjectHandle()); + ef.replaceKey("/F", efsoh.getObjectHandle()); + ef.replaceKey("/UF", efsoh.getObjectHandle()); oh.replaceKey("/EF", ef); return result; } diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 4a0a69ae..f3d1883a 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -959,7 +959,7 @@ QPDFObjectHandle::setArrayFromVector(std::vector const& items) } } -QPDFObjectHandle& +void QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) { if (isArray()) { @@ -968,7 +968,6 @@ QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) typeWarning("array", "ignoring attempt to insert item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); } - return *this; } QPDFObjectHandle @@ -978,7 +977,7 @@ QPDFObjectHandle::insertItemAndGet(int at, QPDFObjectHandle const& item) return item; } -QPDFObjectHandle& +void QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) { if (isArray()) { @@ -988,7 +987,6 @@ QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) typeWarning("array", "ignoring attempt to append item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); } - return *this; } QPDFObjectHandle @@ -998,7 +996,7 @@ QPDFObjectHandle::appendItemAndGet(QPDFObjectHandle const& item) return item; } -QPDFObjectHandle& +void QPDFObjectHandle::eraseItem(int at) { if (isArray() && (at < getArrayNItems()) && (at >= 0)) { @@ -1012,7 +1010,6 @@ QPDFObjectHandle::eraseItem(int at) QTC::TC("qpdf", "QPDFObjectHandle array ignoring erase item"); } } - return *this; } QPDFObjectHandle @@ -1289,7 +1286,7 @@ QPDFObjectHandle::getOwningQPDF() // Dictionary mutators -QPDFObjectHandle& +void QPDFObjectHandle::replaceKey( std::string const& key, QPDFObjectHandle const& value) { @@ -1300,7 +1297,6 @@ QPDFObjectHandle::replaceKey( typeWarning("dictionary", "ignoring key replacement request"); QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); } - return *this; } QPDFObjectHandle @@ -1311,7 +1307,7 @@ QPDFObjectHandle::replaceKeyAndGet( return value; } -QPDFObjectHandle& +void QPDFObjectHandle::removeKey(std::string const& key) { if (isDictionary()) { @@ -1320,7 +1316,6 @@ QPDFObjectHandle::removeKey(std::string const& key) typeWarning("dictionary", "ignoring key removal request"); QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); } - return *this; } QPDFObjectHandle diff --git a/libqpdf/QPDFPageLabelDocumentHelper.cc b/libqpdf/QPDFPageLabelDocumentHelper.cc index 8f3472c1..babfd5aa 100644 --- a/libqpdf/QPDFPageLabelDocumentHelper.cc +++ b/libqpdf/QPDFPageLabelDocumentHelper.cc @@ -44,8 +44,9 @@ QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx) QIntC::range_check(start, offset); start += offset; result = QPDFObjectHandle::newDictionary(); - result.replaceKey("/S", S).replaceKey("/P", P).replaceKey( - "/St", QPDFObjectHandle::newInteger(start)); + result.replaceKey("/S", S); + result.replaceKey("/P", P); + result.replaceKey("/St", QPDFObjectHandle::newInteger(start)); return result; } diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index a8880ec0..6c38f098 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -78,8 +78,8 @@ QPDFObjectHandle InlineImageTracker::convertIIDict(QPDFObjectHandle odict) { QPDFObjectHandle dict = QPDFObjectHandle::newDictionary(); - dict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject")) - .replaceKey("/Subtype", QPDFObjectHandle::newName("/Image")); + dict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject")); + dict.replaceKey("/Subtype", QPDFObjectHandle::newName("/Image")); std::set keys = odict.getKeys(); for (auto key: keys) { QPDFObjectHandle value = odict.getKey(key); @@ -752,11 +752,11 @@ QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations) } QPDFObjectHandle result = QPDFObjectHandle::newStream(qpdf); QPDFObjectHandle newdict = result.getDict(); - newdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject")) - .replaceKey("/Subtype", QPDFObjectHandle::newName("/Form")) - .replaceKey( - "/Resources", getAttribute("/Resources", false).shallowCopy()) - .replaceKey("/Group", getAttribute("/Group", false).shallowCopy()); + newdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject")); + newdict.replaceKey("/Subtype", QPDFObjectHandle::newName("/Form")); + newdict.replaceKey( + "/Resources", getAttribute("/Resources", false).shallowCopy()); + newdict.replaceKey("/Group", getAttribute("/Group", false).shallowCopy()); QPDFObjectHandle bbox = getTrimBox(false).shallowCopy(); if (!bbox.isRectangle()) { this->oh.warnIfPossible("bounding box is invalid; form" diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index ff62df73..c6f0d873 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -725,8 +725,8 @@ QPDF_Stream::replaceFilterData( QPDFObjectHandle const& decode_parms, size_t length) { - this->stream_dict.replaceKey("/Filter", filter) - .replaceKey("/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/libtests/nntree.cc b/libtests/nntree.cc index 2296a27c..98e4fc77 100644 --- a/libtests/nntree.cc +++ b/libtests/nntree.cc @@ -62,15 +62,16 @@ test_bsearch() auto mk = [&q](std::vector const& v) { auto nums = QPDFObjectHandle::newArray(); for (auto i: v) { - nums.appendItem(QPDFObjectHandle::newInteger(i)) - .appendItem(QPDFObjectHandle::newString( - "-" + QUtil::int_to_string(i) + "-")); + nums.appendItem(QPDFObjectHandle::newInteger(i)); + nums.appendItem(QPDFObjectHandle::newString( + "-" + QUtil::int_to_string(i) + "-")); } auto limits = QPDFObjectHandle::newArray(); - limits.appendItem(QPDFObjectHandle::newInteger(v.at(0))) - .appendItem(QPDFObjectHandle::newInteger(v.at(v.size() - 1))); + limits.appendItem(QPDFObjectHandle::newInteger(v.at(0))); + limits.appendItem(QPDFObjectHandle::newInteger(v.at(v.size() - 1))); auto node = q.makeIndirectObject(QPDFObjectHandle::newDictionary()); - node.replaceKey("/Nums", nums).replaceKey("/Limits", limits); + node.replaceKey("/Nums", nums); + node.replaceKey("/Limits", limits); return node; }; @@ -168,8 +169,8 @@ test_depth() int val = (((((i1 * NITEMS) + i2) * NITEMS) + i3) * NITEMS) + i4; std::string str = QUtil::int_to_string(10 * val, 6); - items.appendItem(QPDFObjectHandle::newString(str)) - .appendItem(QPDFObjectHandle::newString("val " + str)); + items.appendItem(QPDFObjectHandle::newString(str)); + items.appendItem(QPDFObjectHandle::newString("val " + str)); if (i4 == 0) { first = str; } else if (i4 == NITEMS - 1) { @@ -178,23 +179,21 @@ test_depth() } auto limits = QPDFObjectHandle::newArray(); n3.replaceKey("/Limits", limits); - limits.appendItem(QPDFObjectHandle::newString(first)) - .appendItem(QPDFObjectHandle::newString(last)); + limits.appendItem(QPDFObjectHandle::newString(first)); + limits.appendItem(QPDFObjectHandle::newString(last)); } auto limits = QPDFObjectHandle::newArray(); n2.replaceKey("/Limits", limits); - limits - .appendItem( - k2.getArrayItem(0).getKey("/Limits").getArrayItem(0)) - .appendItem(k2.getArrayItem(NITEMS - 1) - .getKey("/Limits") - .getArrayItem(1)); + limits.appendItem( + k2.getArrayItem(0).getKey("/Limits").getArrayItem(0)); + limits.appendItem( + k2.getArrayItem(NITEMS - 1).getKey("/Limits").getArrayItem(1)); } auto limits = QPDFObjectHandle::newArray(); n1.replaceKey("/Limits", limits); - limits.appendItem(k1.getArrayItem(0).getKey("/Limits").getArrayItem(0)) - .appendItem( - k1.getArrayItem(NITEMS - 1).getKey("/Limits").getArrayItem(1)); + limits.appendItem(k1.getArrayItem(0).getKey("/Limits").getArrayItem(0)); + limits.appendItem( + k1.getArrayItem(NITEMS - 1).getKey("/Limits").getArrayItem(1)); } QPDFNameTreeObjectHelper nh(n0, q); diff --git a/manual/release-notes.rst b/manual/release-notes.rst index 043245f4..31ddabfd 100644 --- a/manual/release-notes.rst +++ b/manual/release-notes.rst @@ -98,12 +98,9 @@ For a detailed list of changes, please see the file - Library Enhancements - - Support for more fluent programming with ``QPDFObjectHandle``. - The methods ``insertItem``, ``appendItem``, ``eraseItem``, - ``replaceKey``, and ``removeKey`` all return a reference to the - object being modified. New methods ``insertItemAndGet``, - ``appendItemAndGet``, ``eraseItemAndGet``, ``replaceKeyAndGet``, - and ``removeKeyAndGet`` return the newly added or removed object. + - New methods ``insertItemAndGet``, ``appendItemAndGet``, + ``eraseItemAndGet``, ``replaceKeyAndGet``, and + ``removeKeyAndGet`` return the newly added or removed object. - Add new ``Pipeline`` methods to reduce the amount of casting that is needed: diff --git a/qpdf/pdf_from_scratch.cc b/qpdf/pdf_from_scratch.cc index 2af5d437..c401e9af 100644 --- a/qpdf/pdf_from_scratch.cc +++ b/qpdf/pdf_from_scratch.cc @@ -60,14 +60,15 @@ runtest(int n) rfont.replaceKey("/F1", font); QPDFObjectHandle resources = QPDFObjectHandle::newDictionary(); - resources.replaceKey("/ProcSet", procset).replaceKey("/Font", rfont); + resources.replaceKey("/ProcSet", procset); + resources.replaceKey("/Font", rfont); QPDFObjectHandle page = pdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); - page.replaceKey("/Type", newName("/Page")) - .replaceKey("/MediaBox", mediabox) - .replaceKey("/Contents", contents) - .replaceKey("/Resources", resources); + page.replaceKey("/Type", newName("/Page")); + page.replaceKey("/MediaBox", mediabox); + page.replaceKey("/Contents", contents); + page.replaceKey("/Resources", resources); QPDFPageDocumentHelper(pdf).addPage(page, true); diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index acd9049b..f355aa54 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -525,7 +525,8 @@ test_9(QPDF& pdf, char const* arg2) "data for other stream\n", QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull()); - root.replaceKey("/QStream", qstream).replaceKey("/RStream", rstream); + root.replaceKey("/QStream", qstream); + root.replaceKey("/RStream", rstream); QPDFWriter w(pdf, "a.pdf"); w.setStaticID(true); w.setStreamDataMode(qpdf_s_preserve); @@ -895,12 +896,15 @@ test_24(QPDF& pdf, char const* arg2) QPDFObjectHandle res1 = QPDFObjectHandle::newReserved(&pdf); QPDFObjectHandle res2 = QPDFObjectHandle::newReserved(&pdf); QPDFObjectHandle trailer = pdf.getTrailer(); - trailer.replaceKey("Array1", res1).replaceKey("Array2", res2); + trailer.replaceKey("Array1", res1); + trailer.replaceKey("Array2", res2); QPDFObjectHandle array1 = QPDFObjectHandle::newArray(); QPDFObjectHandle array2 = QPDFObjectHandle::newArray(); - array1.appendItem(res2).appendItem(QPDFObjectHandle::newInteger(1)); - array2.appendItem(res1).appendItem(QPDFObjectHandle::newInteger(2)); + array1.appendItem(res2); + array1.appendItem(QPDFObjectHandle::newInteger(1)); + array2.appendItem(res1); + array2.appendItem(QPDFObjectHandle::newInteger(2)); // Make sure trying to ask questions about a reserved object // doesn't break it. if (res1.isArray()) { @@ -1065,14 +1069,13 @@ test_27(QPDF& pdf, char const* arg2) dh.addPage(O3.getKey("/OtherPage"), false); dh.addPage(O3, false); QPDFObjectHandle s2 = QPDFObjectHandle::newStream(&oldpdf, "potato\n"); - pdf.getTrailer() - .replaceKey("/QTest", pdf.copyForeignObject(qtest)) - .replaceKey("/QTest2", QPDFObjectHandle::newArray()); - pdf.getTrailer() - .getKey("/QTest2") - .appendItem(pdf.copyForeignObject(s1)) - .appendItem(pdf.copyForeignObject(s2)) - .appendItem(pdf.copyForeignObject(s3)); + auto trailer = pdf.getTrailer(); + trailer.replaceKey("/QTest", pdf.copyForeignObject(qtest)); + auto qtest2 = + trailer.replaceKeyAndGet("/QTest2", QPDFObjectHandle::newArray()); + qtest2.appendItem(pdf.copyForeignObject(s1)); + qtest2.appendItem(pdf.copyForeignObject(s2)); + qtest2.appendItem(pdf.copyForeignObject(s3)); } QPDFWriter w(pdf, "a.pdf"); @@ -2035,12 +2038,6 @@ test_55(QPDF& pdf, char const* arg2) QPDFPageDocumentHelper(pdf).getAllPages(); QPDFObjectHandle qtest = QPDFObjectHandle::newArray(); for (auto& ph: pages) { - // Note: using fluent appendItem causes a test failure with - // MSVC 19.31.31107, which appears to evaluate the argument to - // the second appendItem before the first. Since these - // arguments have the side effect of creating objects, the - // object numbers end up being different even though the - // resulting file is semantically correct. qtest.appendItem(ph.getFormXObjectForPage()); qtest.appendItem(ph.getFormXObjectForPage(false)); } @@ -2196,10 +2193,10 @@ test_60(QPDF& pdf, char const* arg2) // The only differences between /QTest and /QTest3 should be // the direct objects merged from r2. - pdf.getTrailer() - .replaceKey("/QTest1", r1) - .replaceKey("/QTest2", r2) - .replaceKey("/QTest3", r3); + auto trailer = pdf.getTrailer(); + trailer.replaceKey("/QTest1", r1); + trailer.replaceKey("/QTest2", r2); + trailer.replaceKey("/QTest3", r3); QPDFWriter w(pdf, "a.pdf"); w.setQDFMode(true); w.setStaticID(true); @@ -2259,9 +2256,9 @@ test_62(QPDF& pdf, char const* arg2) long long q2 = QIntC::to_longlong(q2_l); unsigned int q3_i = UINT_MAX; long long q3 = QIntC::to_longlong(q3_i); - t.replaceKey("/Q1", QPDFObjectHandle::newInteger(q1)) - .replaceKey("/Q2", QPDFObjectHandle::newInteger(q2)) - .replaceKey("/Q3", QPDFObjectHandle::newInteger(q3)); + t.replaceKey("/Q1", QPDFObjectHandle::newInteger(q1)); + t.replaceKey("/Q2", QPDFObjectHandle::newInteger(q2)); + t.replaceKey("/Q3", QPDFObjectHandle::newInteger(q3)); assert_compare_numbers(q1, t.getKey("/Q1").getIntValue()); assert_compare_numbers(q1_l, t.getKey("/Q1").getUIntValue()); assert_compare_numbers(INT_MAX, t.getKey("/Q1").getIntValueAsInt()); @@ -3120,17 +3117,16 @@ test_87(QPDF& pdf, char const* arg2) static void test_88(QPDF& pdf, char const* arg2) { - // Exercise fluent QPDFObjectHandle mutators and similar methods - // added for qpdf 11. - auto dict = QPDFObjectHandle::newDictionary() - .replaceKey("/One", QPDFObjectHandle::newInteger(1)) - .replaceKey("/Two", QPDFObjectHandle::newInteger(2)); - dict.replaceKeyAndGet("/Three", QPDFObjectHandle::newArray()) - .appendItem("(a)"_qpdf) - .appendItem("(b)"_qpdf) - .appendItemAndGet(QPDFObjectHandle::newDictionary()) - .replaceKey("/Z", "/Y"_qpdf) - .replaceKey("/X", "/W"_qpdf); + // Exercise mutate and get methods added for qpdf 11. + auto dict = QPDFObjectHandle::newDictionary(); + dict.replaceKey("/One", QPDFObjectHandle::newInteger(1)); + dict.replaceKey("/Two", QPDFObjectHandle::newInteger(2)); + auto three = dict.replaceKeyAndGet("/Three", QPDFObjectHandle::newArray()); + three.appendItem("(a)"_qpdf); + three.appendItem("(b)"_qpdf); + auto newdict = three.appendItemAndGet(QPDFObjectHandle::newDictionary()); + newdict.replaceKey("/Z", "/Y"_qpdf); + newdict.replaceKey("/X", "/W"_qpdf); assert(dict.unparse() == R"( << /One 1 @@ -3138,14 +3134,15 @@ test_88(QPDF& pdf, char const* arg2) /Three [ (a) (b) << /Z /Y /X /W >> ] >> )"_qpdf.unparse()); - auto arr = dict.getKey("/Three") - .insertItem(0, QPDFObjectHandle::newString("0")) - .insertItem(0, QPDFObjectHandle::newString("00")); + auto arr = dict.getKey("/Three"); + arr.insertItem(0, QPDFObjectHandle::newString("0")); + arr.insertItem(0, QPDFObjectHandle::newString("00")); assert( arr.unparse() == "[ (00) (0) (a) (b) << /Z /Y /X /W >> ]"_qpdf.unparse()); auto new_dict = arr.insertItemAndGet(1, "<< /P /Q /R /S >>"_qpdf); - arr.eraseItem(2).eraseItem(0); + arr.eraseItem(2); + arr.eraseItem(0); assert( arr.unparse() == "[ << /P /Q /R /S >> (a) (b) << /Z /Y /X /W >> ]"_qpdf.unparse()); @@ -3154,7 +3151,8 @@ test_88(QPDF& pdf, char const* arg2) // always been this way, and there is code that relies on this // behavior. Maybe it would be different if I could start over // again... - new_dict.removeKey("/R").replaceKey("/T", "/U"_qpdf); + new_dict.removeKey("/R"); + new_dict.replaceKey("/T", "/U"_qpdf); assert( arr.unparse() == "[ << /P /Q /T /U >> (a) (b) << /Z /Y /X /W >> ]"_qpdf.unparse()); diff --git a/qpdf/test_large_file.cc b/qpdf/test_large_file.cc index 4f4f5a49..e8bea103 100644 --- a/qpdf/test_large_file.cc +++ b/qpdf/test_large_file.cc @@ -187,37 +187,37 @@ create_pdf(char const* filename) QPDFObjectHandle font = pdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); - font.replaceKey("/Type", newName("/Font")) - .replaceKey("/Subtype", newName("/Type1")) - .replaceKey("/Name", newName("/F1")) - .replaceKey("/BaseFont", newName("/Helvetica")) - .replaceKey("/Encoding", newName("/WinAnsiEncoding")); + font.replaceKey("/Type", newName("/Font")); + font.replaceKey("/Subtype", newName("/Type1")); + font.replaceKey("/Name", newName("/F1")); + font.replaceKey("/BaseFont", newName("/Helvetica")); + font.replaceKey("/Encoding", newName("/WinAnsiEncoding")); QPDFObjectHandle procset = pdf.makeIndirectObject(QPDFObjectHandle::newArray()); - procset.appendItem(newName("/PDF")) - .appendItem(newName("/Text")) - .appendItem(newName("/ImageC")); + procset.appendItem(newName("/PDF")); + procset.appendItem(newName("/Text")); + procset.appendItem(newName("/ImageC")); QPDFObjectHandle rfont = QPDFObjectHandle::newDictionary(); rfont.replaceKey("/F1", font); QPDFObjectHandle mediabox = QPDFObjectHandle::newArray(); - mediabox.appendItem(newInteger(0)) - .appendItem(newInteger(0)) - .appendItem(newInteger(612)) - .appendItem(newInteger(792)); + mediabox.appendItem(newInteger(0)); + mediabox.appendItem(newInteger(0)); + mediabox.appendItem(newInteger(612)); + mediabox.appendItem(newInteger(792)); QPDFPageDocumentHelper dh(pdf); for (size_t pageno = 1; pageno <= npages; ++pageno) { QPDFObjectHandle image = QPDFObjectHandle::newStream(&pdf); QPDFObjectHandle image_dict = image.getDict(); - image_dict.replaceKey("/Type", newName("/XObject")) - .replaceKey("/Subtype", newName("/Image")) - .replaceKey("/ColorSpace", newName("/DeviceGray")) - .replaceKey("/BitsPerComponent", newInteger(8)) - .replaceKey("/Width", newInteger(width)) - .replaceKey("/Height", newInteger(height)); + image_dict.replaceKey("/Type", newName("/XObject")); + image_dict.replaceKey("/Subtype", newName("/Image")); + image_dict.replaceKey("/ColorSpace", newName("/DeviceGray")); + image_dict.replaceKey("/BitsPerComponent", newInteger(8)); + image_dict.replaceKey("/Width", newInteger(width)); + image_dict.replaceKey("/Height", newInteger(height)); ImageProvider* p = new ImageProvider(pageno); std::shared_ptr provider(p); image.replaceStreamData( @@ -227,18 +227,18 @@ create_pdf(char const* filename) xobject.replaceKey("/Im1", image); QPDFObjectHandle resources = QPDFObjectHandle::newDictionary(); - resources.replaceKey("/ProcSet", procset) - .replaceKey("/Font", rfont) - .replaceKey("/XObject", xobject); + resources.replaceKey("/ProcSet", procset); + resources.replaceKey("/Font", rfont); + resources.replaceKey("/XObject", xobject); QPDFObjectHandle contents = create_page_contents(pdf, pageno); QPDFObjectHandle page = pdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); - page.replaceKey("/Type", newName("/Page")) - .replaceKey("/MediaBox", mediabox) - .replaceKey("/Contents", contents) - .replaceKey("/Resources", resources); + page.replaceKey("/Type", newName("/Page")); + page.replaceKey("/MediaBox", mediabox); + page.replaceKey("/Contents", contents); + page.replaceKey("/Resources", resources); dh.addPage(page, false); }