Commit f7978db1f604083c16733952d2b01d3b0f4b0a6a

Authored by m-holger
1 parent 3404ca8a

QPDFObjGen : tidy QPDF private methods

Change method signatures to use QPDFObjGen.
Use QPDFObjGen methods where possible.
Remove redundant QPDF::objGenToIndirect.
include/qpdf/QPDF.hh
... ... @@ -815,9 +815,9 @@ class QPDF
815 815  
816 816 private:
817 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 822 static bool
823 823 objectChanged(
... ... @@ -879,8 +879,7 @@ class QPDF
879 879 static bool
880 880 pipeStreamData(
881 881 QPDF* qpdf,
882   - int objid,
883   - int generation,
  882 + QPDFObjGen const& og,
884 883 qpdf_offset_t offset,
885 884 size_t length,
886 885 QPDFObjectHandle dict,
... ... @@ -889,8 +888,7 @@ class QPDF
889 888 bool will_retry)
890 889 {
891 890 return qpdf->pipeStreamData(
892   - objid,
893   - generation,
  891 + og,
894 892 offset,
895 893 length,
896 894 dict,
... ... @@ -959,8 +957,7 @@ class QPDF
959 957 std::string user_password;
960 958 std::string encryption_key;
961 959 std::string cached_object_encryption_key;
962   - int cached_key_objid;
963   - int cached_key_generation;
  960 + QPDFObjGen cached_key_og;
964 961 bool user_password_matched;
965 962 bool owner_password_matched;
966 963 };
... ... @@ -973,8 +970,7 @@ class QPDF
973 970 ForeignStreamData(
974 971 std::shared_ptr<EncryptionParameters> encp,
975 972 std::shared_ptr<InputSource> file,
976   - int foreign_objid,
977   - int foreign_generation,
  973 + QPDFObjGen const& foreign_og,
978 974 qpdf_offset_t offset,
979 975 size_t length,
980 976 QPDFObjectHandle local_dict);
... ... @@ -982,8 +978,7 @@ class QPDF
982 978 private:
983 979 std::shared_ptr<EncryptionParameters> encp;
984 980 std::shared_ptr<InputSource> file;
985   - int foreign_objid;
986   - int foreign_generation;
  981 + QPDFObjGen foreign_og;
987 982 qpdf_offset_t offset;
988 983 size_t length;
989 984 QPDFObjectHandle local_dict;
... ... @@ -1017,14 +1012,13 @@ class QPDF
1017 1012 friend class QPDF;
1018 1013  
1019 1014 public:
1020   - StringDecrypter(QPDF* qpdf, int objid, int gen);
  1015 + StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
1021 1016 virtual ~StringDecrypter() = default;
1022 1017 virtual void decryptString(std::string& val);
1023 1018  
1024 1019 private:
1025 1020 QPDF* qpdf;
1026   - int objid;
1027   - int gen;
  1021 + QPDFObjGen og;
1028 1022 };
1029 1023  
1030 1024 class ResolveRecorder
... ... @@ -1127,17 +1121,15 @@ class QPDF
1127 1121 void insertXrefEntry(
1128 1122 int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
1129 1123 void setLastObjectDescription(
1130   - std::string const& description, int objid, int generation);
  1124 + std::string const& description, QPDFObjGen const& og);
1131 1125 QPDFObjectHandle readObject(
1132 1126 std::shared_ptr<InputSource>,
1133 1127 std::string const& description,
1134   - int objid,
1135   - int generation,
  1128 + QPDFObjGen const& og,
1136 1129 bool in_object_stream);
1137 1130 size_t recoverStreamLength(
1138 1131 std::shared_ptr<InputSource> input,
1139   - int objid,
1140   - int generation,
  1132 + QPDFObjGen const& og,
1141 1133 qpdf_offset_t stream_offset);
1142 1134 QPDFTokenizer::Token
1143 1135 readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
... ... @@ -1149,16 +1141,15 @@ class QPDF
1149 1141 QPDFObjGen const& exp_og,
1150 1142 QPDFObjGen& og);
1151 1143 bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph);
1152   - std::shared_ptr<QPDFObject> resolve(int objid, int generation);
  1144 + std::shared_ptr<QPDFObject> resolve(QPDFObjGen const& og);
