Add optional parameter separator to QPDFObjGen::unparse

Also, revert inlining of unparse and operator << from commit 4c6640c in
order to avoid exposing QUtil.
This commit is contained in:
m-holger 2022-07-16 11:21:11 +01:00
parent 6f1041afb8
commit eeb6162f76
12 changed files with 58 additions and 70 deletions

View File

@ -23,7 +23,6 @@
#define QPDFOBJGEN_HH #define QPDFOBJGEN_HH
#include <qpdf/DLL.h> #include <qpdf/DLL.h>
#include <qpdf/QUtil.hh>
#include <iostream> #include <iostream>
// This class represents an object ID and generation pair. It is // This class represents an object ID and generation pair. It is
@ -69,18 +68,9 @@ class QPDFObjGen
return gen; return gen;
} }
QPDF_DLL QPDF_DLL
std::string std::string unparse(char separator = ',') const;
unparse() const
{
return QUtil::int_to_string(obj) + "," + QUtil::int_to_string(gen);
}
QPDF_DLL QPDF_DLL
friend std::ostream& friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og);
operator<<(std::ostream& os, const QPDFObjGen& og)
{
os << og.obj << "," << og.gen;
return os;
}
private: private:
// This class does not use the Members pattern to avoid a memory // This class does not use the Members pattern to avoid a memory

View File

