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 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&amp; 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&amp; 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,
... ...