Commit 5696a507b6dacf34d066810a3f2fca3525eb02f5

Authored by Jay Berkenbilt
Committed by GitHub
2 parents 6f1041af 8b4afa42

Merge pull request #731 from m-holger/og_unparse

Tidy QPDFObjGen related code
examples/pdf-create.cc
@@ -29,8 +29,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider @@ -29,8 +29,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider
29 public: 29 public:
30 ImageProvider(std::string const& color_space, std::string const& filter); 30 ImageProvider(std::string const& color_space, std::string const& filter);
31 virtual ~ImageProvider() = default; 31 virtual ~ImageProvider() = default;
32 - virtual void  
33 - provideStreamData(int objid, int generation, Pipeline* pipeline); 32 + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
34 size_t getWidth() const; 33 size_t getWidth() const;
35 size_t getHeight() const; 34 size_t getHeight() const;
36 35
@@ -93,7 +92,7 @@ ImageProvider::getHeight() const @@ -93,7 +92,7 @@ ImageProvider::getHeight() const
93 } 92 }
94 93
95 void 94 void
96 -ImageProvider::provideStreamData(int objid, int generation, Pipeline* pipeline) 95 +ImageProvider::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
97 { 96 {
98 std::vector<std::shared_ptr<Pipeline>> to_delete; 97 std::vector<std::shared_ptr<Pipeline>> to_delete;
99 Pipeline* p = pipeline; 98 Pipeline* p = pipeline;
@@ -292,7 +291,7 @@ check( @@ -292,7 +291,7 @@ check(
292 ImageProvider* p = new ImageProvider(desired_color_space, "null"); 291 ImageProvider* p = new ImageProvider(desired_color_space, "null");
293 std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider(p); 292 std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider(p);
294 Pl_Buffer b_p("get image data"); 293 Pl_Buffer b_p("get image data");
295 - provider->provideStreamData(0, 0, &b_p); 294 + provider->provideStreamData(QPDFObjGen(), &b_p);
296 std::shared_ptr<Buffer> desired_data(b_p.getBuffer()); 295 std::shared_ptr<Buffer> desired_data(b_p.getBuffer());
297 296
298 if (desired_data->getSize() != actual_data->getSize()) { 297 if (desired_data->getSize() != actual_data->getSize()) {
examples/pdf-custom-filter.cc
@@ -201,7 +201,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider @@ -201,7 +201,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
201 StreamReplacer(QPDF* pdf); 201 StreamReplacer(QPDF* pdf);
202 virtual ~StreamReplacer() = default; 202 virtual ~StreamReplacer() = default;
203 virtual void 203 virtual void
204 - provideStreamData(int objid, int generation, Pipeline* pipeline) override; 204 + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
205 205
206 void registerStream( 206 void registerStream(
207 QPDFObjectHandle stream, 207 QPDFObjectHandle stream,
@@ -384,9 +384,8 @@ StreamReplacer::registerStream( @@ -384,9 +384,8 @@ StreamReplacer::registerStream(
384 } 384 }
385 385
386 void 386 void
387 -StreamReplacer::provideStreamData(int objid, int generation, Pipeline* pipeline) 387 +StreamReplacer::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
388 { 388 {
389 - QPDFObjGen og(objid, generation);  
390 QPDFObjectHandle orig = this->copied_streams[og]; 389 QPDFObjectHandle orig = this->copied_streams[og];
391 // call maybeReplace again, this time with the pipeline and no 390 // call maybeReplace again, this time with the pipeline and no
392 // dict_updates. In this mode, maybeReplace doesn't make any 391 // dict_updates. In this mode, maybeReplace doesn't make any
examples/pdf-invert-images.cc
@@ -35,7 +35,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider @@ -35,7 +35,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
35 public: 35 public:
36 virtual ~ImageInverter() = default; 36 virtual ~ImageInverter() = default;
37 virtual void 37 virtual void
38 - provideStreamData(int objid, int generation, Pipeline* pipeline) override; 38 + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
39 39
40 void registerImage( 40 void registerImage(
41 QPDFObjectHandle image, 41 QPDFObjectHandle image,
@@ -82,12 +82,11 @@ ImageInverter::registerImage( @@ -82,12 +82,11 @@ ImageInverter::registerImage(
82 } 82 }
83 83
84 void 84 void
85 -ImageInverter::provideStreamData(int objid, int generation, Pipeline* pipeline) 85 +ImageInverter::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
86 { 86 {
87 // Use the object and generation number supplied to look up the 87 // Use the object and generation number supplied to look up the
88 // image data. Then invert the image data and write the inverted 88 // image data. Then invert the image data and write the inverted
89 // data to the pipeline. 89 // data to the pipeline.
90 - QPDFObjGen og(objid, generation);  
91 std::shared_ptr<Buffer> data = 90 std::shared_ptr<Buffer> data =
92 this->copied_images[og].getStreamData(qpdf_dl_all); 91 this->copied_images[og].getStreamData(qpdf_dl_all);
93 size_t size = data->getSize(); 92 size_t size = data->getSize();
include/qpdf/QPDF.hh
@@ -815,9 +815,9 @@ class QPDF @@ -815,9 +815,9 @@ class QPDF
815 815
816 private: 816 private:
817 static std::shared_ptr<QPDFObject> 817 static std::shared_ptr<QPDFObject>
818 - resolve(QPDF* qpdf, int objid, int generation) 818 + resolve(QPDF* qpdf, QPDFObjGen const& og)
819 { 819 {
820 - return qpdf->resolve(objid, generation); 820 + return qpdf->resolve(og);
821 } 821 }
822 static bool 822 static bool
823 objectChanged( 823 objectChanged(
@@ -879,8 +879,7 @@ class QPDF @@ -879,8 +879,7 @@ class QPDF
879 static bool 879 static bool
880 pipeStreamData( 880 pipeStreamData(
881 QPDF* qpdf, 881 QPDF* qpdf,
882 - int objid,  
883 - int generation, 882 + QPDFObjGen const& og,
884 qpdf_offset_t offset, 883 qpdf_offset_t offset,
885 size_t length, 884 size_t length,
886 QPDFObjectHandle dict, 885 QPDFObjectHandle dict,
@@ -889,8 +888,7 @@ class QPDF @@ -889,8 +888,7 @@ class QPDF
889 bool will_retry) 888 bool will_retry)
890 { 889 {
891 return qpdf->pipeStreamData( 890 return qpdf->pipeStreamData(
892 - objid,  
893 - generation, 891 + og,
894 offset, 892 offset,
895 length, 893 length,
896 dict, 894 dict,
@@ -959,8 +957,7 @@ class QPDF @@ -959,8 +957,7 @@ class QPDF
959 std::string user_password; 957 std::string user_password;
960 std::string encryption_key; 958 std::string encryption_key;
961 std::string cached_object_encryption_key; 959 std::string cached_object_encryption_key;
962 - int cached_key_objid;  
963 - int cached_key_generation; 960 + QPDFObjGen cached_key_og;
964 bool user_password_matched; 961 bool user_password_matched;
965 bool owner_password_matched; 962 bool owner_password_matched;
966 }; 963 };
@@ -973,8 +970,7 @@ class QPDF @@ -973,8 +970,7 @@ class QPDF
973 ForeignStreamData( 970 ForeignStreamData(
974 std::shared_ptr<EncryptionParameters> encp, 971 std::shared_ptr<EncryptionParameters> encp,
975 std::shared_ptr<InputSource> file, 972 std::shared_ptr<InputSource> file,
976 - int foreign_objid,  
977 - int foreign_generation, 973 + QPDFObjGen const& foreign_og,
978 qpdf_offset_t offset, 974 qpdf_offset_t offset,
979 size_t length, 975 size_t length,
980 QPDFObjectHandle local_dict); 976 QPDFObjectHandle local_dict);
@@ -982,8 +978,7 @@ class QPDF @@ -982,8 +978,7 @@ class QPDF
982 private: 978 private:
983 std::shared_ptr<EncryptionParameters> encp; 979 std::shared_ptr<EncryptionParameters> encp;
984 std::shared_ptr<InputSource> file; 980 std::shared_ptr<InputSource> file;
985 - int foreign_objid;  
986 - int foreign_generation; 981 + QPDFObjGen foreign_og;
987 qpdf_offset_t offset; 982 qpdf_offset_t offset;
988 size_t length; 983 size_t length;
989 QPDFObjectHandle local_dict; 984 QPDFObjectHandle local_dict;
@@ -995,8 +990,7 @@ class QPDF @@ -995,8 +990,7 @@ class QPDF
995 CopiedStreamDataProvider(QPDF& destination_qpdf); 990 CopiedStreamDataProvider(QPDF& destination_qpdf);
996 virtual ~CopiedStreamDataProvider() = default; 991 virtual ~CopiedStreamDataProvider() = default;
997 virtual bool provideStreamData( 992 virtual bool provideStreamData(
998 - int objid,  
999 - int generation, 993 + QPDFObjGen const& og,
1000 Pipeline* pipeline, 994 Pipeline* pipeline,
1001 bool suppress_warnings, 995 bool suppress_warnings,
1002 bool will_retry) override; 996 bool will_retry) override;
@@ -1017,14 +1011,13 @@ class QPDF @@ -1017,14 +1011,13 @@ class QPDF
1017 friend class QPDF; 1011 friend class QPDF;
1018 1012
1019 public: 1013 public:
1020 - StringDecrypter(QPDF* qpdf, int objid, int gen); 1014 + StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
1021 virtual ~StringDecrypter() = default; 1015 virtual ~StringDecrypter() = default;
1022 virtual void decryptString(std::string& val); 1016 virtual void decryptString(std::string& val);
1023 1017
1024 private: 1018 private:
1025 QPDF* qpdf; 1019 QPDF* qpdf;
1026 - int objid;  
1027 - int gen; 1020 + QPDFObjGen og;
1028 }; 1021 };
1029 1022
1030 class ResolveRecorder 1023 class ResolveRecorder
@@ -1127,17 +1120,15 @@ class QPDF @@ -1127,17 +1120,15 @@ class QPDF
1127 void insertXrefEntry( 1120 void insertXrefEntry(
1128 int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false); 1121 int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
1129 void setLastObjectDescription( 1122 void setLastObjectDescription(
1130 - std::string const& description, int objid, int generation); 1123 + std::string const& description, QPDFObjGen const& og);
1131 QPDFObjectHandle readObject( 1124 QPDFObjectHandle readObject(
1132 std::shared_ptr<InputSource>, 1125 std::shared_ptr<InputSource>,
1133 std::string const& description, 1126 std::string const& description,
1134 - int objid,  
1135 - int generation, 1127 + QPDFObjGen const& og,
1136 bool in_object_stream); 1128 bool in_object_stream);
1137 size_t recoverStreamLength( 1129 size_t recoverStreamLength(
1138 std::shared_ptr<InputSource> input, 1130 std::shared_ptr<InputSource> input,
1139 - int objid,  
1140 - int generation, 1131 + QPDFObjGen const& og,
1141 qpdf_offset_t stream_offset); 1132 qpdf_offset_t stream_offset);
1142 QPDFTokenizer::Token 1133 QPDFTokenizer::Token
1143 readToken(std::shared_ptr<InputSource>, size_t max_len = 0); 1134 readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
@@ -1146,21 +1137,18 @@ class QPDF @@ -1146,21 +1137,18 @@ class QPDF
1146 bool attempt_recovery, 1137 bool attempt_recovery,
1147 qpdf_offset_t offset, 1138 qpdf_offset_t offset,
1148 std::string const& description, 1139 std::string const& description,
1149 - int exp_objid,  
1150 - int exp_generation,  
1151 - int& act_objid,  
1152 - int& act_generation); 1140 + QPDFObjGen const& exp_og,
  1141 + QPDFObjGen& og);
1153 bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph); 1142 bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph);
1154 - std::shared_ptr<QPDFObject> resolve(int objid, int generation); 1143 + std::shared_ptr<QPDFObject> resolve(QPDFObjGen const& og);
1155 void resolveObjectsInStream(int obj_stream_number); 1144 void resolveObjectsInStream(int obj_stream_number);
1156 void stopOnError(std::string const& message); 1145 void stopOnError(std::string const& message);
1157 - QPDFObjectHandle reserveObjectIfNotExists(int objid, int gen);  
1158 - QPDFObjectHandle reserveStream(int objid, int gen); 1146 + QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
  1147 + QPDFObjectHandle reserveStream(QPDFObjGen const& og);
1159 1148
1160 // Calls finish() on the pipeline when done but does not delete it 1149 // Calls finish() on the pipeline when done but does not delete it
1161 bool pipeStreamData( 1150 bool pipeStreamData(
1162 - int objid,  
1163 - int generation, 1151 + QPDFObjGen const& og,
1164 qpdf_offset_t offset, 1152 qpdf_offset_t offset,
1165 size_t length, 1153 size_t length,
1166 QPDFObjectHandle dict, 1154 QPDFObjectHandle dict,
@@ -1176,8 +1164,7 @@ class QPDF @@ -1176,8 +1164,7 @@ class QPDF
1176 std::shared_ptr<QPDF::EncryptionParameters> encp, 1164 std::shared_ptr<QPDF::EncryptionParameters> encp,
1177 std::shared_ptr<InputSource> file, 1165 std::shared_ptr<InputSource> file,
1178 QPDF& qpdf_for_warning, 1166 QPDF& qpdf_for_warning,
1179 - int objid,  
1180 - int generation, 1167 + QPDFObjGen const& og,
1181 qpdf_offset_t offset, 1168 qpdf_offset_t offset,
1182 size_t length, 1169 size_t length,
1183 QPDFObjectHandle dict, 1170 QPDFObjectHandle dict,
@@ -1230,10 +1217,9 @@ class QPDF @@ -1230,10 +1217,9 @@ class QPDF
1230 void initializeEncryption(); 1217 void initializeEncryption();
1231 static std::string getKeyForObject( 1218 static std::string getKeyForObject(
1232 std::shared_ptr<EncryptionParameters> encp, 1219 std::shared_ptr<EncryptionParameters> encp,
1233 - int objid,  
1234 - int generation, 1220 + QPDFObjGen const& og,
1235 bool use_aes); 1221 bool use_aes);
1236 - void decryptString(std::string&, int objid, int generation); 1222 + void decryptString(std::string&, QPDFObjGen const& og);
1237 static std::string compute_encryption_key_from_password( 1223 static std::string compute_encryption_key_from_password(
1238 std::string const& password, EncryptionData const& data); 1224 std::string const& password, EncryptionData const& data);
1239 static std::string recover_encryption_key_with_password( 1225 static std::string recover_encryption_key_with_password(
@@ -1247,8 +1233,7 @@ class QPDF @@ -1247,8 +1233,7 @@ class QPDF
1247 std::shared_ptr<InputSource> file, 1233 std::shared_ptr<InputSource> file,
1248 QPDF& qpdf_for_warning, 1234 QPDF& qpdf_for_warning,
1249 Pipeline*& pipeline, 1235 Pipeline*& pipeline,
1250 - int objid,  
1251 - int generation, 1236 + QPDFObjGen const& og,
1252 QPDFObjectHandle& stream_dict, 1237 QPDFObjectHandle& stream_dict,
1253 std::vector<std::shared_ptr<Pipeline>>& heap); 1238 std::vector<std::shared_ptr<Pipeline>>& heap);
1254 1239
@@ -1571,7 +1556,6 @@ class QPDF @@ -1571,7 +1556,6 @@ class QPDF
1571 void dumpHSharedObject(); 1556 void dumpHSharedObject();
1572 void dumpHGeneric(HGeneric&); 1557 void dumpHGeneric(HGeneric&);
1573 qpdf_offset_t adjusted_offset(qpdf_offset_t offset); 1558 qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
1574 - QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);  
1575 void 1559 void
1576 calculateLinearizationData(std::map<int, int> const& object_stream_data); 1560 calculateLinearizationData(std::map<int, int> const& object_stream_data);
1577 void pushOutlinesToPart( 1561 void pushOutlinesToPart(
include/qpdf/QPDFObjGen.hh
@@ -23,7 +23,6 @@ @@ -23,7 +23,6 @@
23 #define QPDFOBJGEN_HH 23 #define QPDFOBJGEN_HH
24 24
25 #include <qpdf/DLL.h> 25 #include <qpdf/DLL.h>
26 -#include <qpdf/QUtil.hh>  
27 #include <iostream> 26 #include <iostream>
28 27
29 // This class represents an object ID and generation pair. It is 28 // This class represents an object ID and generation pair. It is
@@ -39,7 +38,7 @@ class QPDFObjGen @@ -39,7 +38,7 @@ class QPDFObjGen
39 { 38 {
40 } 39 }
41 QPDF_DLL 40 QPDF_DLL
42 - QPDFObjGen(int obj, int gen) : 41 + explicit QPDFObjGen(int obj, int gen) :
43 obj(obj), 42 obj(obj),
44 gen(gen) 43 gen(gen)
45 { 44 {
@@ -48,13 +47,19 @@ class QPDFObjGen @@ -48,13 +47,19 @@ class QPDFObjGen
48 bool 47 bool
49 operator<(QPDFObjGen const& rhs) const 48 operator<(QPDFObjGen const& rhs) const
50 { 49 {
51 - return ((obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen))); 50 + return (obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen));
52 } 51 }
53 QPDF_DLL 52 QPDF_DLL
54 bool 53 bool
55 operator==(QPDFObjGen const& rhs) const 54 operator==(QPDFObjGen const& rhs) const
56 { 55 {
57 - return ((obj == rhs.obj) && (gen == rhs.gen)); 56 + return (obj == rhs.obj) && (gen == rhs.gen);
  57 + }
  58 + QPDF_DLL
  59 + bool
  60 + operator!=(QPDFObjGen const& rhs) const
  61 + {
  62 + return (obj != rhs.obj) || (gen != rhs.gen);
58 } 63 }
59 QPDF_DLL 64 QPDF_DLL
60 int 65 int
@@ -69,18 +74,15 @@ class QPDFObjGen @@ -69,18 +74,15 @@ class QPDFObjGen
69 return gen; 74 return gen;
70 } 75 }
71 QPDF_DLL 76 QPDF_DLL
72 - std::string  
73 - unparse() const 77 + bool
  78 + isIndirect() const
74 { 79 {
75 - return QUtil::int_to_string(obj) + "," + QUtil::int_to_string(gen); 80 + return obj != 0;
76 } 81 }
77 QPDF_DLL 82 QPDF_DLL
78 - friend std::ostream&  
79 - operator<<(std::ostream& os, const QPDFObjGen& og)  
80 - {  
81 - os << og.obj << "," << og.gen;  
82 - return os;  
83 - } 83 + std::string unparse(char separator = ',') const;
  84 + QPDF_DLL
  85 + friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og);
84 86
85 private: 87 private:
86 // This class does not use the Members pattern to avoid a memory 88 // This class does not use the Members pattern to avoid a memory
include/qpdf/QPDFObjectHandle.hh
@@ -116,9 +116,16 @@ class QPDFObjectHandle @@ -116,9 +116,16 @@ class QPDFObjectHandle
116 // indicating whether it ran without errors. 116 // indicating whether it ran without errors.
117 QPDF_DLL 117 QPDF_DLL
118 virtual void 118 virtual void
119 - provideStreamData(int objid, int generation, Pipeline* pipeline); 119 + provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
120 QPDF_DLL 120 QPDF_DLL
121 virtual bool provideStreamData( 121 virtual bool provideStreamData(
  122 + QPDFObjGen const& og,
  123 + Pipeline* pipeline,
  124 + bool suppress_warnings,
  125 + bool will_retry);
  126 + QPDF_DLL virtual void
  127 + provideStreamData(int objid, int generation, Pipeline* pipeline);
  128 + QPDF_DLL virtual bool provideStreamData(
122 int objid, 129 int objid,
123 int generation, 130 int generation,
124 Pipeline* pipeline, 131 Pipeline* pipeline,
@@ -1429,21 +1436,20 @@ class QPDFObjectHandle @@ -1429,21 +1436,20 @@ class QPDFObjectHandle
1429 1436
1430 private: 1437 private:
1431 static QPDFObjectHandle 1438 static QPDFObjectHandle
1432 - newIndirect(QPDF* qpdf, int objid, int generation) 1439 + newIndirect(QPDF* qpdf, QPDFObjGen const& og)
1433 { 1440 {
1434 - return QPDFObjectHandle::newIndirect(qpdf, objid, generation); 1441 + return QPDFObjectHandle::newIndirect(qpdf, og);
1435 } 1442 }
1436 static QPDFObjectHandle 1443 static QPDFObjectHandle
1437 newStream( 1444 newStream(
1438 QPDF* qpdf, 1445 QPDF* qpdf,
1439 - int objid,  
1440 - int generation, 1446 + QPDFObjGen const& og,
1441 QPDFObjectHandle stream_dict, 1447 QPDFObjectHandle stream_dict,
1442 qpdf_offset_t offset, 1448 qpdf_offset_t offset,
1443 size_t length) 1449 size_t length)
1444 { 1450 {
1445 return QPDFObjectHandle::newStream( 1451 return QPDFObjectHandle::newStream(
1446 - qpdf, objid, generation, stream_dict, offset, length); 1452 + qpdf, og, stream_dict, offset, length);
1447 } 1453 }
1448 // Reserve an object with a specific ID 1454 // Reserve an object with a specific ID
1449 static QPDFObjectHandle 1455 static QPDFObjectHandle
@@ -1550,7 +1556,7 @@ class QPDFObjectHandle @@ -1550,7 +1556,7 @@ class QPDFObjectHandle
1550 bool isImage(bool exclude_imagemask = true); 1556 bool isImage(bool exclude_imagemask = true);
1551 1557
1552 private: 1558 private:
1553 - QPDFObjectHandle(QPDF*, int objid, int generation); 1559 + QPDFObjectHandle(QPDF*, QPDFObjGen const& og);
1554 QPDFObjectHandle(std::shared_ptr<QPDFObject> const&); 1560 QPDFObjectHandle(std::shared_ptr<QPDFObject> const&);
1555 1561
1556 enum parser_state_e { 1562 enum parser_state_e {
@@ -1563,11 +1569,10 @@ class QPDFObjectHandle @@ -1563,11 +1569,10 @@ class QPDFObjectHandle
1563 }; 1569 };
1564 1570
1565 // Private object factory methods 1571 // Private object factory methods
1566 - static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation); 1572 + static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og);
1567 static QPDFObjectHandle newStream( 1573 static QPDFObjectHandle newStream(
1568 QPDF* qpdf, 1574 QPDF* qpdf,
1569 - int objid,  
1570 - int generation, 1575 + QPDFObjGen const& og,
1571 QPDFObjectHandle stream_dict, 1576 QPDFObjectHandle stream_dict,
1572 qpdf_offset_t offset, 1577 qpdf_offset_t offset,
1573 size_t length); 1578 size_t length);
@@ -1584,7 +1589,6 @@ class QPDFObjectHandle @@ -1584,7 +1589,6 @@ class QPDFObjectHandle
1584 bool stop_at_streams); 1589 bool stop_at_streams);
1585 void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only); 1590 void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
1586 void releaseResolved(); 1591 void releaseResolved();
1587 - std::string getObjGenAsStr() const;  
1588 static void setObjectDescriptionFromInput( 1592 static void setObjectDescriptionFromInput(
1589 QPDFObjectHandle, 1593 QPDFObjectHandle,
1590 QPDF*, 1594 QPDF*,
@@ -1618,8 +1622,7 @@ class QPDFObjectHandle @@ -1618,8 +1622,7 @@ class QPDFObjectHandle
1618 // a substantial performance penalty since QPDFObjectHandle 1622 // a substantial performance penalty since QPDFObjectHandle
1619 // objects are copied around so frequently. 1623 // objects are copied around so frequently.
1620 QPDF* qpdf; 1624 QPDF* qpdf;
1621 - int objid; // 0 for direct object  
1622 - int generation; 1625 + QPDFObjGen og;
1623 std::shared_ptr<QPDFObject> obj; 1626 std::shared_ptr<QPDFObject> obj;
1624 bool reserved; 1627 bool reserved;
1625 }; 1628 };
libqpdf/CMakeLists.txt
@@ -74,6 +74,7 @@ set(libqpdf_SOURCES @@ -74,6 +74,7 @@ set(libqpdf_SOURCES
74 QPDFNumberTreeObjectHelper.cc 74 QPDFNumberTreeObjectHelper.cc
75 QPDFObject.cc 75 QPDFObject.cc
76 QPDFObjectHandle.cc 76 QPDFObjectHandle.cc
  77 + QPDFObjGen.cc
77 QPDFOutlineDocumentHelper.cc 78 QPDFOutlineDocumentHelper.cc
78 QPDFOutlineObjectHelper.cc 79 QPDFOutlineObjectHelper.cc
79 QPDFPageDocumentHelper.cc 80 QPDFPageDocumentHelper.cc
libqpdf/QPDF.cc
@@ -113,15 +113,13 @@ namespace @@ -113,15 +113,13 @@ namespace
113 QPDF::ForeignStreamData::ForeignStreamData( 113 QPDF::ForeignStreamData::ForeignStreamData(
114 std::shared_ptr<EncryptionParameters> encp, 114 std::shared_ptr<EncryptionParameters> encp,
115 std::shared_ptr<InputSource> file, 115 std::shared_ptr<InputSource> file,
116 - int foreign_objid,  
117 - int foreign_generation, 116 + QPDFObjGen const& foreign_og,
118 qpdf_offset_t offset, 117 qpdf_offset_t offset,
119 size_t length, 118 size_t length,
120 QPDFObjectHandle local_dict) : 119 QPDFObjectHandle local_dict) :
121 encp(encp), 120 encp(encp),
122 file(file), 121 file(file),
123 - foreign_objid(foreign_objid),  
124 - foreign_generation(foreign_generation), 122 + foreign_og(foreign_og),
125 offset(offset), 123 offset(offset),
126 length(length), 124 length(length),
127 local_dict(local_dict) 125 local_dict(local_dict)
@@ -137,22 +135,19 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider( @@ -137,22 +135,19 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
137 135
138 bool 136 bool
139 QPDF::CopiedStreamDataProvider::provideStreamData( 137 QPDF::CopiedStreamDataProvider::provideStreamData(
140 - int objid,  
141 - int generation, 138 + QPDFObjGen const& og,
142 Pipeline* pipeline, 139 Pipeline* pipeline,
143 bool suppress_warnings, 140 bool suppress_warnings,
144 bool will_retry) 141 bool will_retry)
145 { 142 {
146 - std::shared_ptr<ForeignStreamData> foreign_data =  
147 - this->foreign_stream_data[QPDFObjGen(objid, generation)]; 143 + std::shared_ptr<ForeignStreamData> foreign_data = foreign_stream_data[og];
148 bool result = false; 144 bool result = false;
149 if (foreign_data.get()) { 145 if (foreign_data.get()) {
150 result = destination_qpdf.pipeForeignStreamData( 146 result = destination_qpdf.pipeForeignStreamData(
151 foreign_data, pipeline, suppress_warnings, will_retry); 147 foreign_data, pipeline, suppress_warnings, will_retry);
152 QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1); 148 QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1);
153 } else { 149 } else {
154 - QPDFObjectHandle foreign_stream =  
155 - this->foreign_streams[QPDFObjGen(objid, generation)]; 150 + auto foreign_stream = foreign_streams[og];
156 result = foreign_stream.pipeStreamData( 151 result = foreign_stream.pipeStreamData(
157 pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry); 152 pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
158 QTC::TC( 153 QTC::TC(
@@ -176,17 +171,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream( @@ -176,17 +171,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream(
176 this->foreign_stream_data[local_og] = foreign_stream; 171 this->foreign_stream_data[local_og] = foreign_stream;
177 } 172 }
178 173
179 -QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, int objid, int gen) : 174 +QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) :
180 qpdf(qpdf), 175 qpdf(qpdf),
181 - objid(objid),  
182 - gen(gen) 176 + og(og)
183 { 177 {
184 } 178 }
185 179
186 void 180 void
187 QPDF::StringDecrypter::decryptString(std::string& val) 181 QPDF::StringDecrypter::decryptString(std::string& val)
188 { 182 {
189 - qpdf->decryptString(val, objid, gen); 183 + qpdf->decryptString(val, og);
190 } 184 }
191 185
192 std::string const& 186 std::string const&
@@ -205,8 +199,6 @@ QPDF::EncryptionParameters::EncryptionParameters() : @@ -205,8 +199,6 @@ QPDF::EncryptionParameters::EncryptionParameters() :
205 cf_stream(e_none), 199 cf_stream(e_none),
206 cf_string(e_none), 200 cf_string(e_none),
207 cf_file(e_none), 201 cf_file(e_none),
208 - cached_key_objid(0),  
209 - cached_key_generation(0),  
210 user_password_matched(false), 202 user_password_matched(false),
211 owner_password_matched(false) 203 owner_password_matched(false)
212 { 204 {
@@ -631,7 +623,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -631,7 +623,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
631 (!this->m->trailer.isInitialized()) && 623 (!this->m->trailer.isInitialized()) &&
632 (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) { 624 (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) {
633 QPDFObjectHandle t = 625 QPDFObjectHandle t =
634 - readObject(this->m->file, "trailer", 0, 0, false); 626 + readObject(this->m->file, "trailer", QPDFObjGen(), false);
635 if (!t.isDictionary()) { 627 if (!t.isDictionary()) {
636 // Oh well. It was worth a try. 628 // Oh well. It was worth a try.
637 } else { 629 } else {
@@ -969,7 +961,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) @@ -969,7 +961,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
969 961
970 // Set offset to previous xref table if any 962 // Set offset to previous xref table if any
971 QPDFObjectHandle cur_trailer = 963 QPDFObjectHandle cur_trailer =
972 - readObject(this->m->file, "trailer", 0, 0, false); 964 + readObject(this->m->file, "trailer", QPDFObjGen(), false);
973 if (!cur_trailer.isDictionary()) { 965 if (!cur_trailer.isDictionary()) {
974 QTC::TC("qpdf", "QPDF missing trailer"); 966 QTC::TC("qpdf", "QPDF missing trailer");
975 throw QPDFExc( 967 throw QPDFExc(
@@ -1055,12 +1047,11 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) @@ -1055,12 +1047,11 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
1055 { 1047 {
1056 bool found = false; 1048 bool found = false;
1057 if (!this->m->ignore_xref_streams) { 1049 if (!this->m->ignore_xref_streams) {
1058 - int xobj;  
1059 - int xgen; 1050 + QPDFObjGen x_og;
1060 QPDFObjectHandle xref_obj; 1051 QPDFObjectHandle xref_obj;
1061 try { 1052 try {
1062 xref_obj = readObjectAtOffset( 1053 xref_obj = readObjectAtOffset(
1063 - false, xref_offset, "xref stream", 0, 0, xobj, xgen); 1054 + false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og);
1064 } catch (QPDFExc&) { 1055 } catch (QPDFExc&) {
1065 // ignore -- report error below 1056 // ignore -- report error below
1066 } 1057 }
@@ -1363,7 +1354,7 @@ QPDF::showXRefTable() @@ -1363,7 +1354,7 @@ QPDF::showXRefTable()
1363 for (auto const& iter: this->m->xref_table) { 1354 for (auto const& iter: this->m->xref_table) {
1364 QPDFObjGen const& og = iter.first; 1355 QPDFObjGen const& og = iter.first;
1365 QPDFXRefEntry const& entry = iter.second; 1356 QPDFXRefEntry const& entry = iter.second;
1366 - cout << og.getObj() << "/" << og.getGen() << ": "; 1357 + cout << og.unparse('/') << ": ";
1367 switch (entry.getType()) { 1358 switch (entry.getType()) {
1368 case 1: 1359 case 1:
1369 cout << "uncompressed; offset = " << entry.getOffset(); 1360 cout << "uncompressed; offset = " << entry.getOffset();
@@ -1405,9 +1396,8 @@ QPDF::fixDanglingReferences(bool force) @@ -1405,9 +1396,8 @@ QPDF::fixDanglingReferences(bool force)
1405 // For each non-scalar item to process, put it in the queue. 1396 // For each non-scalar item to process, put it in the queue.
1406 std::list<QPDFObjectHandle> queue; 1397 std::list<QPDFObjectHandle> queue;
1407 queue.push_back(this->m->trailer); 1398 queue.push_back(this->m->trailer);
1408 - for (auto const& iter: to_process) {  
1409 - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(  
1410 - this, iter.getObj(), iter.getGen()); 1399 + for (auto const& og: to_process) {
  1400 + QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og);
1411 if (obj.isDictionary() || obj.isArray()) { 1401 if (obj.isDictionary() || obj.isArray()) {
1412 queue.push_back(obj); 1402 queue.push_back(obj);
1413 } else if (obj.isStream()) { 1403 } else if (obj.isStream()) {
@@ -1473,29 +1463,24 @@ QPDF::getAllObjects() @@ -1473,29 +1463,24 @@ QPDF::getAllObjects()
1473 std::vector<QPDFObjectHandle> result; 1463 std::vector<QPDFObjectHandle> result;
1474 for (auto const& iter: this->m->obj_cache) { 1464 for (auto const& iter: this->m->obj_cache) {
1475 QPDFObjGen const& og = iter.first; 1465 QPDFObjGen const& og = iter.first;
1476 - result.push_back(  
1477 - // line-break  
1478 - QPDFObjectHandle::Factory::newIndirect(  
1479 - this, og.getObj(), og.getGen())); 1466 + result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og));
1480 } 1467 }
1481 return result; 1468 return result;
1482 } 1469 }
1483 1470
1484 void 1471 void
1485 QPDF::setLastObjectDescription( 1472 QPDF::setLastObjectDescription(
1486 - std::string const& description, int objid, int generation) 1473 + std::string const& description, QPDFObjGen const& og)
1487 { 1474 {
1488 this->m->last_object_description.clear(); 1475 this->m->last_object_description.clear();
1489 if (!description.empty()) { 1476 if (!description.empty()) {
1490 this->m->last_object_description += description; 1477 this->m->last_object_description += description;
1491 - if (objid > 0) { 1478 + if (og.isIndirect()) {
1492 this->m->last_object_description += ": "; 1479 this->m->last_object_description += ": ";
1493 } 1480 }
1494 } 1481 }
1495 - if (objid > 0) {  
1496 - this->m->last_object_description += "object " +  
1497 - QUtil::int_to_string(objid) + " " +  
1498 - QUtil::int_to_string(generation); 1482 + if (og.isIndirect()) {
  1483 + this->m->last_object_description += "object " + og.unparse(' ');
1499 } 1484 }
1500 } 1485 }
1501 1486
@@ -1503,19 +1488,17 @@ QPDFObjectHandle @@ -1503,19 +1488,17 @@ QPDFObjectHandle
1503 QPDF::readObject( 1488 QPDF::readObject(
1504 std::shared_ptr<InputSource> input, 1489 std::shared_ptr<InputSource> input,
1505 std::string const& description, 1490 std::string const& description,
1506 - int objid,  
1507 - int generation, 1491 + QPDFObjGen const& og,
1508 bool in_object_stream) 1492 bool in_object_stream)
1509 { 1493 {
1510 - setLastObjectDescription(description, objid, generation); 1494 + setLastObjectDescription(description, og);
1511 qpdf_offset_t offset = input->tell(); 1495 qpdf_offset_t offset = input->tell();
1512 1496
1513 bool empty = false; 1497 bool empty = false;
1514 std::shared_ptr<StringDecrypter> decrypter_ph; 1498 std::shared_ptr<StringDecrypter> decrypter_ph;
1515 StringDecrypter* decrypter = 0; 1499 StringDecrypter* decrypter = 0;
1516 if (this->m->encp->encrypted && (!in_object_stream)) { 1500 if (this->m->encp->encrypted && (!in_object_stream)) {
1517 - decrypter_ph =  
1518 - std::make_shared<StringDecrypter>(this, objid, generation); 1501 + decrypter_ph = std::make_shared<StringDecrypter>(this, og);
1519 decrypter = decrypter_ph.get(); 1502 decrypter = decrypter_ph.get();
1520 } 1503 }
1521 QPDFObjectHandle object = QPDFObjectHandle::parse( 1504 QPDFObjectHandle object = QPDFObjectHandle::parse(
@@ -1657,14 +1640,13 @@ QPDF::readObject( @@ -1657,14 +1640,13 @@ QPDF::readObject(
1657 } catch (QPDFExc& e) { 1640 } catch (QPDFExc& e) {
1658 if (this->m->attempt_recovery) { 1641 if (this->m->attempt_recovery) {
1659 warn(e); 1642 warn(e);
1660 - length = recoverStreamLength(  
1661 - input, objid, generation, stream_offset); 1643 + length = recoverStreamLength(input, og, stream_offset);
1662 } else { 1644 } else {
1663 throw e; 1645 throw e;
1664 } 1646 }
1665 } 1647 }
1666 object = QPDFObjectHandle::Factory::newStream( 1648 object = QPDFObjectHandle::Factory::newStream(
1667 - this, objid, generation, object, stream_offset, length); 1649 + this, og, object, stream_offset, length);
1668 } else { 1650 } else {
1669 input->seek(cur_offset, SEEK_SET); 1651 input->seek(cur_offset, SEEK_SET);
1670 } 1652 }
@@ -1692,8 +1674,7 @@ QPDF::findEndstream() @@ -1692,8 +1674,7 @@ QPDF::findEndstream()
1692 size_t 1674 size_t
1693 QPDF::recoverStreamLength( 1675 QPDF::recoverStreamLength(
1694 std::shared_ptr<InputSource> input, 1676 std::shared_ptr<InputSource> input,
1695 - int objid,  
1696 - int generation, 1677 + QPDFObjGen const& og,
1697 qpdf_offset_t stream_offset) 1678 qpdf_offset_t stream_offset)
1698 { 1679 {
1699 // Try to reconstruct stream length by looking for 1680 // Try to reconstruct stream length by looking for
@@ -1718,11 +1699,10 @@ QPDF::recoverStreamLength( @@ -1718,11 +1699,10 @@ QPDF::recoverStreamLength(
1718 1699
1719 if (length) { 1700 if (length) {
1720 qpdf_offset_t this_obj_offset = 0; 1701 qpdf_offset_t this_obj_offset = 0;
1721 - QPDFObjGen this_obj(0, 0); 1702 + QPDFObjGen this_og;
1722 1703
1723 // Make sure this is inside this object 1704 // Make sure this is inside this object
1724 for (auto const& iter: this->m->xref_table) { 1705 for (auto const& iter: this->m->xref_table) {
1725 - QPDFObjGen const& og = iter.first;  
1726 QPDFXRefEntry const& entry = iter.second; 1706 QPDFXRefEntry const& entry = iter.second;
1727 if (entry.getType() == 1) { 1707 if (entry.getType() == 1) {
1728 qpdf_offset_t obj_offset = entry.getOffset(); 1708 qpdf_offset_t obj_offset = entry.getOffset();
@@ -1730,12 +1710,11 @@ QPDF::recoverStreamLength( @@ -1730,12 +1710,11 @@ QPDF::recoverStreamLength(
1730 ((this_obj_offset == 0) || 1710 ((this_obj_offset == 0) ||
1731 (this_obj_offset > obj_offset))) { 1711 (this_obj_offset > obj_offset))) {
1732 this_obj_offset = obj_offset; 1712 this_obj_offset = obj_offset;
1733 - this_obj = og; 1713 + this_og = iter.first;
1734 } 1714 }
1735 } 1715 }
1736 } 1716 }
1737 - if (this_obj_offset && (this_obj.getObj() == objid) &&  
1738 - (this_obj.getGen() == generation)) { 1717 + if (this_obj_offset && (this_og == og)) {
1739 // Well, we found endstream\nendobj within the space 1718 // Well, we found endstream\nendobj within the space
1740 // allowed for this object, so we're probably in good 1719 // allowed for this object, so we're probably in good
1741 // shape. 1720 // shape.
@@ -1777,13 +1756,11 @@ QPDF::readObjectAtOffset( @@ -1777,13 +1756,11 @@ QPDF::readObjectAtOffset(
1777 bool try_recovery, 1756 bool try_recovery,
1778 qpdf_offset_t offset, 1757 qpdf_offset_t offset,
1779 std::string const& description, 1758 std::string const& description,
1780 - int exp_objid,  
1781 - int exp_generation,  
1782 - int& objid,  
1783 - int& generation) 1759 + QPDFObjGen const& exp_og,
  1760 + QPDFObjGen& og)
1784 { 1761 {
1785 bool check_og = true; 1762 bool check_og = true;
1786 - if (exp_objid == 0) { 1763 + if (exp_og.getObj() == 0) {
1787 // This method uses an expect object ID of 0 to indicate that 1764 // This method uses an expect object ID of 0 to indicate that
1788 // we don't know or don't care what the actual object ID is at 1765 // we don't know or don't care what the actual object ID is at
1789 // this offset. This is true when we read the xref stream and 1766 // this offset. This is true when we read the xref stream and
@@ -1795,7 +1772,7 @@ QPDF::readObjectAtOffset( @@ -1795,7 +1772,7 @@ QPDF::readObjectAtOffset(
1795 check_og = false; 1772 check_og = false;
1796 try_recovery = false; 1773 try_recovery = false;
1797 } else { 1774 } else {
1798 - setLastObjectDescription(description, exp_objid, exp_generation); 1775 + setLastObjectDescription(description, exp_og);
1799 } 1776 }
1800 1777
1801 if (!this->m->attempt_recovery) { 1778 if (!this->m->attempt_recovery) {
@@ -1841,9 +1818,9 @@ QPDF::readObjectAtOffset( @@ -1841,9 +1818,9 @@ QPDF::readObjectAtOffset(
1841 offset, 1818 offset,
1842 "expected n n obj"); 1819 "expected n n obj");
1843 } 1820 }
1844 - objid = QUtil::string_to_int(tobjid.getValue().c_str());  
1845 - generation = QUtil::string_to_int(tgen.getValue().c_str());  
1846 - 1821 + int objid = QUtil::string_to_int(tobjid.getValue().c_str());
  1822 + int generation = QUtil::string_to_int(tgen.getValue().c_str());
  1823 + og = QPDFObjGen(objid, generation);
1847 if (objid == 0) { 1824 if (objid == 0) {
1848 QTC::TC("qpdf", "QPDF object id 0"); 1825 QTC::TC("qpdf", "QPDF object id 0");
1849 throw QPDFExc( 1826 throw QPDFExc(
@@ -1853,17 +1830,14 @@ QPDF::readObjectAtOffset( @@ -1853,17 +1830,14 @@ QPDF::readObjectAtOffset(
1853 offset, 1830 offset,
1854 "object with ID 0"); 1831 "object with ID 0");
1855 } 1832 }
1856 -  
1857 - if (check_og &&  
1858 - (!((objid == exp_objid) && (generation == exp_generation)))) { 1833 + if (check_og && (exp_og != og)) {
1859 QTC::TC("qpdf", "QPDF err wrong objid/generation"); 1834 QTC::TC("qpdf", "QPDF err wrong objid/generation");
1860 QPDFExc e( 1835 QPDFExc e(
1861 qpdf_e_damaged_pdf, 1836 qpdf_e_damaged_pdf,
1862 this->m->file->getName(), 1837 this->m->file->getName(),
1863 this->m->last_object_description, 1838 this->m->last_object_description,
1864 offset, 1839 offset,
1865 - (std::string("expected ") + QUtil::int_to_string(exp_objid) +  
1866 - " " + QUtil::int_to_string(exp_generation) + " obj")); 1840 + (std::string("expected ") + exp_og.unparse(' ') + " obj"));
1867 if (try_recovery) { 1841 if (try_recovery) {
1868 // Will be retried below 1842 // Will be retried below
1869 throw e; 1843 throw e;
@@ -1877,18 +1851,12 @@ QPDF::readObjectAtOffset( @@ -1877,18 +1851,12 @@ QPDF::readObjectAtOffset(
1877 if (try_recovery) { 1851 if (try_recovery) {
1878 // Try again after reconstructing xref table 1852 // Try again after reconstructing xref table
1879 reconstruct_xref(e); 1853 reconstruct_xref(e);
1880 - QPDFObjGen og(exp_objid, exp_generation);  
1881 - if (this->m->xref_table.count(og) &&  
1882 - (this->m->xref_table[og].getType() == 1)) {  
1883 - qpdf_offset_t new_offset = this->m->xref_table[og].getOffset(); 1854 + if (this->m->xref_table.count(exp_og) &&
  1855 + (this->m->xref_table[exp_og].getType() == 1)) {
  1856 + qpdf_offset_t new_offset =
  1857 + this->m->xref_table[exp_og].getOffset();
1884 QPDFObjectHandle result = readObjectAtOffset( 1858 QPDFObjectHandle result = readObjectAtOffset(
1885 - false,  
1886 - new_offset,  
1887 - description,  
1888 - exp_objid,  
1889 - exp_generation,  
1890 - objid,  
1891 - generation); 1859 + false, new_offset, description, exp_og, og);
1892 QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset"); 1860 QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset");
1893 return result; 1861 return result;
1894 } else { 1862 } else {
@@ -1898,8 +1866,7 @@ QPDF::readObjectAtOffset( @@ -1898,8 +1866,7 @@ QPDF::readObjectAtOffset(
1898 "", 1866 "",
1899 0, 1867 0,
1900 std::string( 1868 std::string(
1901 - "object " + QUtil::int_to_string(exp_objid) + " " +  
1902 - QUtil::int_to_string(exp_generation) + 1869 + "object " + exp_og.unparse(' ') +
1903 " not found in file after regenerating" 1870 " not found in file after regenerating"
1904 " cross reference table")); 1871 " cross reference table"));
1905 return QPDFObjectHandle::newNull(); 1872 return QPDFObjectHandle::newNull();
@@ -1909,8 +1876,7 @@ QPDF::readObjectAtOffset( @@ -1909,8 +1876,7 @@ QPDF::readObjectAtOffset(
1909 } 1876 }
1910 } 1877 }
1911 1878
1912 - QPDFObjectHandle oh =  
1913 - readObject(this->m->file, description, objid, generation, false); 1879 + QPDFObjectHandle oh = readObject(this->m->file, description, og, false);
1914 1880
1915 if (!(readToken(this->m->file) == 1881 if (!(readToken(this->m->file) ==
1916 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { 1882 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) {
@@ -1922,7 +1888,6 @@ QPDF::readObjectAtOffset( @@ -1922,7 +1888,6 @@ QPDF::readObjectAtOffset(
1922 "expected endobj"); 1888 "expected endobj");
1923 } 1889 }
1924 1890
1925 - QPDFObjGen og(objid, generation);  
1926 if (!this->m->obj_cache.count(og)) { 1891 if (!this->m->obj_cache.count(og)) {
1927 // Store the object in the cache here so it gets cached 1892 // Store the object in the cache here so it gets cached
1928 // whether we first know the offset or whether we first know 1893 // whether we first know the offset or whether we first know
@@ -1987,12 +1952,11 @@ QPDF::objectChanged(QPDFObjGen const&amp; og, std::shared_ptr&lt;QPDFObject&gt;&amp; oph) @@ -1987,12 +1952,11 @@ QPDF::objectChanged(QPDFObjGen const&amp; og, std::shared_ptr&lt;QPDFObject&gt;&amp; oph)
1987 } 1952 }
1988 1953
1989 std::shared_ptr<QPDFObject> 1954 std::shared_ptr<QPDFObject>
1990 -QPDF::resolve(int objid, int generation) 1955 +QPDF::resolve(QPDFObjGen const& og)
1991 { 1956 {
1992 // Check object cache before checking xref table. This allows us 1957 // Check object cache before checking xref table. This allows us
1993 // to insert things into the object cache that don't actually 1958 // to insert things into the object cache that don't actually
1994 // exist in the file. 1959 // exist in the file.
1995 - QPDFObjGen og(objid, generation);  
1996 if (this->m->resolving.count(og)) { 1960 if (this->m->resolving.count(og)) {
1997 // This can happen if an object references itself directly or 1961 // This can happen if an object references itself directly or
1998 // indirectly in some key that has to be resolved during 1962 // indirectly in some key that has to be resolved during
@@ -2002,8 +1966,7 @@ QPDF::resolve(int objid, int generation) @@ -2002,8 +1966,7 @@ QPDF::resolve(int objid, int generation)
2002 qpdf_e_damaged_pdf, 1966 qpdf_e_damaged_pdf,
2003 "", 1967 "",
2004 this->m->file->getLastOffset(), 1968 this->m->file->getLastOffset(),
2005 - ("loop detected resolving object " + QUtil::int_to_string(objid) +  
2006 - " " + QUtil::int_to_string(generation))); 1969 + ("loop detected resolving object " + og.unparse(' ')));
2007 return QPDF_Null::create(); 1970 return QPDF_Null::create();
2008 } 1971 }
2009 ResolveRecorder rr(this, og); 1972 ResolveRecorder rr(this, og);
@@ -2016,16 +1979,9 @@ QPDF::resolve(int objid, int generation) @@ -2016,16 +1979,9 @@ QPDF::resolve(int objid, int generation)
2016 { 1979 {
2017 qpdf_offset_t offset = entry.getOffset(); 1980 qpdf_offset_t offset = entry.getOffset();
2018 // Object stored in cache by readObjectAtOffset 1981 // Object stored in cache by readObjectAtOffset
2019 - int aobjid;  
2020 - int ageneration;  
2021 - QPDFObjectHandle oh = readObjectAtOffset(  
2022 - true,  
2023 - offset,  
2024 - "",  
2025 - objid,  
2026 - generation,  
2027 - aobjid,  
2028 - ageneration); 1982 + QPDFObjGen a_og;
  1983 + QPDFObjectHandle oh =
  1984 + readObjectAtOffset(true, offset, "", og, a_og);
2029 } 1985 }
2030 break; 1986 break;
2031 1987
@@ -2039,8 +1995,7 @@ QPDF::resolve(int objid, int generation) @@ -2039,8 +1995,7 @@ QPDF::resolve(int objid, int generation)
2039 this->m->file->getName(), 1995 this->m->file->getName(),
2040 "", 1996 "",
2041 0, 1997 0,
2042 - ("object " + QUtil::int_to_string(objid) + "/" +  
2043 - QUtil::int_to_string(generation) + 1998 + ("object " + og.unparse('/') +
2044 " has unexpected xref entry type")); 1999 " has unexpected xref entry type"));
2045 } 2000 }
2046 } catch (QPDFExc& e) { 2001 } catch (QPDFExc& e) {
@@ -2050,8 +2005,7 @@ QPDF::resolve(int objid, int generation) @@ -2050,8 +2005,7 @@ QPDF::resolve(int objid, int generation)
2050 qpdf_e_damaged_pdf, 2005 qpdf_e_damaged_pdf,
2051 "", 2006 "",
2052 0, 2007 0,
2053 - ("object " + QUtil::int_to_string(objid) + "/" +  
2054 - QUtil::int_to_string(generation) + 2008 + ("object " + og.unparse('/') +
2055 ": error reading object: " + e.what())); 2009 ": error reading object: " + e.what()));
2056 } 2010 }
2057 } 2011 }
@@ -2065,10 +2019,7 @@ QPDF::resolve(int objid, int generation) @@ -2065,10 +2019,7 @@ QPDF::resolve(int objid, int generation)
2065 2019
2066 std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object); 2020 std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
2067 if (!result->hasDescription()) { 2021 if (!result->hasDescription()) {
2068 - result->setDescription(  
2069 - this,  
2070 - ("object " + QUtil::int_to_string(objid) + " " +  
2071 - QUtil::int_to_string(generation))); 2022 + result->setDescription(this, ("object " + og.unparse(' ')));
2072 } 2023 }
2073 return result; 2024 return result;
2074 } 2025 }
@@ -2165,7 +2116,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -2165,7 +2116,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
2165 (entry.getObjStreamNumber() == obj_stream_number)) { 2116 (entry.getObjStreamNumber() == obj_stream_number)) {
2166 int offset = iter.second; 2117 int offset = iter.second;
2167 input->seek(offset, SEEK_SET); 2118 input->seek(offset, SEEK_SET);
2168 - QPDFObjectHandle oh = readObject(input, "", obj, 0, true); 2119 + QPDFObjectHandle oh = readObject(input, "", og, true);
2169 this->m->obj_cache[og] = ObjCache( 2120 this->m->obj_cache[og] = ObjCache(
2170 QPDFObjectHandle::ObjAccessor::getObject(oh), 2121 QPDFObjectHandle::ObjAccessor::getObject(oh),
2171 end_before_space, 2122 end_before_space,
@@ -2187,48 +2138,46 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) @@ -2187,48 +2138,46 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh)
2187 QPDFObjGen next(max_objid + 1, 0); 2138 QPDFObjGen next(max_objid + 1, 0);
2188 this->m->obj_cache[next] = 2139 this->m->obj_cache[next] =
2189 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); 2140 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
2190 - return QPDFObjectHandle::Factory::newIndirect(  
2191 - this, next.getObj(), next.getGen()); 2141 + return QPDFObjectHandle::Factory::newIndirect(this, next);
2192 } 2142 }
2193 2143
2194 QPDFObjectHandle 2144 QPDFObjectHandle
2195 -QPDF::reserveObjectIfNotExists(int objid, int gen) 2145 +QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
2196 { 2146 {
2197 - QPDFObjGen og(objid, gen);  
2198 if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) { 2147 if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) {
2199 - resolve(objid, gen);  
2200 - replaceObject(objid, gen, QPDFObjectHandle::Factory::makeReserved()); 2148 + resolve(og);
  2149 + replaceObject(og, QPDFObjectHandle::Factory::makeReserved());
2201 } 2150 }
2202 - return getObjectByID(objid, gen); 2151 + return getObjectByObjGen(og);
2203 } 2152 }
2204 2153
2205 QPDFObjectHandle 2154 QPDFObjectHandle
2206 -QPDF::reserveStream(int objid, int gen) 2155 +QPDF::reserveStream(QPDFObjGen const& og)
2207 { 2156 {
2208 return QPDFObjectHandle::Factory::newStream( 2157 return QPDFObjectHandle::Factory::newStream(
2209 - this, objid, gen, QPDFObjectHandle::newDictionary(), 0, 0); 2158 + this, og, QPDFObjectHandle::newDictionary(), 0, 0);
2210 } 2159 }
2211 2160
2212 QPDFObjectHandle 2161 QPDFObjectHandle
2213 QPDF::getObjectByObjGen(QPDFObjGen const& og) 2162 QPDF::getObjectByObjGen(QPDFObjGen const& og)
2214 { 2163 {
2215 - return getObjectByID(og.getObj(), og.getGen()); 2164 + return QPDFObjectHandle::Factory::newIndirect(this, og);
2216 } 2165 }
2217 2166
2218 QPDFObjectHandle 2167 QPDFObjectHandle
2219 QPDF::getObjectByID(int objid, int generation) 2168 QPDF::getObjectByID(int objid, int generation)
2220 { 2169 {
2221 - return QPDFObjectHandle::Factory::newIndirect(this, objid, generation); 2170 + return getObjectByObjGen(QPDFObjGen(objid, generation));
2222 } 2171 }
2223 2172
2224 void 2173 void
2225 -QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) 2174 +QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2226 { 2175 {
2227 - replaceObject(og.getObj(), og.getGen(), oh); 2176 + replaceObject(QPDFObjGen(objid, generation), oh);
2228 } 2177 }
2229 2178
2230 void 2179 void
2231 -QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) 2180 +QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
2232 { 2181 {
2233 if (oh.isIndirect()) { 2182 if (oh.isIndirect()) {
2234 QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); 2183 QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
@@ -2237,10 +2186,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) @@ -2237,10 +2186,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2237 } 2186 }
2238 2187
2239 // Force new object to appear in the cache 2188 // Force new object to appear in the cache
2240 - resolve(objid, generation); 2189 + resolve(og);
2241 2190
2242 // Replace the object in the object cache 2191 // Replace the object in the object cache
2243 - QPDFObjGen og(objid, generation);  
2244 this->m->ever_replaced_objects = true; 2192 this->m->ever_replaced_objects = true;
2245 this->m->obj_cache[og] = 2193 this->m->obj_cache[og] =
2246 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); 2194 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
@@ -2540,8 +2488,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) @@ -2540,8 +2488,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2540 auto foreign_stream_data = std::make_shared<ForeignStreamData>( 2488 auto foreign_stream_data = std::make_shared<ForeignStreamData>(
2541 foreign_stream_qpdf->m->encp, 2489 foreign_stream_qpdf->m->encp,
2542 foreign_stream_qpdf->m->file, 2490 foreign_stream_qpdf->m->file,
2543 - foreign.getObjectID(),  
2544 - foreign.getGeneration(), 2491 + foreign.getObjGen(),
2545 stream->getOffset(), 2492 stream->getOffset(),
2546 stream->getLength(), 2493 stream->getLength(),
2547 dict); 2494 dict);
@@ -2555,20 +2502,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) @@ -2555,20 +2502,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2555 } 2502 }
2556 2503
2557 void 2504 void
2558 -QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) 2505 +QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
2559 { 2506 {
2560 - swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen()); 2507 + swapObjects(
  2508 + QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2));
2561 } 2509 }
2562 2510
2563 void 2511 void
2564 -QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) 2512 +QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
2565 { 2513 {
2566 // Force objects to be loaded into cache; then swap them in the 2514 // Force objects to be loaded into cache; then swap them in the
2567 // cache. 2515 // cache.
2568 - resolve(objid1, generation1);  
2569 - resolve(objid2, generation2);  
2570 - QPDFObjGen og1(objid1, generation1);  
2571 - QPDFObjGen og2(objid2, generation2); 2516 + resolve(og1);
  2517 + resolve(og2);
2572 ObjCache t = this->m->obj_cache[og1]; 2518 ObjCache t = this->m->obj_cache[og1];
2573 this->m->ever_replaced_objects = true; 2519 this->m->ever_replaced_objects = true;
2574 this->m->obj_cache[og1] = this->m->obj_cache[og2]; 2520 this->m->obj_cache[og1] = this->m->obj_cache[og2];
@@ -2752,8 +2698,7 @@ QPDF::pipeStreamData( @@ -2752,8 +2698,7 @@ QPDF::pipeStreamData(
2752 std::shared_ptr<EncryptionParameters> encp, 2698 std::shared_ptr<EncryptionParameters> encp,
2753 std::shared_ptr<InputSource> file, 2699 std::shared_ptr<InputSource> file,
2754 QPDF& qpdf_for_warning, 2700 QPDF& qpdf_for_warning,
2755 - int objid,  
2756 - int generation, 2701 + QPDFObjGen const& og,
2757 qpdf_offset_t offset, 2702 qpdf_offset_t offset,
2758 size_t length, 2703 size_t length,
2759 QPDFObjectHandle stream_dict, 2704 QPDFObjectHandle stream_dict,
@@ -2764,14 +2709,7 @@ QPDF::pipeStreamData( @@ -2764,14 +2709,7 @@ QPDF::pipeStreamData(
2764 std::vector<std::shared_ptr<Pipeline>> to_delete; 2709 std::vector<std::shared_ptr<Pipeline>> to_delete;
2765 if (encp->encrypted) { 2710 if (encp->encrypted) {
2766 decryptStream( 2711 decryptStream(
2767 - encp,  
2768 - file,  
2769 - qpdf_for_warning,  
2770 - pipeline,  
2771 - objid,  
2772 - generation,  
2773 - stream_dict,  
2774 - to_delete); 2712 + encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete);
2775 } 2713 }
2776 2714
2777 bool success = false; 2715 bool success = false;
@@ -2809,8 +2747,7 @@ QPDF::pipeStreamData( @@ -2809,8 +2747,7 @@ QPDF::pipeStreamData(
2809 "", 2747 "",
2810 file->getLastOffset(), 2748 file->getLastOffset(),
2811 ("error decoding stream data for object " + 2749 ("error decoding stream data for object " +
2812 - QUtil::int_to_string(objid) + " " +  
2813 - QUtil::int_to_string(generation) + ": " + e.what()))); 2750 + og.unparse(' ') + ": " + e.what())));
2814 if (will_retry) { 2751 if (will_retry) {
2815 qpdf_for_warning.warn( 2752 qpdf_for_warning.warn(
2816 // line-break 2753 // line-break
@@ -2836,8 +2773,7 @@ QPDF::pipeStreamData( @@ -2836,8 +2773,7 @@ QPDF::pipeStreamData(
2836 2773
2837 bool 2774 bool
2838 QPDF::pipeStreamData( 2775 QPDF::pipeStreamData(
2839 - int objid,  
2840 - int generation, 2776 + QPDFObjGen const& og,
2841 qpdf_offset_t offset, 2777 qpdf_offset_t offset,
2842 size_t length, 2778 size_t length,
2843 QPDFObjectHandle stream_dict, 2779 QPDFObjectHandle stream_dict,
@@ -2849,8 +2785,7 @@ QPDF::pipeStreamData( @@ -2849,8 +2785,7 @@ QPDF::pipeStreamData(
2849 this->m->encp, 2785 this->m->encp,
2850 this->m->file, 2786 this->m->file,
2851 *this, 2787 *this,
2852 - objid,  
2853 - generation, 2788 + og,
2854 offset, 2789 offset,
2855 length, 2790 length,
2856 stream_dict, 2791 stream_dict,
@@ -2873,8 +2808,7 @@ QPDF::pipeForeignStreamData( @@ -2873,8 +2808,7 @@ QPDF::pipeForeignStreamData(
2873 foreign->encp, 2808 foreign->encp,
2874 foreign->file, 2809 foreign->file,
2875 *this, 2810 *this,
2876 - foreign->foreign_objid,  
2877 - foreign->foreign_generation, 2811 + foreign->foreign_og,
2878 foreign->offset, 2812 foreign->offset,
2879 foreign->length, 2813 foreign->length,
2880 foreign->local_dict, 2814 foreign->local_dict,
libqpdf/QPDFAcroFormDocumentHelper.cc
@@ -991,8 +991,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -991,8 +991,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
991 } else { 991 } else {
992 parent.warnIfPossible( 992 parent.warnIfPossible(
993 "while traversing field " + 993 "while traversing field " +
994 - obj.getObjGen().unparse() + ", found parent (" +  
995 - parent_og.unparse() + 994 + obj.getObjGen().unparse(',') + ", found parent (" +
  995 + parent_og.unparse(',') +
996 ") that had not been seen, indicating likely" 996 ") that had not been seen, indicating likely"
997 " invalid field structure"); 997 " invalid field structure");
998 } 998 }
libqpdf/QPDFJob.cc
@@ -49,8 +49,7 @@ namespace @@ -49,8 +49,7 @@ namespace
49 size_t oi_min_area, 49 size_t oi_min_area,
50 QPDFObjectHandle& image); 50 QPDFObjectHandle& image);
51 virtual ~ImageOptimizer() = default; 51 virtual ~ImageOptimizer() = default;
52 - virtual void  
53 - provideStreamData(int objid, int generation, Pipeline* pipeline); 52 + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
54 std::shared_ptr<Pipeline> 53 std::shared_ptr<Pipeline>
55 makePipeline(std::string const& description, Pipeline* next); 54 makePipeline(std::string const& description, Pipeline* next);
56 bool evaluate(std::string const& description); 55 bool evaluate(std::string const& description);
@@ -250,7 +249,7 @@ ImageOptimizer::evaluate(std::string const&amp; description) @@ -250,7 +249,7 @@ ImageOptimizer::evaluate(std::string const&amp; description)
250 } 249 }
251 250
252 void 251 void
253 -ImageOptimizer::provideStreamData(int, int, Pipeline* pipeline) 252 +ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
254 { 253 {
255 std::shared_ptr<Pipeline> p = makePipeline("", pipeline); 254 std::shared_ptr<Pipeline> p = makePipeline("", pipeline);
256 if (p.get() == nullptr) { 255 if (p.get() == nullptr) {
@@ -947,7 +946,7 @@ QPDFJob::doShowObj(QPDF&amp; pdf) @@ -947,7 +946,7 @@ QPDFJob::doShowObj(QPDF&amp; pdf)
947 } 946 }
948 if (error) { 947 if (error) {
949 throw std::runtime_error( 948 throw std::runtime_error(
950 - "unable to get object " + obj.getObjGen().unparse()); 949 + "unable to get object " + obj.getObjGen().unparse(','));
951 } 950 }
952 } 951 }
953 952
@@ -995,7 +994,8 @@ QPDFJob::doListAttachments(QPDF&amp; pdf) @@ -995,7 +994,8 @@ QPDFJob::doListAttachments(QPDF&amp; pdf)
995 auto efoh = i.second; 994 auto efoh = i.second;
996 *this->m->log->getInfo() 995 *this->m->log->getInfo()
997 << key << " -> " 996 << key << " -> "
998 - << efoh->getEmbeddedFileStream().getObjGen().unparse() << "\n"; 997 + << efoh->getEmbeddedFileStream().getObjGen().unparse(',')
  998 + << "\n";
999 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 999 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
1000 auto desc = efoh->getDescription(); 1000 auto desc = efoh->getDescription();
1001 if (!desc.empty()) { 1001 if (!desc.empty()) {
@@ -1010,7 +1010,7 @@ QPDFJob::doListAttachments(QPDF&amp; pdf) @@ -1010,7 +1010,7 @@ QPDFJob::doListAttachments(QPDF&amp; pdf)
1010 for (auto i2: efoh->getEmbeddedFileStreams().ditems()) { 1010 for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
1011 auto efs = QPDFEFStreamObjectHelper(i2.second); 1011 auto efs = QPDFEFStreamObjectHelper(i2.second);
1012 v << " " << i2.first << " -> " 1012 v << " " << i2.first << " -> "
1013 - << efs.getObjectHandle().getObjGen().unparse() << "\n"; 1013 + << efs.getObjectHandle().getObjGen().unparse(',') << "\n";
1014 v << " creation date: " << efs.getCreationDate() 1014 v << " creation date: " << efs.getCreationDate()
1015 << "\n" 1015 << "\n"
1016 << " modification date: " << efs.getModDate() << "\n" 1016 << " modification date: " << efs.getModDate() << "\n"
@@ -2463,7 +2463,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf) @@ -2463,7 +2463,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf)
2463 QTC::TC("qpdf", "QPDFJob found resources in non-leaf"); 2463 QTC::TC("qpdf", "QPDFJob found resources in non-leaf");
2464 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 2464 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
2465 v << " found resources in non-leaf page node " 2465 v << " found resources in non-leaf page node "
2466 - << og.getObj() << " " << og.getGen() << "\n"; 2466 + << og.unparse(' ') << "\n";
2467 }); 2467 });
2468 return true; 2468 return true;
2469 } 2469 }
@@ -2480,9 +2480,8 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf) @@ -2480,9 +2480,8 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf)
2480 QTC::TC("qpdf", "QPDFJob found shared resources in leaf"); 2480 QTC::TC("qpdf", "QPDFJob found shared resources in leaf");
2481 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 2481 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
2482 v << " found shared resources in leaf node " 2482 v << " found shared resources in leaf node "
2483 - << og.getObj() << " " << og.getGen() << ": "  
2484 - << resources_og.getObj() << " "  
2485 - << resources_og.getGen() << "\n"; 2483 + << og.unparse(' ') << ": "
  2484 + << resources_og.unparse(' ') << "\n";
2486 }); 2485 });
2487 return true; 2486 return true;
2488 } 2487 }
@@ -2497,8 +2496,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf) @@ -2497,8 +2496,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF&amp; pdf)
2497 QTC::TC("qpdf", "QPDFJob found shared xobject in leaf"); 2496 QTC::TC("qpdf", "QPDFJob found shared xobject in leaf");
2498 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 2497 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
2499 v << " found shared xobject in leaf node " 2498 v << " found shared xobject in leaf node "
2500 - << og.getObj() << " " << og.getGen() << ": "  
2501 - << xobject_og.getObj() << " " << xobject_og.getGen() 2499 + << og.unparse(' ') << ": " << xobject_og.unparse(' ')
2502 << "\n"; 2500 << "\n";
2503 }); 2501 });
2504 return true; 2502 return true;
@@ -3375,7 +3373,7 @@ QPDFJob::writeJSON(QPDF&amp; pdf) @@ -3375,7 +3373,7 @@ QPDFJob::writeJSON(QPDF&amp; pdf)
3375 auto wanted = getWantedJSONObjects(); 3373 auto wanted = getWantedJSONObjects();
3376 for (auto const& og: wanted) { 3374 for (auto const& og: wanted) {
3377 std::ostringstream s; 3375 std::ostringstream s;
3378 - s << "obj:" << og.getObj() << " " << og.getGen() << " R"; 3376 + s << "obj:" << og.unparse(' ') << " R";
3379 json_objects.insert(s.str()); 3377 json_objects.insert(s.str());
3380 } 3378 }
3381 pdf.writeJSON( 3379 pdf.writeJSON(
libqpdf/QPDFObjGen.cc 0 โ†’ 100644
  1 +#include <qpdf/QPDFObjGen.hh>
  2 +
  3 +#include <qpdf/QUtil.hh>
  4 +
  5 +std::ostream&
  6 +operator<<(std::ostream& os, const QPDFObjGen& og)
  7 +{
  8 + os << og.obj << "," << og.gen;
  9 + return os;
  10 +}
  11 +
  12 +std::string
  13 +QPDFObjGen::unparse(char separator) const
  14 +{
  15 + return QUtil::int_to_string(this->obj) + separator +
  16 + QUtil::int_to_string(this->gen);
  17 +}
libqpdf/QPDFObjectHandle.cc
@@ -53,6 +53,24 @@ QPDFObjectHandle::StreamDataProvider::~StreamDataProvider() @@ -53,6 +53,24 @@ QPDFObjectHandle::StreamDataProvider::~StreamDataProvider()
53 53
54 void 54 void
55 QPDFObjectHandle::StreamDataProvider::provideStreamData( 55 QPDFObjectHandle::StreamDataProvider::provideStreamData(
  56 + QPDFObjGen const& og, Pipeline* pipeline)
  57 +{
  58 + return provideStreamData(og.getObj(), og.getGen(), pipeline);
  59 +}
  60 +
  61 +bool
  62 +QPDFObjectHandle::StreamDataProvider::provideStreamData(
  63 + QPDFObjGen const& og,
  64 + Pipeline* pipeline,
  65 + bool suppress_warnings,
  66 + bool will_retry)
  67 +{
  68 + return provideStreamData(
  69 + og.getObj(), og.getGen(), pipeline, suppress_warnings, will_retry);
  70 +}
  71 +
  72 +void
  73 +QPDFObjectHandle::StreamDataProvider::provideStreamData(
56 int objid, int generation, Pipeline* pipeline) 74 int objid, int generation, Pipeline* pipeline)
57 { 75 {
58 throw std::logic_error( 76 throw std::logic_error(
@@ -90,8 +108,7 @@ namespace @@ -90,8 +108,7 @@ namespace
90 { 108 {
91 } 109 }
92 virtual ~CoalesceProvider() = default; 110 virtual ~CoalesceProvider() = default;
93 - virtual void  
94 - provideStreamData(int objid, int generation, Pipeline* pipeline); 111 + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
95 112
96 private: 113 private:
97 QPDFObjectHandle containing_page; 114 QPDFObjectHandle containing_page;
@@ -100,12 +117,11 @@ namespace @@ -100,12 +117,11 @@ namespace
100 } // namespace 117 } // namespace
101 118
102 void 119 void
103 -CoalesceProvider::provideStreamData(int, int, Pipeline* p) 120 +CoalesceProvider::provideStreamData(QPDFObjGen const&, Pipeline* p)
104 { 121 {
105 QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data"); 122 QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data");
106 - std::string description = "page object " +  
107 - QUtil::int_to_string(containing_page.getObjectID()) + " " +  
108 - QUtil::int_to_string(containing_page.getGeneration()); 123 + std::string description =
  124 + "page object " + containing_page.getObjGen().unparse(' ');
109 std::string all_description; 125 std::string all_description;
110 old_contents.pipeContentStreams(p, description, all_description); 126 old_contents.pipeContentStreams(p, description, all_description);
111 } 127 }
@@ -219,27 +235,22 @@ LastChar::getLastChar() @@ -219,27 +235,22 @@ LastChar::getLastChar()
219 235
220 QPDFObjectHandle::QPDFObjectHandle() : 236 QPDFObjectHandle::QPDFObjectHandle() :
221 initialized(false), 237 initialized(false),
222 - qpdf(0),  
223 - objid(0),  
224 - generation(0), 238 + qpdf(nullptr),
225 reserved(false) 239 reserved(false)
226 { 240 {
227 } 241 }
228 242
229 -QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, int objid, int generation) : 243 +QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, QPDFObjGen const& og) :
230 initialized(true), 244 initialized(true),
231 qpdf(qpdf), 245 qpdf(qpdf),
232 - objid(objid),  
233 - generation(generation), 246 + og(og),
234 reserved(false) 247 reserved(false)
235 { 248 {
236 } 249 }
237 250
238 QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) : 251 QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) :
239 initialized(true), 252 initialized(true),
240 - qpdf(0),  
241 - objid(0),  
242 - generation(0), 253 + qpdf(nullptr),
243 obj(data), 254 obj(data),
244 reserved(false) 255 reserved(false)
245 { 256 {
@@ -1431,15 +1442,14 @@ namespace @@ -1431,15 +1442,14 @@ namespace
1431 } 1442 }
1432 1443
1433 virtual void 1444 virtual void
1434 - provideStreamData(int, int, Pipeline* pipeline) override 1445 + provideStreamData(QPDFObjGen const&, Pipeline* pipeline) override
1435 { 1446 {
1436 p1(pipeline); 1447 p1(pipeline);
1437 } 1448 }
1438 1449
1439 virtual bool 1450 virtual bool
1440 provideStreamData( 1451 provideStreamData(
1441 - int,  
1442 - int, 1452 + QPDFObjGen const&,
1443 Pipeline* pipeline, 1453 Pipeline* pipeline,
1444 bool suppress_warnings, 1454 bool suppress_warnings,
1445 bool will_retry) override 1455 bool will_retry) override
@@ -1482,26 +1492,19 @@ QPDFObjectHandle::replaceStreamData( @@ -1482,26 +1492,19 @@ QPDFObjectHandle::replaceStreamData(
1482 QPDFObjGen 1492 QPDFObjGen
1483 QPDFObjectHandle::getObjGen() const 1493 QPDFObjectHandle::getObjGen() const
1484 { 1494 {
1485 - return QPDFObjGen(this->objid, this->generation);  
1486 -}  
1487 -  
1488 -std::string  
1489 -QPDFObjectHandle::getObjGenAsStr() const  
1490 -{  
1491 - return QUtil::int_to_string(this->objid) + " " +  
1492 - QUtil::int_to_string(this->generation); 1495 + return og;
1493 } 1496 }
1494 1497
1495 int 1498 int
1496 QPDFObjectHandle::getObjectID() const 1499 QPDFObjectHandle::getObjectID() const
1497 { 1500 {
1498 - return this->objid; 1501 + return og.getObj();
1499 } 1502 }
1500 1503
1501 int 1504 int
1502 QPDFObjectHandle::getGeneration() const 1505 QPDFObjectHandle::getGeneration() const
1503 { 1506 {
1504 - return this->generation; 1507 + return og.getGen();
1505 } 1508 }
1506 1509
1507 std::map<std::string, QPDFObjectHandle> 1510 std::map<std::string, QPDFObjectHandle>
@@ -1556,7 +1559,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( @@ -1556,7 +1559,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
1556 } else { 1559 } else {
1557 all_description += ","; 1560 all_description += ",";
1558 } 1561 }
1559 - all_description += " stream " + item.getObjGenAsStr(); 1562 + all_description += " stream " + item.getObjGen().unparse(' ');
1560 } 1563 }
1561 1564
1562 return result; 1565 return result;
@@ -1565,7 +1568,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( @@ -1565,7 +1568,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
1565 std::vector<QPDFObjectHandle> 1568 std::vector<QPDFObjectHandle>
1566 QPDFObjectHandle::getPageContents() 1569 QPDFObjectHandle::getPageContents()
1567 { 1570 {
1568 - std::string description = "page object " + getObjGenAsStr(); 1571 + std::string description = "page object " + getObjGen().unparse(' ');
1569 std::string all_description; 1572 std::string all_description;
1570 return this->getKey("/Contents") 1573 return this->getKey("/Contents")
1571 .arrayOrStreamToStreamArray(description, all_description); 1574 .arrayOrStreamToStreamArray(description, all_description);
@@ -1674,7 +1677,7 @@ QPDFObjectHandle::unparse() @@ -1674,7 +1677,7 @@ QPDFObjectHandle::unparse()
1674 { 1677 {
1675 std::string result; 1678 std::string result;
1676 if (this->isIndirect()) { 1679 if (this->isIndirect()) {
1677 - result = getObjGenAsStr() + " R"; 1680 + result = getObjGen().unparse(' ') + " R";
1678 } else { 1681 } else {
1679 result = unparseResolved(); 1682 result = unparseResolved();
1680 } 1683 }
@@ -1789,7 +1792,7 @@ QPDFObjectHandle::parse( @@ -1789,7 +1792,7 @@ QPDFObjectHandle::parse(
1789 void 1792 void
1790 QPDFObjectHandle::pipePageContents(Pipeline* p) 1793 QPDFObjectHandle::pipePageContents(Pipeline* p)
1791 { 1794 {
1792 - std::string description = "page object " + getObjGenAsStr(); 1795 + std::string description = "page object " + getObjGen().unparse(' ');
1793 std::string all_description; 1796 std::string all_description;
1794 this->getKey("/Contents") 1797 this->getKey("/Contents")
1795 .pipeContentStreams(p, description, all_description); 1798 .pipeContentStreams(p, description, all_description);
@@ -1813,7 +1816,7 @@ QPDFObjectHandle::pipeContentStreams( @@ -1813,7 +1816,7 @@ QPDFObjectHandle::pipeContentStreams(
1813 throw QPDFExc( 1816 throw QPDFExc(
1814 qpdf_e_damaged_pdf, 1817 qpdf_e_damaged_pdf,
1815 "content stream", 1818 "content stream",
1816 - "content stream object " + stream.getObjGenAsStr(), 1819 + "content stream object " + stream.getObjGen().unparse(' '),
1817 0, 1820 0,
1818 "errors while decoding content stream"); 1821 "errors while decoding content stream");
1819 } 1822 }
@@ -1829,7 +1832,7 @@ QPDFObjectHandle::pipeContentStreams( @@ -1829,7 +1832,7 @@ QPDFObjectHandle::pipeContentStreams(
1829 void 1832 void
1830 QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks) 1833 QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
1831 { 1834 {
1832 - std::string description = "page object " + getObjGenAsStr(); 1835 + std::string description = "page object " + getObjGen().unparse(' ');
1833 this->getKey("/Contents") 1836 this->getKey("/Contents")
1834 .parseContentStream_internal(description, callbacks); 1837 .parseContentStream_internal(description, callbacks);
1835 } 1838 }
@@ -1837,14 +1840,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks) @@ -1837,14 +1840,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
1837 void 1840 void
1838 QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks) 1841 QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks)
1839 { 1842 {
1840 - std::string description = "object " + getObjGenAsStr(); 1843 + std::string description = "object " + getObjGen().unparse(' ');
1841 this->parseContentStream_internal(description, callbacks); 1844 this->parseContentStream_internal(description, callbacks);
1842 } 1845 }
1843 1846
1844 void 1847 void
1845 QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next) 1848 QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
1846 { 1849 {
1847 - auto description = "token filter for page object " + getObjGenAsStr(); 1850 + auto description =
  1851 + "token filter for page object " + getObjGen().unparse(' ');
1848 Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next); 1852 Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
1849 this->pipePageContents(&token_pipeline); 1853 this->pipePageContents(&token_pipeline);
1850 } 1854 }
@@ -1852,7 +1856,7 @@ QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next) @@ -1852,7 +1856,7 @@ QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
1852 void 1856 void
1853 QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next) 1857 QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next)
1854 { 1858 {
1855 - auto description = "token filter for object " + getObjGenAsStr(); 1859 + auto description = "token filter for object " + getObjGen().unparse(' ');
1856 Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next); 1860 Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
1857 this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized); 1861 this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized);
1858 } 1862 }
@@ -2192,8 +2196,9 @@ QPDFObjectHandle::parseInternal( @@ -2192,8 +2196,9 @@ QPDFObjectHandle::parseInternal(
2192 // Try to resolve indirect objects 2196 // Try to resolve indirect objects
2193 object = newIndirect( 2197 object = newIndirect(
2194 context, 2198 context,
2195 - olist.at(olist.size() - 2).getIntValueAsInt(),  
2196 - olist.at(olist.size() - 1).getIntValueAsInt()); 2199 + QPDFObjGen(
  2200 + olist.at(olist.size() - 2).getIntValueAsInt(),
  2201 + olist.at(olist.size() - 1).getIntValueAsInt()));
2197 olist.remove_last(); 2202 olist.remove_last();
2198 olist.remove_last(); 2203 olist.remove_last();
2199 } else if ((value == "endobj") && (state == st_top)) { 2204 } else if ((value == "endobj") && (state == st_top)) {
@@ -2481,9 +2486,9 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) @@ -2481,9 +2486,9 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset)
2481 } 2486 }
2482 2487
2483 QPDFObjectHandle 2488 QPDFObjectHandle
2484 -QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) 2489 +QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og)
2485 { 2490 {
2486 - if (objid == 0) { 2491 + if (!og.isIndirect()) {
2487 // Special case: QPDF uses objid 0 as a sentinel for direct 2492 // Special case: QPDF uses objid 0 as a sentinel for direct
2488 // objects, and the PDF specification doesn't allow for object 2493 // objects, and the PDF specification doesn't allow for object
2489 // 0. Treat indirect references to object 0 as null so that we 2494 // 0. Treat indirect references to object 0 as null so that we
@@ -2492,7 +2497,7 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) @@ -2492,7 +2497,7 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation)
2492 return newNull(); 2497 return newNull();
2493 } 2498 }
2494 2499
2495 - return QPDFObjectHandle(qpdf, objid, generation); 2500 + return QPDFObjectHandle(qpdf, og);
2496 } 2501 }
2497 2502
2498 QPDFObjectHandle 2503 QPDFObjectHandle
@@ -2640,14 +2645,13 @@ QPDFObjectHandle::newDictionary( @@ -2640,14 +2645,13 @@ QPDFObjectHandle::newDictionary(
2640 QPDFObjectHandle 2645 QPDFObjectHandle
2641 QPDFObjectHandle::newStream( 2646 QPDFObjectHandle::newStream(
2642 QPDF* qpdf, 2647 QPDF* qpdf,
2643 - int objid,  
2644 - int generation, 2648 + QPDFObjGen const& og,
2645 QPDFObjectHandle stream_dict, 2649 QPDFObjectHandle stream_dict,
2646 qpdf_offset_t offset, 2650 qpdf_offset_t offset,
2647 size_t length) 2651 size_t length)
2648 { 2652 {
2649 - QPDFObjectHandle result = QPDFObjectHandle(QPDF_Stream::create(  
2650 - qpdf, objid, generation, stream_dict, offset, length)); 2653 + QPDFObjectHandle result = QPDFObjectHandle(
  2654 + QPDF_Stream::create(qpdf, og, stream_dict, offset, length));
2651 if (offset) { 2655 if (offset) {
2652 result.setParsedOffset(offset); 2656 result.setParsedOffset(offset);
2653 } 2657 }
@@ -2663,11 +2667,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf) @@ -2663,11 +2667,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf)
2663 } 2667 }
2664 QTC::TC("qpdf", "QPDFObjectHandle newStream"); 2668 QTC::TC("qpdf", "QPDFObjectHandle newStream");
2665 QPDFObjectHandle stream_dict = newDictionary(); 2669 QPDFObjectHandle stream_dict = newDictionary();
2666 - QPDFObjectHandle result = qpdf->makeIndirectObject(  
2667 - QPDFObjectHandle(QPDF_Stream::create(qpdf, 0, 0, stream_dict, 0, 0))); 2670 + QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle(
  2671 + QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0)));
2668 result.dereference(); 2672 result.dereference();
2669 QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get()); 2673 QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get());
2670 - stream->setObjGen(result.getObjectID(), result.getGeneration()); 2674 + stream->setObjGen(result.getObjGen());
2671 return result; 2675 return result;
2672 } 2676 }
2673 2677
@@ -2695,8 +2699,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) @@ -2695,8 +2699,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf)
2695 // Reserve a spot for this object by assigning it an object 2699 // Reserve a spot for this object by assigning it an object
2696 // number, but then return an unresolved handle to the object. 2700 // number, but then return an unresolved handle to the object.
2697 QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved()); 2701 QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved());
2698 - QPDFObjectHandle result =  
2699 - newIndirect(qpdf, reserved.objid, reserved.generation); 2702 + QPDFObjectHandle result = newIndirect(qpdf, reserved.getObjGen());
2700 result.reserved = true; 2703 result.reserved = true;
2701 return result; 2704 return result;
2702 } 2705 }
@@ -2796,9 +2799,8 @@ QPDFObjectHandle::copyObject( @@ -2796,9 +2799,8 @@ QPDFObjectHandle::copyObject(
2796 " reserved object handle direct"); 2799 " reserved object handle direct");
2797 } 2800 }
2798 2801
2799 - this->qpdf = 0;  
2800 - this->objid = 0;  
2801 - this->generation = 0; 2802 + qpdf = nullptr;
  2803 + og = QPDFObjGen();
