diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index f1dcb7f7..677c009b 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -413,6 +413,24 @@ class QPDF QPDF_DLL QPDFObjectHandle newStream(std::string const& data); + // A reserved object is a special sentinel used for qpdf to + // reserve a spot for an object that is going to be added to the + // QPDF object. Normally you don't have to use this type since + // you can just call QPDF::makeIndirectObject. However, in some + // cases, if you have to create objects with circular references, + // you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved + // objects have the special property that they can't be resolved + // to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing + // references to them. When you are ready to replace a reserved + // object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It + // is an error to try to write a QPDF with QPDFWriter if it has + // any reserved objects in it. + QPDF_DLL + QPDFObjectHandle newReserved(); + // Install this object handle as an indirect object and return an // indirect reference to it. QPDF_DLL diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index eaab6dc6..aeca4bf6 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -668,7 +668,8 @@ class QPDFObjectHandle // object with its replacement, use QPDF::replaceReserved for this // purpose rather than the more general QPDF::replaceObject. It // is an error to try to write a QPDF with QPDFWriter if it has - // any reserved objects in it. + // any reserved objects in it. From QPDF 11.4, you can + // call QPDF::newReserved() instead. QPDF_DLL static QPDFObjectHandle newReserved(QPDF* qpdf); diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 56a18ccd..33e9c18d 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -4,13 +4,13 @@ #include #include +#include +#include #include #include #include #include #include -#include -#include #include #include @@ -1984,6 +1984,12 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) return makeIndirectFromQPDFObject(oh.getObj()); } +QPDFObjectHandle +QPDF::newReserved() +{ + return makeIndirectFromQPDFObject(QPDF_Reserved::create()); +} + QPDFObjectHandle QPDF::newStream() { @@ -2207,9 +2213,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top) QTC::TC("qpdf", "QPDF copy indirect"); if (obj_copier.object_map.count(foreign_og) == 0) { obj_copier.to_copy.push_back(foreign); - obj_copier.object_map[foreign_og] = foreign.isStream() - ? newStream() - : QPDFObjectHandle::newReserved(this); + obj_copier.object_map[foreign_og] = + foreign.isStream() ? newStream() : newReserved(); } } @@ -2528,9 +2533,7 @@ QPDF::getCompressibleObjGens() if (obj.isStream()) { QPDFObjectHandle dict = obj.getDict(); std::set keys = dict.getKeys(); - for (auto iter = keys.rbegin(); - iter != keys.rend(); - ++iter) { + for (auto iter = keys.rbegin(); iter != keys.rend(); ++iter) { std::string const& key = *iter; QPDFObjectHandle value = dict.getKey(key); if (key == "/Length") { @@ -2544,9 +2547,7 @@ QPDF::getCompressibleObjGens() } } else if (obj.isDictionary()) { std::set keys = obj.getKeys(); - for (auto iter = keys.rbegin(); - iter != keys.rend(); - ++iter) { + for (auto iter = keys.rbegin(); iter != keys.rend(); ++iter) { queue.push_front(obj.getKey(*iter)); } } else if (obj.isArray()) { diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 9191f7db..1689cd40 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -2128,7 +2128,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) QPDFObjectHandle QPDFObjectHandle::newReserved(QPDF* qpdf) { - return qpdf->makeIndirectObject(QPDFObjectHandle(QPDF_Reserved::create())); + if (qpdf == nullptr) { + throw std::runtime_error( + "attempt to create reserved object in null qpdf object"); + } + return qpdf->newReserved(); } void