1153 1145 void resolveObjectsInStream(int obj_stream_number);
1154 1146 void stopOnError(std::string const& message);
1155   - QPDFObjectHandle reserveObjectIfNotExists(int objid, int gen);
1156   - QPDFObjectHandle reserveStream(int objid, int gen);
  1147 + QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
  1148 + QPDFObjectHandle reserveStream(QPDFObjGen const& og);
1157 1149  
1158 1150 // Calls finish() on the pipeline when done but does not delete it
1159 1151 bool pipeStreamData(
1160   - int objid,
1161   - int generation,
  1152 + QPDFObjGen const& og,
1162 1153 qpdf_offset_t offset,
1163 1154 size_t length,
1164 1155 QPDFObjectHandle dict,
... ... @@ -1174,8 +1165,7 @@ class QPDF
1174 1165 std::shared_ptr<QPDF::EncryptionParameters> encp,
1175 1166 std::shared_ptr<InputSource> file,
1176 1167 QPDF& qpdf_for_warning,
1177   - int objid,
1178   - int generation,
  1168 + QPDFObjGen const& og,
1179 1169 qpdf_offset_t offset,
1180 1170 size_t length,
1181 1171 QPDFObjectHandle dict,
... ... @@ -1228,10 +1218,9 @@ class QPDF
1228 1218 void initializeEncryption();
1229 1219 static std::string getKeyForObject(
1230 1220 std::shared_ptr<EncryptionParameters> encp,
1231   - int objid,
1232   - int generation,
  1221 + QPDFObjGen const& og,
1233 1222 bool use_aes);
1234   - void decryptString(std::string&, int objid, int generation);
  1223 + void decryptString(std::string&, QPDFObjGen const& og);
1235 1224 static std::string compute_encryption_key_from_password(
1236 1225 std::string const& password, EncryptionData const& data);
1237 1226 static std::string recover_encryption_key_with_password(
... ... @@ -1245,8 +1234,7 @@ class QPDF
1245 1234 std::shared_ptr<InputSource> file,
1246 1235 QPDF& qpdf_for_warning,
1247 1236 Pipeline*& pipeline,
1248   - int objid,
1249   - int generation,
  1237 + QPDFObjGen const& og,
1250 1238 QPDFObjectHandle& stream_dict,
1251 1239 std::vector<std::shared_ptr<Pipeline>>& heap);
1252 1240  
... ... @@ -1569,7 +1557,6 @@ class QPDF
1569 1557 void dumpHSharedObject();
1570 1558 void dumpHGeneric(HGeneric&);
1571 1559 qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
1572   - QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
1573 1560 void
1574 1561 calculateLinearizationData(std::map<int, int> const& object_stream_data);
1575 1562 void pushOutlinesToPart(
... ...
libqpdf/QPDF.cc
... ... @@ -113,15 +113,13 @@ namespace
113 113 QPDF::ForeignStreamData::ForeignStreamData(
114 114 std::shared_ptr<EncryptionParameters> encp,
115 115 std::shared_ptr<InputSource> file,
116   - int foreign_objid,
117   - int foreign_generation,
  116 + QPDFObjGen const& foreign_og,
118 117 qpdf_offset_t offset,
119 118 size_t length,
120 119 QPDFObjectHandle local_dict) :
121 120 encp(encp),
122 121 file(file),
123   - foreign_objid(foreign_objid),
124   - foreign_generation(foreign_generation),
  122 + foreign_og(foreign_og),
125 123 offset(offset),
126 124 length(length),
127 125 local_dict(local_dict)
... ... @@ -176,17 +174,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream(
176 174 this->foreign_stream_data[local_og] = foreign_stream;
177 175 }
178 176  
179   -QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, int objid, int gen) :
  177 +QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) :
180 178 qpdf(qpdf),
181   - objid(objid),
182   - gen(gen)
  179 + og(og)