2802 2804
2803 std::shared_ptr<QPDFObject> new_obj; 2805 std::shared_ptr<QPDFObject> new_obj;
2804 2806
@@ -3112,7 +3114,7 @@ QPDFObjectHandle::dereference() @@ -3112,7 +3114,7 @@ QPDFObjectHandle::dereference()
3112 } 3114 }
3113 if (this->obj.get() == 0) { 3115 if (this->obj.get() == 0) {
3114 std::shared_ptr<QPDFObject> obj = 3116 std::shared_ptr<QPDFObject> obj =
3115 - QPDF::Resolver::resolve(this->qpdf, getObjectID(), getGeneration()); 3117 + QPDF::Resolver::resolve(this->qpdf, getObjGen());
3116 if (obj.get() == 0) { 3118 if (obj.get() == 0) {
3117 // QPDF::resolve never returns an uninitialized object, but 3119 // QPDF::resolve never returns an uninitialized object, but
3118 // check just in case. 3120 // check just in case.
libqpdf/QPDFPageObjectHelper.cc
@@ -21,8 +21,7 @@ namespace @@ -21,8 +21,7 @@ namespace
21 { 21 {
22 } 22 }
23 virtual ~ContentProvider() = default; 23 virtual ~ContentProvider() = default;
24 - virtual void  
25 - provideStreamData(int objid, int generation, Pipeline* pipeline); 24 + virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
26 25
27 private: 26 private:
28 QPDFObjectHandle from_page; 27 QPDFObjectHandle from_page;
@@ -30,12 +29,11 @@ namespace @@ -30,12 +29,11 @@ namespace
30 } // namespace 29 } // namespace
31 30
32 void 31 void
33 -ContentProvider::provideStreamData(int, int, Pipeline* p) 32 +ContentProvider::provideStreamData(QPDFObjGen const&, Pipeline* p)
34 { 33 {
35 Pl_Concatenate concat("concatenate", p); 34 Pl_Concatenate concat("concatenate", p);
36 - std::string description = "contents from page object " +  
37 - QUtil::int_to_string(from_page.getObjectID()) + " " +  
38 - QUtil::int_to_string(from_page.getGeneration()); 35 + std::string description =
  36 + "contents from page object " + from_page.getObjGen().unparse(' ');
39 std::string all_description; 37 std::string all_description;
40 from_page.getKey("/Contents") 38 from_page.getKey("/Contents")
41 .pipeContentStreams(&concat, description, all_description); 39 .pipeContentStreams(&concat, description, all_description);
libqpdf/QPDFWriter.cc
@@ -1990,9 +1990,8 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index) @@ -1990,9 +1990,8 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index)
1990 if (object_stream_index == -1) { 1990 if (object_stream_index == -1) {
1991 if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) { 1991 if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) {
1992 writeString( 1992 writeString(
1993 - "%% Original object ID: " +  
1994 - QUtil::int_to_string(object.getObjectID()) + " " +  
1995 - QUtil::int_to_string(object.getGeneration()) + "\n"); 1993 + "%% Original object ID: " + object.getObjGen().unparse(' ') +
  1994 + "\n");
1996 } 1995 }
1997 openObject(new_id); 1996 openObject(new_id);
1998 setDataKey(new_id); 1997 setDataKey(new_id);
libqpdf/QPDF_Stream.cc
@@ -110,14 +110,12 @@ StreamBlobProvider::operator()(Pipeline* p) @@ -110,14 +110,12 @@ StreamBlobProvider::operator()(Pipeline* p)
110 110
111 QPDF_Stream::QPDF_Stream( 111 QPDF_Stream::QPDF_Stream(
112 QPDF* qpdf, 112 QPDF* qpdf,
113 - int objid,  
114 - int generation, 113 + QPDFObjGen const& og,
115 QPDFObjectHandle stream_dict, 114 QPDFObjectHandle stream_dict,
116 qpdf_offset_t offset, 115 qpdf_offset_t offset,
117 size_t length) : 116 size_t length) :
118 qpdf(qpdf), 117 qpdf(qpdf),
119 - objid(objid),  
120 - generation(generation), 118 + og(og),
121 filter_on_write(true), 119 filter_on_write(true),
122 stream_dict(stream_dict), 120 stream_dict(stream_dict),
123 offset(offset), 121 offset(offset),
@@ -128,23 +126,18 @@ QPDF_Stream::QPDF_Stream( @@ -128,23 +126,18 @@ QPDF_Stream::QPDF_Stream(
128 "object for dictionary"); 126 "object for dictionary");
129 } 127 }
130 setDescription( 128 setDescription(
131 - this->qpdf,  
132 - this->qpdf->getFilename() + ", stream object " +  
133 - QUtil::int_to_string(this->objid) + " " +  
134 - QUtil::int_to_string(this->generation)); 129 + qpdf, qpdf->getFilename() + ", stream object " + og.unparse(' '));
135 } 130 }
136 131
137 std::shared_ptr<QPDFObject> 132 std::shared_ptr<QPDFObject>
138 QPDF_Stream::create( 133 QPDF_Stream::create(
139 QPDF* qpdf, 134 QPDF* qpdf,
140 - int objid,  
141 - int generation, 135 + QPDFObjGen const& og,
142 QPDFObjectHandle stream_dict, 136 QPDFObjectHandle stream_dict,
143 qpdf_offset_t offset, 137 qpdf_offset_t offset,
144 size_t length) 138 size_t length)
145 { 139 {
146 - return do_create(  
147 - new QPDF_Stream(qpdf, objid, generation, stream_dict, offset, length)); 140 + return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length));
148 } 141 }
149 142
150 std::shared_ptr<QPDFObject> 143 std::shared_ptr<QPDFObject>
@@ -181,23 +174,21 @@ QPDF_Stream::releaseResolved() @@ -181,23 +174,21 @@ QPDF_Stream::releaseResolved()
181 } 174 }
182 175
183 void 176 void
184 -QPDF_Stream::setObjGen(int objid, int generation) 177 +QPDF_Stream::setObjGen(QPDFObjGen const& og)
185 { 178 {
186 - if (!((this->objid == 0) && (this->generation == 0))) { 179 + if (this->og.isIndirect()) {
187 throw std::logic_error( 180 throw std::logic_error(
188 "attempt to set object ID and generation of a stream" 181 "attempt to set object ID and generation of a stream"
189 " that already has them"); 182 " that already has them");
190 } 183 }
191 - this->objid = objid;  
192 - this->generation = generation; 184 + this->og = og;
193 } 185 }
194 186
195 std::string 187 std::string
196 QPDF_Stream::unparse() 188 QPDF_Stream::unparse()
197 { 189 {
198 // Unparse stream objects as indirect references 190 // Unparse stream objects as indirect references
199 - return QUtil::int_to_string(this->objid) + " " +  
200 - QUtil::int_to_string(this->generation) + " R"; 191 + return og.unparse(' ') + " R";
201 } 192 }
202 193
203 JSON 194 JSON
@@ -619,17 +610,12 @@ QPDF_Stream::pipeStreamData( @@ -619,17 +610,12 @@ QPDF_Stream::pipeStreamData(
619 Pl_Count count("stream provider count", pipeline); 610 Pl_Count count("stream provider count", pipeline);
620 if (this->stream_provider->supportsRetry()) { 611 if (this->stream_provider->supportsRetry()) {
621 if (!this->stream_provider->provideStreamData( 612 if (!this->stream_provider->provideStreamData(
622 - this->objid,  
623 - this->generation,  
624 - &count,  
625 - suppress_warnings,  
626 - will_retry)) { 613 + og, &count, suppress_warnings, will_retry)) {
627 filter = false; 614 filter = false;
628 success = false; 615 success = false;
629 } 616 }
630 } else { 617 } else {
631 - this->stream_provider->provideStreamData(  
632 - this->objid, this->generation, &count); 618 + this->stream_provider->provideStreamData(og, &count);
633 } 619 }
634 qpdf_offset_t actual_length = count.getCount(); 620 qpdf_offset_t actual_length = count.getCount();
635 qpdf_offset_t desired_length = 0; 621 qpdf_offset_t desired_length = 0;
@@ -642,10 +628,8 @@ QPDF_Stream::pipeStreamData( @@ -642,10 +628,8 @@ QPDF_Stream::pipeStreamData(
642 // This would be caused by programmer error on the 628 // This would be caused by programmer error on the
643 // part of a library user, not by invalid input data. 629 // part of a library user, not by invalid input data.
644 throw std::runtime_error( 630 throw std::runtime_error(
645 - "stream data provider for " +  
646 - QUtil::int_to_string(this->objid) + " " +  
647 - QUtil::int_to_string(this->generation) + " provided " +  
648 - QUtil::int_to_string(actual_length) + 631 + "stream data provider for " + og.unparse(' ') +
  632 + " provided " + QUtil::int_to_string(actual_length) +
649 " bytes instead of expected " + 633 " bytes instead of expected " +
650 QUtil::int_to_string(desired_length) + " bytes"); 634 QUtil::int_to_string(desired_length) + " bytes");
651 } 635 }
@@ -661,8 +645,7 @@ QPDF_Stream::pipeStreamData( @@ -661,8 +645,7 @@ QPDF_Stream::pipeStreamData(
661 QTC::TC("qpdf", "QPDF_Stream pipe original stream data"); 645 QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
662 if (!QPDF::Pipe::pipeStreamData( 646 if (!QPDF::Pipe::pipeStreamData(
663 this->qpdf, 647 this->qpdf,
664 - this->objid,  
665 - this->generation, 648 + og,
666 this->offset, 649 this->offset,
667 this->length, 650 this->length,
668 this->stream_dict, 651 this->stream_dict,
libqpdf/QPDF_encryption.cc
@@ -1075,8 +1075,7 @@ QPDF::initializeEncryption() @@ -1075,8 +1075,7 @@ QPDF::initializeEncryption()
1075 std::string 1075 std::string
1076 QPDF::getKeyForObject( 1076 QPDF::getKeyForObject(
1077 std::shared_ptr<EncryptionParameters> encp, 1077 std::shared_ptr<EncryptionParameters> encp,
1078 - int objid,  
1079 - int generation, 1078 + QPDFObjGen const& og,
1080 bool use_aes) 1079 bool use_aes)
1081 { 1080 {
1082 if (!encp->encrypted) { 1081 if (!encp->encrypted) {
@@ -1084,26 +1083,24 @@ QPDF::getKeyForObject( @@ -1084,26 +1083,24 @@ QPDF::getKeyForObject(
1084 "request for encryption key in non-encrypted PDF"); 1083 "request for encryption key in non-encrypted PDF");
1085 } 1084 }
1086 1085
1087 - if (!((objid == encp->cached_key_objid) &&  
1088 - (generation == encp->cached_key_generation))) { 1086 + if (og != encp->cached_key_og) {
1089 encp->cached_object_encryption_key = compute_data_key( 1087 encp->cached_object_encryption_key = compute_data_key(
1090 encp->encryption_key, 1088 encp->encryption_key,
1091 - objid,  
1092 - generation, 1089 + og.getObj(),
  1090 + og.getGen(),
1093 use_aes, 1091 use_aes,
1094 encp->encryption_V, 1092 encp->encryption_V,
1095 encp->encryption_R); 1093 encp->encryption_R);
1096 - encp->cached_key_objid = objid;  
1097 - encp->cached_key_generation = generation; 1094 + encp->cached_key_og = og;
1098 } 1095 }
1099 1096
1100 return encp->cached_object_encryption_key; 1097 return encp->cached_object_encryption_key;
1101 } 1098 }
1102 1099
1103 void 1100 void
1104 -QPDF::decryptString(std::string& str, int objid, int generation) 1101 +QPDF::decryptString(std::string& str, QPDFObjGen const& og)
1105 { 1102 {
1106 - if (objid == 0) { 1103 + if (!og.isIndirect()) {
1107 return; 1104 return;
1108 } 1105 }
1109 bool use_aes = false; 1106 bool use_aes = false;
@@ -1139,8 +1136,7 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation) @@ -1139,8 +1136,7 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1139 } 1136 }
1140 } 1137 }
1141 1138
1142 - std::string key =  
1143 - getKeyForObject(this->m->encp, objid, generation, use_aes); 1139 + std::string key = getKeyForObject(this->m->encp, og, use_aes);
1144 try { 1140 try {
1145 if (use_aes) { 1141 if (use_aes) {
1146 QTC::TC("qpdf", "QPDF_encryption aes decode string"); 1142 QTC::TC("qpdf", "QPDF_encryption aes decode string");
@@ -1175,9 +1171,8 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation) @@ -1175,9 +1171,8 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1175 this->m->file->getName(), 1171 this->m->file->getName(),
1176 this->m->last_object_description, 1172 this->m->last_object_description,
1177 this->m->file->getLastOffset(), 1173 this->m->file->getLastOffset(),
1178 - "error decrypting string for object " +  
1179 - QUtil::int_to_string(objid) + " " +  
1180 - QUtil::int_to_string(generation) + ": " + e.what()); 1174 + "error decrypting string for object " + og.unparse() + ": " +
  1175 + e.what());
1181 } 1176 }
1182 } 1177 }
1183 1178
@@ -1187,8 +1182,7 @@ QPDF::decryptStream( @@ -1187,8 +1182,7 @@ QPDF::decryptStream(
1187 std::shared_ptr<InputSource> file, 1182 std::shared_ptr<InputSource> file,
1188 QPDF& qpdf_for_warning, 1183 QPDF& qpdf_for_warning,
1189 Pipeline*& pipeline, 1184 Pipeline*& pipeline,
1190 - int objid,  
1191 - int generation, 1185 + QPDFObjGen const& og,
1192 QPDFObjectHandle& stream_dict, 1186 QPDFObjectHandle& stream_dict,
1193 std::vector<std::shared_ptr<Pipeline>>& heap) 1187 std::vector<std::shared_ptr<Pipeline>>& heap)
1194 { 1188 {
@@ -1283,7 +1277,7 @@ QPDF::decryptStream( @@ -1283,7 +1277,7 @@ QPDF::decryptStream(
1283 break; 1277 break;
1284 } 1278 }
1285 } 1279 }
1286 - std::string key = getKeyForObject(encp, objid, generation, use_aes); 1280 + std::string key = getKeyForObject(encp, og, use_aes);
1287 std::shared_ptr<Pipeline> new_pipeline; 1281 std::shared_ptr<Pipeline> new_pipeline;
1288 if (use_aes) { 1282 if (use_aes) {
1289 QTC::TC("qpdf", "QPDF_encryption aes decode stream"); 1283 QTC::TC("qpdf", "QPDF_encryption aes decode stream");
libqpdf/QPDF_json.cc
@@ -371,9 +371,10 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value) @@ -371,9 +371,10 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value)
371 QPDFObjectHandle 371 QPDFObjectHandle
372 QPDF::JSONReactor::reserveObject(int obj, int gen) 372 QPDF::JSONReactor::reserveObject(int obj, int gen)
373 { 373 {
374 - auto oh = pdf.reserveObjectIfNotExists(obj, gen); 374 + QPDFObjGen og(obj, gen);
  375 + auto oh = pdf.reserveObjectIfNotExists(og);
375 if (oh.isReserved()) { 376 if (oh.isReserved()) {
376 - this->reserved.insert(QPDFObjGen(obj, gen)); 377 + this->reserved.insert(og);
377 } 378 }
378 return oh; 379 return oh;
379 } 380 }
@@ -495,8 +496,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -495,8 +496,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
495 QTC::TC("qpdf", "QPDF_json updating existing stream"); 496 QTC::TC("qpdf", "QPDF_json updating existing stream");
496 } else { 497 } else {
497 this->this_stream_needs_data = true; 498 this->this_stream_needs_data = true;
498 - replacement =  
499 - pdf.reserveStream(tos.getObjectID(), tos.getGeneration()); 499 + replacement = pdf.reserveStream(tos.getObjGen());
500 replaceObject(tos, replacement, value); 500 replaceObject(tos, replacement, value);
501 } 501 }
502 } else { 502 } else {
libqpdf/QPDF_linearization.cc
@@ -137,8 +137,8 @@ QPDF::isLinearized() @@ -137,8 +137,8 @@ QPDF::isLinearized()
137 return false; 137 return false;
138 } 138 }
139 139
140 - QPDFObjectHandle candidate =  
141 - QPDFObjectHandle::Factory::newIndirect(this, lindict_obj, 0); 140 + QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect(
  141 + this, QPDFObjGen(lindict_obj, 0));
