diff --git a/ChangeLog b/ChangeLog index b0dda0de..28bf6840 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-06-14 Jay Berkenbilt + + * Add new QPDFObjGen object to represent an object ID/generation + pair. + 2013-04-14 Jay Berkenbilt * 4.1.0: release diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index a1644f84..6f78c687 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -519,17 +520,6 @@ class QPDF private: static std::string qpdf_version; - class ObjGen - { - public: - ObjGen(); - ObjGen(int obj, int gen); - bool operator<(ObjGen const&) const; - - int obj; - int gen; - }; - class ObjCache { public: @@ -555,9 +545,9 @@ class QPDF class ObjCopier { public: - std::map object_map; + std::map object_map; std::vector to_copy; - std::set visiting; + std::set visiting; }; class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider @@ -568,11 +558,11 @@ class QPDF } virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); - void registerForeignStream(ObjGen const& local_og, + void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream); private: - std::map foreign_streams; + std::map foreign_streams; }; class StringDecrypter: public QPDFObjectHandle::StringDecrypter @@ -932,7 +922,7 @@ class QPDF void readHSharedObject(BitStream); void readHGeneric(BitStream, HGeneric&); qpdf_offset_t maxEnd(ObjUser const& ou); - qpdf_offset_t getLinearizationOffset(ObjGen const&); + qpdf_offset_t getLinearizationOffset(QPDFObjGen const&); QPDFObjectHandle getUncompressedObject( QPDFObjectHandle&, std::map const& object_stream_data); int lengthNextN(int first_object, int n, @@ -950,12 +940,12 @@ class QPDF void dumpHSharedObject(); void dumpHGeneric(HGeneric&); int adjusted_offset(int offset); - QPDFObjectHandle objGenToIndirect(ObjGen const&); + QPDFObjectHandle objGenToIndirect(QPDFObjGen const&); void calculateLinearizationData( std::map const& object_stream_data); void pushOutlinesToPart( std::vector& part, - std::set& lc_outlines, + std::set& lc_outlines, std::map const& object_stream_data); int outputLengthNextN( int in_object, int n, @@ -989,7 +979,7 @@ class QPDF bool allow_changes, bool warn_skipped_keys); void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, - std::set& visited, bool top); + std::set& visited, bool top); void filterCompressedObjects(std::map const& object_stream_data); @@ -1017,19 +1007,19 @@ class QPDF int cached_key_objid; int cached_key_generation; std::string pdf_version; - std::map xref_table; + std::map xref_table; std::set deleted_objects; - std::map obj_cache; + std::map obj_cache; QPDFObjectHandle trailer; std::vector all_pages; - std::map pageobj_to_pages_pos; + std::map pageobj_to_pages_pos; bool pushed_inherited_attributes_to_pages; std::vector warnings; std::map object_copiers; PointerHolder copied_streams; // copied_stream_data_provider is owned by copied_streams CopiedStreamDataProvider* copied_stream_data_provider; - std::set attachment_streams; + std::set attachment_streams; // Linearization data qpdf_offset_t first_xref_item_offset; // actual value from file @@ -1061,8 +1051,8 @@ class QPDF std::vector part9; // Optimization data - std::map > obj_user_to_objects; - std::map > object_to_obj_users; + std::map > obj_user_to_objects; + std::map > object_to_obj_users; }; #endif // __QPDF_HH__ diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh new file mode 100644 index 00000000..5f789197 --- /dev/null +++ b/include/qpdf/QPDFObjGen.hh @@ -0,0 +1,35 @@ +// Copyright (c) 2005-2013 Jay Berkenbilt +// +// This file is part of qpdf. This software may be distributed under +// the terms of version 2 of the Artistic License which may be found +// in the source distribution. It is provided "as is" without express +// or implied warranty. + +#ifndef __QPDFOBJGEN_HH__ +#define __QPDFOBJGEN_HH__ + +#include + +// This class represents an object ID and generation pair. It is +// suitable to use as a key in a map or set. + +class QPDFObjGen +{ + public: + QPDF_DLL + QPDFObjGen(); + QPDF_DLL + QPDFObjGen(int obj, int gen); + QPDF_DLL + bool operator<(QPDFObjGen const&) const; + QPDF_DLL + int getObj() const; + QPDF_DLL + int getGen() const; + + private: + int obj; + int gen; +}; + +#endif // __QPDFOBJGEN_HH__ diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 3458d6cc..053aeaa8 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -39,32 +39,18 @@ static char const* EMPTY_PDF = "110\n" "%%EOF\n"; - -QPDF::ObjGen::ObjGen(int o = 0, int g = 0) : - obj(o), - gen(g) -{ -} - -bool -QPDF::ObjGen::operator<(ObjGen const& rhs) const -{ - return ((this->obj < rhs.obj) || - ((this->obj == rhs.obj) && (this->gen < rhs.gen))); -} - void QPDF::CopiedStreamDataProvider::provideStreamData( int objid, int generation, Pipeline* pipeline) { QPDFObjectHandle foreign_stream = - this->foreign_streams[ObjGen(objid, generation)]; + this->foreign_streams[QPDFObjGen(objid, generation)]; foreign_stream.pipeStreamData(pipeline, false, false, false); } void QPDF::CopiedStreamDataProvider::registerForeignStream( - ObjGen const& local_og, QPDFObjectHandle foreign_stream) + QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream) { this->foreign_streams[local_og] = foreign_stream; } @@ -128,7 +114,8 @@ QPDF::~QPDF() // have the effect of undoing any modifications that may have been // made to any of the objects. this->xref_table.clear(); - for (std::map::iterator iter = this->obj_cache.begin(); + for (std::map::iterator iter = + this->obj_cache.begin(); iter != obj_cache.end(); ++iter) { QPDFObject::ObjAccessor::releaseResolved( @@ -354,8 +341,8 @@ QPDF::reconstruct_xref(QPDFExc& e) "Attempting to reconstruct cross-reference table")); // Delete all references to type 1 (uncompressed) objects - std::set to_delete; - for (std::map::iterator iter = + std::set to_delete; + for (std::map::iterator iter = this->xref_table.begin(); iter != this->xref_table.end(); ++iter) { @@ -364,7 +351,7 @@ QPDF::reconstruct_xref(QPDFExc& e) to_delete.insert((*iter).first); } } - for (std::set::iterator iter = to_delete.begin(); + for (std::set::iterator iter = to_delete.begin(); iter != to_delete.end(); ++iter) { this->xref_table.erase(*iter); @@ -464,7 +451,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) int max_obj = 0; if (! xref_table.empty()) { - max_obj = (*(xref_table.rbegin())).first.obj; + max_obj = (*(xref_table.rbegin())).first.getObj(); } if (! this->deleted_objects.empty()) { @@ -491,7 +478,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) PCRE xref_first_re("^\\s*(\\d+)\\s+(\\d+)"); PCRE xref_entry_re("(?s:(^\\d{10}) (\\d{5}) ([fn])[ \r\n]{2}$)"); - std::vector deleted_items; + std::vector deleted_items; this->file->seek(xref_offset, SEEK_SET); bool done = false; @@ -538,7 +525,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) { // Save deleted items until after we've checked the // XRefStm, if any. - deleted_items.push_back(ObjGen(i, f2)); + deleted_items.push_back(QPDFObjGen(i, f2)); } else { @@ -615,11 +602,11 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) } // Handle any deleted items now that we've read the /XRefStm. - for (std::vector::iterator iter = deleted_items.begin(); + for (std::vector::iterator iter = deleted_items.begin(); iter != deleted_items.end(); ++iter) { - ObjGen& og = *iter; - insertXrefEntry(og.obj, 0, 0, og.gen); + QPDFObjGen& og = *iter; + insertXrefEntry(og.getObj(), 0, 0, og.getGen()); } if (cur_trailer.hasKey("/Prev")) @@ -874,7 +861,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) // object. Disregard this one. { // private scope int gen = (f0 == 2 ? 0 : f2); - ObjGen og(obj, gen); + QPDFObjGen og(obj, gen); if (this->xref_table.count(og)) { if (overwrite) @@ -904,11 +891,11 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) case 1: // f2 is generation QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0)); - this->xref_table[ObjGen(obj, f2)] = QPDFXRefEntry(f0, f1, f2); + this->xref_table[QPDFObjGen(obj, f2)] = QPDFXRefEntry(f0, f1, f2); break; case 2: - this->xref_table[ObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2); + this->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2); break; default: @@ -923,13 +910,13 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) void QPDF::showXRefTable() { - for (std::map::iterator iter = + for (std::map::iterator iter = this->xref_table.begin(); iter != this->xref_table.end(); ++iter) { - ObjGen const& og = (*iter).first; + QPDFObjGen const& og = (*iter).first; QPDFXRefEntry const& entry = (*iter).second; - *out_stream << og.obj << "/" << og.gen << ": "; + *out_stream << og.getObj() << "/" << og.getGen() << ": "; switch (entry.getType()) { case 1: @@ -1213,14 +1200,14 @@ QPDF::recoverStreamLength(PointerHolder input, if (length) { int this_obj_offset = 0; - ObjGen this_obj(0, 0); + QPDFObjGen this_obj(0, 0); // Make sure this is inside this object - for (std::map::iterator iter = + for (std::map::iterator iter = this->xref_table.begin(); iter != this->xref_table.end(); ++iter) { - ObjGen const& og = (*iter).first; + QPDFObjGen const& og = (*iter).first; QPDFXRefEntry const& entry = (*iter).second; if (entry.getType() == 1) { @@ -1235,8 +1222,8 @@ QPDF::recoverStreamLength(PointerHolder input, } } if (this_obj_offset && - (this_obj.obj == objid) && - (this_obj.gen == generation)) + (this_obj.getObj() == objid) && + (this_obj.getGen() == generation)) { // Well, we found endstream\nendobj within the space // allowed for this object, so we're probably in good @@ -1330,7 +1317,7 @@ QPDF::readObjectAtOffset(bool try_recovery, { // Try again after reconstructing xref table reconstruct_xref(e); - ObjGen og(exp_objid, exp_generation); + QPDFObjGen og(exp_objid, exp_generation); if (this->xref_table.count(og) && (this->xref_table[og].getType() == 1)) { @@ -1375,7 +1362,7 @@ QPDF::readObjectAtOffset(bool try_recovery, "expected endobj")); } - ObjGen og(objid, generation); + QPDFObjGen og(objid, generation); if (! this->obj_cache.count(og)) { // Store the object in the cache here so it gets cached @@ -1425,7 +1412,7 @@ QPDF::resolve(int objid, int generation) // 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. - ObjGen og(objid, generation); + QPDFObjGen og(objid, generation); if (! this->obj_cache.count(og)) { if (! this->xref_table.count(og)) @@ -1482,7 +1469,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) // For linearization data in the object, use the data from the // object stream for the objects in the stream. - ObjGen stream_og(obj_stream_number, 0); + QPDFObjGen stream_og(obj_stream_number, 0); qpdf_offset_t end_before_space = this->obj_cache[stream_og].end_before_space; qpdf_offset_t end_after_space = @@ -1548,7 +1535,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) iter != offsets.end(); ++iter) { int obj = (*iter).first; - ObjGen og(obj, 0); + QPDFObjGen og(obj, 0); QPDFXRefEntry const& entry = this->xref_table[og]; if ((entry.getType() == 2) && (entry.getObjStreamNumber() == obj_stream_number)) @@ -1570,19 +1557,20 @@ QPDF::resolveObjectsInStream(int obj_stream_number) QPDFObjectHandle QPDF::makeIndirectObject(QPDFObjectHandle oh) { - ObjGen o1(0, 0); + QPDFObjGen o1(0, 0); if (! this->obj_cache.empty()) { o1 = (*(this->obj_cache.rbegin())).first; } - ObjGen o2 = (*(this->xref_table.rbegin())).first; + QPDFObjGen o2 = (*(this->xref_table.rbegin())).first; QTC::TC("qpdf", "QPDF indirect last obj from xref", - (o2.obj > o1.obj) ? 1 : 0); - int max_objid = std::max(o1.obj, o2.obj); - ObjGen next(max_objid + 1, 0); + (o2.getObj() > o1.getObj()) ? 1 : 0); + int max_objid = std::max(o1.getObj(), o2.getObj()); + QPDFObjGen next(max_objid + 1, 0); this->obj_cache[next] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); - return QPDFObjectHandle::Factory::newIndirect(this, next.obj, next.gen); + return QPDFObjectHandle::Factory::newIndirect( + this, next.getObj(), next.getGen()); } QPDFObjectHandle @@ -1605,7 +1593,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) resolve(objid, generation); // Replace the object in the object cache - ObjGen og(objid, generation); + QPDFObjGen og(objid, generation); this->obj_cache[og] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); } @@ -1653,8 +1641,8 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign, bool allow_page) // Make sure we have an object in this file for every referenced // object in the old file. obj_copier.object_map maps foreign - // ObjGen to local objects. For everything new that we have to - // copy, the local object will be a reservation, unless it is a + // QPDFObjGen to local objects. For everything new that we have + // to copy, the local object will be a reservation, unless it is a // stream, in which case the local object will already be a // stream. reserveObjects(foreign, obj_copier, true); @@ -1675,14 +1663,14 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign, bool allow_page) replaceForeignIndirectObjects(to_copy, obj_copier, true); if (! to_copy.isStream()) { - ObjGen og(to_copy.getObjectID(), to_copy.getGeneration()); + QPDFObjGen og(to_copy.getObjectID(), to_copy.getGeneration()); replaceReserved(obj_copier.object_map[og], copy); } } obj_copier.to_copy.clear(); - return obj_copier.object_map[ObjGen(foreign.getObjectID(), - foreign.getGeneration())]; + return obj_copier.object_map[QPDFObjGen(foreign.getObjectID(), + foreign.getGeneration())]; } void @@ -1709,7 +1697,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, if (foreign.isIndirect()) { - ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); + QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); if (obj_copier.visiting.find(foreign_og) != obj_copier.visiting.end()) { QTC::TC("qpdf", "QPDF loop reserving objects"); @@ -1717,7 +1705,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, } QTC::TC("qpdf", "QPDF copy indirect"); obj_copier.visiting.insert(foreign_og); - std::map::iterator mapping = + std::map::iterator mapping = obj_copier.object_map.find(foreign_og); if (mapping == obj_copier.object_map.end()) { @@ -1762,7 +1750,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, if (foreign.isIndirect()) { - ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); + QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); obj_copier.visiting.erase(foreign_og); } } @@ -1775,8 +1763,8 @@ QPDF::replaceForeignIndirectObjects( if ((! top) && foreign.isIndirect()) { QTC::TC("qpdf", "QPDF replace indirect"); - ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); - std::map::iterator mapping = + QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); + std::map::iterator mapping = obj_copier.object_map.find(foreign_og); if (mapping == obj_copier.object_map.end()) { @@ -1819,7 +1807,7 @@ QPDF::replaceForeignIndirectObjects( else if (foreign.isStream()) { QTC::TC("qpdf", "QPDF replace stream"); - ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); + QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); result = obj_copier.object_map[foreign_og]; result.assertStream(); QPDFObjectHandle dict = result.getDict(); @@ -1838,7 +1826,7 @@ QPDF::replaceForeignIndirectObjects( this->copied_stream_data_provider = new CopiedStreamDataProvider(); this->copied_streams = this->copied_stream_data_provider; } - ObjGen local_og(result.getObjectID(), result.getGeneration()); + QPDFObjGen local_og(result.getObjectID(), result.getGeneration()); this->copied_stream_data_provider->registerForeignStream( local_og, foreign); result.replaceStreamData(this->copied_streams, @@ -1867,8 +1855,8 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) // cache. resolve(objid1, generation1); resolve(objid2, generation2); - ObjGen og1(objid1, generation1); - ObjGen og2(objid2, generation2); + QPDFObjGen og1(objid1, generation1); + QPDFObjGen og2(objid2, generation2); ObjCache t = this->obj_cache[og1]; this->obj_cache[og1] = this->obj_cache[og2]; this->obj_cache[og2] = t; @@ -1925,15 +1913,15 @@ QPDF::getRoot() void QPDF::getObjectStreamData(std::map& omap) { - for (std::map::iterator iter = + for (std::map::iterator iter = this->xref_table.begin(); iter != this->xref_table.end(); ++iter) { - ObjGen const& og = (*iter).first; + QPDFObjGen const& og = (*iter).first; QPDFXRefEntry const& entry = (*iter).second; if (entry.getType() == 2) { - omap[og.obj] = entry.getObjStreamNumber(); + omap[og.getObj()] = entry.getObjStreamNumber(); } } } @@ -2114,7 +2102,7 @@ QPDF::findAttachmentStreams() { QPDFObjectHandle stream = item.getKey("/EF").getKey("/F"); this->attachment_streams.insert( - ObjGen(stream.getObjectID(), stream.getGeneration())); + QPDFObjGen(stream.getObjectID(), stream.getGeneration())); } } } diff --git a/libqpdf/QPDFObjGen.cc b/libqpdf/QPDFObjGen.cc new file mode 100644 index 00000000..e43a0aea --- /dev/null +++ b/libqpdf/QPDFObjGen.cc @@ -0,0 +1,26 @@ +#include + +QPDFObjGen::QPDFObjGen(int o = 0, int g = 0) : + obj(o), + gen(g) +{ +} + +bool +QPDFObjGen::operator<(QPDFObjGen const& rhs) const +{ + return ((this->obj < rhs.obj) || + ((this->obj == rhs.obj) && (this->gen < rhs.gen))); +} + +int +QPDFObjGen::getObj() const +{ + return this->obj; +} + +int +QPDFObjGen::getGen() const +{ + return this->gen; +} diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 022ee9a4..51ed3072 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -1202,7 +1202,7 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, else { if (this->attachment_streams.count( - ObjGen(objid, generation)) > 0) + QPDFObjGen(objid, generation)) > 0) { method = this->cf_file; } diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index d047ad11..fc57c115 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -312,7 +312,7 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) int gen; QPDFObjectHandle H = readObjectAtOffset( false, offset, "linearization hint stream", -1, 0, obj, gen); - ObjCache& oc = this->obj_cache[ObjGen(obj, gen)]; + ObjCache& oc = this->obj_cache[QPDFObjGen(obj, gen)]; qpdf_offset_t min_end_offset = oc.end_before_space; qpdf_offset_t max_end_offset = oc.end_after_space; if (! H.isStream()) @@ -337,8 +337,8 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) // Force resolution (void) length_obj.getIntValue(); ObjCache& oc = this->obj_cache - [ObjGen(length_obj.getObjectID(), - length_obj.getGeneration())]; + [QPDFObjGen(length_obj.getObjectID(), + length_obj.getGeneration())]; min_end_offset = oc.end_before_space; max_end_offset = oc.end_after_space; } @@ -499,7 +499,7 @@ QPDF::checkLinearizationInternal() for (int i = 0; i < npages; ++i) { QPDFObjectHandle const& page = pages[i]; - ObjGen og(page.getObjectID(), page.getGeneration()); + QPDFObjGen og(page.getObjectID(), page.getGeneration()); if (this->xref_table[og].getType() == 2) { errors.push_back("page dictionary for page " + @@ -550,15 +550,15 @@ QPDF::checkLinearizationInternal() // uncompressed. { // local scope std::map object_stream_data; - for (std::map::const_iterator iter = + for (std::map::const_iterator iter = this->xref_table.begin(); iter != this->xref_table.end(); ++iter) { - ObjGen const& og = (*iter).first; + QPDFObjGen const& og = (*iter).first; QPDFXRefEntry const& entry = (*iter).second; if (entry.getType() == 2) { - object_stream_data[og.obj] = entry.getObjStreamNumber(); + object_stream_data[og.getObj()] = entry.getObjStreamNumber(); } } optimize(object_stream_data, false); @@ -582,7 +582,7 @@ QPDF::checkLinearizationInternal() for (std::vector::iterator iter = this->part6.begin(); iter != this->part6.end(); ++iter) { - ObjGen og((*iter).getObjectID(), (*iter).getGeneration()); + QPDFObjGen og((*iter).getObjectID(), (*iter).getGeneration()); // All objects have to have been dereferenced to be classified. assert(this->obj_cache.count(og) > 0); ObjCache const& oc = this->obj_cache[og]; @@ -637,12 +637,12 @@ qpdf_offset_t QPDF::maxEnd(ObjUser const& ou) { assert(this->obj_user_to_objects.count(ou) > 0); - std::set const& ogs = this->obj_user_to_objects[ou]; + std::set const& ogs = this->obj_user_to_objects[ou]; qpdf_offset_t end = 0; - for (std::set::const_iterator iter = ogs.begin(); + for (std::set::const_iterator iter = ogs.begin(); iter != ogs.end(); ++iter) { - ObjGen const& og = *iter; + QPDFObjGen const& og = *iter; assert(this->obj_cache.count(og) > 0); end = std::max(end, this->obj_cache[og].end_after_space); } @@ -650,7 +650,7 @@ QPDF::maxEnd(ObjUser const& ou) } qpdf_offset_t -QPDF::getLinearizationOffset(ObjGen const& og) +QPDF::getLinearizationOffset(QPDFObjGen const& og) { QPDFXRefEntry entry = this->xref_table[og]; qpdf_offset_t result = 0; @@ -663,7 +663,8 @@ QPDF::getLinearizationOffset(ObjGen const& og) case 2: // For compressed objects, return the offset of the object // stream that contains them. - result = getLinearizationOffset(ObjGen(entry.getObjStreamNumber(), 0)); + result = getLinearizationOffset( + QPDFObjGen(entry.getObjStreamNumber(), 0)); break; default: @@ -685,7 +686,7 @@ QPDF::getUncompressedObject(QPDFObjectHandle& obj, else { int repl = (*(object_stream_data.find(obj.getObjectID()))).second; - return objGenToIndirect(ObjGen(repl, 0)); + return objGenToIndirect(QPDFObjGen(repl, 0)); } } @@ -696,7 +697,7 @@ QPDF::lengthNextN(int first_object, int n, int length = 0; for (int i = 0; i < n; ++i) { - ObjGen og(first_object + i, 0); + QPDFObjGen og(first_object + i, 0); if (this->xref_table.count(og) == 0) { errors.push_back( @@ -739,7 +740,7 @@ QPDF::checkHPageOffset(std::list& errors, unsigned int npages = pages.size(); int table_offset = adjusted_offset( this->page_offset_hints.first_page_offset); - ObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration()); + QPDFObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration()); assert(this->xref_table.count(first_page_og) > 0); int offset = getLinearizationOffset(first_page_og); if (table_offset != offset) @@ -749,9 +750,9 @@ QPDF::checkHPageOffset(std::list& errors, for (unsigned int pageno = 0; pageno < npages; ++pageno) { - ObjGen page_og(pages[pageno].getObjectID(), - pages[pageno].getGeneration()); - int first_object = page_og.obj; + QPDFObjGen page_og(pages[pageno].getObjectID(), + pages[pageno].getGeneration()); + int first_object = page_og.getObj(); assert(this->xref_table.count(page_og) > 0); offset = getLinearizationOffset(page_og); @@ -906,7 +907,7 @@ QPDF::checkHSharedObject(std::list& errors, cur_object = so.first_shared_obj; - ObjGen og(cur_object, 0); + QPDFObjGen og(cur_object, 0); assert(this->xref_table.count(og) > 0); int offset = getLinearizationOffset(og); int h_offset = adjusted_offset(so.first_shared_offset); @@ -960,7 +961,7 @@ QPDF::checkHOutlines(std::list& warnings) { // Check length and offset. Acrobat gets these wrong. QPDFObjectHandle outlines = getRoot().getKey("/Outlines"); - ObjGen og(outlines.getObjectID(), outlines.getGeneration()); + QPDFObjGen og(outlines.getObjectID(), outlines.getGeneration()); assert(this->xref_table.count(og) > 0); int offset = getLinearizationOffset(og); ObjUser ou(ObjUser::ou_root_key, "/Outlines"); @@ -1170,9 +1171,9 @@ QPDF::dumpHGeneric(HGeneric& t) } QPDFObjectHandle -QPDF::objGenToIndirect(ObjGen const& og) +QPDF::objGenToIndirect(QPDFObjGen const& og) { - return getObjectByID(og.obj, og.gen); + return getObjectByID(og.getObj(), og.getGen()); } void @@ -1280,22 +1281,22 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) open_document_keys.insert("/OpenAction"); open_document_keys.insert("/AcroForm"); - std::set lc_open_document; - std::set lc_first_page_private; - std::set lc_first_page_shared; - std::set lc_other_page_private; - std::set lc_other_page_shared; - std::set lc_thumbnail_private; - std::set lc_thumbnail_shared; - std::set lc_other; - std::set lc_outlines; - std::set lc_root; + std::set lc_open_document; + std::set lc_first_page_private; + std::set lc_first_page_shared; + std::set lc_other_page_private; + std::set lc_other_page_shared; + std::set lc_thumbnail_private; + std::set lc_thumbnail_shared; + std::set lc_other; + std::set lc_outlines; + std::set lc_root; - for (std::map >::iterator oiter = + for (std::map >::iterator oiter = this->object_to_obj_users.begin(); oiter != this->object_to_obj_users.end(); ++oiter) { - ObjGen const& og = (*oiter).first; + QPDFObjGen const& og = (*oiter).first; std::set& ous = (*oiter).second; @@ -1414,10 +1415,10 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // optimizing this by going straight into the vector, we'll leave // these phases separate for now. That way, this section can be // concerned only with ordering, and the above section can be - // considered only with categorization. Note that sets of ObjGens - // are sorted by ObjGen. In a linearized file, objects appear in - // sequence with the possible exception of hints tables which we - // won't see here anyway. That means that running + // considered only with categorization. Note that sets of + // QPDFObjGens are sorted by QPDFObjGen. In a linearized file, + // objects appear in sequence with the possible exception of hints + // tables which we won't see here anyway. That means that running // calculateLinearizationData() on a linearized file should give // results identical to the original file ordering. @@ -1452,7 +1453,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) assert(lc_root.size() == 1); this->part4.push_back(objGenToIndirect(*(lc_root.begin()))); - for (std::set::iterator iter = lc_open_document.begin(); + for (std::set::iterator iter = lc_open_document.begin(); iter != lc_open_document.end(); ++iter) { this->part4.push_back(objGenToIndirect(*iter)); @@ -1465,7 +1466,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // will do the same. // First, place the actual first page object itself. - ObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration()); + QPDFObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration()); if (! lc_first_page_private.count(first_page_og)) { throw std::logic_error( @@ -1481,13 +1482,13 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // groups private and shared objects contiguously for the sake of // hint tables. - for (std::set::iterator iter = lc_first_page_private.begin(); + for (std::set::iterator iter = lc_first_page_private.begin(); iter != lc_first_page_private.end(); ++iter) { this->part6.push_back(objGenToIndirect(*iter)); } - for (std::set::iterator iter = lc_first_page_shared.begin(); + for (std::set::iterator iter = lc_first_page_shared.begin(); iter != lc_first_page_shared.end(); ++iter) { this->part6.push_back(objGenToIndirect(*iter)); @@ -1514,7 +1515,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) { // Place this page's page object - ObjGen page_og(pages[i].getObjectID(), pages[i].getGeneration()); + QPDFObjGen page_og(pages[i].getObjectID(), pages[i].getGeneration()); if (! lc_other_page_private.count(page_og)) { throw std::logic_error( @@ -1532,11 +1533,11 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) ObjUser ou(ObjUser::ou_page, i); assert(this->obj_user_to_objects.count(ou) > 0); - std::set ogs = this->obj_user_to_objects[ou]; - for (std::set::iterator iter = ogs.begin(); + std::set ogs = this->obj_user_to_objects[ou]; + for (std::set::iterator iter = ogs.begin(); iter != ogs.end(); ++iter) { - ObjGen const& og = (*iter); + QPDFObjGen const& og = (*iter); if (lc_other_page_private.count(og)) { lc_other_page_private.erase(og); @@ -1557,7 +1558,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // Part 8: other pages' shared objects // Order is unimportant. - for (std::set::iterator iter = lc_other_page_shared.begin(); + for (std::set::iterator iter = lc_other_page_shared.begin(); iter != lc_other_page_shared.end(); ++iter) { this->part8.push_back(objGenToIndirect(*iter)); @@ -1573,13 +1574,13 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // arbitrary order. // Place the pages tree. - std::set pages_ogs = + std::set pages_ogs = this->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")]; assert(! pages_ogs.empty()); - for (std::set::iterator iter = pages_ogs.begin(); + for (std::set::iterator iter = pages_ogs.begin(); iter != pages_ogs.end(); ++iter) { - ObjGen const& og = *iter; + QPDFObjGen const& og = *iter; if (lc_other.count(og)) { lc_other.erase(og); @@ -1597,7 +1598,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) if (! thumb.isNull()) { // Output the thumbnail itself - ObjGen thumb_og(thumb.getObjectID(), thumb.getGeneration()); + QPDFObjGen thumb_og(thumb.getObjectID(), thumb.getGeneration()); if (lc_thumbnail_private.count(thumb_og)) { lc_thumbnail_private.erase(thumb_og); @@ -1612,12 +1613,12 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) // having been in some set other than // lc_thumbnail_private. } - std::set& ogs = + std::set& ogs = this->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)]; - for (std::set::iterator iter = ogs.begin(); + for (std::set::iterator iter = ogs.begin(); iter != ogs.end(); ++iter) { - ObjGen const& og = *iter; + QPDFObjGen const& og = *iter; if (lc_thumbnail_private.count(og)) { lc_thumbnail_private.erase(og); @@ -1635,7 +1636,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) } // Place shared thumbnail objects - for (std::set::iterator iter = lc_thumbnail_shared.begin(); + for (std::set::iterator iter = lc_thumbnail_shared.begin(); iter != lc_thumbnail_shared.end(); ++iter) { this->part9.push_back(objGenToIndirect(*iter)); @@ -1648,7 +1649,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) } // Place all remaining objects - for (std::set::iterator iter = lc_other.begin(); + for (std::set::iterator iter = lc_other.begin(); iter != lc_other.end(); ++iter) { this->part9.push_back(objGenToIndirect(*iter)); @@ -1723,15 +1724,15 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) CHPageOffsetEntry& pe = this->c_page_offset_data.entries[i]; ObjUser ou(ObjUser::ou_page, i); assert(this->obj_user_to_objects.count(ou) > 0); - std::set const& ogs = this->obj_user_to_objects[ou]; - for (std::set::const_iterator iter = ogs.begin(); + std::set const& ogs = this->obj_user_to_objects[ou]; + for (std::set::const_iterator iter = ogs.begin(); iter != ogs.end(); ++iter) { - ObjGen const& og = *iter; + QPDFObjGen const& og = *iter; if ((this->object_to_obj_users[og].size() > 1) && - (obj_to_index.count(og.obj) > 0)) + (obj_to_index.count(og.getObj()) > 0)) { - int idx = obj_to_index[og.obj]; + int idx = obj_to_index[og.getObj()]; ++pe.nshared_objects; pe.shared_identifiers.push_back(idx); } @@ -1742,7 +1743,7 @@ QPDF::calculateLinearizationData(std::map const& object_stream_data) void QPDF::pushOutlinesToPart( std::vector& part, - std::set& lc_outlines, + std::set& lc_outlines, std::map const& object_stream_data) { QPDFObjectHandle root = getRoot(); @@ -1752,16 +1753,16 @@ QPDF::pushOutlinesToPart( return; } outlines = getUncompressedObject(outlines, object_stream_data); - ObjGen outlines_og(outlines.getObjectID(), outlines.getGeneration()); + QPDFObjGen outlines_og(outlines.getObjectID(), outlines.getGeneration()); QTC::TC("qpdf", "QPDF lin outlines in part", ((&part == (&this->part6)) ? 0 : (&part == (&this->part9)) ? 1 : 9999)); // can't happen - this->c_outline_data.first_object = outlines_og.obj; + this->c_outline_data.first_object = outlines_og.getObj(); this->c_outline_data.nobjects = 1; lc_outlines.erase(outlines_og); part.push_back(outlines); - for (std::set::iterator iter = lc_outlines.begin(); + for (std::set::iterator iter = lc_outlines.begin(); iter != lc_outlines.end(); ++iter) { part.push_back(objGenToIndirect(*iter)); diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc index befa871e..271c6610 100644 --- a/libqpdf/QPDF_optimization.cc +++ b/libqpdf/QPDF_optimization.cc @@ -115,7 +115,7 @@ QPDF::optimize(std::map const& object_stream_data, } ObjUser root_ou = ObjUser(ObjUser::ou_root); - ObjGen root_og = ObjGen(root.getObjectID(), root.getGeneration()); + QPDFObjGen root_og = QPDFObjGen(root.getObjectID(), root.getGeneration()); obj_user_to_objects[root_ou].insert(root_og); object_to_obj_users[root_og].insert(root_ou); @@ -310,13 +310,13 @@ QPDF::pushInheritedAttributesToPageInternal( void QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh) { - std::set visited; + std::set visited; updateObjectMapsInternal(ou, oh, visited, true); } void QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, - std::set& visited, bool top) + std::set& visited, bool top) { // Traverse the object tree from this point taking care to avoid // crossing page boundaries. @@ -338,7 +338,7 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, if (oh.isIndirect()) { - ObjGen og(oh.getObjectID(), oh.getGeneration()); + QPDFObjGen og(oh.getObjectID(), oh.getGeneration()); if (visited.count(og)) { QTC::TC("qpdf", "QPDF opt loop detected"); @@ -403,51 +403,51 @@ QPDF::filterCompressedObjects(std::map const& object_stream_data) // user of a compressed object, then it is really a user of the // object stream that contains it. - std::map > t_obj_user_to_objects; - std::map > t_object_to_obj_users; + std::map > t_obj_user_to_objects; + std::map > t_object_to_obj_users; - for (std::map >::iterator i1 = + for (std::map >::iterator i1 = this->obj_user_to_objects.begin(); i1 != this->obj_user_to_objects.end(); ++i1) { ObjUser const& ou = (*i1).first; - std::set const& objects = (*i1).second; - for (std::set::const_iterator i2 = objects.begin(); + std::set const& objects = (*i1).second; + for (std::set::const_iterator i2 = objects.begin(); i2 != objects.end(); ++i2) { - ObjGen const& og = (*i2); + QPDFObjGen const& og = (*i2); std::map::const_iterator i3 = - object_stream_data.find(og.obj); + object_stream_data.find(og.getObj()); if (i3 == object_stream_data.end()) { t_obj_user_to_objects[ou].insert(og); } else { - t_obj_user_to_objects[ou].insert(ObjGen((*i3).second, 0)); + t_obj_user_to_objects[ou].insert(QPDFObjGen((*i3).second, 0)); } } } - for (std::map >::iterator i1 = + for (std::map >::iterator i1 = this->object_to_obj_users.begin(); i1 != this->object_to_obj_users.end(); ++i1) { - ObjGen const& og = (*i1).first; + QPDFObjGen const& og = (*i1).first; std::set const& objusers = (*i1).second; for (std::set::const_iterator i2 = objusers.begin(); i2 != objusers.end(); ++i2) { ObjUser const& ou = (*i2); std::map::const_iterator i3 = - object_stream_data.find(og.obj); + object_stream_data.find(og.getObj()); if (i3 == object_stream_data.end()) { t_object_to_obj_users[og].insert(ou); } else { - t_object_to_obj_users[ObjGen((*i3).second, 0)].insert(ou); + t_object_to_obj_users[QPDFObjGen((*i3).second, 0)].insert(ou); } } } diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc index 11f57dd9..4f1525e7 100644 --- a/libqpdf/QPDF_pages.cc +++ b/libqpdf/QPDF_pages.cc @@ -127,7 +127,7 @@ void QPDF::insertPageobjToPage(QPDFObjectHandle const& obj, int pos, bool check_duplicate) { - ObjGen og(obj.getObjectID(), obj.getGeneration()); + QPDFObjGen og(obj.getObjectID(), obj.getGeneration()); if (check_duplicate) { if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second) @@ -135,7 +135,7 @@ QPDF::insertPageobjToPage(QPDFObjectHandle const& obj, int pos, QTC::TC("qpdf", "QPDF duplicate page reference"); setLastObjectDescription("page " + QUtil::int_to_string(pos) + " (numbered from zero)", - og.obj, og.gen); + og.getObj(), og.getGen()); throw QPDFExc(qpdf_e_pages, this->file->getName(), this->last_object_description, 0, "duplicate page reference found;" @@ -215,7 +215,7 @@ QPDF::removePage(QPDFObjectHandle page) this->all_pages.erase(this->all_pages.begin() + pos); assert(this->all_pages.size() == static_cast(npages)); this->pageobj_to_pages_pos.erase( - ObjGen(page.getObjectID(), page.getGeneration())); + QPDFObjGen(page.getObjectID(), page.getGeneration())); assert(this->pageobj_to_pages_pos.size() == static_cast(npages)); for (int i = pos; i < npages; ++i) { @@ -260,8 +260,8 @@ int QPDF::findPage(int objid, int generation) { flattenPagesTree(); - std::map::iterator it = - this->pageobj_to_pages_pos.find(ObjGen(objid, generation)); + std::map::iterator it = + this->pageobj_to_pages_pos.find(QPDFObjGen(objid, generation)); if (it == this->pageobj_to_pages_pos.end()) { setLastObjectDescription("page object", objid, generation); diff --git a/libqpdf/build.mk b/libqpdf/build.mk index 78153c4a..9c86e774 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -32,6 +32,7 @@ SRCS_libqpdf = \ libqpdf/Pl_StdioFile.cc \ libqpdf/QPDF.cc \ libqpdf/QPDFExc.cc \ + libqpdf/QPDFObjGen.cc \ libqpdf/QPDFObject.cc \ libqpdf/QPDFObjectHandle.cc \ libqpdf/QPDFTokenizer.cc \