Commit 3d0191215d84d28fe63c2b5d78c0f710fd089c13
1 parent
a148b870
Refactor QPDF_Dictionary
Move all dictionary specific methods to BaseDictionary. Create new subclass Dictionary to allow QPDFObjectHandle to access the moved methods.
Showing
6 changed files
with
168 additions
and
87 deletions
include/qpdf/ObjectHandle.hh
| ... | ... | @@ -22,9 +22,10 @@ |
| 22 | 22 | |
| 23 | 23 | #include <qpdf/Constants.h> |
| 24 | 24 | #include <qpdf/DLL.h> |
| 25 | +#include <qpdf/QPDFObjGen.hh> | |
| 25 | 26 | #include <qpdf/Types.h> |
| 26 | 27 | |
| 27 | -#include <qpdf/QPDFObjGen.hh> | |
| 28 | +#include <cstdint> | |
| 28 | 29 | |
| 29 | 30 | class QPDF_Dictionary; |
| 30 | 31 | class QPDFObject; |
| ... | ... | @@ -32,6 +33,11 @@ class QPDFObjectHandle; |
| 32 | 33 | |
| 33 | 34 | namespace qpdf |
| 34 | 35 | { |
| 36 | + class Dictionary; | |
| 37 | + class BaseDictionary; | |
| 38 | + | |
| 39 | + enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4}; | |
| 40 | + | |
| 35 | 41 | // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only |
| 36 | 42 | // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, |
| 37 | 43 | // QPDFObjGen and bool. |
| ... | ... | @@ -44,6 +50,8 @@ namespace qpdf |
| 44 | 50 | |
| 45 | 51 | // The rest of the header file is for qpdf internal use only. |
| 46 | 52 | |
| 53 | + inline qpdf_object_type_e type_code() const; | |
| 54 | + | |
| 47 | 55 | protected: |
| 48 | 56 | BaseHandle() = default; |
| 49 | 57 | BaseHandle(std::shared_ptr<QPDFObject> const& obj) : | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -304,7 +304,7 @@ class QPDFObjectHandle final: public qpdf::BaseHandle |
| 304 | 304 | // other one changes color." This does not perform a structural comparison of the contents of |
| 305 | 305 | // the objects. |
| 306 | 306 | QPDF_DLL |
| 307 | - bool isSameObjectAs(QPDFObjectHandle const&) const noexcept; | |
| 307 | + bool isSameObjectAs(QPDFObjectHandle const&) const; | |
| 308 | 308 | |
| 309 | 309 | // Return type code and type name of underlying object. These are useful for doing rapid type |
| 310 | 310 | // tests (like switch statements) or for testing and debugging. |
| ... | ... | @@ -1355,6 +1355,8 @@ class QPDFObjectHandle final: public qpdf::BaseHandle |
| 1355 | 1355 | |
| 1356 | 1356 | void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; |
| 1357 | 1357 | |
| 1358 | + inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const; | |
| 1359 | + | |
| 1358 | 1360 | private: |
| 1359 | 1361 | QPDF_Array* asArray() const; |
| 1360 | 1362 | QPDF_Bool* asBool() const; | ... | ... |
libqpdf/QPDFObjectHandle.cc
| 1 | -#include <qpdf/QPDFObjectHandle.hh> | |
| 1 | +#include <qpdf/QPDFObjectHandle_private.hh> | |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/BufferInputSource.hh> |
| 4 | 4 | #include <qpdf/JSON_writer.hh> |
| ... | ... | @@ -38,7 +38,6 @@ |
| 38 | 38 | #include <stdexcept> |
| 39 | 39 | |
| 40 | 40 | using namespace std::literals; |
| 41 | - | |
| 42 | 41 | using namespace qpdf; |
| 43 | 42 | |
| 44 | 43 | BaseHandle:: |
| ... | ... | @@ -230,7 +229,7 @@ LastChar::getLastChar() |
| 230 | 229 | } |
| 231 | 230 | |
| 232 | 231 | bool |
| 233 | -QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const noexcept | |
| 232 | +QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | |
| 234 | 233 | { |
| 235 | 234 | return this->obj == rhs.obj; |
| 236 | 235 | } |
| ... | ... | @@ -986,9 +985,9 @@ QPDFObjectHandle::ditems() |
| 986 | 985 | bool |
| 987 | 986 | QPDFObjectHandle::hasKey(std::string const& key) const |
| 988 | 987 | { |
| 989 | - auto dict = asDictionary(); | |
| 988 | + auto dict = as_dictionary(strict); | |
| 990 | 989 | if (dict) { |
| 991 | - return dict->hasKey(key); | |
| 990 | + return dict.hasKey(key); | |
| 992 | 991 | } else { |
| 993 | 992 | typeWarning("dictionary", "returning false for a key containment request"); |
| 994 | 993 | QTC::TC("qpdf", "QPDFObjectHandle dictionary false for hasKey"); |
| ... | ... | @@ -999,14 +998,13 @@ QPDFObjectHandle::hasKey(std::string const& key) const |
| 999 | 998 | QPDFObjectHandle |
| 1000 | 999 | QPDFObjectHandle::getKey(std::string const& key) const |
| 1001 | 1000 | { |
| 1002 | - if (auto dict = asDictionary()) { | |
| 1003 | - return dict->getKey(key); | |
| 1004 | - } else { | |
| 1005 | - typeWarning("dictionary", "returning null for attempted key retrieval"); | |
| 1006 | - QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); | |
| 1007 | - static auto constexpr msg = " -> null returned from getting key $VD from non-Dictionary"sv; | |
| 1008 | - return QPDF_Null::create(obj, msg, ""); | |
| 1001 | + if (auto dict = as_dictionary(strict)) { | |
| 1002 | + return dict.getKey(key); | |
| 1009 | 1003 | } |
| 1004 | + typeWarning("dictionary", "returning null for attempted key retrieval"); | |
| 1005 | + QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); | |
| 1006 | + static auto constexpr msg = " -> null returned from getting key $VD from non-Dictionary"sv; | |
| 1007 | + return QPDF_Null::create(obj, msg, ""); | |
| 1010 | 1008 | } |
| 1011 | 1009 | |
| 1012 | 1010 | QPDFObjectHandle |
| ... | ... | @@ -1018,29 +1016,23 @@ QPDFObjectHandle::getKeyIfDict(std::string const& key) const |
| 1018 | 1016 | std::set<std::string> |
| 1019 | 1017 | QPDFObjectHandle::getKeys() const |
| 1020 | 1018 | { |
| 1021 | - std::set<std::string> result; | |
| 1022 | - auto dict = asDictionary(); | |
| 1023 | - if (dict) { | |
| 1024 | - result = dict->getKeys(); | |
| 1025 | - } else { | |
| 1026 | - typeWarning("dictionary", "treating as empty"); | |
| 1027 | - QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); | |
| 1019 | + if (auto dict = as_dictionary(strict)) { | |
| 1020 | + return dict.getKeys(); | |
| 1028 | 1021 | } |
| 1029 | - return result; | |
| 1022 | + typeWarning("dictionary", "treating as empty"); | |
| 1023 | + QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); | |
| 1024 | + return {}; | |
| 1030 | 1025 | } |
| 1031 | 1026 | |
| 1032 | 1027 | std::map<std::string, QPDFObjectHandle> |
| 1033 | 1028 | QPDFObjectHandle::getDictAsMap() const |
| 1034 | 1029 | { |
| 1035 | - std::map<std::string, QPDFObjectHandle> result; | |
| 1036 | - auto dict = asDictionary(); | |
| 1037 | - if (dict) { | |
| 1038 | - result = dict->getAsMap(); | |
| 1039 | - } else { | |
| 1040 | - typeWarning("dictionary", "treating as empty"); | |
| 1041 | - QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); | |
| 1030 | + if (auto dict = as_dictionary(strict)) { | |
| 1031 | + return dict.getAsMap(); | |
| 1042 | 1032 | } |
| 1043 | - return result; | |
| 1033 | + typeWarning("dictionary", "treating as empty"); | |
| 1034 | + QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); | |
| 1035 | + return {}; | |
| 1044 | 1036 | } |
| 1045 | 1037 | |
| 1046 | 1038 | // Array and Name accessors |
| ... | ... | @@ -1221,14 +1213,13 @@ QPDFObjectHandle::getUniqueResourceName( |
| 1221 | 1213 | void |
| 1222 | 1214 | QPDFObjectHandle::replaceKey(std::string const& key, QPDFObjectHandle const& value) |
| 1223 | 1215 | { |
| 1224 | - auto dict = asDictionary(); | |
| 1225 | - if (dict) { | |
| 1216 | + if (auto dict = as_dictionary(strict)) { | |
| 1226 | 1217 | checkOwnership(value); |
| 1227 | - dict->replaceKey(key, value); | |
| 1228 | - } else { | |
| 1229 | - typeWarning("dictionary", "ignoring key replacement request"); | |
| 1230 | - QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); | |
| 1218 | + dict.replaceKey(key, value); | |
| 1219 | + return; | |
| 1231 | 1220 | } |
| 1221 | + typeWarning("dictionary", "ignoring key replacement request"); | |
| 1222 | + QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); | |
| 1232 | 1223 | } |
| 1233 | 1224 | |
| 1234 | 1225 | QPDFObjectHandle |
| ... | ... | @@ -1249,22 +1240,20 @@ QPDFObjectHandle::replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle c |
| 1249 | 1240 | void |
| 1250 | 1241 | QPDFObjectHandle::removeKey(std::string const& key) |
| 1251 | 1242 | { |
| 1252 | - auto dict = asDictionary(); | |
| 1253 | - if (dict) { | |
| 1254 | - dict->removeKey(key); | |
| 1255 | - } else { | |
| 1256 | - typeWarning("dictionary", "ignoring key removal request"); | |
| 1257 | - QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); | |
| 1243 | + if (auto dict = as_dictionary(strict)) { | |
| 1244 | + dict.removeKey(key); | |
| 1245 | + return; | |
| 1258 | 1246 | } |
| 1247 | + typeWarning("dictionary", "ignoring key removal request"); | |
| 1248 | + QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); | |
| 1259 | 1249 | } |
| 1260 | 1250 | |
| 1261 | 1251 | QPDFObjectHandle |
| 1262 | 1252 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) |
| 1263 | 1253 | { |
| 1264 | 1254 | auto result = QPDFObjectHandle::newNull(); |
| 1265 | - auto dict = asDictionary(); | |
| 1266 | - if (dict) { | |
| 1267 | - result = dict->getKey(key); | |
| 1255 | + if (auto dict = as_dictionary(strict)) { | |
| 1256 | + result = dict.getKey(key); | |
| 1268 | 1257 | } |
| 1269 | 1258 | removeKey(key); |
| 1270 | 1259 | return result; |
| ... | ... | @@ -2115,9 +2104,9 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) |
| 2115 | 2104 | this->obj = QPDF_Array::create(items); |
| 2116 | 2105 | } else if (isDictionary()) { |
| 2117 | 2106 | std::map<std::string, QPDFObjectHandle> items; |
| 2118 | - auto dict = asDictionary(); | |
| 2107 | + auto dict = as_dictionary(strict); | |
| 2119 | 2108 | for (auto const& key: getKeys()) { |
| 2120 | - items[key] = dict->getKey(key); | |
| 2109 | + items[key] = dict.getKey(key); | |
| 2121 | 2110 | items[key].makeDirect(visited, stop_at_streams); |
| 2122 | 2111 | } |
| 2123 | 2112 | this->obj = QPDF_Dictionary::create(items); | ... | ... |
libqpdf/QPDF_Dictionary.cc
| 1 | 1 | #include <qpdf/QPDF_Dictionary.hh> |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/JSON_writer.hh> |
| 4 | -#include <qpdf/QPDFObjectHandle.hh> | |
| 4 | +#include <qpdf/QPDFObjectHandle_private.hh> | |
| 5 | 5 | #include <qpdf/QPDFObject_private.hh> |
| 6 | 6 | #include <qpdf/QPDF_Name.hh> |
| 7 | -#include <qpdf/QPDF_Null.hh> | |
| 7 | +#include <qpdf/QTC.hh> | |
| 8 | 8 | #include <qpdf/QUtil.hh> |
| 9 | 9 | |
| 10 | 10 | using namespace std::literals; |
| ... | ... | @@ -96,31 +96,45 @@ QPDF_Dictionary::writeJSON(int json_version, JSON::Writer& p) |
| 96 | 96 | p.writeEnd('}'); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | +QPDF_Dictionary* | |
| 100 | +BaseDictionary::dict() const | |
| 101 | +{ | |
| 102 | + if (obj) { | |
| 103 | + if (auto d = obj->as<QPDF_Dictionary>()) { | |
| 104 | + return d; | |
| 105 | + } | |
| 106 | + } | |
| 107 | + throw std::runtime_error("Expected a dictionary but found a non-dictionary object"); | |
| 108 | + return nullptr; // unreachable | |
| 109 | +} | |
| 110 | + | |
| 99 | 111 | bool |
| 100 | -QPDF_Dictionary::hasKey(std::string const& key) | |
| 112 | +BaseDictionary::hasKey(std::string const& key) const | |
| 101 | 113 | { |
| 102 | - return ((this->items.count(key) > 0) && (!this->items[key].isNull())); | |
| 114 | + auto d = dict(); | |
| 115 | + return d->items.count(key) > 0 && !d->items[key].isNull(); | |
| 103 | 116 | } |
| 104 | 117 | |
| 105 | 118 | QPDFObjectHandle |
| 106 | -QPDF_Dictionary::getKey(std::string const& key) | |
| 119 | +BaseDictionary::getKey(std::string const& key) const | |
| 107 | 120 | { |
| 121 | + auto d = dict(); | |
| 122 | + | |
| 108 | 123 | // PDF spec says fetching a non-existent key from a dictionary returns the null object. |
| 109 | - auto item = this->items.find(key); | |
| 110 | - if (item != this->items.end()) { | |
| 124 | + auto item = d->items.find(key); | |
| 125 | + if (item != d->items.end()) { | |
| 111 | 126 | // May be a null object |
| 112 | 127 | return item->second; |
| 113 | - } else { | |
| 114 | - static auto constexpr msg = " -> dictionary key $VD"sv; | |
| 115 | - return QPDF_Null::create(shared_from_this(), msg, key); | |
| 116 | 128 | } |
| 129 | + static auto constexpr msg = " -> dictionary key $VD"sv; | |
| 130 | + return QPDF_Null::create(obj, msg, key); | |
| 117 | 131 | } |
| 118 | 132 | |
| 119 | 133 | std::set<std::string> |
| 120 | -QPDF_Dictionary::getKeys() | |
| 134 | +BaseDictionary::getKeys() | |
| 121 | 135 | { |
| 122 | 136 | std::set<std::string> result; |
| 123 | - for (auto& iter: this->items) { | |
| 137 | + for (auto& iter: dict()->items) { | |
| 124 | 138 | if (!iter.second.isNull()) { |
| 125 | 139 | result.insert(iter.first); |
| 126 | 140 | } |
| ... | ... | @@ -129,28 +143,29 @@ QPDF_Dictionary::getKeys() |
| 129 | 143 | } |
| 130 | 144 | |
| 131 | 145 | std::map<std::string, QPDFObjectHandle> const& |
| 132 | -QPDF_Dictionary::getAsMap() const | |
| 146 | +BaseDictionary::getAsMap() const | |
| 133 | 147 | { |
| 134 | - return this->items; | |
| 148 | + return dict()->items; | |
| 135 | 149 | } |
| 136 | 150 | |
| 137 | 151 | void |
| 138 | -QPDF_Dictionary::replaceKey(std::string const& key, QPDFObjectHandle value) | |
| 152 | +BaseDictionary::removeKey(std::string const& key) | |
| 139 | 153 | { |
| 140 | - if (value.isNull() && !value.isIndirect()) { | |
| 141 | - // The PDF spec doesn't distinguish between keys with null values and missing keys. Allow | |
| 142 | - // indirect nulls which are equivalent to a dangling reference, which is permitted by the | |
| 143 | - // spec. | |
| 144 | - removeKey(key); | |
| 145 | - } else { | |
| 146 | - // add or replace value | |
| 147 | - this->items[key] = value; | |
| 148 | - } | |
| 154 | + // no-op if key does not exist | |
| 155 | + dict()->items.erase(key); | |
| 149 | 156 | } |
| 150 | 157 | |
| 151 | 158 | void |
| 152 | -QPDF_Dictionary::removeKey(std::string const& key) | |
| 159 | +BaseDictionary::replaceKey(std::string const& key, QPDFObjectHandle value) | |
| 153 | 160 | { |
| 154 | - // no-op if key does not exist | |
| 155 | - this->items.erase(key); | |
| 161 | + auto d = dict(); | |
| 162 | + if (value.isNull() && !value.isIndirect()) { | |
| 163 | + // The PDF spec doesn't distinguish between keys with null values and missing keys. | |
| 164 | + // Allow indirect nulls which are equivalent to a dangling reference, which is | |
| 165 | + // permitted by the spec. | |
| 166 | + d->items.erase(key); | |
| 167 | + } else { | |
| 168 | + // add or replace value | |
| 169 | + d->items[key] = value; | |
| 170 | + } | |
| 156 | 171 | } | ... | ... |
libqpdf/qpdf/QPDFObjectHandle_private.hh
0 โ 100644
| 1 | +#ifndef OBJECTHANDLE_PRIVATE_HH | |
| 2 | +#define OBJECTHANDLE_PRIVATE_HH | |
| 3 | + | |
| 4 | +#include <qpdf/QPDFObjectHandle.hh> | |
| 5 | + | |
| 6 | +#include <qpdf/QPDFObject_private.hh> | |
| 7 | +#include <qpdf/QPDF_Dictionary.hh> | |
| 8 | + | |
| 9 | +namespace qpdf | |
| 10 | +{ | |
| 11 | + // BaseDictionary is only used as a base class. It does not contain any methods exposed in the | |
| 12 | + // public API. | |
| 13 | + class BaseDictionary: public BaseHandle | |
| 14 | + { | |
| 15 | + public: | |
| 16 | + // The following methods are not part of the public API. | |
| 17 | + bool hasKey(std::string const& key) const; | |
| 18 | + QPDFObjectHandle getKey(std::string const& key) const; | |
| 19 | + std::set<std::string> getKeys(); | |
| 20 | + std::map<std::string, QPDFObjectHandle> const& getAsMap() const; | |
| 21 | + void removeKey(std::string const& key); | |
| 22 | + void replaceKey(std::string const& key, QPDFObjectHandle value); | |
| 23 | + | |
| 24 | + protected: | |
| 25 | + BaseDictionary() = default; | |
| 26 | + BaseDictionary(std::shared_ptr<QPDFObject> const& obj) : | |
| 27 | + BaseHandle(obj) {}; | |
| 28 | + BaseDictionary(std::shared_ptr<QPDFObject>&& obj) : | |
| 29 | + BaseHandle(std::move(obj)) {}; | |
| 30 | + BaseDictionary(BaseDictionary const&) = default; | |
| 31 | + BaseDictionary& operator=(BaseDictionary const&) = default; | |
| 32 | + BaseDictionary(BaseDictionary&&) = default; | |
| 33 | + BaseDictionary& operator=(BaseDictionary&&) = default; | |
| 34 | + ~BaseDictionary() = default; | |
| 35 | + | |
| 36 | + QPDF_Dictionary* dict() const; | |
| 37 | + }; | |
| 38 | + | |
| 39 | + class Dictionary final: public BaseDictionary | |
| 40 | + { | |
| 41 | + public: | |
| 42 | + explicit Dictionary(std::shared_ptr<QPDFObject> const& obj) : | |
| 43 | + BaseDictionary(obj) | |
| 44 | + { | |
| 45 | + } | |
| 46 | + | |
| 47 | + explicit Dictionary(std::shared_ptr<QPDFObject>&& obj) : | |
| 48 | + BaseDictionary(std::move(obj)) | |
| 49 | + { | |
| 50 | + } | |
| 51 | + }; | |
| 52 | + | |
| 53 | + inline qpdf_object_type_e | |
| 54 | + BaseHandle::type_code() const | |
| 55 | + { | |
| 56 | + return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized; | |
| 57 | + } | |
| 58 | + | |
| 59 | +} // namespace qpdf | |
| 60 | + | |
| 61 | +inline qpdf::Dictionary | |
| 62 | +QPDFObjectHandle::as_dictionary(qpdf::typed options) const | |
| 63 | +{ | |
| 64 | + if (options & qpdf::any_flag || type_code() == ::ot_dictionary || | |
| 65 | + (options & qpdf::optional && type_code() == ::ot_null)) { | |
| 66 | + return qpdf::Dictionary(obj); | |
| 67 | + } | |
| 68 | + if (options & qpdf::error) { | |
| 69 | + assertType("dictionary", false); | |
| 70 | + } | |
| 71 | + return qpdf::Dictionary(std::shared_ptr<QPDFObject>()); | |
| 72 | +} | |
| 73 | + | |
| 74 | +#endif // OBJECTHANDLE_PRIVATE_HH | ... | ... |
libqpdf/qpdf/QPDF_Dictionary.hh
| ... | ... | @@ -6,7 +6,10 @@ |
| 6 | 6 | #include <map> |
| 7 | 7 | #include <set> |
| 8 | 8 | |
| 9 | +#include <qpdf/QPDFExc.hh> | |
| 9 | 10 | #include <qpdf/QPDFObjectHandle.hh> |
| 11 | +#include <qpdf/QPDFObject_private.hh> | |
| 12 | +#include <qpdf/QPDF_Null.hh> | |
| 10 | 13 | |
| 11 | 14 | class QPDF_Dictionary: public QPDFValue |
| 12 | 15 | { |
| ... | ... | @@ -19,22 +22,12 @@ class QPDF_Dictionary: public QPDFValue |
| 19 | 22 | void writeJSON(int json_version, JSON::Writer& p) override; |
| 20 | 23 | void disconnect() override; |
| 21 | 24 | |
| 22 | - // hasKey() and getKeys() treat keys with null values as if they aren't there. getKey() returns | |
| 23 | - // null for the value of a non-existent key. This is as per the PDF spec. | |
| 24 | - bool hasKey(std::string const&); | |
| 25 | - QPDFObjectHandle getKey(std::string const&); | |
| 26 | - std::set<std::string> getKeys(); | |
| 27 | - std::map<std::string, QPDFObjectHandle> const& getAsMap() const; | |
| 28 | - | |
| 29 | - // If value is null, remove key; otherwise, replace the value of key, adding it if it does not | |
| 30 | - // exist. | |
| 31 | - void replaceKey(std::string const& key, QPDFObjectHandle value); | |
| 32 | - // Remove key, doing nothing if key does not exist | |
| 33 | - void removeKey(std::string const& key); | |
| 34 | - | |
| 35 | 25 | private: |
| 26 | + friend class qpdf::BaseDictionary; | |
| 27 | + | |
| 36 | 28 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items); |
| 37 | 29 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items); |
| 30 | + | |
| 38 | 31 | std::map<std::string, QPDFObjectHandle> items; |
| 39 | 32 | }; |
| 40 | 33 | ... | ... |