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()); } }