Commit 873562f46bcc61e29f696477d41914fdeb050ea8
1 parent
8d7ed764
Move QPDFObject::as to BaseHandle
Showing
9 changed files
with
61 additions
and
91 deletions
include/qpdf/ObjectHandle.hh
| @@ -67,6 +67,9 @@ namespace qpdf | @@ -67,6 +67,9 @@ namespace qpdf | ||
| 67 | BaseHandle& operator=(BaseHandle&&) = default; | 67 | BaseHandle& operator=(BaseHandle&&) = default; |
| 68 | ~BaseHandle() = default; | 68 | ~BaseHandle() = default; |
| 69 | 69 | ||
| 70 | + template <typename T> | ||
| 71 | + T* as() const; | ||
| 72 | + | ||
| 70 | std::shared_ptr<QPDFObject> obj; | 73 | std::shared_ptr<QPDFObject> obj; |
| 71 | }; | 74 | }; |
| 72 | 75 |
include/qpdf/QPDF.hh
| @@ -798,9 +798,10 @@ class QPDF | @@ -798,9 +798,10 @@ class QPDF | ||
| 798 | { | 798 | { |
| 799 | friend class QPDFObject; | 799 | friend class QPDFObject; |
| 800 | friend class QPDF_Unresolved; | 800 | friend class QPDF_Unresolved; |
| 801 | + friend class qpdf::BaseHandle; | ||
| 801 | 802 | ||
| 802 | private: | 803 | private: |
| 803 | - static QPDFObject* | 804 | + static std::shared_ptr<QPDFObject> const& |
| 804 | resolved(QPDF* qpdf, QPDFObjGen og) | 805 | resolved(QPDF* qpdf, QPDFObjGen og) |
| 805 | { | 806 | { |
| 806 | return qpdf->resolve(og); | 807 | return qpdf->resolve(og); |
| @@ -1072,7 +1073,7 @@ class QPDF | @@ -1072,7 +1073,7 @@ class QPDF | ||
| 1072 | QPDFObjGen exp_og, | 1073 | QPDFObjGen exp_og, |
| 1073 | QPDFObjGen& og, | 1074 | QPDFObjGen& og, |
| 1074 | bool skip_cache_if_in_xref); | 1075 | bool skip_cache_if_in_xref); |
| 1075 | - QPDFObject* resolve(QPDFObjGen og); | 1076 | + std::shared_ptr<QPDFObject> const& resolve(QPDFObjGen og); |
| 1076 | void resolveObjectsInStream(int obj_stream_number); | 1077 | void resolveObjectsInStream(int obj_stream_number); |
| 1077 | void stopOnError(std::string const& message); | 1078 | void stopOnError(std::string const& message); |
| 1078 | QPDFObjGen nextObjGen(); | 1079 | QPDFObjGen nextObjGen(); |
include/qpdf/QPDFObjectHandle.hh
| @@ -1359,20 +1359,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -1359,20 +1359,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 1359 | inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; | 1359 | inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; |
| 1360 | 1360 | ||
| 1361 | private: | 1361 | private: |
| 1362 | - QPDF_Array* asArray() const; | ||
| 1363 | - QPDF_Bool* asBool() const; | ||
| 1364 | - QPDF_Dictionary* asDictionary() const; | ||
| 1365 | - QPDF_InlineImage* asInlineImage() const; | ||
| 1366 | - QPDF_Integer* asInteger() const; | ||
| 1367 | - QPDF_Name* asName() const; | ||
| 1368 | - QPDF_Null* asNull() const; | ||
| 1369 | - QPDF_Operator* asOperator() const; | ||
| 1370 | - QPDF_Real* asReal() const; | ||
| 1371 | - QPDF_Reserved* asReserved() const; | ||
| 1372 | - QPDF_Stream* asStream() const; | ||
| 1373 | - QPDF_Stream* asStreamWithAssert() const; | ||
| 1374 | - QPDF_String* asString() const; | ||
| 1375 | - | ||
| 1376 | void typeWarning(char const* expected_type, std::string const& warning) const; | 1362 | void typeWarning(char const* expected_type, std::string const& warning) const; |
| 1377 | void objectWarning(std::string const& warning) const; | 1363 | void objectWarning(std::string const& warning) const; |
| 1378 | void assertType(char const* type_name, bool istype) const; | 1364 | void assertType(char const* type_name, bool istype) const; |
libqpdf/QPDF.cc
| @@ -1867,11 +1867,11 @@ QPDF::readObjectAtOffset( | @@ -1867,11 +1867,11 @@ QPDF::readObjectAtOffset( | ||
| 1867 | return oh; | 1867 | return oh; |
| 1868 | } | 1868 | } |
| 1869 | 1869 | ||
| 1870 | -QPDFObject* | 1870 | +std::shared_ptr<QPDFObject> const& |
| 1871 | QPDF::resolve(QPDFObjGen og) | 1871 | QPDF::resolve(QPDFObjGen og) |
| 1872 | { | 1872 | { |
| 1873 | if (!isUnresolved(og)) { | 1873 | if (!isUnresolved(og)) { |
| 1874 | - return m->obj_cache[og].object.get(); | 1874 | + return m->obj_cache[og].object; |
| 1875 | } | 1875 | } |
| 1876 | 1876 | ||
| 1877 | if (m->resolving.count(og)) { | 1877 | if (m->resolving.count(og)) { |
| @@ -1880,7 +1880,7 @@ QPDF::resolve(QPDFObjGen og) | @@ -1880,7 +1880,7 @@ QPDF::resolve(QPDFObjGen og) | ||
| 1880 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); | 1880 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); |
| 1881 | warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); | 1881 | warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); |
| 1882 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); | 1882 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); |
| 1883 | - return m->obj_cache[og].object.get(); | 1883 | + return m->obj_cache[og].object; |
| 1884 | } | 1884 | } |
| 1885 | ResolveRecorder rr(this, og); | 1885 | ResolveRecorder rr(this, og); |
| 1886 | 1886 | ||
| @@ -1919,9 +1919,9 @@ QPDF::resolve(QPDFObjGen og) | @@ -1919,9 +1919,9 @@ QPDF::resolve(QPDFObjGen og) | ||
| 1919 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); | 1919 | updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); |
| 1920 | } | 1920 | } |
| 1921 | 1921 | ||
| 1922 | - auto result(m->obj_cache[og].object); | 1922 | + auto& result(m->obj_cache[og].object); |
| 1923 | result->setDefaultDescription(this, og); | 1923 | result->setDefaultDescription(this, og); |
| 1924 | - return result.get(); | 1924 | + return result; |
| 1925 | } | 1925 | } |
| 1926 | 1926 | ||
| 1927 | void | 1927 | void |
libqpdf/QPDFObjectHandle.cc
| @@ -697,24 +697,6 @@ QPDFObjectHandle::getTypeName() const | @@ -697,24 +697,6 @@ QPDFObjectHandle::getTypeName() const | ||
| 697 | return obj ? tn[getTypeCode()] : "uninitialized"; | 697 | return obj ? tn[getTypeCode()] : "uninitialized"; |
| 698 | } | 698 | } |
| 699 | 699 | ||
| 700 | -QPDF_Bool* | ||
| 701 | -QPDFObjectHandle::asBool() const | ||
| 702 | -{ | ||
| 703 | - return obj ? obj->as<QPDF_Bool>() : nullptr; | ||
| 704 | -} | ||
| 705 | - | ||
| 706 | -QPDF_Integer* | ||
| 707 | -QPDFObjectHandle::asInteger() const | ||
| 708 | -{ | ||
| 709 | - return obj ? obj->as<QPDF_Integer>() : nullptr; | ||
| 710 | -} | ||
| 711 | - | ||
| 712 | -QPDF_String* | ||
| 713 | -QPDFObjectHandle::asString() const | ||
| 714 | -{ | ||
| 715 | - return obj ? obj->as<QPDF_String>() : nullptr; | ||
| 716 | -} | ||
| 717 | - | ||
| 718 | bool | 700 | bool |
| 719 | QPDFObjectHandle::isDestroyed() const | 701 | QPDFObjectHandle::isDestroyed() const |
| 720 | { | 702 | { |
| @@ -861,8 +843,7 @@ QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& sub | @@ -861,8 +843,7 @@ QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& sub | ||
| 861 | bool | 843 | bool |
| 862 | QPDFObjectHandle::getBoolValue() const | 844 | QPDFObjectHandle::getBoolValue() const |
| 863 | { | 845 | { |
| 864 | - auto boolean = asBool(); | ||
| 865 | - if (boolean) { | 846 | + if (auto boolean = as<QPDF_Bool>()) { |
| 866 | return boolean->val; | 847 | return boolean->val; |
| 867 | } else { | 848 | } else { |
| 868 | typeWarning("boolean", "returning false"); | 849 | typeWarning("boolean", "returning false"); |
| @@ -874,12 +855,11 @@ QPDFObjectHandle::getBoolValue() const | @@ -874,12 +855,11 @@ QPDFObjectHandle::getBoolValue() const | ||
| 874 | bool | 855 | bool |
| 875 | QPDFObjectHandle::getValueAsBool(bool& value) const | 856 | QPDFObjectHandle::getValueAsBool(bool& value) const |
| 876 | { | 857 | { |
| 877 | - auto boolean = asBool(); | ||
| 878 | - if (boolean == nullptr) { | ||
| 879 | - return false; | 858 | + if (auto boolean = as<QPDF_Bool>()) { |
| 859 | + value = boolean->val; | ||
| 860 | + return true; | ||
| 880 | } | 861 | } |
| 881 | - value = boolean->val; | ||
| 882 | - return true; | 862 | + return false; |
| 883 | } | 863 | } |
| 884 | 864 | ||
| 885 | // Integer accessors | 865 | // Integer accessors |
| @@ -887,8 +867,7 @@ QPDFObjectHandle::getValueAsBool(bool& value) const | @@ -887,8 +867,7 @@ QPDFObjectHandle::getValueAsBool(bool& value) const | ||
| 887 | long long | 867 | long long |
| 888 | QPDFObjectHandle::getIntValue() const | 868 | QPDFObjectHandle::getIntValue() const |
| 889 | { | 869 | { |
| 890 | - auto integer = asInteger(); | ||
| 891 | - if (integer) { | 870 | + if (auto integer = as<QPDF_Integer>()) { |
| 892 | return integer->val; | 871 | return integer->val; |
| 893 | } else { | 872 | } else { |
| 894 | typeWarning("integer", "returning 0"); | 873 | typeWarning("integer", "returning 0"); |
| @@ -900,12 +879,11 @@ QPDFObjectHandle::getIntValue() const | @@ -900,12 +879,11 @@ QPDFObjectHandle::getIntValue() const | ||
| 900 | bool | 879 | bool |
| 901 | QPDFObjectHandle::getValueAsInt(long long& value) const | 880 | QPDFObjectHandle::getValueAsInt(long long& value) const |
| 902 | { | 881 | { |
| 903 | - auto integer = asInteger(); | ||
| 904 | - if (integer == nullptr) { | ||
| 905 | - return false; | 882 | + if (auto integer = as<QPDF_Integer>()) { |
| 883 | + value = integer->val; | ||
| 884 | + return true; | ||
| 906 | } | 885 | } |
| 907 | - value = integer->val; | ||
| 908 | - return true; | 886 | + return false; |
| 909 | } | 887 | } |
| 910 | 888 | ||
| 911 | int | 889 | int |
| @@ -1062,8 +1040,7 @@ QPDFObjectHandle::getValueAsString(std::string& value) const | @@ -1062,8 +1040,7 @@ QPDFObjectHandle::getValueAsString(std::string& value) const | ||
| 1062 | std::string | 1040 | std::string |
| 1063 | QPDFObjectHandle::getUTF8Value() const | 1041 | QPDFObjectHandle::getUTF8Value() const |
| 1064 | { | 1042 | { |
| 1065 | - auto str = asString(); | ||
| 1066 | - if (str) { | 1043 | + if (auto str = as<QPDF_String>()) { |
| 1067 | return str->getUTF8Val(); | 1044 | return str->getUTF8Val(); |
| 1068 | } else { | 1045 | } else { |
| 1069 | typeWarning("string", "returning empty string"); | 1046 | typeWarning("string", "returning empty string"); |
| @@ -1075,12 +1052,11 @@ QPDFObjectHandle::getUTF8Value() const | @@ -1075,12 +1052,11 @@ QPDFObjectHandle::getUTF8Value() const | ||
| 1075 | bool | 1052 | bool |
| 1076 | QPDFObjectHandle::getValueAsUTF8(std::string& value) const | 1053 | QPDFObjectHandle::getValueAsUTF8(std::string& value) const |
| 1077 | { | 1054 | { |
| 1078 | - auto str = asString(); | ||
| 1079 | - if (str == nullptr) { | ||
| 1080 | - return false; | 1055 | + if (auto str = as<QPDF_String>()) { |
| 1056 | + value = str->getUTF8Val(); | ||
| 1057 | + return true; | ||
| 1081 | } | 1058 | } |
| 1082 | - value = str->getUTF8Val(); | ||
| 1083 | - return true; | 1059 | + return false; |
| 1084 | } | 1060 | } |
| 1085 | 1061 | ||
| 1086 | // Operator and Inline Image accessors | 1062 | // Operator and Inline Image accessors |
| @@ -1487,7 +1463,7 @@ QPDFObjectHandle::unparseResolved() const | @@ -1487,7 +1463,7 @@ QPDFObjectHandle::unparseResolved() const | ||
| 1487 | std::string | 1463 | std::string |
| 1488 | QPDFObjectHandle::unparseBinary() const | 1464 | QPDFObjectHandle::unparseBinary() const |
| 1489 | { | 1465 | { |
| 1490 | - if (auto str = asString()) { | 1466 | + if (auto str = as<QPDF_String>()) { |
| 1491 | return str->unparse(true); | 1467 | return str->unparse(true); |
| 1492 | } else { | 1468 | } else { |
| 1493 | return unparse(); | 1469 | return unparse(); |
libqpdf/QPDF_Array.cc
| @@ -59,11 +59,10 @@ QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse | @@ -59,11 +59,10 @@ QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse | ||
| 59 | QPDF_Array* | 59 | QPDF_Array* |
| 60 | Array::array() const | 60 | Array::array() const |
| 61 | { | 61 | { |
| 62 | - if (obj) { | ||
| 63 | - if (auto a = obj->as<QPDF_Array>()) { | ||
| 64 | - return a; | ||
| 65 | - } | 62 | + if (auto a = as<QPDF_Array>()) { |
| 63 | + return a; | ||
| 66 | } | 64 | } |
| 65 | + | ||
| 67 | throw std::runtime_error("Expected an array but found a non-array object"); | 66 | throw std::runtime_error("Expected an array but found a non-array object"); |
| 68 | return nullptr; // unreachable | 67 | return nullptr; // unreachable |
| 69 | } | 68 | } |
libqpdf/QPDF_Dictionary.cc
| @@ -9,10 +9,8 @@ using namespace qpdf; | @@ -9,10 +9,8 @@ using namespace qpdf; | ||
| 9 | QPDF_Dictionary* | 9 | QPDF_Dictionary* |
| 10 | BaseDictionary::dict() const | 10 | BaseDictionary::dict() const |
| 11 | { | 11 | { |
| 12 | - if (obj) { | ||
| 13 | - if (auto d = obj->as<QPDF_Dictionary>()) { | ||
| 14 | - return d; | ||
| 15 | - } | 12 | + if (auto d = as<QPDF_Dictionary>()) { |
| 13 | + return d; | ||
| 16 | } | 14 | } |
| 17 | throw std::runtime_error("Expected a dictionary but found a non-dictionary object"); | 15 | throw std::runtime_error("Expected a dictionary but found a non-dictionary object"); |
| 18 | return nullptr; // unreachable | 16 | return nullptr; // unreachable |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| @@ -204,12 +204,13 @@ namespace qpdf | @@ -204,12 +204,13 @@ namespace qpdf | ||
| 204 | QPDF_Stream::Members* | 204 | QPDF_Stream::Members* |
| 205 | stream() const | 205 | stream() const |
| 206 | { | 206 | { |
| 207 | - if (obj) { | ||
| 208 | - if (auto s = obj->as<QPDF_Stream>()) { | ||
| 209 | - return s->m.get(); | 207 | + if (auto s = as<QPDF_Stream>()) { |
| 208 | + if (auto ptr = s->m.get()) { | ||
| 209 | + return ptr; | ||
| 210 | } | 210 | } |
| 211 | + throw std::logic_error("QPDF_Stream: unexpected nullptr"); | ||
| 211 | } | 212 | } |
| 212 | - throw std::runtime_error("operation for stream attempted on object of type dictionary"); | 213 | + throw std::runtime_error("operation for stream attempted on non-stream object"); |
| 213 | return nullptr; // unreachable | 214 | return nullptr; // unreachable |
| 214 | } | 215 | } |
| 215 | bool filterable( | 216 | bool filterable( |
| @@ -226,6 +227,26 @@ namespace qpdf | @@ -226,6 +227,26 @@ namespace qpdf | ||
| 226 | filter_factories; | 227 | filter_factories; |
| 227 | }; | 228 | }; |
| 228 | 229 | ||
| 230 | + template <typename T> | ||
| 231 | + T* | ||
| 232 | + BaseHandle::as() const | ||
| 233 | + { | ||
| 234 | + if (!obj) { | ||
| 235 | + return nullptr; | ||
| 236 | + } | ||
| 237 | + if (std::holds_alternative<T>(obj->value)) { | ||
| 238 | + return &std::get<T>(obj->value); | ||
| 239 | + } | ||
| 240 | + if (std::holds_alternative<QPDF_Unresolved>(obj->value)) { | ||
| 241 | + return BaseHandle(QPDF::Resolver::resolved(obj->qpdf, obj->og)).as<T>(); | ||
| 242 | + } | ||
| 243 | + if (std::holds_alternative<QPDF_Reference>(obj->value)) { | ||
| 244 | + // see comment in QPDF_Reference. | ||
| 245 | + return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>(); | ||
| 246 | + } | ||
| 247 | + return nullptr; | ||
| 248 | + } | ||
| 249 | + | ||
| 229 | inline qpdf_object_type_e | 250 | inline qpdf_object_type_e |
| 230 | BaseHandle::type_code() const | 251 | BaseHandle::type_code() const |
| 231 | { | 252 | { |
libqpdf/qpdf/QPDFObject_private.hh
| @@ -172,6 +172,7 @@ class QPDF_Reference | @@ -172,6 +172,7 @@ class QPDF_Reference | ||
| 172 | // objects that are an indirect reference we will need to support multiple levels of | 172 | // objects that are an indirect reference we will need to support multiple levels of |
| 173 | // indirection, including the possibility of circular references. | 173 | // indirection, including the possibility of circular references. |
| 174 | friend class QPDFObject; | 174 | friend class QPDFObject; |
| 175 | + friend class qpdf::BaseHandle; | ||
| 175 | 176 | ||
| 176 | QPDF_Reference(std::shared_ptr<QPDFObject> obj) : | 177 | QPDF_Reference(std::shared_ptr<QPDFObject> obj) : |
| 177 | obj(std::move(obj)) | 178 | obj(std::move(obj)) |
| @@ -366,7 +367,7 @@ class QPDFObject | @@ -366,7 +367,7 @@ class QPDFObject | ||
| 366 | const QPDFObject* | 367 | const QPDFObject* |
| 367 | resolved_object() const | 368 | resolved_object() const |
| 368 | { | 369 | { |
| 369 | - return isUnresolved() ? QPDF::Resolver::resolved(qpdf, og) : this; | 370 | + return isUnresolved() ? QPDF::Resolver::resolved(qpdf, og).get() : this; |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | struct JSON_Descr | 373 | struct JSON_Descr |
| @@ -461,25 +462,10 @@ class QPDFObject | @@ -461,25 +462,10 @@ class QPDFObject | ||
| 461 | return og; | 462 | return og; |
| 462 | } | 463 | } |
| 463 | 464 | ||
| 464 | - template <typename T> | ||
| 465 | - T* | ||
| 466 | - as() | ||
| 467 | - { | ||
| 468 | - if (std::holds_alternative<T>(value)) { | ||
| 469 | - return &std::get<T>(value); | ||
| 470 | - } | ||
| 471 | - if (std::holds_alternative<QPDF_Unresolved>(value)) { | ||
| 472 | - return QPDF::Resolver::resolved(qpdf, og)->as<T>(); | ||
| 473 | - } | ||
| 474 | - if (std::holds_alternative<QPDF_Reference>(value)) { | ||
| 475 | - // see comment in QPDF_Reference. | ||
| 476 | - return std::get<QPDF_Reference>(value).obj->as<T>(); | ||
| 477 | - } | ||
| 478 | - return nullptr; | ||
| 479 | - } | ||
| 480 | - | ||
| 481 | private: | 465 | private: |
| 482 | friend class QPDF_Stream; | 466 | friend class QPDF_Stream; |
| 467 | + friend class qpdf::BaseHandle; | ||
| 468 | + | ||
| 483 | typedef std::variant< | 469 | typedef std::variant< |
| 484 | std::monostate, | 470 | std::monostate, |
| 485 | QPDF_Reserved, | 471 | QPDF_Reserved, |