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,6 +82,8 @@ enum qpdf_object_type_e { | ||
| 82 | /* Additional object types that can occur in content streams */ | 82 | /* Additional object types that can occur in content streams */ |
| 83 | ot_operator, | 83 | ot_operator, |
| 84 | ot_inlineimage, | 84 | ot_inlineimage, |
| 85 | + /* Object types internal to qpdf */ | ||
| 86 | + ot_unresolved, | ||
| 85 | /* NOTE: if adding to this list, update QPDFObject.hh */ | 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,19 +843,13 @@ class QPDF | ||
| 843 | // it can resolve indirect references. | 843 | // it can resolve indirect references. |
| 844 | class Resolver | 844 | class Resolver |
| 845 | { | 845 | { |
| 846 | - friend class QPDFObjectHandle; | 846 | + friend class QPDFObject; |
| 847 | 847 | ||
| 848 | private: | 848 | private: |
| 849 | - static std::shared_ptr<QPDFObject> | 849 | + static void |
| 850 | resolve(QPDF* qpdf, QPDFObjGen const& og) | 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 | friend class Resolver; | 855 | friend class Resolver; |
| @@ -1174,12 +1168,20 @@ class QPDF | @@ -1174,12 +1168,20 @@ class QPDF | ||
| 1174 | std::string const& description, | 1168 | std::string const& description, |
| 1175 | QPDFObjGen const& exp_og, | 1169 | QPDFObjGen const& exp_og, |
| 1176 | QPDFObjGen& og); | 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 | void resolveObjectsInStream(int obj_stream_number); | 1172 | void resolveObjectsInStream(int obj_stream_number); |
| 1180 | void stopOnError(std::string const& message); | 1173 | void stopOnError(std::string const& message); |
| 1181 | QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); | 1174 | QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); |
| 1182 | QPDFObjectHandle reserveStream(QPDFObjGen const& og); | 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 | // Calls finish() on the pipeline when done but does not delete it | 1186 | // Calls finish() on the pipeline when done but does not delete it |
| 1185 | bool pipeStreamData( | 1187 | bool pipeStreamData( |
| @@ -1727,7 +1729,6 @@ class QPDF | @@ -1727,7 +1729,6 @@ class QPDF | ||
| 1727 | bool in_parse; | 1729 | bool in_parse; |
| 1728 | bool parsed; | 1730 | bool parsed; |
| 1729 | std::set<int> resolved_object_streams; | 1731 | std::set<int> resolved_object_streams; |
| 1730 | - bool ever_replaced_objects; | ||
| 1731 | 1732 | ||
| 1732 | // Linearization data | 1733 | // Linearization data |
| 1733 | qpdf_offset_t first_xref_item_offset; // actual value from file | 1734 | qpdf_offset_t first_xref_item_offset; // actual value from file |
include/qpdf/QPDFObject.hh
| @@ -25,6 +25,7 @@ | @@ -25,6 +25,7 @@ | ||
| 25 | #include <qpdf/Constants.h> | 25 | #include <qpdf/Constants.h> |
| 26 | #include <qpdf/DLL.h> | 26 | #include <qpdf/DLL.h> |
| 27 | #include <qpdf/JSON.hh> | 27 | #include <qpdf/JSON.hh> |
| 28 | +#include <qpdf/QPDFValue.hh> | ||
| 28 | #include <qpdf/Types.h> | 29 | #include <qpdf/Types.h> |
| 29 | 30 | ||
| 30 | #include <string> | 31 | #include <string> |
| @@ -34,9 +35,9 @@ class QPDFObjectHandle; | @@ -34,9 +35,9 @@ class QPDFObjectHandle; | ||
| 34 | 35 | ||
| 35 | class QPDFObject | 36 | class QPDFObject |
| 36 | { | 37 | { |
| 37 | - public: | ||
| 38 | - QPDFObject(); | 38 | + friend class QPDFValue; |
| 39 | 39 | ||
| 40 | + public: | ||
| 40 | // Objects derived from QPDFObject are accessible through | 41 | // Objects derived from QPDFObject are accessible through |
| 41 | // QPDFObjectHandle. Each object returns a unique type code that | 42 | // QPDFObjectHandle. Each object returns a unique type code that |
| 42 | // has one of the valid qpdf_object_type_e values. As new object | 43 | // has one of the valid qpdf_object_type_e values. As new object |
| @@ -61,18 +62,128 @@ class QPDFObject | @@ -61,18 +62,128 @@ class QPDFObject | ||
| 61 | static constexpr object_type_e ot_stream = ::ot_stream; | 62 | static constexpr object_type_e ot_stream = ::ot_stream; |
| 62 | static constexpr object_type_e ot_operator = ::ot_operator; | 63 | static constexpr object_type_e ot_operator = ::ot_operator; |
| 63 | static constexpr object_type_e ot_inlineimage = ::ot_inlineimage; | 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 | virtual ~QPDFObject() = default; | 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 | // Return a unique type code for the object | 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 | // Return a string literal that describes the type, useful for | 93 | // Return a string literal that describes the type, useful for |
| 74 | // debugging and testing | 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 | // Accessor to give specific access to non-public methods | 188 | // Accessor to give specific access to non-public methods |
| 78 | class ObjAccessor | 189 | class ObjAccessor |
| @@ -89,29 +200,20 @@ class QPDFObject | @@ -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 | protected: | 206 | protected: |
| 102 | virtual void | 207 | virtual void |
| 103 | releaseResolved() | 208 | releaseResolved() |
| 104 | { | 209 | { |
| 210 | + value->releaseResolved(); | ||
| 105 | } | 211 | } |
| 106 | - static std::shared_ptr<QPDFObject> do_create(QPDFObject*); | ||
| 107 | 212 | ||
| 108 | private: | 213 | private: |
| 109 | QPDFObject(QPDFObject const&) = delete; | 214 | QPDFObject(QPDFObject const&) = delete; |
| 110 | QPDFObject& operator=(QPDFObject const&) = delete; | 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 | #endif // QPDFOBJECT_HH | 219 | #endif // QPDFOBJECT_HH |
include/qpdf/QPDFObjectHandle.hh
| @@ -43,8 +43,18 @@ | @@ -43,8 +43,18 @@ | ||
| 43 | 43 | ||
| 44 | class Pipeline; | 44 | class Pipeline; |
| 45 | class QPDF; | 45 | class QPDF; |
| 46 | -class QPDF_Dictionary; | ||
| 47 | class QPDF_Array; | 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 | class QPDFTokenizer; | 58 | class QPDFTokenizer; |
| 49 | class QPDFExc; | 59 | class QPDFExc; |
| 50 | class Pl_QPDFTokenizer; | 60 | class Pl_QPDFTokenizer; |
| @@ -316,7 +326,7 @@ class QPDFObjectHandle | @@ -316,7 +326,7 @@ class QPDFObjectHandle | ||
| 316 | }; | 326 | }; |
| 317 | 327 | ||
| 318 | QPDF_DLL | 328 | QPDF_DLL |
| 319 | - QPDFObjectHandle(); | 329 | + QPDFObjectHandle() = default; |
| 320 | QPDF_DLL | 330 | QPDF_DLL |
| 321 | QPDFObjectHandle(QPDFObjectHandle const&) = default; | 331 | QPDFObjectHandle(QPDFObjectHandle const&) = default; |
| 322 | QPDF_DLL | 332 | QPDF_DLL |
| @@ -963,8 +973,8 @@ class QPDFObjectHandle | @@ -963,8 +973,8 @@ class QPDFObjectHandle | ||
| 963 | // null for a direct object if allow_nullptr is set to true or | 973 | // null for a direct object if allow_nullptr is set to true or |
| 964 | // throws a runtime error otherwise. | 974 | // throws a runtime error otherwise. |
| 965 | QPDF_DLL | 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 | // Create a shallow copy of an object as a direct object, but do not | 979 | // Create a shallow copy of an object as a direct object, but do not |
| 970 | // traverse across indirect object boundaries. That means that, | 980 | // traverse across indirect object boundaries. That means that, |
| @@ -1443,9 +1453,9 @@ class QPDFObjectHandle | @@ -1443,9 +1453,9 @@ class QPDFObjectHandle | ||
| 1443 | 1453 | ||
| 1444 | private: | 1454 | private: |
| 1445 | static QPDFObjectHandle | 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 | static QPDFObjectHandle | 1460 | static QPDFObjectHandle |
| 1451 | newStream( | 1461 | newStream( |
| @@ -1458,12 +1468,6 @@ class QPDFObjectHandle | @@ -1458,12 +1468,6 @@ class QPDFObjectHandle | ||
| 1458 | return QPDFObjectHandle::newStream( | 1468 | return QPDFObjectHandle::newStream( |
| 1459 | qpdf, og, stream_dict, offset, length); | 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 | friend class Factory; | 1472 | friend class Factory; |
| 1469 | 1473 | ||
| @@ -1483,6 +1487,16 @@ class QPDFObjectHandle | @@ -1483,6 +1487,16 @@ class QPDFObjectHandle | ||
| 1483 | }; | 1487 | }; |
| 1484 | return o.obj; | 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 | friend class ObjAccessor; | 1501 | friend class ObjAccessor; |
| 1488 | 1502 | ||
| @@ -1563,18 +1577,32 @@ class QPDFObjectHandle | @@ -1563,18 +1577,32 @@ class QPDFObjectHandle | ||
| 1563 | bool isImage(bool exclude_imagemask = true); | 1577 | bool isImage(bool exclude_imagemask = true); |
| 1564 | 1578 | ||
| 1565 | private: | 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 | // Private object factory methods | 1585 | // Private object factory methods |
| 1570 | - static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og); | ||
| 1571 | static QPDFObjectHandle newStream( | 1586 | static QPDFObjectHandle newStream( |
| 1572 | QPDF* qpdf, | 1587 | QPDF* qpdf, |
| 1573 | QPDFObjGen const& og, | 1588 | QPDFObjGen const& og, |
| 1574 | QPDFObjectHandle stream_dict, | 1589 | QPDFObjectHandle stream_dict, |
| 1575 | qpdf_offset_t offset, | 1590 | qpdf_offset_t offset, |
| 1576 | size_t length); | 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 | void typeWarning(char const* expected_type, std::string const& warning); | 1607 | void typeWarning(char const* expected_type, std::string const& warning); |
| 1580 | void objectWarning(std::string const& warning); | 1608 | void objectWarning(std::string const& warning); |
| @@ -1601,15 +1629,10 @@ class QPDFObjectHandle | @@ -1601,15 +1629,10 @@ class QPDFObjectHandle | ||
| 1601 | static void warn(QPDF*, QPDFExc const&); | 1629 | static void warn(QPDF*, QPDFExc const&); |
| 1602 | void checkOwnership(QPDFObjectHandle const&) const; | 1630 | void checkOwnership(QPDFObjectHandle const&) const; |
| 1603 | 1631 | ||
| 1604 | - bool initialized; | ||
| 1605 | - | ||
| 1606 | // Moving members of QPDFObjectHandle into a smart pointer incurs | 1632 | // Moving members of QPDFObjectHandle into a smart pointer incurs |
| 1607 | // a substantial performance penalty since QPDFObjectHandle | 1633 | // a substantial performance penalty since QPDFObjectHandle |
| 1608 | // objects are copied around so frequently. | 1634 | // objects are copied around so frequently. |
| 1609 | - QPDF* qpdf; | ||
| 1610 | - QPDFObjGen og; | ||
| 1611 | std::shared_ptr<QPDFObject> obj; | 1635 | std::shared_ptr<QPDFObject> obj; |
| 1612 | - bool reserved; | ||
| 1613 | }; | 1636 | }; |
| 1614 | 1637 | ||
| 1615 | #ifndef QPDF_NO_QPDF_STRING | 1638 | #ifndef QPDF_NO_QPDF_STRING |
| @@ -1832,44 +1855,45 @@ class QPDFObjectHandle::QPDFArrayItems | @@ -1832,44 +1855,45 @@ class QPDFObjectHandle::QPDFArrayItems | ||
| 1832 | inline QPDFObjGen | 1855 | inline QPDFObjGen |
| 1833 | QPDFObjectHandle::getObjGen() const | 1856 | QPDFObjectHandle::getObjGen() const |
| 1834 | { | 1857 | { |
| 1835 | - return og; | 1858 | + return isInitialized() ? obj->getObjGen() : QPDFObjGen(); |
| 1836 | } | 1859 | } |
| 1837 | 1860 | ||
| 1838 | inline int | 1861 | inline int |
| 1839 | QPDFObjectHandle::getObjectID() const | 1862 | QPDFObjectHandle::getObjectID() const |
| 1840 | { | 1863 | { |
| 1841 | - return og.getObj(); | 1864 | + return getObjGen().getObj(); |
| 1842 | } | 1865 | } |
| 1843 | 1866 | ||
| 1844 | inline int | 1867 | inline int |
| 1845 | QPDFObjectHandle::getGeneration() const | 1868 | QPDFObjectHandle::getGeneration() const |
| 1846 | { | 1869 | { |
| 1847 | - return og.getGen(); | 1870 | + return getObjGen().getGen(); |
| 1848 | } | 1871 | } |
| 1849 | 1872 | ||
| 1850 | inline bool | 1873 | inline bool |
| 1851 | QPDFObjectHandle::isIndirect() const | 1874 | QPDFObjectHandle::isIndirect() const |
| 1852 | { | 1875 | { |
| 1853 | - return initialized && (getObjectID() != 0); | 1876 | + return (obj != nullptr) && (getObjectID() != 0); |
| 1854 | } | 1877 | } |
| 1855 | 1878 | ||
| 1856 | inline bool | 1879 | inline bool |
| 1857 | QPDFObjectHandle::isInitialized() const | 1880 | QPDFObjectHandle::isInitialized() const |
| 1858 | { | 1881 | { |
| 1859 | - return initialized; | 1882 | + return obj != nullptr; |
| 1860 | } | 1883 | } |
| 1861 | 1884 | ||
| 1862 | // Indirect object accessors | 1885 | // Indirect object accessors |
| 1863 | inline QPDF* | 1886 | inline QPDF* |
| 1864 | QPDFObjectHandle::getOwningQPDF( | 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 | // Will be null for direct objects | 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 | throw std::runtime_error( | 1893 | throw std::runtime_error( |
| 1870 | error_msg == "" ? "attempt to use a null qpdf object" : error_msg); | 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 | inline void | 1899 | inline void |
| @@ -1877,7 +1901,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) | @@ -1877,7 +1901,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) | ||
| 1877 | { | 1901 | { |
| 1878 | // This is called during parsing on newly created direct objects, | 1902 | // This is called during parsing on newly created direct objects, |
| 1879 | // so we can't call dereference() here. | 1903 | // so we can't call dereference() here. |
| 1880 | - if (this->obj.get()) { | 1904 | + if (isInitialized()) { |
| 1881 | this->obj->setParsedOffset(offset); | 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,6 +85,7 @@ set(libqpdf_SOURCES | ||
| 85 | QPDFSystemError.cc | 85 | QPDFSystemError.cc |
| 86 | QPDFTokenizer.cc | 86 | QPDFTokenizer.cc |
| 87 | QPDFUsage.cc | 87 | QPDFUsage.cc |
| 88 | + QPDFValue.cc | ||
| 88 | QPDFWriter.cc | 89 | QPDFWriter.cc |
| 89 | QPDFXRefEntry.cc | 90 | QPDFXRefEntry.cc |
| 90 | QPDF_Array.cc | 91 | QPDF_Array.cc |
| @@ -99,6 +100,7 @@ set(libqpdf_SOURCES | @@ -99,6 +100,7 @@ set(libqpdf_SOURCES | ||
| 99 | QPDF_Reserved.cc | 100 | QPDF_Reserved.cc |
| 100 | QPDF_Stream.cc | 101 | QPDF_Stream.cc |
| 101 | QPDF_String.cc | 102 | QPDF_String.cc |
| 103 | + QPDF_Unresolved.cc | ||
| 102 | QPDF_encryption.cc | 104 | QPDF_encryption.cc |
| 103 | QPDF_json.cc | 105 | QPDF_json.cc |
| 104 | QPDF_linearization.cc | 106 | QPDF_linearization.cc |
libqpdf/QPDF.cc
| @@ -24,7 +24,9 @@ | @@ -24,7 +24,9 @@ | ||
| 24 | #include <qpdf/QPDF_Array.hh> | 24 | #include <qpdf/QPDF_Array.hh> |
| 25 | #include <qpdf/QPDF_Dictionary.hh> | 25 | #include <qpdf/QPDF_Dictionary.hh> |
| 26 | #include <qpdf/QPDF_Null.hh> | 26 | #include <qpdf/QPDF_Null.hh> |
| 27 | +#include <qpdf/QPDF_Reserved.hh> | ||
| 27 | #include <qpdf/QPDF_Stream.hh> | 28 | #include <qpdf/QPDF_Stream.hh> |
| 29 | +#include <qpdf/QPDF_Unresolved.hh> | ||
| 28 | #include <qpdf/QTC.hh> | 30 | #include <qpdf/QTC.hh> |
| 29 | #include <qpdf/QUtil.hh> | 31 | #include <qpdf/QUtil.hh> |
| 30 | 32 | ||
| @@ -222,7 +224,6 @@ QPDF::Members::Members() : | @@ -222,7 +224,6 @@ QPDF::Members::Members() : | ||
| 222 | immediate_copy_from(false), | 224 | immediate_copy_from(false), |
| 223 | in_parse(false), | 225 | in_parse(false), |
| 224 | parsed(false), | 226 | parsed(false), |
| 225 | - ever_replaced_objects(false), | ||
| 226 | first_xref_item_offset(0), | 227 | first_xref_item_offset(0), |
| 227 | uncompressed_after_compressed(false) | 228 | uncompressed_after_compressed(false) |
| 228 | { | 229 | { |
| @@ -258,6 +259,7 @@ QPDF::~QPDF() | @@ -258,6 +259,7 @@ QPDF::~QPDF() | ||
| 258 | this->m->xref_table.clear(); | 259 | this->m->xref_table.clear(); |
| 259 | for (auto const& iter: this->m->obj_cache) { | 260 | for (auto const& iter: this->m->obj_cache) { |
| 260 | QPDFObject::ObjAccessor::releaseResolved(iter.second.object.get()); | 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,7 +1399,7 @@ QPDF::fixDanglingReferences(bool force) | ||
| 1397 | std::list<QPDFObjectHandle> queue; | 1399 | std::list<QPDFObjectHandle> queue; |
| 1398 | queue.push_back(this->m->trailer); | 1400 | queue.push_back(this->m->trailer); |
| 1399 | for (auto const& og: to_process) { | 1401 | for (auto const& og: to_process) { |
| 1400 | - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og); | 1402 | + auto obj = getObject(og); |
| 1401 | if (obj.isDictionary() || obj.isArray()) { | 1403 | if (obj.isDictionary() || obj.isArray()) { |
| 1402 | queue.push_back(obj); | 1404 | queue.push_back(obj); |
| 1403 | } else if (obj.isStream()) { | 1405 | } else if (obj.isStream()) { |
| @@ -1419,18 +1421,15 @@ QPDF::fixDanglingReferences(bool force) | @@ -1419,18 +1421,15 @@ QPDF::fixDanglingReferences(bool force) | ||
| 1419 | to_check.push_back(iter.second); | 1421 | to_check.push_back(iter.second); |
| 1420 | } | 1422 | } |
| 1421 | } else if (obj.isArray()) { | 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 | arr->addExplicitElementsToList(to_check); | 1425 | arr->addExplicitElementsToList(to_check); |
| 1425 | } | 1426 | } |
| 1426 | for (auto sub: to_check) { | 1427 | for (auto sub: to_check) { |
| 1427 | if (sub.isIndirect()) { | 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 | } else { | 1434 | } else { |
| 1436 | queue.push_back(sub); | 1435 | queue.push_back(sub); |
| @@ -1462,8 +1461,7 @@ QPDF::getAllObjects() | @@ -1462,8 +1461,7 @@ QPDF::getAllObjects() | ||
| 1462 | fixDanglingReferences(true); | 1461 | fixDanglingReferences(true); |
| 1463 | std::vector<QPDFObjectHandle> result; | 1462 | std::vector<QPDFObjectHandle> result; |
| 1464 | for (auto const& iter: this->m->obj_cache) { | 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 | return result; | 1466 | return result; |
| 1469 | } | 1467 | } |
| @@ -1888,7 +1886,7 @@ QPDF::readObjectAtOffset( | @@ -1888,7 +1886,7 @@ QPDF::readObjectAtOffset( | ||
| 1888 | "expected endobj"); | 1886 | "expected endobj"); |
| 1889 | } | 1887 | } |
| 1890 | 1888 | ||
| 1891 | - if (!this->m->obj_cache.count(og)) { | 1889 | + if (isUnresolved(og)) { |
| 1892 | // Store the object in the cache here so it gets cached | 1890 | // Store the object in the cache here so it gets cached |
| 1893 | // whether we first know the offset or whether we first know | 1891 | // whether we first know the offset or whether we first know |
| 1894 | // the object ID and generation (in which we case we would get | 1892 | // the object ID and generation (in which we case we would get |
| @@ -1919,8 +1917,8 @@ QPDF::readObjectAtOffset( | @@ -1919,8 +1917,8 @@ QPDF::readObjectAtOffset( | ||
| 1919 | } | 1917 | } |
| 1920 | } | 1918 | } |
| 1921 | qpdf_offset_t end_after_space = this->m->file->tell(); | 1919 | qpdf_offset_t end_after_space = this->m->file->tell(); |
| 1922 | - | ||
| 1923 | - this->m->obj_cache[og] = ObjCache( | 1920 | + updateCache( |
| 1921 | + og, | ||
| 1924 | QPDFObjectHandle::ObjAccessor::getObject(oh), | 1922 | QPDFObjectHandle::ObjAccessor::getObject(oh), |
| 1925 | end_before_space, | 1923 | end_before_space, |
| 1926 | end_after_space); | 1924 | end_after_space); |
| @@ -1929,31 +1927,14 @@ QPDF::readObjectAtOffset( | @@ -1929,31 +1927,14 @@ QPDF::readObjectAtOffset( | ||
| 1929 | return oh; | 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 | QPDF::resolve(QPDFObjGen const& og) | 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 | // Check object cache before checking xref table. This allows us | 1938 | // Check object cache before checking xref table. This allows us |
| 1958 | // to insert things into the object cache that don't actually | 1939 | // to insert things into the object cache that don't actually |
| 1959 | // exist in the file. | 1940 | // exist in the file. |
| @@ -1967,11 +1948,12 @@ QPDF::resolve(QPDFObjGen const& og) | @@ -1967,11 +1948,12 @@ QPDF::resolve(QPDFObjGen const& og) | ||
| 1967 | "", | 1948 | "", |
| 1968 | this->m->file->getLastOffset(), | 1949 | this->m->file->getLastOffset(), |
| 1969 | ("loop detected resolving object " + og.unparse(' '))); | 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 | ResolveRecorder rr(this, og); | 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 | QPDFXRefEntry const& entry = this->m->xref_table[og]; | 1957 | QPDFXRefEntry const& entry = this->m->xref_table[og]; |
| 1976 | try { | 1958 | try { |
| 1977 | switch (entry.getType()) { | 1959 | switch (entry.getType()) { |
| @@ -2009,19 +1991,17 @@ QPDF::resolve(QPDFObjGen const& og) | @@ -2009,19 +1991,17 @@ QPDF::resolve(QPDFObjGen const& og) | ||
| 2009 | ": error reading object: " + e.what())); | 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 | // PDF spec says unknown objects resolve to the null object. | 1996 | // PDF spec says unknown objects resolve to the null object. |
| 2014 | QTC::TC("qpdf", "QPDF resolve failure to null"); | 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 | if (!result->hasDescription()) { | 2002 | if (!result->hasDescription()) { |
| 2022 | result->setDescription(this, ("object " + og.unparse(' '))); | 2003 | result->setDescription(this, ("object " + og.unparse(' '))); |
| 2023 | } | 2004 | } |
| 2024 | - return result; | ||
| 2025 | } | 2005 | } |
| 2026 | 2006 | ||
| 2027 | void | 2007 | void |
| @@ -2109,15 +2089,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | @@ -2109,15 +2089,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | ||
| 2109 | // objects appended to the file, so it is necessary to recheck the | 2089 | // objects appended to the file, so it is necessary to recheck the |
| 2110 | // xref table and only cache what would actually be resolved here. | 2090 | // xref table and only cache what would actually be resolved here. |
| 2111 | for (auto const& iter: offsets) { | 2091 | for (auto const& iter: offsets) { |
| 2112 | - int obj = iter.first; | ||
| 2113 | - QPDFObjGen og(obj, 0); | 2092 | + QPDFObjGen og(iter.first, 0); |
| 2114 | QPDFXRefEntry const& entry = this->m->xref_table[og]; | 2093 | QPDFXRefEntry const& entry = this->m->xref_table[og]; |
| 2115 | if ((entry.getType() == 2) && | 2094 | if ((entry.getType() == 2) && |
| 2116 | (entry.getObjStreamNumber() == obj_stream_number)) { | 2095 | (entry.getObjStreamNumber() == obj_stream_number)) { |
| 2117 | int offset = iter.second; | 2096 | int offset = iter.second; |
| 2118 | input->seek(offset, SEEK_SET); | 2097 | input->seek(offset, SEEK_SET); |
| 2119 | QPDFObjectHandle oh = readObject(input, "", og, true); | 2098 | QPDFObjectHandle oh = readObject(input, "", og, true); |
| 2120 | - this->m->obj_cache[og] = ObjCache( | 2099 | + updateCache( |
| 2100 | + og, | ||
| 2121 | QPDFObjectHandle::ObjAccessor::getObject(oh), | 2101 | QPDFObjectHandle::ObjAccessor::getObject(oh), |
| 2122 | end_before_space, | 2102 | end_before_space, |
| 2123 | end_after_space); | 2103 | end_after_space); |
| @@ -2128,6 +2108,47 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | @@ -2128,6 +2108,47 @@ QPDF::resolveObjectsInStream(int obj_stream_number) | ||
| 2128 | } | 2108 | } |
| 2129 | 2109 | ||
| 2130 | QPDFObjectHandle | 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 | QPDF::makeIndirectObject(QPDFObjectHandle oh) | 2152 | QPDF::makeIndirectObject(QPDFObjectHandle oh) |
| 2132 | { | 2153 | { |
| 2133 | int max_objid = toI(getObjectCount()); | 2154 | int max_objid = toI(getObjectCount()); |
| @@ -2136,19 +2157,21 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) | @@ -2136,19 +2157,21 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) | ||
| 2136 | "max object id is too high to create new objects"); | 2157 | "max object id is too high to create new objects"); |
| 2137 | } | 2158 | } |
| 2138 | QPDFObjGen next(max_objid + 1, 0); | 2159 | QPDFObjGen next(max_objid + 1, 0); |
| 2139 | - this->m->obj_cache[next] = | 2160 | + m->obj_cache[next] = |
| 2140 | ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); | 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 | QPDFObjectHandle | 2165 | QPDFObjectHandle |
| 2145 | QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) | 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 | resolve(og); | 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 | QPDFObjectHandle | 2177 | QPDFObjectHandle |
| @@ -2161,7 +2184,13 @@ QPDF::reserveStream(QPDFObjGen const& og) | @@ -2161,7 +2184,13 @@ QPDF::reserveStream(QPDFObjGen const& og) | ||
| 2161 | QPDFObjectHandle | 2184 | QPDFObjectHandle |
| 2162 | QPDF::getObject(QPDFObjGen const& og) | 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 | QPDFObjectHandle | 2196 | QPDFObjectHandle |
| @@ -2196,14 +2225,11 @@ QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) | @@ -2196,14 +2225,11 @@ QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) | ||
| 2196 | throw std::logic_error( | 2225 | throw std::logic_error( |
| 2197 | "QPDF::replaceObject called with indirect object handle"); | 2226 | "QPDF::replaceObject called with indirect object handle"); |
| 2198 | } | 2227 | } |
| 2199 | - | ||
| 2200 | // Force new object to appear in the cache | 2228 | // Force new object to appear in the cache |
| 2201 | resolve(og); | 2229 | resolve(og); |
| 2202 | 2230 | ||
| 2203 | // Replace the object in the object cache | 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 | void | 2235 | void |
| @@ -2456,12 +2482,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) | @@ -2456,12 +2482,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) | ||
| 2456 | QPDFObjGen local_og(result.getObjGen()); | 2482 | QPDFObjGen local_og(result.getObjGen()); |
| 2457 | // Copy information from the foreign stream so we can pipe its | 2483 | // Copy information from the foreign stream so we can pipe its |
| 2458 | // data later without keeping the original QPDF object around. | 2484 | // data later without keeping the original QPDF object around. |
| 2485 | + | ||
| 2459 | QPDF* foreign_stream_qpdf = foreign.getOwningQPDF( | 2486 | QPDF* foreign_stream_qpdf = foreign.getOwningQPDF( |
| 2460 | false, "unable to retrieve owning qpdf from foreign stream"); | 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 | throw std::logic_error("unable to retrieve underlying" | 2491 | throw std::logic_error("unable to retrieve underlying" |
| 2466 | " stream object from foreign stream"); | 2492 | " stream object from foreign stream"); |
| 2467 | } | 2493 | } |
| @@ -2525,10 +2551,7 @@ QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) | @@ -2525,10 +2551,7 @@ QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) | ||
| 2525 | // cache. | 2551 | // cache. |
| 2526 | resolve(og1); | 2552 | resolve(og1); |
| 2527 | resolve(og2); | 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 | unsigned long long | 2557 | unsigned long long |
libqpdf/QPDFObject.cc
| 1 | #include <qpdf/QPDFObject.hh> | 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 | void | 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,6 +21,7 @@ | ||
| 21 | #include <qpdf/QPDF_Reserved.hh> | 21 | #include <qpdf/QPDF_Reserved.hh> |
| 22 | #include <qpdf/QPDF_Stream.hh> | 22 | #include <qpdf/QPDF_Stream.hh> |
| 23 | #include <qpdf/QPDF_String.hh> | 23 | #include <qpdf/QPDF_String.hh> |
| 24 | +#include <qpdf/QPDF_Unresolved.hh> | ||
| 24 | #include <qpdf/SparseOHArray.hh> | 25 | #include <qpdf/SparseOHArray.hh> |
| 25 | 26 | ||
| 26 | #include <qpdf/QIntC.hh> | 27 | #include <qpdf/QIntC.hh> |
| @@ -234,29 +235,6 @@ LastChar::getLastChar() | @@ -234,29 +235,6 @@ LastChar::getLastChar() | ||
| 234 | return this->last_char; | 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 | void | 238 | void |
| 261 | QPDFObjectHandle::releaseResolved() | 239 | QPDFObjectHandle::releaseResolved() |
| 262 | { | 240 | { |
| @@ -286,24 +264,90 @@ QPDFObjectHandle::getTypeName() | @@ -286,24 +264,90 @@ QPDFObjectHandle::getTypeName() | ||
| 286 | return dereference() ? this->obj->getTypeName() : "uninitialized"; | 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 | bool | 347 | bool |
| 304 | QPDFObjectHandle::isBool() | 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 | bool | 353 | bool |
| @@ -312,26 +356,26 @@ QPDFObjectHandle::isDirectNull() const | @@ -312,26 +356,26 @@ QPDFObjectHandle::isDirectNull() const | ||
| 312 | // Don't call dereference() -- this is a const method, and we know | 356 | // Don't call dereference() -- this is a const method, and we know |
| 313 | // objid == 0, so there's nothing to resolve. | 357 | // objid == 0, so there's nothing to resolve. |
| 314 | return ( | 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 | bool | 363 | bool |
| 320 | QPDFObjectHandle::isNull() | 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 | bool | 369 | bool |
| 326 | QPDFObjectHandle::isInteger() | 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 | bool | 375 | bool |
| 332 | QPDFObjectHandle::isReal() | 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 | bool | 381 | bool |
| @@ -368,51 +412,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) | @@ -368,51 +412,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) | ||
| 368 | bool | 412 | bool |
| 369 | QPDFObjectHandle::isName() | 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 | bool | 418 | bool |
| 375 | QPDFObjectHandle::isString() | 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 | bool | 424 | bool |
| 381 | QPDFObjectHandle::isOperator() | 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 | bool | 430 | bool |
| 387 | QPDFObjectHandle::isInlineImage() | 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 | bool | 436 | bool |
| 394 | QPDFObjectHandle::isArray() | 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 | bool | 442 | bool |
| 400 | QPDFObjectHandle::isDictionary() | 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 | bool | 448 | bool |
| 406 | QPDFObjectHandle::isStream() | 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 | bool | 454 | bool |
| 412 | QPDFObjectHandle::isReserved() | 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 | bool | 460 | bool |
| @@ -450,8 +492,9 @@ QPDFObjectHandle::isStreamOfType( | @@ -450,8 +492,9 @@ QPDFObjectHandle::isStreamOfType( | ||
| 450 | bool | 492 | bool |
| 451 | QPDFObjectHandle::getBoolValue() | 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 | } else { | 498 | } else { |
| 456 | typeWarning("boolean", "returning false"); | 499 | typeWarning("boolean", "returning false"); |
| 457 | QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); | 500 | QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); |
| @@ -462,10 +505,11 @@ QPDFObjectHandle::getBoolValue() | @@ -462,10 +505,11 @@ QPDFObjectHandle::getBoolValue() | ||
| 462 | bool | 505 | bool |
| 463 | QPDFObjectHandle::getValueAsBool(bool& value) | 506 | QPDFObjectHandle::getValueAsBool(bool& value) |
| 464 | { | 507 | { |
| 465 | - if (!isBool()) { | 508 | + auto boolean = asBool(); |
| 509 | + if (boolean == nullptr) { | ||
| 466 | return false; | 510 | return false; |
| 467 | } | 511 | } |
| 468 | - value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); | 512 | + value = boolean->getVal(); |
| 469 | return true; | 513 | return true; |
| 470 | } | 514 | } |
| 471 | 515 | ||
| @@ -474,8 +518,9 @@ QPDFObjectHandle::getValueAsBool(bool& value) | @@ -474,8 +518,9 @@ QPDFObjectHandle::getValueAsBool(bool& value) | ||
| 474 | long long | 518 | long long |
| 475 | QPDFObjectHandle::getIntValue() | 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 | } else { | 524 | } else { |
| 480 | typeWarning("integer", "returning 0"); | 525 | typeWarning("integer", "returning 0"); |
| 481 | QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); | 526 | QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); |
| @@ -486,10 +531,11 @@ QPDFObjectHandle::getIntValue() | @@ -486,10 +531,11 @@ QPDFObjectHandle::getIntValue() | ||
| 486 | bool | 531 | bool |
| 487 | QPDFObjectHandle::getValueAsInt(long long& value) | 532 | QPDFObjectHandle::getValueAsInt(long long& value) |
| 488 | { | 533 | { |
| 489 | - if (!isInteger()) { | 534 | + auto integer = asInteger(); |
| 535 | + if (integer == nullptr) { | ||
| 490 | return false; | 536 | return false; |
| 491 | } | 537 | } |
| 492 | - value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); | 538 | + value = integer->getVal(); |
| 493 | return true; | 539 | return true; |
| 494 | } | 540 | } |
| 495 | 541 | ||
| @@ -585,8 +631,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int& value) | @@ -585,8 +631,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int& value) | ||
| 585 | std::string | 631 | std::string |
| 586 | QPDFObjectHandle::getRealValue() | 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 | } else { | 637 | } else { |
| 591 | typeWarning("real", "returning 0.0"); | 638 | typeWarning("real", "returning 0.0"); |
| 592 | QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0"); | 639 | QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0"); |
| @@ -597,10 +644,11 @@ QPDFObjectHandle::getRealValue() | @@ -597,10 +644,11 @@ QPDFObjectHandle::getRealValue() | ||
| 597 | bool | 644 | bool |
| 598 | QPDFObjectHandle::getValueAsReal(std::string& value) | 645 | QPDFObjectHandle::getValueAsReal(std::string& value) |
| 599 | { | 646 | { |
| 600 | - if (!isReal()) { | 647 | + auto real = asReal(); |
| 648 | + if (real == nullptr) { | ||
| 601 | return false; | 649 | return false; |
| 602 | } | 650 | } |
| 603 | - value = dynamic_cast<QPDF_Real*>(obj.get())->getVal(); | 651 | + value = real->getVal(); |
| 604 | return true; | 652 | return true; |
| 605 | } | 653 | } |
| 606 | 654 | ||
| @@ -609,8 +657,9 @@ QPDFObjectHandle::getValueAsReal(std::string& value) | @@ -609,8 +657,9 @@ QPDFObjectHandle::getValueAsReal(std::string& value) | ||
| 609 | std::string | 657 | std::string |
| 610 | QPDFObjectHandle::getName() | 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 | } else { | 663 | } else { |
| 615 | typeWarning("name", "returning dummy name"); | 664 | typeWarning("name", "returning dummy name"); |
| 616 | QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); | 665 | QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); |
| @@ -621,10 +670,11 @@ QPDFObjectHandle::getName() | @@ -621,10 +670,11 @@ QPDFObjectHandle::getName() | ||
| 621 | bool | 670 | bool |
| 622 | QPDFObjectHandle::getValueAsName(std::string& value) | 671 | QPDFObjectHandle::getValueAsName(std::string& value) |
| 623 | { | 672 | { |
| 624 | - if (!isName()) { | 673 | + auto name = asName(); |
| 674 | + if (name == nullptr) { | ||
| 625 | return false; | 675 | return false; |
| 626 | } | 676 | } |
| 627 | - value = dynamic_cast<QPDF_Name*>(obj.get())->getName(); | 677 | + value = name->getName(); |
| 628 | return true; | 678 | return true; |
| 629 | } | 679 | } |
| 630 | 680 | ||
| @@ -633,8 +683,9 @@ QPDFObjectHandle::getValueAsName(std::string& value) | @@ -633,8 +683,9 @@ QPDFObjectHandle::getValueAsName(std::string& value) | ||
| 633 | std::string | 683 | std::string |
| 634 | QPDFObjectHandle::getStringValue() | 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 | } else { | 689 | } else { |
| 639 | typeWarning("string", "returning empty string"); | 690 | typeWarning("string", "returning empty string"); |
| 640 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); | 691 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); |
| @@ -645,18 +696,20 @@ QPDFObjectHandle::getStringValue() | @@ -645,18 +696,20 @@ QPDFObjectHandle::getStringValue() | ||
| 645 | bool | 696 | bool |
| 646 | QPDFObjectHandle::getValueAsString(std::string& value) | 697 | QPDFObjectHandle::getValueAsString(std::string& value) |
| 647 | { | 698 | { |
| 648 | - if (!isString()) { | 699 | + auto str = asString(); |
| 700 | + if (str == nullptr) { | ||
| 649 | return false; | 701 | return false; |
| 650 | } | 702 | } |
| 651 | - value = dynamic_cast<QPDF_String*>(obj.get())->getVal(); | 703 | + value = str->getVal(); |
| 652 | return true; | 704 | return true; |
| 653 | } | 705 | } |
| 654 | 706 | ||
| 655 | std::string | 707 | std::string |
| 656 | QPDFObjectHandle::getUTF8Value() | 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 | } else { | 713 | } else { |
| 661 | typeWarning("string", "returning empty string"); | 714 | typeWarning("string", "returning empty string"); |
| 662 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); | 715 | QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); |
| @@ -667,10 +720,11 @@ QPDFObjectHandle::getUTF8Value() | @@ -667,10 +720,11 @@ QPDFObjectHandle::getUTF8Value() | ||
| 667 | bool | 720 | bool |
| 668 | QPDFObjectHandle::getValueAsUTF8(std::string& value) | 721 | QPDFObjectHandle::getValueAsUTF8(std::string& value) |
| 669 | { | 722 | { |
| 670 | - if (!isString()) { | 723 | + auto str = asString(); |
| 724 | + if (str == nullptr) { | ||
| 671 | return false; | 725 | return false; |
| 672 | } | 726 | } |
| 673 | - value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); | 727 | + value = str->getUTF8Val(); |
| 674 | return true; | 728 | return true; |
| 675 | } | 729 | } |
| 676 | 730 | ||
| @@ -679,8 +733,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string& value) | @@ -679,8 +733,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string& value) | ||
| 679 | std::string | 733 | std::string |
| 680 | QPDFObjectHandle::getOperatorValue() | 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 | } else { | 739 | } else { |
| 685 | typeWarning("operator", "returning fake value"); | 740 | typeWarning("operator", "returning fake value"); |
| 686 | QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value"); | 741 | QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value"); |
| @@ -691,18 +746,20 @@ QPDFObjectHandle::getOperatorValue() | @@ -691,18 +746,20 @@ QPDFObjectHandle::getOperatorValue() | ||
| 691 | bool | 746 | bool |
| 692 | QPDFObjectHandle::getValueAsOperator(std::string& value) | 747 | QPDFObjectHandle::getValueAsOperator(std::string& value) |
| 693 | { | 748 | { |
| 694 | - if (!isOperator()) { | 749 | + auto op = asOperator(); |
| 750 | + if (op == nullptr) { | ||
| 695 | return false; | 751 | return false; |
| 696 | } | 752 | } |
| 697 | - value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); | 753 | + value = op->getVal(); |
| 698 | return true; | 754 | return true; |
| 699 | } | 755 | } |
| 700 | 756 | ||
| 701 | std::string | 757 | std::string |
| 702 | QPDFObjectHandle::getInlineImageValue() | 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 | } else { | 763 | } else { |
| 707 | typeWarning("inlineimage", "returning empty data"); | 764 | typeWarning("inlineimage", "returning empty data"); |
| 708 | QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data"); | 765 | QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data"); |
| @@ -713,10 +770,11 @@ QPDFObjectHandle::getInlineImageValue() | @@ -713,10 +770,11 @@ QPDFObjectHandle::getInlineImageValue() | ||
| 713 | bool | 770 | bool |
| 714 | QPDFObjectHandle::getValueAsInlineImage(std::string& value) | 771 | QPDFObjectHandle::getValueAsInlineImage(std::string& value) |
| 715 | { | 772 | { |
| 716 | - if (!isInlineImage()) { | 773 | + auto image = asInlineImage(); |
| 774 | + if (image == nullptr) { | ||
| 717 | return false; | 775 | return false; |
| 718 | } | 776 | } |
| 719 | - value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); | 777 | + value = image->getVal(); |
| 720 | return true; | 778 | return true; |
| 721 | } | 779 | } |
| 722 | 780 | ||
| @@ -731,8 +789,9 @@ QPDFObjectHandle::aitems() | @@ -731,8 +789,9 @@ QPDFObjectHandle::aitems() | ||
| 731 | int | 789 | int |
| 732 | QPDFObjectHandle::getArrayNItems() | 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 | } else { | 795 | } else { |
| 737 | typeWarning("array", "treating as empty"); | 796 | typeWarning("array", "treating as empty"); |
| 738 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); | 797 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); |
| @@ -744,11 +803,12 @@ QPDFObjectHandle | @@ -744,11 +803,12 @@ QPDFObjectHandle | ||
| 744 | QPDFObjectHandle::getArrayItem(int n) | 803 | QPDFObjectHandle::getArrayItem(int n) |
| 745 | { | 804 | { |
| 746 | QPDFObjectHandle result; | 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 | } else { | 809 | } else { |
| 750 | result = newNull(); | 810 | result = newNull(); |
| 751 | - if (isArray()) { | 811 | + if (array) { |
| 752 | objectWarning("returning null for out of bounds array access"); | 812 | objectWarning("returning null for out of bounds array access"); |
| 753 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); | 813 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); |
| 754 | } else { | 814 | } else { |
| @@ -757,7 +817,7 @@ QPDFObjectHandle::getArrayItem(int n) | @@ -757,7 +817,7 @@ QPDFObjectHandle::getArrayItem(int n) | ||
| 757 | } | 817 | } |
| 758 | QPDF* context = nullptr; | 818 | QPDF* context = nullptr; |
| 759 | std::string description; | 819 | std::string description; |
| 760 | - if (this->obj->getDescription(context, description)) { | 820 | + if (obj->getDescription(context, description)) { |
| 761 | result.setObjectDescription( | 821 | result.setObjectDescription( |
| 762 | context, | 822 | context, |
| 763 | description + " -> null returned from invalid array access"); | 823 | description + " -> null returned from invalid array access"); |
| @@ -769,14 +829,12 @@ QPDFObjectHandle::getArrayItem(int n) | @@ -769,14 +829,12 @@ QPDFObjectHandle::getArrayItem(int n) | ||
| 769 | bool | 829 | bool |
| 770 | QPDFObjectHandle::isRectangle() | 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 | return false; | 834 | return false; |
| 777 | } | 835 | } |
| 778 | for (int i = 0; i < 4; ++i) { | 836 | for (int i = 0; i < 4; ++i) { |
| 779 | - if (!getArrayItem(i).isNumber()) { | 837 | + if (!array->getItem(i).isNumber()) { |
| 780 | return false; | 838 | return false; |
| 781 | } | 839 | } |
| 782 | } | 840 | } |
| @@ -786,14 +844,12 @@ QPDFObjectHandle::isRectangle() | @@ -786,14 +844,12 @@ QPDFObjectHandle::isRectangle() | ||
| 786 | bool | 844 | bool |
| 787 | QPDFObjectHandle::isMatrix() | 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 | return false; | 849 | return false; |
| 794 | } | 850 | } |
| 795 | for (int i = 0; i < 6; ++i) { | 851 | for (int i = 0; i < 6; ++i) { |
| 796 | - if (!getArrayItem(i).isNumber()) { | 852 | + if (!array->getItem(i).isNumber()) { |
| 797 | return false; | 853 | return false; |
| 798 | } | 854 | } |
| 799 | } | 855 | } |
| @@ -805,13 +861,14 @@ QPDFObjectHandle::getArrayAsRectangle() | @@ -805,13 +861,14 @@ QPDFObjectHandle::getArrayAsRectangle() | ||
| 805 | { | 861 | { |
| 806 | Rectangle result; | 862 | Rectangle result; |
| 807 | if (isRectangle()) { | 863 | if (isRectangle()) { |
| 864 | + auto array = asArray(); | ||
| 808 | // Rectangle coordinates are always supposed to be llx, lly, | 865 | // Rectangle coordinates are always supposed to be llx, lly, |
| 809 | // urx, ury, but files have been found in the wild where | 866 | // urx, ury, but files have been found in the wild where |
| 810 | // llx > urx or lly > ury. | 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 | result = Rectangle( | 872 | result = Rectangle( |
| 816 | std::min(i0, i2), | 873 | std::min(i0, i2), |
| 817 | std::min(i1, i3), | 874 | std::min(i1, i3), |
| @@ -826,13 +883,14 @@ QPDFObjectHandle::getArrayAsMatrix() | @@ -826,13 +883,14 @@ QPDFObjectHandle::getArrayAsMatrix() | ||
| 826 | { | 883 | { |
| 827 | Matrix result; | 884 | Matrix result; |
| 828 | if (isMatrix()) { | 885 | if (isMatrix()) { |
| 886 | + auto array = asArray(); | ||
| 829 | result = Matrix( | 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 | return result; | 895 | return result; |
| 838 | } | 896 | } |
| @@ -841,8 +899,9 @@ std::vector<QPDFObjectHandle> | @@ -841,8 +899,9 @@ std::vector<QPDFObjectHandle> | ||
| 841 | QPDFObjectHandle::getArrayAsVector() | 899 | QPDFObjectHandle::getArrayAsVector() |
| 842 | { | 900 | { |
| 843 | std::vector<QPDFObjectHandle> result; | 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 | } else { | 905 | } else { |
| 847 | typeWarning("array", "treating as empty"); | 906 | typeWarning("array", "treating as empty"); |
| 848 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); | 907 | QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); |
| @@ -855,9 +914,10 @@ QPDFObjectHandle::getArrayAsVector() | @@ -855,9 +914,10 @@ QPDFObjectHandle::getArrayAsVector() | ||
| 855 | void | 914 | void |
| 856 | QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) | 915 | QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) |
| 857 | { | 916 | { |
| 858 | - if (isArray()) { | 917 | + auto array = asArray(); |
| 918 | + if (array) { | ||
| 859 | checkOwnership(item); | 919 | checkOwnership(item); |
| 860 | - dynamic_cast<QPDF_Array*>(obj.get())->setItem(n, item); | 920 | + array->setItem(n, item); |
| 861 | } else { | 921 | } else { |
| 862 | typeWarning("array", "ignoring attempt to set item"); | 922 | typeWarning("array", "ignoring attempt to set item"); |
| 863 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); | 923 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); |
| @@ -867,11 +927,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) | @@ -867,11 +927,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) | ||
| 867 | void | 927 | void |
| 868 | QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) | 928 | QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) |
| 869 | { | 929 | { |
| 870 | - if (isArray()) { | 930 | + auto array = asArray(); |
| 931 | + if (array) { | ||
| 871 | for (auto const& item: items) { | 932 | for (auto const& item: items) { |
| 872 | checkOwnership(item); | 933 | checkOwnership(item); |
| 873 | } | 934 | } |
| 874 | - dynamic_cast<QPDF_Array*>(obj.get())->setFromVector(items); | 935 | + array->setFromVector(items); |
| 875 | } else { | 936 | } else { |
| 876 | typeWarning("array", "ignoring attempt to replace items"); | 937 | typeWarning("array", "ignoring attempt to replace items"); |
| 877 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); | 938 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); |
| @@ -881,8 +942,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) | @@ -881,8 +942,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) | ||
| 881 | void | 942 | void |
| 882 | QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) | 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 | } else { | 948 | } else { |
| 887 | typeWarning("array", "ignoring attempt to insert item"); | 949 | typeWarning("array", "ignoring attempt to insert item"); |
| 888 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); | 950 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); |
| @@ -899,9 +961,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const& item) | @@ -899,9 +961,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const& item) | ||
| 899 | void | 961 | void |
| 900 | QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) | 962 | QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) |
| 901 | { | 963 | { |
| 902 | - if (isArray()) { | 964 | + auto array = asArray(); |
| 965 | + if (array) { | ||
| 903 | checkOwnership(item); | 966 | checkOwnership(item); |
| 904 | - dynamic_cast<QPDF_Array*>(obj.get())->appendItem(item); | 967 | + array->appendItem(item); |
| 905 | } else { | 968 | } else { |
| 906 | typeWarning("array", "ignoring attempt to append item"); | 969 | typeWarning("array", "ignoring attempt to append item"); |
| 907 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); | 970 | QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); |
| @@ -918,10 +981,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) | @@ -918,10 +981,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) | ||
| 918 | void | 981 | void |
| 919 | QPDFObjectHandle::eraseItem(int at) | 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 | } else { | 987 | } else { |
| 924 | - if (isArray()) { | 988 | + if (array) { |
| 925 | objectWarning("ignoring attempt to erase out of bounds array item"); | 989 | objectWarning("ignoring attempt to erase out of bounds array item"); |
| 926 | QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); | 990 | QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); |
| 927 | } else { | 991 | } else { |
| @@ -935,8 +999,9 @@ QPDFObjectHandle | @@ -935,8 +999,9 @@ QPDFObjectHandle | ||
| 935 | QPDFObjectHandle::eraseItemAndGetOld(int at) | 999 | QPDFObjectHandle::eraseItemAndGetOld(int at) |
| 936 | { | 1000 | { |
| 937 | auto result = QPDFObjectHandle::newNull(); | 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 | eraseItem(at); | 1006 | eraseItem(at); |
| 942 | return result; | 1007 | return result; |
| @@ -953,8 +1018,9 @@ QPDFObjectHandle::ditems() | @@ -953,8 +1018,9 @@ QPDFObjectHandle::ditems() | ||
| 953 | bool | 1018 | bool |
| 954 | QPDFObjectHandle::hasKey(std::string const& key) | 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 | } else { | 1024 | } else { |
| 959 | typeWarning( | 1025 | typeWarning( |
| 960 | "dictionary", "returning false for a key containment request"); | 1026 | "dictionary", "returning false for a key containment request"); |
| @@ -967,15 +1033,16 @@ QPDFObjectHandle | @@ -967,15 +1033,16 @@ QPDFObjectHandle | ||
| 967 | QPDFObjectHandle::getKey(std::string const& key) | 1033 | QPDFObjectHandle::getKey(std::string const& key) |
| 968 | { | 1034 | { |
| 969 | QPDFObjectHandle result; | 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 | } else { | 1039 | } else { |
| 973 | typeWarning("dictionary", "returning null for attempted key retrieval"); | 1040 | typeWarning("dictionary", "returning null for attempted key retrieval"); |
| 974 | QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); | 1041 | QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); |
| 975 | result = newNull(); | 1042 | result = newNull(); |
| 976 | QPDF* qpdf = nullptr; | 1043 | QPDF* qpdf = nullptr; |
| 977 | std::string description; | 1044 | std::string description; |
| 978 | - if (this->obj->getDescription(qpdf, description)) { | 1045 | + if (obj->getDescription(qpdf, description)) { |
| 979 | result.setObjectDescription( | 1046 | result.setObjectDescription( |
| 980 | qpdf, | 1047 | qpdf, |
| 981 | (description + " -> null returned from getting key " + key + | 1048 | (description + " -> null returned from getting key " + key + |
| @@ -995,8 +1062,9 @@ std::set<std::string> | @@ -995,8 +1062,9 @@ std::set<std::string> | ||
| 995 | QPDFObjectHandle::getKeys() | 1062 | QPDFObjectHandle::getKeys() |
| 996 | { | 1063 | { |
| 997 | std::set<std::string> result; | 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 | } else { | 1068 | } else { |
| 1001 | typeWarning("dictionary", "treating as empty"); | 1069 | typeWarning("dictionary", "treating as empty"); |
| 1002 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); | 1070 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); |
| @@ -1008,8 +1076,9 @@ std::map<std::string, QPDFObjectHandle> | @@ -1008,8 +1076,9 @@ std::map<std::string, QPDFObjectHandle> | ||
| 1008 | QPDFObjectHandle::getDictAsMap() | 1076 | QPDFObjectHandle::getDictAsMap() |
| 1009 | { | 1077 | { |
| 1010 | std::map<std::string, QPDFObjectHandle> result; | 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 | } else { | 1082 | } else { |
| 1014 | typeWarning("dictionary", "treating as empty"); | 1083 | typeWarning("dictionary", "treating as empty"); |
| 1015 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); | 1084 | QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); |
| @@ -1200,9 +1269,10 @@ void | @@ -1200,9 +1269,10 @@ void | ||
| 1200 | QPDFObjectHandle::replaceKey( | 1269 | QPDFObjectHandle::replaceKey( |
| 1201 | std::string const& key, QPDFObjectHandle const& value) | 1270 | std::string const& key, QPDFObjectHandle const& value) |
| 1202 | { | 1271 | { |
| 1203 | - if (isDictionary()) { | 1272 | + auto dict = asDictionary(); |
| 1273 | + if (dict) { | ||
| 1204 | checkOwnership(value); | 1274 | checkOwnership(value); |
| 1205 | - dynamic_cast<QPDF_Dictionary*>(obj.get())->replaceKey(key, value); | 1275 | + dict->replaceKey(key, value); |
| 1206 | } else { | 1276 | } else { |
| 1207 | typeWarning("dictionary", "ignoring key replacement request"); | 1277 | typeWarning("dictionary", "ignoring key replacement request"); |
| 1208 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); | 1278 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); |
| @@ -1229,8 +1299,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( | @@ -1229,8 +1299,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( | ||
| 1229 | void | 1299 | void |
| 1230 | QPDFObjectHandle::removeKey(std::string const& key) | 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 | } else { | 1305 | } else { |
| 1235 | typeWarning("dictionary", "ignoring key removal request"); | 1306 | typeWarning("dictionary", "ignoring key removal request"); |
| 1236 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); | 1307 | QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); |
| @@ -1241,8 +1312,9 @@ QPDFObjectHandle | @@ -1241,8 +1312,9 @@ QPDFObjectHandle | ||
| 1241 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) | 1312 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) |
| 1242 | { | 1313 | { |
| 1243 | auto result = QPDFObjectHandle::newNull(); | 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 | removeKey(key); | 1319 | removeKey(key); |
| 1248 | return result; | 1320 | return result; |
| @@ -1259,50 +1331,43 @@ QPDFObjectHandle::replaceOrRemoveKey( | @@ -1259,50 +1331,43 @@ QPDFObjectHandle::replaceOrRemoveKey( | ||
| 1259 | QPDFObjectHandle | 1331 | QPDFObjectHandle |
| 1260 | QPDFObjectHandle::getDict() | 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 | void | 1337 | void |
| 1267 | QPDFObjectHandle::setFilterOnWrite(bool val) | 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 | bool | 1343 | bool |
| 1274 | QPDFObjectHandle::getFilterOnWrite() | 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 | bool | 1349 | bool |
| 1281 | QPDFObjectHandle::isDataModified() | 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 | void | 1355 | void |
| 1288 | QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict) | 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 | std::shared_ptr<Buffer> | 1361 | std::shared_ptr<Buffer> |
| 1295 | QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) | 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 | std::shared_ptr<Buffer> | 1367 | std::shared_ptr<Buffer> |
| 1302 | QPDFObjectHandle::getRawStreamData() | 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 | bool | 1373 | bool |
| @@ -1314,8 +1379,7 @@ QPDFObjectHandle::pipeStreamData( | @@ -1314,8 +1379,7 @@ QPDFObjectHandle::pipeStreamData( | ||
| 1314 | bool suppress_warnings, | 1379 | bool suppress_warnings, |
| 1315 | bool will_retry) | 1380 | bool will_retry) |
| 1316 | { | 1381 | { |
| 1317 | - assertStream(); | ||
| 1318 | - return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( | 1382 | + return asStreamWithAssert()->pipeStreamData( |
| 1319 | p, | 1383 | p, |
| 1320 | filtering_attempted, | 1384 | filtering_attempted, |
| 1321 | encode_flags, | 1385 | encode_flags, |
| @@ -1332,9 +1396,8 @@ QPDFObjectHandle::pipeStreamData( | @@ -1332,9 +1396,8 @@ QPDFObjectHandle::pipeStreamData( | ||
| 1332 | bool suppress_warnings, | 1396 | bool suppress_warnings, |
| 1333 | bool will_retry) | 1397 | bool will_retry) |
| 1334 | { | 1398 | { |
| 1335 | - assertStream(); | ||
| 1336 | bool filtering_attempted; | 1399 | bool filtering_attempted; |
| 1337 | - dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( | 1400 | + asStreamWithAssert()->pipeStreamData( |
| 1338 | p, | 1401 | p, |
| 1339 | &filtering_attempted, | 1402 | &filtering_attempted, |
| 1340 | encode_flags, | 1403 | encode_flags, |
| @@ -1368,9 +1431,7 @@ QPDFObjectHandle::replaceStreamData( | @@ -1368,9 +1431,7 @@ QPDFObjectHandle::replaceStreamData( | ||
| 1368 | QPDFObjectHandle const& filter, | 1431 | QPDFObjectHandle const& filter, |
| 1369 | QPDFObjectHandle const& decode_parms) | 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 | void | 1437 | void |
| @@ -1379,14 +1440,12 @@ QPDFObjectHandle::replaceStreamData( | @@ -1379,14 +1440,12 @@ QPDFObjectHandle::replaceStreamData( | ||
| 1379 | QPDFObjectHandle const& filter, | 1440 | QPDFObjectHandle const& filter, |
| 1380 | QPDFObjectHandle const& decode_parms) | 1441 | QPDFObjectHandle const& decode_parms) |
| 1381 | { | 1442 | { |
| 1382 | - assertStream(); | ||
| 1383 | auto b = std::make_shared<Buffer>(data.length()); | 1443 | auto b = std::make_shared<Buffer>(data.length()); |
| 1384 | unsigned char* bp = b->getBuffer(); | 1444 | unsigned char* bp = b->getBuffer(); |
| 1385 | if (bp) { | 1445 | if (bp) { |
| 1386 | memcpy(bp, data.c_str(), data.length()); | 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 | void | 1451 | void |
| @@ -1395,9 +1454,7 @@ QPDFObjectHandle::replaceStreamData( | @@ -1395,9 +1454,7 @@ QPDFObjectHandle::replaceStreamData( | ||
| 1395 | QPDFObjectHandle const& filter, | 1454 | QPDFObjectHandle const& filter, |
| 1396 | QPDFObjectHandle const& decode_parms) | 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 | namespace | 1460 | namespace |
| @@ -1446,11 +1503,9 @@ QPDFObjectHandle::replaceStreamData( | @@ -1446,11 +1503,9 @@ QPDFObjectHandle::replaceStreamData( | ||
| 1446 | QPDFObjectHandle const& filter, | 1503 | QPDFObjectHandle const& filter, |
| 1447 | QPDFObjectHandle const& decode_parms) | 1504 | QPDFObjectHandle const& decode_parms) |
| 1448 | { | 1505 | { |
| 1449 | - assertStream(); | ||
| 1450 | auto sdp = | 1506 | auto sdp = |
| 1451 | std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); | 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 | void | 1511 | void |
| @@ -1459,11 +1514,9 @@ QPDFObjectHandle::replaceStreamData( | @@ -1459,11 +1514,9 @@ QPDFObjectHandle::replaceStreamData( | ||
| 1459 | QPDFObjectHandle const& filter, | 1514 | QPDFObjectHandle const& filter, |
| 1460 | QPDFObjectHandle const& decode_parms) | 1515 | QPDFObjectHandle const& decode_parms) |
| 1461 | { | 1516 | { |
| 1462 | - assertStream(); | ||
| 1463 | auto sdp = | 1517 | auto sdp = |
| 1464 | std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); | 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 | std::map<std::string, QPDFObjectHandle> | 1522 | std::map<std::string, QPDFObjectHandle> |
| @@ -1478,10 +1531,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | @@ -1478,10 +1531,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | ||
| 1478 | { | 1531 | { |
| 1479 | all_description = description; | 1532 | all_description = description; |
| 1480 | std::vector<QPDFObjectHandle> result; | 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 | for (int i = 0; i < n_items; ++i) { | 1537 | for (int i = 0; i < n_items; ++i) { |
| 1484 | - QPDFObjectHandle item = getArrayItem(i); | 1538 | + QPDFObjectHandle item = array->getItem(i); |
| 1485 | if (item.isStream()) { | 1539 | if (item.isStream()) { |
| 1486 | result.push_back(item); | 1540 | result.push_back(item); |
| 1487 | } else { | 1541 | } else { |
| @@ -1648,18 +1702,16 @@ QPDFObjectHandle::unparseResolved() | @@ -1648,18 +1702,16 @@ QPDFObjectHandle::unparseResolved() | ||
| 1648 | if (!dereference()) { | 1702 | if (!dereference()) { |
| 1649 | throw std::logic_error( | 1703 | throw std::logic_error( |
| 1650 | "attempted to dereference an uninitialized QPDFObjectHandle"); | 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 | std::string | 1709 | std::string |
| 1659 | QPDFObjectHandle::unparseBinary() | 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 | } else { | 1715 | } else { |
| 1664 | return unparse(); | 1716 | return unparse(); |
| 1665 | } | 1717 | } |
| @@ -1675,16 +1727,13 @@ QPDFObjectHandle::getJSON(bool dereference_indirect) | @@ -1675,16 +1727,13 @@ QPDFObjectHandle::getJSON(bool dereference_indirect) | ||
| 1675 | JSON | 1727 | JSON |
| 1676 | QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) | 1728 | QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) |
| 1677 | { | 1729 | { |
| 1678 | - if ((!dereference_indirect) && this->isIndirect()) { | 1730 | + if ((!dereference_indirect) && isIndirect()) { |
| 1679 | return JSON::makeString(unparse()); | 1731 | return JSON::makeString(unparse()); |
| 1680 | } else if (!dereference()) { | 1732 | } else if (!dereference()) { |
| 1681 | throw std::logic_error( | 1733 | throw std::logic_error( |
| 1682 | "attempted to dereference an uninitialized QPDFObjectHandle"); | 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 | } else { | 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,8 +1745,7 @@ QPDFObjectHandle::getStreamJSON( | ||
| 1696 | Pipeline* p, | 1745 | Pipeline* p, |
| 1697 | std::string const& data_filename) | 1746 | std::string const& data_filename) |
| 1698 | { | 1747 | { |
| 1699 | - assertStream(); | ||
| 1700 | - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamJSON( | 1748 | + return asStreamWithAssert()->getStreamJSON( |
| 1701 | json_version, json_data, decode_level, p, data_filename); | 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,8 +1965,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr<TokenFilter> filter) | ||
| 1917 | void | 1965 | void |
| 1918 | QPDFObjectHandle::addTokenFilter(std::shared_ptr<TokenFilter> filter) | 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 | QPDFObjectHandle | 1971 | QPDFObjectHandle |
| @@ -1945,21 +1992,6 @@ QPDFObjectHandle::getParsedOffset() | @@ -1945,21 +1992,6 @@ QPDFObjectHandle::getParsedOffset() | ||
| 1945 | } | 1992 | } |
| 1946 | 1993 | ||
| 1947 | QPDFObjectHandle | 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 | QPDFObjectHandle::newBool(bool value) | 1995 | QPDFObjectHandle::newBool(bool value) |
| 1964 | { | 1996 | { |
| 1965 | return QPDFObjectHandle(QPDF_Bool::create(value)); | 1997 | return QPDFObjectHandle(QPDF_Bool::create(value)); |
| @@ -2128,8 +2160,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) | @@ -2128,8 +2160,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) | ||
| 2128 | QPDFObjectHandle stream_dict = newDictionary(); | 2160 | QPDFObjectHandle stream_dict = newDictionary(); |
| 2129 | QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( | 2161 | QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( |
| 2130 | QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0))); | 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 | stream->setObjGen(result.getObjGen()); | 2164 | stream->setObjGen(result.getObjGen()); |
| 2134 | return result; | 2165 | return result; |
| 2135 | } | 2166 | } |
| @@ -2155,18 +2186,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) | @@ -2155,18 +2186,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) | ||
| 2155 | QPDFObjectHandle | 2186 | QPDFObjectHandle |
| 2156 | QPDFObjectHandle::newReserved(QPDF* qpdf) | 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 | void | 2192 | void |
| @@ -2212,12 +2232,7 @@ QPDFObjectHandle::shallowCopyInternal( | @@ -2212,12 +2232,7 @@ QPDFObjectHandle::shallowCopyInternal( | ||
| 2212 | QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream"); | 2232 | QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream"); |
| 2213 | throw std::runtime_error("attempt to make a shallow copy of a stream"); | 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 | std::set<QPDFObjGen> visited; | 2237 | std::set<QPDFObjGen> visited; |
| 2223 | new_obj.copyObject(visited, false, first_level_only, false); | 2238 | new_obj.copyObject(visited, false, first_level_only, false); |
| @@ -2258,9 +2273,6 @@ QPDFObjectHandle::copyObject( | @@ -2258,9 +2273,6 @@ QPDFObjectHandle::copyObject( | ||
| 2258 | " reserved object handle direct"); | 2273 | " reserved object handle direct"); |
| 2259 | } | 2274 | } |
| 2260 | 2275 | ||
| 2261 | - qpdf = nullptr; | ||
| 2262 | - og = QPDFObjGen(); | ||
| 2263 | - | ||
| 2264 | std::shared_ptr<QPDFObject> new_obj; | 2276 | std::shared_ptr<QPDFObject> new_obj; |
| 2265 | 2277 | ||
| 2266 | if (isBool() || isInteger() || isName() || isNull() || isReal() || | 2278 | if (isBool() || isInteger() || isName() || isNull() || isReal() || |
| @@ -2268,9 +2280,10 @@ QPDFObjectHandle::copyObject( | @@ -2268,9 +2280,10 @@ QPDFObjectHandle::copyObject( | ||
| 2268 | new_obj = obj->shallowCopy(); | 2280 | new_obj = obj->shallowCopy(); |
| 2269 | } else if (isArray()) { | 2281 | } else if (isArray()) { |
| 2270 | std::vector<QPDFObjectHandle> items; | 2282 | std::vector<QPDFObjectHandle> items; |
| 2271 | - int n = getArrayNItems(); | 2283 | + auto array = asArray(); |
| 2284 | + int n = array->getNItems(); | ||
| 2272 | for (int i = 0; i < n; ++i) { | 2285 | for (int i = 0; i < n; ++i) { |
| 2273 | - items.push_back(getArrayItem(i)); | 2286 | + items.push_back(array->getItem(i)); |
| 2274 | if ((!first_level_only) && | 2287 | if ((!first_level_only) && |
| 2275 | (cross_indirect || (!items.back().isIndirect()))) { | 2288 | (cross_indirect || (!items.back().isIndirect()))) { |
| 2276 | items.back().copyObject( | 2289 | items.back().copyObject( |
| @@ -2280,8 +2293,9 @@ QPDFObjectHandle::copyObject( | @@ -2280,8 +2293,9 @@ QPDFObjectHandle::copyObject( | ||
| 2280 | new_obj = QPDF_Array::create(items); | 2293 | new_obj = QPDF_Array::create(items); |
| 2281 | } else if (isDictionary()) { | 2294 | } else if (isDictionary()) { |
| 2282 | std::map<std::string, QPDFObjectHandle> items; | 2295 | std::map<std::string, QPDFObjectHandle> items; |
| 2296 | + auto dict = asDictionary(); | ||
| 2283 | for (auto const& key: getKeys()) { | 2297 | for (auto const& key: getKeys()) { |
| 2284 | - items[key] = getKey(key); | 2298 | + items[key] = dict->getKey(key); |
| 2285 | if ((!first_level_only) && | 2299 | if ((!first_level_only) && |
| 2286 | (cross_indirect || (!items[key].isIndirect()))) { | 2300 | (cross_indirect || (!items[key].isIndirect()))) { |
| 2287 | items[key].copyObject( | 2301 | items[key].copyObject( |
| @@ -2329,7 +2343,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) | @@ -2329,7 +2343,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) | ||
| 2329 | void | 2343 | void |
| 2330 | QPDFObjectHandle::assertInitialized() const | 2344 | QPDFObjectHandle::assertInitialized() const |
| 2331 | { | 2345 | { |
| 2332 | - if (!this->initialized) { | 2346 | + if (!isInitialized()) { |
| 2333 | throw std::logic_error("operation attempted on uninitialized " | 2347 | throw std::logic_error("operation attempted on uninitialized " |
| 2334 | "QPDFObjectHandle"); | 2348 | "QPDFObjectHandle"); |
| 2335 | } | 2349 | } |
| @@ -2544,8 +2558,9 @@ QPDFObjectHandle::isImage(bool exclude_imagemask) | @@ -2544,8 +2558,9 @@ QPDFObjectHandle::isImage(bool exclude_imagemask) | ||
| 2544 | void | 2558 | void |
| 2545 | QPDFObjectHandle::checkOwnership(QPDFObjectHandle const& item) const | 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 | QTC::TC("qpdf", "QPDFObjectHandle check ownership"); | 2564 | QTC::TC("qpdf", "QPDFObjectHandle check ownership"); |
| 2550 | throw std::logic_error( | 2565 | throw std::logic_error( |
| 2551 | "Attempting to add an object from a different QPDF." | 2566 | "Attempting to add an object from a different QPDF." |
| @@ -2564,28 +2579,10 @@ QPDFObjectHandle::assertPageObject() | @@ -2564,28 +2579,10 @@ QPDFObjectHandle::assertPageObject() | ||
| 2564 | bool | 2579 | bool |
| 2565 | QPDFObjectHandle::dereference() | 2580 | QPDFObjectHandle::dereference() |
| 2566 | { | 2581 | { |
| 2567 | - if (!this->initialized) { | 2582 | + if (!isInitialized()) { |
| 2568 | return false; | 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 | return true; | 2586 | return true; |
| 2590 | } | 2587 | } |
| 2591 | 2588 |
libqpdf/QPDFParser.cc
| 1 | #include <qpdf/QPDFParser.hh> | 1 | #include <qpdf/QPDFParser.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/QPDF.hh> | 3 | #include <qpdf/QPDF.hh> |
| 4 | +#include <qpdf/QPDFObjGen.hh> | ||
| 4 | #include <qpdf/QPDFObjectHandle.hh> | 5 | #include <qpdf/QPDFObjectHandle.hh> |
| 5 | -#include <qpdf/QPDF_Array.hh> | ||
| 6 | #include <qpdf/QTC.hh> | 6 | #include <qpdf/QTC.hh> |
| 7 | #include <qpdf/QUtil.hh> | 7 | #include <qpdf/QUtil.hh> |
| 8 | 8 | ||
| @@ -55,6 +55,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -55,6 +55,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 55 | 55 | ||
| 56 | while (!done) { | 56 | while (!done) { |
| 57 | bool bad = false; | 57 | bool bad = false; |
| 58 | + bool indirect_ref = false; | ||
| 58 | is_null = false; | 59 | is_null = false; |
| 59 | auto& frame = stack.back(); | 60 | auto& frame = stack.back(); |
| 60 | auto& olist = frame.olist; | 61 | auto& olist = frame.olist; |
| @@ -185,12 +186,16 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -185,12 +186,16 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 185 | "QPDFObjectHandle::parse called without context" | 186 | "QPDFObjectHandle::parse called without context" |
| 186 | " on an object with indirect references"); | 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 | olist.pop_back(); | 199 | olist.pop_back(); |
| 195 | olist.pop_back(); | 200 | olist.pop_back(); |
| 196 | } else if ((value == "endobj") && (state == st_top)) { | 201 | } else if ((value == "endobj") && (state == st_top)) { |
| @@ -274,8 +279,8 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -274,8 +279,8 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 274 | 279 | ||
| 275 | case st_dictionary: | 280 | case st_dictionary: |
| 276 | case st_array: | 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 | // become implicit. | 284 | // become implicit. |
| 280 | setDescriptionFromInput(object, input->getLastOffset()); | 285 | setDescriptionFromInput(object, input->getLastOffset()); |
| 281 | object.setParsedOffset(input->getLastOffset()); | 286 | object.setParsedOffset(input->getLastOffset()); |
libqpdf/QPDFValue.cc
0 โ 100644
libqpdf/QPDF_Array.cc
| @@ -4,12 +4,14 @@ | @@ -4,12 +4,14 @@ | ||
| 4 | #include <qpdf/QUtil.hh> | 4 | #include <qpdf/QUtil.hh> |
| 5 | #include <stdexcept> | 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 | setFromVector(v); | 10 | setFromVector(v); |
| 10 | } | 11 | } |
| 11 | 12 | ||
| 12 | QPDF_Array::QPDF_Array(SparseOHArray const& items) : | 13 | QPDF_Array::QPDF_Array(SparseOHArray const& items) : |
| 14 | + QPDFValue(::ot_array, "array"), | ||
| 13 | elements(items) | 15 | elements(items) |
| 14 | { | 16 | { |
| 15 | } | 17 | } |
| @@ -62,18 +64,6 @@ QPDF_Array::getJSON(int json_version) | @@ -62,18 +64,6 @@ QPDF_Array::getJSON(int json_version) | ||
| 62 | return j; | 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 | int | 67 | int |
| 78 | QPDF_Array::getNItems() const | 68 | QPDF_Array::getNItems() const |
| 79 | { | 69 | { |
libqpdf/QPDF_Bool.cc
| 1 | #include <qpdf/QPDF_Bool.hh> | 1 | #include <qpdf/QPDF_Bool.hh> |
| 2 | 2 | ||
| 3 | QPDF_Bool::QPDF_Bool(bool val) : | 3 | QPDF_Bool::QPDF_Bool(bool val) : |
| 4 | + QPDFValue(::ot_boolean, "boolean"), | ||
| 4 | val(val) | 5 | val(val) |
| 5 | { | 6 | { |
| 6 | } | 7 | } |
| @@ -29,18 +30,6 @@ QPDF_Bool::getJSON(int json_version) | @@ -29,18 +30,6 @@ QPDF_Bool::getJSON(int json_version) | ||
| 29 | return JSON::makeBool(this->val); | 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 | bool | 33 | bool |
| 45 | QPDF_Bool::getVal() const | 34 | QPDF_Bool::getVal() const |
| 46 | { | 35 | { |
libqpdf/QPDF_Dictionary.cc
| 1 | #include <qpdf/QPDF_Dictionary.hh> | 1 | #include <qpdf/QPDF_Dictionary.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/QPDF_Name.hh> | 3 | #include <qpdf/QPDF_Name.hh> |
| 4 | -#include <qpdf/QPDF_Null.hh> | ||
| 5 | 4 | ||
| 6 | QPDF_Dictionary::QPDF_Dictionary( | 5 | QPDF_Dictionary::QPDF_Dictionary( |
| 7 | std::map<std::string, QPDFObjectHandle> const& items) : | 6 | std::map<std::string, QPDFObjectHandle> const& items) : |
| 7 | + QPDFValue(::ot_dictionary, "dictionary"), | ||
| 8 | items(items) | 8 | items(items) |
| 9 | { | 9 | { |
| 10 | } | 10 | } |
| @@ -58,18 +58,6 @@ QPDF_Dictionary::getJSON(int json_version) | @@ -58,18 +58,6 @@ QPDF_Dictionary::getJSON(int json_version) | ||
| 58 | return j; | 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 | bool | 61 | bool |
| 74 | QPDF_Dictionary::hasKey(std::string const& key) | 62 | QPDF_Dictionary::hasKey(std::string const& key) |
| 75 | { | 63 | { |
libqpdf/QPDF_InlineImage.cc
| 1 | #include <qpdf/QPDF_InlineImage.hh> | 1 | #include <qpdf/QPDF_InlineImage.hh> |
| 2 | 2 | ||
| 3 | QPDF_InlineImage::QPDF_InlineImage(std::string const& val) : | 3 | QPDF_InlineImage::QPDF_InlineImage(std::string const& val) : |
| 4 | + QPDFValue(::ot_inlineimage, "inline-image"), | ||
| 4 | val(val) | 5 | val(val) |
| 5 | { | 6 | { |
| 6 | } | 7 | } |
| @@ -29,18 +30,6 @@ QPDF_InlineImage::getJSON(int json_version) | @@ -29,18 +30,6 @@ QPDF_InlineImage::getJSON(int json_version) | ||
| 29 | return JSON::makeNull(); | 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 | std::string | 33 | std::string |
| 45 | QPDF_InlineImage::getVal() const | 34 | QPDF_InlineImage::getVal() const |
| 46 | { | 35 | { |
libqpdf/QPDF_Integer.cc
| @@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
| 3 | #include <qpdf/QUtil.hh> | 3 | #include <qpdf/QUtil.hh> |
| 4 | 4 | ||
| 5 | QPDF_Integer::QPDF_Integer(long long val) : | 5 | QPDF_Integer::QPDF_Integer(long long val) : |
| 6 | + QPDFValue(::ot_integer, "integer"), | ||
| 6 | val(val) | 7 | val(val) |
| 7 | { | 8 | { |
| 8 | } | 9 | } |
| @@ -31,18 +32,6 @@ QPDF_Integer::getJSON(int json_version) | @@ -31,18 +32,6 @@ QPDF_Integer::getJSON(int json_version) | ||
| 31 | return JSON::makeInt(this->val); | 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 | long long | 35 | long long |
| 47 | QPDF_Integer::getVal() const | 36 | QPDF_Integer::getVal() const |
| 48 | { | 37 | { |
libqpdf/QPDF_Name.cc
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | #include <string.h> | 5 | #include <string.h> |
| 6 | 6 | ||
| 7 | QPDF_Name::QPDF_Name(std::string const& name) : | 7 | QPDF_Name::QPDF_Name(std::string const& name) : |
| 8 | + QPDFValue(::ot_name, "name"), | ||
| 8 | name(name) | 9 | name(name) |
| 9 | { | 10 | { |
| 10 | } | 11 | } |
| @@ -61,18 +62,6 @@ QPDF_Name::getJSON(int json_version) | @@ -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 | std::string | 65 | std::string |
| 77 | QPDF_Name::getName() const | 66 | QPDF_Name::getName() const |
| 78 | { | 67 | { |
libqpdf/QPDF_Null.cc
| 1 | #include <qpdf/QPDF_Null.hh> | 1 | #include <qpdf/QPDF_Null.hh> |
| 2 | 2 | ||
| 3 | +QPDF_Null::QPDF_Null() : | ||
| 4 | + QPDFValue(::ot_null, "null") | ||
| 5 | +{ | ||
| 6 | +} | ||
| 7 | + | ||
| 3 | std::shared_ptr<QPDFObject> | 8 | std::shared_ptr<QPDFObject> |
| 4 | QPDF_Null::create() | 9 | QPDF_Null::create() |
| 5 | { | 10 | { |
| @@ -23,15 +28,3 @@ QPDF_Null::getJSON(int json_version) | @@ -23,15 +28,3 @@ QPDF_Null::getJSON(int json_version) | ||
| 23 | { | 28 | { |
| 24 | return JSON::makeNull(); | 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 | #include <qpdf/QPDF_Operator.hh> | 1 | #include <qpdf/QPDF_Operator.hh> |
| 2 | 2 | ||
| 3 | QPDF_Operator::QPDF_Operator(std::string const& val) : | 3 | QPDF_Operator::QPDF_Operator(std::string const& val) : |
| 4 | + QPDFValue(::ot_operator, "operator"), | ||
| 4 | val(val) | 5 | val(val) |
| 5 | { | 6 | { |
| 6 | } | 7 | } |
| @@ -20,7 +21,7 @@ QPDF_Operator::shallowCopy() | @@ -20,7 +21,7 @@ QPDF_Operator::shallowCopy() | ||
| 20 | std::string | 21 | std::string |
| 21 | QPDF_Operator::unparse() | 22 | QPDF_Operator::unparse() |
| 22 | { | 23 | { |
| 23 | - return this->val; | 24 | + return val; |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | JSON | 27 | JSON |
| @@ -29,18 +30,6 @@ QPDF_Operator::getJSON(int json_version) | @@ -29,18 +30,6 @@ QPDF_Operator::getJSON(int json_version) | ||
| 29 | return JSON::makeNull(); | 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 | std::string | 33 | std::string |
| 45 | QPDF_Operator::getVal() const | 34 | QPDF_Operator::getVal() const |
| 46 | { | 35 | { |
libqpdf/QPDF_Real.cc
| @@ -3,12 +3,14 @@ | @@ -3,12 +3,14 @@ | ||
| 3 | #include <qpdf/QUtil.hh> | 3 | #include <qpdf/QUtil.hh> |
| 4 | 4 | ||
| 5 | QPDF_Real::QPDF_Real(std::string const& val) : | 5 | QPDF_Real::QPDF_Real(std::string const& val) : |
| 6 | + QPDFValue(::ot_real, "real"), | ||
| 6 | val(val) | 7 | val(val) |
| 7 | { | 8 | { |
| 8 | } | 9 | } |
| 9 | 10 | ||
| 10 | QPDF_Real::QPDF_Real( | 11 | QPDF_Real::QPDF_Real( |
| 11 | double value, int decimal_places, bool trim_trailing_zeroes) : | 12 | double value, int decimal_places, bool trim_trailing_zeroes) : |
| 13 | + QPDFValue(::ot_real, "real"), | ||
| 12 | val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes)) | 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,18 +62,6 @@ QPDF_Real::getJSON(int json_version) | ||
| 60 | return JSON::makeNumber(result); | 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 | std::string | 65 | std::string |
| 76 | QPDF_Real::getVal() | 66 | QPDF_Real::getVal() |
| 77 | { | 67 | { |
libqpdf/QPDF_Reserved.cc
| @@ -2,6 +2,11 @@ | @@ -2,6 +2,11 @@ | ||
| 2 | 2 | ||
| 3 | #include <stdexcept> | 3 | #include <stdexcept> |
| 4 | 4 | ||
| 5 | +QPDF_Reserved::QPDF_Reserved() : | ||
| 6 | + QPDFValue(::ot_reserved, "reserved") | ||
| 7 | +{ | ||
| 8 | +} | ||
| 9 | + | ||
| 5 | std::shared_ptr<QPDFObject> | 10 | std::shared_ptr<QPDFObject> |
| 6 | QPDF_Reserved::create() | 11 | QPDF_Reserved::create() |
| 7 | { | 12 | { |
| @@ -17,25 +22,15 @@ QPDF_Reserved::shallowCopy() | @@ -17,25 +22,15 @@ QPDF_Reserved::shallowCopy() | ||
| 17 | std::string | 22 | std::string |
| 18 | QPDF_Reserved::unparse() | 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 | return ""; | 27 | return ""; |
| 22 | } | 28 | } |
| 23 | 29 | ||
| 24 | JSON | 30 | JSON |
| 25 | QPDF_Reserved::getJSON(int json_version) | 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 | return JSON::makeNull(); | 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,6 +114,7 @@ QPDF_Stream::QPDF_Stream( | ||
| 114 | QPDFObjectHandle stream_dict, | 114 | QPDFObjectHandle stream_dict, |
| 115 | qpdf_offset_t offset, | 115 | qpdf_offset_t offset, |
| 116 | size_t length) : | 116 | size_t length) : |
| 117 | + QPDFValue(::ot_stream, "stream"), | ||
| 117 | qpdf(qpdf), | 118 | qpdf(qpdf), |
| 118 | og(og), | 119 | og(og), |
| 119 | filter_on_write(true), | 120 | filter_on_write(true), |
| @@ -291,22 +292,10 @@ QPDF_Stream::getStreamJSON( | @@ -291,22 +292,10 @@ QPDF_Stream::getStreamJSON( | ||
| 291 | return result; | 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 | void | 295 | void |
| 307 | QPDF_Stream::setDescription(QPDF* qpdf, std::string const& description) | 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 | setDictDescription(); | 299 | setDictDescription(); |
| 311 | } | 300 | } |
| 312 | 301 |
libqpdf/QPDF_String.cc
| @@ -21,6 +21,7 @@ is_iso_latin1_printable(char ch) | @@ -21,6 +21,7 @@ is_iso_latin1_printable(char ch) | ||
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | QPDF_String::QPDF_String(std::string const& val) : | 23 | QPDF_String::QPDF_String(std::string const& val) : |
| 24 | + QPDFValue(::ot_string, "string"), | ||
| 24 | val(val) | 25 | val(val) |
| 25 | { | 26 | { |
| 26 | } | 27 | } |
| @@ -84,18 +85,6 @@ QPDF_String::getJSON(int json_version) | @@ -84,18 +85,6 @@ QPDF_String::getJSON(int json_version) | ||
| 84 | return JSON::makeString(result); | 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 | bool | 88 | bool |
| 100 | QPDF_String::useHexString() const | 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,8 +137,7 @@ QPDF::isLinearized() | ||
| 137 | return false; | 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 | if (!candidate.isDictionary()) { | 141 | if (!candidate.isDictionary()) { |
| 143 | return false; | 142 | return false; |
| 144 | } | 143 | } |
libqpdf/qpdf/QPDF_Array.hh
| 1 | #ifndef QPDF_ARRAY_HH | 1 | #ifndef QPDF_ARRAY_HH |
| 2 | #define QPDF_ARRAY_HH | 2 | #define QPDF_ARRAY_HH |
| 3 | 3 | ||
| 4 | -#include <qpdf/QPDFObject.hh> | 4 | +#include <qpdf/QPDFValue.hh> |
| 5 | 5 | ||
| 6 | #include <qpdf/SparseOHArray.hh> | 6 | #include <qpdf/SparseOHArray.hh> |
| 7 | #include <list> | 7 | #include <list> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | -class QPDF_Array: public QPDFObject | 10 | +class QPDF_Array: public QPDFValue |
| 11 | { | 11 | { |
| 12 | public: | 12 | public: |
| 13 | virtual ~QPDF_Array() = default; | 13 | virtual ~QPDF_Array() = default; |
| @@ -17,8 +17,6 @@ class QPDF_Array: public QPDFObject | @@ -17,8 +17,6 @@ class QPDF_Array: public QPDFObject | ||
| 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | virtual std::string unparse(); | 18 | virtual std::string unparse(); |
| 19 | virtual JSON getJSON(int json_version); | 19 | virtual JSON getJSON(int json_version); |
| 20 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 21 | - virtual char const* getTypeName() const; | ||
| 22 | 20 | ||
| 23 | int getNItems() const; | 21 | int getNItems() const; |
| 24 | QPDFObjectHandle getItem(int n) const; | 22 | QPDFObjectHandle getItem(int n) const; |
libqpdf/qpdf/QPDF_Bool.hh
| 1 | #ifndef QPDF_BOOL_HH | 1 | #ifndef QPDF_BOOL_HH |
| 2 | #define QPDF_BOOL_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Bool() = default; | 9 | virtual ~QPDF_Bool() = default; |
| @@ -11,8 +11,6 @@ class QPDF_Bool: public QPDFObject | @@ -11,8 +11,6 @@ class QPDF_Bool: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | bool getVal() const; | 14 | bool getVal() const; |
| 17 | 15 | ||
| 18 | private: | 16 | private: |
libqpdf/qpdf/QPDF_Dictionary.hh
| 1 | #ifndef QPDF_DICTIONARY_HH | 1 | #ifndef QPDF_DICTIONARY_HH |
| 2 | #define QPDF_DICTIONARY_HH | 2 | #define QPDF_DICTIONARY_HH |
| 3 | 3 | ||
| 4 | -#include <qpdf/QPDFObject.hh> | 4 | +#include <qpdf/QPDFValue.hh> |
| 5 | 5 | ||
| 6 | #include <map> | 6 | #include <map> |
| 7 | #include <set> | 7 | #include <set> |
| 8 | 8 | ||
| 9 | #include <qpdf/QPDFObjectHandle.hh> | 9 | #include <qpdf/QPDFObjectHandle.hh> |
| 10 | 10 | ||
| 11 | -class QPDF_Dictionary: public QPDFObject | 11 | +class QPDF_Dictionary: public QPDFValue |
| 12 | { | 12 | { |
| 13 | public: | 13 | public: |
| 14 | virtual ~QPDF_Dictionary() = default; | 14 | virtual ~QPDF_Dictionary() = default; |
| @@ -17,8 +17,6 @@ class QPDF_Dictionary: public QPDFObject | @@ -17,8 +17,6 @@ class QPDF_Dictionary: public QPDFObject | ||
| 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | virtual std::string unparse(); | 18 | virtual std::string unparse(); |
| 19 | virtual JSON getJSON(int json_version); | 19 | virtual JSON getJSON(int json_version); |
| 20 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 21 | - virtual char const* getTypeName() const; | ||
| 22 | 20 | ||
| 23 | // hasKey() and getKeys() treat keys with null values as if they | 21 | // hasKey() and getKeys() treat keys with null values as if they |
| 24 | // aren't there. getKey() returns null for the value of a | 22 | // aren't there. getKey() returns null for the value of a |
libqpdf/qpdf/QPDF_InlineImage.hh
| 1 | #ifndef QPDF_INLINEIMAGE_HH | 1 | #ifndef QPDF_INLINEIMAGE_HH |
| 2 | #define QPDF_INLINEIMAGE_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_InlineImage() = default; | 9 | virtual ~QPDF_InlineImage() = default; |
| @@ -11,8 +11,6 @@ class QPDF_InlineImage: public QPDFObject | @@ -11,8 +11,6 @@ class QPDF_InlineImage: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | std::string getVal() const; | 14 | std::string getVal() const; |
| 17 | 15 | ||
| 18 | private: | 16 | private: |
libqpdf/qpdf/QPDF_Integer.hh
| 1 | #ifndef QPDF_INTEGER_HH | 1 | #ifndef QPDF_INTEGER_HH |
| 2 | #define QPDF_INTEGER_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Integer() = default; | 9 | virtual ~QPDF_Integer() = default; |
| @@ -11,8 +11,6 @@ class QPDF_Integer: public QPDFObject | @@ -11,8 +11,6 @@ class QPDF_Integer: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | long long getVal() const; | 14 | long long getVal() const; |
| 17 | 15 | ||
| 18 | private: | 16 | private: |
libqpdf/qpdf/QPDF_Name.hh
| 1 | #ifndef QPDF_NAME_HH | 1 | #ifndef QPDF_NAME_HH |
| 2 | #define QPDF_NAME_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Name() = default; | 9 | virtual ~QPDF_Name() = default; |
| @@ -11,8 +11,6 @@ class QPDF_Name: public QPDFObject | @@ -11,8 +11,6 @@ class QPDF_Name: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | std::string getName() const; | 14 | std::string getName() const; |
| 17 | 15 | ||
| 18 | // Put # into strings with characters unsuitable for name token | 16 | // Put # into strings with characters unsuitable for name token |
libqpdf/qpdf/QPDF_Null.hh
| 1 | #ifndef QPDF_NULL_HH | 1 | #ifndef QPDF_NULL_HH |
| 2 | #define QPDF_NULL_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Null() = default; | 9 | virtual ~QPDF_Null() = default; |
| @@ -11,11 +11,9 @@ class QPDF_Null: public QPDFObject | @@ -11,11 +11,9 @@ class QPDF_Null: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | 14 | ||
| 17 | private: | 15 | private: |
| 18 | - QPDF_Null() = default; | 16 | + QPDF_Null(); |
| 19 | }; | 17 | }; |
| 20 | 18 | ||
| 21 | #endif // QPDF_NULL_HH | 19 | #endif // QPDF_NULL_HH |
libqpdf/qpdf/QPDF_Operator.hh
| 1 | #ifndef QPDF_OPERATOR_HH | 1 | #ifndef QPDF_OPERATOR_HH |
| 2 | #define QPDF_OPERATOR_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Operator() = default; | 9 | virtual ~QPDF_Operator() = default; |
| @@ -11,8 +11,6 @@ class QPDF_Operator: public QPDFObject | @@ -11,8 +11,6 @@ class QPDF_Operator: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | std::string getVal() const; | 14 | std::string getVal() const; |
| 17 | 15 | ||
| 18 | private: | 16 | private: |
libqpdf/qpdf/QPDF_Real.hh
| 1 | #ifndef QPDF_REAL_HH | 1 | #ifndef QPDF_REAL_HH |
| 2 | #define QPDF_REAL_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Real() = default; | 9 | virtual ~QPDF_Real() = default; |
| @@ -13,8 +13,6 @@ class QPDF_Real: public QPDFObject | @@ -13,8 +13,6 @@ class QPDF_Real: public QPDFObject | ||
| 13 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 13 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 14 | virtual std::string unparse(); | 14 | virtual std::string unparse(); |
| 15 | virtual JSON getJSON(int json_version); | 15 | virtual JSON getJSON(int json_version); |
| 16 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 17 | - virtual char const* getTypeName() const; | ||
| 18 | std::string getVal(); | 16 | std::string getVal(); |
| 19 | 17 | ||
| 20 | private: | 18 | private: |
libqpdf/qpdf/QPDF_Reserved.hh
| 1 | #ifndef QPDF_RESERVED_HH | 1 | #ifndef QPDF_RESERVED_HH |
| 2 | #define QPDF_RESERVED_HH | 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 | public: | 8 | public: |
| 9 | virtual ~QPDF_Reserved() = default; | 9 | virtual ~QPDF_Reserved() = default; |
| @@ -11,11 +11,9 @@ class QPDF_Reserved: public QPDFObject | @@ -11,11 +11,9 @@ class QPDF_Reserved: public QPDFObject | ||
| 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 11 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 12 | virtual std::string unparse(); | 12 | virtual std::string unparse(); |
| 13 | virtual JSON getJSON(int json_version); | 13 | virtual JSON getJSON(int json_version); |
| 14 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 15 | - virtual char const* getTypeName() const; | ||
| 16 | 14 | ||
| 17 | private: | 15 | private: |
| 18 | - QPDF_Reserved() = default; | 16 | + QPDF_Reserved(); |
| 19 | }; | 17 | }; |
| 20 | 18 | ||
| 21 | #endif // QPDF_RESERVED_HH | 19 | #endif // QPDF_RESERVED_HH |
libqpdf/qpdf/QPDF_Stream.hh
| @@ -3,9 +3,9 @@ | @@ -3,9 +3,9 @@ | ||
| 3 | 3 | ||
| 4 | #include <qpdf/Types.h> | 4 | #include <qpdf/Types.h> |
| 5 | 5 | ||
| 6 | -#include <qpdf/QPDFObject.hh> | ||
| 7 | #include <qpdf/QPDFObjectHandle.hh> | 6 | #include <qpdf/QPDFObjectHandle.hh> |
| 8 | #include <qpdf/QPDFStreamFilter.hh> | 7 | #include <qpdf/QPDFStreamFilter.hh> |
| 8 | +#include <qpdf/QPDFValue.hh> | ||
| 9 | 9 | ||
| 10 | #include <functional> | 10 | #include <functional> |
| 11 | #include <memory> | 11 | #include <memory> |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | class Pipeline; | 13 | class Pipeline; |
| 14 | class QPDF; | 14 | class QPDF; |
| 15 | 15 | ||
| 16 | -class QPDF_Stream: public QPDFObject | 16 | +class QPDF_Stream: public QPDFValue |
| 17 | { | 17 | { |
| 18 | public: | 18 | public: |
| 19 | virtual ~QPDF_Stream() = default; | 19 | virtual ~QPDF_Stream() = default; |
| @@ -26,8 +26,6 @@ class QPDF_Stream: public QPDFObject | @@ -26,8 +26,6 @@ class QPDF_Stream: public QPDFObject | ||
| 26 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 26 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 27 | virtual std::string unparse(); | 27 | virtual std::string unparse(); |
| 28 | virtual JSON getJSON(int json_version); | 28 | virtual JSON getJSON(int json_version); |
| 29 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 30 | - virtual char const* getTypeName() const; | ||
| 31 | virtual void setDescription(QPDF*, std::string const&); | 29 | virtual void setDescription(QPDF*, std::string const&); |
| 32 | QPDFObjectHandle getDict() const; | 30 | QPDFObjectHandle getDict() const; |
| 33 | bool isDataModified() const; | 31 | bool isDataModified() const; |
libqpdf/qpdf/QPDF_String.hh
| 1 | #ifndef QPDF_STRING_HH | 1 | #ifndef QPDF_STRING_HH |
| 2 | #define QPDF_STRING_HH | 2 | #define QPDF_STRING_HH |
| 3 | 3 | ||
| 4 | -#include <qpdf/QPDFObject.hh> | 4 | +#include <qpdf/QPDFValue.hh> |
| 5 | 5 | ||
| 6 | // QPDF_Strings may included embedded null characters. | 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 | friend class QPDFWriter; | 10 | friend class QPDFWriter; |
| 11 | 11 | ||
| @@ -16,8 +16,6 @@ class QPDF_String: public QPDFObject | @@ -16,8 +16,6 @@ class QPDF_String: public QPDFObject | ||
| 16 | create_utf16(std::string const& utf8_val); | 16 | create_utf16(std::string const& utf8_val); |
| 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); | 17 | virtual std::shared_ptr<QPDFObject> shallowCopy(); |
| 18 | virtual std::string unparse(); | 18 | virtual std::string unparse(); |
| 19 | - virtual QPDFObject::object_type_e getTypeCode() const; | ||
| 20 | - virtual char const* getTypeName() const; | ||
| 21 | std::string unparse(bool force_binary); | 19 | std::string unparse(bool force_binary); |
| 22 | virtual JSON getJSON(int json_version); | 20 | virtual JSON getJSON(int json_version); |
| 23 | std::string getVal() const; | 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,7 +254,7 @@ QPDFWriter standard deterministic ID 1 | ||
| 254 | QPDFWriter linearized deterministic ID 1 | 254 | QPDFWriter linearized deterministic ID 1 |
| 255 | QPDFWriter deterministic with no data 0 | 255 | QPDFWriter deterministic with no data 0 |
| 256 | qpdf-c called qpdf_set_deterministic_ID 0 | 256 | qpdf-c called qpdf_set_deterministic_ID 0 |
| 257 | -QPDFObjectHandle indirect with 0 objid 0 | 257 | +QPDFParser indirect with 0 objid 0 |
| 258 | QPDF object id 0 0 | 258 | QPDF object id 0 0 |
| 259 | QPDF recursion loop in resolve 0 | 259 | QPDF recursion loop in resolve 0 |
| 260 | QPDFParser treat word as string 0 | 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,7 +9,6 @@ WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary | ||
| 9 | WARNING: issue-51.pdf (object 2 0, offset 71): attempting to recover stream length | 9 | WARNING: issue-51.pdf (object 2 0, offset 71): attempting to recover stream length |
| 10 | WARNING: issue-51.pdf (object 2 0, offset 71): unable to recover stream data; treating stream as empty | 10 | WARNING: issue-51.pdf (object 2 0, offset 71): unable to recover stream data; treating stream as empty |
| 11 | WARNING: issue-51.pdf (object 2 0, offset 977): expected endobj | 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 | WARNING: issue-51.pdf (object 3 0): object has offset 0 | 12 | WARNING: issue-51.pdf (object 3 0): object has offset 0 |
| 14 | WARNING: issue-51.pdf (object 4 0): object has offset 0 | 13 | WARNING: issue-51.pdf (object 4 0): object has offset 0 |
| 15 | WARNING: issue-51.pdf (object 5 0): object has offset 0 | 14 | WARNING: issue-51.pdf (object 5 0): object has offset 0 |
qpdf/qtest/type-checks.test
| @@ -14,7 +14,7 @@ cleanup(); | @@ -14,7 +14,7 @@ cleanup(); | ||
| 14 | 14 | ||
| 15 | my $td = new TestDriver('type-checks'); | 15 | my $td = new TestDriver('type-checks'); |
| 16 | 16 | ||
| 17 | -my $n_tests = 5; | 17 | +my $n_tests = 6; |
| 18 | 18 | ||
| 19 | # Whenever object-types.pdf is edited, object-types-os.pdf should be | 19 | # Whenever object-types.pdf is edited, object-types-os.pdf should be |
| 20 | # regenerated. | 20 | # regenerated. |
| @@ -43,6 +43,10 @@ $td->runtest("compound type checks", | @@ -43,6 +43,10 @@ $td->runtest("compound type checks", | ||
| 43 | {$td->COMMAND => "test_driver 82 object-types-os.pdf"}, | 43 | {$td->COMMAND => "test_driver 82 object-types-os.pdf"}, |
| 44 | {$td->STRING => "test 82 done\n", $td->EXIT_STATUS => 0}, | 44 | {$td->STRING => "test 82 done\n", $td->EXIT_STATUS => 0}, |
| 45 | $td->NORMALIZE_NEWLINES); | 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 | cleanup(); | 51 | cleanup(); |
| 48 | $td->report($n_tests); | 52 | $td->report($n_tests); |
qpdf/test_driver.cc
| @@ -3258,6 +3258,20 @@ test_91(QPDF& pdf, char const* arg2) | @@ -3258,6 +3258,20 @@ test_91(QPDF& pdf, char const* arg2) | ||
| 3258 | 2, &p, qpdf_dl_none, qpdf_sj_inline, "", std::set<std::string>()); | 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 | void | 3275 | void |
| 3262 | runtest(int n, char const* filename1, char const* arg2) | 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,7 +3279,7 @@ runtest(int n, char const* filename1, char const* arg2) | ||
| 3265 | // the test suite to see how the test is invoked to find the file | 3279 | // the test suite to see how the test is invoked to find the file |
| 3266 | // that the test is supposed to operate on. | 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 | if (n == 0) { | 3284 | if (n == 0) { |
| 3271 | // Throw in some random test cases that don't fit anywhere | 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,7 +3376,8 @@ runtest(int n, char const* filename1, char const* arg2) | ||
| 3362 | {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, | 3376 | {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, |
| 3363 | {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, | 3377 | {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, |
| 3364 | {84, test_84}, {85, test_85}, {86, test_86}, {87, test_87}, | 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 | auto fn = test_functions.find(n); | 3382 | auto fn = test_functions.find(n); |
| 3368 | if (fn == test_functions.end()) { | 3383 | if (fn == test_functions.end()) { |