142 if (!candidate.isDictionary()) { 142 if (!candidate.isDictionary()) {
143 return false; 143 return false;
144 } 144 }
@@ -325,11 +325,10 @@ QPDF::readLinearizationData() @@ -325,11 +325,10 @@ QPDF::readLinearizationData()
325 QPDFObjectHandle 325 QPDFObjectHandle
326 QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length) 326 QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
327 { 327 {
328 - int obj;  
329 - int gen; 328 + QPDFObjGen og;
330 QPDFObjectHandle H = readObjectAtOffset( 329 QPDFObjectHandle H = readObjectAtOffset(
331 - false, offset, "linearization hint stream", 0, 0, obj, gen);  
332 - ObjCache& oc = this->m->obj_cache[QPDFObjGen(obj, gen)]; 330 + false, offset, "linearization hint stream", QPDFObjGen(0, 0), og);
  331 + ObjCache& oc = this->m->obj_cache[og];
333 qpdf_offset_t min_end_offset = oc.end_before_space; 332 qpdf_offset_t min_end_offset = oc.end_before_space;
334 qpdf_offset_t max_end_offset = oc.end_after_space; 333 qpdf_offset_t max_end_offset = oc.end_after_space;
335 if (!H.isStream()) { 334 if (!H.isStream()) {
@@ -707,7 +706,7 @@ QPDF::getUncompressedObject( @@ -707,7 +706,7 @@ QPDF::getUncompressedObject(
707 return obj; 706 return obj;
708 } else { 707 } else {
709 int repl = (*(object_stream_data.find(obj.getObjectID()))).second; 708 int repl = (*(object_stream_data.find(obj.getObjectID()))).second;
710 - return objGenToIndirect(QPDFObjGen(repl, 0)); 709 + return getObjectByObjGen(QPDFObjGen(repl, 0));
711 } 710 }
712 } 711 }
713 712
@@ -1144,12 +1143,6 @@ QPDF::dumpHGeneric(HGeneric&amp; t) @@ -1144,12 +1143,6 @@ QPDF::dumpHGeneric(HGeneric&amp; t)
1144 << "group_length: " << t.group_length << "\n"; 1143 << "group_length: " << t.group_length << "\n";
1145 } 1144 }
1146 1145
1147 -QPDFObjectHandle  
1148 -QPDF::objGenToIndirect(QPDFObjGen const& og)  
1149 -{  
1150 - return getObjectByID(og.getObj(), og.getGen());  
1151 -}  
1152 -  
1153 void 1146 void
1154 QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data) 1147 QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
1155 { 1148 {
@@ -1388,9 +1381,9 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1388,9 +1381,9 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1388 stopOnError("found other than one root while" 1381 stopOnError("found other than one root while"
1389 " calculating linearization data"); 1382 " calculating linearization data");
1390 } 1383 }
1391 - this->m->part4.push_back(objGenToIndirect(*(lc_root.begin()))); 1384 + this->m->part4.push_back(getObjectByObjGen(*(lc_root.begin())));
1392 for (auto const& og: lc_open_document) { 1385 for (auto const& og: lc_open_document) {
1393 - this->m->part4.push_back(objGenToIndirect(og)); 1386 + this->m->part4.push_back(getObjectByObjGen(og));
1394 } 1387 }
1395 1388
1396 // Part 6: first page objects. Note: implementation note 124 1389 // Part 6: first page objects. Note: implementation note 124
@@ -1419,11 +1412,11 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1419,11 +1412,11 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1419 // hint tables. 1412 // hint tables.
1420 1413
1421 for (auto const& og: lc_first_page_private) { 1414 for (auto const& og: lc_first_page_private) {
1422 - this->m->part6.push_back(objGenToIndirect(og)); 1415 + this->m->part6.push_back(getObjectByObjGen(og));
1423 } 1416 }
1424 1417
1425 for (auto const& og: lc_first_page_shared) { 1418 for (auto const& og: lc_first_page_shared) {
1426 - this->m->part6.push_back(objGenToIndirect(og)); 1419 + this->m->part6.push_back(getObjectByObjGen(og));
1427 } 1420 }
1428 1421
1429 // Place the outline dictionary if it goes in the first page section. 1422 // Place the outline dictionary if it goes in the first page section.
@@ -1469,7 +1462,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1469,7 +1462,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1469 for (auto const& og: this->m->obj_user_to_objects[ou]) { 1462 for (auto const& og: this->m->obj_user_to_objects[ou]) {
1470 if (lc_other_page_private.count(og)) { 1463 if (lc_other_page_private.count(og)) {
1471 lc_other_page_private.erase(og); 1464 lc_other_page_private.erase(og);
1472 - this->m->part7.push_back(objGenToIndirect(og)); 1465 + this->m->part7.push_back(getObjectByObjGen(og));
1473 ++this->m->c_page_offset_data.entries.at(i).nobjects; 1466 ++this->m->c_page_offset_data.entries.at(i).nobjects;
1474 } 1467 }
1475 } 1468 }
@@ -1486,7 +1479,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1486,7 +1479,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1486 1479
1487 // Order is unimportant. 1480 // Order is unimportant.
1488 for (auto const& og: lc_other_page_shared) { 1481 for (auto const& og: lc_other_page_shared) {
1489 - this->m->part8.push_back(objGenToIndirect(og)); 1482 + this->m->part8.push_back(getObjectByObjGen(og));
1490 } 1483 }
1491 1484
1492 // Part 9: other objects 1485 // Part 9: other objects
@@ -1508,7 +1501,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1508,7 +1501,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1508 for (auto const& og: pages_ogs) { 1501 for (auto const& og: pages_ogs) {
1509 if (lc_other.count(og)) { 1502 if (lc_other.count(og)) {
1510 lc_other.erase(og); 1503 lc_other.erase(og);
1511 - this->m->part9.push_back(objGenToIndirect(og)); 1504 + this->m->part9.push_back(getObjectByObjGen(og));
1512 } 1505 }
1513 } 1506 }
1514 1507
@@ -1538,7 +1531,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1538,7 +1531,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1538 for (auto const& og: ogs) { 1531 for (auto const& og: ogs) {
1539 if (lc_thumbnail_private.count(og)) { 1532 if (lc_thumbnail_private.count(og)) {
1540 lc_thumbnail_private.erase(og); 1533 lc_thumbnail_private.erase(og);
1541 - this->m->part9.push_back(objGenToIndirect(og)); 1534 + this->m->part9.push_back(getObjectByObjGen(og));
1542 } 1535 }
1543 } 1536 }
1544 } 1537 }
@@ -1551,7 +1544,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1551,7 +1544,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1551 1544
1552 // Place shared thumbnail objects 1545 // Place shared thumbnail objects
1553 for (auto const& og: lc_thumbnail_shared) { 1546 for (auto const& og: lc_thumbnail_shared) {
1554 - this->m->part9.push_back(objGenToIndirect(og)); 1547 + this->m->part9.push_back(getObjectByObjGen(og));
1555 } 1548 }
1556 1549
1557 // Place outlines unless in first page 1550 // Place outlines unless in first page
@@ -1561,7 +1554,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data) @@ -1561,7 +1554,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1561 1554
1562 // Place all remaining objects 1555 // Place all remaining objects
1563 for (auto const& og: lc_other) { 1556 for (auto const& og: lc_other) {
1564 - this->m->part9.push_back(objGenToIndirect(og)); 1557 + this->m->part9.push_back(getObjectByObjGen(og));
1565 } 1558 }
1566 1559
1567 // Make sure we got everything exactly once. 1560 // Make sure we got everything exactly once.
@@ -1663,7 +1656,7 @@ QPDF::pushOutlinesToPart( @@ -1663,7 +1656,7 @@ QPDF::pushOutlinesToPart(
1663 lc_outlines.erase(outlines_og); 1656 lc_outlines.erase(outlines_og);
1664 part.push_back(outlines); 1657 part.push_back(outlines);
1665 for (auto const& og: lc_outlines) { 1658 for (auto const& og: lc_outlines) {
1666 - part.push_back(objGenToIndirect(og)); 1659 + part.push_back(getObjectByObjGen(og));
1667 ++this->m->c_outline_data.nobjects; 1660 ++this->m->c_outline_data.nobjects;
1668 } 1661 }
1669 } 1662 }
libqpdf/QPDF_optimization.cc
@@ -252,9 +252,7 @@ QPDF::pushInheritedAttributesToPageInternal( @@ -252,9 +252,7 @@ QPDF::pushInheritedAttributesToPageInternal(
252 if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) { 252 if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) {
253 QTC::TC("qpdf", "QPDF unknown key not inherited"); 253 QTC::TC("qpdf", "QPDF unknown key not inherited");
254 setLastObjectDescription( 254 setLastObjectDescription(
255 - "Pages object",  
256 - cur_pages.getObjectID(),  
257 - cur_pages.getGeneration()); 255 + "Pages object", cur_pages.getObjGen());
258 warn( 256 warn(
259 qpdf_e_pages, 257 qpdf_e_pages,
260 this->m->last_object_description, 258 this->m->last_object_description,
libqpdf/QPDF_pages.cc
@@ -207,8 +207,7 @@ QPDF::insertPageobjToPage( @@ -207,8 +207,7 @@ QPDF::insertPageobjToPage(
207 // that causes this to happen. 207 // that causes this to happen.
208 setLastObjectDescription( 208 setLastObjectDescription(
209 "page " + QUtil::int_to_string(pos) + " (numbered from zero)", 209 "page " + QUtil::int_to_string(pos) + " (numbered from zero)",
210 - og.getObj(),  
211 - og.getGen()); 210 + og);
212 throw QPDFExc( 211 throw QPDFExc(
213 qpdf_e_pages, 212 qpdf_e_pages,
214 this->m->file->getName(), 213 this->m->file->getName(),
@@ -334,7 +333,7 @@ QPDF::findPage(QPDFObjGen const&amp; og) @@ -334,7 +333,7 @@ QPDF::findPage(QPDFObjGen const&amp; og)
334 auto it = this->m->pageobj_to_pages_pos.find(og); 333 auto it = this->m->pageobj_to_pages_pos.find(og);
335 if (it == this->m->pageobj_to_pages_pos.end()) { 334 if (it == this->m->pageobj_to_pages_pos.end()) {
336 QTC::TC("qpdf", "QPDF_pages findPage not found"); 335 QTC::TC("qpdf", "QPDF_pages findPage not found");
337 - setLastObjectDescription("page object", og.getObj(), og.getGen()); 336 + setLastObjectDescription("page object", og);
338 throw QPDFExc( 337 throw QPDFExc(
339 qpdf_e_pages, 338 qpdf_e_pages,
340 this->m->file->getName(), 339 this->m->file->getName(),
libqpdf/qpdf/QPDF_Stream.hh
@@ -19,8 +19,7 @@ class QPDF_Stream: public QPDFObject @@ -19,8 +19,7 @@ class QPDF_Stream: public QPDFObject
19 virtual ~QPDF_Stream() = default; 19 virtual ~QPDF_Stream() = default;
20 static std::shared_ptr<QPDFObject> create( 20 static std::shared_ptr<QPDFObject> create(
21 QPDF*, 21 QPDF*,
22 - int objid,  
23 - int generation, 22 + QPDFObjGen const& og,
24 QPDFObjectHandle stream_dict, 23 QPDFObjectHandle stream_dict,
25 qpdf_offset_t offset, 24 qpdf_offset_t offset,
26 size_t length); 25 size_t length);
@@ -78,7 +77,7 @@ class QPDF_Stream: public QPDFObject @@ -78,7 +77,7 @@ class QPDF_Stream: public QPDFObject
78 // Replace object ID and generation. This may only be called if 77 // Replace object ID and generation. This may only be called if
79 // object ID and generation are 0. It is used by QPDFObjectHandle 78 // object ID and generation are 0. It is used by QPDFObjectHandle
80 // when adding streams to files. 79 // when adding streams to files.
81 - void setObjGen(int objid, int generation); 80 + void setObjGen(QPDFObjGen const& og);
82 81
83 protected: 82 protected:
84 virtual void releaseResolved(); 83 virtual void releaseResolved();
@@ -86,8 +85,7 @@ class QPDF_Stream: public QPDFObject @@ -86,8 +85,7 @@ class QPDF_Stream: public QPDFObject
86 private: 85 private:
87 QPDF_Stream( 86 QPDF_Stream(
88 QPDF*, 87 QPDF*,
89 - int objid,  
90 - int generation, 88 + QPDFObjGen const& og,
91 QPDFObjectHandle stream_dict, 89 QPDFObjectHandle stream_dict,
92 qpdf_offset_t offset, 90 qpdf_offset_t offset,
93 size_t length); 91 size_t length);
@@ -111,8 +109,7 @@ class QPDF_Stream: public QPDFObject @@ -111,8 +109,7 @@ class QPDF_Stream: public QPDFObject
111 void setDictDescription(); 109 void setDictDescription();
112 110
113 QPDF* qpdf; 111 QPDF* qpdf;
114 - int objid;  
115 - int generation; 112 + QPDFObjGen og;
116 bool filter_on_write; 113 bool filter_on_write;
117 QPDFObjectHandle stream_dict; 114 QPDFObjectHandle stream_dict;
118 qpdf_offset_t offset; 115 qpdf_offset_t offset;
qpdf/test_driver.cc
@@ -56,6 +56,8 @@ class Provider: public QPDFObjectHandle::StreamDataProvider @@ -56,6 +56,8 @@ class Provider: public QPDFObjectHandle::StreamDataProvider
56 virtual void 56 virtual void
57 provideStreamData(int objid, int generation, Pipeline* p) 57 provideStreamData(int objid, int generation, Pipeline* p)
58 { 58 {
  59 + // Don't change signature to use QPDFObjGen const& to detect
  60 + // problems forwarding to legacy implementations.
59 p->write(b->getBuffer(), b->getSize()); 61 p->write(b->getBuffer(), b->getSize());
60 if (this->bad_length) { 62 if (this->bad_length) {
61 unsigned char ch = ' '; 63 unsigned char ch = ' ';