2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-04 03:10:52 +00:00

Promote QPDF::ObjGen to top-level object QPDFObjGen

This commit is contained in:
Jay Berkenbilt 2013-06-14 11:22:04 -04:00
parent 690d6031db
commit d88231e01e
10 changed files with 226 additions and 180 deletions

View File

@ -1,3 +1,8 @@
2013-06-14 Jay Berkenbilt <ejb@ql.org>
* Add new QPDFObjGen object to represent an object ID/generation
pair.
2013-04-14 Jay Berkenbilt <ejb@ql.org> 2013-04-14 Jay Berkenbilt <ejb@ql.org>
* 4.1.0: release * 4.1.0: release

View File

@ -17,6 +17,7 @@
#include <list> #include <list>
#include <iostream> #include <iostream>
#include <qpdf/QPDFObjGen.hh>
#include <qpdf/QPDFXRefEntry.hh> #include <qpdf/QPDFXRefEntry.hh>
#include <qpdf/QPDFObjectHandle.hh> #include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDFTokenizer.hh> #include <qpdf/QPDFTokenizer.hh>
@ -519,17 +520,6 @@ class QPDF
private: private:
static std::string qpdf_version; 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 class ObjCache
{ {
public: public:
@ -555,9 +545,9 @@ class QPDF
class ObjCopier class ObjCopier
{ {
public: public:
std::map<ObjGen, QPDFObjectHandle> object_map; std::map<QPDFObjGen, QPDFObjectHandle> object_map;
std::vector<QPDFObjectHandle> to_copy; std::vector<QPDFObjectHandle> to_copy;
std::set<ObjGen> visiting; std::set<QPDFObjGen> visiting;
}; };
class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
@ -568,11 +558,11 @@ class QPDF
} }
virtual void provideStreamData(int objid, int generation, virtual void provideStreamData(int objid, int generation,
Pipeline* pipeline); Pipeline* pipeline);
void registerForeignStream(ObjGen const& local_og, void registerForeignStream(QPDFObjGen const& local_og,
QPDFObjectHandle foreign_stream); QPDFObjectHandle foreign_stream);
private: private:
std::map<ObjGen, QPDFObjectHandle> foreign_streams; std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
}; };
class StringDecrypter: public QPDFObjectHandle::StringDecrypter class StringDecrypter: public QPDFObjectHandle::StringDecrypter
@ -932,7 +922,7 @@ class QPDF
void readHSharedObject(BitStream); void readHSharedObject(BitStream);
void readHGeneric(BitStream, HGeneric&); void readHGeneric(BitStream, HGeneric&);
qpdf_offset_t maxEnd(ObjUser const& ou); qpdf_offset_t maxEnd(ObjUser const& ou);
qpdf_offset_t getLinearizationOffset(ObjGen const&); qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
QPDFObjectHandle getUncompressedObject( QPDFObjectHandle getUncompressedObject(
QPDFObjectHandle&, std::map<int, int> const& object_stream_data); QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
int lengthNextN(int first_object, int n, int lengthNextN(int first_object, int n,
@ -950,12 +940,12 @@ class QPDF
void dumpHSharedObject(); void dumpHSharedObject();
void dumpHGeneric(HGeneric&); void dumpHGeneric(HGeneric&);
int adjusted_offset(int offset); int adjusted_offset(int offset);
QPDFObjectHandle objGenToIndirect(ObjGen const&); QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
void calculateLinearizationData( void calculateLinearizationData(
std::map<int, int> const& object_stream_data); std::map<int, int> const& object_stream_data);
void pushOutlinesToPart( void pushOutlinesToPart(
std::vector<QPDFObjectHandle>& part, std::vector<QPDFObjectHandle>& part,
std::set<ObjGen>& lc_outlines, std::set<QPDFObjGen>& lc_outlines,
std::map<int, int> const& object_stream_data); std::map<int, int> const& object_stream_data);
int outputLengthNextN( int outputLengthNextN(
int in_object, int n, int in_object, int n,
@ -989,7 +979,7 @@ class QPDF
bool allow_changes, bool warn_skipped_keys); bool allow_changes, bool warn_skipped_keys);
void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh);
void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
std::set<ObjGen>& visited, bool top); std::set<QPDFObjGen>& visited, bool top);
void filterCompressedObjects(std::map<int, int> const& object_stream_data); void filterCompressedObjects(std::map<int, int> const& object_stream_data);
@ -1017,19 +1007,19 @@ class QPDF
int cached_key_objid; int cached_key_objid;
int cached_key_generation; int cached_key_generation;
std::string pdf_version; std::string pdf_version;
std::map<ObjGen, QPDFXRefEntry> xref_table; std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
std::set<int> deleted_objects; std::set<int> deleted_objects;
std::map<ObjGen, ObjCache> obj_cache; std::map<QPDFObjGen, ObjCache> obj_cache;
QPDFObjectHandle trailer; QPDFObjectHandle trailer;
std::vector<QPDFObjectHandle> all_pages; std::vector<QPDFObjectHandle> all_pages;
std::map<ObjGen, int> pageobj_to_pages_pos; std::map<QPDFObjGen, int> pageobj_to_pages_pos;
bool pushed_inherited_attributes_to_pages; bool pushed_inherited_attributes_to_pages;
std::vector<QPDFExc> warnings; std::vector<QPDFExc> warnings;
std::map<QPDF*, ObjCopier> object_copiers; std::map<QPDF*, ObjCopier> object_copiers;
PointerHolder<QPDFObjectHandle::StreamDataProvider> copied_streams; PointerHolder<QPDFObjectHandle::StreamDataProvider> copied_streams;
// copied_stream_data_provider is owned by copied_streams // copied_stream_data_provider is owned by copied_streams
CopiedStreamDataProvider* copied_stream_data_provider; CopiedStreamDataProvider* copied_stream_data_provider;
std::set<ObjGen> attachment_streams; std::set<QPDFObjGen> attachment_streams;
// Linearization data // Linearization data
qpdf_offset_t first_xref_item_offset; // actual value from file qpdf_offset_t first_xref_item_offset; // actual value from file
@ -1061,8 +1051,8 @@ class QPDF
std::vector<QPDFObjectHandle> part9; std::vector<QPDFObjectHandle> part9;
// Optimization data // Optimization data
std::map<ObjUser, std::set<ObjGen> > obj_user_to_objects; std::map<ObjUser, std::set<QPDFObjGen> > obj_user_to_objects;
std::map<ObjGen, std::set<ObjUser> > object_to_obj_users; std::map<QPDFObjGen, std::set<ObjUser> > object_to_obj_users;
}; };
#endif // __QPDF_HH__ #endif // __QPDF_HH__

