Commit f78b99939c7d56b8c92c1f0e1bf4507363e351c7
1 parent
586865f9
Move QPDFObject::disconnect to Basehandle
Showing
6 changed files
with
49 additions
and
61 deletions
include/qpdf/ObjectHandle.hh
| ... | ... | @@ -47,6 +47,8 @@ namespace qpdf |
| 47 | 47 | // QPDFObjGen and bool. |
| 48 | 48 | class BaseHandle |
| 49 | 49 | { |
| 50 | + friend class QPDF; | |
| 51 | + | |
| 50 | 52 | public: |
| 51 | 53 | explicit inline operator bool() const; |
| 52 | 54 | inline operator QPDFObjectHandle() const; |
| ... | ... | @@ -55,6 +57,9 @@ namespace qpdf |
| 55 | 57 | // The rest of the header file is for qpdf internal use only. |
| 56 | 58 | |
| 57 | 59 | std::shared_ptr<QPDFObject> copy(bool shallow = false) const; |
| 60 | + // Recursively remove association with any QPDF object. This method may only be called | |
| 61 | + // during final destruction. | |
| 62 | + void disconnect(bool only_direct = true); | |
| 58 | 63 | inline QPDFObjGen id_gen() const; |
| 59 | 64 | inline bool indirect() const; |
| 60 | 65 | inline bool null() const; | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -1242,19 +1242,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle |
| 1242 | 1242 | QPDF_DLL |
| 1243 | 1243 | void warnIfPossible(std::string const& warning) const; |
| 1244 | 1244 | |
| 1245 | - // Provide access to specific classes for recursive disconnected(). | |
| 1246 | - class DisconnectAccess | |
| 1247 | - { | |
| 1248 | - friend class QPDFObject; | |
| 1249 | - | |
| 1250 | - private: | |
| 1251 | - static void | |
| 1252 | - disconnect(QPDFObjectHandle o) | |
| 1253 | - { | |
| 1254 | - o.disconnect(); | |
| 1255 | - } | |
| 1256 | - }; | |
| 1257 | - | |
| 1258 | 1245 | // Convenience routine: Throws if the assumption is violated. Your code will be better if you |
| 1259 | 1246 | // call one of the isType methods and handle the case of the type being wrong, but these can be |
| 1260 | 1247 | // convenient if you have already verified the type. |
| ... | ... | @@ -1354,7 +1341,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle |
| 1354 | 1341 | void objectWarning(std::string const& warning) const; |
| 1355 | 1342 | void assertType(char const* type_name, bool istype) const; |
| 1356 | 1343 | void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); |
| 1357 | - void disconnect(); | |
| 1358 | 1344 | void setParsedOffset(qpdf_offset_t offset); |
| 1359 | 1345 | void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); |
| 1360 | 1346 | static void parseContentStream_data( | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -212,6 +212,25 @@ QPDF::QPDF() : |
| 212 | 212 | m->unique_id = unique_id.fetch_add(1ULL); |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | +// Provide access to disconnect(). Disconnect will in due course be merged into the current ObjCache | |
| 216 | +// (future Objects::Entry) to centralize all QPDF access to QPDFObject. | |
| 217 | +class Disconnect: BaseHandle | |
| 218 | +{ | |
| 219 | + public: | |
| 220 | + Disconnect(std::shared_ptr<QPDFObject> const& obj) : | |
| 221 | + BaseHandle(obj) | |
| 222 | + { | |
| 223 | + } | |
| 224 | + void | |
| 225 | + disconnect() | |
| 226 | + { | |
| 227 | + BaseHandle::disconnect(false); | |
| 228 | + if (raw_type_code() != ::ot_null) { | |
| 229 | + obj->value = QPDF_Destroyed(); | |
| 230 | + } | |
| 231 | + } | |
| 232 | +}; | |
| 233 | + | |
| 215 | 234 | QPDF::~QPDF() |
| 216 | 235 | { |
| 217 | 236 | // If two objects are mutually referential (through each object having an array or dictionary |
| ... | ... | @@ -228,10 +247,7 @@ QPDF::~QPDF() |
| 228 | 247 | // the xref table anyway just to prevent any possibility of resolve() succeeding. |
| 229 | 248 | m->xref_table.clear(); |
| 230 | 249 | for (auto const& iter: m->obj_cache) { |
| 231 | - iter.second.object->disconnect(); | |
| 232 | - if (iter.second.object->getTypeCode() != ::ot_null) { | |
| 233 | - iter.second.object->destroy(); | |
| 234 | - } | |
| 250 | + Disconnect(iter.second.object).disconnect(); | |
| 235 | 251 | } |
| 236 | 252 | } |
| 237 | 253 | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -580,48 +580,49 @@ BaseHandle::write_json(int json_version, JSON::Writer& p) const |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | 582 | void |
| 583 | -QPDFObject::disconnect() | |
| 583 | +BaseHandle::disconnect(bool only_direct) | |
| 584 | 584 | { |
| 585 | - // Disconnect an object from its owning QPDF. This is called by QPDF's destructor. | |
| 585 | + // QPDF::~QPDF() calls disconnect for indirect objects, so we don't do that here. | |
| 586 | + if (only_direct && indirect()) { | |
| 587 | + return; | |
| 588 | + } | |
| 586 | 589 | |
| 587 | - switch (getTypeCode()) { | |
| 590 | + switch (raw_type_code()) { | |
| 588 | 591 | case ::ot_array: |
| 589 | 592 | { |
| 590 | - auto& a = std::get<QPDF_Array>(value); | |
| 593 | + auto& a = std::get<QPDF_Array>(obj->value); | |
| 591 | 594 | if (a.sp) { |
| 592 | 595 | for (auto& item: a.sp->elements) { |
| 593 | - auto& obj = item.second; | |
| 594 | - if (!obj.indirect()) { | |
| 595 | - obj.getObj()->disconnect(); | |
| 596 | - } | |
| 596 | + item.second.disconnect(); | |
| 597 | 597 | } |
| 598 | 598 | } else { |
| 599 | - for (auto& obj: a.elements) { | |
| 600 | - if (!obj.indirect()) { | |
| 601 | - obj.getObj()->disconnect(); | |
| 602 | - } | |
| 599 | + for (auto& oh: a.elements) { | |
| 600 | + oh.disconnect(); | |
| 603 | 601 | } |
| 604 | 602 | } |
| 605 | 603 | } |
| 606 | 604 | break; |
| 607 | 605 | case ::ot_dictionary: |
| 608 | - for (auto& iter: std::get<QPDF_Dictionary>(value).items) { | |
| 609 | - QPDFObjectHandle::DisconnectAccess::disconnect(iter.second); | |
| 606 | + for (auto& iter: std::get<QPDF_Dictionary>(obj->value).items) { | |
| 607 | + iter.second.disconnect(); | |
| 610 | 608 | } |
| 611 | 609 | break; |
| 612 | 610 | case ::ot_stream: |
| 613 | 611 | { |
| 614 | - auto& s = std::get<QPDF_Stream>(value); | |
| 612 | + auto& s = std::get<QPDF_Stream>(obj->value); | |
| 615 | 613 | s.m->stream_provider = nullptr; |
| 616 | - QPDFObjectHandle::DisconnectAccess::disconnect(s.m->stream_dict); | |
| 614 | + s.m->stream_dict.disconnect(); | |
| 617 | 615 | } |
| 618 | 616 | break; |
| 617 | + case ::ot_uninitialized: | |
| 618 | + return; | |
| 619 | 619 | default: |
| 620 | 620 | break; |
| 621 | 621 | } |
| 622 | - qpdf = nullptr; | |
| 623 | - og = QPDFObjGen(); | |
| 622 | + obj->qpdf = nullptr; | |
| 623 | + obj->og = QPDFObjGen(); | |
| 624 | 624 | } |
| 625 | + | |
| 625 | 626 | std::string |
| 626 | 627 | QPDFObject::getStringValue() const |
| 627 | 628 | { |
| ... | ... | @@ -649,16 +650,6 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const |
| 649 | 650 | { |
| 650 | 651 | return this->obj == rhs.obj; |
| 651 | 652 | } |
| 652 | -void | |
| 653 | -QPDFObjectHandle::disconnect() | |
| 654 | -{ | |
| 655 | - // Recursively remove association with any QPDF object. This method may only be called during | |
| 656 | - // final destruction. QPDF::~QPDF() calls it for indirect objects using the object pointer | |
| 657 | - // itself, so we don't do that here. Other objects call it through this method. | |
| 658 | - if (obj && !isIndirect()) { | |
| 659 | - this->obj->disconnect(); | |
| 660 | - } | |
| 661 | -} | |
| 662 | 653 | |
| 663 | 654 | qpdf_object_type_e |
| 664 | 655 | QPDFObjectHandle::getTypeCode() const | ... | ... |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| ... | ... | @@ -358,7 +358,7 @@ namespace qpdf |
| 358 | 358 | inline bool |
| 359 | 359 | BaseHandle::null() const |
| 360 | 360 | { |
| 361 | - return !obj || obj->getResolvedTypeCode() == ::ot_null; | |
| 361 | + return !obj || type_code() == ::ot_null; | |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | 364 | inline QPDF* |
| ... | ... | @@ -383,7 +383,7 @@ namespace qpdf |
| 383 | 383 | return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode(); |
| 384 | 384 | } |
| 385 | 385 | if (raw_type_code() == ::ot_reference) { |
| 386 | - return std::get<QPDF_Reference>(obj->value).obj->getResolvedTypeCode(); | |
| 386 | + return std::get<QPDF_Reference>(obj->value).obj->getTypeCode(); | |
| 387 | 387 | } |
| 388 | 388 | return raw_type_code(); |
| 389 | 389 | } | ... | ... |
libqpdf/qpdf/QPDFObject_private.hh
| ... | ... | @@ -18,6 +18,7 @@ |
| 18 | 18 | #include <variant> |
| 19 | 19 | #include <vector> |
| 20 | 20 | |
| 21 | +class Disconnect; | |
| 21 | 22 | class QPDFObject; |
| 22 | 23 | class QPDFObjectHandle; |
| 23 | 24 | |
| ... | ... | @@ -297,7 +298,6 @@ class QPDFObject |
| 297 | 298 | qpdf, og, std::forward<T>(T(std::forward<Args>(args)...))); |
| 298 | 299 | } |
| 299 | 300 | |
| 300 | - void disconnect(); | |
| 301 | 301 | std::string getStringValue() const; |
| 302 | 302 | |
| 303 | 303 | // Return a unique type code for the resolved object |
| ... | ... | @@ -308,7 +308,7 @@ class QPDFObject |
| 308 | 308 | return QPDF::Resolver::resolved(qpdf, og)->getTypeCode(); |
| 309 | 309 | } |
| 310 | 310 | if (getTypeCode() == ::ot_reference) { |
| 311 | - return std::get<QPDF_Reference>(value).obj->getResolvedTypeCode(); | |
| 311 | + return std::get<QPDF_Reference>(value).obj->getTypeCode(); | |
| 312 | 312 | } |
| 313 | 313 | return getTypeCode(); |
| 314 | 314 | } |
| ... | ... | @@ -354,23 +354,12 @@ class QPDFObject |
| 354 | 354 | qpdf = a_qpdf; |
| 355 | 355 | og = a_og; |
| 356 | 356 | } |
| 357 | - // Mark an object as destroyed. Used by QPDF's destructor for its indirect objects. | |
| 358 | - void | |
| 359 | - destroy() | |
| 360 | - { | |
| 361 | - value = QPDF_Destroyed(); | |
| 362 | - } | |
| 363 | 357 | |
| 364 | 358 | bool |
| 365 | 359 | isUnresolved() const |
| 366 | 360 | { |
| 367 | 361 | return getTypeCode() == ::ot_unresolved; |
| 368 | 362 | } |
| 369 | - const QPDFObject* | |
| 370 | - resolved_object() const | |
| 371 | - { | |
| 372 | - return isUnresolved() ? QPDF::Resolver::resolved(qpdf, og).get() : this; | |
| 373 | - } | |
| 374 | 363 | |
| 375 | 364 | struct JSON_Descr |
| 376 | 365 | { |
| ... | ... | @@ -467,6 +456,7 @@ class QPDFObject |
| 467 | 456 | private: |
| 468 | 457 | friend class QPDF_Stream; |
| 469 | 458 | friend class qpdf::BaseHandle; |
| 459 | + friend class Disconnect; | |
| 470 | 460 | |
| 471 | 461 | typedef std::variant< |
| 472 | 462 | std::monostate, | ... | ... |