@ -1584,7 +1584,6 @@ class QPDFObjectHandle
bool stop_at_streams); bool stop_at_streams);
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only); void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
void releaseResolved(); void releaseResolved();
std::string getObjGenAsStr() const;
static void setObjectDescriptionFromInput( static void setObjectDescriptionFromInput(
QPDFObjectHandle, QPDFObjectHandle,
QPDF*, QPDF*,

View File

@ -74,6 +74,7 @@ set(libqpdf_SOURCES
QPDFNumberTreeObjectHelper.cc QPDFNumberTreeObjectHelper.cc
QPDFObject.cc QPDFObject.cc
QPDFObjectHandle.cc QPDFObjectHandle.cc
QPDFObjGen.cc
QPDFOutlineDocumentHelper.cc QPDFOutlineDocumentHelper.cc
QPDFOutlineObjectHelper.cc QPDFOutlineObjectHelper.cc
QPDFPageDocumentHelper.cc QPDFPageDocumentHelper.cc

View File

@ -1493,9 +1493,8 @@ QPDF::setLastObjectDescription(
} }
} }
if (objid > 0) { if (objid > 0) {
this->m->last_object_description += "object " + this->m->last_object_description +=
QUtil::int_to_string(objid) + " " + "object " + QPDFObjGen(objid, generation).unparse(' ');
QUtil::int_to_string(generation);
} }
} }
@ -1862,8 +1861,8 @@ QPDF::readObjectAtOffset(
this->m->file->getName(), this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
offset, offset,
(std::string("expected ") + QUtil::int_to_string(exp_objid) + (std::string("expected ") +
" " + QUtil::int_to_string(exp_generation) + " obj")); QPDFObjGen(exp_objid, exp_generation).unparse(' ') + " obj"));
if (try_recovery) { if (try_recovery) {
// Will be retried below // Will be retried below
throw e; throw e;
@ -1898,8 +1897,8 @@ QPDF::readObjectAtOffset(
"", "",
0, 0,
std::string( std::string(
"object " + QUtil::int_to_string(exp_objid) + " " + "object " +
QUtil::int_to_string(exp_generation) + QPDFObjGen(exp_objid, exp_generation).unparse(' ') +
" not found in file after regenerating" " not found in file after regenerating"
" cross reference table")); " cross reference table"));
return QPDFObjectHandle::newNull(); return QPDFObjectHandle::newNull();
@ -2002,8 +2001,7 @@ QPDF::resolve(int objid, int generation)
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
"", "",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
("loop detected resolving object " + QUtil::int_to_string(objid) + ("loop detected resolving object " + og.unparse(' ')));
" " + QUtil::int_to_string(generation)));
return QPDF_Null::create(); return QPDF_Null::create();
} }
ResolveRecorder rr(this, og); ResolveRecorder rr(this, og);
@ -2039,8 +2037,7 @@ QPDF::resolve(int objid, int generation)
this->m->file->getName(), this->m->file->getName(),
"", "",
0, 0,
("object " + QUtil::int_to_string(objid) + "/" + ("object " + og.unparse('/') +
QUtil::int_to_string(generation) +
" has unexpected xref entry type")); " has unexpected xref entry type"));
} }
} catch (QPDFExc& e) { } catch (QPDFExc& e) {
@ -2050,8 +2047,7 @@ QPDF::resolve(int objid, int generation)
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
"", "",
0, 0,
("object " + QUtil::int_to_string(objid) + "/" + ("object " + og.unparse('/') +
QUtil::int_to_string(generation) +
": error reading object: " + e.what())); ": error reading object: " + e.what()));
} }
} }
@ -2065,10 +2061,7 @@ QPDF::resolve(int objid, int generation)
std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object); std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
if (!result->hasDescription()) { if (!result->hasDescription()) {
result->setDescription( result->setDescription(this, ("object " + og.unparse(' ')));
this,
("object " + QUtil::int_to_string(objid) + " " +
QUtil::int_to_string(generation)));
} }
return result; return result;
} }
@ -2809,8 +2802,8 @@ QPDF::pipeStreamData(
"", "",
file->getLastOffset(), file->getLastOffset(),
("error decoding stream data for object " + ("error decoding stream data for object " +
QUtil::int_to_string(objid) + " " + QPDFObjGen(objid, generation).unparse(' ') + ": " +
QUtil::int_to_string(generation) + ": " + e.what()))); e.what())));
if (will_retry) { if (will_retry) {
qpdf_for_warning.warn( qpdf_for_warning.warn(
// line-break // line-break

View File

@ -991,8 +991,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
} else { } else {
parent.warnIfPossible( parent.warnIfPossible(
"while traversing field " + "while traversing field " +
obj.getObjGen().unparse() + ", found parent (" + obj.getObjGen().unparse(',') + ", found parent (" +
parent_og.unparse() + parent_og.unparse(',') +
") that had not been seen, indicating likely" ") that had not been seen, indicating likely"
" invalid field structure"); " invalid field structure");
} }

View File

@ -947,7 +947,7 @@ QPDFJob::doShowObj(QPDF& pdf)
} }
if (error) { if (error) {
throw std::runtime_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; auto efoh = i.second;
*this->m->log->getInfo() *this->m->log->getInfo()
<< key << " -> " << key << " -> "
<< efoh->getEmbeddedFileStream().getObjGen().unparse() << "\n"; << efoh->getEmbeddedFileStream().getObjGen().unparse(',')
<< "\n";
doIfVerbose([&](Pipeline& v, std::string const& prefix) { doIfVerbose([&](Pipeline& v, std::string const& prefix) {
auto desc = efoh->getDescription(); auto desc = efoh->getDescription();
if (!desc.empty()) { if (!desc.empty()) {
@ -1010,7 +1011,7 @@ QPDFJob::doListAttachments(QPDF& pdf)
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) { for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
auto efs = QPDFEFStreamObjectHelper(i2.second); auto efs = QPDFEFStreamObjectHelper(i2.second);
v << " " << i2.first << " -> " v << " " << i2.first << " -> "
<< efs.getObjectHandle().getObjGen().unparse() << "\n"; << efs.getObjectHandle().getObjGen().unparse(',') << "\n";
v << " creation date: " << efs.getCreationDate() v << " creation date: " << efs.getCreationDate()
<< "\n" << "\n"
<< " modification date: " << efs.getModDate() << "\n" << " modification date: " << efs.getModDate() << "\n"

17
libqpdf/QPDFObjGen.cc Normal file
View File

@ -0,0 +1,17 @@
#include <qpdf/QPDFObjGen.hh>
#include <qpdf/QUtil.hh>
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);
}

View File

@ -103,9 +103,8 @@ void
CoalesceProvider::provideStreamData(int, int, Pipeline* p) CoalesceProvider::provideStreamData(int, int, Pipeline* p)
{ {
QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data"); QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data");
std::string description = "page object " + std::string description =
QUtil::int_to_string(containing_page.getObjectID()) + " " + "page object " + containing_page.getObjGen().unparse(' ');
QUtil::int_to_string(containing_page.getGeneration());
std::string all_description; std::string all_description;
old_contents.pipeContentStreams(p, description, all_description); old_contents.pipeContentStreams(p, description, all_description);
} }
@ -1485,13 +1484,6 @@ QPDFObjectHandle::getObjGen() const
return QPDFObjGen(this->objid, this->generation); 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 int
QPDFObjectHandle::getObjectID() const QPDFObjectHandle::getObjectID() const
{ {
@ -1556,7 +1548,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
} else { } else {
all_description += ","; all_description += ",";
} }
all_description += " stream " + item.getObjGenAsStr(); all_description += " stream " + item.getObjGen().unparse(' ');
} }
return result; return result;
@ -1565,7 +1557,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
std::vector<QPDFObjectHandle> std::vector<QPDFObjectHandle>
QPDFObjectHandle::getPageContents() QPDFObjectHandle::getPageContents()
{ {
std::string description = "page object " + getObjGenAsStr(); std::string description = "page object " + getObjGen().unparse(' ');
std::string all_description; std::string all_description;
return this->getKey("/Contents") return this->getKey("/Contents")
.arrayOrStreamToStreamArray(description, all_description); .arrayOrStreamToStreamArray(description, all_description);
@ -1674,7 +1666,7 @@ QPDFObjectHandle::unparse()
{ {
std::string result; std::string result;
if (this->isIndirect()) { if (this->isIndirect()) {
result = getObjGenAsStr() + " R"; result = getObjGen().unparse(' ') + " R";
} else { } else {
result = unparseResolved(); result = unparseResolved();
} }
@ -1789,7 +1781,7 @@ QPDFObjectHandle::parse(
void void
QPDFObjectHandle::pipePageContents(Pipeline* p) QPDFObjectHandle::pipePageContents(Pipeline* p)
{ {
std::string description = "page object " + getObjGenAsStr(); std::string description = "page object " + getObjGen().unparse(' ');
std::string all_description; std::string all_description;
this->getKey("/Contents") this->getKey("/Contents")
.pipeContentStreams(p, description, all_description); .pipeContentStreams(p, description, all_description);
@ -1813,7 +1805,7 @@ QPDFObjectHandle::pipeContentStreams(
throw QPDFExc( throw QPDFExc(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
"content stream", "content stream",
"content stream object " + stream.getObjGenAsStr(), "content stream object " + stream.getObjGen().unparse(' '),
0, 0,
"errors while decoding content stream"); "errors while decoding content stream");
} }
@ -1829,7 +1821,7 @@ QPDFObjectHandle::pipeContentStreams(
void void
QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks) QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
{ {
std::string description = "page object " + getObjGenAsStr(); std::string description = "page object " + getObjGen().unparse(' ');
this->getKey("/Contents") this->getKey("/Contents")
.parseContentStream_internal(description, callbacks); .parseContentStream_internal(description, callbacks);
} }
@ -1837,14 +1829,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
void void
QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks) QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks)
{ {
std::string description = "object " + getObjGenAsStr(); std::string description = "object " + getObjGen().unparse(' ');
this->parseContentStream_internal(description, callbacks); this->parseContentStream_internal(description, callbacks);
} }
void void
QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next) 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); Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
this->pipePageContents(&token_pipeline); this->pipePageContents(&token_pipeline);
} }
@ -1852,7 +1845,7 @@ QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
void void
QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next) 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); Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized); this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized);
} }