183 180 {
184 181 }
185 182  
186 183 void
187 184 QPDF::StringDecrypter::decryptString(std::string& val)
188 185 {
189   - qpdf->decryptString(val, objid, gen);
  186 + qpdf->decryptString(val, og);
190 187 }
191 188  
192 189 std::string const&
... ... @@ -205,8 +202,6 @@ QPDF::EncryptionParameters::EncryptionParameters() :
205 202 cf_stream(e_none),
206 203 cf_string(e_none),
207 204 cf_file(e_none),
208   - cached_key_objid(0),
209   - cached_key_generation(0),
210 205 user_password_matched(false),
211 206 owner_password_matched(false)
212 207 {
... ... @@ -631,7 +626,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
631 626 (!this->m->trailer.isInitialized()) &&
632 627 (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) {
633 628 QPDFObjectHandle t =
634   - readObject(this->m->file, "trailer", 0, 0, false);
  629 + readObject(this->m->file, "trailer", QPDFObjGen(), false);
635 630 if (!t.isDictionary()) {
636 631 // Oh well. It was worth a try.
637 632 } else {
... ... @@ -969,7 +964,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
969 964  
970 965 // Set offset to previous xref table if any
971 966 QPDFObjectHandle cur_trailer =
972   - readObject(this->m->file, "trailer", 0, 0, false);
  967 + readObject(this->m->file, "trailer", QPDFObjGen(), false);
973 968 if (!cur_trailer.isDictionary()) {
974 969 QTC::TC("qpdf", "QPDF missing trailer");
975 970 throw QPDFExc(
... ... @@ -1341,7 +1336,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
1341 1336 break;
1342 1337  
1343 1338 case 2:
1344   - this->m->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2);
  1339 + this->m->xref_table[QPDFObjGen(obj)] = QPDFXRefEntry(f0, f1, f2);
1345 1340 break;
1346 1341  
1347 1342 default:
... ... @@ -1362,7 +1357,7 @@ QPDF::showXRefTable()
1362 1357 for (auto const& iter: this->m->xref_table) {
1363 1358 QPDFObjGen const& og = iter.first;
1364 1359 QPDFXRefEntry const& entry = iter.second;
1365   - cout << og.getObj() << "/" << og.getGen() << ": ";
  1360 + cout << og.unparse('/') << ": ";
1366 1361 switch (entry.getType()) {
1367 1362 case 1:
1368 1363 cout << "uncompressed; offset = " << entry.getOffset();
... ... @@ -1478,18 +1473,17 @@ QPDF::getAllObjects()
1478 1473  
1479 1474 void
1480 1475 QPDF::setLastObjectDescription(
1481   - std::string const& description, int objid, int generation)
  1476 + std::string const& description, QPDFObjGen const& og)
1482 1477 {
1483 1478 this->m->last_object_description.clear();
1484 1479 if (!description.empty()) {
1485 1480 this->m->last_object_description += description;
1486   - if (objid > 0) {
  1481 + if (og.isIndirect()) {
1487 1482 this->m->last_object_description += ": ";
1488 1483 }
1489 1484 }
1490   - if (objid > 0) {
1491   - this->m->last_object_description +=
1492   - "object " + QPDFObjGen(objid, generation).unparse(' ');
  1485 + if (og.isIndirect()) {
  1486 + this->m->last_object_description += "object " + og.unparse(' ');
1493 1487 }
1494 1488 }
1495 1489  
... ... @@ -1497,19 +1491,17 @@ QPDFObjectHandle
1497 1491 QPDF::readObject(
1498 1492 std::shared_ptr<InputSource> input,
1499 1493 std::string const& description,
1500   - int objid,
1501   - int generation,
  1494 + QPDFObjGen const& og,
1502 1495 bool in_object_stream)
1503 1496 {
1504   - setLastObjectDescription(description, objid, generation);
  1497 + setLastObjectDescription(description, og);
1505 1498 qpdf_offset_t offset = input->tell();
1506 1499  
1507 1500 bool empty = false;
1508 1501 std::shared_ptr<StringDecrypter> decrypter_ph;
1509 1502 StringDecrypter* decrypter = 0;
1510 1503 if (this->m->encp->encrypted && (!in_object_stream)) {
1511   - decrypter_ph =
1512   - std::make_shared<StringDecrypter>(this, objid, generation);
  1504 + decrypter_ph = std::make_shared<StringDecrypter>(this, og);
1513 1505 decrypter = decrypter_ph.get();
1514 1506 }
1515 1507 QPDFObjectHandle object = QPDFObjectHandle::parse(
... ... @@ -1651,18 +1643,13 @@ QPDF::readObject(
1651 1643 } catch (QPDFExc& e) {
1652 1644 if (this->m->attempt_recovery) {
1653 1645 warn(e);
1654   - length = recoverStreamLength(
1655   - input, objid, generation, stream_offset);
  1646 + length = recoverStreamLength(input, og, stream_offset);
1656 1647 } else {
1657 1648 throw e;
1658 1649 }
1659 1650 }
1660 1651 object = QPDFObjectHandle::Factory::newStream(
1661   - this,
1662   - QPDFObjGen(objid, generation),
1663   - object,
1664   - stream_offset,
1665   - length);
  1652 + this, og, object, stream_offset, length);
1666 1653 } else {
1667 1654 input->seek(cur_offset, SEEK_SET);
1668 1655 }
... ... @@ -1690,8 +1677,7 @@ QPDF::findEndstream()
1690 1677 size_t
1691 1678 QPDF::recoverStreamLength(
1692 1679 std::shared_ptr<InputSource> input,
1693   - int objid,
1694   - int generation,
  1680 + QPDFObjGen const& og,
1695 1681 qpdf_offset_t stream_offset)
1696 1682 {
1697 1683 // Try to reconstruct stream length by looking for
... ... @@ -1716,11 +1702,10 @@ QPDF::recoverStreamLength(
1716 1702  
1717 1703 if (length) {
1718 1704 qpdf_offset_t this_obj_offset = 0;
1719   - QPDFObjGen this_obj(0, 0);
  1705 + QPDFObjGen this_og;
1720 1706  
1721 1707 // Make sure this is inside this object
1722 1708 for (auto const& iter: this->m->xref_table) {
1723   - QPDFObjGen const& og = iter.first;
1724 1709 QPDFXRefEntry const& entry = iter.second;
1725 1710 if (entry.getType() == 1) {
1726 1711 qpdf_offset_t obj_offset = entry.getOffset();
... ... @@ -1728,12 +1713,11 @@ QPDF::recoverStreamLength(
1728 1713 ((this_obj_offset == 0) ||
1729 1714 (this_obj_offset > obj_offset))) {
1730 1715 this_obj_offset = obj_offset;
1731   - this_obj = og;
  1716 + this_og = iter.first;
1732 1717 }
1733 1718 }
1734 1719 }
1735   - if (this_obj_offset && (this_obj.getObj() == objid) &&
1736   - (this_obj.getGen() == generation)) {
  1720 + if (this_obj_offset && (this_og == og)) {
1737 1721 // Well, we found endstream\nendobj within the space
1738 1722 // allowed for this object, so we're probably in good
1739 1723 // shape.
... ... @@ -1791,7 +1775,7 @@ QPDF::readObjectAtOffset(
1791 1775 check_og = false;
1792 1776 try_recovery = false;
1793 1777 } else {
1794   - setLastObjectDescription(description, exp_og.getObj(), exp_og.getGen());
  1778 + setLastObjectDescription(description, exp_og);
1795 1779 }
1796 1780  
1797 1781 if (!this->m->attempt_recovery) {
... ... @@ -1895,8 +1879,7 @@ QPDF::readObjectAtOffset(
1895 1879 }
1896 1880 }
1897 1881  
1898   - QPDFObjectHandle oh =
1899   - readObject(this->m->file, description, og.getObj(), og.getGen(), false);
  1882 + QPDFObjectHandle oh = readObject(this->m->file, description, og, false);
1900 1883  
1901 1884 if (!(readToken(this->m->file) ==
1902 1885 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) {
... ... @@ -1972,12 +1955,11 @@ QPDF::objectChanged(QPDFObjGen const&amp; og, std::shared_ptr&lt;QPDFObject&gt;&amp; oph)
1972 1955 }
1973 1956  
1974 1957 std::shared_ptr<QPDFObject>
1975   -QPDF::resolve(int objid, int generation)
  1958 +QPDF::resolve(QPDFObjGen const& og)
1976 1959 {
1977 1960 // Check object cache before checking xref table. This allows us
1978 1961 // to insert things into the object cache that don't actually
1979 1962 // exist in the file.
1980   - QPDFObjGen og(objid, generation);
1981 1963 if (this->m->resolving.count(og)) {
1982 1964 // This can happen if an object references itself directly or
1983 1965 // indirectly in some key that has to be resolved during
... ... @@ -2131,13 +2113,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
2131 2113 // xref table and only cache what would actually be resolved here.
2132 2114 for (auto const& iter: offsets) {
2133 2115 int obj = iter.first;
2134   - QPDFObjGen og(obj, 0);
  2116 + QPDFObjGen og(obj);
2135 2117 QPDFXRefEntry const& entry = this->m->xref_table[og];
2136 2118 if ((entry.getType() == 2) &&
2137 2119 (entry.getObjStreamNumber() == obj_stream_number)) {
2138 2120 int offset = iter.second;
2139 2121 input->seek(offset, SEEK_SET);
2140   - QPDFObjectHandle oh = readObject(input, "", obj, 0, true);
  2122 + QPDFObjectHandle oh = readObject(input, "", og, true);
2141 2123 this->m->obj_cache[og] = ObjCache(
2142 2124 QPDFObjectHandle::ObjAccessor::getObject(oh),
2143 2125 end_before_space,
... ... @@ -2163,21 +2145,20 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh)
2163 2145 }
2164 2146  
2165 2147 QPDFObjectHandle
2166   -QPDF::reserveObjectIfNotExists(int objid, int gen)
  2148 +QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
2167 2149 {
2168   - QPDFObjGen og(objid, gen);
2169 2150 if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) {
2170   - resolve(objid, gen);
2171   - replaceObject(objid, gen, QPDFObjectHandle::Factory::makeReserved());
  2151 + resolve(og);
  2152 + replaceObject(og, QPDFObjectHandle::Factory::makeReserved());
2172 2153 }
2173   - return getObjectByID(objid, gen);
  2154 + return getObjectByObjGen(og);
2174 2155 }
2175 2156  
2176 2157 QPDFObjectHandle
2177   -QPDF::reserveStream(int objid, int gen)
  2158 +QPDF::reserveStream(QPDFObjGen const& og)
2178 2159 {
2179 2160 return QPDFObjectHandle::Factory::newStream(
2180   - this, QPDFObjGen(objid, gen), QPDFObjectHandle::newDictionary(), 0, 0);
  2161 + this, og, QPDFObjectHandle::newDictionary(), 0, 0);
2181 2162 }
2182 2163  
2183 2164 QPDFObjectHandle
... ... @@ -2193,13 +2174,13 @@ QPDF::getObjectByID(int objid, int generation)
2193 2174 }
2194 2175  
2195 2176 void
2196   -QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
  2177 +QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2197 2178 {
2198   - replaceObject(og.getObj(), og.getGen(), oh);
  2179 + replaceObject(QPDFObjGen(objid, generation), oh);
2199 2180 }
2200 2181  
2201 2182 void
2202   -QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
  2183 +QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
2203 2184 {
2204 2185 if (oh.isIndirect()) {
2205 2186 QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
... ... @@ -2208,10 +2189,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2208 2189 }
2209 2190  
2210 2191 // Force new object to appear in the cache
2211   - resolve(objid, generation);
  2192 + resolve(og);
2212 2193  
2213 2194 // Replace the object in the object cache
2214   - QPDFObjGen og(objid, generation);
2215 2195 this->m->ever_replaced_objects = true;
2216 2196 this->m->obj_cache[og] =
2217 2197 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
... ... @@ -2511,8 +2491,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2511 2491 auto foreign_stream_data = std::make_shared<ForeignStreamData>(
2512 2492 foreign_stream_qpdf->m->encp,
2513 2493 foreign_stream_qpdf->m->file,
2514   - foreign.getObjectID(),
2515   - foreign.getGeneration(),
  2494 + foreign.getObjGen(),
2516 2495 stream->getOffset(),
2517 2496 stream->getLength(),
2518 2497 dict);
... ... @@ -2526,20 +2505,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2526 2505 }
2527 2506  
2528 2507 void
2529   -QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
  2508 +QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
2530 2509 {
2531   - swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen());
  2510 + swapObjects(
  2511 + QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2));
2532 2512 }
2533 2513  
2534 2514 void
2535   -QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
  2515 +QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
2536 2516 {
2537 2517 // Force objects to be loaded into cache; then swap them in the
2538 2518 // cache.
2539   - resolve(objid1, generation1);
2540   - resolve(objid2, generation2);
2541   - QPDFObjGen og1(objid1, generation1);
2542   - QPDFObjGen og2(objid2, generation2);
  2519 + resolve(og1);
  2520 + resolve(og2);
2543 2521 ObjCache t = this->m->obj_cache[og1];
2544 2522 this->m->ever_replaced_objects = true;
2545 2523 this->m->obj_cache[og1] = this->m->obj_cache[og2];
... ... @@ -2723,8 +2701,7 @@ QPDF::pipeStreamData(
2723 2701 std::shared_ptr<EncryptionParameters> encp,
2724 2702 std::shared_ptr<InputSource> file,
2725 2703 QPDF& qpdf_for_warning,
2726   - int objid,
2727   - int generation,
  2704 + QPDFObjGen const& og,
2728 2705 qpdf_offset_t offset,
2729 2706 size_t length,
2730 2707 QPDFObjectHandle stream_dict,
... ... @@ -2735,14 +2712,7 @@ QPDF::pipeStreamData(
2735 2712 std::vector<std::shared_ptr<Pipeline>> to_delete;
2736 2713 if (encp->encrypted) {
2737 2714 decryptStream(
2738   - encp,
2739   - file,
2740   - qpdf_for_warning,
2741   - pipeline,
2742   - objid,
2743   - generation,
2744   - stream_dict,
2745   - to_delete);
  2715 + encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete);
2746 2716 }
2747 2717  
2748 2718 bool success = false;
... ... @@ -2780,8 +2750,7 @@ QPDF::pipeStreamData(
2780 2750 "",
2781 2751 file->getLastOffset(),
2782 2752 ("error decoding stream data for object " +
2783   - QPDFObjGen(objid, generation).unparse(' ') + ": " +
2784   - e.what())));
  2753 + og.unparse(' ') + ": " + e.what())));
2785 2754 if (will_retry) {
2786 2755 qpdf_for_warning.warn(
2787 2756 // line-break
... ... @@ -2807,8 +2776,7 @@ QPDF::pipeStreamData(
2807 2776  
2808 2777 bool
2809 2778 QPDF::pipeStreamData(
2810   - int objid,
2811   - int generation,
  2779 + QPDFObjGen const& og,
2812 2780 qpdf_offset_t offset,
2813 2781 size_t length,
2814 2782 QPDFObjectHandle stream_dict,
... ... @@ -2820,8 +2788,7 @@ QPDF::pipeStreamData(
2820 2788 this->m->encp,
2821 2789 this->m->file,
2822 2790 *this,
2823   - objid,
2824   - generation,
  2791 + og,
2825 2792 offset,
2826 2793 length,
2827 2794 stream_dict,
... ... @@ -2844,8 +2811,7 @@ QPDF::pipeForeignStreamData(
2844 2811 foreign->encp,
2845 2812 foreign->file,
2846 2813 *this,
2847   - foreign->foreign_objid,
2848   - foreign->foreign_generation,
  2814 + foreign->foreign_og,
2849 2815 foreign->offset,
2850 2816 foreign->length,
2851 2817 foreign->local_dict,
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -3098,7 +3098,7 @@ QPDFObjectHandle::dereference()
3098 3098 }
3099 3099 if (this->obj.get() == 0) {
3100 3100 std::shared_ptr<QPDFObject> obj =
3101   - QPDF::Resolver::resolve(this->qpdf, getObjectID(), getGeneration());
  3101 + QPDF::Resolver::resolve(this->qpdf, getObjGen());
3102 3102 if (obj.get() == 0) {
3103 3103 // QPDF::resolve never returns an uninitialized object, but
3104 3104 // check just in case.
... ...
libqpdf/QPDF_Stream.cc
... ... @@ -658,8 +658,7 @@ QPDF_Stream::pipeStreamData(
658 658 QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
659 659 if (!QPDF::Pipe::pipeStreamData(
660 660 this->qpdf,
661   - this->objid,
662   - this->generation,
  661 + QPDFObjGen(this->objid, this->generation),
663 662 this->offset,
664 663 this->length,
665 664 this->stream_dict,
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -1075,8 +1075,7 @@ QPDF::initializeEncryption()
1075 1075 std::string
1076 1076 QPDF::getKeyForObject(
1077 1077 std::shared_ptr<EncryptionParameters> encp,
1078   - int objid,
1079   - int generation,
  1078 + QPDFObjGen const& og,
1080 1079 bool use_aes)
1081 1080 {
1082 1081 if (!encp->encrypted) {
... ... @@ -1084,26 +1083,24 @@ QPDF::getKeyForObject(
1084 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 1087 encp->cached_object_encryption_key = compute_data_key(
1090 1088 encp->encryption_key,
1091   - objid,
1092   - generation,
  1089 + og.getObj(),
  1090 + og.getGen(),
1093 1091 use_aes,
1094 1092 encp->encryption_V,
1095 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 1097 return encp->cached_object_encryption_key;
1101 1098 }
1102 1099  
1103 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 1104 return;
1108 1105 }
1109 1106 bool use_aes = false;
... ... @@ -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 1140 try {
1145 1141 if (use_aes) {
1146 1142 QTC::TC("qpdf", "QPDF_encryption aes decode string");
... ... @@ -1175,8 +1171,8 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1175 1171 this->m->file->getName(),
1176 1172 this->m->last_object_description,
1177 1173 this->m->file->getLastOffset(),
1178   - "error decrypting string for object " +
1179   - QPDFObjGen(objid, generation).unparse() + ": " + e.what());
  1174 + "error decrypting string for object " + og.unparse() + ": " +
  1175 + e.what());
1180 1176 }
1181 1177 }
1182 1178  
... ... @@ -1186,8 +1182,7 @@ QPDF::decryptStream(
1186 1182 std::shared_ptr<InputSource> file,
1187 1183 QPDF& qpdf_for_warning,
1188 1184 Pipeline*& pipeline,
1189   - int objid,
1190   - int generation,
  1185 + QPDFObjGen const& og,
1191 1186 QPDFObjectHandle& stream_dict,
1192 1187 std::vector<std::shared_ptr<Pipeline>>& heap)
1193 1188 {
... ... @@ -1282,7 +1277,7 @@ QPDF::decryptStream(
1282 1277 break;
1283 1278 }
1284 1279 }
1285   - std::string key = getKeyForObject(encp, objid, generation, use_aes);
  1280 + std::string key = getKeyForObject(encp, og, use_aes);
1286 1281 std::shared_ptr<Pipeline> new_pipeline;
1287 1282 if (use_aes) {
1288 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 371 QPDFObjectHandle
372 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 376 if (oh.isReserved()) {
376   - this->reserved.insert(QPDFObjGen(obj, gen));
  377 + this->reserved.insert(og);
377 378 }
378 379 return oh;
379 380 }
... ... @@ -495,8 +496,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
495 496 QTC::TC("qpdf", "QPDF_json updating existing stream");
496 497 } else {
497 498 this->this_stream_needs_data = true;
498   - replacement =
499   - pdf.reserveStream(tos.getObjectID(), tos.getGeneration());
  499 + replacement = pdf.reserveStream(tos.getObjGen());
500 500 replaceObject(tos, replacement, value);
501 501 }
502 502 } else {
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -706,7 +706,7 @@ QPDF::getUncompressedObject(
706 706 return obj;
707 707 } else {
708 708 int repl = (*(object_stream_data.find(obj.getObjectID()))).second;
709   - return objGenToIndirect(QPDFObjGen(repl, 0));
  709 + return getObjectByObjGen(QPDFObjGen(repl));
710 710 }
711 711 }
712 712  
... ... @@ -1143,12 +1143,6 @@ QPDF::dumpHGeneric(HGeneric&amp; t)
1143 1143 << "group_length: " << t.group_length << "\n";
1144 1144 }
1145 1145  
1146   -QPDFObjectHandle
1147   -QPDF::objGenToIndirect(QPDFObjGen const& og)
1148   -{
1149   - return getObjectByID(og.getObj(), og.getGen());
1150   -}
1151   -
1152 1146 void
1153 1147 QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
1154 1148 {
... ... @@ -1387,9 +1381,9 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1387 1381 stopOnError("found other than one root while"
1388 1382 " calculating linearization data");
1389 1383 }
1390   - this->m->part4.push_back(objGenToIndirect(*(lc_root.begin())));
  1384 + this->m->part4.push_back(getObjectByObjGen(*(lc_root.begin())));
1391 1385 for (auto const& og: lc_open_document) {
1392   - this->m->part4.push_back(objGenToIndirect(og));
  1386 + this->m->part4.push_back(getObjectByObjGen(og));
1393 1387 }
1394 1388  
1395 1389 // Part 6: first page objects. Note: implementation note 124
... ... @@ -1418,11 +1412,11 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1418 1412 // hint tables.
1419 1413  
1420 1414 for (auto const& og: lc_first_page_private) {
1421   - this->m->part6.push_back(objGenToIndirect(og));
  1415 + this->m->part6.push_back(getObjectByObjGen(og));
1422 1416 }
1423 1417  
1424 1418 for (auto const& og: lc_first_page_shared) {
1425   - this->m->part6.push_back(objGenToIndirect(og));
  1419 + this->m->part6.push_back(getObjectByObjGen(og));
1426 1420 }
1427 1421  
1428 1422 // Place the outline dictionary if it goes in the first page section.
... ... @@ -1468,7 +1462,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1468 1462 for (auto const& og: this->m->obj_user_to_objects[ou]) {
1469 1463 if (lc_other_page_private.count(og)) {
1470 1464 lc_other_page_private.erase(og);
1471   - this->m->part7.push_back(objGenToIndirect(og));
  1465 + this->m->part7.push_back(getObjectByObjGen(og));
1472 1466 ++this->m->c_page_offset_data.entries.at(i).nobjects;
1473 1467 }
1474 1468 }
... ... @@ -1485,7 +1479,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1485 1479  
1486 1480 // Order is unimportant.
1487 1481 for (auto const& og: lc_other_page_shared) {
1488   - this->m->part8.push_back(objGenToIndirect(og));
  1482 + this->m->part8.push_back(getObjectByObjGen(og));
1489 1483 }
1490 1484  
1491 1485 // Part 9: other objects
... ... @@ -1507,7 +1501,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1507 1501 for (auto const& og: pages_ogs) {
1508 1502 if (lc_other.count(og)) {
1509 1503 lc_other.erase(og);
1510   - this->m->part9.push_back(objGenToIndirect(og));
  1504 + this->m->part9.push_back(getObjectByObjGen(og));
1511 1505 }
1512 1506 }
1513 1507  
... ... @@ -1537,7 +1531,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1537 1531 for (auto const& og: ogs) {
1538 1532 if (lc_thumbnail_private.count(og)) {
1539 1533 lc_thumbnail_private.erase(og);
1540   - this->m->part9.push_back(objGenToIndirect(og));
  1534 + this->m->part9.push_back(getObjectByObjGen(og));
1541 1535 }
1542 1536 }
1543 1537 }
... ... @@ -1550,7 +1544,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1550 1544  
1551 1545 // Place shared thumbnail objects
1552 1546 for (auto const& og: lc_thumbnail_shared) {
1553   - this->m->part9.push_back(objGenToIndirect(og));
  1547 + this->m->part9.push_back(getObjectByObjGen(og));
1554 1548 }
1555 1549  
1556 1550 // Place outlines unless in first page
... ... @@ -1560,7 +1554,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1560 1554  
1561 1555 // Place all remaining objects
1562 1556 for (auto const& og: lc_other) {
1563   - this->m->part9.push_back(objGenToIndirect(og));
  1557 + this->m->part9.push_back(getObjectByObjGen(og));
1564 1558 }
1565 1559  
1566 1560 // Make sure we got everything exactly once.
... ... @@ -1662,7 +1656,7 @@ QPDF::pushOutlinesToPart(
1662 1656 lc_outlines.erase(outlines_og);
1663 1657 part.push_back(outlines);
1664 1658 for (auto const& og: lc_outlines) {
1665   - part.push_back(objGenToIndirect(og));
  1659 + part.push_back(getObjectByObjGen(og));
1666 1660 ++this->m->c_outline_data.nobjects;
1667 1661 }
1668 1662 }
... ...
libqpdf/QPDF_optimization.cc
... ... @@ -252,9 +252,7 @@ QPDF::pushInheritedAttributesToPageInternal(
252 252 if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) {
253 253 QTC::TC("qpdf", "QPDF unknown key not inherited");
254 254 setLastObjectDescription(
255   - "Pages object",
256   - cur_pages.getObjectID(),
257   - cur_pages.getGeneration());
  255 + "Pages object", cur_pages.getObjGen());
258 256 warn(
259 257 qpdf_e_pages,
260 258 this->m->last_object_description,
... ...
libqpdf/QPDF_pages.cc
... ... @@ -207,8 +207,7 @@ QPDF::insertPageobjToPage(
207 207 // that causes this to happen.
208 208 setLastObjectDescription(
209 209 "page " + QUtil::int_to_string(pos) + " (numbered from zero)",
210   - og.getObj(),
211   - og.getGen());
  210 + og);
212 211 throw QPDFExc(
213 212 qpdf_e_pages,
214 213 this->m->file->getName(),
... ... @@ -334,7 +333,7 @@ QPDF::findPage(QPDFObjGen const&amp; og)
334 333 auto it = this->m->pageobj_to_pages_pos.find(og);
335 334 if (it == this->m->pageobj_to_pages_pos.end()) {
336 335 QTC::TC("qpdf", "QPDF_pages findPage not found");
337   - setLastObjectDescription("page object", og.getObj(), og.getGen());
  336 + setLastObjectDescription("page object", og);
338 337 throw QPDFExc(
339 338 qpdf_e_pages,
340 339 this->m->file->getName(),
... ...