Commit decc7d3c12ab8ce4a6c77d48cfc57d721913b887

Authored by m-holger
1 parent 587177b1

Refactor `QPDFObjectHandle` and `BaseHandle`: streamline type handling, simplify…

… warnings, and centralize utility methods.
include/qpdf/ObjectHandle.hh
... ... @@ -22,7 +22,10 @@
22 22  
23 23 #include <qpdf/Constants.h>
24 24 #include <qpdf/DLL.h>
  25 +#include <qpdf/Types.h>
  26 +
25 27 #include <qpdf/JSON.hh>
  28 +#include <qpdf/QPDFExc.hh>
26 29 #include <qpdf/QPDFObjGen.hh>
27 30 #include <qpdf/Types.h>
28 31  
... ... @@ -71,6 +74,9 @@ namespace qpdf
71 74 inline qpdf_object_type_e type_code() const;
72 75 std::string unparse() const;
73 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 81 protected:
76 82 BaseHandle() = default;
... ... @@ -87,6 +93,11 @@ namespace qpdf
87 93 template <typename T>
88 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 101 std::shared_ptr<QPDFObject> obj;
91 102 };
92 103  
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -1357,7 +1357,6 @@ class QPDFObjectHandle: public qpdf::BaseHandle
1357 1357 QPDF* context);
1358 1358 std::vector<QPDFObjectHandle>
1359 1359 arrayOrStreamToStreamArray(std::string const& description, std::string& all_description);
1360   - static void warn(QPDF*, QPDFExc const&);
1361 1360 void checkOwnership(QPDFObjectHandle const&) const;
1362 1361 };
1363 1362  
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -611,11 +611,11 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const&amp; rhs) const
611 611 qpdf_object_type_e
612 612 QPDFObjectHandle::getTypeCode() const
613 613 {
614   - return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized;
  614 + return type_code();
615 615 }
616 616  
617 617 char const*
618   -QPDFObjectHandle::getTypeName() const
  618 +BaseHandle::type_name() const
619 619 {
620 620 static constexpr std::array<char const*, 16> tn{
621 621 "uninitialized",
... ... @@ -634,7 +634,13 @@ QPDFObjectHandle::getTypeName() const
634 634 "unresolved",
635 635 "destroyed",
636 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 646 bool
... ... @@ -1242,27 +1248,23 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
1242 1248 result.emplace_back(item);
1243 1249 } else {
1244 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 1259 } else if (isStream()) {
1256 1260 result.emplace_back(*this);
1257   - } else if (!isNull()) {
  1261 + } else if (!null()) {
1258 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 1270 bool first = true;
... ... @@ -1824,6 +1826,12 @@ QPDFObjectHandle::newReserved(QPDF* qpdf)
1824 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 1835 void
1828 1836 QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description)
1829 1837 {
... ... @@ -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 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 1967 if (!obj) {
1945 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 1973 void
1961 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 1979 void
1973 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 1985 void
... ... @@ -2130,15 +2132,30 @@ QPDFObjectHandle::assertPageObject() const
2130 2132 }
2131 2133  
2132 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 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 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 437 qpdf_offset_t
445 438 getParsedOffset()
446 439 {
... ...