Add new method QPDF::newReserved

This commit is contained in:
m-holger 2023-05-20 19:56:01 +01:00
parent a85635b839
commit 05a49cecf1
4 changed files with 37 additions and 13 deletions

View File

@ -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

View File

@ -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);

View File

@ -4,13 +4,13 @@
#include <algorithm>
#include <atomic>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <map>
#include <memory.h>
#include <regex>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <qpdf/BufferInputSource.hh>
@ -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<std::string> 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<std::string> 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()) {

View File

@ -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