Commit f8fd7d60e301b9b1bf4d705ce747e281c320487e
Committed by
GitHub
Merge pull request #726 from m-holger/tidy3
Split QPDFObject into QPDFObject and QPDFValue
Showing
42 changed files
with
825 additions
and
638 deletions
include/qpdf/Constants.h
| ... | ... | @@ -82,6 +82,8 @@ enum qpdf_object_type_e { |
| 82 | 82 | /* Additional object types that can occur in content streams */ |
| 83 | 83 | ot_operator, |
| 84 | 84 | ot_inlineimage, |
| 85 | + /* Object types internal to qpdf */ | |
| 86 | + ot_unresolved, | |
| 85 | 87 | /* NOTE: if adding to this list, update QPDFObject.hh */ |
| 86 | 88 | }; |
| 87 | 89 | ... | ... |
include/qpdf/QPDF.hh
| ... | ... | @@ -843,19 +843,13 @@ class QPDF |
| 843 | 843 | // it can resolve indirect references. |
| 844 | 844 | class Resolver |
| 845 | 845 | { |
| 846 | - friend class QPDFObjectHandle; | |
| 846 | + friend class QPDFObject; | |
| 847 | 847 | |
| 848 | 848 | private: |
| 849 | - static std::shared_ptr<QPDFObject> | |
| 849 | + static void | |
| 850 | 850 | resolve(QPDF* qpdf, QPDFObjGen const& og) |
| 851 | 851 | { |
| 852 | - return qpdf->resolve(og); | |
| 853 | - } | |
| 854 | - static bool | |
| 855 | - objectChanged( | |
| 856 | - QPDF* qpdf, QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph) | |
| 857 | - { | |
| 858 | - return qpdf->objectChanged(og, oph); | |
| 852 | + qpdf->resolve(og); | |
| 859 | 853 | } |
| 860 | 854 | }; |
| 861 | 855 | friend class Resolver; |
| ... | ... | @@ -1174,12 +1168,20 @@ class QPDF |
| 1174 | 1168 | std::string const& description, |
| 1175 | 1169 | QPDFObjGen const& exp_og, |
| 1176 | 1170 | QPDFObjGen& og); |
| 1177 | - bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph); | |
| 1178 | - std::shared_ptr<QPDFObject> resolve(QPDFObjGen const& og); | |
| 1171 | + void resolve(QPDFObjGen const& og); | |
| 1179 | 1172 | void resolveObjectsInStream(int obj_stream_number); |
| 1180 | 1173 | void stopOnError(std::string const& message); |
| 1181 | 1174 | QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); |
| 1182 | 1175 | QPDFObjectHandle reserveStream(QPDFObjGen const& og); |
| 1176 | + QPDFObjectHandle | |
| 1177 | + newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&); | |
| 1178 | + bool isCached(QPDFObjGen const& og); | |
| 1179 | + bool isUnresolved(QPDFObjGen const& og); | |
| 1180 | + void updateCache( | |
| 1181 | + QPDFObjGen const& og, | |
| 1182 | + std::shared_ptr<QPDFObject> const& object, | |
| 1183 | + qpdf_offset_t end_before_space, | |
| 1184 | + qpdf_offset_t end_after_space); | |
| 1183 | 1185 | |
| 1184 | 1186 | // Calls finish() on the pipeline when done but does not delete it |
| 1185 | 1187 | bool pipeStreamData( |
| ... | ... | @@ -1727,7 +1729,6 @@ class QPDF |
| 1727 | 1729 | bool in_parse; |
| 1728 | 1730 | bool parsed; |
| 1729 | 1731 | std::set<int> resolved_object_streams; |
| 1730 | - bool ever_replaced_objects; | |
| 1731 | 1732 | |
| 1732 | 1733 | // Linearization data |
| 1733 | 1734 | qpdf_offset_t first_xref_item_offset; // actual value from file | ... | ... |
include/qpdf/QPDFObject.hh
| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | #include <qpdf/Constants.h> |
| 26 | 26 | #include <qpdf/DLL.h> |
| 27 | 27 | #include <qpdf/JSON.hh> |
| 28 | +#include <qpdf/QPDFValue.hh> | |
| 28 | 29 | #include <qpdf/Types.h> |
| 29 | 30 | |
| 30 | 31 | #include <string> |
| ... | ... | @@ -34,9 +35,9 @@ class QPDFObjectHandle; |
| 34 | 35 | |
| 35 | 36 | class QPDFObject |
| 36 | 37 | { |
| 37 | - public: | |
| 38 | - QPDFObject(); | |
| 38 | + friend class QPDFValue; | |
| 39 | 39 | |
| 40 | + public: | |
| 40 | 41 | // Objects derived from QPDFObject are accessible through |
| 41 | 42 | // QPDFObjectHandle. Each object returns a unique type code that |
| 42 | 43 | // has one of the valid qpdf_object_type_e values. As new object |
| ... | ... | @@ -61,18 +62,128 @@ class QPDFObject |
| 61 | 62 | static constexpr object_type_e ot_stream = ::ot_stream; |
| 62 | 63 | static constexpr object_type_e ot_operator = ::ot_operator; |
| 63 | 64 | static constexpr object_type_e ot_inlineimage = ::ot_inlineimage; |
| 65 | + static constexpr object_type_e ot_unresolved = ::ot_unresolved; | |
| 64 | 66 | |
| 67 | + QPDFObject() = default; | |
| 65 | 68 | virtual ~QPDFObject() = default; |
| 66 | - virtual std::shared_ptr<QPDFObject> shallowCopy() = 0; | |
| 67 | - virtual std::string unparse() = 0; | |
| 68 | - virtual JSON getJSON(int json_version) = 0; | |
| 69 | + | |
| 70 | + std::shared_ptr<QPDFObject> | |
| 71 | + shallowCopy() | |
| 72 | + { | |
| 73 | + return value->shallowCopy(); | |
| 74 | + } | |
| 75 | + std::string | |
| 76 | + unparse() | |
| 77 | + { | |
| 78 | + return value->unparse(); | |
| 79 | + } | |
| 80 | + JSON | |
| 81 | + getJSON(int json_version) | |
| 82 | + { | |
| 83 | + return value->getJSON(json_version); | |
| 84 | + } | |
| 69 | 85 | |
| 70 | 86 | // Return a unique type code for the object |
| 71 | - virtual object_type_e getTypeCode() const = 0; | |
| 87 | + object_type_e | |
| 88 | + getTypeCode() const | |
| 89 | + { | |
| 90 | + return value->type_code; | |
| 91 | + } | |
| 72 | 92 | |
| 73 | 93 | // Return a string literal that describes the type, useful for |
| 74 | 94 | // debugging and testing |
| 75 | - virtual char const* getTypeName() const = 0; | |
| 95 | + char const* | |
| 96 | + getTypeName() const | |
| 97 | + { | |
| 98 | + return value->type_name; | |
| 99 | + } | |
| 100 | + // Returns nullptr for direct objects | |
| 101 | + QPDF* | |
| 102 | + getQPDF() const | |
| 103 | + { | |
| 104 | + return value->qpdf; | |
| 105 | + } | |
| 106 | + QPDFObjGen | |
| 107 | + getObjGen() const | |
| 108 | + { | |
| 109 | + return value->og; | |
| 110 | + } | |
| 111 | + | |
| 112 | + void | |
| 113 | + setDescription(QPDF* qpdf, std::string const& description) | |
| 114 | + { | |
| 115 | + return value->setDescription(qpdf, description); | |
| 116 | + } | |
| 117 | + bool | |
| 118 | + getDescription(QPDF*& qpdf, std::string& description) | |
| 119 | + { | |
| 120 | + return value->getDescription(qpdf, description); | |
| 121 | + } | |
| 122 | + bool | |
| 123 | + hasDescription() | |
| 124 | + { | |
| 125 | + return value->hasDescription(); | |
| 126 | + } | |
| 127 | + void | |
| 128 | + setParsedOffset(qpdf_offset_t offset) | |
| 129 | + { | |
| 130 | + value->setParsedOffset(offset); | |
| 131 | + } | |
| 132 | + qpdf_offset_t | |
| 133 | + getParsedOffset() | |
| 134 | + { | |
| 135 | + return value->getParsedOffset(); | |
| 136 | + } | |
| 137 | + void | |
| 138 | + assign(std::shared_ptr<QPDFObject> o) | |
| 139 | + { | |
| 140 | + value = o->value; | |
| 141 | + } | |
| 142 | + void | |
| 143 | + swapWith(std::shared_ptr<QPDFObject> o) | |
| 144 | + { | |
| 145 | + auto v = value; | |
| 146 | + value = o->value; | |
| 147 | + o->value = v; | |
| 148 | + auto og = value->og; | |
| 149 | + value->og = o->value->og; | |
| 150 | + o->value->og = og; | |
| 151 | + } | |
| 152 | + | |
| 153 | + // The following two methods are for use by class QPDF only | |
| 154 | + void | |
| 155 | + setObjGen(QPDF* qpdf, QPDFObjGen const& og) | |
| 156 | + { | |
| 157 | + value->qpdf = qpdf; | |
| 158 | + value->og = og; | |
| 159 | + } | |
| 160 | + void | |
| 161 | + resetObjGen() | |
| 162 | + { | |
| 163 | + value->qpdf = nullptr; | |
| 164 | + value->og = QPDFObjGen(); | |
| 165 | + } | |
| 166 | + | |
| 167 | + bool | |
| 168 | + isUnresolved() const | |
| 169 | + { | |
| 170 | + return value->type_code == ::ot_unresolved; | |
| 171 | + } | |
| 172 | + void | |
| 173 | + resolve() | |
| 174 | + { | |
| 175 | + if (isUnresolved()) { | |
| 176 | + doResolve(); | |
| 177 | + } | |
| 178 | + } | |
| 179 | + void doResolve(); | |
| 180 | + | |
| 181 | + template <typename T> | |
| 182 | + T* | |
| 183 | + as() | |
| 184 | + { | |
| 185 | + return dynamic_cast<T*>(value.get()); | |
| 186 | + } | |
| 76 | 187 | |
| 77 | 188 | // Accessor to give specific access to non-public methods |
| 78 | 189 | class ObjAccessor |
| ... | ... | @@ -89,29 +200,20 @@ class QPDFObject |
| 89 | 200 | } |
| 90 | 201 | } |
| 91 | 202 | }; |
| 92 | - friend class ObjAccessor; | |
| 93 | 203 | |
| 94 | - virtual void setDescription(QPDF*, std::string const&); | |
| 95 | - bool getDescription(QPDF*&, std::string&); | |
| 96 | - bool hasDescription(); | |
| 97 | - | |
| 98 | - void setParsedOffset(qpdf_offset_t offset); | |
| 99 | - qpdf_offset_t getParsedOffset(); | |
| 204 | + friend class ObjAccessor; | |
| 100 | 205 | |
| 101 | 206 | protected: |
| 102 | 207 | virtual void |
| 103 | 208 | releaseResolved() |
| 104 | 209 | { |
| 210 | + value->releaseResolved(); | |
| 105 | 211 | } |
| 106 | - static std::shared_ptr<QPDFObject> do_create(QPDFObject*); | |
| 107 | 212 | |
| 108 | 213 | private: |
| 109 | 214 | QPDFObject(QPDFObject const&) = delete; |
| 110 | 215 | QPDFObject& operator=(QPDFObject const&) = delete; |
| 111 | - | |
| 112 | - QPDF* owning_qpdf; | |
| 113 | - std::string object_description; | |
| 114 | - qpdf_offset_t parsed_offset; | |
| 216 | + std::shared_ptr<QPDFValue> value; | |
| 115 | 217 | }; |
| 116 | 218 | |
| 117 | 219 | #endif // QPDFOBJECT_HH | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -43,8 +43,18 @@ |
| 43 | 43 | |
| 44 | 44 | class Pipeline; |
| 45 | 45 | class QPDF; |
| 46 | -class QPDF_Dictionary; | |
| 47 | 46 | class QPDF_Array; |
| 47 | +class QPDF_Bool; | |
| 48 | +class QPDF_Dictionary; | |
| 49 | +class QPDF_InlineImage; | |
| 50 | +class QPDF_Integer; | |
| 51 | +class QPDF_Name; | |
| 52 | +class QPDF_Null; | |
| 53 | +class QPDF_Operator; | |
| 54 | +class QPDF_Real; | |
| 55 | +class QPDF_Reserved; | |
| 56 | +class QPDF_Stream; | |
| 57 | +class QPDF_String; | |
| 48 | 58 | class QPDFTokenizer; |
| 49 | 59 | class QPDFExc; |
| 50 | 60 | class Pl_QPDFTokenizer; |
| ... | ... | @@ -316,7 +326,7 @@ class QPDFObjectHandle |
| 316 | 326 | }; |
| 317 | 327 | |
| 318 | 328 | QPDF_DLL |
| 319 | - QPDFObjectHandle(); | |
| 329 | + QPDFObjectHandle() = default; | |
| 320 | 330 | QPDF_DLL |
| 321 | 331 | QPDFObjectHandle(QPDFObjectHandle const&) = default; |
| 322 | 332 | QPDF_DLL |
| ... | ... | @@ -963,8 +973,8 @@ class QPDFObjectHandle |
| 963 | 973 | // null for a direct object if allow_nullptr is set to true or |
| 964 | 974 | // throws a runtime error otherwise. |
| 965 | 975 | QPDF_DLL |
| 966 | - inline QPDF* | |
| 967 | - getOwningQPDF(bool allow_nullptr = true, std::string const& error_msg = ""); | |
| 976 | + inline QPDF* getOwningQPDF( | |
| 977 | + bool allow_nullptr = true, std::string const& error_msg = "") const; | |
| 968 | 978 | |
| 969 | 979 | // Create a shallow copy of an object as a direct object, but do not |
| 970 | 980 | // traverse across indirect object boundaries. That means that, |
| ... | ... | @@ -1443,9 +1453,9 @@ class QPDFObjectHandle |
| 1443 | 1453 | |
| 1444 | 1454 | private: |
| 1445 | 1455 | static QPDFObjectHandle |
| 1446 | - newIndirect(QPDF* qpdf, QPDFObjGen const& og) | |
| 1456 | + newIndirect(std::shared_ptr<QPDFObject> const& obj) | |
| 1447 | 1457 | { |
| 1448 | - return QPDFObjectHandle::newIndirect(qpdf, og); | |
| 1458 | + return QPDFObjectHandle(obj); | |
| 1449 | 1459 | } |
| 1450 | 1460 | static QPDFObjectHandle |
| 1451 | 1461 | newStream( |
| ... | ... | @@ -1458,12 +1468,6 @@ class QPDFObjectHandle |
| 1458 | 1468 | return QPDFObjectHandle::newStream( |
| 1459 | 1469 | qpdf, og, stream_dict, offset, length); |
| 1460 | 1470 | } |
| 1461 | - // Reserve an object with a specific ID | |
| 1462 | - static QPDFObjectHandle | |
| 1463 | - makeReserved() | |
| 1464 | - { | |
| 1465 | - return QPDFObjectHandle::makeReserved(); | |
| 1466 | - } | |
| 1467 | 1471 | }; |
| 1468 | 1472 | friend class Factory; |
| 1469 | 1473 | |
| ... | ... | @@ -1483,6 +1487,16 @@ class QPDFObjectHandle |
| 1483 | 1487 | }; |
| 1484 | 1488 | return o.obj; |
| 1485 | 1489 | } |
| 1490 | + static QPDF_Array* | |
| 1491 | + asArray(QPDFObjectHandle& oh) | |
| 1492 | + { | |
| 1493 | + return oh.asArray(); | |
| 1494 | + } | |
| 1495 | + static QPDF_Stream* | |
| 1496 | + asStream(QPDFObjectHandle& oh) | |
| 1497 | + { | |
| 1498 | + return oh.asStream(); | |
| 1499 | + } | |
| 1486 | 1500 | }; |
| 1487 | 1501 | friend class ObjAccessor; |
| 1488 | 1502 | |
| ... | ... | @@ -1563,18 +1577,32 @@ class QPDFObjectHandle |
| 1563 | 1577 | bool isImage(bool exclude_imagemask = true); |
| 1564 | 1578 | |
| 1565 | 1579 | private: |
| 1566 | - QPDFObjectHandle(QPDF*, QPDFObjGen const& og); | |
| 1567 | - QPDFObjectHandle(std::shared_ptr<QPDFObject> const&); | |
| 1580 | + QPDFObjectHandle(std::shared_ptr<QPDFObject> const& obj) : | |
| 1581 | + obj(obj) | |
| 1582 | + { | |
| 1583 | + } | |
| 1568 | 1584 | |
| 1569 | 1585 | // Private object factory methods |
| 1570 | - static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og); | |
| 1571 | 1586 | static QPDFObjectHandle newStream( |
| 1572 | 1587 | QPDF* qpdf, |
| 1573 | 1588 | QPDFObjGen const& og, |
| 1574 | 1589 | QPDFObjectHandle stream_dict, |
| 1575 | 1590 | qpdf_offset_t offset, |
| 1576 | 1591 | size_t length); |
| 1577 | - static QPDFObjectHandle makeReserved(); | |
| 1592 | + | |
| 1593 | + QPDF_Array* asArray(); | |
| 1594 | + QPDF_Bool* asBool(); | |
| 1595 | + QPDF_Dictionary* asDictionary(); | |
| 1596 | + QPDF_InlineImage* asInlineImage(); | |
| 1597 | + QPDF_Integer* asInteger(); | |
| 1598 | + QPDF_Name* asName(); | |
| 1599 | + QPDF_Null* asNull(); | |
| 1600 | + QPDF_Operator* asOperator(); | |
| 1601 | + QPDF_Real* asReal(); | |
| 1602 | + QPDF_Reserved* asReserved(); | |
| 1603 | + QPDF_Stream* asStream(); | |
| 1604 | + QPDF_Stream* asStreamWithAssert(); | |
| 1605 | + QPDF_String* asString(); | |
| 1578 | 1606 | |
| 1579 | 1607 | void typeWarning(char const* expected_type, std::string const& warning); |
| 1580 | 1608 | void objectWarning(std::string const& warning); |
| ... | ... | @@ -1601,15 +1629,10 @@ class QPDFObjectHandle |
| 1601 | 1629 | static void warn(QPDF*, QPDFExc const&); |
| 1602 | 1630 | void checkOwnership(QPDFObjectHandle const&) const; |
| 1603 | 1631 | |
| 1604 | - bool initialized; | |
| 1605 | - | |
| 1606 | 1632 | // Moving members of QPDFObjectHandle into a smart pointer incurs |
| 1607 | 1633 | // a substantial performance penalty since QPDFObjectHandle |
| 1608 | 1634 | // objects are copied around so frequently. |
| 1609 | - QPDF* qpdf; | |
| 1610 | - QPDFObjGen og; | |
| 1611 | 1635 | std::shared_ptr<QPDFObject> obj; |
| 1612 | - bool reserved; | |
| 1613 | 1636 | }; |
| 1614 | 1637 | |
| 1615 | 1638 | #ifndef QPDF_NO_QPDF_STRING |
| ... | ... | @@ -1832,44 +1855,45 @@ class QPDFObjectHandle::QPDFArrayItems |
| 1832 | 1855 | inline QPDFObjGen |
| 1833 | 1856 | QPDFObjectHandle::getObjGen() const |
| 1834 | 1857 | { |
| 1835 | - return og; | |
| 1858 | + return isInitialized() ? obj->getObjGen() : QPDFObjGen(); | |
| 1836 | 1859 | } |
| 1837 | 1860 | |
| 1838 | 1861 | inline int |
| 1839 | 1862 | QPDFObjectHandle::getObjectID() const |
| 1840 | 1863 | { |
| 1841 | - return og.getObj(); | |
| 1864 | + return getObjGen().getObj(); | |
| 1842 | 1865 | } |
| 1843 | 1866 | |
| 1844 | 1867 | inline int |
| 1845 | 1868 | QPDFObjectHandle::getGeneration() const |
| 1846 | 1869 | { |
| 1847 | - return og.getGen(); | |
| 1870 | + return getObjGen().getGen(); | |
| 1848 | 1871 | } |
| 1849 | 1872 | |
| 1850 | 1873 | inline bool |
| 1851 | 1874 | QPDFObjectHandle::isIndirect() const |
| 1852 | 1875 | { |
| 1853 | - return initialized && (getObjectID() != 0); | |
| 1876 | + return (obj != nullptr) && (getObjectID() != 0); | |
| 1854 | 1877 | } |
| 1855 | 1878 | |
| 1856 | 1879 | inline bool |
| 1857 | 1880 | QPDFObjectHandle::isInitialized() const |
| 1858 | 1881 | { |
| 1859 | - return initialized; | |
| 1882 | + return obj != nullptr; | |
| 1860 | 1883 | } |
| 1861 | 1884 | |
| 1862 | 1885 | // Indirect object accessors |
| 1863 | 1886 | inline QPDF* |
| 1864 | 1887 | QPDFObjectHandle::getOwningQPDF( |
| 1865 | - bool allow_nullptr, std::string const& error_msg) | |
| 1888 | + bool allow_nullptr, std::string const& error_msg) const | |
| 1866 | 1889 | { |
| 1867 | 1890 | // Will be null for direct objects |
| 1868 | - if (!allow_nullptr && (this->qpdf == nullptr)) { | |
| 1891 | + auto result = isInitialized() ? this->obj->getQPDF() : nullptr; | |
| 1892 | + if (!allow_nullptr && (result == nullptr)) { | |
| 1869 | 1893 | throw std::runtime_error( |
| 1870 | 1894 | error_msg == "" ? "attempt to use a null qpdf object" : error_msg); |
| 1871 | 1895 | } |
| 1872 | - return this->qpdf; | |
| 1896 | + return result; | |
| 1873 | 1897 | } |
| 1874 | 1898 | |
| 1875 | 1899 | inline void |
| ... | ... | @@ -1877,7 +1901,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) |
| 1877 | 1901 | { |
| 1878 | 1902 | // This is called during parsing on newly created direct objects, |
| 1879 | 1903 | // so we can't call dereference() here. |
| 1880 | - if (this->obj.get()) { | |
| 1904 | + if (isInitialized()) { | |
| 1881 | 1905 | this->obj->setParsedOffset(offset); |
| 1882 | 1906 | } |
| 1883 | 1907 | } | ... | ... |
include/qpdf/QPDFValue.hh
0 → 100644
| 1 | +// Copyright (c) 2005-2022 Jay Berkenbilt | |
| 2 | +// | |
| 3 | +// This file is part of qpdf. | |
| 4 | +// | |
| 5 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 | +// you may not use this file except in compliance with the License. | |
| 7 | +// You may obtain a copy of the License at | |
| 8 | +// | |
| 9 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | +// | |
| 11 | +// Unless required by applicable law or agreed to in writing, software | |
| 12 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | +// See the License for the specific language governing permissions and | |
| 15 | +// limitations under the License. | |
| 16 | +// | |
| 17 | +// Versions of qpdf prior to version 7 were released under the terms | |
| 18 | +// of version 2.0 of the Artistic License. At your option, you may | |
| 19 | +// continue to consider qpdf to be licensed under those terms. Please | |
| 20 | +// see the manual for additional information. | |
| 21 | + | |
| 22 | +#ifndef QPDFVALUE_HH | |
| 23 | +#define QPDFVALUE_HH | |
| 24 | + | |
| 25 | +#include <qpdf/Constants.h> | |
| 26 | +#include <qpdf/DLL.h> | |
| 27 | +#include <qpdf/JSON.hh> | |
| 28 | +#include <qpdf/QPDFObjGen.hh> | |
| 29 | +#include <qpdf/Types.h> | |
| 30 | + | |
| 31 | +#include <string> | |
| 32 | + | |
| 33 | +class QPDF; | |
| 34 | +class QPDFObjectHandle; | |
| 35 | +class QPDFObject; | |
| 36 | + | |
| 37 | +class QPDFValue | |
| 38 | +{ | |
| 39 | + friend class QPDFObject; | |
| 40 | + | |
| 41 | + public: | |
| 42 | + virtual ~QPDFValue() = default; | |
| 43 | + | |
| 44 | + virtual std::shared_ptr<QPDFObject> shallowCopy() = 0; | |
| 45 | + virtual std::string unparse() = 0; | |
| 46 | + virtual JSON getJSON(int json_version) = 0; | |
| 47 | + virtual void | |
| 48 | + setDescription(QPDF* qpdf, std::string const& description) | |
| 49 | + { | |
| 50 | + owning_qpdf = qpdf; | |
| 51 | + object_description = description; | |
| 52 | + } | |
| 53 | + bool | |
| 54 | + getDescription(QPDF*& qpdf, std::string& description) | |
| 55 | + { | |
| 56 | + qpdf = owning_qpdf; | |
| 57 | + description = object_description; | |
| 58 | + return owning_qpdf != nullptr; | |
| 59 | + } | |
| 60 | + bool | |
| 61 | + hasDescription() | |
| 62 | + { | |
| 63 | + return owning_qpdf != nullptr; | |
| 64 | + } | |
| 65 | + void | |
| 66 | + setParsedOffset(qpdf_offset_t offset) | |
| 67 | + { | |
| 68 | + if (parsed_offset < 0) { | |
| 69 | + parsed_offset = offset; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + qpdf_offset_t | |
| 73 | + getParsedOffset() | |
| 74 | + { | |
| 75 | + return parsed_offset; | |
| 76 | + } | |
| 77 | + QPDF* | |
| 78 | + getQPDF() | |
| 79 | + { | |
| 80 | + return qpdf; | |
| 81 | + } | |
| 82 | + QPDFObjGen | |
| 83 | + getObjGen() | |
| 84 | + { | |
| 85 | + return og; | |
| 86 | + } | |
| 87 | + | |
| 88 | + protected: | |
| 89 | + QPDFValue() : | |
| 90 | + type_code(::ot_uninitialized), | |
| 91 | + type_name("uninitialized") | |
| 92 | + { | |
| 93 | + } | |
| 94 | + QPDFValue(qpdf_object_type_e type_code, char const* type_name) : | |
| 95 | + type_code(type_code), | |
| 96 | + type_name(type_name) | |
| 97 | + { | |
| 98 | + } | |
| 99 | + QPDFValue( | |
| 100 | + qpdf_object_type_e type_code, | |
| 101 | + char const* type_name, | |
| 102 | + QPDF* qpdf, | |
| 103 | + QPDFObjGen const& og) : | |
| 104 | + type_code(type_code), | |
| 105 | + type_name(type_name), | |
| 106 | + qpdf(qpdf), | |
| 107 | + og(og) | |
| 108 | + { | |
| 109 | + } | |
| 110 | + virtual void | |
| 111 | + releaseResolved() | |
| 112 | + { | |
| 113 | + } | |
| 114 | + static std::shared_ptr<QPDFObject> do_create(QPDFValue*); | |
| 115 | + | |
| 116 | + private: | |
| 117 | + QPDFValue(QPDFValue const&) = delete; | |
| 118 | + QPDFValue& operator=(QPDFValue const&) = delete; | |
| 119 | + QPDF* owning_qpdf{nullptr}; | |
| 120 | + std::string object_description; | |
| 121 | + qpdf_offset_t parsed_offset{-1}; | |
| 122 | + const qpdf_object_type_e type_code; | |
| 123 | + char const* type_name; | |
| 124 | + | |
| 125 | + protected: | |
| 126 | + QPDF* qpdf{nullptr}; | |
| 127 | + QPDFObjGen og; | |
| 128 | +}; | |
| 129 | + | |
| 130 | +#endif // QPDFVALUE_HH | ... | ... |
libqpdf/CMakeLists.txt
| ... | ... | @@ -85,6 +85,7 @@ set(libqpdf_SOURCES |
| 85 | 85 | QPDFSystemError.cc |
| 86 | 86 | QPDFTokenizer.cc |
| 87 | 87 | QPDFUsage.cc |
| 88 | + QPDFValue.cc | |
| 88 | 89 | QPDFWriter.cc |
| 89 | 90 | QPDFXRefEntry.cc |
| 90 | 91 | QPDF_Array.cc |
| ... | ... | @@ -99,6 +100,7 @@ set(libqpdf_SOURCES |
| 99 | 100 | QPDF_Reserved.cc |
| 100 | 101 | QPDF_Stream.cc |
| 101 | 102 | QPDF_String.cc |
| 103 | + QPDF_Unresolved.cc | |
| 102 | 104 | QPDF_encryption.cc |
| 103 | 105 | QPDF_json.cc |
| 104 | 106 | QPDF_linearization.cc | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -24,7 +24,9 @@ |
| 24 | 24 | #include <qpdf/QPDF_Array.hh> |
| 25 | 25 | #include <qpdf/QPDF_Dictionary.hh> |
| 26 | 26 | #include <qpdf/QPDF_Null.hh> |
| 27 | +#include <qpdf/QPDF_Reserved.hh> | |
| 27 | 28 | #include <qpdf/QPDF_Stream.hh> |
| 29 | +#include <qpdf/QPDF_Unresolved.hh> | |
| 28 | 30 | #include <qpdf/QTC.hh> |
| 29 | 31 | #include <qpdf/QUtil.hh> |
| 30 | 32 | |
| ... | ... | @@ -222,7 +224,6 @@ QPDF::Members::Members() : |
| 222 | 224 | immediate_copy_from(false), |
| 223 | 225 | in_parse(false), |
| 224 | 226 | parsed(false), |
| 225 | - ever_replaced_objects(false), | |
| 226 | 227 | first_xref_item_offset(0), |
| 227 | 228 | uncompressed_after_compressed(false) |
| 228 | 229 | { |
| ... | ... | @@ -258,6 +259,7 @@ QPDF::~QPDF() |
| 258 | 259 | this->m->xref_table.clear(); |
| 259 | 260 | for (auto const& iter: this->m->obj_cache) { |
| 260 | 261 | QPDFObject::ObjAccessor::releaseResolved(iter.second.object.get()); |
| 262 | + iter.second.object->resetObjGen(); | |
| 261 | 263 | } |
| 262 | 264 | } |
| 263 | 265 | |
| ... | ... | @@ -1397,7 +1399,7 @@ QPDF::fixDanglingReferences(bool force) |
| 1397 | 1399 | std::list<QPDFObjectHandle> queue; |
| 1398 | 1400 | queue.push_back(this->m->trailer); |
| 1399 | 1401 | for (auto const& og: to_process) { |
| 1400 | - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og); | |
| 1402 | + auto obj = getObject(og); | |
| 1401 | 1403 | if (obj.isDictionary() || obj.isArray()) { |
| 1402 | 1404 | queue.push_back(obj); |
| 1403 | 1405 | } else if (obj.isStream()) { |
| ... | ... | @@ -1419,18 +1421,15 @@ QPDF::fixDanglingReferences(bool force) |
| 1419 | 1421 | to_check.push_back(iter.second); |
| 1420 | 1422 | } |
| 1421 | 1423 | } else if (obj.isArray()) { |
| 1422 | - QPDF_Array* arr = dynamic_cast<QPDF_Array*>( | |
| 1423 | - QPDFObjectHandle::ObjAccessor::getObject(obj).get()); | |
| 1424 | + auto arr = QPDFObjectHandle::ObjAccessor::asArray(obj); | |
| 1424 | 1425 | arr->addExplicitElementsToList(to_check); |
| 1425 | 1426 | } |
| 1426 | 1427 | for (auto sub: to_check) { |
| 1427 | 1428 | if (sub.isIndirect()) { |
| 1428 | - if (sub.getOwningQPDF() == this) { | |
| 1429 | - QPDFObjGen og(sub.getObjGen()); | |
| 1430 | - if (this->m->obj_cache.count(og) == 0) { | |
| 1431 | - QTC::TC("qpdf", "QPDF detected dangling ref"); | |
| 1432 | - queue.push_back(sub); | |
| 1433 | - } | |
| 1429 | + if ((sub.getOwningQPDF() == this) && | |
| 1430 | + isUnresolved(sub.getObjGen())) { | |
| 1431 | + QTC::TC("qpdf", "QPDF detected dangling ref"); | |
| 1432 | + queue.push_back(sub); | |
| 1434 | 1433 | } |
| 1435 | 1434 | } else { |
| 1436 | 1435 | queue.push_back(sub); |
| ... | ... | @@ -1462,8 +1461,7 @@ QPDF::getAllObjects() |
| 1462 | 1461 | fixDanglingReferences(true); |
| 1463 | 1462 | std::vector<QPDFObjectHandle> result; |
| 1464 | 1463 | for (auto const& iter: this->m->obj_cache) { |
| 1465 | - QPDFObjGen const& og = iter.first; | |
| 1466 | - result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og)); | |
| 1464 | + result.push_back(newIndirect(iter.first, iter.second.object)); | |
| 1467 | 1465 | } |
| 1468 | 1466 | return result; |
| 1469 | 1467 | } |
| ... | ... | @@ -1888,7 +1886,7 @@ QPDF::readObjectAtOffset( |
| 1888 | 1886 | "expected endobj"); |
| 1889 | 1887 | } |
| 1890 | 1888 | |
| 1891 | - if (!this->m->obj_cache.count(og)) { | |
| 1889 | + if (isUnresolved(og)) { | |
| 1892 | 1890 | // Store the object in the cache here so it gets cached |
| 1893 | 1891 | // whether we first know the offset or whether we first know |
| 1894 | 1892 | // the object ID and generation (in which we case we would get |
| ... | ... | @@ -1919,8 +1917,8 @@ QPDF::readObjectAtOffset( |
| 1919 | 1917 | } |
| 1920 | 1918 | } |
| 1921 | 1919 | qpdf_offset_t end_after_space = this->m->file->tell(); |
| 1922 | - | |
| 1923 | - this->m->obj_cache[og] = ObjCache( | |
| 1920 | + updateCache( | |
| 1921 | + og, | |
| 1924 | 1922 | QPDFObjectHandle::ObjAccessor::getObject(oh), |
| 1925 | 1923 | end_before_space, |
| 1926 | 1924 | end_after_space); |
| ... | ... | @@ -1929,31 +1927,14 @@ QPDF::readObjectAtOffset( |
| 1929 | 1927 | return oh; |
| 1930 | 1928 | } |
| 1931 | 1929 | |
| 1932 | -bool | |
| 1933 | -QPDF::objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph) | |
| 1934 | -{ | |
| 1935 | - // See if the object cached at og, if any, is the one passed in. | |
| 1936 | - // QPDFObjectHandle uses this to detect outdated handles to | |
| 1937 | - // replaced or swapped objects. This is a somewhat expensive check | |
| 1938 | - // because it happens with every dereference of a | |
| 1939 | - // QPDFObjectHandle. To reduce the hit somewhat, short-circuit the | |
| 1940 | - // check if we never called a function that replaces an object | |
| 1941 | - // already in cache. It is important for functions that do this to | |
| 1942 | - // set ever_replaced_objects = true. | |
| 1943 | - | |
| 1944 | - if (!this->m->ever_replaced_objects) { | |
| 1945 | - return false; | |
| 1946 | - } | |
| 1947 | - auto c = this->m->obj_cache.find(og); | |
| 1948 | - if (c == this->m->obj_cache.end()) { | |
| 1949 | - return true; | |
| 1950 | - } | |
| 1951 | - return (c->second.object.get() != oph.get()); | |
| 1952 | -} | |
| 1953 | - | |
| 1954 | -std::shared_ptr<QPDFObject> | |
| 1930 | +void | |
| 1955 | 1931 | QPDF::resolve(QPDFObjGen const& og) |
| 1956 | 1932 | { |
| 1933 | + if (isCached(og) && !isUnresolved(og)) { | |
| 1934 | + // We only need to resolve unresolved objects | |
| 1935 | + return; | |
| 1936 | + } | |
| 1937 | + | |
| 1957 | 1938 | // Check object cache before checking xref table. This allows us |
| 1958 | 1939 | // to insert things into the object cache that don't actually |
| 1959 | 1940 | // exist in the file. |
| ... | ... | @@ -1967,11 +1948,12 @@ QPDF::resolve(QPDFObjGen const& og) |
| 1967 | 1948 | "", |
| 1968 | 1949 | this->m->file->getLastOffset(), |
| 1969 | 1950 | ("loop detected resolving object " + og.unparse(' '))); |
| 1970 | - return QPDF_Null::create(); | |
| 1951 | + updateCache(og, QPDF_Null::create(), -1, -1); | |
| 1952 | + return; | |
| 1971 | 1953 | } |
| 1972 | 1954 | ResolveRecorder rr(this, og); |
| 1973 | 1955 | |
| 1974 | - if ((!this->m->obj_cache.count(og)) && this->m->xref_table.count(og)) { | |
| 1956 | + if (m->xref_table.count(og) != 0) { | |
| 1975 | 1957 | QPDFXRefEntry const& entry = this->m->xref_table[og]; |
| 1976 | 1958 | try { |
| 1977 | 1959 | switch (entry.getType()) { |
| ... | ... | @@ -2009,19 +1991,17 @@ QPDF::resolve(QPDFObjGen const& og) |
| 2009 | 1991 | ": error reading object: " + e.what())); |
| 2010 | 1992 | } |
| 2011 | 1993 | } |
| 2012 | - if (this->m->obj_cache.count(og) == 0) { | |
| 1994 | + | |
| 1995 | + if (isUnresolved(og)) { | |
| 2013 | 1996 | // PDF spec says unknown objects resolve to the null object. |
| 2014 | 1997 | QTC::TC("qpdf", "QPDF resolve failure to null"); |
| 2015 | - QPDFObjectHandle oh = QPDFObjectHandle::newNull(); | |
| 2016 | - this->m->obj_cache[og] = | |
| 2017 | - ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); | |
| 1998 | + updateCache(og, QPDF_Null::create(), -1, -1); | |
| 2018 | 1999 | } |
| 2019 | 2000 | |
| 2020 | - std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object); | |
| 2001 | + auto result(this->m->obj_cache[og].object); | |
| 2021 | 2002 | if (!result->hasDescription()) { |
| 2022 | 2003 | result->setDescription(this, ("object " + og.unparse(' '))); |
| 2023 | 2004 | } |
| 2024 | - return result; | |
| 2025 | 2005 | } |
| 2026 | 2006 | |
| 2027 | 2007 | void |
| ... | ... | @@ -2109,15 +2089,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number) |
| 2109 | 2089 | // objects appended to the file, so it is necessary to recheck the |
| 2110 | 2090 | // xref table and only cache what would actually be resolved here. |
| 2111 | 2091 | for (auto const& iter: offsets) { |
| 2112 | - int obj = iter.first; | |
| 2113 | - QPDFObjGen og(obj, 0); | |
| 2092 | + QPDFObjGen og(iter.first, 0); | |
| 2114 | 2093 | QPDFXRefEntry const& entry = this->m->xref_table[og]; |
| 2115 | 2094 | if ((entry.getType() == 2) && |
| 2116 | 2095 | (entry.getObjStreamNumber() == obj_stream_number)) { |
| 2117 | 2096 | int offset = iter.second; |
| 2118 | 2097 | input->seek(offset, SEEK_SET); |
| 2119 | 2098 | QPDFObjectHandle oh = readObject(input, "", og, true); |
| 2120 | - this->m->obj_cache[og] = ObjCache( | |
| 2099 | + updateCache( | |
| 2100 | + og, | |
| 2121 | 2101 | QPDFObjectHandle::ObjAccessor::getObject(oh), |
| 2122 | 2102 | end_before_space, |
| 2123 | 2103 | end_after_space); |
| ... | ... | @@ -2128,6 +2108,47 @@ QPDF::resolveObjectsInStream(int obj_stream_number) |
| 2128 | 2108 | } |
| 2129 | 2109 | |
| 2130 | 2110 | QPDFObjectHandle |
| 2111 | +QPDF::newIndirect(QPDFObjGen const& og, std::shared_ptr<QPDFObject> const& obj) | |
| 2112 | +{ | |
| 2113 | + obj->setObjGen(this, og); | |
| 2114 | + if (!obj->hasDescription()) { | |
| 2115 | + obj->setDescription(this, "object " + og.unparse(' ')); | |
| 2116 | + } | |
| 2117 | + return QPDFObjectHandle::Factory::newIndirect(obj); | |
| 2118 | +} | |
| 2119 | + | |
| 2120 | +void | |
| 2121 | +QPDF::updateCache( | |
| 2122 | + QPDFObjGen const& og, | |
| 2123 | + std::shared_ptr<QPDFObject> const& object, | |
| 2124 | + qpdf_offset_t end_before_space, | |
| 2125 | + qpdf_offset_t end_after_space) | |
| 2126 | +{ | |
| 2127 | + object->setObjGen(this, og); | |
| 2128 | + if (isCached(og)) { | |
| 2129 | + auto& cache = m->obj_cache[og]; | |
| 2130 | + cache.object->resetObjGen(); | |
| 2131 | + cache.object->assign(object); | |
| 2132 | + cache.end_before_space = end_before_space; | |
| 2133 | + cache.end_after_space = end_after_space; | |
| 2134 | + } else { | |
| 2135 | + m->obj_cache[og] = ObjCache(object, end_before_space, end_after_space); | |
| 2136 | + } | |
| 2137 | +} | |
| 2138 | + | |
| 2139 | +bool | |
| 2140 | +QPDF::isCached(QPDFObjGen const& og) | |
| 2141 | +{ | |
| 2142 | + return m->obj_cache.count(og) != 0; | |
| 2143 | +} | |
| 2144 | + | |
| 2145 | +bool | |
| 2146 | +QPDF::isUnresolved(QPDFObjGen const& og) | |
| 2147 | +{ | |
| 2148 | + return !isCached(og) || m->obj_cache[og].object->isUnresolved(); | |
| 2149 | +} | |
| 2150 | + | |
| 2151 | +QPDFObjectHandle | |
| 2131 | 2152 | QPDF::makeIndirectObject(QPDFObjectHandle oh) |
| 2132 | 2153 | { |
| 2133 | 2154 | int max_objid = toI(getObjectCount()); |
| ... | ... | @@ -2136,19 +2157,21 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) |
| 2136 | 2157 | "max object id is too high to create new objects"); |
| 2137 | 2158 | } |
| 2138 | 2159 | QPDFObjGen next(max_objid + 1, 0); |
| 2139 | - this->m->obj_cache[next] = | |
| 2160 | + m->obj_cache[next] = | |
| 2140 | 2161 | ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); |
| 2141 | - return QPDFObjectHandle::Factory::newIndirect(this, next); | |
| 2162 | + return newIndirect(next, m->obj_cache[next].object); | |
| 2142 | 2163 | } |
| 2143 | 2164 | |
| 2144 | 2165 | QPDFObjectHandle |
| 2145 | 2166 | QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) |
| 2146 | 2167 | { |
| 2147 | - if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) { | |
| 2168 | + if (!isCached(og) && !m->xref_table.count(og)) { | |
| 2148 | 2169 | resolve(og); |
| 2149 | - replaceObject(og, QPDFObjectHandle::Factory::makeReserved()); | |
| 2170 | + m->obj_cache[og].object = QPDF_Reserved::create(); | |
| 2171 | + return newIndirect(og, m->obj_cache[og].object); | |
| 2172 | + } else { | |
| 2173 | + return getObject(og); | |
| 2150 | 2174 | } |
| 2151 | - return getObject(og); | |
| 2152 | 2175 | } |
| 2153 | 2176 | |
| 2154 | 2177 | QPDFObjectHandle |
| ... | ... | @@ -2161,7 +2184,13 @@ QPDF::reserveStream(QPDFObjGen const& og) |
| 2161 | 2184 | QPDFObjectHandle |
| 2162 | 2185 | QPDF::getObject(QPDFObjGen const& og) |
| 2163 | 2186 | { |
| 2164 | - return QPDFObjectHandle::Factory::newIndirect(this, og); | |
| 2187 | + if (!og.isIndirect()) { | |
| 2188 | + return QPDFObjectHandle::newNull(); | |
| 2189 | + } | |
| 2190 | + if (!isCached(og)) { | |
| 2191 | + m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(this, og), -1, -1); | |
| 2192 | + } | |
| 2193 | + return newIndirect(og, m->obj_cache[og].object); | |
| 2165 | 2194 | } |
| 2166 | 2195 | |
| 2167 | 2196 | QPDFObjectHandle |
| ... | ... | @@ -2196,14 +2225,11 @@ QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) |
| 2196 | 2225 | throw std::logic_error( |
| 2197 | 2226 | "QPDF::replaceObject called with indirect object handle"); |
| 2198 | 2227 | } |
| 2199 | - | |
| 2200 | 2228 | // Force new object to appear in the cache |
| 2201 | 2229 | resolve(og); |
| 2202 | 2230 | |
| 2203 | 2231 | // Replace the object in the object cache |
| 2204 | - this->m->ever_replaced_objects = true; | |
| 2205 | - this->m->obj_cache[og] = | |
| 2206 | - ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); | |
| 2232 | + updateCache(og, QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); | |
| 2207 | 2233 | } |
| 2208 | 2234 | |
| 2209 | 2235 | void |
| ... | ... | @@ -2456,12 +2482,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) |
| 2456 | 2482 | QPDFObjGen local_og(result.getObjGen()); |
| 2457 | 2483 | // Copy information from the foreign stream so we can pipe its |
| 2458 | 2484 | // data later without keeping the original QPDF object around. |
| 2485 | + | |
| 2459 | 2486 | QPDF* foreign_stream_qpdf = foreign.getOwningQPDF( |
| 2460 | 2487 | false, "unable to retrieve owning qpdf from foreign stream"); |
| 2461 | 2488 | |
| 2462 | - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>( | |
| 2463 | - QPDFObjectHandle::ObjAccessor::getObject(foreign).get()); | |
| 2464 | - if (!stream) { | |
| 2489 | + auto stream = QPDFObjectHandle::ObjAccessor::asStream(foreign); | |
| 2490 | + if (stream == nullptr) { | |
| 2465 | 2491 | throw std::logic_error("unable to retrieve underlying" |
| 2466 | 2492 | " stream object from foreign stream"); |
| 2467 | 2493 | } |
| ... | ... | @@ -2525,10 +2551,7 @@ QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) |
| 2525 | 2551 | // cache. |
| 2526 | 2552 | resolve(og1); |
| 2527 | 2553 | resolve(og2); |
| 2528 | - ObjCache t = this->m->obj_cache[og1]; | |
| 2529 | - this->m->ever_replaced_objects = true; | |
| 2530 | - this->m->obj_cache[og1] = this->m->obj_cache[og2]; | |
| 2531 | - this->m->obj_cache[og2] = t; | |
| 2554 | + m->obj_cache[og1].object->swapWith(m->obj_cache[og2].object); | |
| 2532 | 2555 | } |
| 2533 | 2556 | |
| 2534 | 2557 | unsigned long long | ... | ... |
libqpdf/QPDFObject.cc
| 1 | 1 | #include <qpdf/QPDFObject.hh> |
| 2 | 2 | |
| 3 | -QPDFObject::QPDFObject() : | |
| 4 | - owning_qpdf(nullptr), | |
| 5 | - parsed_offset(-1) | |
| 6 | -{ | |
| 7 | -} | |
| 8 | - | |
| 9 | -std::shared_ptr<QPDFObject> | |
| 10 | -QPDFObject::do_create(QPDFObject* object) | |
| 11 | -{ | |
| 12 | - std::shared_ptr<QPDFObject> obj(object); | |
| 13 | - return obj; | |
| 14 | -} | |
| 15 | - | |
| 16 | -void | |
| 17 | -QPDFObject::setDescription(QPDF* qpdf, std::string const& description) | |
| 18 | -{ | |
| 19 | - this->owning_qpdf = qpdf; | |
| 20 | - this->object_description = description; | |
| 21 | -} | |
| 22 | - | |
| 23 | -bool | |
| 24 | -QPDFObject::getDescription(QPDF*& qpdf, std::string& description) | |
| 25 | -{ | |
| 26 | - qpdf = this->owning_qpdf; | |
| 27 | - description = this->object_description; | |
| 28 | - return this->owning_qpdf != nullptr; | |
| 29 | -} | |
| 30 | - | |
| 31 | -bool | |
| 32 | -QPDFObject::hasDescription() | |
| 33 | -{ | |
| 34 | - return this->owning_qpdf != nullptr; | |
| 35 | -} | |
| 3 | +#include <qpdf/QPDF.hh> | |
| 36 | 4 | |
| 37 | 5 | void |
| 38 | -QPDFObject::setParsedOffset(qpdf_offset_t offset) | |
| 39 | -{ | |
| 40 | - this->parsed_offset = offset; | |
| 41 | -} | |
| 42 | - | |
| 43 | -qpdf_offset_t | |
| 44 | -QPDFObject::getParsedOffset() | |
| 6 | +QPDFObject::doResolve() | |
| 45 | 7 | { |
| 46 | - return this->parsed_offset; | |
| 8 | + auto og = value->og; | |
| 9 | + QPDF::Resolver::resolve(value->qpdf, og); | |
| 47 | 10 | } | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | #include <qpdf/QPDF_Reserved.hh> |
| 22 | 22 | #include <qpdf/QPDF_Stream.hh> |
| 23 | 23 | #include <qpdf/QPDF_String.hh> |
| 24 | +#include <qpdf/QPDF_Unresolved.hh> | |
| 24 | 25 | #include <qpdf/SparseOHArray.hh> |
| 25 | 26 | |
| 26 | 27 | #include <qpdf/QIntC.hh> |
| ... | ... | @@ -234,29 +235,6 @@ LastChar::getLastChar() |
| 234 | 235 | return this->last_char; |
| 235 | 236 | } |
| 236 | 237 | |
| 237 | -QPDFObjectHandle::QPDFObjectHandle() : | |
| 238 | - initialized(false), | |
| 239 | - qpdf(nullptr), | |
| 240 | - reserved(false) | |
| 241 | -{ | |
| 242 | -} | |
| 243 | - | |
| 244 | -QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, QPDFObjGen const& og) : | |
| 245 | - initialized(true), | |
| 246 | - qpdf(qpdf), | |
| 247 | - og(og), | |
| 248 | - reserved(false) | |
| 249 | -{ | |
| 250 | -} | |
| 251 | - | |
| 252 | -QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) : | |
| 253 | - initialized(true), | |
| 254 | - qpdf(nullptr), | |
| 255 | - obj(data), | |
| 256 | - reserved(false) | |
| 257 | -{ | |
| 258 | -} | |
| 259 | - | |
| 260 | 238 | void |
| 261 | 239 | QPDFObjectHandle::releaseResolved() |
| 262 | 240 | { |
| ... | ... | @@ -286,24 +264,90 @@ QPDFObjectHandle::getTypeName() |
| 286 | 264 | return dereference() ? this->obj->getTypeName() : "uninitialized"; |
| 287 | 265 | } |
| 288 | 266 | |
| 289 | -namespace | |
| 267 | +QPDF_Array* | |
| 268 | +QPDFObjectHandle::asArray() | |
| 290 | 269 | { |
| 291 | - template <class T> | |
| 292 | - class QPDFObjectTypeAccessor | |
| 293 | - { | |
| 294 | - public: | |
| 295 | - static bool | |
| 296 | - check(std::shared_ptr<QPDFObject> const& o) | |
| 297 | - { | |
| 298 | - return (o && dynamic_cast<T const*>(o.get())); | |
| 299 | - } | |
| 300 | - }; | |
| 301 | -} // namespace | |
| 270 | + return dereference() ? obj->as<QPDF_Array>() : nullptr; | |
| 271 | +} | |
| 272 | + | |
| 273 | +QPDF_Bool* | |
| 274 | +QPDFObjectHandle::asBool() | |
| 275 | +{ | |
| 276 | + return dereference() ? obj->as<QPDF_Bool>() : nullptr; | |
| 277 | +} | |
| 278 | + | |
| 279 | +QPDF_Dictionary* | |
| 280 | +QPDFObjectHandle::asDictionary() | |
| 281 | +{ | |
| 282 | + return dereference() ? obj->as<QPDF_Dictionary>() : nullptr; | |
| 283 | +} | |
| 284 | + | |
| 285 | +QPDF_InlineImage* | |
| 286 | +QPDFObjectHandle::asInlineImage() | |
| 287 | +{ | |
| 288 | + return dereference() ? obj->as<QPDF_InlineImage>() : nullptr; | |
| 289 | +} | |
| 290 | + | |
| 291 | +QPDF_Integer* | |
| 292 | +QPDFObjectHandle::asInteger() | |
| 293 | +{ | |
| 294 | + return dereference() ? obj->as<QPDF_Integer>() : nullptr; | |
| 295 | +} | |
| 296 | + | |
| 297 | +QPDF_Name* | |
| 298 | +QPDFObjectHandle::asName() | |
| 299 | +{ | |
| 300 | + return dereference() ? obj->as<QPDF_Name>() : nullptr; | |
| 301 | +} | |
| 302 | + | |
| 303 | +QPDF_Null* | |
| 304 | +QPDFObjectHandle::asNull() | |
| 305 | +{ | |
| 306 | + return dereference() ? obj->as<QPDF_Null>() : nullptr; | |
| 307 | +} | |
| 308 | + | |
| 309 | +QPDF_Operator* | |
| 310 | +QPDFObjectHandle::asOperator() | |
| 311 | +{ | |
| 312 | + return dereference() ? obj->as<QPDF_Operator>() : nullptr; | |
| 313 | +} | |
| 314 | + | |
| 315 | +QPDF_Real* | |
| 316 | +QPDFObjectHandle::asReal() | |
| 317 | +{ | |
| 318 | + return dereference() ? obj->as<QPDF_Real>() : nullptr; | |
| 319 | +} | |
| 320 | + | |
| 321 | +QPDF_Reserved* | |
| 322 | +QPDFObjectHandle::asReserved() | |
| 323 | +{ | |
| 324 | + return dereference() ? obj->as<QPDF_Reserved>() : nullptr; | |
| 325 | +} | |
| 326 | + | |
| 327 | +QPDF_Stream* | |
| 328 | +QPDFObjectHandle::asStream() | |
| 329 | +{ | |
| 330 | + return dereference() ? obj->as<QPDF_Stream>() : nullptr; | |
| 331 | +} | |
| 332 | + | |
| 333 | +QPDF_Stream* | |
| 334 | +QPDFObjectHandle::asStreamWithAssert() | |
| 335 | +{ | |
| 336 | + auto stream = asStream(); | |
| 337 | + assertType("stream", stream); | |
| 338 | + return stream; | |
| 339 | +} | |
| 340 | + | |
| 341 | +QPDF_String* | |
| 342 | +QPDFObjectHandle::asString() | |
| 343 | +{ | |
| 344 | + return dereference() ? obj->as<QPDF_String>() : nullptr; | |
| 345 | +} | |
| 302 | 346 | |
| 303 | 347 | bool |
| 304 | 348 | QPDFObjectHandle::isBool() |
| 305 | 349 | { |
| 306 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Bool>::check(obj); | |
| 350 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_boolean); | |
| 307 | 351 | } |
| 308 | 352 | |
| 309 | 353 | bool |
| ... | ... | @@ -312,26 +356,26 @@ QPDFObjectHandle::isDirectNull() const |
| 312 | 356 | // Don't call dereference() -- this is a const method, and we know |
| 313 | 357 | // objid == 0, so there's nothing to resolve. |
| 314 | 358 | return ( |
| 315 | - this->initialized && (getObjectID() == 0) && | |
| 316 | - QPDFObjectTypeAccessor<QPDF_Null>::check(obj)); | |
| 359 | + isInitialized() && (getObjectID() == 0) && | |
| 360 | + (obj->getTypeCode() == QPDFObject::ot_null)); | |
| 317 | 361 | } |
| 318 | 362 | |
| 319 | 363 | bool |
| 320 | 364 | QPDFObjectHandle::isNull() |
| 321 | 365 | { |
| 322 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Null>::check(obj); | |
| 366 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_null); | |
| 323 | 367 | } |
| 324 | 368 | |
| 325 | 369 | bool |
| 326 | 370 | QPDFObjectHandle::isInteger() |
| 327 | 371 | { |
| 328 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Integer>::check(obj); | |
| 372 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_integer); | |
| 329 | 373 | } |
| 330 | 374 | |
| 331 | 375 | bool |
| 332 | 376 | QPDFObjectHandle::isReal() |
| 333 | 377 | { |
| 334 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Real>::check(obj); | |
| 378 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_real); | |
| 335 | 379 | } |
| 336 | 380 | |
| 337 | 381 | bool |
| ... | ... | @@ -368,51 +412,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) |
| 368 | 412 | bool |
| 369 | 413 | QPDFObjectHandle::isName() |
| 370 | 414 | { |
| 371 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Name>::check(obj); | |
| 415 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_name); | |
| 372 | 416 | } |
| 373 | 417 | |
| 374 | 418 | bool |
| 375 | 419 | QPDFObjectHandle::isString() |
| 376 | 420 | { |
| 377 | - return dereference() && QPDFObjectTypeAccessor<QPDF_String>::check(obj); | |
| 421 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_string); | |
| 378 | 422 | } |
| 379 | 423 | |
| 380 | 424 | bool |
| 381 | 425 | QPDFObjectHandle::isOperator() |
| 382 | 426 | { |
| 383 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Operator>::check(obj); | |
| 427 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_operator); | |
| 384 | 428 | } |
| 385 | 429 | |
| 386 | 430 | bool |
| 387 | 431 | QPDFObjectHandle::isInlineImage() |
| 388 | 432 | { |
| 389 | - return dereference() && | |
| 390 | - QPDFObjectTypeAccessor<QPDF_InlineImage>::check(obj); | |
| 433 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_inlineimage); | |
| 391 | 434 | } |
| 392 | 435 | |
| 393 | 436 | bool |
| 394 | 437 | QPDFObjectHandle::isArray() |
| 395 | 438 | { |
| 396 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Array>::check(obj); | |
| 439 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_array); | |
| 397 | 440 | } |
| 398 | 441 | |
| 399 | 442 | bool |
| 400 | 443 | QPDFObjectHandle::isDictionary() |
| 401 | 444 | { |
| 402 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj); | |
| 445 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_dictionary); | |
| 403 | 446 | } |
| 404 | 447 | |
| 405 | 448 | bool |
| 406 | 449 | QPDFObjectHandle::isStream() |
| 407 | 450 | { |
| 408 | - return dereference() && QPDFObjectTypeAccessor<QPDF_Stream>::check(obj); | |
| 451 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_stream); | |
| 409 | 452 | } |
| 410 | 453 | |
| 411 | 454 | bool |
| 412 | 455 | QPDFObjectHandle::isReserved() |
| 413 | 456 | { |
| 414 | - // dereference will clear reserved if this has been replaced | |
| 415 | - return dereference() && this->reserved; | |
| 457 | + return dereference() && (obj->getTypeCode() == QPDFObject::ot_reserved); | |
| 416 | 458 | } |
| 417 | 459 | |
| 418 | 460 | bool |
| ... | ... | @@ -450,8 +492,9 @@ QPDFObjectHandle::isStreamOfType( |
| 450 | 492 | bool |
| 451 | 493 | QPDFObjectHandle::getBoolValue() |
| 452 | 494 | { |
| 453 | - if (isBool()) { | |
| 454 | - return dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); | |
| 495 | + auto boolean = asBool(); | |
| 496 | + if (boolean) { | |
| 497 | + return boolean->getVal(); | |
| 455 | 498 | } else { |
| 456 | 499 | typeWarning("boolean", "returning false"); |
| 457 | 500 | QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); |
| ... | ... | @@ -462,10 +505,11 @@ QPDFObjectHandle::getBoolValue() |
| 462 | 505 | bool |
| 463 | 506 | QPDFObjectHandle::getValueAsBool(bool& value) |
| 464 | 507 | { |
| 465 | - if (!isBool()) { | |
| 508 | + auto boolean = asBool(); | |
| 509 | + if (boolean == nullptr) { | |
| 466 | 510 | return false; |
| 467 | 511 | } |
| 468 | - value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); | |
| 512 | + value = boolean->getVal(); | |
| 469 | 513 | return true; |
| 470 | 514 | } |
| 471 | 515 | |
| ... | ... | @@ -474,8 +518,9 @@ QPDFObjectHandle::getValueAsBool(bool& value) |
| 474 | 518 | long long |
| 475 | 519 | QPDFObjectHandle::getIntValue() |
| 476 | 520 | { |
| 477 | - if (isInteger()) { | |
| 478 | - return dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); | |
| 521 | + auto integer = asInteger(); | |
| 522 | + if (integer) { | |
| 523 | + return integer->getVal(); | |
| 479 | 524 | } else { |
| 480 | 525 | typeWarning("integer", "returning 0"); |
| 481 | 526 | QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); |
| ... | ... | @@ -486,10 +531,11 @@ QPDFObjectHandle::getIntValue() |
| 486 | 531 | bool |
| 487 | 532 | QPDFObjectHandle::getValueAsInt(long long& value) |
| 488 | 533 | { |
| 489 | - if (!isInteger()) { | |
| 534 | + auto integer = asInteger(); | |
| 535 | + if (integer == nullptr) { | |
| 490 | 536 | return false; |
| 491 | 537 | } |
| 492 | - value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); | |
| 538 | + value = integer->getVal(); | |
| 493 | 539 | return true; |
| 494 | 540 | } |
| 495 | 541 | |
| ... | ... | @@ -585,8 +631,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int& value) |
| 585 | 631 | std::string |
| 586 | 632 | QPDFObjectHandle::getRealValue() |
| 587 | 633 | { |
| 588 | - if (isReal()) { | |
| 589 | - return dynamic_cast<QPDF_Real*>(obj.get())->getVal(); | |
| 634 | + auto real = asReal(); | |
| 635 | + if (real) { | |
| 636 | + return real->getVal(); | |
| 590 | 637 | } else { |
| 591 | 638 | typeWarning("real", "returning 0.0"); |
| 592 | 639 | QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0"); |
| ... | ... | @@ -597,10 +644,11 @@ QPDFObjectHandle::getRealValue() |
| 597 | 644 | bool |
| 598 | 645 | QPDFObjectHandle::getValueAsReal(std::string& value) |
| 599 | 646 | { |
| 600 | - if (!isReal()) { | |
| 647 | + auto real = asReal(); | |
| 648 | + if (real == nullptr) { | |
| 601 | 649 | return false; |
| 602 | 650 | } |
| 603 | - value = dynamic_cast<QPDF_Real*>(obj.get())->getVal(); | |
| 651 | + value = real->getVal(); | |
| 604 | 652 | return true; |
| 605 | 653 | } |
| 606 | 654 | |
| ... | ... | @@ -609,8 +657,9 @@ QPDFObjectHandle::getValueAsReal(std::string& value) |
| 609 | 657 | std::string |
| 610 | 658 | QPDFObjectHandle::getName() |
| 611 | 659 | { |
| 612 | - if (isName()) { | |
| 613 | - return dynamic_cast<QPDF_Name*>(obj.get())->getName(); | |
| 660 | + auto name = asName(); | |
| 661 | + if (name) { | |
| 662 | + return name->getName(); | |
| 614 | 663 | } else { |
| 615 | 664 | typeWarning("name", "returning dummy name"); |
| 616 | 665 | QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); |
| ... | ... | @@ -621,10 +670,11 @@ QPDFObjectHandle::getName() |
| 621 | 670 | bool |
| 622 | 671 | QPDFObjectHandle::getValueAsName(std::string& value) |
| 623 | 672 | { |
| 624 | - if (!isName()) { | |
| 673 | + auto name = asName(); | |
| 674 | + if (name == nullptr) { | |
| 625 | 675 | return false; |
| 626 | 676 | } |
| 627 | - value = dynamic_cast<QPDF_Name*>(obj.get())->getName(); | |
| 677 | + value = name->getName(); | |
| 628 | 678 | return true; |
| 629 | 679 | } |
| 630 | 680 | |
| ... | ... | @@ -633,8 +683,9 @@ QPDFObjectHandle::getValueAsName(std::string& value) |
| 633 | 683 | std::string |
| 634 | 684 | QPDFObjectHandle::getStringValue() |
| 635 | 685 | { |
| 636 | - if (isString()) { | |
| 637 | - return dynamic_cast<QPDF_String*>(obj.get())->getVal(); | |
| 686 | + auto str = asString(); | |
| 687 | + if (str) { | |
| 688 | + return str->getVal(); | |
| 638 | 689 | } else { |
| 639 | 690 | typeWarning("string", "returning empty string"); |
| 640 | 691 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); |
| ... | ... | @@ -645,18 +696,20 @@ QPDFObjectHandle::getStringValue() |
| 645 | 696 | bool |
| 646 | 697 | QPDFObjectHandle::getValueAsString(std::string& value) |
| 647 | 698 | { |
| 648 | - if (!isString()) { | |
| 699 | + auto str = asString(); | |
| 700 | + if (str == nullptr) { | |
| 649 | 701 | return false; |
| 650 | 702 | } |
| 651 | - value = dynamic_cast<QPDF_String*>(obj.get())->getVal(); | |
| 703 | + value = str->getVal(); | |
| 652 | 704 | return true; |
| 653 | 705 | } |
| 654 | 706 | |
| 655 | 707 | std::string |
| 656 | 708 | QPDFObjectHandle::getUTF8Value() |
| 657 | 709 | { |
| 658 | - if (isString()) { | |
| 659 | - return dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); | |
| 710 | + auto str = asString(); | |
| 711 | + if (str) { | |
| 712 | + return str->getUTF8Val(); | |
| 660 | 713 | } else { |
| 661 | 714 | typeWarning("string", "returning empty string"); |
| 662 | 715 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); |
| ... | ... | @@ -667,10 +720,11 @@ QPDFObjectHandle::getUTF8Value() |
| 667 | 720 | bool |
| 668 | 721 | QPDFObjectHandle::getValueAsUTF8(std::string& value) |
| 669 | 722 | { |
| 670 | - if (!isString()) { | |
| 723 | + auto str = asString(); | |
| 724 | + if (str == nullptr) { | |
| 671 | 725 | return false; |
| 672 | 726 | } |
| 673 | - value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); | |
| 727 | + value = str->getUTF8Val(); | |
| 674 | 728 | return true; |
| 675 | 729 | } |
| 676 | 730 | |
| ... | ... | @@ -679,8 +733,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string& value) |
| 679 | 733 | std::string |
| 680 | 734 | QPDFObjectHandle::getOperatorValue() |
| 681 | 735 | { |
| 682 | - if (isOperator()) { | |
| 683 | - return dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); | |
| 736 | + auto op = asOperator(); | |
| 737 | + if (op) { | |
| 738 | + return op->getVal(); | |
| 684 | 739 | } else { |
| 685 | 740 | typeWarning("operator", "returning fake value"); |
| 686 | 741 | QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value"); |
| ... | ... | @@ -691,18 +746,20 @@ QPDFObjectHandle::getOperatorValue() |
| 691 | 746 | bool |
| 692 | 747 | QPDFObjectHandle::getValueAsOperator(std::string& value) |
| 693 | 748 | { |
| 694 | - if (!isOperator()) { | |
| 749 | + auto op = asOperator(); | |
| 750 | + if (op == nullptr) { | |
| 695 | 751 | return false; |
| 696 | 752 | } |
| 697 | - value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); | |
| 753 | + value = op->getVal(); | |
| 698 | 754 | return true; |
| 699 | 755 | } |
| 700 | 756 | |
| 701 | 757 | std::string |
| 702 | 758 | QPDFObjectHandle::getInlineImageValue() |
| 703 | 759 | { |
| 704 | - if (isInlineImage()) { | |
| 705 | - return dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); | |
| 760 | + auto image = asInlineImage(); | |
| 761 | + if (image) { | |
| 762 | + return image->getVal(); | |
| 706 | 763 | } else { |
| 707 | 764 | typeWarning("inlineimage", "returning empty data"); |
| 708 | 765 | QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data"); |
| ... | ... | @@ -713,10 +770,11 @@ QPDFObjectHandle::getInlineImageValue() |
| 713 | 770 | bool |
| 714 | 771 | QPDFObjectHandle::getValueAsInlineImage(std::string& value) |
| 715 | 772 | { |
| 716 | - if (!isInlineImage()) { | |
| 773 | + auto image = asInlineImage(); | |
| 774 | + if (image == nullptr) { | |
| 717 | 775 | return false; |
| 718 | 776 | } |
| 719 | - value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); | |
| 777 | + value = image->getVal(); | |
| 720 | 778 | return true; |
| 721 | 779 | } |
| 722 | 780 | |
| ... | ... | @@ -731,8 +789,9 @@ QPDFObjectHandle::aitems() |
| 731 | 789 | int |
| 732 | 790 | QPDFObjectHandle::getArrayNItems() |
| 733 | 791 | { |
| 734 | - if (isArray()) { | |
| 735 | - return dynamic_cast<QPDF_Array*>(obj.get())->getNItems(); | |
| 792 | + auto array = asArray(); | |
| 793 | + if (array) { | |
| 794 | + return array->getNItems(); | |
| 736 | 795 | } else { |
| 737 | 796 | typeWarning("array", "treating as empty"); |
| 738 | 797 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); |
| ... | ... | @@ -744,11 +803,12 @@ QPDFObjectHandle |
| 744 | 803 | QPDFObjectHandle::getArrayItem(int n) |
| 745 | 804 | { |
| 746 | 805 | QPDFObjectHandle result; |
| 747 | - if (isArray() && (n < getArrayNItems()) && (n >= 0)) { | |
| 748 | - result = dynamic_cast<QPDF_Array*>(obj.get())->getItem(n); | |
| 806 | + auto array = asArray(); | |
| 807 | + if (array && (n < array->getNItems()) && (n >= 0)) { | |
| 808 | + result = array->getItem(n); | |
| 749 | 809 | } else { |
| 750 | 810 | result = newNull(); |
| 751 | - if (isArray()) { | |
| 811 | + if (array) { | |
| 752 | 812 | objectWarning("returning null for out of bounds array access"); |
| 753 | 813 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); |
| 754 | 814 | } else { |
| ... | ... | @@ -757,7 +817,7 @@ QPDFObjectHandle::getArrayItem(int n) |
| 757 | 817 | } |
| 758 | 818 | QPDF* context = nullptr; |
| 759 | 819 | std::string description; |
| 760 | - if (this->obj->getDescription(context, description)) { | |
| 820 | + if (obj->getDescription(context, description)) { | |
| 761 | 821 | result.setObjectDescription( |
| 762 | 822 | context, |
| 763 | 823 | description + " -> null returned from invalid array access"); |
| ... | ... | @@ -769,14 +829,12 @@ QPDFObjectHandle::getArrayItem(int n) |
| 769 | 829 | bool |
| 770 | 830 | QPDFObjectHandle::isRectangle() |
| 771 | 831 | { |
| 772 | - if (!isArray()) { | |
| 773 | - return false; | |
| 774 | - } | |
| 775 | - if (getArrayNItems() != 4) { | |
| 832 | + auto array = asArray(); | |
| 833 | + if ((array == nullptr) || (array->getNItems() != 4)) { | |
| 776 | 834 | return false; |
| 777 | 835 | } |
| 778 | 836 | for (int i = 0; i < 4; ++i) { |
| 779 | - if (!getArrayItem(i).isNumber()) { | |
| 837 | + if (!array->getItem(i).isNumber()) { | |
| 780 | 838 | return false; |
| 781 | 839 | } |
| 782 | 840 | } |
| ... | ... | @@ -786,14 +844,12 @@ QPDFObjectHandle::isRectangle() |
| 786 | 844 | bool |
| 787 | 845 | QPDFObjectHandle::isMatrix() |
| 788 | 846 | { |
| 789 | - if (!isArray()) { | |
| 790 | - return false; | |
| 791 | - } | |
| 792 | - if (getArrayNItems() != 6) { | |
| 847 | + auto array = asArray(); | |
| 848 | + if ((array == nullptr) || (array->getNItems() != 6)) { | |
| 793 | 849 | return false; |
| 794 | 850 | } |
| 795 | 851 | for (int i = 0; i < 6; ++i) { |
| 796 | - if (!getArrayItem(i).isNumber()) { | |
| 852 | + if (!array->getItem(i).isNumber()) { | |
| 797 | 853 | return false; |
| 798 | 854 | } |
| 799 | 855 | } |
| ... | ... | @@ -805,13 +861,14 @@ QPDFObjectHandle::getArrayAsRectangle() |
| 805 | 861 | { |
| 806 | 862 | Rectangle result; |
| 807 | 863 | if (isRectangle()) { |
| 864 | + auto array = asArray(); | |
| 808 | 865 | // Rectangle coordinates are always supposed to be llx, lly, |
| 809 | 866 | // urx, ury, but files have been found in the wild where |
| 810 | 867 | // llx > urx or lly > ury. |
| 811 | - double i0 = getArrayItem(0).getNumericValue(); | |
| 812 | - double i1 = getArrayItem(1).getNumericValue(); | |
| 813 | - double i2 = getArrayItem(2).getNumericValue(); | |
| 814 | - double i3 = getArrayItem(3).getNumericValue(); | |
| 868 | + double i0 = array->getItem(0).getNumericValue(); | |
| 869 | + double i1 = array->getItem(1).getNumericValue(); | |
| 870 | + double i2 = array->getItem(2).getNumericValue(); | |
| 871 | + double i3 = array->getItem(3).getNumericValue(); | |
| 815 | 872 | result = Rectangle( |
| 816 | 873 | std::min(i0, i2), |
| 817 | 874 | std::min(i1, i3), |
| ... | ... | @@ -826,13 +883,14 @@ QPDFObjectHandle::getArrayAsMatrix() |
| 826 | 883 | { |
| 827 | 884 | Matrix result; |
| 828 | 885 | if (isMatrix()) { |
| 886 | + auto array = asArray(); | |
| 829 | 887 | result = Matrix( |
| 830 | - getArrayItem(0).getNumericValue(), | |
| 831 | - getArrayItem(1).getNumericValue(), | |
| 832 | - getArrayItem(2).getNumericValue(), | |
| 833 | - getArrayItem(3).getNumericValue(), | |
| 834 | - getArrayItem(4).getNumericValue(), | |
| 835 | - getArrayItem(5).getNumericValue()); | |
| 888 | + array->getItem(0).getNumericValue(), | |
| 889 | + array->getItem(1).getNumericValue(), | |
| 890 | + array->getItem(2).getNumericValue(), | |
| 891 | + array->getItem(3).getNumericValue(), | |
| 892 | + array->getItem(4).getNumericValue(), | |
| 893 | + array->getItem(5).getNumericValue()); | |
| 836 | 894 | } |
| 837 | 895 | return result; |
| 838 | 896 | } |
| ... | ... | @@ -841,8 +899,9 @@ std::vector<QPDFObjectHandle> |
| 841 | 899 | QPDFObjectHandle::getArrayAsVector() |
| 842 | 900 | { |
| 843 | 901 | std::vector<QPDFObjectHandle> result; |
| 844 | - if (isArray()) { | |
| 845 | - dynamic_cast<QPDF_Array*>(obj.get())->getAsVector(result); | |
| 902 | + auto array = asArray(); | |
| 903 | + if (array) { | |
| 904 | + array->getAsVector(result); | |
| 846 | 905 | } else { |
| 847 | 906 | typeWarning("array", "treating as empty"); |
| 848 | 907 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); |
| ... | ... | @@ -855,9 +914,10 @@ QPDFObjectHandle::getArrayAsVector() |
| 855 | 914 | void |
| 856 | 915 | QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) |
| 857 | 916 | { |
| 858 | - if (isArray()) { | |
| 917 | + auto array = asArray(); | |
| 918 | + if (array) { | |
| 859 | 919 | checkOwnership(item); |
| 860 | - dynamic_cast<QPDF_Array*>(obj.get())->setItem(n, item); | |
| 920 | + array->setItem(n, item); | |
| 861 | 921 | } else { |
| 862 | 922 | typeWarning("array", "ignoring attempt to set item"); |
| 863 | 923 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); |
| ... | ... | @@ -867,11 +927,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) |
| 867 | 927 | void |
| 868 | 928 | QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) |
| 869 | 929 | { |
| 870 | - if (isArray()) { | |
| 930 | + auto array = asArray(); | |
| 931 | + if (array) { | |
| 871 | 932 | for (auto const& item: items) { |
| 872 | 933 | checkOwnership(item); |
| 873 | 934 | } |
| 874 | - dynamic_cast<QPDF_Array*>(obj.get())->setFromVector(items); | |
| 935 | + array->setFromVector(items); | |
| 875 | 936 | } else { |
| 876 | 937 | typeWarning("array", "ignoring attempt to replace items"); |
| 877 | 938 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); |
| ... | ... | @@ -881,8 +942,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) |
| 881 | 942 | void |
| 882 | 943 | QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) |
| 883 | 944 | { |
| 884 | - if (isArray()) { | |
| 885 | - dynamic_cast<QPDF_Array*>(obj.get())->insertItem(at, item); | |
| 945 | + auto array = asArray(); | |
| 946 | + if (array) { | |
| 947 | + array->insertItem(at, item); | |
| 886 | 948 | } else { |
| 887 | 949 | typeWarning("array", "ignoring attempt to insert item"); |
| 888 | 950 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); |
| ... | ... | @@ -899,9 +961,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const& item) |
| 899 | 961 | void |
| 900 | 962 | QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) |
| 901 | 963 | { |
| 902 | - if (isArray()) { | |
| 964 | + auto array = asArray(); | |
| 965 | + if (array) { | |
| 903 | 966 | checkOwnership(item); |
| 904 | - dynamic_cast<QPDF_Array*>(obj.get())->appendItem(item); | |
| 967 | + array->appendItem(item); | |
| 905 | 968 | } else { |
| 906 | 969 | typeWarning("array", "ignoring attempt to append item"); |
| 907 | 970 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); |
| ... | ... | @@ -918,10 +981,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) |
| 918 | 981 | void |
| 919 | 982 | QPDFObjectHandle::eraseItem(int at) |
| 920 | 983 | { |
| 921 | - if (isArray() && (at < getArrayNItems()) && (at >= 0)) { | |
| 922 | - dynamic_cast<QPDF_Array*>(obj.get())->eraseItem(at); | |
| 984 | + auto array = asArray(); | |
| 985 | + if (array && (at < array->getNItems()) && (at >= 0)) { | |
| 986 | + array->eraseItem(at); | |
| 923 | 987 | } else { |
| 924 | - if (isArray()) { | |
| 988 | + if (array) { | |
| 925 | 989 | objectWarning("ignoring attempt to erase out of bounds array item"); |
| 926 | 990 | QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); |
| 927 | 991 | } else { |
| ... | ... | @@ -935,8 +999,9 @@ QPDFObjectHandle |
| 935 | 999 | QPDFObjectHandle::eraseItemAndGetOld(int at) |
| 936 | 1000 | { |
| 937 | 1001 | auto result = QPDFObjectHandle::newNull(); |
| 938 | - if (isArray() && (at < getArrayNItems()) && (at >= 0)) { | |
| 939 | - result = getArrayItem(at); | |
| 1002 | + auto array = asArray(); | |
| 1003 | + if (array && (at < array->getNItems()) && (at >= 0)) { | |
| 1004 | + result = array->getItem(at); | |
| 940 | 1005 | } |
| 941 | 1006 | eraseItem(at); |
| 942 | 1007 | return result; |
| ... | ... | @@ -953,8 +1018,9 @@ QPDFObjectHandle::ditems() |
| 953 | 1018 | bool |
| 954 | 1019 | QPDFObjectHandle::hasKey(std::string const& key) |
| 955 | 1020 | { |
| 956 | - if (isDictionary()) { | |
| 957 | - return dynamic_cast<QPDF_Dictionary*>(obj.get())->hasKey(key); | |
| 1021 | + auto dict = asDictionary(); | |
| 1022 | + if (dict) { | |
| 1023 | + return dict->hasKey(key); | |
| 958 | 1024 | } else { |
| 959 | 1025 | typeWarning( |
| 960 | 1026 | "dictionary", "returning false for a key containment request"); |
| ... | ... | @@ -967,15 +1033,16 @@ QPDFObjectHandle |
| 967 | 1033 | QPDFObjectHandle::getKey(std::string const& key) |
| 968 | 1034 | { |
| 969 | 1035 | QPDFObjectHandle result; |
| 970 | - if (isDictionary()) { | |
| 971 | - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKey(key); | |
| 1036 | + auto dict = asDictionary(); | |
| 1037 | + if (dict) { | |
| 1038 | + result = dict->getKey(key); | |
| 972 | 1039 | } else { |
| 973 | 1040 | typeWarning("dictionary", "returning null for attempted key retrieval"); |
| 974 | 1041 | QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); |
| 975 | 1042 | result = newNull(); |
| 976 | 1043 | QPDF* qpdf = nullptr; |
| 977 | 1044 | std::string description; |
| 978 | - if (this->obj->getDescription(qpdf, description)) { | |
| 1045 | + if (obj->getDescription(qpdf, description)) { | |
| 979 | 1046 | result.setObjectDescription( |
| 980 | 1047 | qpdf, |
| 981 | 1048 | (description + " -> null returned from getting key " + key + |
| ... | ... | @@ -995,8 +1062,9 @@ std::set<std::string> |
| 995 | 1062 | QPDFObjectHandle::getKeys() |
| 996 | 1063 | { |
| 997 | 1064 | std::set<std::string> result; |
| 998 | - if (isDictionary()) { | |
| 999 | - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKeys(); | |
| 1065 | + auto dict = asDictionary(); | |
| 1066 | + if (dict) { | |
| 1067 | + result = dict->getKeys(); | |
| 1000 | 1068 | } else { |
| 1001 | 1069 | typeWarning("dictionary", "treating as empty"); |
| 1002 | 1070 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); |
| ... | ... | @@ -1008,8 +1076,9 @@ std::map<std::string, QPDFObjectHandle> |
| 1008 | 1076 | QPDFObjectHandle::getDictAsMap() |
| 1009 | 1077 | { |
| 1010 | 1078 | std::map<std::string, QPDFObjectHandle> result; |
| 1011 | - if (isDictionary()) { | |
| 1012 | - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getAsMap(); | |
| 1079 | + auto dict = asDictionary(); | |
| 1080 | + if (dict) { | |
| 1081 | + result = dict->getAsMap(); | |
| 1013 | 1082 | } else { |
| 1014 | 1083 | typeWarning("dictionary", "treating as empty"); |
| 1015 | 1084 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); |
| ... | ... | @@ -1200,9 +1269,10 @@ void |
| 1200 | 1269 | QPDFObjectHandle::replaceKey( |
| 1201 | 1270 | std::string const& key, QPDFObjectHandle const& value) |
| 1202 | 1271 | { |
| 1203 | - if (isDictionary()) { | |
| 1272 | + auto dict = asDictionary(); | |
| 1273 | + if (dict) { | |
| 1204 | 1274 | checkOwnership(value); |
| 1205 | - dynamic_cast<QPDF_Dictionary*>(obj.get())->replaceKey(key, value); | |
| 1275 | + dict->replaceKey(key, value); | |
| 1206 | 1276 | } else { |
| 1207 | 1277 | typeWarning("dictionary", "ignoring key replacement request"); |
| 1208 | 1278 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); |
| ... | ... | @@ -1229,8 +1299,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( |
| 1229 | 1299 | void |
| 1230 | 1300 | QPDFObjectHandle::removeKey(std::string const& key) |
| 1231 | 1301 | { |
| 1232 | - if (isDictionary()) { | |
| 1233 | - dynamic_cast<QPDF_Dictionary*>(obj.get())->removeKey(key); | |
| 1302 | + auto dict = asDictionary(); | |
| 1303 | + if (dict) { | |
| 1304 | + dict->removeKey(key); | |
| 1234 | 1305 | } else { |
| 1235 | 1306 | typeWarning("dictionary", "ignoring key removal request"); |
| 1236 | 1307 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); |
| ... | ... | @@ -1241,8 +1312,9 @@ QPDFObjectHandle |
| 1241 | 1312 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) |
| 1242 | 1313 | { |
| 1243 | 1314 | auto result = QPDFObjectHandle::newNull(); |
| 1244 | - if (isDictionary()) { | |
| 1245 | - result = getKey(key); | |
| 1315 | + auto dict = asDictionary(); | |
| 1316 | + if (dict) { | |
| 1317 | + result = dict->getKey(key); | |
| 1246 | 1318 | } |
| 1247 | 1319 | removeKey(key); |
| 1248 | 1320 | return result; |
| ... | ... | @@ -1259,50 +1331,43 @@ QPDFObjectHandle::replaceOrRemoveKey( |
| 1259 | 1331 | QPDFObjectHandle |
| 1260 | 1332 | QPDFObjectHandle::getDict() |
| 1261 | 1333 | { |
| 1262 | - assertStream(); | |
| 1263 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getDict(); | |
| 1334 | + return asStreamWithAssert()->getDict(); | |
| 1264 | 1335 | } |
| 1265 | 1336 | |
| 1266 | 1337 | void |
| 1267 | 1338 | QPDFObjectHandle::setFilterOnWrite(bool val) |
| 1268 | 1339 | { |
| 1269 | - assertStream(); | |
| 1270 | - dynamic_cast<QPDF_Stream*>(obj.get())->setFilterOnWrite(val); | |
| 1340 | + asStreamWithAssert()->setFilterOnWrite(val); | |
| 1271 | 1341 | } |
| 1272 | 1342 | |
| 1273 | 1343 | bool |
| 1274 | 1344 | QPDFObjectHandle::getFilterOnWrite() |
| 1275 | 1345 | { |
| 1276 | - assertStream(); | |
| 1277 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getFilterOnWrite(); | |
| 1346 | + return asStreamWithAssert()->getFilterOnWrite(); | |
| 1278 | 1347 | } |
| 1279 | 1348 | |
| 1280 | 1349 | bool |
| 1281 | 1350 | QPDFObjectHandle::isDataModified() |
| 1282 | 1351 | { |
| 1283 | - assertStream(); | |
| 1284 | - return dynamic_cast<QPDF_Stream*>(obj.get())->isDataModified(); | |
| 1352 | + return asStreamWithAssert()->isDataModified(); | |
| 1285 | 1353 | } |
| 1286 | 1354 | |
| 1287 | 1355 | void |
| 1288 | 1356 | QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict) |
| 1289 | 1357 | { |
| 1290 | - assertStream(); | |
| 1291 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceDict(new_dict); | |
| 1358 | + asStreamWithAssert()->replaceDict(new_dict); | |
| 1292 | 1359 | } |
| 1293 | 1360 | |
| 1294 | 1361 | std::shared_ptr<Buffer> |
| 1295 | 1362 | QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) |
| 1296 | 1363 | { |
| 1297 | - assertStream(); | |
| 1298 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamData(level); | |
| 1364 | + return asStreamWithAssert()->getStreamData(level); | |
| 1299 | 1365 | } |
| 1300 | 1366 | |
| 1301 | 1367 | std::shared_ptr<Buffer> |
| 1302 | 1368 | QPDFObjectHandle::getRawStreamData() |
| 1303 | 1369 | { |
| 1304 | - assertStream(); | |
| 1305 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getRawStreamData(); | |
| 1370 | + return asStreamWithAssert()->getRawStreamData(); | |
| 1306 | 1371 | } |
| 1307 | 1372 | |
| 1308 | 1373 | bool |
| ... | ... | @@ -1314,8 +1379,7 @@ QPDFObjectHandle::pipeStreamData( |
| 1314 | 1379 | bool suppress_warnings, |
| 1315 | 1380 | bool will_retry) |
| 1316 | 1381 | { |
| 1317 | - assertStream(); | |
| 1318 | - return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( | |
| 1382 | + return asStreamWithAssert()->pipeStreamData( | |
| 1319 | 1383 | p, |
| 1320 | 1384 | filtering_attempted, |
| 1321 | 1385 | encode_flags, |
| ... | ... | @@ -1332,9 +1396,8 @@ QPDFObjectHandle::pipeStreamData( |
| 1332 | 1396 | bool suppress_warnings, |
| 1333 | 1397 | bool will_retry) |
| 1334 | 1398 | { |
| 1335 | - assertStream(); | |
| 1336 | 1399 | bool filtering_attempted; |
| 1337 | - dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( | |
| 1400 | + asStreamWithAssert()->pipeStreamData( | |
| 1338 | 1401 | p, |
| 1339 | 1402 | &filtering_attempted, |
| 1340 | 1403 | encode_flags, |
| ... | ... | @@ -1368,9 +1431,7 @@ QPDFObjectHandle::replaceStreamData( |
| 1368 | 1431 | QPDFObjectHandle const& filter, |
| 1369 | 1432 | QPDFObjectHandle const& decode_parms) |
| 1370 | 1433 | { |
| 1371 | - assertStream(); | |
| 1372 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( | |
| 1373 | - data, filter, decode_parms); | |
| 1434 | + asStreamWithAssert()->replaceStreamData(data, filter, decode_parms); | |
| 1374 | 1435 | } |
| 1375 | 1436 | |
| 1376 | 1437 | void |
| ... | ... | @@ -1379,14 +1440,12 @@ QPDFObjectHandle::replaceStreamData( |
| 1379 | 1440 | QPDFObjectHandle const& filter, |
| 1380 | 1441 | QPDFObjectHandle const& decode_parms) |
| 1381 | 1442 | { |
| 1382 | - assertStream(); | |
| 1383 | 1443 | auto b = std::make_shared<Buffer>(data.length()); |
| 1384 | 1444 | unsigned char* bp = b->getBuffer(); |
| 1385 | 1445 | if (bp) { |
| 1386 | 1446 | memcpy(bp, data.c_str(), data.length()); |
| 1387 | 1447 | } |
| 1388 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( | |
| 1389 | - b, filter, decode_parms); | |
| 1448 | + asStreamWithAssert()->replaceStreamData(b, filter, decode_parms); | |
| 1390 | 1449 | } |
| 1391 | 1450 | |
| 1392 | 1451 | void |
| ... | ... | @@ -1395,9 +1454,7 @@ QPDFObjectHandle::replaceStreamData( |
| 1395 | 1454 | QPDFObjectHandle const& filter, |
| 1396 | 1455 | QPDFObjectHandle const& decode_parms) |
| 1397 | 1456 | { |
| 1398 | - assertStream(); | |
| 1399 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( | |
| 1400 | - provider, filter, decode_parms); | |
| 1457 | + asStreamWithAssert()->replaceStreamData(provider, filter, decode_parms); | |
| 1401 | 1458 | } |
| 1402 | 1459 | |
| 1403 | 1460 | namespace |
| ... | ... | @@ -1446,11 +1503,9 @@ QPDFObjectHandle::replaceStreamData( |
| 1446 | 1503 | QPDFObjectHandle const& filter, |
| 1447 | 1504 | QPDFObjectHandle const& decode_parms) |
| 1448 | 1505 | { |
| 1449 | - assertStream(); | |
| 1450 | 1506 | auto sdp = |
| 1451 | 1507 | std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); |
| 1452 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( | |
| 1453 | - sdp, filter, decode_parms); | |
| 1508 | + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); | |
| 1454 | 1509 | } |
| 1455 | 1510 | |
| 1456 | 1511 | void |
| ... | ... | @@ -1459,11 +1514,9 @@ QPDFObjectHandle::replaceStreamData( |
| 1459 | 1514 | QPDFObjectHandle const& filter, |
| 1460 | 1515 | QPDFObjectHandle const& decode_parms) |
| 1461 | 1516 | { |
| 1462 | - assertStream(); | |
| 1463 | 1517 | auto sdp = |
| 1464 | 1518 | std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); |
| 1465 | - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( | |
| 1466 | - sdp, filter, decode_parms); | |
| 1519 | + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); | |
| 1467 | 1520 | } |
| 1468 | 1521 | |
| 1469 | 1522 | std::map<std::string, QPDFObjectHandle> |
| ... | ... | @@ -1478,10 +1531,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( |
| 1478 | 1531 | { |
| 1479 | 1532 | all_description = description; |
| 1480 | 1533 | std::vector<QPDFObjectHandle> result; |
| 1481 | - if (isArray()) { | |
| 1482 | - int n_items = getArrayNItems(); | |
| 1534 | + auto array = asArray(); | |
| 1535 | + if (array) { | |
| 1536 | + int n_items = array->getNItems(); | |
| 1483 | 1537 | for (int i = 0; i < n_items; ++i) { |
| 1484 | - QPDFObjectHandle item = getArrayItem(i); | |
| 1538 | + QPDFObjectHandle item = array->getItem(i); | |
| 1485 | 1539 | if (item.isStream()) { |
| 1486 | 1540 | result.push_back(item); |
| 1487 | 1541 | } else { |
| ... | ... | @@ -1648,18 +1702,16 @@ QPDFObjectHandle::unparseResolved() |
| 1648 | 1702 | if (!dereference()) { |
| 1649 | 1703 | throw std::logic_error( |
| 1650 | 1704 | "attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1651 | - } else if (this->reserved) { | |
| 1652 | - throw std::logic_error( | |
| 1653 | - "QPDFObjectHandle: attempting to unparse a reserved object"); | |
| 1654 | 1705 | } |
| 1655 | - return this->obj->unparse(); | |
| 1706 | + return obj->unparse(); | |
| 1656 | 1707 | } |
| 1657 | 1708 | |
| 1658 | 1709 | std::string |
| 1659 | 1710 | QPDFObjectHandle::unparseBinary() |
| 1660 | 1711 | { |
| 1661 | - if (this->isString()) { | |
| 1662 | - return dynamic_cast<QPDF_String*>(this->obj.get())->unparse(true); | |
| 1712 | + auto str = asString(); | |
| 1713 | + if (str) { | |
| 1714 | + return str->unparse(true); | |
| 1663 | 1715 | } else { |
| 1664 | 1716 | return unparse(); |
| 1665 | 1717 | } |
| ... | ... | @@ -1675,16 +1727,13 @@ QPDFObjectHandle::getJSON(bool dereference_indirect) |
| 1675 | 1727 | JSON |
| 1676 | 1728 | QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) |
| 1677 | 1729 | { |
| 1678 | - if ((!dereference_indirect) && this->isIndirect()) { | |
| 1730 | + if ((!dereference_indirect) && isIndirect()) { | |
| 1679 | 1731 | return JSON::makeString(unparse()); |
| 1680 | 1732 | } else if (!dereference()) { |
| 1681 | 1733 | throw std::logic_error( |
| 1682 | 1734 | "attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1683 | - } else if (this->reserved) { | |
| 1684 | - throw std::logic_error( | |
| 1685 | - "QPDFObjectHandle: attempting to unparse a reserved object"); | |
| 1686 | 1735 | } else { |
| 1687 | - return this->obj->getJSON(json_version); | |
| 1736 | + return obj->getJSON(json_version); | |
| 1688 | 1737 | } |
| 1689 | 1738 | } |
| 1690 | 1739 | |
| ... | ... | @@ -1696,8 +1745,7 @@ QPDFObjectHandle::getStreamJSON( |
| 1696 | 1745 | Pipeline* p, |
| 1697 | 1746 | std::string const& data_filename) |
| 1698 | 1747 | { |
| 1699 | - assertStream(); | |
| 1700 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamJSON( | |
| 1748 | + return asStreamWithAssert()->getStreamJSON( | |
| 1701 | 1749 | json_version, json_data, decode_level, p, data_filename); |
| 1702 | 1750 | } |
| 1703 | 1751 | |
| ... | ... | @@ -1917,8 +1965,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr<TokenFilter> filter) |
| 1917 | 1965 | void |
| 1918 | 1966 | QPDFObjectHandle::addTokenFilter(std::shared_ptr<TokenFilter> filter) |
| 1919 | 1967 | { |
| 1920 | - assertStream(); | |
| 1921 | - return dynamic_cast<QPDF_Stream*>(obj.get())->addTokenFilter(filter); | |
| 1968 | + return asStreamWithAssert()->addTokenFilter(filter); | |
| 1922 | 1969 | } |
| 1923 | 1970 | |
| 1924 | 1971 | QPDFObjectHandle |
| ... | ... | @@ -1945,21 +1992,6 @@ QPDFObjectHandle::getParsedOffset() |
| 1945 | 1992 | } |
| 1946 | 1993 | |
| 1947 | 1994 | QPDFObjectHandle |
| 1948 | -QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og) | |
| 1949 | -{ | |
| 1950 | - if (!og.isIndirect()) { | |
| 1951 | - // Special case: QPDF uses objid 0 as a sentinel for direct | |
| 1952 | - // objects, and the PDF specification doesn't allow for object | |
| 1953 | - // 0. Treat indirect references to object 0 as null so that we | |
| 1954 | - // never create an indirect object with objid 0. | |
| 1955 | - QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid"); | |
| 1956 | - return newNull(); | |
| 1957 | - } | |
| 1958 | - | |
| 1959 | - return QPDFObjectHandle(qpdf, og); | |
| 1960 | -} | |
| 1961 | - | |
| 1962 | -QPDFObjectHandle | |
| 1963 | 1995 | QPDFObjectHandle::newBool(bool value) |
| 1964 | 1996 | { |
| 1965 | 1997 | return QPDFObjectHandle(QPDF_Bool::create(value)); |
| ... | ... | @@ -2128,8 +2160,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) |
| 2128 | 2160 | QPDFObjectHandle stream_dict = newDictionary(); |
| 2129 | 2161 | QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( |
| 2130 | 2162 | QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0))); |
| 2131 | - result.dereference(); | |
| 2132 | - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get()); | |
| 2163 | + auto stream = result.asStream(); | |
| 2133 | 2164 | stream->setObjGen(result.getObjGen()); |
| 2134 | 2165 | return result; |
| 2135 | 2166 | } |
| ... | ... | @@ -2155,18 +2186,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) |
| 2155 | 2186 | QPDFObjectHandle |
| 2156 | 2187 | QPDFObjectHandle::newReserved(QPDF* qpdf) |
| 2157 | 2188 | { |
| 2158 | - // Reserve a spot for this object by assigning it an object | |
| 2159 | - // number, but then return an unresolved handle to the object. | |
| 2160 | - QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved()); | |
| 2161 | - QPDFObjectHandle result = newIndirect(qpdf, reserved.getObjGen()); | |
| 2162 | - result.reserved = true; | |
| 2163 | - return result; | |
| 2164 | -} | |
| 2165 | - | |
| 2166 | -QPDFObjectHandle | |
| 2167 | -QPDFObjectHandle::makeReserved() | |
| 2168 | -{ | |
| 2169 | - return QPDFObjectHandle(QPDF_Reserved::create()); | |
| 2189 | + return qpdf->makeIndirectObject(QPDFObjectHandle(QPDF_Reserved::create())); | |
| 2170 | 2190 | } |
| 2171 | 2191 | |
| 2172 | 2192 | void |
| ... | ... | @@ -2212,12 +2232,7 @@ QPDFObjectHandle::shallowCopyInternal( |
| 2212 | 2232 | QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream"); |
| 2213 | 2233 | throw std::runtime_error("attempt to make a shallow copy of a stream"); |
| 2214 | 2234 | } |
| 2215 | - | |
| 2216 | - if (isArray() || isDictionary()) { | |
| 2217 | - new_obj = QPDFObjectHandle(obj->shallowCopy()); | |
| 2218 | - } else { | |
| 2219 | - new_obj = *this; | |
| 2220 | - } | |
| 2235 | + new_obj = QPDFObjectHandle(obj->shallowCopy()); | |
| 2221 | 2236 | |
| 2222 | 2237 | std::set<QPDFObjGen> visited; |
| 2223 | 2238 | new_obj.copyObject(visited, false, first_level_only, false); |
| ... | ... | @@ -2258,9 +2273,6 @@ QPDFObjectHandle::copyObject( |
| 2258 | 2273 | " reserved object handle direct"); |
| 2259 | 2274 | } |
| 2260 | 2275 | |
| 2261 | - qpdf = nullptr; | |
| 2262 | - og = QPDFObjGen(); | |
| 2263 | - | |
| 2264 | 2276 | std::shared_ptr<QPDFObject> new_obj; |
| 2265 | 2277 | |
| 2266 | 2278 | if (isBool() || isInteger() || isName() || isNull() || isReal() || |
| ... | ... | @@ -2268,9 +2280,10 @@ QPDFObjectHandle::copyObject( |
| 2268 | 2280 | new_obj = obj->shallowCopy(); |
| 2269 | 2281 | } else if (isArray()) { |
| 2270 | 2282 | std::vector<QPDFObjectHandle> items; |
| 2271 | - int n = getArrayNItems(); | |
| 2283 | + auto array = asArray(); | |
| 2284 | + int n = array->getNItems(); | |
| 2272 | 2285 | for (int i = 0; i < n; ++i) { |
| 2273 | - items.push_back(getArrayItem(i)); | |
| 2286 | + items.push_back(array->getItem(i)); | |
| 2274 | 2287 | if ((!first_level_only) && |
| 2275 | 2288 | (cross_indirect || (!items.back().isIndirect()))) { |
| 2276 | 2289 | items.back().copyObject( |
| ... | ... | @@ -2280,8 +2293,9 @@ QPDFObjectHandle::copyObject( |
| 2280 | 2293 | new_obj = QPDF_Array::create(items); |
| 2281 | 2294 | } else if (isDictionary()) { |
| 2282 | 2295 | std::map<std::string, QPDFObjectHandle> items; |
| 2296 | + auto dict = asDictionary(); | |
| 2283 | 2297 | for (auto const& key: getKeys()) { |
| 2284 | - items[key] = getKey(key); | |
| 2298 | + items[key] = dict->getKey(key); | |
| 2285 | 2299 | if ((!first_level_only) && |
| 2286 | 2300 | (cross_indirect || (!items[key].isIndirect()))) { |
| 2287 | 2301 | items[key].copyObject( |
| ... | ... | @@ -2329,7 +2343,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) |
| 2329 | 2343 | void |
| 2330 | 2344 | QPDFObjectHandle::assertInitialized() const |
| 2331 | 2345 | { |
| 2332 | - if (!this->initialized) { | |
| 2346 | + if (!isInitialized()) { | |
| 2333 | 2347 | throw std::logic_error("operation attempted on uninitialized " |
| 2334 | 2348 | "QPDFObjectHandle"); |
| 2335 | 2349 | } |
| ... | ... | @@ -2544,8 +2558,9 @@ QPDFObjectHandle::isImage(bool exclude_imagemask) |
| 2544 | 2558 | void |
| 2545 | 2559 | QPDFObjectHandle::checkOwnership(QPDFObjectHandle const& item) const |
| 2546 | 2560 | { |
| 2547 | - if ((this->qpdf != nullptr) && (item.qpdf != nullptr) && | |
| 2548 | - (this->qpdf != item.qpdf)) { | |
| 2561 | + auto qpdf = getOwningQPDF(); | |
| 2562 | + auto item_qpdf = item.getOwningQPDF(); | |
| 2563 | + if ((qpdf != nullptr) && (item_qpdf != nullptr) && (qpdf != item_qpdf)) { | |
| 2549 | 2564 | QTC::TC("qpdf", "QPDFObjectHandle check ownership"); |
| 2550 | 2565 | throw std::logic_error( |
| 2551 | 2566 | "Attempting to add an object from a different QPDF." |
| ... | ... | @@ -2564,28 +2579,10 @@ QPDFObjectHandle::assertPageObject() |
| 2564 | 2579 | bool |
| 2565 | 2580 | QPDFObjectHandle::dereference() |
| 2566 | 2581 | { |
| 2567 | - if (!this->initialized) { | |
| 2582 | + if (!isInitialized()) { | |
| 2568 | 2583 | return false; |
| 2569 | 2584 | } |
| 2570 | - if (this->obj.get() && getObjectID() && | |
| 2571 | - QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj)) { | |
| 2572 | - this->obj = nullptr; | |
| 2573 | - } | |
| 2574 | - if (this->obj == nullptr) { | |
| 2575 | - std::shared_ptr<QPDFObject> obj = | |
| 2576 | - QPDF::Resolver::resolve(this->qpdf, getObjGen()); | |
| 2577 | - if (obj == nullptr) { | |
| 2578 | - // QPDF::resolve never returns an uninitialized object, but | |
| 2579 | - // check just in case. | |
| 2580 | - this->obj = QPDF_Null::create(); | |
| 2581 | - } else if (dynamic_cast<QPDF_Reserved*>(obj.get())) { | |
| 2582 | - // Do not resolve | |
| 2583 | - this->reserved = true; | |
| 2584 | - } else { | |
| 2585 | - this->reserved = false; | |
| 2586 | - this->obj = obj; | |
| 2587 | - } | |
| 2588 | - } | |
| 2585 | + this->obj->resolve(); | |
| 2589 | 2586 | return true; |
| 2590 | 2587 | } |
| 2591 | 2588 | ... | ... |
libqpdf/QPDFParser.cc
| 1 | 1 | #include <qpdf/QPDFParser.hh> |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QPDF.hh> |
| 4 | +#include <qpdf/QPDFObjGen.hh> | |
| 4 | 5 | #include <qpdf/QPDFObjectHandle.hh> |
| 5 | -#include <qpdf/QPDF_Array.hh> | |
| 6 | 6 | #include <qpdf/QTC.hh> |
| 7 | 7 | #include <qpdf/QUtil.hh> |
| 8 | 8 | |
| ... | ... | @@ -55,6 +55,7 @@ QPDFParser::parse(bool& empty, bool content_stream) |
| 55 | 55 | |
| 56 | 56 | while (!done) { |
| 57 | 57 | bool bad = false; |
| 58 | + bool indirect_ref = false; | |
| 58 | 59 | is_null = false; |
| 59 | 60 | auto& frame = stack.back(); |
| 60 | 61 | auto& olist = frame.olist; |
| ... | ... | @@ -185,12 +186,16 @@ QPDFParser::parse(bool& empty, bool content_stream) |
| 185 | 186 | "QPDFObjectHandle::parse called without context" |
| 186 | 187 | " on an object with indirect references"); |
| 187 | 188 | } |
| 188 | - // Try to resolve indirect objects | |
| 189 | - object = QPDFObjectHandle::newIndirect( | |
| 190 | - context, | |
| 191 | - QPDFObjGen( | |
| 192 | - olist.at(size - 2).getIntValueAsInt(), | |
| 193 | - olist.back().getIntValueAsInt())); | |
| 189 | + auto ref_og = QPDFObjGen( | |
| 190 | + olist.at(size - 2).getIntValueAsInt(), | |
| 191 | + olist.back().getIntValueAsInt()); | |
| 192 | + if (ref_og.isIndirect()) { | |
| 193 | + object = context->getObject(ref_og); | |
| 194 | + indirect_ref = true; | |
| 195 | + } else { | |
| 196 | + QTC::TC("qpdf", "QPDFParser indirect with 0 objid"); | |
| 197 | + is_null = true; | |
| 198 | + } | |
| 194 | 199 | olist.pop_back(); |
| 195 | 200 | olist.pop_back(); |
| 196 | 201 | } else if ((value == "endobj") && (state == st_top)) { |
| ... | ... | @@ -274,8 +279,8 @@ QPDFParser::parse(bool& empty, bool content_stream) |
| 274 | 279 | |
| 275 | 280 | case st_dictionary: |
| 276 | 281 | case st_array: |
| 277 | - if (!object.isDirectNull()) { | |
| 278 | - // No need to set description for direct nulls- they will | |
| 282 | + if (!indirect_ref && !object.isDirectNull()) { | |
| 283 | + // No need to set description for direct nulls - they will | |
| 279 | 284 | // become implicit. |
| 280 | 285 | setDescriptionFromInput(object, input->getLastOffset()); |
| 281 | 286 | object.setParsedOffset(input->getLastOffset()); | ... | ... |
libqpdf/QPDFValue.cc
0 → 100644
libqpdf/QPDF_Array.cc
| ... | ... | @@ -4,12 +4,14 @@ |
| 4 | 4 | #include <qpdf/QUtil.hh> |
| 5 | 5 | #include <stdexcept> |
| 6 | 6 | |
| 7 | -QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) | |
| 7 | +QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) : | |
| 8 | + QPDFValue(::ot_array, "array") | |
| 8 | 9 | { |
| 9 | 10 | setFromVector(v); |
| 10 | 11 | } |
| 11 | 12 | |
| 12 | 13 | QPDF_Array::QPDF_Array(SparseOHArray const& items) : |
| 14 | + QPDFValue(::ot_array, "array"), | |
| 13 | 15 | elements(items) |
| 14 | 16 | { |
| 15 | 17 | } |
| ... | ... | @@ -62,18 +64,6 @@ QPDF_Array::getJSON(int json_version) |
| 62 | 64 | return j; |
| 63 | 65 | } |
| 64 | 66 | |
| 65 | -QPDFObject::object_type_e | |
| 66 | -QPDF_Array::getTypeCode() const | |
| 67 | -{ | |
| 68 | - return QPDFObject::ot_array; | |
| 69 | -} | |
| 70 | - | |
| 71 | -char const* | |
| 72 | -QPDF_Array::getTypeName() const | |
| 73 | -{ | |
| 74 | - return "array"; | |
| 75 | -} | |
| 76 | - | |
| 77 | 67 | int |
| 78 | 68 | QPDF_Array::getNItems() const |
| 79 | 69 | { | ... | ... |
libqpdf/QPDF_Bool.cc
| 1 | 1 | #include <qpdf/QPDF_Bool.hh> |
| 2 | 2 | |
| 3 | 3 | QPDF_Bool::QPDF_Bool(bool val) : |
| 4 | + QPDFValue(::ot_boolean, "boolean"), | |
| 4 | 5 | val(val) |
| 5 | 6 | { |
| 6 | 7 | } |
| ... | ... | @@ -29,18 +30,6 @@ QPDF_Bool::getJSON(int json_version) |
| 29 | 30 | return JSON::makeBool(this->val); |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | -QPDFObject::object_type_e | |
| 33 | -QPDF_Bool::getTypeCode() const | |
| 34 | -{ | |
| 35 | - return QPDFObject::ot_boolean; | |
| 36 | -} | |
| 37 | - | |
| 38 | -char const* | |
| 39 | -QPDF_Bool::getTypeName() const | |
| 40 | -{ | |
| 41 | - return "boolean"; | |
| 42 | -} | |
| 43 | - | |
| 44 | 33 | bool |
| 45 | 34 | QPDF_Bool::getVal() const |
| 46 | 35 | { | ... | ... |
libqpdf/QPDF_Dictionary.cc
| 1 | 1 | #include <qpdf/QPDF_Dictionary.hh> |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QPDF_Name.hh> |
| 4 | -#include <qpdf/QPDF_Null.hh> | |
| 5 | 4 | |
| 6 | 5 | QPDF_Dictionary::QPDF_Dictionary( |
| 7 | 6 | std::map<std::string, QPDFObjectHandle> const& items) : |
| 7 | + QPDFValue(::ot_dictionary, "dictionary"), | |
| 8 | 8 | items(items) |
| 9 | 9 | { |
| 10 | 10 | } |
| ... | ... | @@ -58,18 +58,6 @@ QPDF_Dictionary::getJSON(int json_version) |
| 58 | 58 | return j; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | -QPDFObject::object_type_e | |
| 62 | -QPDF_Dictionary::getTypeCode() const | |
| 63 | -{ | |
| 64 | - return QPDFObject::ot_dictionary; | |
| 65 | -} | |
| 66 | - | |
| 67 | -char const* | |
| 68 | -QPDF_Dictionary::getTypeName() const | |
| 69 | -{ | |
| 70 | - return "dictionary"; | |
| 71 | -} | |
| 72 | - | |
| 73 | 61 | bool |
| 74 | 62 | QPDF_Dictionary::hasKey(std::string const& key) |
| 75 | 63 | { | ... | ... |
libqpdf/QPDF_InlineImage.cc
| 1 | 1 | #include <qpdf/QPDF_InlineImage.hh> |
| 2 | 2 | |
| 3 | 3 | QPDF_InlineImage::QPDF_InlineImage(std::string const& val) : |
| 4 | + QPDFValue(::ot_inlineimage, "inline-image"), | |
| 4 | 5 | val(val) |
| 5 | 6 | { |
| 6 | 7 | } |
| ... | ... | @@ -29,18 +30,6 @@ QPDF_InlineImage::getJSON(int json_version) |
| 29 | 30 | return JSON::makeNull(); |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | -QPDFObject::object_type_e | |
| 33 | -QPDF_InlineImage::getTypeCode() const | |
| 34 | -{ | |
| 35 | - return QPDFObject::ot_inlineimage; | |
| 36 | -} | |
| 37 | - | |
| 38 | -char const* | |
| 39 | -QPDF_InlineImage::getTypeName() const | |
| 40 | -{ | |
| 41 | - return "inline-image"; | |
| 42 | -} | |
| 43 | - | |
| 44 | 33 | std::string |
| 45 | 34 | QPDF_InlineImage::getVal() const |
| 46 | 35 | { | ... | ... |
libqpdf/QPDF_Integer.cc
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | #include <qpdf/QUtil.hh> |
| 4 | 4 | |
| 5 | 5 | QPDF_Integer::QPDF_Integer(long long val) : |
| 6 | + QPDFValue(::ot_integer, "integer"), | |
| 6 | 7 | val(val) |
| 7 | 8 | { |
| 8 | 9 | } |
| ... | ... | @@ -31,18 +32,6 @@ QPDF_Integer::getJSON(int json_version) |
| 31 | 32 | return JSON::makeInt(this->val); |
| 32 | 33 | } |
| 33 | 34 | |
| 34 | -QPDFObject::object_type_e | |
| 35 | -QPDF_Integer::getTypeCode() const | |
| 36 | -{ | |
| 37 | - return QPDFObject::ot_integer; | |
| 38 | -} | |
| 39 | - | |
| 40 | -char const* | |
| 41 | -QPDF_Integer::getTypeName() const | |
| 42 | -{ | |
| 43 | - return "integer"; | |
| 44 | -} | |
| 45 | - | |
| 46 | 35 | long long |
| 47 | 36 | QPDF_Integer::getVal() const |
| 48 | 37 | { | ... | ... |
libqpdf/QPDF_Name.cc
| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | #include <string.h> |
| 6 | 6 | |
| 7 | 7 | QPDF_Name::QPDF_Name(std::string const& name) : |
| 8 | + QPDFValue(::ot_name, "name"), | |
| 8 | 9 | name(name) |
| 9 | 10 | { |
| 10 | 11 | } |
| ... | ... | @@ -61,18 +62,6 @@ QPDF_Name::getJSON(int json_version) |
| 61 | 62 | } |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | -QPDFObject::object_type_e | |
| 65 | -QPDF_Name::getTypeCode() const | |
| 66 | -{ | |
| 67 | - return QPDFObject::ot_name; | |
| 68 | -} | |
| 69 | - | |
| 70 | -char const* | |
| 71 | -QPDF_Name::getTypeName() const | |
| 72 | -{ | |
| 73 | - return "name"; | |
| 74 | -} | |
| 75 | - | |
| 76 | 65 | std::string |
| 77 | 66 | QPDF_Name::getName() const |
| 78 | 67 | { | ... | ... |
libqpdf/QPDF_Null.cc
| 1 | 1 | #include <qpdf/QPDF_Null.hh> |
| 2 | 2 | |
| 3 | +QPDF_Null::QPDF_Null() : | |
| 4 | + QPDFValue(::ot_null, "null") | |
| 5 | +{ | |
| 6 | +} | |
| 7 | + | |
| 3 | 8 | std::shared_ptr<QPDFObject> |
| 4 | 9 | QPDF_Null::create() |
| 5 | 10 | { |
| ... | ... | @@ -23,15 +28,3 @@ QPDF_Null::getJSON(int json_version) |
| 23 | 28 | { |
| 24 | 29 | return JSON::makeNull(); |
| 25 | 30 | } |
| 26 | - | |
| 27 | -QPDFObject::object_type_e | |
| 28 | -QPDF_Null::getTypeCode() const | |
| 29 | -{ | |
| 30 | - return QPDFObject::ot_null; | |
| 31 | -} | |
| 32 | - | |
| 33 | -char const* | |
| 34 | -QPDF_Null::getTypeName() const | |
| 35 | -{ | |
| 36 | - return "null"; | |
| 37 | -} | ... | ... |
libqpdf/QPDF_Operator.cc
| 1 | 1 | #include <qpdf/QPDF_Operator.hh> |
| 2 | 2 | |
| 3 | 3 | QPDF_Operator::QPDF_Operator(std::string const& val) : |
| 4 | + QPDFValue(::ot_operator, "operator"), | |
| 4 | 5 | val(val) |
| 5 | 6 | { |
| 6 | 7 | } |
| ... | ... | @@ -20,7 +21,7 @@ QPDF_Operator::shallowCopy() |
| 20 | 21 | std::string |
| 21 | 22 | QPDF_Operator::unparse() |
| 22 | 23 | { |
| 23 | - return this->val; | |
| 24 | + return val; | |
| 24 | 25 | } |
| 25 | 26 | |
| 26 | 27 | JSON |
| ... | ... | @@ -29,18 +30,6 @@ QPDF_Operator::getJSON(int json_version) |
| 29 | 30 | return JSON::makeNull(); |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | -QPDFObject::object_type_e | |
| 33 | -QPDF_Operator::getTypeCode() const | |
| 34 | -{ | |
| 35 | - return QPDFObject::ot_operator; | |
| 36 | -} | |
| 37 | - | |
| 38 | -char const* | |
| 39 | -QPDF_Operator::getTypeName() const | |
| 40 | -{ | |
| 41 | - return "operator"; | |
| 42 | -} | |
| 43 | - | |
| 44 | 33 | std::string |
| 45 | 34 | QPDF_Operator::getVal() const |
| 46 | 35 | { | ... | ... |
libqpdf/QPDF_Real.cc
| ... | ... | @@ -3,12 +3,14 @@ |
| 3 | 3 | #include <qpdf/QUtil.hh> |
| 4 | 4 | |
| 5 | 5 | QPDF_Real::QPDF_Real(std::string const& val) : |
| 6 | + QPDFValue(::ot_real, "real"), | |
| 6 | 7 | val(val) |
| 7 | 8 | { |
| 8 | 9 | } |
| 9 | 10 | |
| 10 | 11 | QPDF_Real::QPDF_Real( |
| 11 | 12 | double value, int decimal_places, bool trim_trailing_zeroes) : |
| 13 | + QPDFValue(::ot_real, "real"), | |
| 12 | 14 | val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes)) |
| 13 | 15 | { |
| 14 | 16 | } |
| ... | ... | @@ -60,18 +62,6 @@ QPDF_Real::getJSON(int json_version) |
| 60 | 62 | return JSON::makeNumber(result); |
| 61 | 63 | } |
| 62 | 64 | |
| 63 | -QPDFObject::object_type_e | |
| 64 | -QPDF_Real::getTypeCode() const | |
| 65 | -{ | |
| 66 | - return QPDFObject::ot_real; | |
| 67 | -} | |
| 68 | - | |
| 69 | -char const* | |
| 70 | -QPDF_Real::getTypeName() const | |
| 71 | -{ | |
| 72 | - return "real"; | |
| 73 | -} | |
| 74 | - | |
| 75 | 65 | std::string |
| 76 | 66 | QPDF_Real::getVal() |
| 77 | 67 | { | ... | ... |
libqpdf/QPDF_Reserved.cc
| ... | ... | @@ -2,6 +2,11 @@ |
| 2 | 2 | |
| 3 | 3 | #include <stdexcept> |
| 4 | 4 | |
| 5 | +QPDF_Reserved::QPDF_Reserved() : | |
| 6 | + QPDFValue(::ot_reserved, "reserved") | |
| 7 | +{ | |
| 8 | +} | |
| 9 | + | |
| 5 | 10 | std::shared_ptr<QPDFObject> |
| 6 | 11 | QPDF_Reserved::create() |
| 7 | 12 | { |
| ... | ... | @@ -17,25 +22,15 @@ QPDF_Reserved::shallowCopy() |
| 17 | 22 | std::string |
| 18 | 23 | QPDF_Reserved::unparse() |
| 19 | 24 | { |
| 20 | - throw std::logic_error("attempt to unparse QPDF_Reserved"); | |
| 25 | + throw std::logic_error( | |
| 26 | + "QPDFObjectHandle: attempting to unparse a reserved object"); | |
| 21 | 27 | return ""; |
| 22 | 28 | } |
| 23 | 29 | |
| 24 | 30 | JSON |
| 25 | 31 | QPDF_Reserved::getJSON(int json_version) |
| 26 | 32 | { |
| 27 | - throw std::logic_error("attempt to generate JSON from QPDF_Reserved"); | |
| 33 | + throw std::logic_error( | |
| 34 | + "QPDFObjectHandle: attempting to unparse a reserved object"); | |
| 28 | 35 | return JSON::makeNull(); |
| 29 | 36 | } |
| 30 | - | |
| 31 | -QPDFObject::object_type_e | |
| 32 | -QPDF_Reserved::getTypeCode() const | |
| 33 | -{ | |
| 34 | - return QPDFObject::ot_reserved; | |
| 35 | -} | |
| 36 | - | |
| 37 | -char const* | |
| 38 | -QPDF_Reserved::getTypeName() const | |
| 39 | -{ | |
| 40 | - return "reserved"; | |
| 41 | -} | ... | ... |
libqpdf/QPDF_Stream.cc
| ... | ... | @@ -114,6 +114,7 @@ QPDF_Stream::QPDF_Stream( |
| 114 | 114 | QPDFObjectHandle stream_dict, |
| 115 | 115 | qpdf_offset_t offset, |
| 116 | 116 | size_t length) : |
| 117 | + QPDFValue(::ot_stream, "stream"), | |
| 117 | 118 | qpdf(qpdf), |
| 118 | 119 | og(og), |
| 119 | 120 | filter_on_write(true), |
| ... | ... | @@ -291,22 +292,10 @@ QPDF_Stream::getStreamJSON( |
| 291 | 292 | return result; |
| 292 | 293 | } |
| 293 | 294 | |
| 294 | -QPDFObject::object_type_e | |
| 295 | -QPDF_Stream::getTypeCode() const | |
| 296 | -{ | |
| 297 | - return QPDFObject::ot_stream; | |
| 298 | -} | |
| 299 | - | |
| 300 | -char const* | |
| 301 | -QPDF_Stream::getTypeName() const | |
| 302 | -{ | |
| 303 | - return "stream"; | |
| 304 | -} | |
| 305 | - | |
| 306 | 295 | void |
| 307 | 296 | QPDF_Stream::setDescription(QPDF* qpdf, std::string const& description) |
| 308 | 297 | { |
| 309 | - this->QPDFObject::setDescription(qpdf, description); | |
| 298 | + this->QPDFValue::setDescription(qpdf, description); | |
| 310 | 299 | setDictDescription(); |
| 311 | 300 | } |
| 312 | 301 | ... | ... |
libqpdf/QPDF_String.cc
| ... | ... | @@ -21,6 +21,7 @@ is_iso_latin1_printable(char ch) |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | QPDF_String::QPDF_String(std::string const& val) : |
| 24 | + QPDFValue(::ot_string, "string"), | |
| 24 | 25 | val(val) |
| 25 | 26 | { |
| 26 | 27 | } |
| ... | ... | @@ -84,18 +85,6 @@ QPDF_String::getJSON(int json_version) |
| 84 | 85 | return JSON::makeString(result); |
| 85 | 86 | } |
| 86 | 87 | |
| 87 | -QPDFObject::object_type_e | |
| 88 | -QPDF_String::getTypeCode() const | |
| 89 | -{ | |
| 90 | - return QPDFObject::ot_string; | |
| 91 | -} | |
| 92 | - | |
| 93 | -char const* | |
| 94 | -QPDF_String::getTypeName() const | |
| 95 | -{ | |
| 96 | - return "string"; | |
| 97 | -} | |
| 98 | - | |
| 99 | 88 | bool |
| 100 | 89 | QPDF_String::useHexString() const |
| 101 | 90 | { | ... | ... |
libqpdf/QPDF_Unresolved.cc
0 → 100644
| 1 | +#include <qpdf/QPDF_Unresolved.hh> | |
| 2 | + | |
| 3 | +#include <stdexcept> | |
| 4 | + | |
| 5 | +QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og) : | |
| 6 | + QPDFValue(::ot_unresolved, "unresolved", qpdf, og) | |
| 7 | +{ | |
| 8 | +} | |
| 9 | + | |
| 10 | +std::shared_ptr<QPDFObject> | |
| 11 | +QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og) | |
| 12 | +{ | |
| 13 | + return do_create(new QPDF_Unresolved(qpdf, og)); | |
| 14 | +} | |
| 15 | + | |
| 16 | +std::shared_ptr<QPDFObject> | |
| 17 | +QPDF_Unresolved::shallowCopy() | |
| 18 | +{ | |
| 19 | + throw std::logic_error( | |
| 20 | + "attempted to shallow copy unresolved QPDFObjectHandle"); | |
| 21 | + return create(qpdf, og); | |
| 22 | +} | |
| 23 | + | |
| 24 | +std::string | |
| 25 | +QPDF_Unresolved::unparse() | |
| 26 | +{ | |
| 27 | + throw std::logic_error( | |
| 28 | + "attempted to unparse an unresolved QPDFObjectHandle"); | |
| 29 | + return ""; | |
| 30 | +} | |
| 31 | + | |
| 32 | +JSON | |
| 33 | +QPDF_Unresolved::getJSON(int json_version) | |
| 34 | +{ | |
| 35 | + return JSON::makeNull(); | |
| 36 | +} | ... | ... |
libqpdf/QPDF_linearization.cc
| ... | ... | @@ -137,8 +137,7 @@ QPDF::isLinearized() |
| 137 | 137 | return false; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | - QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect( | |
| 141 | - this, QPDFObjGen(lindict_obj, 0)); | |
| 140 | + auto candidate = getObjectByID(lindict_obj, 0); | |
| 142 | 141 | if (!candidate.isDictionary()) { |
| 143 | 142 | return false; |
| 144 | 143 | } | ... | ... |
libqpdf/qpdf/QPDF_Array.hh
| 1 | 1 | #ifndef QPDF_ARRAY_HH |
| 2 | 2 | #define QPDF_ARRAY_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | 6 | #include <qpdf/SparseOHArray.hh> |
| 7 | 7 | #include <list> |
| 8 | 8 | #include <vector> |
| 9 | 9 | |
| 10 | -class QPDF_Array: public QPDFObject | |
| 10 | +class QPDF_Array: public QPDFValue | |
| 11 | 11 | { |
| 12 | 12 | public: |
| 13 | 13 | virtual ~QPDF_Array() = default; |
| ... | ... | @@ -17,8 +17,6 @@ class QPDF_Array: public QPDFObject |
| 17 | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | 18 | virtual std::string unparse(); |
| 19 | 19 | virtual JSON getJSON(int json_version); |
| 20 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 21 | - virtual char const* getTypeName() const; | |
| 22 | 20 | |
| 23 | 21 | int getNItems() const; |
| 24 | 22 | QPDFObjectHandle getItem(int n) const; | ... | ... |
libqpdf/qpdf/QPDF_Bool.hh
| 1 | 1 | #ifndef QPDF_BOOL_HH |
| 2 | 2 | #define QPDF_BOOL_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Bool: public QPDFObject | |
| 6 | +class QPDF_Bool: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Bool() = default; |
| ... | ... | @@ -11,8 +11,6 @@ class QPDF_Bool: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | bool getVal() const; |
| 17 | 15 | |
| 18 | 16 | private: | ... | ... |
libqpdf/qpdf/QPDF_Dictionary.hh
| 1 | 1 | #ifndef QPDF_DICTIONARY_HH |
| 2 | 2 | #define QPDF_DICTIONARY_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | 6 | #include <map> |
| 7 | 7 | #include <set> |
| 8 | 8 | |
| 9 | 9 | #include <qpdf/QPDFObjectHandle.hh> |
| 10 | 10 | |
| 11 | -class QPDF_Dictionary: public QPDFObject | |
| 11 | +class QPDF_Dictionary: public QPDFValue | |
| 12 | 12 | { |
| 13 | 13 | public: |
| 14 | 14 | virtual ~QPDF_Dictionary() = default; |
| ... | ... | @@ -17,8 +17,6 @@ class QPDF_Dictionary: public QPDFObject |
| 17 | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | 18 | virtual std::string unparse(); |
| 19 | 19 | virtual JSON getJSON(int json_version); |
| 20 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 21 | - virtual char const* getTypeName() const; | |
| 22 | 20 | |
| 23 | 21 | // hasKey() and getKeys() treat keys with null values as if they |
| 24 | 22 | // aren't there. getKey() returns null for the value of a | ... | ... |
libqpdf/qpdf/QPDF_InlineImage.hh
| 1 | 1 | #ifndef QPDF_INLINEIMAGE_HH |
| 2 | 2 | #define QPDF_INLINEIMAGE_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_InlineImage: public QPDFObject | |
| 6 | +class QPDF_InlineImage: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_InlineImage() = default; |
| ... | ... | @@ -11,8 +11,6 @@ class QPDF_InlineImage: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | std::string getVal() const; |
| 17 | 15 | |
| 18 | 16 | private: | ... | ... |
libqpdf/qpdf/QPDF_Integer.hh
| 1 | 1 | #ifndef QPDF_INTEGER_HH |
| 2 | 2 | #define QPDF_INTEGER_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Integer: public QPDFObject | |
| 6 | +class QPDF_Integer: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Integer() = default; |
| ... | ... | @@ -11,8 +11,6 @@ class QPDF_Integer: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | long long getVal() const; |
| 17 | 15 | |
| 18 | 16 | private: | ... | ... |
libqpdf/qpdf/QPDF_Name.hh
| 1 | 1 | #ifndef QPDF_NAME_HH |
| 2 | 2 | #define QPDF_NAME_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Name: public QPDFObject | |
| 6 | +class QPDF_Name: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Name() = default; |
| ... | ... | @@ -11,8 +11,6 @@ class QPDF_Name: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | std::string getName() const; |
| 17 | 15 | |
| 18 | 16 | // Put # into strings with characters unsuitable for name token | ... | ... |
libqpdf/qpdf/QPDF_Null.hh
| 1 | 1 | #ifndef QPDF_NULL_HH |
| 2 | 2 | #define QPDF_NULL_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Null: public QPDFObject | |
| 6 | +class QPDF_Null: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Null() = default; |
| ... | ... | @@ -11,11 +11,9 @@ class QPDF_Null: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | |
| 17 | 15 | private: |
| 18 | - QPDF_Null() = default; | |
| 16 | + QPDF_Null(); | |
| 19 | 17 | }; |
| 20 | 18 | |
| 21 | 19 | #endif // QPDF_NULL_HH | ... | ... |
libqpdf/qpdf/QPDF_Operator.hh
| 1 | 1 | #ifndef QPDF_OPERATOR_HH |
| 2 | 2 | #define QPDF_OPERATOR_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Operator: public QPDFObject | |
| 6 | +class QPDF_Operator: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Operator() = default; |
| ... | ... | @@ -11,8 +11,6 @@ class QPDF_Operator: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | std::string getVal() const; |
| 17 | 15 | |
| 18 | 16 | private: | ... | ... |
libqpdf/qpdf/QPDF_Real.hh
| 1 | 1 | #ifndef QPDF_REAL_HH |
| 2 | 2 | #define QPDF_REAL_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Real: public QPDFObject | |
| 6 | +class QPDF_Real: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Real() = default; |
| ... | ... | @@ -13,8 +13,6 @@ class QPDF_Real: public QPDFObject |
| 13 | 13 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 14 | 14 | virtual std::string unparse(); |
| 15 | 15 | virtual JSON getJSON(int json_version); |
| 16 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 17 | - virtual char const* getTypeName() const; | |
| 18 | 16 | std::string getVal(); |
| 19 | 17 | |
| 20 | 18 | private: | ... | ... |
libqpdf/qpdf/QPDF_Reserved.hh
| 1 | 1 | #ifndef QPDF_RESERVED_HH |
| 2 | 2 | #define QPDF_RESERVED_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | -class QPDF_Reserved: public QPDFObject | |
| 6 | +class QPDF_Reserved: public QPDFValue | |
| 7 | 7 | { |
| 8 | 8 | public: |
| 9 | 9 | virtual ~QPDF_Reserved() = default; |
| ... | ... | @@ -11,11 +11,9 @@ class QPDF_Reserved: public QPDFObject |
| 11 | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | 12 | virtual std::string unparse(); |
| 13 | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 15 | - virtual char const* getTypeName() const; | |
| 16 | 14 | |
| 17 | 15 | private: |
| 18 | - QPDF_Reserved() = default; | |
| 16 | + QPDF_Reserved(); | |
| 19 | 17 | }; |
| 20 | 18 | |
| 21 | 19 | #endif // QPDF_RESERVED_HH | ... | ... |
libqpdf/qpdf/QPDF_Stream.hh
| ... | ... | @@ -3,9 +3,9 @@ |
| 3 | 3 | |
| 4 | 4 | #include <qpdf/Types.h> |
| 5 | 5 | |
| 6 | -#include <qpdf/QPDFObject.hh> | |
| 7 | 6 | #include <qpdf/QPDFObjectHandle.hh> |
| 8 | 7 | #include <qpdf/QPDFStreamFilter.hh> |
| 8 | +#include <qpdf/QPDFValue.hh> | |
| 9 | 9 | |
| 10 | 10 | #include <functional> |
| 11 | 11 | #include <memory> |
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | class Pipeline; |
| 14 | 14 | class QPDF; |
| 15 | 15 | |
| 16 | -class QPDF_Stream: public QPDFObject | |
| 16 | +class QPDF_Stream: public QPDFValue | |
| 17 | 17 | { |
| 18 | 18 | public: |
| 19 | 19 | virtual ~QPDF_Stream() = default; |
| ... | ... | @@ -26,8 +26,6 @@ class QPDF_Stream: public QPDFObject |
| 26 | 26 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 27 | 27 | virtual std::string unparse(); |
| 28 | 28 | virtual JSON getJSON(int json_version); |
| 29 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 30 | - virtual char const* getTypeName() const; | |
| 31 | 29 | virtual void setDescription(QPDF*, std::string const&); |
| 32 | 30 | QPDFObjectHandle getDict() const; |
| 33 | 31 | bool isDataModified() const; | ... | ... |
libqpdf/qpdf/QPDF_String.hh
| 1 | 1 | #ifndef QPDF_STRING_HH |
| 2 | 2 | #define QPDF_STRING_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFObject.hh> | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | 5 | |
| 6 | 6 | // QPDF_Strings may included embedded null characters. |
| 7 | 7 | |
| 8 | -class QPDF_String: public QPDFObject | |
| 8 | +class QPDF_String: public QPDFValue | |
| 9 | 9 | { |
| 10 | 10 | friend class QPDFWriter; |
| 11 | 11 | |
| ... | ... | @@ -16,8 +16,6 @@ class QPDF_String: public QPDFObject |
| 16 | 16 | create_utf16(std::string const& utf8_val); |
| 17 | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | 18 | virtual std::string unparse(); |
| 19 | - virtual QPDFObject::object_type_e getTypeCode() const; | |
| 20 | - virtual char const* getTypeName() const; | |
| 21 | 19 | std::string unparse(bool force_binary); |
| 22 | 20 | virtual JSON getJSON(int json_version); |
| 23 | 21 | std::string getVal() const; | ... | ... |
libqpdf/qpdf/QPDF_Unresolved.hh
0 → 100644
| 1 | +#ifndef QPDF_UNRESOLVED_HH | |
| 2 | +#define QPDF_UNRESOLVED_HH | |
| 3 | + | |
| 4 | +#include <qpdf/QPDFValue.hh> | |
| 5 | + | |
| 6 | +class QPDF_Unresolved: public QPDFValue | |
| 7 | +{ | |
| 8 | + public: | |
| 9 | + virtual ~QPDF_Unresolved() = default; | |
| 10 | + static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen const& og); | |
| 11 | + virtual std::shared_ptr<QPDFObject> shallowCopy(); | |
| 12 | + virtual std::string unparse(); | |
| 13 | + virtual JSON getJSON(int json_version); | |
| 14 | + | |
| 15 | + private: | |
| 16 | + QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og); | |
| 17 | +}; | |
| 18 | + | |
| 19 | +#endif // QPDF_UNRESOLVED_HH | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -254,7 +254,7 @@ QPDFWriter standard deterministic ID 1 |
| 254 | 254 | QPDFWriter linearized deterministic ID 1 |
| 255 | 255 | QPDFWriter deterministic with no data 0 |
| 256 | 256 | qpdf-c called qpdf_set_deterministic_ID 0 |
| 257 | -QPDFObjectHandle indirect with 0 objid 0 | |
| 257 | +QPDFParser indirect with 0 objid 0 | |
| 258 | 258 | QPDF object id 0 0 |
| 259 | 259 | QPDF recursion loop in resolve 0 |
| 260 | 260 | QPDFParser treat word as string 0 | ... | ... |
qpdf/qtest/qpdf/issue-51.out
| ... | ... | @@ -9,7 +9,6 @@ WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary |
| 9 | 9 | WARNING: issue-51.pdf (object 2 0, offset 71): attempting to recover stream length |
| 10 | 10 | WARNING: issue-51.pdf (object 2 0, offset 71): unable to recover stream data; treating stream as empty |
| 11 | 11 | WARNING: issue-51.pdf (object 2 0, offset 977): expected endobj |
| 12 | -WARNING: issue-51.pdf (object 2 0, offset 977): EOF after endobj | |
| 13 | 12 | WARNING: issue-51.pdf (object 3 0): object has offset 0 |
| 14 | 13 | WARNING: issue-51.pdf (object 4 0): object has offset 0 |
| 15 | 14 | WARNING: issue-51.pdf (object 5 0): object has offset 0 | ... | ... |
qpdf/qtest/type-checks.test
| ... | ... | @@ -14,7 +14,7 @@ cleanup(); |
| 14 | 14 | |
| 15 | 15 | my $td = new TestDriver('type-checks'); |
| 16 | 16 | |
| 17 | -my $n_tests = 5; | |
| 17 | +my $n_tests = 6; | |
| 18 | 18 | |
| 19 | 19 | # Whenever object-types.pdf is edited, object-types-os.pdf should be |
| 20 | 20 | # regenerated. |
| ... | ... | @@ -43,6 +43,10 @@ $td->runtest("compound type checks", |
| 43 | 43 | {$td->COMMAND => "test_driver 82 object-types-os.pdf"}, |
| 44 | 44 | {$td->STRING => "test 82 done\n", $td->EXIT_STATUS => 0}, |
| 45 | 45 | $td->NORMALIZE_NEWLINES); |
| 46 | +$td->runtest("indirect objects belonging to destroyed QPDF", | |
| 47 | + {$td->COMMAND => "test_driver 92 -"}, | |
| 48 | + {$td->STRING => "test 92 done\n", $td->EXIT_STATUS => 0}, | |
| 49 | + $td->NORMALIZE_NEWLINES); | |
| 46 | 50 | |
| 47 | 51 | cleanup(); |
| 48 | 52 | $td->report($n_tests); | ... | ... |
qpdf/test_driver.cc
| ... | ... | @@ -3258,6 +3258,20 @@ test_91(QPDF& pdf, char const* arg2) |
| 3258 | 3258 | 2, &p, qpdf_dl_none, qpdf_sj_inline, "", std::set<std::string>()); |
| 3259 | 3259 | } |
| 3260 | 3260 | |
| 3261 | +static void | |
| 3262 | +test_92(QPDF& pdf, char const* arg2) | |
| 3263 | +{ | |
| 3264 | + // Exercise indirect objects owned by destroyed QPDF object. | |
| 3265 | + QPDF* qpdf = new QPDF(); | |
| 3266 | + qpdf->emptyPDF(); | |
| 3267 | + auto root = qpdf->getRoot(); | |
| 3268 | + assert(root.getOwningQPDF() != nullptr); | |
| 3269 | + assert(root.isIndirect()); | |
| 3270 | + delete qpdf; | |
| 3271 | + assert(root.getOwningQPDF() == nullptr); | |
| 3272 | + assert(!root.isIndirect()); | |
| 3273 | +} | |
| 3274 | + | |
| 3261 | 3275 | void |
| 3262 | 3276 | runtest(int n, char const* filename1, char const* arg2) |
| 3263 | 3277 | { |
| ... | ... | @@ -3265,7 +3279,7 @@ runtest(int n, char const* filename1, char const* arg2) |
| 3265 | 3279 | // the test suite to see how the test is invoked to find the file |
| 3266 | 3280 | // that the test is supposed to operate on. |
| 3267 | 3281 | |
| 3268 | - std::set<int> ignore_filename = {61, 81, 83, 84, 85, 86, 87}; | |
| 3282 | + std::set<int> ignore_filename = {61, 81, 83, 84, 85, 86, 87, 92}; | |
| 3269 | 3283 | |
| 3270 | 3284 | if (n == 0) { |
| 3271 | 3285 | // Throw in some random test cases that don't fit anywhere |
| ... | ... | @@ -3362,7 +3376,8 @@ runtest(int n, char const* filename1, char const* arg2) |
| 3362 | 3376 | {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, |
| 3363 | 3377 | {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, |
| 3364 | 3378 | {84, test_84}, {85, test_85}, {86, test_86}, {87, test_87}, |
| 3365 | - {88, test_88}, {89, test_89}, {90, test_90}, {91, test_91}}; | |
| 3379 | + {88, test_88}, {89, test_89}, {90, test_90}, {91, test_91}, | |
| 3380 | + {92, test_92}}; | |
| 3366 | 3381 | |
| 3367 | 3382 | auto fn = test_functions.find(n); |
| 3368 | 3383 | if (fn == test_functions.end()) { | ... | ... |