Commit decc7d3c12ab8ce4a6c77d48cfc57d721913b887
1 parent
587177b1
Refactor `QPDFObjectHandle` and `BaseHandle`: streamline type handling, simplify…
… warnings, and centralize utility methods.
Showing
4 changed files
with
83 additions
and
63 deletions
include/qpdf/ObjectHandle.hh
| @@ -22,7 +22,10 @@ | @@ -22,7 +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/Types.h> | ||
| 26 | + | ||
| 25 | #include <qpdf/JSON.hh> | 27 | #include <qpdf/JSON.hh> |
| 28 | +#include <qpdf/QPDFExc.hh> | ||
| 26 | #include <qpdf/QPDFObjGen.hh> | 29 | #include <qpdf/QPDFObjGen.hh> |
| 27 | #include <qpdf/Types.h> | 30 | #include <qpdf/Types.h> |
| 28 | 31 | ||
| @@ -71,6 +74,9 @@ namespace qpdf | @@ -71,6 +74,9 @@ namespace qpdf | ||
| 71 | inline qpdf_object_type_e type_code() const; | 74 | inline qpdf_object_type_e type_code() const; |
| 72 | std::string unparse() const; | 75 | std::string unparse() const; |
| 73 | void write_json(int json_version, JSON::Writer& p) const; | 76 | void write_json(int json_version, JSON::Writer& p) const; |
| 77 | + static void warn(QPDF*, QPDFExc&&); | ||
| 78 | + void warn(QPDFExc&&) const; | ||
| 79 | + void warn(std::string const& warning) const; | ||
| 74 | 80 | ||
| 75 | protected: | 81 | protected: |
| 76 | BaseHandle() = default; | 82 | BaseHandle() = default; |
| @@ -87,6 +93,11 @@ namespace qpdf | @@ -87,6 +93,11 @@ namespace qpdf | ||
| 87 | template <typename T> | 93 | template <typename T> |
| 88 | T* as() const; | 94 | T* as() const; |
| 89 | 95 | ||
| 96 | + std::string description() const; | ||
| 97 | + std::runtime_error type_error(char const* expected_type) const; | ||
| 98 | + QPDFExc type_error(char const* expected_type, std::string const& message) const; | ||
| 99 | + char const* type_name() const; | ||
| 100 | + | ||
| 90 | std::shared_ptr<QPDFObject> obj; | 101 | std::shared_ptr<QPDFObject> obj; |
| 91 | }; | 102 | }; |
| 92 | 103 |
include/qpdf/QPDFObjectHandle.hh
| @@ -1357,7 +1357,6 @@ class QPDFObjectHandle: public qpdf::BaseHandle | @@ -1357,7 +1357,6 @@ class QPDFObjectHandle: public qpdf::BaseHandle | ||
| 1357 | QPDF* context); | 1357 | QPDF* context); |
| 1358 | std::vector<QPDFObjectHandle> | 1358 | std::vector<QPDFObjectHandle> |
| 1359 | arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); | 1359 | arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); |
| 1360 | - static void warn(QPDF*, QPDFExc const&); | ||
| 1361 | void checkOwnership(QPDFObjectHandle const&) const; | 1360 | void checkOwnership(QPDFObjectHandle const&) const; |
| 1362 | }; | 1361 | }; |
| 1363 | 1362 |
libqpdf/QPDFObjectHandle.cc
| @@ -611,11 +611,11 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | @@ -611,11 +611,11 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | ||
| 611 | qpdf_object_type_e | 611 | qpdf_object_type_e |
| 612 | QPDFObjectHandle::getTypeCode() const | 612 | QPDFObjectHandle::getTypeCode() const |
| 613 | { | 613 | { |
| 614 | - return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized; | 614 | + return type_code(); |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | char const* | 617 | char const* |
| 618 | -QPDFObjectHandle::getTypeName() const | 618 | +BaseHandle::type_name() const |
| 619 | { | 619 | { |
| 620 | static constexpr std::array<char const*, 16> tn{ | 620 | static constexpr std::array<char const*, 16> tn{ |
| 621 | "uninitialized", | 621 | "uninitialized", |
| @@ -634,7 +634,13 @@ QPDFObjectHandle::getTypeName() const | @@ -634,7 +634,13 @@ QPDFObjectHandle::getTypeName() const | ||
| 634 | "unresolved", | 634 | "unresolved", |
| 635 | "destroyed", | 635 | "destroyed", |
| 636 | "reference"}; | 636 | "reference"}; |
| 637 | - return obj ? tn[getTypeCode()] : "uninitialized"; | 637 | + return tn[type_code()]; |
| 638 | +} | ||
| 639 | + | ||
| 640 | +char const* | ||
| 641 | +QPDFObjectHandle::getTypeName() const | ||
| 642 | +{ | ||
| 643 | + return type_name(); | ||
| 638 | } | 644 | } |
| 639 | 645 | ||
| 640 | bool | 646 | bool |
| @@ -1242,27 +1248,23 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | @@ -1242,27 +1248,23 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | ||
| 1242 | result.emplace_back(item); | 1248 | result.emplace_back(item); |
| 1243 | } else { | 1249 | } else { |
| 1244 | QTC::TC("qpdf", "QPDFObjectHandle non-stream in stream array"); | 1250 | QTC::TC("qpdf", "QPDFObjectHandle non-stream in stream array"); |
| 1245 | - warn( | ||
| 1246 | - item.getOwningQPDF(), | ||
| 1247 | - QPDFExc( | ||
| 1248 | - qpdf_e_damaged_pdf, | ||
| 1249 | - "", | ||
| 1250 | - description + ": item index " + std::to_string(i) + " (from 0)", | ||
| 1251 | - 0, | ||
| 1252 | - "ignoring non-stream in an array of streams")); | 1251 | + item.warn( |
| 1252 | + {qpdf_e_damaged_pdf, | ||
| 1253 | + "", | ||
| 1254 | + description + ": item index " + std::to_string(i) + " (from 0)", | ||
| 1255 | + 0, | ||
| 1256 | + "ignoring non-stream in an array of streams"}); | ||
| 1253 | } | 1257 | } |
| 1254 | } | 1258 | } |
| 1255 | } else if (isStream()) { | 1259 | } else if (isStream()) { |
| 1256 | result.emplace_back(*this); | 1260 | result.emplace_back(*this); |
| 1257 | - } else if (!isNull()) { | 1261 | + } else if (!null()) { |
| 1258 | warn( | 1262 | warn( |
| 1259 | - getOwningQPDF(), | ||
| 1260 | - QPDFExc( | ||
| 1261 | - qpdf_e_damaged_pdf, | ||
| 1262 | - "", | ||
| 1263 | - description, | ||
| 1264 | - 0, | ||
| 1265 | - " object is supposed to be a stream or an array of streams but is neither")); | 1263 | + {qpdf_e_damaged_pdf, |
| 1264 | + "", | ||
| 1265 | + description, | ||
| 1266 | + 0, | ||
| 1267 | + " object is supposed to be a stream or an array of streams but is neither"}); | ||
| 1266 | } | 1268 | } |
| 1267 | 1269 | ||
| 1268 | bool first = true; | 1270 | bool first = true; |
| @@ -1824,6 +1826,12 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) | @@ -1824,6 +1826,12 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) | ||
| 1824 | return qpdf->newReserved(); | 1826 | return qpdf->newReserved(); |
| 1825 | } | 1827 | } |
| 1826 | 1828 | ||
| 1829 | +std::string | ||
| 1830 | +BaseHandle::description() const | ||
| 1831 | +{ | ||
| 1832 | + return obj ? obj->getDescription() : ""s; | ||
| 1833 | +} | ||
| 1834 | + | ||
| 1827 | void | 1835 | void |
| 1828 | QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description) | 1836 | QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description) |
| 1829 | { | 1837 | { |
| @@ -1934,50 +1942,44 @@ QPDFObjectHandle::assertInitialized() const | @@ -1934,50 +1942,44 @@ QPDFObjectHandle::assertInitialized() const | ||
| 1934 | } | 1942 | } |
| 1935 | } | 1943 | } |
| 1936 | 1944 | ||
| 1945 | +std::runtime_error | ||
| 1946 | +BaseHandle::type_error(char const* expected_type) const | ||
| 1947 | +{ | ||
| 1948 | + return std::runtime_error( | ||
| 1949 | + "operation for "s + expected_type + " attempted on object of type " + type_name()); | ||
| 1950 | +} | ||
| 1951 | + | ||
| 1952 | +QPDFExc | ||
| 1953 | +BaseHandle::type_error(char const* expected_type, std::string const& message) const | ||
| 1954 | +{ | ||
| 1955 | + return { | ||
| 1956 | + qpdf_e_object, | ||
| 1957 | + "", | ||
| 1958 | + description(), | ||
| 1959 | + 0, | ||
| 1960 | + "operation for "s + expected_type + " attempted on object of type " + type_name() + ": " + | ||
| 1961 | + message}; | ||
| 1962 | +} | ||
| 1963 | + | ||
| 1937 | void | 1964 | void |
| 1938 | -QPDFObjectHandle::typeWarning(char const* expected_type, std::string const& warning) const | 1965 | +QPDFObjectHandle::typeWarning(char const* expected_type, std::string const& message) const |
| 1939 | { | 1966 | { |
| 1940 | - QPDF* context = nullptr; | ||
| 1941 | - std::string description; | ||
| 1942 | - // Type checks above guarantee that the object has been dereferenced. Nevertheless, dereference | ||
| 1943 | - // throws exceptions in the test suite | ||
| 1944 | if (!obj) { | 1967 | if (!obj) { |
| 1945 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); | 1968 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1946 | } | 1969 | } |
| 1947 | - obj->getDescription(context, description); | ||
| 1948 | - // Null context handled by warn | ||
| 1949 | - warn( | ||
| 1950 | - context, | ||
| 1951 | - QPDFExc( | ||
| 1952 | - qpdf_e_object, | ||
| 1953 | - "", | ||
| 1954 | - description, | ||
| 1955 | - 0, | ||
| 1956 | - std::string("operation for ") + expected_type + " attempted on object of type " + | ||
| 1957 | - QPDFObjectHandle(*this).getTypeName() + ": " + warning)); | 1970 | + warn(type_error(expected_type, message)); |
| 1958 | } | 1971 | } |
| 1959 | 1972 | ||
| 1960 | void | 1973 | void |
| 1961 | QPDFObjectHandle::warnIfPossible(std::string const& warning) const | 1974 | QPDFObjectHandle::warnIfPossible(std::string const& warning) const |
| 1962 | { | 1975 | { |
| 1963 | - QPDF* context = nullptr; | ||
| 1964 | - std::string description; | ||
| 1965 | - if (obj && obj->getDescription(context, description)) { | ||
| 1966 | - warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning)); | ||
| 1967 | - } else { | ||
| 1968 | - *QPDFLogger::defaultLogger()->getError() << warning << "\n"; | ||
| 1969 | - } | 1976 | + warn(warning); |
| 1970 | } | 1977 | } |
| 1971 | 1978 | ||
| 1972 | void | 1979 | void |
| 1973 | QPDFObjectHandle::objectWarning(std::string const& warning) const | 1980 | QPDFObjectHandle::objectWarning(std::string const& warning) const |
| 1974 | { | 1981 | { |
| 1975 | - QPDF* context = nullptr; | ||
| 1976 | - std::string description; | ||
| 1977 | - // Type checks above guarantee that the object is initialized. | ||
| 1978 | - obj->getDescription(context, description); | ||
| 1979 | - // Null context handled by warn | ||
| 1980 | - warn(context, QPDFExc(qpdf_e_object, "", description, 0, warning)); | 1982 | + warn({qpdf_e_object, "", description(), 0, warning}); |
| 1981 | } | 1983 | } |
| 1982 | 1984 | ||
| 1983 | void | 1985 | void |
| @@ -2130,15 +2132,30 @@ QPDFObjectHandle::assertPageObject() const | @@ -2130,15 +2132,30 @@ QPDFObjectHandle::assertPageObject() const | ||
| 2130 | } | 2132 | } |
| 2131 | 2133 | ||
| 2132 | void | 2134 | void |
| 2133 | -QPDFObjectHandle::warn(QPDF* qpdf, QPDFExc const& e) | 2135 | +BaseHandle::warn(QPDF* qpdf, QPDFExc&& e) |
| 2134 | { | 2136 | { |
| 2135 | - // If parsing on behalf of a QPDF object and want to give a warning, we can warn through the | ||
| 2136 | - // object. If parsing for some other reason, such as an explicit creation of an object from a | ||
| 2137 | - // string, then just throw the exception. | ||
| 2138 | - if (qpdf) { | ||
| 2139 | - qpdf->warn(e); | 2137 | + if (!qpdf) { |
| 2138 | + throw std::move(e); | ||
| 2139 | + } | ||
| 2140 | + qpdf->warn(std::move(e)); | ||
| 2141 | +} | ||
| 2142 | + | ||
| 2143 | +void | ||
| 2144 | +BaseHandle::warn(QPDFExc&& e) const | ||
| 2145 | +{ | ||
| 2146 | + if (!qpdf()) { | ||
| 2147 | + throw std::move(e); | ||
| 2148 | + } | ||
| 2149 | + qpdf()->warn(std::move(e)); | ||
| 2150 | +} | ||
| 2151 | + | ||
| 2152 | +void | ||
| 2153 | +BaseHandle::warn(std::string const& warning) const | ||
| 2154 | +{ | ||
| 2155 | + if (qpdf()) { | ||
| 2156 | + warn({qpdf_e_damaged_pdf, "", description(), 0, warning}); | ||
| 2140 | } else { | 2157 | } else { |
| 2141 | - throw e; | 2158 | + *QPDFLogger::defaultLogger()->getError() << warning << "\n"; |
| 2142 | } | 2159 | } |
| 2143 | } | 2160 | } |
| 2144 | 2161 |
libqpdf/qpdf/QPDFObject_private.hh
| @@ -434,13 +434,6 @@ class QPDFObject | @@ -434,13 +434,6 @@ class QPDFObject | ||
| 434 | parsed_offset = offset; | 434 | parsed_offset = offset; |
| 435 | } | 435 | } |
| 436 | } | 436 | } |
| 437 | - bool | ||
| 438 | - getDescription(QPDF*& a_qpdf, std::string& description) | ||
| 439 | - { | ||
| 440 | - a_qpdf = qpdf; | ||
| 441 | - description = getDescription(); | ||
| 442 | - return qpdf != nullptr; | ||
| 443 | - } | ||
| 444 | qpdf_offset_t | 437 | qpdf_offset_t |
| 445 | getParsedOffset() | 438 | getParsedOffset() |
| 446 | { | 439 | { |