Commit 05a49cecf1b1caa12575fa34fa478560ba25e31b

Authored by m-holger
1 parent a85635b8

Add new method QPDF::newReserved

include/qpdf/QPDF.hh
... ... @@ -413,6 +413,24 @@ class QPDF
413 413 QPDF_DLL
414 414 QPDFObjectHandle newStream(std::string const& data);
415 415  
  416 + // A reserved object is a special sentinel used for qpdf to
  417 + // reserve a spot for an object that is going to be added to the
  418 + // QPDF object. Normally you don't have to use this type since
  419 + // you can just call QPDF::makeIndirectObject. However, in some
  420 + // cases, if you have to create objects with circular references,
  421 + // you may need to create a reserved object so that you can have a
  422 + // reference to it and then replace the object later. Reserved
  423 + // objects have the special property that they can't be resolved
  424 + // to direct objects. This makes it possible to replace a
  425 + // reserved object with a new object while preserving existing
  426 + // references to them. When you are ready to replace a reserved
  427 + // object with its replacement, use QPDF::replaceReserved for this
  428 + // purpose rather than the more general QPDF::replaceObject. It
  429 + // is an error to try to write a QPDF with QPDFWriter if it has
  430 + // any reserved objects in it.
  431 + QPDF_DLL
  432 + QPDFObjectHandle newReserved();
  433 +
416 434 // Install this object handle as an indirect object and return an
417 435 // indirect reference to it.
418 436 QPDF_DLL
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -668,7 +668,8 @@ class QPDFObjectHandle
668 668 // object with its replacement, use QPDF::replaceReserved for this
669 669 // purpose rather than the more general QPDF::replaceObject. It
670 670 // is an error to try to write a QPDF with QPDFWriter if it has
671   - // any reserved objects in it.
  671 + // any reserved objects in it. From QPDF 11.4, you can
  672 + // call QPDF::newReserved() instead.
672 673 QPDF_DLL
673 674 static QPDFObjectHandle newReserved(QPDF* qpdf);
674 675  
... ...
libqpdf/QPDF.cc
... ... @@ -4,13 +4,13 @@
4 4  
5 5 #include <algorithm>
6 6 #include <atomic>
  7 +#include <cstdlib>
  8 +#include <cstring>
7 9 #include <limits>
8 10 #include <map>
9 11 #include <memory.h>
10 12 #include <regex>
11 13 #include <sstream>
12   -#include <cstdlib>
13   -#include <cstring>
14 14 #include <vector>
15 15  
16 16 #include <qpdf/BufferInputSource.hh>
... ... @@ -1985,6 +1985,12 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh)
1985 1985 }
1986 1986  
1987 1987 QPDFObjectHandle
  1988 +QPDF::newReserved()
  1989 +{
  1990 + return makeIndirectFromQPDFObject(QPDF_Reserved::create());
  1991 +}
  1992 +
  1993 +QPDFObjectHandle
1988 1994 QPDF::newStream()
1989 1995 {
1990 1996 return makeIndirectFromQPDFObject(QPDF_Stream::create(
... ... @@ -2207,9 +2213,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; obj_copier, bool top)
2207 2213 QTC::TC("qpdf", "QPDF copy indirect");
2208 2214 if (obj_copier.object_map.count(foreign_og) == 0) {
2209 2215 obj_copier.to_copy.push_back(foreign);
2210   - obj_copier.object_map[foreign_og] = foreign.isStream()
2211   - ? newStream()
2212   - : QPDFObjectHandle::newReserved(this);
  2216 + obj_copier.object_map[foreign_og] =
  2217 + foreign.isStream() ? newStream() : newReserved();
2213 2218 }
2214 2219 }
2215 2220  
... ... @@ -2528,9 +2533,7 @@ QPDF::getCompressibleObjGens()
2528 2533 if (obj.isStream()) {
2529 2534 QPDFObjectHandle dict = obj.getDict();
2530 2535 std::set<std::string> keys = dict.getKeys();
2531   - for (auto iter = keys.rbegin();
2532   - iter != keys.rend();
2533   - ++iter) {
  2536 + for (auto iter = keys.rbegin(); iter != keys.rend(); ++iter) {
2534 2537 std::string const& key = *iter;
2535 2538 QPDFObjectHandle value = dict.getKey(key);
2536 2539 if (key == "/Length") {
... ... @@ -2544,9 +2547,7 @@ QPDF::getCompressibleObjGens()
2544 2547 }
2545 2548 } else if (obj.isDictionary()) {
2546 2549 std::set<std::string> keys = obj.getKeys();
2547   - for (auto iter = keys.rbegin();
2548   - iter != keys.rend();
2549   - ++iter) {
  2550 + for (auto iter = keys.rbegin(); iter != keys.rend(); ++iter) {
2550 2551 queue.push_front(obj.getKey(*iter));
2551 2552 }
2552 2553 } else if (obj.isArray()) {
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -2128,7 +2128,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const&amp; data)
2128 2128 QPDFObjectHandle
2129 2129 QPDFObjectHandle::newReserved(QPDF* qpdf)
2130 2130 {
2131   - return qpdf->makeIndirectObject(QPDFObjectHandle(QPDF_Reserved::create()));
  2131 + if (qpdf == nullptr) {
  2132 + throw std::runtime_error(
  2133 + "attempt to create reserved object in null qpdf object");
  2134 + }
  2135 + return qpdf->newReserved();
2132 2136 }
2133 2137  
2134 2138 void
... ...