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,9 +22,10 @@ | ||
| 22 | 22 | ||
| 23 | #include <qpdf/Constants.h> | 23 | #include <qpdf/Constants.h> |
| 24 | #include <qpdf/DLL.h> | 24 | #include <qpdf/DLL.h> |
| 25 | +#include <qpdf/QPDFObjGen.hh> | ||
| 25 | #include <qpdf/Types.h> | 26 | #include <qpdf/Types.h> |
| 26 | 27 | ||
| 27 | -#include <qpdf/QPDFObjGen.hh> | 28 | +#include <cstdint> |
| 28 | 29 | ||
| 29 | class QPDF_Dictionary; | 30 | class QPDF_Dictionary; |
| 30 | class QPDFObject; | 31 | class QPDFObject; |
| @@ -32,6 +33,11 @@ class QPDFObjectHandle; | @@ -32,6 +33,11 @@ class QPDFObjectHandle; | ||
| 32 | 33 | ||
| 33 | namespace qpdf | 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 | // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only | 41 | // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only |
| 36 | // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, | 42 | // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, |
| 37 | // QPDFObjGen and bool. | 43 | // QPDFObjGen and bool. |
| @@ -44,6 +50,8 @@ namespace qpdf | @@ -44,6 +50,8 @@ namespace qpdf | ||
| 44 | 50 | ||
| 45 | // The rest of the header file is for qpdf internal use only. | 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 | protected: | 55 | protected: |
| 48 | BaseHandle() = default; | 56 | BaseHandle() = default; |
| 49 | BaseHandle(std::shared_ptr<QPDFObject> const& obj) : | 57 | BaseHandle(std::shared_ptr<QPDFObject> const& obj) : |
include/qpdf/QPDFObjectHandle.hh
| @@ -304,7 +304,7 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -304,7 +304,7 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 304 | // other one changes color." This does not perform a structural comparison of the contents of | 304 | // other one changes color." This does not perform a structural comparison of the contents of |
| 305 | // the objects. | 305 | // the objects. |
| 306 | QPDF_DLL | 306 | QPDF_DLL |
| 307 | - bool isSameObjectAs(QPDFObjectHandle const&) const noexcept; | 307 | + bool isSameObjectAs(QPDFObjectHandle const&) const; |
| 308 | 308 | ||
| 309 | // Return type code and type name of underlying object. These are useful for doing rapid type | 309 | // Return type code and type name of underlying object. These are useful for doing rapid type |
| 310 | // tests (like switch statements) or for testing and debugging. | 310 | // tests (like switch statements) or for testing and debugging. |
| @@ -1355,6 +1355,8 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -1355,6 +1355,8 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 1355 | 1355 | ||
| 1356 | void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; | 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 | private: | 1360 | private: |
| 1359 | QPDF_Array* asArray() const; | 1361 | QPDF_Array* asArray() const; |
| 1360 | QPDF_Bool* asBool() const; | 1362 | QPDF_Bool* asBool() const; |
libqpdf/QPDFObjectHandle.cc
| 1 | -#include <qpdf/QPDFObjectHandle.hh> | 1 | +#include <qpdf/QPDFObjectHandle_private.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/BufferInputSource.hh> | 3 | #include <qpdf/BufferInputSource.hh> |
| 4 | #include <qpdf/JSON_writer.hh> | 4 | #include <qpdf/JSON_writer.hh> |
| @@ -38,7 +38,6 @@ | @@ -38,7 +38,6 @@ | ||
| 38 | #include <stdexcept> | 38 | #include <stdexcept> |
| 39 | 39 | ||
| 40 | using namespace std::literals; | 40 | using namespace std::literals; |
| 41 | - | ||
| 42 | using namespace qpdf; | 41 | using namespace qpdf; |
| 43 | 42 | ||
| 44 | BaseHandle:: | 43 | BaseHandle:: |
| @@ -230,7 +229,7 @@ LastChar::getLastChar() | @@ -230,7 +229,7 @@ LastChar::getLastChar() | ||
| 230 | } | 229 | } |
| 231 | 230 | ||
| 232 | bool | 231 | bool |
| 233 | -QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const noexcept | 232 | +QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const |
| 234 | { | 233 | { |
| 235 | return this->obj == rhs.obj; | 234 | return this->obj == rhs.obj; |
| 236 | } | 235 | } |
| @@ -986,9 +985,9 @@ QPDFObjectHandle::ditems() | @@ -986,9 +985,9 @@ QPDFObjectHandle::ditems() | ||
| 986 | bool | 985 | bool |
| 987 | QPDFObjectHandle::hasKey(std::string const& key) const | 986 | QPDFObjectHandle::hasKey(std::string const& key) const |
| 988 | { | 987 | { |
| 989 | - auto dict = asDictionary(); | 988 | + auto dict = as_dictionary(strict); |
| 990 | if (dict) { | 989 | if (dict) { |
| 991 | - return dict->hasKey(key); | 990 | + return dict.hasKey(key); |
| 992 | } else { | 991 | } else { |
| 993 | typeWarning("dictionary", "returning false for a key containment request"); | 992 | typeWarning("dictionary", "returning false for a key containment request"); |
| 994 | QTC::TC("qpdf", "QPDFObjectHandle dictionary false for hasKey"); | 993 | QTC::TC("qpdf", "QPDFObjectHandle dictionary false for hasKey"); |
| @@ -999,14 +998,13 @@ QPDFObjectHandle::hasKey(std::string const& key) const | @@ -999,14 +998,13 @@ QPDFObjectHandle::hasKey(std::string const& key) const | ||
| 999 | QPDFObjectHandle | 998 | QPDFObjectHandle |
| 1000 | QPDFObjectHandle::getKey(std::string const& key) const | 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 | QPDFObjectHandle | 1010 | QPDFObjectHandle |
| @@ -1018,29 +1016,23 @@ QPDFObjectHandle::getKeyIfDict(std::string const& key) const | @@ -1018,29 +1016,23 @@ QPDFObjectHandle::getKeyIfDict(std::string const& key) const | ||
| 1018 | std::set<std::string> | 1016 | std::set<std::string> |
| 1019 | QPDFObjectHandle::getKeys() const | 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 | std::map<std::string, QPDFObjectHandle> | 1027 | std::map<std::string, QPDFObjectHandle> |
| 1033 | QPDFObjectHandle::getDictAsMap() const | 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 | // Array and Name accessors | 1038 | // Array and Name accessors |
| @@ -1221,14 +1213,13 @@ QPDFObjectHandle::getUniqueResourceName( | @@ -1221,14 +1213,13 @@ QPDFObjectHandle::getUniqueResourceName( | ||
| 1221 | void | 1213 | void |
| 1222 | QPDFObjectHandle::replaceKey(std::string const& key, QPDFObjectHandle const& value) | 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 | checkOwnership(value); | 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 | QPDFObjectHandle | 1225 | QPDFObjectHandle |
| @@ -1249,22 +1240,20 @@ QPDFObjectHandle::replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle c | @@ -1249,22 +1240,20 @@ QPDFObjectHandle::replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle c | ||
| 1249 | void | 1240 | void |
| 1250 | QPDFObjectHandle::removeKey(std::string const& key) | 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 | QPDFObjectHandle | 1251 | QPDFObjectHandle |
| 1262 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) | 1252 | QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) |
| 1263 | { | 1253 | { |
| 1264 | auto result = QPDFObjectHandle::newNull(); | 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 | removeKey(key); | 1258 | removeKey(key); |
| 1270 | return result; | 1259 | return result; |
| @@ -2115,9 +2104,9 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | @@ -2115,9 +2104,9 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | ||
| 2115 | this->obj = QPDF_Array::create(items); | 2104 | this->obj = QPDF_Array::create(items); |
| 2116 | } else if (isDictionary()) { | 2105 | } else if (isDictionary()) { |
| 2117 | std::map<std::string, QPDFObjectHandle> items; | 2106 | std::map<std::string, QPDFObjectHandle> items; |
| 2118 | - auto dict = asDictionary(); | 2107 | + auto dict = as_dictionary(strict); |
| 2119 | for (auto const& key: getKeys()) { | 2108 | for (auto const& key: getKeys()) { |
| 2120 | - items[key] = dict->getKey(key); | 2109 | + items[key] = dict.getKey(key); |
| 2121 | items[key].makeDirect(visited, stop_at_streams); | 2110 | items[key].makeDirect(visited, stop_at_streams); |
| 2122 | } | 2111 | } |
| 2123 | this->obj = QPDF_Dictionary::create(items); | 2112 | this->obj = QPDF_Dictionary::create(items); |
libqpdf/QPDF_Dictionary.cc
| 1 | #include <qpdf/QPDF_Dictionary.hh> | 1 | #include <qpdf/QPDF_Dictionary.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/JSON_writer.hh> | 3 | #include <qpdf/JSON_writer.hh> |
| 4 | -#include <qpdf/QPDFObjectHandle.hh> | 4 | +#include <qpdf/QPDFObjectHandle_private.hh> |
| 5 | #include <qpdf/QPDFObject_private.hh> | 5 | #include <qpdf/QPDFObject_private.hh> |
| 6 | #include <qpdf/QPDF_Name.hh> | 6 | #include <qpdf/QPDF_Name.hh> |
| 7 | -#include <qpdf/QPDF_Null.hh> | 7 | +#include <qpdf/QTC.hh> |
| 8 | #include <qpdf/QUtil.hh> | 8 | #include <qpdf/QUtil.hh> |
| 9 | 9 | ||
| 10 | using namespace std::literals; | 10 | using namespace std::literals; |
| @@ -96,31 +96,45 @@ QPDF_Dictionary::writeJSON(int json_version, JSON::Writer& p) | @@ -96,31 +96,45 @@ QPDF_Dictionary::writeJSON(int json_version, JSON::Writer& p) | ||
| 96 | p.writeEnd('}'); | 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 | bool | 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 | QPDFObjectHandle | 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 | // PDF spec says fetching a non-existent key from a dictionary returns the null object. | 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 | // May be a null object | 126 | // May be a null object |
| 112 | return item->second; | 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 | std::set<std::string> | 133 | std::set<std::string> |
| 120 | -QPDF_Dictionary::getKeys() | 134 | +BaseDictionary::getKeys() |
| 121 | { | 135 | { |
| 122 | std::set<std::string> result; | 136 | std::set<std::string> result; |
| 123 | - for (auto& iter: this->items) { | 137 | + for (auto& iter: dict()->items) { |
| 124 | if (!iter.second.isNull()) { | 138 | if (!iter.second.isNull()) { |
| 125 | result.insert(iter.first); | 139 | result.insert(iter.first); |
| 126 | } | 140 | } |
| @@ -129,28 +143,29 @@ QPDF_Dictionary::getKeys() | @@ -129,28 +143,29 @@ QPDF_Dictionary::getKeys() | ||
| 129 | } | 143 | } |
| 130 | 144 | ||
| 131 | std::map<std::string, QPDFObjectHandle> const& | 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 | void | 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 | void | 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,7 +6,10 @@ | ||
| 6 | #include <map> | 6 | #include <map> |
| 7 | #include <set> | 7 | #include <set> |
| 8 | 8 | ||
| 9 | +#include <qpdf/QPDFExc.hh> | ||
| 9 | #include <qpdf/QPDFObjectHandle.hh> | 10 | #include <qpdf/QPDFObjectHandle.hh> |
| 11 | +#include <qpdf/QPDFObject_private.hh> | ||
| 12 | +#include <qpdf/QPDF_Null.hh> | ||
| 10 | 13 | ||
| 11 | class QPDF_Dictionary: public QPDFValue | 14 | class QPDF_Dictionary: public QPDFValue |
| 12 | { | 15 | { |
| @@ -19,22 +22,12 @@ class QPDF_Dictionary: public QPDFValue | @@ -19,22 +22,12 @@ class QPDF_Dictionary: public QPDFValue | ||
| 19 | void writeJSON(int json_version, JSON::Writer& p) override; | 22 | void writeJSON(int json_version, JSON::Writer& p) override; |
| 20 | void disconnect() override; | 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 | private: | 25 | private: |
| 26 | + friend class qpdf::BaseDictionary; | ||
| 27 | + | ||
| 36 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items); | 28 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items); |
| 37 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items); | 29 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items); |
| 30 | + | ||
| 38 | std::map<std::string, QPDFObjectHandle> items; | 31 | std::map<std::string, QPDFObjectHandle> items; |
| 39 | }; | 32 | }; |
| 40 | 33 |