Commit 9641626cae44ed17ef4af4e72e89276065dd85ed
1 parent
ce5b864c
Refactor resolving of objects
Showing
9 changed files
with
112 additions
and
119 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -792,12 +792,13 @@ class QPDF |
| 792 | 792 | class Resolver |
| 793 | 793 | { |
| 794 | 794 | friend class QPDFObject; |
| 795 | + friend class QPDF_Unresolved; | |
| 795 | 796 | |
| 796 | 797 | private: |
| 797 | - static void | |
| 798 | - resolve(QPDF* qpdf, QPDFObjGen const& og) | |
| 798 | + static QPDFObject* | |
| 799 | + resolved(QPDF* qpdf, QPDFObjGen og) | |
| 799 | 800 | { |
| 800 | - qpdf->resolve(og); | |
| 801 | + return qpdf->resolve(og); | |
| 801 | 802 | } |
| 802 | 803 | }; |
| 803 | 804 | |
| ... | ... | @@ -1056,7 +1057,7 @@ class QPDF |
| 1056 | 1057 | QPDFObjGen exp_og, |
| 1057 | 1058 | QPDFObjGen& og, |
| 1058 | 1059 | bool skip_cache_if_in_xref); |
| 1059 | - void resolve(QPDFObjGen og); | |
| 1060 | + QPDFObject* resolve(QPDFObjGen og); | |
| 1060 | 1061 | void resolveObjectsInStream(int obj_stream_number); |
| 1061 | 1062 | void stopOnError(std::string const& message); |
| 1062 | 1063 | QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -1363,24 +1363,23 @@ class QPDFObjectHandle |
| 1363 | 1363 | void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false); |
| 1364 | 1364 | |
| 1365 | 1365 | private: |
| 1366 | - QPDF_Array* asArray(); | |
| 1367 | - QPDF_Bool* asBool(); | |
| 1368 | - QPDF_Dictionary* asDictionary(); | |
| 1369 | - QPDF_InlineImage* asInlineImage(); | |
| 1370 | - QPDF_Integer* asInteger(); | |
| 1371 | - QPDF_Name* asName(); | |
| 1372 | - QPDF_Null* asNull(); | |
| 1373 | - QPDF_Operator* asOperator(); | |
| 1374 | - QPDF_Real* asReal(); | |
| 1375 | - QPDF_Reserved* asReserved(); | |
| 1376 | - QPDF_Stream* asStream(); | |
| 1366 | + QPDF_Array* asArray() const; | |
| 1367 | + QPDF_Bool* asBool() const; | |
| 1368 | + QPDF_Dictionary* asDictionary() const; | |
| 1369 | + QPDF_InlineImage* asInlineImage() const; | |
| 1370 | + QPDF_Integer* asInteger() const; | |
| 1371 | + QPDF_Name* asName() const; | |
| 1372 | + QPDF_Null* asNull() const; | |
| 1373 | + QPDF_Operator* asOperator() const; | |
| 1374 | + QPDF_Real* asReal() const; | |
| 1375 | + QPDF_Reserved* asReserved() const; | |
| 1376 | + QPDF_Stream* asStream() const; | |
| 1377 | 1377 | QPDF_Stream* asStreamWithAssert(); |
| 1378 | - QPDF_String* asString(); | |
| 1378 | + QPDF_String* asString() const; | |
| 1379 | 1379 | |
| 1380 | 1380 | void typeWarning(char const* expected_type, std::string const& warning); |
| 1381 | 1381 | void objectWarning(std::string const& warning); |
| 1382 | 1382 | void assertType(char const* type_name, bool istype); |
| 1383 | - inline bool dereference(); | |
| 1384 | 1383 | void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); |
| 1385 | 1384 | void disconnect(); |
| 1386 | 1385 | void setParsedOffset(qpdf_offset_t offset); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -1728,11 +1728,11 @@ QPDF::readObjectAtOffset( |
| 1728 | 1728 | return oh; |
| 1729 | 1729 | } |
| 1730 | 1730 | |
| 1731 | -void | |
| 1731 | +QPDFObject* | |
| 1732 | 1732 | QPDF::resolve(QPDFObjGen og) |
| 1733 | 1733 | { |
| 1734 | 1734 | if (!isUnresolved(og)) { |
| 1735 | - return; | |
| 1735 | + return m->obj_cache[og].object.get(); | |
| 1736 | 1736 | } |
| 1737 | 1737 | |
| 1738 | 1738 | if (m->resolving.count(og)) { |
| ... | ... | @@ -1741,7 +1741,7 @@ QPDF::resolve(QPDFObjGen og) |
| 1741 | 1741 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); |
| 1742 | 1742 | warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); |
| 1743 | 1743 | updateCache(og, QPDF_Null::create(), -1, -1); |
| 1744 | - return; | |
| 1744 | + return m->obj_cache[og].object.get(); | |
| 1745 | 1745 | } |
| 1746 | 1746 | ResolveRecorder rr(this, og); |
| 1747 | 1747 | |
| ... | ... | @@ -1782,6 +1782,7 @@ QPDF::resolve(QPDFObjGen og) |
| 1782 | 1782 | |
| 1783 | 1783 | auto result(m->obj_cache[og].object); |
| 1784 | 1784 | result->setDefaultDescription(this, og); |
| 1785 | + return result.get(); | |
| 1785 | 1786 | } |
| 1786 | 1787 | |
| 1787 | 1788 | void | ... | ... |
libqpdf/QPDFObject.cc
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -240,79 +240,79 @@ QPDFObjectHandle::disconnect() |
| 240 | 240 | qpdf_object_type_e |
| 241 | 241 | QPDFObjectHandle::getTypeCode() |
| 242 | 242 | { |
| 243 | - return dereference() ? this->obj->getTypeCode() : ::ot_uninitialized; | |
| 243 | + return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized; | |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | 246 | char const* |
| 247 | 247 | QPDFObjectHandle::getTypeName() |
| 248 | 248 | { |
| 249 | - return dereference() ? this->obj->getTypeName() : "uninitialized"; | |
| 249 | + return obj ? obj->getTypeName() : "uninitialized"; | |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | QPDF_Array* |
| 253 | -QPDFObjectHandle::asArray() | |
| 253 | +QPDFObjectHandle::asArray() const | |
| 254 | 254 | { |
| 255 | - return dereference() ? obj->as<QPDF_Array>() : nullptr; | |
| 255 | + return obj ? obj->as<QPDF_Array>() : nullptr; | |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | 258 | QPDF_Bool* |
| 259 | -QPDFObjectHandle::asBool() | |
| 259 | +QPDFObjectHandle::asBool() const | |
| 260 | 260 | { |
| 261 | - return dereference() ? obj->as<QPDF_Bool>() : nullptr; | |
| 261 | + return obj ? obj->as<QPDF_Bool>() : nullptr; | |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | 264 | QPDF_Dictionary* |
| 265 | -QPDFObjectHandle::asDictionary() | |
| 265 | +QPDFObjectHandle::asDictionary() const | |
| 266 | 266 | { |
| 267 | - return dereference() ? obj->as<QPDF_Dictionary>() : nullptr; | |
| 267 | + return obj ? obj->as<QPDF_Dictionary>() : nullptr; | |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | 270 | QPDF_InlineImage* |
| 271 | -QPDFObjectHandle::asInlineImage() | |
| 271 | +QPDFObjectHandle::asInlineImage() const | |
| 272 | 272 | { |
| 273 | - return dereference() ? obj->as<QPDF_InlineImage>() : nullptr; | |
| 273 | + return obj ? obj->as<QPDF_InlineImage>() : nullptr; | |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | 276 | QPDF_Integer* |
| 277 | -QPDFObjectHandle::asInteger() | |
| 277 | +QPDFObjectHandle::asInteger() const | |
| 278 | 278 | { |
| 279 | - return dereference() ? obj->as<QPDF_Integer>() : nullptr; | |
| 279 | + return obj ? obj->as<QPDF_Integer>() : nullptr; | |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | 282 | QPDF_Name* |
| 283 | -QPDFObjectHandle::asName() | |
| 283 | +QPDFObjectHandle::asName() const | |
| 284 | 284 | { |
| 285 | - return dereference() ? obj->as<QPDF_Name>() : nullptr; | |
| 285 | + return obj ? obj->as<QPDF_Name>() : nullptr; | |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | 288 | QPDF_Null* |
| 289 | -QPDFObjectHandle::asNull() | |
| 289 | +QPDFObjectHandle::asNull() const | |
| 290 | 290 | { |
| 291 | - return dereference() ? obj->as<QPDF_Null>() : nullptr; | |
| 291 | + return obj ? obj->as<QPDF_Null>() : nullptr; | |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | 294 | QPDF_Operator* |
| 295 | -QPDFObjectHandle::asOperator() | |
| 295 | +QPDFObjectHandle::asOperator() const | |
| 296 | 296 | { |
| 297 | - return dereference() ? obj->as<QPDF_Operator>() : nullptr; | |
| 297 | + return obj ? obj->as<QPDF_Operator>() : nullptr; | |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | QPDF_Real* |
| 301 | -QPDFObjectHandle::asReal() | |
| 301 | +QPDFObjectHandle::asReal() const | |
| 302 | 302 | { |
| 303 | - return dereference() ? obj->as<QPDF_Real>() : nullptr; | |
| 303 | + return obj ? obj->as<QPDF_Real>() : nullptr; | |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | 306 | QPDF_Reserved* |
| 307 | -QPDFObjectHandle::asReserved() | |
| 307 | +QPDFObjectHandle::asReserved() const | |
| 308 | 308 | { |
| 309 | - return dereference() ? obj->as<QPDF_Reserved>() : nullptr; | |
| 309 | + return obj ? obj->as<QPDF_Reserved>() : nullptr; | |
| 310 | 310 | } |
| 311 | 311 | |
| 312 | 312 | QPDF_Stream* |
| 313 | -QPDFObjectHandle::asStream() | |
| 313 | +QPDFObjectHandle::asStream() const | |
| 314 | 314 | { |
| 315 | - return dereference() ? obj->as<QPDF_Stream>() : nullptr; | |
| 315 | + return obj ? obj->as<QPDF_Stream>() : nullptr; | |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | 318 | QPDF_Stream* |
| ... | ... | @@ -324,21 +324,21 @@ QPDFObjectHandle::asStreamWithAssert() |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | 326 | QPDF_String* |
| 327 | -QPDFObjectHandle::asString() | |
| 327 | +QPDFObjectHandle::asString() const | |
| 328 | 328 | { |
| 329 | - return dereference() ? obj->as<QPDF_String>() : nullptr; | |
| 329 | + return obj ? obj->as<QPDF_String>() : nullptr; | |
| 330 | 330 | } |
| 331 | 331 | |
| 332 | 332 | bool |
| 333 | 333 | QPDFObjectHandle::isDestroyed() |
| 334 | 334 | { |
| 335 | - return dereference() && (obj->getTypeCode() == ::ot_destroyed); | |
| 335 | + return obj && obj->getResolvedTypeCode() == ::ot_destroyed; | |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | 338 | bool |
| 339 | 339 | QPDFObjectHandle::isBool() |
| 340 | 340 | { |
| 341 | - return dereference() && (obj->getTypeCode() == ::ot_boolean); | |
| 341 | + return obj && obj->getResolvedTypeCode() == ::ot_boolean; | |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | bool |
| ... | ... | @@ -346,25 +346,25 @@ QPDFObjectHandle::isDirectNull() const |
| 346 | 346 | { |
| 347 | 347 | // Don't call dereference() -- this is a const method, and we know |
| 348 | 348 | // objid == 0, so there's nothing to resolve. |
| 349 | - return (isInitialized() && (getObjectID() == 0) && (obj->getTypeCode() == ::ot_null)); | |
| 349 | + return (obj && getObjectID() == 0 && obj->getTypeCode() == ::ot_null); | |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | 352 | bool |
| 353 | 353 | QPDFObjectHandle::isNull() |
| 354 | 354 | { |
| 355 | - return dereference() && (obj->getTypeCode() == ::ot_null); | |
| 355 | + return obj && obj->getResolvedTypeCode() == ::ot_null; | |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | bool |
| 359 | 359 | QPDFObjectHandle::isInteger() |
| 360 | 360 | { |
| 361 | - return dereference() && (obj->getTypeCode() == ::ot_integer); | |
| 361 | + return obj && obj->getResolvedTypeCode() == ::ot_integer; | |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | 364 | bool |
| 365 | 365 | QPDFObjectHandle::isReal() |
| 366 | 366 | { |
| 367 | - return dereference() && (obj->getTypeCode() == ::ot_real); | |
| 367 | + return obj && obj->getResolvedTypeCode() == ::ot_real; | |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | 370 | bool |
| ... | ... | @@ -401,49 +401,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) |
| 401 | 401 | bool |
| 402 | 402 | QPDFObjectHandle::isName() |
| 403 | 403 | { |
| 404 | - return dereference() && (obj->getTypeCode() == ::ot_name); | |
| 404 | + return obj && obj->getResolvedTypeCode() == ::ot_name; | |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | 407 | bool |
| 408 | 408 | QPDFObjectHandle::isString() |
| 409 | 409 | { |
| 410 | - return dereference() && (obj->getTypeCode() == ::ot_string); | |
| 410 | + return obj && obj->getResolvedTypeCode() == ::ot_string; | |
| 411 | 411 | } |
| 412 | 412 | |
| 413 | 413 | bool |
| 414 | 414 | QPDFObjectHandle::isOperator() |
| 415 | 415 | { |
| 416 | - return dereference() && (obj->getTypeCode() == ::ot_operator); | |
| 416 | + return obj && obj->getResolvedTypeCode() == ::ot_operator; | |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | 419 | bool |
| 420 | 420 | QPDFObjectHandle::isInlineImage() |
| 421 | 421 | { |
| 422 | - return dereference() && (obj->getTypeCode() == ::ot_inlineimage); | |
| 422 | + return obj && obj->getResolvedTypeCode() == ::ot_inlineimage; | |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | 425 | bool |
| 426 | 426 | QPDFObjectHandle::isArray() |
| 427 | 427 | { |
| 428 | - return dereference() && (obj->getTypeCode() == ::ot_array); | |
| 428 | + return obj && obj->getResolvedTypeCode() == ::ot_array; | |
| 429 | 429 | } |
| 430 | 430 | |
| 431 | 431 | bool |
| 432 | 432 | QPDFObjectHandle::isDictionary() |
| 433 | 433 | { |
| 434 | - return dereference() && (obj->getTypeCode() == ::ot_dictionary); | |
| 434 | + return obj && obj->getResolvedTypeCode() == ::ot_dictionary; | |
| 435 | 435 | } |
| 436 | 436 | |
| 437 | 437 | bool |
| 438 | 438 | QPDFObjectHandle::isStream() |
| 439 | 439 | { |
| 440 | - return dereference() && (obj->getTypeCode() == ::ot_stream); | |
| 440 | + return obj && obj->getResolvedTypeCode() == ::ot_stream; | |
| 441 | 441 | } |
| 442 | 442 | |
| 443 | 443 | bool |
| 444 | 444 | QPDFObjectHandle::isReserved() |
| 445 | 445 | { |
| 446 | - return dereference() && (obj->getTypeCode() == ::ot_reserved); | |
| 446 | + return obj && obj->getResolvedTypeCode() == ::ot_reserved; | |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | 449 | bool |
| ... | ... | @@ -1586,7 +1586,7 @@ QPDFObjectHandle::unparse() |
| 1586 | 1586 | std::string |
| 1587 | 1587 | QPDFObjectHandle::unparseResolved() |
| 1588 | 1588 | { |
| 1589 | - if (!dereference()) { | |
| 1589 | + if (!obj) { | |
| 1590 | 1590 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1591 | 1591 | } |
| 1592 | 1592 | return obj->unparse(); |
| ... | ... | @@ -1615,7 +1615,7 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) |
| 1615 | 1615 | { |
| 1616 | 1616 | if ((!dereference_indirect) && isIndirect()) { |
| 1617 | 1617 | return JSON::makeString(unparse()); |
| 1618 | - } else if (!dereference()) { | |
| 1618 | + } else if (!obj) { | |
| 1619 | 1619 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1620 | 1620 | } else { |
| 1621 | 1621 | Pl_Buffer p{"json"}; |
| ... | ... | @@ -1631,7 +1631,7 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_ |
| 1631 | 1631 | { |
| 1632 | 1632 | if (!dereference_indirect && isIndirect()) { |
| 1633 | 1633 | p << "\"" << getObjGen().unparse(' ') << " R\""; |
| 1634 | - } else if (!dereference()) { | |
| 1634 | + } else if (!obj) { | |
| 1635 | 1635 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1636 | 1636 | } else { |
| 1637 | 1637 | obj->writeJSON(json_version, p); |
| ... | ... | @@ -1874,11 +1874,7 @@ QPDFObjectHandle::parse( |
| 1874 | 1874 | qpdf_offset_t |
| 1875 | 1875 | QPDFObjectHandle::getParsedOffset() |
| 1876 | 1876 | { |
| 1877 | - if (dereference()) { | |
| 1878 | - return this->obj->getParsedOffset(); | |
| 1879 | - } else { | |
| 1880 | - return -1; | |
| 1881 | - } | |
| 1877 | + return obj ? obj->getParsedOffset() : -1; | |
| 1882 | 1878 | } |
| 1883 | 1879 | |
| 1884 | 1880 | QPDFObjectHandle |
| ... | ... | @@ -2055,9 +2051,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf) |
| 2055 | 2051 | void |
| 2056 | 2052 | QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description) |
| 2057 | 2053 | { |
| 2058 | - // This is called during parsing on newly created direct objects, so we can't call dereference() | |
| 2059 | - // here. | |
| 2060 | - if (isInitialized() && obj.get()) { | |
| 2054 | + if (obj) { | |
| 2061 | 2055 | auto descr = std::make_shared<QPDFValue::Description>(object_description); |
| 2062 | 2056 | obj->setDescription(owning_qpdf, descr); |
| 2063 | 2057 | } |
| ... | ... | @@ -2066,13 +2060,13 @@ QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& obj |
| 2066 | 2060 | bool |
| 2067 | 2061 | QPDFObjectHandle::hasObjectDescription() |
| 2068 | 2062 | { |
| 2069 | - return dereference() && obj.get() && obj->hasDescription(); | |
| 2063 | + return obj && obj->hasDescription(); | |
| 2070 | 2064 | } |
| 2071 | 2065 | |
| 2072 | 2066 | QPDFObjectHandle |
| 2073 | 2067 | QPDFObjectHandle::shallowCopy() |
| 2074 | 2068 | { |
| 2075 | - if (!dereference()) { | |
| 2069 | + if (!obj) { | |
| 2076 | 2070 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); |
| 2077 | 2071 | } |
| 2078 | 2072 | return {obj->copy()}; |
| ... | ... | @@ -2081,7 +2075,7 @@ QPDFObjectHandle::shallowCopy() |
| 2081 | 2075 | QPDFObjectHandle |
| 2082 | 2076 | QPDFObjectHandle::unsafeShallowCopy() |
| 2083 | 2077 | { |
| 2084 | - if (!dereference()) { | |
| 2078 | + if (!obj) { | |
| 2085 | 2079 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); |
| 2086 | 2080 | } |
| 2087 | 2081 | return {obj->copy(true)}; |
| ... | ... | @@ -2172,10 +2166,10 @@ QPDFObjectHandle::typeWarning(char const* expected_type, std::string const& warn |
| 2172 | 2166 | std::string description; |
| 2173 | 2167 | // Type checks above guarantee that the object has been dereferenced. Nevertheless, dereference |
| 2174 | 2168 | // throws exceptions in the test suite |
| 2175 | - if (!dereference()) { | |
| 2169 | + if (!obj) { | |
| 2176 | 2170 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 2177 | 2171 | } |
| 2178 | - this->obj->getDescription(context, description); | |
| 2172 | + obj->getDescription(context, description); | |
| 2179 | 2173 | // Null context handled by warn |
| 2180 | 2174 | warn( |
| 2181 | 2175 | context, |
| ... | ... | @@ -2193,7 +2187,7 @@ QPDFObjectHandle::warnIfPossible(std::string const& warning) |
| 2193 | 2187 | { |
| 2194 | 2188 | QPDF* context = nullptr; |
| 2195 | 2189 | std::string description; |
| 2196 | - if (dereference() && obj->getDescription(context, description)) { | |
| 2190 | + if (obj && obj->getDescription(context, description)) { | |
| 2197 | 2191 | warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning)); |
| 2198 | 2192 | } else { |
| 2199 | 2193 | *QPDFLogger::defaultLogger()->getError() << warning << "\n"; |
| ... | ... | @@ -2205,8 +2199,8 @@ QPDFObjectHandle::objectWarning(std::string const& warning) |
| 2205 | 2199 | { |
| 2206 | 2200 | QPDF* context = nullptr; |
| 2207 | 2201 | std::string description; |
| 2208 | - // Type checks above guarantee that the object has been dereferenced. | |
| 2209 | - this->obj->getDescription(context, description); | |
| 2202 | + // Type checks above guarantee that the object is initialized. | |
| 2203 | + obj->getDescription(context, description); | |
| 2210 | 2204 | // Null context handled by warn |
| 2211 | 2205 | warn(context, QPDFExc(qpdf_e_object, "", description, 0, warning)); |
| 2212 | 2206 | } |
| ... | ... | @@ -2372,16 +2366,6 @@ QPDFObjectHandle::assertPageObject() |
| 2372 | 2366 | } |
| 2373 | 2367 | } |
| 2374 | 2368 | |
| 2375 | -inline bool | |
| 2376 | -QPDFObjectHandle::dereference() | |
| 2377 | -{ | |
| 2378 | - if (!isInitialized()) { | |
| 2379 | - return false; | |
| 2380 | - } | |
| 2381 | - this->obj->resolve(); | |
| 2382 | - return true; | |
| 2383 | -} | |
| 2384 | - | |
| 2385 | 2369 | void |
| 2386 | 2370 | QPDFObjectHandle::warn(QPDF* qpdf, QPDFExc const& e) |
| 2387 | 2371 | { | ... | ... |
libqpdf/QPDF_Array.cc
| ... | ... | @@ -130,8 +130,7 @@ QPDF_Array::unparse() |
| 130 | 130 | for (int j = next; j < key; ++j) { |
| 131 | 131 | result += "null "; |
| 132 | 132 | } |
| 133 | - item.second->resolve(); | |
| 134 | - auto og = item.second->getObjGen(); | |
| 133 | + auto og = item.second->resolved_object()->getObjGen(); | |
| 135 | 134 | result += og.isIndirect() ? og.unparse(' ') + " R " : item.second->unparse() + " "; |
| 136 | 135 | next = ++key; |
| 137 | 136 | } |
| ... | ... | @@ -140,8 +139,7 @@ QPDF_Array::unparse() |
| 140 | 139 | } |
| 141 | 140 | } else { |
| 142 | 141 | for (auto const& item: elements) { |
| 143 | - item->resolve(); | |
| 144 | - auto og = item->getObjGen(); | |
| 142 | + auto og = item->resolved_object()->getObjGen(); | |
| 145 | 143 | result += og.isIndirect() ? og.unparse(' ') + " R " : item->unparse() + " "; |
| 146 | 144 | } |
| 147 | 145 | } | ... | ... |
libqpdf/QPDF_Unresolved.cc
| 1 | 1 | #include <qpdf/QPDF_Unresolved.hh> |
| 2 | 2 | |
| 3 | -#include <stdexcept> | |
| 3 | +#include <qpdf/QPDF.hh> | |
| 4 | +#include <qpdf/QPDFObject_private.hh> | |
| 4 | 5 | |
| 5 | 6 | QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og) : |
| 6 | 7 | QPDFValue(::ot_unresolved, "unresolved", qpdf, og) |
| ... | ... | @@ -16,19 +17,23 @@ QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og) |
| 16 | 17 | std::shared_ptr<QPDFObject> |
| 17 | 18 | QPDF_Unresolved::copy(bool shallow) |
| 18 | 19 | { |
| 19 | - throw std::logic_error("attempted to shallow copy an unresolved QPDFObjectHandle"); | |
| 20 | - return nullptr; | |
| 20 | + return QPDF::Resolver::resolved(qpdf, og)->copy(shallow); | |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | std::string |
| 24 | 24 | QPDF_Unresolved::unparse() |
| 25 | 25 | { |
| 26 | - throw std::logic_error("attempted to unparse an unresolved QPDFObjectHandle"); | |
| 27 | - return ""; | |
| 26 | + return QPDF::Resolver::resolved(qpdf, og)->unparse(); | |
| 28 | 27 | } |
| 29 | 28 | |
| 30 | 29 | void |
| 31 | 30 | QPDF_Unresolved::writeJSON(int json_version, JSON::Writer& p) |
| 32 | 31 | { |
| 33 | - throw std::logic_error("attempted to get JSON from an unresolved QPDFObjectHandle"); | |
| 32 | + QPDF::Resolver::resolved(qpdf, og)->writeJSON(json_version, p); | |
| 33 | +} | |
| 34 | + | |
| 35 | +std::string | |
| 36 | +QPDF_Unresolved::getStringValue() const | |
| 37 | +{ | |
| 38 | + return QPDF::Resolver::resolved(qpdf, og)->getStringValue(); | |
| 34 | 39 | } | ... | ... |
libqpdf/qpdf/QPDFObject_private.hh
| ... | ... | @@ -5,8 +5,8 @@ |
| 5 | 5 | // include/qpdf/QPDFObject.hh. See comments there for an explanation. |
| 6 | 6 | |
| 7 | 7 | #include <qpdf/Constants.h> |
| 8 | -#include <qpdf/DLL.h> | |
| 9 | 8 | #include <qpdf/JSON.hh> |
| 9 | +#include <qpdf/QPDF.hh> | |
| 10 | 10 | #include <qpdf/QPDFValue.hh> |
| 11 | 11 | #include <qpdf/Types.h> |
| 12 | 12 | |
| ... | ... | @@ -43,18 +43,26 @@ class QPDFObject |
| 43 | 43 | { |
| 44 | 44 | return value->getStringValue(); |
| 45 | 45 | } |
| 46 | + // Return a unique type code for the resolved object | |
| 47 | + qpdf_object_type_e | |
| 48 | + getResolvedTypeCode() const | |
| 49 | + { | |
| 50 | + auto tc = value->type_code; | |
| 51 | + return tc == ::ot_unresolved | |
| 52 | + ? QPDF::Resolver::resolved(value->qpdf, value->og)->value->type_code | |
| 53 | + : tc; | |
| 54 | + } | |
| 46 | 55 | // Return a unique type code for the object |
| 47 | 56 | qpdf_object_type_e |
| 48 | - getTypeCode() const | |
| 57 | + getTypeCode() const noexcept | |
| 49 | 58 | { |
| 50 | 59 | return value->type_code; |
| 51 | 60 | } |
| 52 | - | |
| 53 | 61 | // Return a string literal that describes the type, useful for debugging and testing |
| 54 | 62 | char const* |
| 55 | 63 | getTypeName() const |
| 56 | 64 | { |
| 57 | - return value->type_name; | |
| 65 | + return resolved_object()->value->type_name; | |
| 58 | 66 | } |
| 59 | 67 | |
| 60 | 68 | QPDF* |
| ... | ... | @@ -157,20 +165,23 @@ class QPDFObject |
| 157 | 165 | { |
| 158 | 166 | return value->type_code == ::ot_unresolved; |
| 159 | 167 | } |
| 160 | - void | |
| 161 | - resolve() | |
| 168 | + const QPDFObject* | |
| 169 | + resolved_object() const | |
| 162 | 170 | { |
| 163 | - if (isUnresolved()) { | |
| 164 | - doResolve(); | |
| 165 | - } | |
| 171 | + return isUnresolved() ? QPDF::Resolver::resolved(value->qpdf, value->og) : this; | |
| 166 | 172 | } |
| 167 | - void doResolve(); | |
| 168 | 173 | |
| 169 | 174 | template <typename T> |
| 170 | 175 | T* |
| 171 | - as() | |
| 172 | - { | |
| 173 | - return dynamic_cast<T*>(value.get()); | |
| 176 | + as() const | |
| 177 | + { | |
| 178 | + if (auto result = dynamic_cast<T*>(value.get())) { | |
| 179 | + return result; | |
| 180 | + } else { | |
| 181 | + return isUnresolved() | |
| 182 | + ? dynamic_cast<T*>(QPDF::Resolver::resolved(value->qpdf, value->og)->value.get()) | |
| 183 | + : nullptr; | |
| 184 | + } | |
| 174 | 185 | } |
| 175 | 186 | |
| 176 | 187 | private: | ... | ... |
libqpdf/qpdf/QPDF_Unresolved.hh
| ... | ... | @@ -11,6 +11,7 @@ class QPDF_Unresolved: public QPDFValue |
| 11 | 11 | std::shared_ptr<QPDFObject> copy(bool shallow = false) override; |
| 12 | 12 | std::string unparse() override; |
| 13 | 13 | void writeJSON(int json_version, JSON::Writer& p) override; |
| 14 | + std::string getStringValue() const override; | |
| 14 | 15 | |
| 15 | 16 | private: |
| 16 | 17 | QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og); | ... | ... |