Commit acc57ca09095d5e6247893a54d94e99ba2304c52
1 parent
336d7833
Add QPDF::Objects destructor
Also, make obj_cache private and rename to table.
Showing
3 changed files
with
65 additions
and
61 deletions
libqpdf/QPDF.cc
| @@ -199,25 +199,7 @@ QPDF::QPDF() : | @@ -199,25 +199,7 @@ QPDF::QPDF() : | ||
| 199 | m->unique_id = unique_id.fetch_add(1ULL); | 199 | m->unique_id = unique_id.fetch_add(1ULL); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | -QPDF::~QPDF() | ||
| 203 | -{ | ||
| 204 | - // If two objects are mutually referential (through each object having an array or dictionary | ||
| 205 | - // that contains an indirect reference to the other), the circular references in the | ||
| 206 | - // std::shared_ptr objects will prevent the objects from being deleted. Walk through all objects | ||
| 207 | - // in the object cache, which is those objects that we read from the file, and break all | ||
| 208 | - // resolved indirect references by replacing them with an internal object type representing that | ||
| 209 | - // they have been destroyed. Note that we can't break references like this at any time when the | ||
| 210 | - // QPDF object is active. The call to reset also causes all direct QPDFObjectHandle objects that | ||
| 211 | - // are reachable from this object to release their association with this QPDF. Direct objects | ||
| 212 | - // are not destroyed since they can be moved to other QPDF objects safely. | ||
| 213 | - | ||
| 214 | - for (auto const& iter: m->objects.obj_cache) { | ||
| 215 | - iter.second.object->disconnect(); | ||
| 216 | - if (iter.second.object->getTypeCode() != ::ot_null) { | ||
| 217 | - iter.second.object->destroy(); | ||
| 218 | - } | ||
| 219 | - } | ||
| 220 | -} | 202 | +QPDF::~QPDF() = default; |
| 221 | 203 | ||
| 222 | std::shared_ptr<QPDF> | 204 | std::shared_ptr<QPDF> |
| 223 | QPDF::create() | 205 | QPDF::create() |
libqpdf/QPDF_objects.cc
| @@ -1154,7 +1154,7 @@ Objects ::all() | @@ -1154,7 +1154,7 @@ Objects ::all() | ||
| 1154 | // After fixDanglingReferences is called, all objects are in the object cache. | 1154 | // After fixDanglingReferences is called, all objects are in the object cache. |
| 1155 | qpdf.fixDanglingReferences(); | 1155 | qpdf.fixDanglingReferences(); |
| 1156 | std::vector<QPDFObjectHandle> result; | 1156 | std::vector<QPDFObjectHandle> result; |
| 1157 | - for (auto const& iter: obj_cache) { | 1157 | + for (auto const& iter: table) { |
| 1158 | result.emplace_back(iter.second.object); | 1158 | result.emplace_back(iter.second.object); |
| 1159 | } | 1159 | } |
| 1160 | return result; | 1160 | return result; |
| @@ -1539,7 +1539,7 @@ QPDFObject* | @@ -1539,7 +1539,7 @@ QPDFObject* | ||
| 1539 | Objects::resolve(QPDFObjGen og) | 1539 | Objects::resolve(QPDFObjGen og) |
| 1540 | { | 1540 | { |
| 1541 | if (!unresolved(og)) { | 1541 | if (!unresolved(og)) { |
| 1542 | - return obj_cache[og].object.get(); | 1542 | + return table[og].object.get(); |
| 1543 | } | 1543 | } |
| 1544 | 1544 | ||
| 1545 | if (m->resolving.count(og)) { | 1545 | if (m->resolving.count(og)) { |
| @@ -1548,7 +1548,7 @@ Objects::resolve(QPDFObjGen og) | @@ -1548,7 +1548,7 @@ Objects::resolve(QPDFObjGen og) | ||
| 1548 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); | 1548 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); |
| 1549 | qpdf.warn(qpdf.damagedPDF("", "loop detected resolving object " + og.unparse(' '))); | 1549 | qpdf.warn(qpdf.damagedPDF("", "loop detected resolving object " + og.unparse(' '))); |
| 1550 | update_table(og, QPDF_Null::create()); | 1550 | update_table(og, QPDF_Null::create()); |
| 1551 | - return obj_cache[og].object.get(); | 1551 | + return table[og].object.get(); |
| 1552 | } | 1552 | } |
| 1553 | ResolveRecorder rr(&qpdf, og); | 1553 | ResolveRecorder rr(&qpdf, og); |
| 1554 | 1554 | ||
| @@ -1585,7 +1585,7 @@ Objects::resolve(QPDFObjGen og) | @@ -1585,7 +1585,7 @@ Objects::resolve(QPDFObjGen og) | ||
| 1585 | update_table(og, QPDF_Null::create()); | 1585 | update_table(og, QPDF_Null::create()); |
| 1586 | } | 1586 | } |
| 1587 | 1587 | ||
| 1588 | - auto result(obj_cache[og].object); | 1588 | + auto result(table[og].object); |
| 1589 | result->setDefaultDescription(&qpdf, og); | 1589 | result->setDefaultDescription(&qpdf, og); |
| 1590 | return result.get(); | 1590 | return result.get(); |
| 1591 | } | 1591 | } |
| @@ -1685,28 +1685,48 @@ Objects::resolveObjectsInStream(int obj_stream_number) | @@ -1685,28 +1685,48 @@ Objects::resolveObjectsInStream(int obj_stream_number) | ||
| 1685 | } | 1685 | } |
| 1686 | } | 1686 | } |
| 1687 | 1687 | ||
| 1688 | +Objects::~Objects() | ||
| 1689 | +{ | ||
| 1690 | + // If two objects are mutually referential (through each object having an array or dictionary | ||
| 1691 | + // that contains an indirect reference to the other), the circular references in the | ||
| 1692 | + // std::shared_ptr objects will prevent the objects from being deleted. Walk through all objects | ||
| 1693 | + // in the object cache, which is those objects that we read from the file, and break all | ||
| 1694 | + // resolved indirect references by replacing them with an internal object type representing that | ||
| 1695 | + // they have been destroyed. Note that we can't break references like this at any time when the | ||
| 1696 | + // QPDF object is active. The call to reset also causes all direct QPDFObjectHandle objects that | ||
| 1697 | + // are reachable from this object to release their association with this QPDF. Direct objects | ||
| 1698 | + // are not destroyed since they can be moved to other QPDF objects safely. | ||
| 1699 | + | ||
| 1700 | + for (auto const& iter: table) { | ||
| 1701 | + iter.second.object->disconnect(); | ||
| 1702 | + if (iter.second.object->getTypeCode() != ::ot_null) { | ||
| 1703 | + iter.second.object->destroy(); | ||
| 1704 | + } | ||
| 1705 | + } | ||
| 1706 | +} | ||
| 1707 | + | ||
| 1688 | void | 1708 | void |
| 1689 | Objects::update_table(QPDFObjGen og, const std::shared_ptr<QPDFObject>& object) | 1709 | Objects::update_table(QPDFObjGen og, const std::shared_ptr<QPDFObject>& object) |
| 1690 | { | 1710 | { |
| 1691 | object->setObjGen(&qpdf, og); | 1711 | object->setObjGen(&qpdf, og); |
| 1692 | if (cached(og)) { | 1712 | if (cached(og)) { |
| 1693 | - auto& cache = obj_cache[og]; | 1713 | + auto& cache = table[og]; |
| 1694 | cache.object->assign(object); | 1714 | cache.object->assign(object); |
| 1695 | } else { | 1715 | } else { |
| 1696 | - obj_cache[og] = Entry(object); | 1716 | + table[og] = Entry(object); |
| 1697 | } | 1717 | } |
| 1698 | } | 1718 | } |
| 1699 | 1719 | ||
| 1700 | bool | 1720 | bool |
| 1701 | Objects::cached(QPDFObjGen og) | 1721 | Objects::cached(QPDFObjGen og) |
| 1702 | { | 1722 | { |
| 1703 | - return obj_cache.count(og) != 0; | 1723 | + return table.count(og) != 0; |
| 1704 | } | 1724 | } |
| 1705 | 1725 | ||
| 1706 | bool | 1726 | bool |
| 1707 | Objects::unresolved(QPDFObjGen og) | 1727 | Objects::unresolved(QPDFObjGen og) |
| 1708 | { | 1728 | { |
| 1709 | - return !cached(og) || obj_cache[og].object->isUnresolved(); | 1729 | + return !cached(og) || table[og].object->isUnresolved(); |
| 1710 | } | 1730 | } |
| 1711 | 1731 | ||
| 1712 | QPDFObjGen | 1732 | QPDFObjGen |
| @@ -1714,8 +1734,8 @@ Objects::next_id() | @@ -1714,8 +1734,8 @@ Objects::next_id() | ||
| 1714 | { | 1734 | { |
| 1715 | qpdf.fixDanglingReferences(); | 1735 | qpdf.fixDanglingReferences(); |
| 1716 | QPDFObjGen og; | 1736 | QPDFObjGen og; |
| 1717 | - if (!obj_cache.empty()) { | ||
| 1718 | - og = (*(m->objects.obj_cache.rbegin())).first; | 1737 | + if (!table.empty()) { |
| 1738 | + og = (*(m->objects.table.rbegin())).first; | ||
| 1719 | } | 1739 | } |
| 1720 | int max_objid = og.getObj(); | 1740 | int max_objid = og.getObj(); |
| 1721 | if (max_objid == std::numeric_limits<int>::max()) { | 1741 | if (max_objid == std::numeric_limits<int>::max()) { |
| @@ -1728,8 +1748,8 @@ QPDFObjectHandle | @@ -1728,8 +1748,8 @@ QPDFObjectHandle | ||
| 1728 | Objects::make_indirect(std::shared_ptr<QPDFObject> const& obj) | 1748 | Objects::make_indirect(std::shared_ptr<QPDFObject> const& obj) |
| 1729 | { | 1749 | { |
| 1730 | QPDFObjGen next{next_id()}; | 1750 | QPDFObjGen next{next_id()}; |
| 1731 | - obj_cache[next] = Entry(obj); | ||
| 1732 | - return qpdf.newIndirect(next, obj_cache[next].object); | 1751 | + table[next] = Entry(obj); |
| 1752 | + return qpdf.newIndirect(next, table[next].object); | ||
| 1733 | } | 1753 | } |
| 1734 | 1754 | ||
| 1735 | std::shared_ptr<QPDFObject> | 1755 | std::shared_ptr<QPDFObject> |
| @@ -1737,23 +1757,23 @@ Objects::get_for_parser(int id, int gen, bool parse_pdf) | @@ -1737,23 +1757,23 @@ Objects::get_for_parser(int id, int gen, bool parse_pdf) | ||
| 1737 | { | 1757 | { |
| 1738 | // This method is called by the parser and therefore must not resolve any objects. | 1758 | // This method is called by the parser and therefore must not resolve any objects. |
| 1739 | auto og = QPDFObjGen(id, gen); | 1759 | auto og = QPDFObjGen(id, gen); |
| 1740 | - if (auto iter = obj_cache.find(og); iter != obj_cache.end()) { | 1760 | + if (auto iter = table.find(og); iter != table.end()) { |
| 1741 | return iter->second.object; | 1761 | return iter->second.object; |
| 1742 | } | 1762 | } |
| 1743 | if (xref.type(og) || !xref.initialized()) { | 1763 | if (xref.type(og) || !xref.initialized()) { |
| 1744 | - return obj_cache.insert({og, QPDF_Unresolved::create(&qpdf, og)}).first->second.object; | 1764 | + return table.insert({og, QPDF_Unresolved::create(&qpdf, og)}).first->second.object; |
| 1745 | } | 1765 | } |
| 1746 | if (parse_pdf) { | 1766 | if (parse_pdf) { |
| 1747 | return QPDF_Null::create(); | 1767 | return QPDF_Null::create(); |
| 1748 | } | 1768 | } |
| 1749 | - return obj_cache.insert({og, QPDF_Null::create(&qpdf, og)}).first->second.object; | 1769 | + return table.insert({og, QPDF_Null::create(&qpdf, og)}).first->second.object; |
| 1750 | } | 1770 | } |
| 1751 | 1771 | ||
| 1752 | std::shared_ptr<QPDFObject> | 1772 | std::shared_ptr<QPDFObject> |
| 1753 | Objects::get_for_json(int id, int gen) | 1773 | Objects::get_for_json(int id, int gen) |
| 1754 | { | 1774 | { |
| 1755 | auto og = QPDFObjGen(id, gen); | 1775 | auto og = QPDFObjGen(id, gen); |
| 1756 | - auto [it, inserted] = obj_cache.try_emplace(og); | 1776 | + auto [it, inserted] = table.try_emplace(og); |
| 1757 | auto& obj = it->second.object; | 1777 | auto& obj = it->second.object; |
| 1758 | if (inserted) { | 1778 | if (inserted) { |
| 1759 | obj = (xref.initialized() && !xref.type(og)) ? QPDF_Null::create(&qpdf, og) | 1779 | obj = (xref.initialized() && !xref.type(og)) ? QPDF_Null::create(&qpdf, og) |
| @@ -1775,11 +1795,11 @@ Objects::replace(QPDFObjGen og, QPDFObjectHandle oh) | @@ -1775,11 +1795,11 @@ Objects::replace(QPDFObjGen og, QPDFObjectHandle oh) | ||
| 1775 | void | 1795 | void |
| 1776 | Objects::erase(QPDFObjGen og) | 1796 | Objects::erase(QPDFObjGen og) |
| 1777 | { | 1797 | { |
| 1778 | - if (auto cached = obj_cache.find(og); cached != obj_cache.end()) { | 1798 | + if (auto cached = table.find(og); cached != table.end()) { |
| 1779 | // Take care of any object handles that may be floating around. | 1799 | // Take care of any object handles that may be floating around. |
| 1780 | cached->second.object->assign(QPDF_Null::create()); | 1800 | cached->second.object->assign(QPDF_Null::create()); |
| 1781 | cached->second.object->setObjGen(nullptr, QPDFObjGen()); | 1801 | cached->second.object->setObjGen(nullptr, QPDFObjGen()); |
| 1782 | - obj_cache.erase(cached); | 1802 | + table.erase(cached); |
| 1783 | } | 1803 | } |
| 1784 | } | 1804 | } |
| 1785 | 1805 | ||
| @@ -1789,19 +1809,19 @@ Objects::swap(QPDFObjGen og1, QPDFObjGen og2) | @@ -1789,19 +1809,19 @@ Objects::swap(QPDFObjGen og1, QPDFObjGen og2) | ||
| 1789 | // Force objects to be read from the input source if needed, then swap them in the cache. | 1809 | // Force objects to be read from the input source if needed, then swap them in the cache. |
| 1790 | resolve(og1); | 1810 | resolve(og1); |
| 1791 | resolve(og2); | 1811 | resolve(og2); |
| 1792 | - obj_cache[og1].object->swapWith(obj_cache[og2].object); | 1812 | + table[og1].object->swapWith(table[og2].object); |
| 1793 | } | 1813 | } |
| 1794 | 1814 | ||
| 1795 | size_t | 1815 | size_t |
| 1796 | Objects::table_size() | 1816 | Objects::table_size() |
| 1797 | { | 1817 | { |
| 1798 | - // If obj_cache is dense, accommodate all object in tables,else accommodate only original | 1818 | + // If table is dense, accommodate all object in tables,else accommodate only original |
| 1799 | // objects. | 1819 | // objects. |
| 1800 | auto max_xref = toI(xref.size()); | 1820 | auto max_xref = toI(xref.size()); |
| 1801 | if (max_xref > 0) { | 1821 | if (max_xref > 0) { |
| 1802 | --max_xref; | 1822 | --max_xref; |
| 1803 | } | 1823 | } |
| 1804 | - auto max_obj = obj_cache.size() ? obj_cache.crbegin()->first.getObj() : 0; | 1824 | + auto max_obj = table.size() ? table.crbegin()->first.getObj() : 0; |
| 1805 | auto max_id = std::numeric_limits<int>::max() - 1; | 1825 | auto max_id = std::numeric_limits<int>::max() - 1; |
| 1806 | if (max_obj >= max_id || max_xref >= max_id) { | 1826 | if (max_obj >= max_id || max_xref >= max_id) { |
| 1807 | // Temporary fix. Long-term solution is | 1827 | // Temporary fix. Long-term solution is |
| @@ -1809,7 +1829,7 @@ Objects::table_size() | @@ -1809,7 +1829,7 @@ Objects::table_size() | ||
| 1809 | // - xref table and obj cache to protect against insertion of impossibly large obj ids | 1829 | // - xref table and obj cache to protect against insertion of impossibly large obj ids |
| 1810 | qpdf.stopOnError("Impossibly large object id encountered."); | 1830 | qpdf.stopOnError("Impossibly large object id encountered."); |
| 1811 | } | 1831 | } |
| 1812 | - if (max_obj < 1.1 * std::max(toI(obj_cache.size()), max_xref)) { | 1832 | + if (max_obj < 1.1 * std::max(toI(table.size()), max_xref)) { |
| 1813 | return toS(++max_obj); | 1833 | return toS(++max_obj); |
| 1814 | } | 1834 | } |
| 1815 | return toS(++max_xref); | 1835 | return toS(++max_xref); |
| @@ -1848,7 +1868,7 @@ Objects::compressible() | @@ -1848,7 +1868,7 @@ Objects::compressible() | ||
| 1848 | queue.emplace_back(trailer()); | 1868 | queue.emplace_back(trailer()); |
| 1849 | std::vector<T> result; | 1869 | std::vector<T> result; |
| 1850 | if constexpr (std::is_same_v<T, QPDFObjGen>) { | 1870 | if constexpr (std::is_same_v<T, QPDFObjGen>) { |
| 1851 | - result.reserve(obj_cache.size()); | 1871 | + result.reserve(table.size()); |
| 1852 | } else if constexpr (std::is_same_v<T, bool>) { | 1872 | } else if constexpr (std::is_same_v<T, bool>) { |
| 1853 | result.resize(max_obj + 1U, false); | 1873 | result.resize(max_obj + 1U, false); |
| 1854 | } else { | 1874 | } else { |
| @@ -1872,8 +1892,8 @@ Objects::compressible() | @@ -1872,8 +1892,8 @@ Objects::compressible() | ||
| 1872 | // Check whether this is the current object. If not, remove it (which changes it into a | 1892 | // Check whether this is the current object. If not, remove it (which changes it into a |
| 1873 | // direct null and therefore stops us from revisiting it) and move on to the next object | 1893 | // direct null and therefore stops us from revisiting it) and move on to the next object |
| 1874 | // in the queue. | 1894 | // in the queue. |
| 1875 | - auto upper = obj_cache.upper_bound(og); | ||
| 1876 | - if (upper != obj_cache.end() && upper->first.getObj() == og.getObj()) { | 1895 | + auto upper = table.upper_bound(og); |
| 1896 | + if (upper != table.end() && upper->first.getObj() == og.getObj()) { | ||
| 1877 | erase(og); | 1897 | erase(og); |
| 1878 | continue; | 1898 | continue; |
| 1879 | } | 1899 | } |
libqpdf/qpdf/QPDF_objects.hh
| @@ -378,17 +378,7 @@ class QPDF::Objects | @@ -378,17 +378,7 @@ class QPDF::Objects | ||
| 378 | qpdf_offset_t first_item_offset_{0}; // actual value from file | 378 | qpdf_offset_t first_item_offset_{0}; // actual value from file |
| 379 | }; // Xref_table; | 379 | }; // Xref_table; |
| 380 | 380 | ||
| 381 | - struct Entry | ||
| 382 | - { | ||
| 383 | - Entry() = default; | ||
| 384 | - | ||
| 385 | - Entry(std::shared_ptr<QPDFObject> object) : | ||
| 386 | - object(std::move(object)) | ||
| 387 | - { | ||
| 388 | - } | ||
| 389 | - | ||
| 390 | - std::shared_ptr<QPDFObject> object; | ||
| 391 | - }; | 381 | + ~Objects(); |
| 392 | 382 | ||
| 393 | Objects(QPDF& qpdf, QPDF::Members* m, InputSource* const& file) : | 383 | Objects(QPDF& qpdf, QPDF::Members* m, InputSource* const& file) : |
| 394 | qpdf(qpdf), | 384 | qpdf(qpdf), |
| @@ -425,12 +415,12 @@ class QPDF::Objects | @@ -425,12 +415,12 @@ class QPDF::Objects | ||
| 425 | QPDFObjectHandle | 415 | QPDFObjectHandle |
| 426 | get(QPDFObjGen og) | 416 | get(QPDFObjGen og) |
| 427 | { | 417 | { |
| 428 | - if (auto it = obj_cache.find(og); it != obj_cache.end()) { | 418 | + if (auto it = table.find(og); it != table.end()) { |
| 429 | return {it->second.object}; | 419 | return {it->second.object}; |
| 430 | } else if (xref.initialized() && !xref.type(og)) { | 420 | } else if (xref.initialized() && !xref.type(og)) { |
| 431 | return QPDF_Null::create(); | 421 | return QPDF_Null::create(); |
| 432 | } else { | 422 | } else { |
| 433 | - auto result = obj_cache.try_emplace(og, QPDF_Unresolved::create(&qpdf, og)); | 423 | + auto result = table.try_emplace(og, QPDF_Unresolved::create(&qpdf, og)); |
| 434 | return {result.first->second.object}; | 424 | return {result.first->second.object}; |
| 435 | } | 425 | } |
| 436 | } | 426 | } |
| @@ -449,9 +439,6 @@ class QPDF::Objects | @@ -449,9 +439,6 @@ class QPDF::Objects | ||
| 449 | 439 | ||
| 450 | void swap(QPDFObjGen og1, QPDFObjGen og2); | 440 | void swap(QPDFObjGen og1, QPDFObjGen og2); |
| 451 | 441 | ||
| 452 | - std::map<QPDFObjGen, Entry> obj_cache; | ||
| 453 | - | ||
| 454 | - QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj); | ||
| 455 | QPDFObjectHandle read( | 442 | QPDFObjectHandle read( |
| 456 | bool attempt_recovery, | 443 | bool attempt_recovery, |
| 457 | qpdf_offset_t offset, | 444 | qpdf_offset_t offset, |
| @@ -460,7 +447,6 @@ class QPDF::Objects | @@ -460,7 +447,6 @@ class QPDF::Objects | ||
| 460 | QPDFObjGen& og, | 447 | QPDFObjGen& og, |
| 461 | bool skip_cache_if_in_xref); | 448 | bool skip_cache_if_in_xref); |
| 462 | QPDFObject* resolve(QPDFObjGen og); | 449 | QPDFObject* resolve(QPDFObjGen og); |
| 463 | - void resolveObjectsInStream(int obj_stream_number); | ||
| 464 | void update_table(QPDFObjGen og, std::shared_ptr<QPDFObject> const& object); | 450 | void update_table(QPDFObjGen og, std::shared_ptr<QPDFObject> const& object); |
| 465 | QPDFObjGen next_id(); | 451 | QPDFObjGen next_id(); |
| 466 | QPDFObjectHandle make_indirect(std::shared_ptr<QPDFObject> const& obj); | 452 | QPDFObjectHandle make_indirect(std::shared_ptr<QPDFObject> const& obj); |
| @@ -477,9 +463,23 @@ class QPDF::Objects | @@ -477,9 +463,23 @@ class QPDF::Objects | ||
| 477 | size_t table_size(); | 463 | size_t table_size(); |
| 478 | 464 | ||
| 479 | private: | 465 | private: |
| 466 | + struct Entry | ||
| 467 | + { | ||
| 468 | + Entry() = default; | ||
| 469 | + | ||
| 470 | + Entry(std::shared_ptr<QPDFObject> object) : | ||
| 471 | + object(object) | ||
| 472 | + { | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + std::shared_ptr<QPDFObject> object; | ||
| 476 | + }; | ||
| 477 | + | ||
| 480 | bool cached(QPDFObjGen og); | 478 | bool cached(QPDFObjGen og); |
| 481 | bool unresolved(QPDFObjGen og); | 479 | bool unresolved(QPDFObjGen og); |
| 482 | 480 | ||
| 481 | + QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj); | ||
| 482 | + void resolveObjectsInStream(int obj_stream_number); | ||
| 483 | QPDFObjectHandle read_object(std::string const& description, QPDFObjGen og); | 483 | QPDFObjectHandle read_object(std::string const& description, QPDFObjGen og); |
| 484 | void read_stream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); | 484 | void read_stream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); |
| 485 | void validate_stream_line_end(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); | 485 | void validate_stream_line_end(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); |
| @@ -490,6 +490,8 @@ class QPDF::Objects | @@ -490,6 +490,8 @@ class QPDF::Objects | ||
| 490 | InputSource* const& file; | 490 | InputSource* const& file; |
| 491 | QPDF::Members* m; | 491 | QPDF::Members* m; |
| 492 | Xref_table xref; | 492 | Xref_table xref; |
| 493 | + | ||
| 494 | + std::map<QPDFObjGen, Entry> table; | ||
| 493 | }; // Objects | 495 | }; // Objects |
| 494 | 496 | ||
| 495 | #endif // QPDF_OBJECTS_HH | 497 | #endif // QPDF_OBJECTS_HH |