Commit f78b99939c7d56b8c92c1f0e1bf4507363e351c7

Authored by m-holger
1 parent 586865f9

Move QPDFObject::disconnect to Basehandle

include/qpdf/ObjectHandle.hh
@@ -47,6 +47,8 @@ namespace qpdf @@ -47,6 +47,8 @@ namespace qpdf
47 // QPDFObjGen and bool. 47 // QPDFObjGen and bool.
48 class BaseHandle 48 class BaseHandle
49 { 49 {
  50 + friend class QPDF;
  51 +
50 public: 52 public:
51 explicit inline operator bool() const; 53 explicit inline operator bool() const;
52 inline operator QPDFObjectHandle() const; 54 inline operator QPDFObjectHandle() const;
@@ -55,6 +57,9 @@ namespace qpdf @@ -55,6 +57,9 @@ namespace qpdf
55 // The rest of the header file is for qpdf internal use only. 57 // The rest of the header file is for qpdf internal use only.
56 58
57 std::shared_ptr<QPDFObject> copy(bool shallow = false) const; 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 inline QPDFObjGen id_gen() const; 63 inline QPDFObjGen id_gen() const;
59 inline bool indirect() const; 64 inline bool indirect() const;
60 inline bool null() const; 65 inline bool null() const;
include/qpdf/QPDFObjectHandle.hh
@@ -1242,19 +1242,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle @@ -1242,19 +1242,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle
1242 QPDF_DLL 1242 QPDF_DLL
1243 void warnIfPossible(std::string const& warning) const; 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 // Convenience routine: Throws if the assumption is violated. Your code will be better if you 1245 // Convenience routine: Throws if the assumption is violated. Your code will be better if you
1259 // call one of the isType methods and handle the case of the type being wrong, but these can be 1246 // call one of the isType methods and handle the case of the type being wrong, but these can be
1260 // convenient if you have already verified the type. 1247 // convenient if you have already verified the type.
@@ -1354,7 +1341,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle @@ -1354,7 +1341,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle
1354 void objectWarning(std::string const& warning) const; 1341 void objectWarning(std::string const& warning) const;
1355 void assertType(char const* type_name, bool istype) const; 1342 void assertType(char const* type_name, bool istype) const;
1356 void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); 1343 void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
1357 - void disconnect();  
1358 void setParsedOffset(qpdf_offset_t offset); 1344 void setParsedOffset(qpdf_offset_t offset);
1359 void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); 1345 void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
1360 static void parseContentStream_data( 1346 static void parseContentStream_data(
libqpdf/QPDF.cc
@@ -212,6 +212,25 @@ QPDF::QPDF() : @@ -212,6 +212,25 @@ QPDF::QPDF() :
212 m->unique_id = unique_id.fetch_add(1ULL); 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 QPDF::~QPDF() 234 QPDF::~QPDF()
216 { 235 {
217 // If two objects are mutually referential (through each object having an array or dictionary 236 // If two objects are mutually referential (through each object having an array or dictionary
@@ -228,10 +247,7 @@ QPDF::~QPDF() @@ -228,10 +247,7 @@ QPDF::~QPDF()
228 // the xref table anyway just to prevent any possibility of resolve() succeeding. 247 // the xref table anyway just to prevent any possibility of resolve() succeeding.
229 m->xref_table.clear(); 248 m->xref_table.clear();
230 for (auto const& iter: m->obj_cache) { 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&amp; p) const @@ -580,48 +580,49 @@ BaseHandle::write_json(int json_version, JSON::Writer&amp; p) const
580 } 580 }
581 581
582 void 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 case ::ot_array: 591 case ::ot_array:
589 { 592 {
590 - auto& a = std::get<QPDF_Array>(value); 593 + auto& a = std::get<QPDF_Array>(obj->value);
591 if (a.sp) { 594 if (a.sp) {
592 for (auto& item: a.sp->elements) { 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 } else { 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 break; 604 break;
607 case ::ot_dictionary: 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 break; 609 break;
612 case ::ot_stream: 610 case ::ot_stream:
613 { 611 {
614 - auto& s = std::get<QPDF_Stream>(value); 612 + auto& s = std::get<QPDF_Stream>(obj->value);
615 s.m->stream_provider = nullptr; 613 s.m->stream_provider = nullptr;
616 - QPDFObjectHandle::DisconnectAccess::disconnect(s.m->stream_dict); 614 + s.m->stream_dict.disconnect();
617 } 615 }
618 break; 616 break;
  617 + case ::ot_uninitialized:
  618 + return;
619 default: 619 default:
620 break; 620 break;
621 } 621 }
622 - qpdf = nullptr;  
623 - og = QPDFObjGen(); 622 + obj->qpdf = nullptr;
  623 + obj->og = QPDFObjGen();
624 } 624 }
  625 +
625 std::string 626 std::string
626 QPDFObject::getStringValue() const 627 QPDFObject::getStringValue() const
627 { 628 {
@@ -649,16 +650,6 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const&amp; rhs) const @@ -649,16 +650,6 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const&amp; rhs) const
649 { 650 {
650 return this->obj == rhs.obj; 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 qpdf_object_type_e 654 qpdf_object_type_e
664 QPDFObjectHandle::getTypeCode() const 655 QPDFObjectHandle::getTypeCode() const
libqpdf/qpdf/QPDFObjectHandle_private.hh
@@ -358,7 +358,7 @@ namespace qpdf @@ -358,7 +358,7 @@ namespace qpdf
358 inline bool 358 inline bool
359 BaseHandle::null() const 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 inline QPDF* 364 inline QPDF*
@@ -383,7 +383,7 @@ namespace qpdf @@ -383,7 +383,7 @@ namespace qpdf
383 return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode(); 383 return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
384 } 384 }
385 if (raw_type_code() == ::ot_reference) { 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 return raw_type_code(); 388 return raw_type_code();
389 } 389 }
libqpdf/qpdf/QPDFObject_private.hh
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include <variant> 18 #include <variant>
19 #include <vector> 19 #include <vector>
20 20
  21 +class Disconnect;
21 class QPDFObject; 22 class QPDFObject;
22 class QPDFObjectHandle; 23 class QPDFObjectHandle;
23 24
@@ -297,7 +298,6 @@ class QPDFObject @@ -297,7 +298,6 @@ class QPDFObject
297 qpdf, og, std::forward<T>(T(std::forward<Args>(args)...))); 298 qpdf, og, std::forward<T>(T(std::forward<Args>(args)...)));
298 } 299 }
299 300
300 - void disconnect();  
301 std::string getStringValue() const; 301 std::string getStringValue() const;
302 302
303 // Return a unique type code for the resolved object 303 // Return a unique type code for the resolved object
@@ -308,7 +308,7 @@ class QPDFObject @@ -308,7 +308,7 @@ class QPDFObject
308 return QPDF::Resolver::resolved(qpdf, og)->getTypeCode(); 308 return QPDF::Resolver::resolved(qpdf, og)->getTypeCode();
309 } 309 }
310 if (getTypeCode() == ::ot_reference) { 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 return getTypeCode(); 313 return getTypeCode();
314 } 314 }
@@ -354,23 +354,12 @@ class QPDFObject @@ -354,23 +354,12 @@ class QPDFObject
354 qpdf = a_qpdf; 354 qpdf = a_qpdf;
355 og = a_og; 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 bool 358 bool
365 isUnresolved() const 359 isUnresolved() const
366 { 360 {
367 return getTypeCode() == ::ot_unresolved; 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 struct JSON_Descr 364 struct JSON_Descr
376 { 365 {
@@ -467,6 +456,7 @@ class QPDFObject @@ -467,6 +456,7 @@ class QPDFObject
467 private: 456 private:
468 friend class QPDF_Stream; 457 friend class QPDF_Stream;
469 friend class qpdf::BaseHandle; 458 friend class qpdf::BaseHandle;
  459 + friend class Disconnect;
470 460
471 typedef std::variant< 461 typedef std::variant<
472 std::monostate, 462 std::monostate,