View File

@ -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 <qpdf/DLL.h>
// 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__

View File

@ -39,32 +39,18 @@ static char const* EMPTY_PDF =
"110\n" "110\n"
"%%EOF\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 void
QPDF::CopiedStreamDataProvider::provideStreamData( QPDF::CopiedStreamDataProvider::provideStreamData(
int objid, int generation, Pipeline* pipeline) int objid, int generation, Pipeline* pipeline)
{ {
QPDFObjectHandle foreign_stream = QPDFObjectHandle foreign_stream =
this->foreign_streams[ObjGen(objid, generation)]; this->foreign_streams[QPDFObjGen(objid, generation)];
foreign_stream.pipeStreamData(pipeline, false, false, false); foreign_stream.pipeStreamData(pipeline, false, false, false);
} }
void void
QPDF::CopiedStreamDataProvider::registerForeignStream( QPDF::CopiedStreamDataProvider::registerForeignStream(
ObjGen const& local_og, QPDFObjectHandle foreign_stream) QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream)
{ {
this->foreign_streams[local_og] = 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 // have the effect of undoing any modifications that may have been
// made to any of the objects. // made to any of the objects.
this->xref_table.clear(); this->xref_table.clear();
for (std::map<ObjGen, ObjCache>::iterator iter = this->obj_cache.begin(); for (std::map<QPDFObjGen, ObjCache>::iterator iter =
this->obj_cache.begin();
iter != obj_cache.end(); ++iter) iter != obj_cache.end(); ++iter)
{ {
QPDFObject::ObjAccessor::releaseResolved( QPDFObject::ObjAccessor::releaseResolved(
@ -354,8 +341,8 @@ QPDF::reconstruct_xref(QPDFExc& e)
"Attempting to reconstruct cross-reference table")); "Attempting to reconstruct cross-reference table"));
// Delete all references to type 1 (uncompressed) objects // Delete all references to type 1 (uncompressed) objects
std::set<ObjGen> to_delete; std::set<QPDFObjGen> to_delete;
for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
this->xref_table.begin(); this->xref_table.begin();
iter != this->xref_table.end(); ++iter) iter != this->xref_table.end(); ++iter)
{ {
@ -364,7 +351,7 @@ QPDF::reconstruct_xref(QPDFExc& e)
to_delete.insert((*iter).first); to_delete.insert((*iter).first);
} }
} }
for (std::set<ObjGen>::iterator iter = to_delete.begin(); for (std::set<QPDFObjGen>::iterator iter = to_delete.begin();
iter != to_delete.end(); ++iter) iter != to_delete.end(); ++iter)
{ {
this->xref_table.erase(*iter); this->xref_table.erase(*iter);
@ -464,7 +451,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
int max_obj = 0; int max_obj = 0;
if (! xref_table.empty()) if (! xref_table.empty())
{ {
max_obj = (*(xref_table.rbegin())).first.obj; max_obj = (*(xref_table.rbegin())).first.getObj();
} }
if (! this->deleted_objects.empty()) 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_first_re("^\\s*(\\d+)\\s+(\\d+)");
PCRE xref_entry_re("(?s:(^\\d{10}) (\\d{5}) ([fn])[ \r\n]{2}$)"); PCRE xref_entry_re("(?s:(^\\d{10}) (\\d{5}) ([fn])[ \r\n]{2}$)");
std::vector<ObjGen> deleted_items; std::vector<QPDFObjGen> deleted_items;
this->file->seek(xref_offset, SEEK_SET); this->file->seek(xref_offset, SEEK_SET);
bool done = false; bool done = false;
@ -538,7 +525,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
{ {
// Save deleted items until after we've checked the // Save deleted items until after we've checked the
// XRefStm, if any. // XRefStm, if any.
deleted_items.push_back(ObjGen(i, f2)); deleted_items.push_back(QPDFObjGen(i, f2));
} }
else else
{ {
@ -615,11 +602,11 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
} }
// Handle any deleted items now that we've read the /XRefStm. // Handle any deleted items now that we've read the /XRefStm.
for (std::vector<ObjGen>::iterator iter = deleted_items.begin(); for (std::vector<QPDFObjGen>::iterator iter = deleted_items.begin();
iter != deleted_items.end(); ++iter) iter != deleted_items.end(); ++iter)
{ {
ObjGen& og = *iter; QPDFObjGen& og = *iter;
insertXrefEntry(og.obj, 0, 0, og.gen); insertXrefEntry(og.getObj(), 0, 0, og.getGen());
} }
if (cur_trailer.hasKey("/Prev")) 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. // object. Disregard this one.
{ // private scope { // private scope
int gen = (f0 == 2 ? 0 : f2); int gen = (f0 == 2 ? 0 : f2);
ObjGen og(obj, gen); QPDFObjGen og(obj, gen);
if (this->xref_table.count(og)) if (this->xref_table.count(og))
{ {
if (overwrite) if (overwrite)
@ -904,11 +891,11 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
case 1: case 1:
// f2 is generation // f2 is generation
QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0)); 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; break;
case 2: case 2:
this->xref_table[ObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2); this->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2);
break; break;
default: default:
@ -923,13 +910,13 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
void void
QPDF::showXRefTable() QPDF::showXRefTable()
{ {
for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
this->xref_table.begin(); this->xref_table.begin();
iter != this->xref_table.end(); ++iter) iter != this->xref_table.end(); ++iter)
{ {
ObjGen const& og = (*iter).first; QPDFObjGen const& og = (*iter).first;
QPDFXRefEntry const& entry = (*iter).second; QPDFXRefEntry const& entry = (*iter).second;
*out_stream << og.obj << "/" << og.gen << ": "; *out_stream << og.getObj() << "/" << og.getGen() << ": ";
switch (entry.getType()) switch (entry.getType())
{ {
case 1: case 1:
@ -1213,14 +1200,14 @@ QPDF::recoverStreamLength(PointerHolder<InputSource> input,
if (length) if (length)
{ {
int this_obj_offset = 0; int this_obj_offset = 0;
ObjGen this_obj(0, 0); QPDFObjGen this_obj(0, 0);
// Make sure this is inside this object // Make sure this is inside this object
for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
this->xref_table.begin(); this->xref_table.begin();
iter != this->xref_table.end(); ++iter) iter != this->xref_table.end(); ++iter)
{ {
ObjGen const& og = (*iter).first; QPDFObjGen const& og = (*iter).first;
QPDFXRefEntry const& entry = (*iter).second; QPDFXRefEntry const& entry = (*iter).second;
if (entry.getType() == 1) if (entry.getType() == 1)
{ {
@ -1235,8 +1222,8 @@ QPDF::recoverStreamLength(PointerHolder<InputSource> input,
} }
} }
if (this_obj_offset && if (this_obj_offset &&
(this_obj.obj == objid) && (this_obj.getObj() == objid) &&
(this_obj.gen == generation)) (this_obj.getGen() == generation))
{ {
// Well, we found endstream\nendobj within the space // Well, we found endstream\nendobj within the space
// allowed for this object, so we're probably in good // 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 // Try again after reconstructing xref table
reconstruct_xref(e); reconstruct_xref(e);
ObjGen og(exp_objid, exp_generation); QPDFObjGen og(exp_objid, exp_generation);
if (this->xref_table.count(og) && if (this->xref_table.count(og) &&
(this->xref_table[og].getType() == 1)) (this->xref_table[og].getType() == 1))
{ {
@ -1375,7 +1362,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
"expected endobj")); "expected endobj"));
} }
ObjGen og(objid, generation); QPDFObjGen og(objid, generation);
if (! this->obj_cache.count(og)) if (! this->obj_cache.count(og))
{ {
// Store the object in the cache here so it gets cached // 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 // Check object cache before checking xref table. This allows us
// to insert things into the object cache that don't actually // to insert things into the object cache that don't actually
// exist in the file. // exist in the file.
ObjGen og(objid, generation); QPDFObjGen og(objid, generation);
if (! this->obj_cache.count(og)) if (! this->obj_cache.count(og))
{ {
if (! this->xref_table.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 // For linearization data in the object, use the data from the
// object stream for the objects in the stream. // 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 = qpdf_offset_t end_before_space =
this->obj_cache[stream_og].end_before_space; this->obj_cache[stream_og].end_before_space;
qpdf_offset_t end_after_space = qpdf_offset_t end_after_space =
@ -1548,7 +1535,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
iter != offsets.end(); ++iter) iter != offsets.end(); ++iter)
{ {
int obj = (*iter).first; int obj = (*iter).first;
ObjGen og(obj, 0); QPDFObjGen og(obj, 0);
QPDFXRefEntry const& entry = this->xref_table[og]; QPDFXRefEntry const& entry = this->xref_table[og];
if ((entry.getType() == 2) && if ((entry.getType() == 2) &&
(entry.getObjStreamNumber() == obj_stream_number)) (entry.getObjStreamNumber() == obj_stream_number))
@ -1570,19 +1557,20 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
QPDFObjectHandle QPDFObjectHandle
QPDF::makeIndirectObject(QPDFObjectHandle oh) QPDF::makeIndirectObject(QPDFObjectHandle oh)
{ {
ObjGen o1(0, 0); QPDFObjGen o1(0, 0);
if (! this->obj_cache.empty()) if (! this->obj_cache.empty())
{ {
o1 = (*(this->obj_cache.rbegin())).first; 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", QTC::TC("qpdf", "QPDF indirect last obj from xref",
(o2.obj > o1.obj) ? 1 : 0); (o2.getObj() > o1.getObj()) ? 1 : 0);
int max_objid = std::max(o1.obj, o2.obj); int max_objid = std::max(o1.getObj(), o2.getObj());
ObjGen next(max_objid + 1, 0); QPDFObjGen next(max_objid + 1, 0);
this->obj_cache[next] = this->obj_cache[next] =
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); 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 QPDFObjectHandle
@ -1605,7 +1593,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
resolve(objid, generation); resolve(objid, generation);
// Replace the object in the object cache // Replace the object in the object cache
ObjGen og(objid, generation); QPDFObjGen og(objid, generation);
this->obj_cache[og] = this->obj_cache[og] =
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); 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 // Make sure we have an object in this file for every referenced
// object in the old file. obj_copier.object_map maps foreign // object in the old file. obj_copier.object_map maps foreign
// ObjGen to local objects. For everything new that we have to // QPDFObjGen to local objects. For everything new that we have
// copy, the local object will be a reservation, unless it is a // 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, in which case the local object will already be a
// stream. // stream.
reserveObjects(foreign, obj_copier, true); reserveObjects(foreign, obj_copier, true);
@ -1675,14 +1663,14 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign, bool allow_page)
replaceForeignIndirectObjects(to_copy, obj_copier, true); replaceForeignIndirectObjects(to_copy, obj_copier, true);
if (! to_copy.isStream()) 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); replaceReserved(obj_copier.object_map[og], copy);
} }
} }
obj_copier.to_copy.clear(); obj_copier.to_copy.clear();
return obj_copier.object_map[ObjGen(foreign.getObjectID(), return obj_copier.object_map[QPDFObjGen(foreign.getObjectID(),
foreign.getGeneration())]; foreign.getGeneration())];
} }
void void
@ -1709,7 +1697,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
if (foreign.isIndirect()) 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()) if (obj_copier.visiting.find(foreign_og) != obj_copier.visiting.end())
{ {
QTC::TC("qpdf", "QPDF loop reserving objects"); QTC::TC("qpdf", "QPDF loop reserving objects");
@ -1717,7 +1705,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
} }
QTC::TC("qpdf", "QPDF copy indirect"); QTC::TC("qpdf", "QPDF copy indirect");
obj_copier.visiting.insert(foreign_og); obj_copier.visiting.insert(foreign_og);
std::map<ObjGen, QPDFObjectHandle>::iterator mapping = std::map<QPDFObjGen, QPDFObjectHandle>::iterator mapping =
obj_copier.object_map.find(foreign_og); obj_copier.object_map.find(foreign_og);
if (mapping == obj_copier.object_map.end()) if (mapping == obj_copier.object_map.end())
{ {
@ -1762,7 +1750,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
if (foreign.isIndirect()) if (foreign.isIndirect())
{ {
ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration());
obj_copier.visiting.erase(foreign_og); obj_copier.visiting.erase(foreign_og);
} }
} }
@ -1775,8 +1763,8 @@ QPDF::replaceForeignIndirectObjects(
if ((! top) && foreign.isIndirect()) if ((! top) && foreign.isIndirect())
{ {
QTC::TC("qpdf", "QPDF replace indirect"); QTC::TC("qpdf", "QPDF replace indirect");
ObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration()); QPDFObjGen foreign_og(foreign.getObjectID(), foreign.getGeneration());
std::map<ObjGen, QPDFObjectHandle>::iterator mapping = std::map<QPDFObjGen, QPDFObjectHandle>::iterator mapping =
obj_copier.object_map.find(foreign_og); obj_copier.object_map.find(foreign_og);
if (mapping == obj_copier.object_map.end()) if (mapping == obj_copier.object_map.end())
{ {
@ -1819,7 +1807,7 @@ QPDF::replaceForeignIndirectObjects(
else if (foreign.isStream()) else if (foreign.isStream())
{ {
QTC::TC("qpdf", "QPDF replace stream"); 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 = obj_copier.object_map[foreign_og];
result.assertStream(); result.assertStream();
QPDFObjectHandle dict = result.getDict(); QPDFObjectHandle dict = result.getDict();
@ -1838,7 +1826,7 @@ QPDF::replaceForeignIndirectObjects(
this->copied_stream_data_provider = new CopiedStreamDataProvider(); this->copied_stream_data_provider = new CopiedStreamDataProvider();
this->copied_streams = this->copied_stream_data_provider; 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( this->copied_stream_data_provider->registerForeignStream(
local_og, foreign); local_og, foreign);
result.replaceStreamData(this->copied_streams, result.replaceStreamData(this->copied_streams,
@ -1867,8 +1855,8 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
// cache. // cache.
resolve(objid1, generation1); resolve(objid1, generation1);
resolve(objid2, generation2); resolve(objid2, generation2);
ObjGen og1(objid1, generation1); QPDFObjGen og1(objid1, generation1);
ObjGen og2(objid2, generation2); QPDFObjGen og2(objid2, generation2);
ObjCache t = this->obj_cache[og1]; ObjCache t = this->obj_cache[og1];
this->obj_cache[og1] = this->obj_cache[og2]; this->obj_cache[og1] = this->obj_cache[og2];
this->obj_cache[og2] = t; this->obj_cache[og2] = t;
@ -1925,15 +1913,15 @@ QPDF::getRoot()
void void
QPDF::getObjectStreamData(std::map<int, int>& omap) QPDF::getObjectStreamData(std::map<int, int>& omap)
{ {
for (std::map<ObjGen, QPDFXRefEntry>::iterator iter = for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
this->xref_table.begin(); this->xref_table.begin();
iter != this->xref_table.end(); ++iter) iter != this->xref_table.end(); ++iter)
{ {
ObjGen const& og = (*iter).first; QPDFObjGen const& og = (*iter).first;
QPDFXRefEntry const& entry = (*iter).second; QPDFXRefEntry const& entry = (*iter).second;
if (entry.getType() == 2) 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"); QPDFObjectHandle stream = item.getKey("/EF").getKey("/F");
this->attachment_streams.insert( this->attachment_streams.insert(
ObjGen(stream.getObjectID(), stream.getGeneration())); QPDFObjGen(stream.getObjectID(), stream.getGeneration()));
} }
} }
} }

26
libqpdf/QPDFObjGen.cc Normal file
View File

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

View File

@ -1202,7 +1202,7 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
else else
{ {
if (this->attachment_streams.count( if (this->attachment_streams.count(
ObjGen(objid, generation)) > 0) QPDFObjGen(objid, generation)) > 0)
{ {
method = this->cf_file; method = this->cf_file;
} }

View File

@ -312,7 +312,7 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
int gen; int gen;
QPDFObjectHandle H = readObjectAtOffset( QPDFObjectHandle H = readObjectAtOffset(
false, offset, "linearization hint stream", -1, 0, obj, gen); 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 min_end_offset = oc.end_before_space;
qpdf_offset_t max_end_offset = oc.end_after_space; qpdf_offset_t max_end_offset = oc.end_after_space;
if (! H.isStream()) if (! H.isStream())
@ -337,8 +337,8 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
// Force resolution // Force resolution
(void) length_obj.getIntValue(); (void) length_obj.getIntValue();
ObjCache& oc = this->obj_cache ObjCache& oc = this->obj_cache
[ObjGen(length_obj.getObjectID(), [QPDFObjGen(length_obj.getObjectID(),
length_obj.getGeneration())]; length_obj.getGeneration())];
min_end_offset = oc.end_before_space; min_end_offset = oc.end_before_space;
max_end_offset = oc.end_after_space; max_end_offset = oc.end_after_space;
} }
@ -499,7 +499,7 @@ QPDF::checkLinearizationInternal()
for (int i = 0; i < npages; ++i) for (int i = 0; i < npages; ++i)
{ {
QPDFObjectHandle const& page = pages[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) if (this->xref_table[og].getType() == 2)
{ {
errors.push_back("page dictionary for page " + errors.push_back("page dictionary for page " +
@ -550,15 +550,15 @@ QPDF::checkLinearizationInternal()
// uncompressed. // uncompressed.
{ // local scope { // local scope
std::map<int, int> object_stream_data; std::map<int, int> object_stream_data;
for (std::map<ObjGen, QPDFXRefEntry>::const_iterator iter = for (std::map<QPDFObjGen, QPDFXRefEntry>::const_iterator iter =
this->xref_table.begin(); this->xref_table.begin();
iter != this->xref_table.end(); ++iter) iter != this->xref_table.end(); ++iter)
{ {
ObjGen const& og = (*iter).first; QPDFObjGen const& og = (*iter).first;
QPDFXRefEntry const& entry = (*iter).second; QPDFXRefEntry const& entry = (*iter).second;
if (entry.getType() == 2) if (entry.getType() == 2)
{ {
object_stream_data[og.obj] = entry.getObjStreamNumber(); object_stream_data[og.getObj()] = entry.getObjStreamNumber();
} }
} }
optimize(object_stream_data, false); optimize(object_stream_data, false);
@ -582,7 +582,7 @@ QPDF::checkLinearizationInternal()
for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin(); for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin();
iter != this->part6.end(); ++iter) 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. // All objects have to have been dereferenced to be classified.
assert(this->obj_cache.count(og) > 0); assert(this->obj_cache.count(og) > 0);
ObjCache const& oc = this->obj_cache[og]; ObjCache const& oc = this->obj_cache[og];
@ -637,12 +637,12 @@ qpdf_offset_t
QPDF::maxEnd(ObjUser const& ou) QPDF::maxEnd(ObjUser const& ou)
{ {
assert(this->obj_user_to_objects.count(ou) > 0); assert(this->obj_user_to_objects.count(ou) > 0);
std::set<ObjGen> const& ogs = this->obj_user_to_objects[ou]; std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou];
qpdf_offset_t end = 0; qpdf_offset_t end = 0;
for (std::set<ObjGen>::const_iterator iter = ogs.begin(); for (std::set<QPDFObjGen>::const_iterator iter = ogs.begin();
iter != ogs.end(); ++iter) iter != ogs.end(); ++iter)
{ {
ObjGen const& og = *iter; QPDFObjGen const& og = *iter;
assert(this->obj_cache.count(og) > 0); assert(this->obj_cache.count(og) > 0);
end = std::max(end, this->obj_cache[og].end_after_space); end = std::max(end, this->obj_cache[og].end_after_space);
} }
@ -650,7 +650,7 @@ QPDF::maxEnd(ObjUser const& ou)
} }
qpdf_offset_t qpdf_offset_t
QPDF::getLinearizationOffset(ObjGen const& og) QPDF::getLinearizationOffset(QPDFObjGen const& og)
{ {
QPDFXRefEntry entry = this->xref_table[og]; QPDFXRefEntry entry = this->xref_table[og];
qpdf_offset_t result = 0; qpdf_offset_t result = 0;
@ -663,7 +663,8 @@ QPDF::getLinearizationOffset(ObjGen const& og)
case 2: case 2:
// For compressed objects, return the offset of the object // For compressed objects, return the offset of the object
// stream that contains them. // stream that contains them.
result = getLinearizationOffset(ObjGen(entry.getObjStreamNumber(), 0)); result = getLinearizationOffset(
QPDFObjGen(entry.getObjStreamNumber(), 0));
break; break;
default: default:
@ -685,7 +686,7 @@ QPDF::getUncompressedObject(QPDFObjectHandle& obj,
else else
{ {
int repl = (*(object_stream_data.find(obj.getObjectID()))).second; 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; int length = 0;
for (int i = 0; i < n; ++i) 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) if (this->xref_table.count(og) == 0)
{ {
errors.push_back( errors.push_back(
@ -739,7 +740,7 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
unsigned int npages = pages.size(); unsigned int npages = pages.size();
int table_offset = adjusted_offset( int table_offset = adjusted_offset(
this->page_offset_hints.first_page_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); assert(this->xref_table.count(first_page_og) > 0);
int offset = getLinearizationOffset(first_page_og); int offset = getLinearizationOffset(first_page_og);
if (table_offset != offset) if (table_offset != offset)
@ -749,9 +750,9 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
for (unsigned int pageno = 0; pageno < npages; ++pageno) for (unsigned int pageno = 0; pageno < npages; ++pageno)
{ {
ObjGen page_og(pages[pageno].getObjectID(), QPDFObjGen page_og(pages[pageno].getObjectID(),
pages[pageno].getGeneration()); pages[pageno].getGeneration());
int first_object = page_og.obj; int first_object = page_og.getObj();
assert(this->xref_table.count(page_og) > 0); assert(this->xref_table.count(page_og) > 0);
offset = getLinearizationOffset(page_og); offset = getLinearizationOffset(page_og);
@ -906,7 +907,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
cur_object = so.first_shared_obj; cur_object = so.first_shared_obj;
ObjGen og(cur_object, 0); QPDFObjGen og(cur_object, 0);
assert(this->xref_table.count(og) > 0); assert(this->xref_table.count(og) > 0);
int offset = getLinearizationOffset(og); int offset = getLinearizationOffset(og);
int h_offset = adjusted_offset(so.first_shared_offset); int h_offset = adjusted_offset(so.first_shared_offset);
@ -960,7 +961,7 @@ QPDF::checkHOutlines(std::list<std::string>& warnings)
{ {
// Check length and offset. Acrobat gets these wrong. // Check length and offset. Acrobat gets these wrong.
QPDFObjectHandle outlines = getRoot().getKey("/Outlines"); QPDFObjectHandle outlines = getRoot().getKey("/Outlines");
ObjGen og(outlines.getObjectID(), outlines.getGeneration()); QPDFObjGen og(outlines.getObjectID(), outlines.getGeneration());
assert(this->xref_table.count(og) > 0); assert(this->xref_table.count(og) > 0);
int offset = getLinearizationOffset(og); int offset = getLinearizationOffset(og);
ObjUser ou(ObjUser::ou_root_key, "/Outlines"); ObjUser ou(ObjUser::ou_root_key, "/Outlines");
@ -1170,9 +1171,9 @@ QPDF::dumpHGeneric(HGeneric& t)
} }
QPDFObjectHandle QPDFObjectHandle
QPDF::objGenToIndirect(ObjGen const& og) QPDF::objGenToIndirect(QPDFObjGen const& og)
{ {
return getObjectByID(og.obj, og.gen); return getObjectByID(og.getObj(), og.getGen());
} }
void void
@ -1280,22 +1281,22 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
open_document_keys.insert("/OpenAction"); open_document_keys.insert("/OpenAction");
open_document_keys.insert("/AcroForm"); open_document_keys.insert("/AcroForm");
std::set<ObjGen> lc_open_document; std::set<QPDFObjGen> lc_open_document;
std::set<ObjGen> lc_first_page_private; std::set<QPDFObjGen> lc_first_page_private;
std::set<ObjGen> lc_first_page_shared; std::set<QPDFObjGen> lc_first_page_shared;
std::set<ObjGen> lc_other_page_private; std::set<QPDFObjGen> lc_other_page_private;
std::set<ObjGen> lc_other_page_shared; std::set<QPDFObjGen> lc_other_page_shared;
std::set<ObjGen> lc_thumbnail_private; std::set<QPDFObjGen> lc_thumbnail_private;
std::set<ObjGen> lc_thumbnail_shared; std::set<QPDFObjGen> lc_thumbnail_shared;
std::set<ObjGen> lc_other; std::set<QPDFObjGen> lc_other;
std::set<ObjGen> lc_outlines; std::set<QPDFObjGen> lc_outlines;
std::set<ObjGen> lc_root; std::set<QPDFObjGen> lc_root;
for (std::map<ObjGen, std::set<ObjUser> >::iterator oiter = for (std::map<QPDFObjGen, std::set<ObjUser> >::iterator oiter =
this->object_to_obj_users.begin(); this->object_to_obj_users.begin();
oiter != this->object_to_obj_users.end(); ++oiter) oiter != this->object_to_obj_users.end(); ++oiter)
{ {
ObjGen const& og = (*oiter).first; QPDFObjGen const& og = (*oiter).first;
std::set<ObjUser>& ous = (*oiter).second; std::set<ObjUser>& ous = (*oiter).second;
@ -1414,10 +1415,10 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// optimizing this by going straight into the vector, we'll leave // optimizing this by going straight into the vector, we'll leave
// these phases separate for now. That way, this section can be // these phases separate for now. That way, this section can be
// concerned only with ordering, and the above section can be // concerned only with ordering, and the above section can be
// considered only with categorization. Note that sets of ObjGens // considered only with categorization. Note that sets of
// are sorted by ObjGen. In a linearized file, objects appear in // QPDFObjGens are sorted by QPDFObjGen. In a linearized file,
// sequence with the possible exception of hints tables which we // objects appear in sequence with the possible exception of hints
// won't see here anyway. That means that running // tables which we won't see here anyway. That means that running
// calculateLinearizationData() on a linearized file should give // calculateLinearizationData() on a linearized file should give
// results identical to the original file ordering. // results identical to the original file ordering.
@ -1452,7 +1453,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
assert(lc_root.size() == 1); assert(lc_root.size() == 1);
this->part4.push_back(objGenToIndirect(*(lc_root.begin()))); this->part4.push_back(objGenToIndirect(*(lc_root.begin())));
for (std::set<ObjGen>::iterator iter = lc_open_document.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_open_document.begin();
iter != lc_open_document.end(); ++iter) iter != lc_open_document.end(); ++iter)
{ {
this->part4.push_back(objGenToIndirect(*iter)); this->part4.push_back(objGenToIndirect(*iter));
@ -1465,7 +1466,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// will do the same. // will do the same.
// First, place the actual first page object itself. // 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)) if (! lc_first_page_private.count(first_page_og))
{ {
throw std::logic_error( throw std::logic_error(
@ -1481,13 +1482,13 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// groups private and shared objects contiguously for the sake of // groups private and shared objects contiguously for the sake of
// hint tables. // hint tables.
for (std::set<ObjGen>::iterator iter = lc_first_page_private.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_first_page_private.begin();
iter != lc_first_page_private.end(); ++iter) iter != lc_first_page_private.end(); ++iter)
{ {
this->part6.push_back(objGenToIndirect(*iter)); this->part6.push_back(objGenToIndirect(*iter));
} }
for (std::set<ObjGen>::iterator iter = lc_first_page_shared.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_first_page_shared.begin();
iter != lc_first_page_shared.end(); ++iter) iter != lc_first_page_shared.end(); ++iter)
{ {
this->part6.push_back(objGenToIndirect(*iter)); this->part6.push_back(objGenToIndirect(*iter));
@ -1514,7 +1515,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
{ {
// Place this page's page object // 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)) if (! lc_other_page_private.count(page_og))
{ {
throw std::logic_error( throw std::logic_error(
@ -1532,11 +1533,11 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
ObjUser ou(ObjUser::ou_page, i); ObjUser ou(ObjUser::ou_page, i);
assert(this->obj_user_to_objects.count(ou) > 0); assert(this->obj_user_to_objects.count(ou) > 0);
std::set<ObjGen> ogs = this->obj_user_to_objects[ou]; std::set<QPDFObjGen> ogs = this->obj_user_to_objects[ou];
for (std::set<ObjGen>::iterator iter = ogs.begin(); for (std::set<QPDFObjGen>::iterator iter = ogs.begin();
iter != ogs.end(); ++iter) iter != ogs.end(); ++iter)
{ {
ObjGen const& og = (*iter); QPDFObjGen const& og = (*iter);
if (lc_other_page_private.count(og)) if (lc_other_page_private.count(og))
{ {
lc_other_page_private.erase(og); lc_other_page_private.erase(og);
@ -1557,7 +1558,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// Part 8: other pages' shared objects // Part 8: other pages' shared objects
// Order is unimportant. // Order is unimportant.
for (std::set<ObjGen>::iterator iter = lc_other_page_shared.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_other_page_shared.begin();
iter != lc_other_page_shared.end(); ++iter) iter != lc_other_page_shared.end(); ++iter)
{ {
this->part8.push_back(objGenToIndirect(*iter)); this->part8.push_back(objGenToIndirect(*iter));
@ -1573,13 +1574,13 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// arbitrary order. // arbitrary order.
// Place the pages tree. // Place the pages tree.
std::set<ObjGen> pages_ogs = std::set<QPDFObjGen> pages_ogs =
this->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")]; this->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")];
assert(! pages_ogs.empty()); assert(! pages_ogs.empty());
for (std::set<ObjGen>::iterator iter = pages_ogs.begin(); for (std::set<QPDFObjGen>::iterator iter = pages_ogs.begin();
iter != pages_ogs.end(); ++iter) iter != pages_ogs.end(); ++iter)
{ {
ObjGen const& og = *iter; QPDFObjGen const& og = *iter;
if (lc_other.count(og)) if (lc_other.count(og))
{ {
lc_other.erase(og); lc_other.erase(og);
@ -1597,7 +1598,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
if (! thumb.isNull()) if (! thumb.isNull())
{ {
// Output the thumbnail itself // 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)) if (lc_thumbnail_private.count(thumb_og))
{ {
lc_thumbnail_private.erase(thumb_og); lc_thumbnail_private.erase(thumb_og);
@ -1612,12 +1613,12 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
// having been in some set other than // having been in some set other than
// lc_thumbnail_private. // lc_thumbnail_private.
} }
std::set<ObjGen>& ogs = std::set<QPDFObjGen>& ogs =
this->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)]; this->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)];
for (std::set<ObjGen>::iterator iter = ogs.begin(); for (std::set<QPDFObjGen>::iterator iter = ogs.begin();
iter != ogs.end(); ++iter) iter != ogs.end(); ++iter)
{ {
ObjGen const& og = *iter; QPDFObjGen const& og = *iter;
if (lc_thumbnail_private.count(og)) if (lc_thumbnail_private.count(og))
{ {
lc_thumbnail_private.erase(og); lc_thumbnail_private.erase(og);
@ -1635,7 +1636,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
} }
// Place shared thumbnail objects // Place shared thumbnail objects
for (std::set<ObjGen>::iterator iter = lc_thumbnail_shared.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_thumbnail_shared.begin();
iter != lc_thumbnail_shared.end(); ++iter) iter != lc_thumbnail_shared.end(); ++iter)
{ {
this->part9.push_back(objGenToIndirect(*iter)); this->part9.push_back(objGenToIndirect(*iter));
@ -1648,7 +1649,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
} }
// Place all remaining objects // Place all remaining objects
for (std::set<ObjGen>::iterator iter = lc_other.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_other.begin();
iter != lc_other.end(); ++iter) iter != lc_other.end(); ++iter)
{ {
this->part9.push_back(objGenToIndirect(*iter)); this->part9.push_back(objGenToIndirect(*iter));
@ -1723,15 +1724,15 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
CHPageOffsetEntry& pe = this->c_page_offset_data.entries[i]; CHPageOffsetEntry& pe = this->c_page_offset_data.entries[i];
ObjUser ou(ObjUser::ou_page, i); ObjUser ou(ObjUser::ou_page, i);
assert(this->obj_user_to_objects.count(ou) > 0); assert(this->obj_user_to_objects.count(ou) > 0);
std::set<ObjGen> const& ogs = this->obj_user_to_objects[ou]; std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou];
for (std::set<ObjGen>::const_iterator iter = ogs.begin(); for (std::set<QPDFObjGen>::const_iterator iter = ogs.begin();
iter != ogs.end(); ++iter) iter != ogs.end(); ++iter)
{ {
ObjGen const& og = *iter; QPDFObjGen const& og = *iter;
if ((this->object_to_obj_users[og].size() > 1) && 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.nshared_objects;
pe.shared_identifiers.push_back(idx); pe.shared_identifiers.push_back(idx);
} }
@ -1742,7 +1743,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
void void
QPDF::pushOutlinesToPart( QPDF::pushOutlinesToPart(
std::vector<QPDFObjectHandle>& part, std::vector<QPDFObjectHandle>& part,
std::set<ObjGen>& lc_outlines, std::set<QPDFObjGen>& lc_outlines,
std::map<int, int> const& object_stream_data) std::map<int, int> const& object_stream_data)
{ {
QPDFObjectHandle root = getRoot(); QPDFObjectHandle root = getRoot();
@ -1752,16 +1753,16 @@ QPDF::pushOutlinesToPart(
return; return;
} }
outlines = getUncompressedObject(outlines, object_stream_data); 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", QTC::TC("qpdf", "QPDF lin outlines in part",
((&part == (&this->part6)) ? 0 ((&part == (&this->part6)) ? 0
: (&part == (&this->part9)) ? 1 : (&part == (&this->part9)) ? 1
: 9999)); // can't happen : 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; this->c_outline_data.nobjects = 1;
lc_outlines.erase(outlines_og); lc_outlines.erase(outlines_og);
part.push_back(outlines); part.push_back(outlines);
for (std::set<ObjGen>::iterator iter = lc_outlines.begin(); for (std::set<QPDFObjGen>::iterator iter = lc_outlines.begin();
iter != lc_outlines.end(); ++iter) iter != lc_outlines.end(); ++iter)
{ {
part.push_back(objGenToIndirect(*iter)); part.push_back(objGenToIndirect(*iter));

View File

@ -115,7 +115,7 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
} }
ObjUser root_ou = ObjUser(ObjUser::ou_root); 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); obj_user_to_objects[root_ou].insert(root_og);
object_to_obj_users[root_og].insert(root_ou); object_to_obj_users[root_og].insert(root_ou);
@ -310,13 +310,13 @@ QPDF::pushInheritedAttributesToPageInternal(
void void
QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh) QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh)
{ {
std::set<ObjGen> visited; std::set<QPDFObjGen> visited;
updateObjectMapsInternal(ou, oh, visited, true); updateObjectMapsInternal(ou, oh, visited, true);
} }
void void
QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
std::set<ObjGen>& visited, bool top) std::set<QPDFObjGen>& visited, bool top)
{ {
// Traverse the object tree from this point taking care to avoid // Traverse the object tree from this point taking care to avoid
// crossing page boundaries. // crossing page boundaries.
@ -338,7 +338,7 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
if (oh.isIndirect()) if (oh.isIndirect())
{ {
ObjGen og(oh.getObjectID(), oh.getGeneration()); QPDFObjGen og(oh.getObjectID(), oh.getGeneration());
if (visited.count(og)) if (visited.count(og))
{ {
QTC::TC("qpdf", "QPDF opt loop detected"); QTC::TC("qpdf", "QPDF opt loop detected");
@ -403,51 +403,51 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data)
// user of a compressed object, then it is really a user of the // user of a compressed object, then it is really a user of the
// object stream that contains it. // object stream that contains it.
std::map<ObjUser, std::set<ObjGen> > t_obj_user_to_objects; std::map<ObjUser, std::set<QPDFObjGen> > t_obj_user_to_objects;
std::map<ObjGen, std::set<ObjUser> > t_object_to_obj_users; std::map<QPDFObjGen, std::set<ObjUser> > t_object_to_obj_users;
for (std::map<ObjUser, std::set<ObjGen> >::iterator i1 = for (std::map<ObjUser, std::set<QPDFObjGen> >::iterator i1 =
this->obj_user_to_objects.begin(); this->obj_user_to_objects.begin();
i1 != this->obj_user_to_objects.end(); ++i1) i1 != this->obj_user_to_objects.end(); ++i1)
{ {
ObjUser const& ou = (*i1).first; ObjUser const& ou = (*i1).first;
std::set<ObjGen> const& objects = (*i1).second; std::set<QPDFObjGen> const& objects = (*i1).second;
for (std::set<ObjGen>::const_iterator i2 = objects.begin(); for (std::set<QPDFObjGen>::const_iterator i2 = objects.begin();
i2 != objects.end(); ++i2) i2 != objects.end(); ++i2)
{ {
ObjGen const& og = (*i2); QPDFObjGen const& og = (*i2);
std::map<int, int>::const_iterator i3 = std::map<int, int>::const_iterator i3 =
object_stream_data.find(og.obj); object_stream_data.find(og.getObj());
if (i3 == object_stream_data.end()) if (i3 == object_stream_data.end())
{ {
t_obj_user_to_objects[ou].insert(og); t_obj_user_to_objects[ou].insert(og);
} }
else 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<ObjGen, std::set<ObjUser> >::iterator i1 = for (std::map<QPDFObjGen, std::set<ObjUser> >::iterator i1 =
this->object_to_obj_users.begin(); this->object_to_obj_users.begin();
i1 != this->object_to_obj_users.end(); ++i1) i1 != this->object_to_obj_users.end(); ++i1)
{ {
ObjGen const& og = (*i1).first; QPDFObjGen const& og = (*i1).first;
std::set<ObjUser> const& objusers = (*i1).second; std::set<ObjUser> const& objusers = (*i1).second;
for (std::set<ObjUser>::const_iterator i2 = objusers.begin(); for (std::set<ObjUser>::const_iterator i2 = objusers.begin();
i2 != objusers.end(); ++i2) i2 != objusers.end(); ++i2)
{ {
ObjUser const& ou = (*i2); ObjUser const& ou = (*i2);
std::map<int, int>::const_iterator i3 = std::map<int, int>::const_iterator i3 =
object_stream_data.find(og.obj); object_stream_data.find(og.getObj());
if (i3 == object_stream_data.end()) if (i3 == object_stream_data.end())
{ {
t_object_to_obj_users[og].insert(ou); t_object_to_obj_users[og].insert(ou);
} }
else else
{ {
t_object_to_obj_users[ObjGen((*i3).second, 0)].insert(ou); t_object_to_obj_users[QPDFObjGen((*i3).second, 0)].insert(ou);
} }
} }
} }

View File

@ -127,7 +127,7 @@ void
QPDF::insertPageobjToPage(QPDFObjectHandle const& obj, int pos, QPDF::insertPageobjToPage(QPDFObjectHandle const& obj, int pos,
bool check_duplicate) bool check_duplicate)
{ {
ObjGen og(obj.getObjectID(), obj.getGeneration()); QPDFObjGen og(obj.getObjectID(), obj.getGeneration());
if (check_duplicate) if (check_duplicate)
{ {
if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second) 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"); QTC::TC("qpdf", "QPDF duplicate page reference");
setLastObjectDescription("page " + QUtil::int_to_string(pos) + setLastObjectDescription("page " + QUtil::int_to_string(pos) +
" (numbered from zero)", " (numbered from zero)",
og.obj, og.gen); og.getObj(), og.getGen());
throw QPDFExc(qpdf_e_pages, this->file->getName(), throw QPDFExc(qpdf_e_pages, this->file->getName(),
this->last_object_description, 0, this->last_object_description, 0,
"duplicate page reference found;" "duplicate page reference found;"
@ -215,7 +215,7 @@ QPDF::removePage(QPDFObjectHandle page)
this->all_pages.erase(this->all_pages.begin() + pos); this->all_pages.erase(this->all_pages.begin() + pos);
assert(this->all_pages.size() == static_cast<size_t>(npages)); assert(this->all_pages.size() == static_cast<size_t>(npages));
this->pageobj_to_pages_pos.erase( 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<size_t>(npages)); assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
for (int i = pos; i < npages; ++i) for (int i = pos; i < npages; ++i)
{ {
@ -260,8 +260,8 @@ int
QPDF::findPage(int objid, int generation) QPDF::findPage(int objid, int generation)
{ {
flattenPagesTree(); flattenPagesTree();
std::map<ObjGen, int>::iterator it = std::map<QPDFObjGen, int>::iterator it =
this->pageobj_to_pages_pos.find(ObjGen(objid, generation)); this->pageobj_to_pages_pos.find(QPDFObjGen(objid, generation));
if (it == this->pageobj_to_pages_pos.end()) if (it == this->pageobj_to_pages_pos.end())
{ {
setLastObjectDescription("page object", objid, generation); setLastObjectDescription("page object", objid, generation);

View File

@ -32,6 +32,7 @@ SRCS_libqpdf = \
libqpdf/Pl_StdioFile.cc \ libqpdf/Pl_StdioFile.cc \
libqpdf/QPDF.cc \ libqpdf/QPDF.cc \
libqpdf/QPDFExc.cc \ libqpdf/QPDFExc.cc \
libqpdf/QPDFObjGen.cc \
libqpdf/QPDFObject.cc \ libqpdf/QPDFObject.cc \
libqpdf/QPDFObjectHandle.cc \ libqpdf/QPDFObjectHandle.cc \
libqpdf/QPDFTokenizer.cc \ libqpdf/QPDFTokenizer.cc \