View File

@ -33,9 +33,8 @@ void
ContentProvider::provideStreamData(int, int, Pipeline* p) ContentProvider::provideStreamData(int, int, Pipeline* p)
{ {
Pl_Concatenate concat("concatenate", p); Pl_Concatenate concat("concatenate", p);
std::string description = "contents from page object " + std::string description =
QUtil::int_to_string(from_page.getObjectID()) + " " + "contents from page object " + from_page.getObjGen().unparse(' ');
QUtil::int_to_string(from_page.getGeneration());
std::string all_description; std::string all_description;
from_page.getKey("/Contents") from_page.getKey("/Contents")
.pipeContentStreams(&concat, description, all_description); .pipeContentStreams(&concat, description, all_description);

View File

@ -1990,9 +1990,8 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index)
if (object_stream_index == -1) { if (object_stream_index == -1) {
if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) { if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) {
writeString( writeString(
"%% Original object ID: " + "%% Original object ID: " + object.getObjGen().unparse(' ') +
QUtil::int_to_string(object.getObjectID()) + " " + "\n");
QUtil::int_to_string(object.getGeneration()) + "\n");
} }
openObject(new_id); openObject(new_id);
setDataKey(new_id); setDataKey(new_id);

View File

@ -130,8 +130,7 @@ QPDF_Stream::QPDF_Stream(
setDescription( setDescription(
this->qpdf, this->qpdf,
this->qpdf->getFilename() + ", stream object " + this->qpdf->getFilename() + ", stream object " +
QUtil::int_to_string(this->objid) + " " + QPDFObjGen(objid, generation).unparse(' '));
QUtil::int_to_string(this->generation));
} }
std::shared_ptr<QPDFObject> std::shared_ptr<QPDFObject>
@ -196,8 +195,7 @@ std::string
QPDF_Stream::unparse() QPDF_Stream::unparse()
{ {
// Unparse stream objects as indirect references // Unparse stream objects as indirect references
return QUtil::int_to_string(this->objid) + " " + return QPDFObjGen(objid, generation).unparse(' ') + " R";
QUtil::int_to_string(this->generation) + " R";
} }
JSON JSON
@ -643,8 +641,7 @@ QPDF_Stream::pipeStreamData(
// part of a library user, not by invalid input data. // part of a library user, not by invalid input data.
throw std::runtime_error( throw std::runtime_error(
"stream data provider for " + "stream data provider for " +
QUtil::int_to_string(this->objid) + " " + QPDFObjGen(objid, generation).unparse(' ') + " provided " +
QUtil::int_to_string(this->generation) + " provided " +
QUtil::int_to_string(actual_length) + QUtil::int_to_string(actual_length) +
" bytes instead of expected " + " bytes instead of expected " +
QUtil::int_to_string(desired_length) + " bytes"); QUtil::int_to_string(desired_length) + " bytes");

View File

@ -1176,8 +1176,7 @@ QPDF::decryptString(std::string& str, int objid, int generation)
this->m->last_object_description, this->m->last_object_description,
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"error decrypting string for object " + "error decrypting string for object " +
QUtil::int_to_string(objid) + " " + QPDFObjGen(objid, generation).unparse() + ": " + e.what());
QUtil::int_to_string(generation) + ": " + e.what());
} }
} }