From eeb6162f7620fba49bb141ccd2c715cd829c8e24 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 16 Jul 2022 11:21:11 +0100 Subject: Add optional parameter separator to QPDFObjGen::unparse Also, revert inlining of unparse and operator << from commit 4c6640c in order to avoid exposing QUtil. --- include/qpdf/QPDFObjGen.hh | 14 ++------------ include/qpdf/QPDFObjectHandle.hh | 1 - libqpdf/CMakeLists.txt | 1 + libqpdf/QPDF.cc | 31 ++++++++++++------------------- libqpdf/QPDFAcroFormDocumentHelper.cc | 4 ++-- libqpdf/QPDFJob.cc | 7 ++++--- libqpdf/QPDFObjGen.cc | 17 +++++++++++++++++ libqpdf/QPDFObjectHandle.cc | 31 ++++++++++++------------------- libqpdf/QPDFPageObjectHelper.cc | 5 ++--- libqpdf/QPDFWriter.cc | 5 ++--- libqpdf/QPDF_Stream.cc | 9 +++------ libqpdf/QPDF_encryption.cc | 3 +-- 12 files changed, 58 insertions(+), 70 deletions(-) create mode 100644 libqpdf/QPDFObjGen.cc diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index ba6e169d..19158aeb 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -23,7 +23,6 @@ #define QPDFOBJGEN_HH #include -#include #include // This class represents an object ID and generation pair. It is @@ -69,18 +68,9 @@ class QPDFObjGen return gen; } QPDF_DLL - std::string - unparse() const - { - return QUtil::int_to_string(obj) + "," + QUtil::int_to_string(gen); - } + std::string unparse(char separator = ',') const; QPDF_DLL - friend std::ostream& - operator<<(std::ostream& os, const QPDFObjGen& og) - { - os << og.obj << "," << og.gen; - return os; - } + friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og); private: // This class does not use the Members pattern to avoid a memory diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 292397d4..804b76c7 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1584,7 +1584,6 @@ class QPDFObjectHandle bool stop_at_streams); void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only); void releaseResolved(); - std::string getObjGenAsStr() const; static void setObjectDescriptionFromInput( QPDFObjectHandle, QPDF*, diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt index 0e450503..cf807f6d 100644 --- a/libqpdf/CMakeLists.txt +++ b/libqpdf/CMakeLists.txt @@ -74,6 +74,7 @@ set(libqpdf_SOURCES QPDFNumberTreeObjectHelper.cc QPDFObject.cc QPDFObjectHandle.cc + QPDFObjGen.cc QPDFOutlineDocumentHelper.cc QPDFOutlineObjectHelper.cc QPDFPageDocumentHelper.cc diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 86a4e3d2..3b2271bc 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -1493,9 +1493,8 @@ QPDF::setLastObjectDescription( } } if (objid > 0) { - this->m->last_object_description += "object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation); + this->m->last_object_description += + "object " + QPDFObjGen(objid, generation).unparse(' '); } } @@ -1862,8 +1861,8 @@ QPDF::readObjectAtOffset( this->m->file->getName(), this->m->last_object_description, offset, - (std::string("expected ") + QUtil::int_to_string(exp_objid) + - " " + QUtil::int_to_string(exp_generation) + " obj")); + (std::string("expected ") + + QPDFObjGen(exp_objid, exp_generation).unparse(' ') + " obj")); if (try_recovery) { // Will be retried below throw e; @@ -1898,8 +1897,8 @@ QPDF::readObjectAtOffset( "", 0, std::string( - "object " + QUtil::int_to_string(exp_objid) + " " + - QUtil::int_to_string(exp_generation) + + "object " + + QPDFObjGen(exp_objid, exp_generation).unparse(' ') + " not found in file after regenerating" " cross reference table")); return QPDFObjectHandle::newNull(); @@ -2002,8 +2001,7 @@ QPDF::resolve(int objid, int generation) qpdf_e_damaged_pdf, "", this->m->file->getLastOffset(), - ("loop detected resolving object " + QUtil::int_to_string(objid) + - " " + QUtil::int_to_string(generation))); + ("loop detected resolving object " + og.unparse(' '))); return QPDF_Null::create(); } ResolveRecorder rr(this, og); @@ -2039,8 +2037,7 @@ QPDF::resolve(int objid, int generation) this->m->file->getName(), "", 0, - ("object " + QUtil::int_to_string(objid) + "/" + - QUtil::int_to_string(generation) + + ("object " + og.unparse('/') + " has unexpected xref entry type")); } } catch (QPDFExc& e) { @@ -2050,8 +2047,7 @@ QPDF::resolve(int objid, int generation) qpdf_e_damaged_pdf, "", 0, - ("object " + QUtil::int_to_string(objid) + "/" + - QUtil::int_to_string(generation) + + ("object " + og.unparse('/') + ": error reading object: " + e.what())); } } @@ -2065,10 +2061,7 @@ QPDF::resolve(int objid, int generation) std::shared_ptr result(this->m->obj_cache[og].object); if (!result->hasDescription()) { - result->setDescription( - this, - ("object " + QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation))); + result->setDescription(this, ("object " + og.unparse(' '))); } return result; } @@ -2809,8 +2802,8 @@ QPDF::pipeStreamData( "", file->getLastOffset(), ("error decoding stream data for object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation) + ": " + e.what()))); + QPDFObjGen(objid, generation).unparse(' ') + ": " + + e.what()))); if (will_retry) { qpdf_for_warning.warn( // line-break diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index ddf10e6d..62dbaeee 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -991,8 +991,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations( } else { parent.warnIfPossible( "while traversing field " + - obj.getObjGen().unparse() + ", found parent (" + - parent_og.unparse() + + obj.getObjGen().unparse(',') + ", found parent (" + + parent_og.unparse(',') + ") that had not been seen, indicating likely" " invalid field structure"); } diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index c5f0eb2d..8af038f4 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -947,7 +947,7 @@ QPDFJob::doShowObj(QPDF& pdf) } if (error) { throw std::runtime_error( - "unable to get object " + obj.getObjGen().unparse()); + "unable to get object " + obj.getObjGen().unparse(',')); } } @@ -995,7 +995,8 @@ QPDFJob::doListAttachments(QPDF& pdf) auto efoh = i.second; *this->m->log->getInfo() << key << " -> " - << efoh->getEmbeddedFileStream().getObjGen().unparse() << "\n"; + << efoh->getEmbeddedFileStream().getObjGen().unparse(',') + << "\n"; doIfVerbose([&](Pipeline& v, std::string const& prefix) { auto desc = efoh->getDescription(); if (!desc.empty()) { @@ -1010,7 +1011,7 @@ QPDFJob::doListAttachments(QPDF& pdf) for (auto i2: efoh->getEmbeddedFileStreams().ditems()) { auto efs = QPDFEFStreamObjectHelper(i2.second); v << " " << i2.first << " -> " - << efs.getObjectHandle().getObjGen().unparse() << "\n"; + << efs.getObjectHandle().getObjGen().unparse(',') << "\n"; v << " creation date: " << efs.getCreationDate() << "\n" << " modification date: " << efs.getModDate() << "\n" diff --git a/libqpdf/QPDFObjGen.cc b/libqpdf/QPDFObjGen.cc new file mode 100644 index 00000000..e372555d --- /dev/null +++ b/libqpdf/QPDFObjGen.cc @@ -0,0 +1,17 @@ +#include + +#include + +std::ostream& +operator<<(std::ostream& os, const QPDFObjGen& og) +{ + os << og.obj << "," << og.gen; + return os; +} + +std::string +QPDFObjGen::unparse(char separator) const +{ + return QUtil::int_to_string(this->obj) + separator + + QUtil::int_to_string(this->gen); +} diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 66087dd4..b01deb6a 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -103,9 +103,8 @@ void CoalesceProvider::provideStreamData(int, int, Pipeline* p) { QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data"); - std::string description = "page object " + - QUtil::int_to_string(containing_page.getObjectID()) + " " + - QUtil::int_to_string(containing_page.getGeneration()); + std::string description = + "page object " + containing_page.getObjGen().unparse(' '); std::string all_description; old_contents.pipeContentStreams(p, description, all_description); } @@ -1485,13 +1484,6 @@ QPDFObjectHandle::getObjGen() const return QPDFObjGen(this->objid, this->generation); } -std::string -QPDFObjectHandle::getObjGenAsStr() const -{ - return QUtil::int_to_string(this->objid) + " " + - QUtil::int_to_string(this->generation); -} - int QPDFObjectHandle::getObjectID() const { @@ -1556,7 +1548,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( } else { all_description += ","; } - all_description += " stream " + item.getObjGenAsStr(); + all_description += " stream " + item.getObjGen().unparse(' '); } return result; @@ -1565,7 +1557,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( std::vector QPDFObjectHandle::getPageContents() { - std::string description = "page object " + getObjGenAsStr(); + std::string description = "page object " + getObjGen().unparse(' '); std::string all_description; return this->getKey("/Contents") .arrayOrStreamToStreamArray(description, all_description); @@ -1674,7 +1666,7 @@ QPDFObjectHandle::unparse() { std::string result; if (this->isIndirect()) { - result = getObjGenAsStr() + " R"; + result = getObjGen().unparse(' ') + " R"; } else { result = unparseResolved(); } @@ -1789,7 +1781,7 @@ QPDFObjectHandle::parse( void QPDFObjectHandle::pipePageContents(Pipeline* p) { - std::string description = "page object " + getObjGenAsStr(); + std::string description = "page object " + getObjGen().unparse(' '); std::string all_description; this->getKey("/Contents") .pipeContentStreams(p, description, all_description); @@ -1813,7 +1805,7 @@ QPDFObjectHandle::pipeContentStreams( throw QPDFExc( qpdf_e_damaged_pdf, "content stream", - "content stream object " + stream.getObjGenAsStr(), + "content stream object " + stream.getObjGen().unparse(' '), 0, "errors while decoding content stream"); } @@ -1829,7 +1821,7 @@ QPDFObjectHandle::pipeContentStreams( void QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks) { - std::string description = "page object " + getObjGenAsStr(); + std::string description = "page object " + getObjGen().unparse(' '); this->getKey("/Contents") .parseContentStream_internal(description, callbacks); } @@ -1837,14 +1829,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks) void QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks) { - std::string description = "object " + getObjGenAsStr(); + std::string description = "object " + getObjGen().unparse(' '); this->parseContentStream_internal(description, callbacks); } void QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next) { - auto description = "token filter for page object " + getObjGenAsStr(); + auto description = + "token filter for page object " + getObjGen().unparse(' '); Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next); this->pipePageContents(&token_pipeline); } @@ -1852,7 +1845,7 @@ QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next) void QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next) { - auto description = "token filter for object " + getObjGenAsStr(); + auto description = "token filter for object " + getObjGen().unparse(' '); Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next); this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized); } diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index 6c38f098..16ab346f 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -33,9 +33,8 @@ void ContentProvider::provideStreamData(int, int, Pipeline* p) { Pl_Concatenate concat("concatenate", p); - std::string description = "contents from page object " + - QUtil::int_to_string(from_page.getObjectID()) + " " + - QUtil::int_to_string(from_page.getGeneration()); + std::string description = + "contents from page object " + from_page.getObjGen().unparse(' '); std::string all_description; from_page.getKey("/Contents") .pipeContentStreams(&concat, description, all_description); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index d160ff99..50ec9406 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -1990,9 +1990,8 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index) if (object_stream_index == -1) { if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) { writeString( - "%% Original object ID: " + - QUtil::int_to_string(object.getObjectID()) + " " + - QUtil::int_to_string(object.getGeneration()) + "\n"); + "%% Original object ID: " + object.getObjGen().unparse(' ') + + "\n"); } openObject(new_id); setDataKey(new_id); diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 0b06a7f5..c0644532 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -130,8 +130,7 @@ QPDF_Stream::QPDF_Stream( setDescription( this->qpdf, this->qpdf->getFilename() + ", stream object " + - QUtil::int_to_string(this->objid) + " " + - QUtil::int_to_string(this->generation)); + QPDFObjGen(objid, generation).unparse(' ')); } std::shared_ptr @@ -196,8 +195,7 @@ std::string QPDF_Stream::unparse() { // Unparse stream objects as indirect references - return QUtil::int_to_string(this->objid) + " " + - QUtil::int_to_string(this->generation) + " R"; + return QPDFObjGen(objid, generation).unparse(' ') + " R"; } JSON @@ -643,8 +641,7 @@ QPDF_Stream::pipeStreamData( // part of a library user, not by invalid input data. throw std::runtime_error( "stream data provider for " + - QUtil::int_to_string(this->objid) + " " + - QUtil::int_to_string(this->generation) + " provided " + + QPDFObjGen(objid, generation).unparse(' ') + " provided " + QUtil::int_to_string(actual_length) + " bytes instead of expected " + QUtil::int_to_string(desired_length) + " bytes"); diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 5a7968ca..95d5ea37 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -1176,8 +1176,7 @@ QPDF::decryptString(std::string& str, int objid, int generation) this->m->last_object_description, this->m->file->getLastOffset(), "error decrypting string for object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation) + ": " + e.what()); + QPDFObjGen(objid, generation).unparse() + ": " + e.what()); } } -- cgit v1.2.3-54-g00ecf From bc5f0fa20b91a7cdc64d0e65495ddaca184d386d Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 12:46:31 +0100 Subject: Add method QPDFObjGen::isIndirect --- include/qpdf/QPDFObjGen.hh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index 19158aeb..30f609a7 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -68,6 +68,12 @@ class QPDFObjGen return gen; } QPDF_DLL + bool + isIndirect() const + { + return obj > 0; + } + QPDF_DLL std::string unparse(char separator = ',') const; QPDF_DLL friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og); -- cgit v1.2.3-54-g00ecf From 21b8625f9595154c661ad9f6d2168cc89b291686 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 12:58:37 +0100 Subject: Add QPDFObjGen operator != --- include/qpdf/QPDFObjGen.hh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index 30f609a7..e0834a9e 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -47,13 +47,19 @@ class QPDFObjGen bool operator<(QPDFObjGen const& rhs) const { - return ((obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen))); + return (obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen)); } QPDF_DLL bool operator==(QPDFObjGen const& rhs) const { - return ((obj == rhs.obj) && (gen == rhs.gen)); + return (obj == rhs.obj) && (gen == rhs.gen); + } + QPDF_DLL + bool + operator!=(QPDFObjGen const& rhs) const + { + return (obj != rhs.obj) || (gen != rhs.gen); } QPDF_DLL int -- cgit v1.2.3-54-g00ecf From 6ea17d1f0e68bc4cced99f0a046f2a605a365ec8 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 13:16:39 +0100 Subject: Make second parameter of QPDFObjGen::QPDFObjGen optional --- include/qpdf/QPDFObjGen.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index e0834a9e..a1829b00 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -38,7 +38,7 @@ class QPDFObjGen { } QPDF_DLL - QPDFObjGen(int obj, int gen) : + explicit QPDFObjGen(int obj, int gen = 0) : obj(obj), gen(gen) { -- cgit v1.2.3-54-g00ecf From c0168cf88c79c9b55a81f86892432f006b9c4d07 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 13:47:18 +0100 Subject: QPPFObjGen : tidy QPDF::readObjectAtOffset Change method signature to use QPDFObjGen. --- include/qpdf/QPDF.hh | 6 ++--- libqpdf/QPDF.cc | 63 +++++++++++++++---------------------------- libqpdf/QPDF_linearization.cc | 7 +++-- 3 files changed, 26 insertions(+), 50 deletions(-) diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index f0c9f6b4..aba3369e 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -1146,10 +1146,8 @@ class QPDF bool attempt_recovery, qpdf_offset_t offset, std::string const& description, - int exp_objid, - int exp_generation, - int& act_objid, - int& act_generation); + QPDFObjGen const& exp_og, + QPDFObjGen& og); bool objectChanged(QPDFObjGen const& og, std::shared_ptr& oph); std::shared_ptr resolve(int objid, int generation); void resolveObjectsInStream(int obj_stream_number); diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 3b2271bc..5397da4f 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -1055,12 +1055,11 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) { bool found = false; if (!this->m->ignore_xref_streams) { - int xobj; - int xgen; + QPDFObjGen x_og; QPDFObjectHandle xref_obj; try { xref_obj = readObjectAtOffset( - false, xref_offset, "xref stream", 0, 0, xobj, xgen); + false, xref_offset, "xref stream", QPDFObjGen(), x_og); } catch (QPDFExc&) { // ignore -- report error below } @@ -1776,13 +1775,11 @@ QPDF::readObjectAtOffset( bool try_recovery, qpdf_offset_t offset, std::string const& description, - int exp_objid, - int exp_generation, - int& objid, - int& generation) + QPDFObjGen const& exp_og, + QPDFObjGen& og) { bool check_og = true; - if (exp_objid == 0) { + if (exp_og.getObj() == 0) { // This method uses an expect object ID of 0 to indicate that // we don't know or don't care what the actual object ID is at // this offset. This is true when we read the xref stream and @@ -1794,7 +1791,7 @@ QPDF::readObjectAtOffset( check_og = false; try_recovery = false; } else { - setLastObjectDescription(description, exp_objid, exp_generation); + setLastObjectDescription(description, exp_og.getObj(), exp_og.getGen()); } if (!this->m->attempt_recovery) { @@ -1840,9 +1837,9 @@ QPDF::readObjectAtOffset( offset, "expected n n obj"); } - objid = QUtil::string_to_int(tobjid.getValue().c_str()); - generation = QUtil::string_to_int(tgen.getValue().c_str()); - + int objid = QUtil::string_to_int(tobjid.getValue().c_str()); + int generation = QUtil::string_to_int(tgen.getValue().c_str()); + og = QPDFObjGen(objid, generation); if (objid == 0) { QTC::TC("qpdf", "QPDF object id 0"); throw QPDFExc( @@ -1852,17 +1849,14 @@ QPDF::readObjectAtOffset( offset, "object with ID 0"); } - - if (check_og && - (!((objid == exp_objid) && (generation == exp_generation)))) { + if (check_og && (exp_og != og)) { QTC::TC("qpdf", "QPDF err wrong objid/generation"); QPDFExc e( qpdf_e_damaged_pdf, this->m->file->getName(), this->m->last_object_description, offset, - (std::string("expected ") + - QPDFObjGen(exp_objid, exp_generation).unparse(' ') + " obj")); + (std::string("expected ") + exp_og.unparse(' ') + " obj")); if (try_recovery) { // Will be retried below throw e; @@ -1876,18 +1870,12 @@ QPDF::readObjectAtOffset( if (try_recovery) { // Try again after reconstructing xref table reconstruct_xref(e); - QPDFObjGen og(exp_objid, exp_generation); - if (this->m->xref_table.count(og) && - (this->m->xref_table[og].getType() == 1)) { - qpdf_offset_t new_offset = this->m->xref_table[og].getOffset(); + if (this->m->xref_table.count(exp_og) && + (this->m->xref_table[exp_og].getType() == 1)) { + qpdf_offset_t new_offset = + this->m->xref_table[exp_og].getOffset(); QPDFObjectHandle result = readObjectAtOffset( - false, - new_offset, - description, - exp_objid, - exp_generation, - objid, - generation); + false, new_offset, description, exp_og, og); QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset"); return result; } else { @@ -1897,8 +1885,7 @@ QPDF::readObjectAtOffset( "", 0, std::string( - "object " + - QPDFObjGen(exp_objid, exp_generation).unparse(' ') + + "object " + exp_og.unparse(' ') + " not found in file after regenerating" " cross reference table")); return QPDFObjectHandle::newNull(); @@ -1909,7 +1896,7 @@ QPDF::readObjectAtOffset( } QPDFObjectHandle oh = - readObject(this->m->file, description, objid, generation, false); + readObject(this->m->file, description, og.getObj(), og.getGen(), false); if (!(readToken(this->m->file) == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { @@ -1921,7 +1908,6 @@ QPDF::readObjectAtOffset( "expected endobj"); } - QPDFObjGen og(objid, generation); if (!this->m->obj_cache.count(og)) { // Store the object in the cache here so it gets cached // whether we first know the offset or whether we first know @@ -2014,16 +2000,9 @@ QPDF::resolve(int objid, int generation) { qpdf_offset_t offset = entry.getOffset(); // Object stored in cache by readObjectAtOffset - int aobjid; - int ageneration; - QPDFObjectHandle oh = readObjectAtOffset( - true, - offset, - "", - objid, - generation, - aobjid, - ageneration); + QPDFObjGen a_og; + QPDFObjectHandle oh = + readObjectAtOffset(true, offset, "", og, a_og); } break; diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index ce6441c9..b92ba5f2 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -325,11 +325,10 @@ QPDF::readLinearizationData() QPDFObjectHandle QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) { - int obj; - int gen; + QPDFObjGen og; QPDFObjectHandle H = readObjectAtOffset( - false, offset, "linearization hint stream", 0, 0, obj, gen); - ObjCache& oc = this->m->obj_cache[QPDFObjGen(obj, gen)]; + false, offset, "linearization hint stream", QPDFObjGen(), og); + ObjCache& oc = this->m->obj_cache[og]; qpdf_offset_t min_end_offset = oc.end_before_space; qpdf_offset_t max_end_offset = oc.end_after_space; if (!H.isStream()) { -- cgit v1.2.3-54-g00ecf From b123f79dfd5015453bdbf5d53f8225d73b6b20aa Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 14:15:55 +0100 Subject: Replace QPDFObjectHandle::objid and generation with QPDFObjectHandle::og --- include/qpdf/QPDFObjectHandle.hh | 5 ++--- libqpdf/QPDFObjectHandle.cc | 28 +++++++++++----------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 804b76c7..fa96c4b0 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1550,7 +1550,7 @@ class QPDFObjectHandle bool isImage(bool exclude_imagemask = true); private: - QPDFObjectHandle(QPDF*, int objid, int generation); + QPDFObjectHandle(QPDF*, QPDFObjGen const& og); QPDFObjectHandle(std::shared_ptr const&); enum parser_state_e { @@ -1617,8 +1617,7 @@ class QPDFObjectHandle // a substantial performance penalty since QPDFObjectHandle // objects are copied around so frequently. QPDF* qpdf; - int objid; // 0 for direct object - int generation; + QPDFObjGen og; std::shared_ptr obj; bool reserved; }; diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index b01deb6a..880e44bd 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -218,27 +218,22 @@ LastChar::getLastChar() QPDFObjectHandle::QPDFObjectHandle() : initialized(false), - qpdf(0), - objid(0), - generation(0), + qpdf(nullptr), reserved(false) { } -QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, int objid, int generation) : +QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, QPDFObjGen const& og) : initialized(true), qpdf(qpdf), - objid(objid), - generation(generation), + og(og), reserved(false) { } QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr const& data) : initialized(true), - qpdf(0), - objid(0), - generation(0), + qpdf(nullptr), obj(data), reserved(false) { @@ -1481,19 +1476,19 @@ QPDFObjectHandle::replaceStreamData( QPDFObjGen QPDFObjectHandle::getObjGen() const { - return QPDFObjGen(this->objid, this->generation); + return og; } int QPDFObjectHandle::getObjectID() const { - return this->objid; + return og.getObj(); } int QPDFObjectHandle::getGeneration() const { - return this->generation; + return og.getGen(); } std::map @@ -2485,7 +2480,7 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) return newNull(); } - return QPDFObjectHandle(qpdf, objid, generation); + return QPDFObjectHandle(qpdf, QPDFObjGen(objid, generation)); } QPDFObjectHandle @@ -2689,7 +2684,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) // number, but then return an unresolved handle to the object. QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved()); QPDFObjectHandle result = - newIndirect(qpdf, reserved.objid, reserved.generation); + newIndirect(qpdf, reserved.getObjectID(), reserved.getGeneration()); result.reserved = true; return result; } @@ -2789,9 +2784,8 @@ QPDFObjectHandle::copyObject( " reserved object handle direct"); } - this->qpdf = 0; - this->objid = 0; - this->generation = 0; + qpdf = nullptr; + og = QPDFObjGen(); std::shared_ptr new_obj; -- cgit v1.2.3-54-g00ecf From 3404ca8ac8e19ccba5ff2d7426081a593880f1c0 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 14:45:54 +0100 Subject: QPDFObjGen : tidy QPDFObjectHandle private methods Change method signature to use QPDFObjGen. --- include/qpdf/QPDFObjectHandle.hh | 14 ++++++-------- libqpdf/QPDF.cc | 25 ++++++++++++------------- libqpdf/QPDFObjectHandle.cc | 19 +++++++++---------- libqpdf/QPDF_linearization.cc | 2 +- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index fa96c4b0..68fc78f8 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1429,21 +1429,20 @@ class QPDFObjectHandle private: static QPDFObjectHandle - newIndirect(QPDF* qpdf, int objid, int generation) + newIndirect(QPDF* qpdf, QPDFObjGen const& og) { - return QPDFObjectHandle::newIndirect(qpdf, objid, generation); + return QPDFObjectHandle::newIndirect(qpdf, og); } static QPDFObjectHandle newStream( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) { return QPDFObjectHandle::newStream( - qpdf, objid, generation, stream_dict, offset, length); + qpdf, og, stream_dict, offset, length); } // Reserve an object with a specific ID static QPDFObjectHandle @@ -1563,11 +1562,10 @@ class QPDFObjectHandle }; // Private object factory methods - static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation); + static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og); static QPDFObjectHandle newStream( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 5397da4f..97303471 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -1404,9 +1404,8 @@ QPDF::fixDanglingReferences(bool force) // For each non-scalar item to process, put it in the queue. std::list queue; queue.push_back(this->m->trailer); - for (auto const& iter: to_process) { - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect( - this, iter.getObj(), iter.getGen()); + for (auto const& og: to_process) { + QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og); if (obj.isDictionary() || obj.isArray()) { queue.push_back(obj); } else if (obj.isStream()) { @@ -1472,10 +1471,7 @@ QPDF::getAllObjects() std::vector result; for (auto const& iter: this->m->obj_cache) { QPDFObjGen const& og = iter.first; - result.push_back( - // line-break - QPDFObjectHandle::Factory::newIndirect( - this, og.getObj(), og.getGen())); + result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og)); } return result; } @@ -1662,7 +1658,11 @@ QPDF::readObject( } } object = QPDFObjectHandle::Factory::newStream( - this, objid, generation, object, stream_offset, length); + this, + QPDFObjGen(objid, generation), + object, + stream_offset, + length); } else { input->seek(cur_offset, SEEK_SET); } @@ -2159,8 +2159,7 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) QPDFObjGen next(max_objid + 1, 0); this->m->obj_cache[next] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); - return QPDFObjectHandle::Factory::newIndirect( - this, next.getObj(), next.getGen()); + return QPDFObjectHandle::Factory::newIndirect(this, next); } QPDFObjectHandle @@ -2178,19 +2177,19 @@ QPDFObjectHandle QPDF::reserveStream(int objid, int gen) { return QPDFObjectHandle::Factory::newStream( - this, objid, gen, QPDFObjectHandle::newDictionary(), 0, 0); + this, QPDFObjGen(objid, gen), QPDFObjectHandle::newDictionary(), 0, 0); } QPDFObjectHandle QPDF::getObjectByObjGen(QPDFObjGen const& og) { - return getObjectByID(og.getObj(), og.getGen()); + return QPDFObjectHandle::Factory::newIndirect(this, og); } QPDFObjectHandle QPDF::getObjectByID(int objid, int generation) { - return QPDFObjectHandle::Factory::newIndirect(this, objid, generation); + return getObjectByObjGen(QPDFObjGen(objid, generation)); } void diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 880e44bd..779a61ed 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -2180,8 +2180,9 @@ QPDFObjectHandle::parseInternal( // Try to resolve indirect objects object = newIndirect( context, - olist.at(olist.size() - 2).getIntValueAsInt(), - olist.at(olist.size() - 1).getIntValueAsInt()); + QPDFObjGen( + olist.at(olist.size() - 2).getIntValueAsInt(), + olist.at(olist.size() - 1).getIntValueAsInt())); olist.remove_last(); olist.remove_last(); } else if ((value == "endobj") && (state == st_top)) { @@ -2469,9 +2470,9 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) } QPDFObjectHandle -QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) +QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og) { - if (objid == 0) { + if (!og.isIndirect()) { // Special case: QPDF uses objid 0 as a sentinel for direct // objects, and the PDF specification doesn't allow for object // 0. Treat indirect references to object 0 as null so that we @@ -2480,7 +2481,7 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) return newNull(); } - return QPDFObjectHandle(qpdf, QPDFObjGen(objid, generation)); + return QPDFObjectHandle(qpdf, og); } QPDFObjectHandle @@ -2628,14 +2629,13 @@ QPDFObjectHandle::newDictionary( QPDFObjectHandle QPDFObjectHandle::newStream( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) { QPDFObjectHandle result = QPDFObjectHandle(QPDF_Stream::create( - qpdf, objid, generation, stream_dict, offset, length)); + qpdf, og.getObj(), og.getGen(), stream_dict, offset, length)); if (offset) { result.setParsedOffset(offset); } @@ -2683,8 +2683,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) // Reserve a spot for this object by assigning it an object // number, but then return an unresolved handle to the object. QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved()); - QPDFObjectHandle result = - newIndirect(qpdf, reserved.getObjectID(), reserved.getGeneration()); + QPDFObjectHandle result = newIndirect(qpdf, reserved.getObjGen()); result.reserved = true; return result; } diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index b92ba5f2..cb4d721f 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -138,7 +138,7 @@ QPDF::isLinearized() } QPDFObjectHandle candidate = - QPDFObjectHandle::Factory::newIndirect(this, lindict_obj, 0); + QPDFObjectHandle::Factory::newIndirect(this, QPDFObjGen(lindict_obj)); if (!candidate.isDictionary()) { return false; } -- cgit v1.2.3-54-g00ecf From f7978db1f604083c16733952d2b01d3b0f4b0a6a Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 16:48:28 +0100 Subject: QPDFObjGen : tidy QPDF private methods Change method signatures to use QPDFObjGen. Use QPDFObjGen methods where possible. Remove redundant QPDF::objGenToIndirect. --- include/qpdf/QPDF.hh | 53 +++++++---------- libqpdf/QPDF.cc | 134 ++++++++++++++++-------------------------- libqpdf/QPDFObjectHandle.cc | 2 +- libqpdf/QPDF_Stream.cc | 3 +- libqpdf/QPDF_encryption.cc | 29 ++++----- libqpdf/QPDF_json.cc | 8 +-- libqpdf/QPDF_linearization.cc | 30 ++++------ libqpdf/QPDF_optimization.cc | 4 +- libqpdf/QPDF_pages.cc | 5 +- 9 files changed, 103 insertions(+), 165 deletions(-) diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index aba3369e..ae5c89e2 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -815,9 +815,9 @@ class QPDF private: static std::shared_ptr - resolve(QPDF* qpdf, int objid, int generation) + resolve(QPDF* qpdf, QPDFObjGen const& og) { - return qpdf->resolve(objid, generation); + return qpdf->resolve(og); } static bool objectChanged( @@ -879,8 +879,7 @@ class QPDF static bool pipeStreamData( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle dict, @@ -889,8 +888,7 @@ class QPDF bool will_retry) { return qpdf->pipeStreamData( - objid, - generation, + og, offset, length, dict, @@ -959,8 +957,7 @@ class QPDF std::string user_password; std::string encryption_key; std::string cached_object_encryption_key; - int cached_key_objid; - int cached_key_generation; + QPDFObjGen cached_key_og; bool user_password_matched; bool owner_password_matched; }; @@ -973,8 +970,7 @@ class QPDF ForeignStreamData( std::shared_ptr encp, std::shared_ptr file, - int foreign_objid, - int foreign_generation, + QPDFObjGen const& foreign_og, qpdf_offset_t offset, size_t length, QPDFObjectHandle local_dict); @@ -982,8 +978,7 @@ class QPDF private: std::shared_ptr encp; std::shared_ptr file; - int foreign_objid; - int foreign_generation; + QPDFObjGen foreign_og; qpdf_offset_t offset; size_t length; QPDFObjectHandle local_dict; @@ -1017,14 +1012,13 @@ class QPDF friend class QPDF; public: - StringDecrypter(QPDF* qpdf, int objid, int gen); + StringDecrypter(QPDF* qpdf, QPDFObjGen const& og); virtual ~StringDecrypter() = default; virtual void decryptString(std::string& val); private: QPDF* qpdf; - int objid; - int gen; + QPDFObjGen og; }; class ResolveRecorder @@ -1127,17 +1121,15 @@ class QPDF void insertXrefEntry( int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false); void setLastObjectDescription( - std::string const& description, int objid, int generation); + std::string const& description, QPDFObjGen const& og); QPDFObjectHandle readObject( std::shared_ptr, std::string const& description, - int objid, - int generation, + QPDFObjGen const& og, bool in_object_stream); size_t recoverStreamLength( std::shared_ptr input, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t stream_offset); QPDFTokenizer::Token readToken(std::shared_ptr, size_t max_len = 0); @@ -1149,16 +1141,15 @@ class QPDF QPDFObjGen const& exp_og, QPDFObjGen& og); bool objectChanged(QPDFObjGen const& og, std::shared_ptr& oph); - std::shared_ptr resolve(int objid, int generation); + std::shared_ptr resolve(QPDFObjGen const& og); void resolveObjectsInStream(int obj_stream_number); void stopOnError(std::string const& message); - QPDFObjectHandle reserveObjectIfNotExists(int objid, int gen); - QPDFObjectHandle reserveStream(int objid, int gen); + QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); + QPDFObjectHandle reserveStream(QPDFObjGen const& og); // Calls finish() on the pipeline when done but does not delete it bool pipeStreamData( - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle dict, @@ -1174,8 +1165,7 @@ class QPDF std::shared_ptr encp, std::shared_ptr file, QPDF& qpdf_for_warning, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle dict, @@ -1228,10 +1218,9 @@ class QPDF void initializeEncryption(); static std::string getKeyForObject( std::shared_ptr encp, - int objid, - int generation, + QPDFObjGen const& og, bool use_aes); - void decryptString(std::string&, int objid, int generation); + void decryptString(std::string&, QPDFObjGen const& og); static std::string compute_encryption_key_from_password( std::string const& password, EncryptionData const& data); static std::string recover_encryption_key_with_password( @@ -1245,8 +1234,7 @@ class QPDF std::shared_ptr file, QPDF& qpdf_for_warning, Pipeline*& pipeline, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle& stream_dict, std::vector>& heap); @@ -1569,7 +1557,6 @@ class QPDF void dumpHSharedObject(); void dumpHGeneric(HGeneric&); qpdf_offset_t adjusted_offset(qpdf_offset_t offset); - QPDFObjectHandle objGenToIndirect(QPDFObjGen const&); void calculateLinearizationData(std::map const& object_stream_data); void pushOutlinesToPart( diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 97303471..a24c17e6 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -113,15 +113,13 @@ namespace QPDF::ForeignStreamData::ForeignStreamData( std::shared_ptr encp, std::shared_ptr file, - int foreign_objid, - int foreign_generation, + QPDFObjGen const& foreign_og, qpdf_offset_t offset, size_t length, QPDFObjectHandle local_dict) : encp(encp), file(file), - foreign_objid(foreign_objid), - foreign_generation(foreign_generation), + foreign_og(foreign_og), offset(offset), length(length), local_dict(local_dict) @@ -176,17 +174,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream( this->foreign_stream_data[local_og] = foreign_stream; } -QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, int objid, int gen) : +QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) : qpdf(qpdf), - objid(objid), - gen(gen) + og(og) { } void QPDF::StringDecrypter::decryptString(std::string& val) { - qpdf->decryptString(val, objid, gen); + qpdf->decryptString(val, og); } std::string const& @@ -205,8 +202,6 @@ QPDF::EncryptionParameters::EncryptionParameters() : cf_stream(e_none), cf_string(e_none), cf_file(e_none), - cached_key_objid(0), - cached_key_generation(0), user_password_matched(false), owner_password_matched(false) { @@ -631,7 +626,7 @@ QPDF::reconstruct_xref(QPDFExc& e) (!this->m->trailer.isInitialized()) && (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) { QPDFObjectHandle t = - readObject(this->m->file, "trailer", 0, 0, false); + readObject(this->m->file, "trailer", QPDFObjGen(), false); if (!t.isDictionary()) { // Oh well. It was worth a try. } else { @@ -969,7 +964,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) // Set offset to previous xref table if any QPDFObjectHandle cur_trailer = - readObject(this->m->file, "trailer", 0, 0, false); + readObject(this->m->file, "trailer", QPDFObjGen(), false); if (!cur_trailer.isDictionary()) { QTC::TC("qpdf", "QPDF missing trailer"); throw QPDFExc( @@ -1341,7 +1336,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) break; case 2: - this->m->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2); + this->m->xref_table[QPDFObjGen(obj)] = QPDFXRefEntry(f0, f1, f2); break; default: @@ -1362,7 +1357,7 @@ QPDF::showXRefTable() for (auto const& iter: this->m->xref_table) { QPDFObjGen const& og = iter.first; QPDFXRefEntry const& entry = iter.second; - cout << og.getObj() << "/" << og.getGen() << ": "; + cout << og.unparse('/') << ": "; switch (entry.getType()) { case 1: cout << "uncompressed; offset = " << entry.getOffset(); @@ -1478,18 +1473,17 @@ QPDF::getAllObjects() void QPDF::setLastObjectDescription( - std::string const& description, int objid, int generation) + std::string const& description, QPDFObjGen const& og) { this->m->last_object_description.clear(); if (!description.empty()) { this->m->last_object_description += description; - if (objid > 0) { + if (og.isIndirect()) { this->m->last_object_description += ": "; } } - if (objid > 0) { - this->m->last_object_description += - "object " + QPDFObjGen(objid, generation).unparse(' '); + if (og.isIndirect()) { + this->m->last_object_description += "object " + og.unparse(' '); } } @@ -1497,19 +1491,17 @@ QPDFObjectHandle QPDF::readObject( std::shared_ptr input, std::string const& description, - int objid, - int generation, + QPDFObjGen const& og, bool in_object_stream) { - setLastObjectDescription(description, objid, generation); + setLastObjectDescription(description, og); qpdf_offset_t offset = input->tell(); bool empty = false; std::shared_ptr decrypter_ph; StringDecrypter* decrypter = 0; if (this->m->encp->encrypted && (!in_object_stream)) { - decrypter_ph = - std::make_shared(this, objid, generation); + decrypter_ph = std::make_shared(this, og); decrypter = decrypter_ph.get(); } QPDFObjectHandle object = QPDFObjectHandle::parse( @@ -1651,18 +1643,13 @@ QPDF::readObject( } catch (QPDFExc& e) { if (this->m->attempt_recovery) { warn(e); - length = recoverStreamLength( - input, objid, generation, stream_offset); + length = recoverStreamLength(input, og, stream_offset); } else { throw e; } } object = QPDFObjectHandle::Factory::newStream( - this, - QPDFObjGen(objid, generation), - object, - stream_offset, - length); + this, og, object, stream_offset, length); } else { input->seek(cur_offset, SEEK_SET); } @@ -1690,8 +1677,7 @@ QPDF::findEndstream() size_t QPDF::recoverStreamLength( std::shared_ptr input, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t stream_offset) { // Try to reconstruct stream length by looking for @@ -1716,11 +1702,10 @@ QPDF::recoverStreamLength( if (length) { qpdf_offset_t this_obj_offset = 0; - QPDFObjGen this_obj(0, 0); + QPDFObjGen this_og; // Make sure this is inside this object for (auto const& iter: this->m->xref_table) { - QPDFObjGen const& og = iter.first; QPDFXRefEntry const& entry = iter.second; if (entry.getType() == 1) { qpdf_offset_t obj_offset = entry.getOffset(); @@ -1728,12 +1713,11 @@ QPDF::recoverStreamLength( ((this_obj_offset == 0) || (this_obj_offset > obj_offset))) { this_obj_offset = obj_offset; - this_obj = og; + this_og = iter.first; } } } - if (this_obj_offset && (this_obj.getObj() == objid) && - (this_obj.getGen() == generation)) { + if (this_obj_offset && (this_og == og)) { // Well, we found endstream\nendobj within the space // allowed for this object, so we're probably in good // shape. @@ -1791,7 +1775,7 @@ QPDF::readObjectAtOffset( check_og = false; try_recovery = false; } else { - setLastObjectDescription(description, exp_og.getObj(), exp_og.getGen()); + setLastObjectDescription(description, exp_og); } if (!this->m->attempt_recovery) { @@ -1895,8 +1879,7 @@ QPDF::readObjectAtOffset( } } - QPDFObjectHandle oh = - readObject(this->m->file, description, og.getObj(), og.getGen(), false); + QPDFObjectHandle oh = readObject(this->m->file, description, og, false); if (!(readToken(this->m->file) == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { @@ -1972,12 +1955,11 @@ QPDF::objectChanged(QPDFObjGen const& og, std::shared_ptr& oph) } std::shared_ptr -QPDF::resolve(int objid, int generation) +QPDF::resolve(QPDFObjGen const& og) { // Check object cache before checking xref table. This allows us // to insert things into the object cache that don't actually // exist in the file. - QPDFObjGen og(objid, generation); if (this->m->resolving.count(og)) { // This can happen if an object references itself directly or // indirectly in some key that has to be resolved during @@ -2131,13 +2113,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number) // xref table and only cache what would actually be resolved here. for (auto const& iter: offsets) { int obj = iter.first; - QPDFObjGen og(obj, 0); + QPDFObjGen og(obj); QPDFXRefEntry const& entry = this->m->xref_table[og]; if ((entry.getType() == 2) && (entry.getObjStreamNumber() == obj_stream_number)) { int offset = iter.second; input->seek(offset, SEEK_SET); - QPDFObjectHandle oh = readObject(input, "", obj, 0, true); + QPDFObjectHandle oh = readObject(input, "", og, true); this->m->obj_cache[og] = ObjCache( QPDFObjectHandle::ObjAccessor::getObject(oh), end_before_space, @@ -2163,21 +2145,20 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) } QPDFObjectHandle -QPDF::reserveObjectIfNotExists(int objid, int gen) +QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) { - QPDFObjGen og(objid, gen); if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) { - resolve(objid, gen); - replaceObject(objid, gen, QPDFObjectHandle::Factory::makeReserved()); + resolve(og); + replaceObject(og, QPDFObjectHandle::Factory::makeReserved()); } - return getObjectByID(objid, gen); + return getObjectByObjGen(og); } QPDFObjectHandle -QPDF::reserveStream(int objid, int gen) +QPDF::reserveStream(QPDFObjGen const& og) { return QPDFObjectHandle::Factory::newStream( - this, QPDFObjGen(objid, gen), QPDFObjectHandle::newDictionary(), 0, 0); + this, og, QPDFObjectHandle::newDictionary(), 0, 0); } QPDFObjectHandle @@ -2193,13 +2174,13 @@ QPDF::getObjectByID(int objid, int generation) } void -QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) +QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) { - replaceObject(og.getObj(), og.getGen(), oh); + replaceObject(QPDFObjGen(objid, generation), oh); } void -QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) +QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) { if (oh.isIndirect()) { QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); @@ -2208,10 +2189,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) } // Force new object to appear in the cache - resolve(objid, generation); + resolve(og); // Replace the object in the object cache - QPDFObjGen og(objid, generation); this->m->ever_replaced_objects = true; this->m->obj_cache[og] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); @@ -2511,8 +2491,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) auto foreign_stream_data = std::make_shared( foreign_stream_qpdf->m->encp, foreign_stream_qpdf->m->file, - foreign.getObjectID(), - foreign.getGeneration(), + foreign.getObjGen(), stream->getOffset(), stream->getLength(), dict); @@ -2526,20 +2505,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) } void -QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) +QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) { - swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen()); + swapObjects( + QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2)); } void -QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) +QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) { // Force objects to be loaded into cache; then swap them in the // cache. - resolve(objid1, generation1); - resolve(objid2, generation2); - QPDFObjGen og1(objid1, generation1); - QPDFObjGen og2(objid2, generation2); + resolve(og1); + resolve(og2); ObjCache t = this->m->obj_cache[og1]; this->m->ever_replaced_objects = true; this->m->obj_cache[og1] = this->m->obj_cache[og2]; @@ -2723,8 +2701,7 @@ QPDF::pipeStreamData( std::shared_ptr encp, std::shared_ptr file, QPDF& qpdf_for_warning, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle stream_dict, @@ -2735,14 +2712,7 @@ QPDF::pipeStreamData( std::vector> to_delete; if (encp->encrypted) { decryptStream( - encp, - file, - qpdf_for_warning, - pipeline, - objid, - generation, - stream_dict, - to_delete); + encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete); } bool success = false; @@ -2780,8 +2750,7 @@ QPDF::pipeStreamData( "", file->getLastOffset(), ("error decoding stream data for object " + - QPDFObjGen(objid, generation).unparse(' ') + ": " + - e.what()))); + og.unparse(' ') + ": " + e.what()))); if (will_retry) { qpdf_for_warning.warn( // line-break @@ -2807,8 +2776,7 @@ QPDF::pipeStreamData( bool QPDF::pipeStreamData( - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle stream_dict, @@ -2820,8 +2788,7 @@ QPDF::pipeStreamData( this->m->encp, this->m->file, *this, - objid, - generation, + og, offset, length, stream_dict, @@ -2844,8 +2811,7 @@ QPDF::pipeForeignStreamData( foreign->encp, foreign->file, *this, - foreign->foreign_objid, - foreign->foreign_generation, + foreign->foreign_og, foreign->offset, foreign->length, foreign->local_dict, diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 779a61ed..e7a98090 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -3098,7 +3098,7 @@ QPDFObjectHandle::dereference() } if (this->obj.get() == 0) { std::shared_ptr obj = - QPDF::Resolver::resolve(this->qpdf, getObjectID(), getGeneration()); + QPDF::Resolver::resolve(this->qpdf, getObjGen()); if (obj.get() == 0) { // QPDF::resolve never returns an uninitialized object, but // check just in case. diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index c0644532..c8290286 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -658,8 +658,7 @@ QPDF_Stream::pipeStreamData( QTC::TC("qpdf", "QPDF_Stream pipe original stream data"); if (!QPDF::Pipe::pipeStreamData( this->qpdf, - this->objid, - this->generation, + QPDFObjGen(this->objid, this->generation), this->offset, this->length, this->stream_dict, diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 95d5ea37..8c35b992 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -1075,8 +1075,7 @@ QPDF::initializeEncryption() std::string QPDF::getKeyForObject( std::shared_ptr encp, - int objid, - int generation, + QPDFObjGen const& og, bool use_aes) { if (!encp->encrypted) { @@ -1084,26 +1083,24 @@ QPDF::getKeyForObject( "request for encryption key in non-encrypted PDF"); } - if (!((objid == encp->cached_key_objid) && - (generation == encp->cached_key_generation))) { + if (og != encp->cached_key_og) { encp->cached_object_encryption_key = compute_data_key( encp->encryption_key, - objid, - generation, + og.getObj(), + og.getGen(), use_aes, encp->encryption_V, encp->encryption_R); - encp->cached_key_objid = objid; - encp->cached_key_generation = generation; + encp->cached_key_og = og; } return encp->cached_object_encryption_key; } void -QPDF::decryptString(std::string& str, int objid, int generation) +QPDF::decryptString(std::string& str, QPDFObjGen const& og) { - if (objid == 0) { + if (!og.isIndirect()) { return; } bool use_aes = false; @@ -1139,8 +1136,7 @@ QPDF::decryptString(std::string& str, int objid, int generation) } } - std::string key = - getKeyForObject(this->m->encp, objid, generation, use_aes); + std::string key = getKeyForObject(this->m->encp, og, use_aes); try { if (use_aes) { QTC::TC("qpdf", "QPDF_encryption aes decode string"); @@ -1175,8 +1171,8 @@ QPDF::decryptString(std::string& str, int objid, int generation) this->m->file->getName(), this->m->last_object_description, this->m->file->getLastOffset(), - "error decrypting string for object " + - QPDFObjGen(objid, generation).unparse() + ": " + e.what()); + "error decrypting string for object " + og.unparse() + ": " + + e.what()); } } @@ -1186,8 +1182,7 @@ QPDF::decryptStream( std::shared_ptr file, QPDF& qpdf_for_warning, Pipeline*& pipeline, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle& stream_dict, std::vector>& heap) { @@ -1282,7 +1277,7 @@ QPDF::decryptStream( break; } } - std::string key = getKeyForObject(encp, objid, generation, use_aes); + std::string key = getKeyForObject(encp, og, use_aes); std::shared_ptr new_pipeline; if (use_aes) { QTC::TC("qpdf", "QPDF_encryption aes decode stream"); diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index 1db9018c..5527318c 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -371,9 +371,10 @@ QPDF::JSONReactor::containerEnd(JSON const& value) QPDFObjectHandle QPDF::JSONReactor::reserveObject(int obj, int gen) { - auto oh = pdf.reserveObjectIfNotExists(obj, gen); + QPDFObjGen og(obj, gen); + auto oh = pdf.reserveObjectIfNotExists(og); if (oh.isReserved()) { - this->reserved.insert(QPDFObjGen(obj, gen)); + this->reserved.insert(og); } return oh; } @@ -495,8 +496,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) QTC::TC("qpdf", "QPDF_json updating existing stream"); } else { this->this_stream_needs_data = true; - replacement = - pdf.reserveStream(tos.getObjectID(), tos.getGeneration()); + replacement = pdf.reserveStream(tos.getObjGen()); replaceObject(tos, replacement, value); } } else { diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index cb4d721f..5fa432e0 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -706,7 +706,7 @@ QPDF::getUncompressedObject( return obj; } else { int repl = (*(object_stream_data.find(obj.getObjectID()))).second; - return objGenToIndirect(QPDFObjGen(repl, 0)); + return getObjectByObjGen(QPDFObjGen(repl)); } } @@ -1143,12 +1143,6 @@ QPDF::dumpHGeneric(HGeneric& t) << "group_length: " << t.group_length << "\n"; } -QPDFObjectHandle -QPDF::objGenToIndirect(QPDFObjGen const& og) -{ - return getObjectByID(og.getObj(), og.getGen()); -} - void QPDF::calculateLinearizationData(std::map const& object_stream_data) { @@ -1387,9 +1381,9 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) stopOnError("found other than one root while" " calculating linearization data"); } - this->m->part4.push_back(objGenToIndirect(*(lc_root.begin()))); + this->m->part4.push_back(getObjectByObjGen(*(lc_root.begin()))); for (auto const& og: lc_open_document) { - this->m->part4.push_back(objGenToIndirect(og)); + this->m->part4.push_back(getObjectByObjGen(og)); } // Part 6: first page objects. Note: implementation note 124 @@ -1418,11 +1412,11 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // hint tables. for (auto const& og: lc_first_page_private) { - this->m->part6.push_back(objGenToIndirect(og)); + this->m->part6.push_back(getObjectByObjGen(og)); } for (auto const& og: lc_first_page_shared) { - this->m->part6.push_back(objGenToIndirect(og)); + this->m->part6.push_back(getObjectByObjGen(og)); } // Place the outline dictionary if it goes in the first page section. @@ -1468,7 +1462,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) for (auto const& og: this->m->obj_user_to_objects[ou]) { if (lc_other_page_private.count(og)) { lc_other_page_private.erase(og); - this->m->part7.push_back(objGenToIndirect(og)); + this->m->part7.push_back(getObjectByObjGen(og)); ++this->m->c_page_offset_data.entries.at(i).nobjects; } } @@ -1485,7 +1479,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // Order is unimportant. for (auto const& og: lc_other_page_shared) { - this->m->part8.push_back(objGenToIndirect(og)); + this->m->part8.push_back(getObjectByObjGen(og)); } // Part 9: other objects @@ -1507,7 +1501,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) for (auto const& og: pages_ogs) { if (lc_other.count(og)) { lc_other.erase(og); - this->m->part9.push_back(objGenToIndirect(og)); + this->m->part9.push_back(getObjectByObjGen(og)); } } @@ -1537,7 +1531,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) for (auto const& og: ogs) { if (lc_thumbnail_private.count(og)) { lc_thumbnail_private.erase(og); - this->m->part9.push_back(objGenToIndirect(og)); + this->m->part9.push_back(getObjectByObjGen(og)); } } } @@ -1550,7 +1544,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // Place shared thumbnail objects for (auto const& og: lc_thumbnail_shared) { - this->m->part9.push_back(objGenToIndirect(og)); + this->m->part9.push_back(getObjectByObjGen(og)); } // Place outlines unless in first page @@ -1560,7 +1554,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // Place all remaining objects for (auto const& og: lc_other) { - this->m->part9.push_back(objGenToIndirect(og)); + this->m->part9.push_back(getObjectByObjGen(og)); } // Make sure we got everything exactly once. @@ -1662,7 +1656,7 @@ QPDF::pushOutlinesToPart( lc_outlines.erase(outlines_og); part.push_back(outlines); for (auto const& og: lc_outlines) { - part.push_back(objGenToIndirect(og)); + part.push_back(getObjectByObjGen(og)); ++this->m->c_outline_data.nobjects; } } diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc index 1fd6da6f..cafdbe64 100644 --- a/libqpdf/QPDF_optimization.cc +++ b/libqpdf/QPDF_optimization.cc @@ -252,9 +252,7 @@ QPDF::pushInheritedAttributesToPageInternal( if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) { QTC::TC("qpdf", "QPDF unknown key not inherited"); setLastObjectDescription( - "Pages object", - cur_pages.getObjectID(), - cur_pages.getGeneration()); + "Pages object", cur_pages.getObjGen()); warn( qpdf_e_pages, this->m->last_object_description, diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc index bd3f80a6..e1a3b2c1 100644 --- a/libqpdf/QPDF_pages.cc +++ b/libqpdf/QPDF_pages.cc @@ -207,8 +207,7 @@ QPDF::insertPageobjToPage( // that causes this to happen. setLastObjectDescription( "page " + QUtil::int_to_string(pos) + " (numbered from zero)", - og.getObj(), - og.getGen()); + og); throw QPDFExc( qpdf_e_pages, this->m->file->getName(), @@ -334,7 +333,7 @@ QPDF::findPage(QPDFObjGen const& og) auto it = this->m->pageobj_to_pages_pos.find(og); if (it == this->m->pageobj_to_pages_pos.end()) { QTC::TC("qpdf", "QPDF_pages findPage not found"); - setLastObjectDescription("page object", og.getObj(), og.getGen()); + setLastObjectDescription("page object", og); throw QPDFExc( qpdf_e_pages, this->m->file->getName(), -- cgit v1.2.3-54-g00ecf From 4b73d057fb637bb2c2810aaf9fefdfe9b8beaef6 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 19:44:11 +0100 Subject: QPDFObjGen : tidy QPDF_Stream Change method signatures to use QPDFObjGen. Replace QPDF_Stream::objid and generation with QPDF_Stream::og. --- libqpdf/QPDFObjectHandle.cc | 10 +++++----- libqpdf/QPDF_Stream.cc | 38 +++++++++++++++----------------------- libqpdf/qpdf/QPDF_Stream.hh | 11 ++++------- 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index e7a98090..e883dcd0 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -2634,8 +2634,8 @@ QPDFObjectHandle::newStream( qpdf_offset_t offset, size_t length) { - QPDFObjectHandle result = QPDFObjectHandle(QPDF_Stream::create( - qpdf, og.getObj(), og.getGen(), stream_dict, offset, length)); + QPDFObjectHandle result = QPDFObjectHandle( + QPDF_Stream::create(qpdf, og, stream_dict, offset, length)); if (offset) { result.setParsedOffset(offset); } @@ -2651,11 +2651,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf) } QTC::TC("qpdf", "QPDFObjectHandle newStream"); QPDFObjectHandle stream_dict = newDictionary(); - QPDFObjectHandle result = qpdf->makeIndirectObject( - QPDFObjectHandle(QPDF_Stream::create(qpdf, 0, 0, stream_dict, 0, 0))); + QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( + QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0))); result.dereference(); QPDF_Stream* stream = dynamic_cast(result.obj.get()); - stream->setObjGen(result.getObjectID(), result.getGeneration()); + stream->setObjGen(result.getObjGen()); return result; } diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index c8290286..aed9370d 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -110,14 +110,12 @@ StreamBlobProvider::operator()(Pipeline* p) QPDF_Stream::QPDF_Stream( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) : qpdf(qpdf), - objid(objid), - generation(generation), + og(og), filter_on_write(true), stream_dict(stream_dict), offset(offset), @@ -128,22 +126,18 @@ QPDF_Stream::QPDF_Stream( "object for dictionary"); } setDescription( - this->qpdf, - this->qpdf->getFilename() + ", stream object " + - QPDFObjGen(objid, generation).unparse(' ')); + qpdf, qpdf->getFilename() + ", stream object " + og.unparse(' ')); } std::shared_ptr QPDF_Stream::create( QPDF* qpdf, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) { - return do_create( - new QPDF_Stream(qpdf, objid, generation, stream_dict, offset, length)); + return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length)); } std::shared_ptr @@ -180,22 +174,21 @@ QPDF_Stream::releaseResolved() } void -QPDF_Stream::setObjGen(int objid, int generation) +QPDF_Stream::setObjGen(QPDFObjGen const& og) { - if (!((this->objid == 0) && (this->generation == 0))) { + if (this->og.isIndirect()) { throw std::logic_error( "attempt to set object ID and generation of a stream" " that already has them"); } - this->objid = objid; - this->generation = generation; + this->og = og; } std::string QPDF_Stream::unparse() { // Unparse stream objects as indirect references - return QPDFObjGen(objid, generation).unparse(' ') + " R"; + return og.unparse(' ') + " R"; } JSON @@ -617,8 +610,8 @@ QPDF_Stream::pipeStreamData( Pl_Count count("stream provider count", pipeline); if (this->stream_provider->supportsRetry()) { if (!this->stream_provider->provideStreamData( - this->objid, - this->generation, + og.getObj(), + og.getGen(), &count, suppress_warnings, will_retry)) { @@ -627,7 +620,7 @@ QPDF_Stream::pipeStreamData( } } else { this->stream_provider->provideStreamData( - this->objid, this->generation, &count); + og.getObj(), og.getGen(), &count); } qpdf_offset_t actual_length = count.getCount(); qpdf_offset_t desired_length = 0; @@ -640,9 +633,8 @@ QPDF_Stream::pipeStreamData( // This would be caused by programmer error on the // part of a library user, not by invalid input data. throw std::runtime_error( - "stream data provider for " + - QPDFObjGen(objid, generation).unparse(' ') + " provided " + - QUtil::int_to_string(actual_length) + + "stream data provider for " + og.unparse(' ') + + " provided " + QUtil::int_to_string(actual_length) + " bytes instead of expected " + QUtil::int_to_string(desired_length) + " bytes"); } @@ -658,7 +650,7 @@ QPDF_Stream::pipeStreamData( QTC::TC("qpdf", "QPDF_Stream pipe original stream data"); if (!QPDF::Pipe::pipeStreamData( this->qpdf, - QPDFObjGen(this->objid, this->generation), + og, this->offset, this->length, this->stream_dict, diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh index 3b7cf358..8980c751 100644 --- a/libqpdf/qpdf/QPDF_Stream.hh +++ b/libqpdf/qpdf/QPDF_Stream.hh @@ -19,8 +19,7 @@ class QPDF_Stream: public QPDFObject virtual ~QPDF_Stream() = default; static std::shared_ptr create( QPDF*, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); @@ -78,7 +77,7 @@ class QPDF_Stream: public QPDFObject // Replace object ID and generation. This may only be called if // object ID and generation are 0. It is used by QPDFObjectHandle // when adding streams to files. - void setObjGen(int objid, int generation); + void setObjGen(QPDFObjGen const& og); protected: virtual void releaseResolved(); @@ -86,8 +85,7 @@ class QPDF_Stream: public QPDFObject private: QPDF_Stream( QPDF*, - int objid, - int generation, + QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); @@ -111,8 +109,7 @@ class QPDF_Stream: public QPDFObject void setDictDescription(); QPDF* qpdf; - int objid; - int generation; + QPDFObjGen og; bool filter_on_write; QPDFObjectHandle stream_dict; qpdf_offset_t offset; -- cgit v1.2.3-54-g00ecf From 5d0469f1bcbe1c4d008e71bc690273198805a405 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 23 Jul 2022 21:16:23 +0100 Subject: QPDFObjGen : tidy QPDFJob Use QPDFObjGen::unparse where appropriate. --- libqpdf/QPDFJob.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 8af038f4..617d6b80 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -2464,7 +2464,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf) QTC::TC("qpdf", "QPDFJob found resources in non-leaf"); doIfVerbose([&](Pipeline& v, std::string const& prefix) { v << " found resources in non-leaf page node " - << og.getObj() << " " << og.getGen() << "\n"; + << og.unparse(' ') << "\n"; }); return true; } @@ -2481,9 +2481,8 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf) QTC::TC("qpdf", "QPDFJob found shared resources in leaf"); doIfVerbose([&](Pipeline& v, std::string const& prefix) { v << " found shared resources in leaf node " - << og.getObj() << " " << og.getGen() << ": " - << resources_og.getObj() << " " - << resources_og.getGen() << "\n"; + << og.unparse(' ') << ": " + << resources_og.unparse(' ') << "\n"; }); return true; } @@ -2498,8 +2497,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf) QTC::TC("qpdf", "QPDFJob found shared xobject in leaf"); doIfVerbose([&](Pipeline& v, std::string const& prefix) { v << " found shared xobject in leaf node " - << og.getObj() << " " << og.getGen() << ": " - << xobject_og.getObj() << " " << xobject_og.getGen() + << og.unparse(' ') << ": " << xobject_og.unparse(' ') << "\n"; }); return true; @@ -3376,7 +3374,7 @@ QPDFJob::writeJSON(QPDF& pdf) auto wanted = getWantedJSONObjects(); for (auto const& og: wanted) { std::ostringstream s; - s << "obj:" << og.getObj() << " " << og.getGen() << " R"; + s << "obj:" << og.unparse(' ') << " R"; json_objects.insert(s.str()); } pdf.writeJSON( -- cgit v1.2.3-54-g00ecf From afd35f9a30e35011e82fef45b65cfae702a006a4 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 24 Jul 2022 14:16:37 +0100 Subject: Overload StreamDataProvider::provideStreamData Use 'QPDFObjGen const&' instead of 'int, int' in signature. --- examples/pdf-create.cc | 7 +++---- examples/pdf-custom-filter.cc | 5 ++--- examples/pdf-invert-images.cc | 5 ++--- include/qpdf/QPDF.hh | 3 +-- include/qpdf/QPDFObjectHandle.hh | 10 +++++++++- libqpdf/QPDF.cc | 9 +++------ libqpdf/QPDFJob.cc | 5 ++--- libqpdf/QPDFObjectHandle.cc | 28 ++++++++++++++++++++++------ libqpdf/QPDFPageObjectHelper.cc | 5 ++--- libqpdf/QPDF_Stream.cc | 9 ++------- qpdf/test_driver.cc | 2 ++ 11 files changed, 50 insertions(+), 38 deletions(-) diff --git a/examples/pdf-create.cc b/examples/pdf-create.cc index 5e9e4239..785021da 100644 --- a/examples/pdf-create.cc +++ b/examples/pdf-create.cc @@ -29,8 +29,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider public: ImageProvider(std::string const& color_space, std::string const& filter); virtual ~ImageProvider() = default; - virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline); + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline); size_t getWidth() const; size_t getHeight() const; @@ -93,7 +92,7 @@ ImageProvider::getHeight() const } void -ImageProvider::provideStreamData(int objid, int generation, Pipeline* pipeline) +ImageProvider::provideStreamData(QPDFObjGen const&, Pipeline* pipeline) { std::vector> to_delete; Pipeline* p = pipeline; @@ -292,7 +291,7 @@ check( ImageProvider* p = new ImageProvider(desired_color_space, "null"); std::shared_ptr provider(p); Pl_Buffer b_p("get image data"); - provider->provideStreamData(0, 0, &b_p); + provider->provideStreamData(QPDFObjGen(), &b_p); std::shared_ptr desired_data(b_p.getBuffer()); if (desired_data->getSize() != actual_data->getSize()) { diff --git a/examples/pdf-custom-filter.cc b/examples/pdf-custom-filter.cc index ede4a19c..e7877bea 100644 --- a/examples/pdf-custom-filter.cc +++ b/examples/pdf-custom-filter.cc @@ -201,7 +201,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider StreamReplacer(QPDF* pdf); virtual ~StreamReplacer() = default; virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline) override; + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override; void registerStream( QPDFObjectHandle stream, @@ -384,9 +384,8 @@ StreamReplacer::registerStream( } void -StreamReplacer::provideStreamData(int objid, int generation, Pipeline* pipeline) +StreamReplacer::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) { - QPDFObjGen og(objid, generation); QPDFObjectHandle orig = this->copied_streams[og]; // call maybeReplace again, this time with the pipeline and no // dict_updates. In this mode, maybeReplace doesn't make any diff --git a/examples/pdf-invert-images.cc b/examples/pdf-invert-images.cc index 2c9a88e7..94392ac3 100644 --- a/examples/pdf-invert-images.cc +++ b/examples/pdf-invert-images.cc @@ -35,7 +35,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider public: virtual ~ImageInverter() = default; virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline) override; + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override; void registerImage( QPDFObjectHandle image, @@ -82,12 +82,11 @@ ImageInverter::registerImage( } void -ImageInverter::provideStreamData(int objid, int generation, Pipeline* pipeline) +ImageInverter::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) { // Use the object and generation number supplied to look up the // image data. Then invert the image data and write the inverted // data to the pipeline. - QPDFObjGen og(objid, generation); std::shared_ptr data = this->copied_images[og].getStreamData(qpdf_dl_all); size_t size = data->getSize(); diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index ae5c89e2..a80ddcd5 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -990,8 +990,7 @@ class QPDF CopiedStreamDataProvider(QPDF& destination_qpdf); virtual ~CopiedStreamDataProvider() = default; virtual bool provideStreamData( - int objid, - int generation, + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) override; diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 68fc78f8..8e33085c 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -116,9 +116,17 @@ class QPDFObjectHandle // indicating whether it ran without errors. QPDF_DLL virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline); + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline); QPDF_DLL virtual bool provideStreamData( + QPDFObjGen const& og, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + // The following two overloads are deprecated. + QPDF_DLL virtual void + provideStreamData(int objid, int generation, Pipeline* pipeline); + QPDF_DLL virtual bool provideStreamData( int objid, int generation, Pipeline* pipeline, diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index a24c17e6..a64096a2 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -135,22 +135,19 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider( bool QPDF::CopiedStreamDataProvider::provideStreamData( - int objid, - int generation, + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) { - std::shared_ptr foreign_data = - this->foreign_stream_data[QPDFObjGen(objid, generation)]; + std::shared_ptr foreign_data = foreign_stream_data[og]; bool result = false; if (foreign_data.get()) { result = destination_qpdf.pipeForeignStreamData( foreign_data, pipeline, suppress_warnings, will_retry); QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1); } else { - QPDFObjectHandle foreign_stream = - this->foreign_streams[QPDFObjGen(objid, generation)]; + auto foreign_stream = foreign_streams[og]; result = foreign_stream.pipeStreamData( pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry); QTC::TC( diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 617d6b80..343fa348 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -49,8 +49,7 @@ namespace size_t oi_min_area, QPDFObjectHandle& image); virtual ~ImageOptimizer() = default; - virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline); + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline); std::shared_ptr makePipeline(std::string const& description, Pipeline* next); bool evaluate(std::string const& description); @@ -250,7 +249,7 @@ ImageOptimizer::evaluate(std::string const& description) } void -ImageOptimizer::provideStreamData(int, int, Pipeline* pipeline) +ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline) { std::shared_ptr p = makePipeline("", pipeline); if (p.get() == nullptr) { diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index e883dcd0..753493ec 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -51,6 +51,24 @@ QPDFObjectHandle::StreamDataProvider::~StreamDataProvider() // README-maintainer } +void +QPDFObjectHandle::StreamDataProvider::provideStreamData( + QPDFObjGen const& og, Pipeline* pipeline) +{ + return provideStreamData(og.getObj(), og.getGen(), pipeline); +} + +bool +QPDFObjectHandle::StreamDataProvider::provideStreamData( + QPDFObjGen const& og, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry) +{ + return provideStreamData( + og.getObj(), og.getGen(), pipeline, suppress_warnings, will_retry); +} + void QPDFObjectHandle::StreamDataProvider::provideStreamData( int objid, int generation, Pipeline* pipeline) @@ -90,8 +108,7 @@ namespace { } virtual ~CoalesceProvider() = default; - virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline); + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline); private: QPDFObjectHandle containing_page; @@ -100,7 +117,7 @@ namespace } // namespace void -CoalesceProvider::provideStreamData(int, int, Pipeline* p) +CoalesceProvider::provideStreamData(QPDFObjGen const&, Pipeline* p) { QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data"); std::string description = @@ -1425,15 +1442,14 @@ namespace } virtual void - provideStreamData(int, int, Pipeline* pipeline) override + provideStreamData(QPDFObjGen const&, Pipeline* pipeline) override { p1(pipeline); } virtual bool provideStreamData( - int, - int, + QPDFObjGen const&, Pipeline* pipeline, bool suppress_warnings, bool will_retry) override diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index 16ab346f..96a8ce69 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -21,8 +21,7 @@ namespace { } virtual ~ContentProvider() = default; - virtual void - provideStreamData(int objid, int generation, Pipeline* pipeline); + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline); private: QPDFObjectHandle from_page; @@ -30,7 +29,7 @@ namespace } // namespace void -ContentProvider::provideStreamData(int, int, Pipeline* p) +ContentProvider::provideStreamData(QPDFObjGen const&, Pipeline* p) { Pl_Concatenate concat("concatenate", p); std::string description = diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index aed9370d..84965102 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -610,17 +610,12 @@ QPDF_Stream::pipeStreamData( Pl_Count count("stream provider count", pipeline); if (this->stream_provider->supportsRetry()) { if (!this->stream_provider->provideStreamData( - og.getObj(), - og.getGen(), - &count, - suppress_warnings, - will_retry)) { + og, &count, suppress_warnings, will_retry)) { filter = false; success = false; } } else { - this->stream_provider->provideStreamData( - og.getObj(), og.getGen(), &count); + this->stream_provider->provideStreamData(og, &count); } qpdf_offset_t actual_length = count.getCount(); qpdf_offset_t desired_length = 0; diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 0eb6ed8d..f1c1d72a 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -56,6 +56,8 @@ class Provider: public QPDFObjectHandle::StreamDataProvider virtual void provideStreamData(int objid, int generation, Pipeline* p) { + // Don't change signature to use QPDFObjGen const& to detect + // problems forwarding to legacy implementations. p->write(b->getBuffer(), b->getSize()); if (this->bad_length) { unsigned char ch = ' '; -- cgit v1.2.3-54-g00ecf From 8b4afa428e9caa1a34cad434dfe8a3e01e5a24d3 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 24 Jul 2022 15:35:19 +0100 Subject: Revert making second parameter of QPDFObjGen::QPDFObjGen optional Also, change test for QPDFObjGen::isIndirect to obj != 0. Delete comment from commit afd35f9. --- include/qpdf/QPDFObjGen.hh | 4 ++-- include/qpdf/QPDFObjectHandle.hh | 1 - libqpdf/QPDF.cc | 6 +++--- libqpdf/QPDF_linearization.cc | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index a1829b00..df9ef737 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -38,7 +38,7 @@ class QPDFObjGen { } QPDF_DLL - explicit QPDFObjGen(int obj, int gen = 0) : + explicit QPDFObjGen(int obj, int gen) : obj(obj), gen(gen) { @@ -77,7 +77,7 @@ class QPDFObjGen bool isIndirect() const { - return obj > 0; + return obj != 0; } QPDF_DLL std::string unparse(char separator = ',') const; diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 8e33085c..790acccd 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -123,7 +123,6 @@ class QPDFObjectHandle Pipeline* pipeline, bool suppress_warnings, bool will_retry); - // The following two overloads are deprecated. QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); QPDF_DLL virtual bool provideStreamData( diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index a64096a2..a0f0f9e1 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -1051,7 +1051,7 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) QPDFObjectHandle xref_obj; try { xref_obj = readObjectAtOffset( - false, xref_offset, "xref stream", QPDFObjGen(), x_og); + false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og); } catch (QPDFExc&) { // ignore -- report error below } @@ -1333,7 +1333,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) break; case 2: - this->m->xref_table[QPDFObjGen(obj)] = QPDFXRefEntry(f0, f1, f2); + this->m->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2); break; default: @@ -2110,7 +2110,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) // xref table and only cache what would actually be resolved here. for (auto const& iter: offsets) { int obj = iter.first; - QPDFObjGen og(obj); + QPDFObjGen og(obj, 0); QPDFXRefEntry const& entry = this->m->xref_table[og]; if ((entry.getType() == 2) && (entry.getObjStreamNumber() == obj_stream_number)) { diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index 5fa432e0..64805f58 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -137,8 +137,8 @@ QPDF::isLinearized() return false; } - QPDFObjectHandle candidate = - QPDFObjectHandle::Factory::newIndirect(this, QPDFObjGen(lindict_obj)); + QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect( + this, QPDFObjGen(lindict_obj, 0)); if (!candidate.isDictionary()) { return false; } @@ -327,7 +327,7 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) { QPDFObjGen og; QPDFObjectHandle H = readObjectAtOffset( - false, offset, "linearization hint stream", QPDFObjGen(), og); + false, offset, "linearization hint stream", QPDFObjGen(0, 0), og); ObjCache& oc = this->m->obj_cache[og]; qpdf_offset_t min_end_offset = oc.end_before_space; qpdf_offset_t max_end_offset = oc.end_after_space; @@ -706,7 +706,7 @@ QPDF::getUncompressedObject( return obj; } else { int repl = (*(object_stream_data.find(obj.getObjectID()))).second; - return getObjectByObjGen(QPDFObjGen(repl)); + return getObjectByObjGen(QPDFObjGen(repl, 0)); } } -- cgit v1.2.3-54-g00ecf