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,6 +413,24 @@ class QPDF
413 QPDF_DLL 413 QPDF_DLL
414 QPDFObjectHandle newStream(std::string const& data); 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 // Install this object handle as an indirect object and return an 434 // Install this object handle as an indirect object and return an
417 // indirect reference to it. 435 // indirect reference to it.
418 QPDF_DLL 436 QPDF_DLL
include/qpdf/QPDFObjectHandle.hh
@@ -668,7 +668,8 @@ class QPDFObjectHandle @@ -668,7 +668,8 @@ class QPDFObjectHandle
668 // object with its replacement, use QPDF::replaceReserved for this 668 // object with its replacement, use QPDF::replaceReserved for this
669 // purpose rather than the more general QPDF::replaceObject. It 669 // purpose rather than the more general QPDF::replaceObject. It
670 // is an error to try to write a QPDF with QPDFWriter if it has 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 QPDF_DLL 673 QPDF_DLL
673 static QPDFObjectHandle newReserved(QPDF* qpdf); 674 static QPDFObjectHandle newReserved(QPDF* qpdf);
674 675
libqpdf/QPDF.cc
@@ -4,13 +4,13 @@ @@ -4,13 +4,13 @@
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <atomic> 6 #include <atomic>
  7 +#include <cstdlib>
  8 +#include <cstring>
7 #include <limits> 9 #include <limits>
8 #include <map> 10 #include <map>
9 #include <memory.h> 11 #include <memory.h>
10 #include <regex> 12 #include <regex>
11 #include <sstream> 13 #include <sstream>
12 -#include <cstdlib>  
13 -#include <cstring>  
14 #include <vector> 14 #include <vector>
15 15
16 #include <qpdf/BufferInputSource.hh> 16 #include <qpdf/BufferInputSource.hh>
@@ -1985,6 +1985,12 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) @@ -1985,6 +1985,12 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh)
1985 } 1985 }
1986 1986
1987 QPDFObjectHandle 1987 QPDFObjectHandle
  1988 +QPDF::newReserved()
  1989 +{
  1990 + return makeIndirectFromQPDFObject(QPDF_Reserved::create());
  1991 +}
  1992 +
  1993 +QPDFObjectHandle
1988 QPDF::newStream() 1994 QPDF::newStream()
1989 { 1995 {
1990 return makeIndirectFromQPDFObject(QPDF_Stream::create( 1996 return makeIndirectFromQPDFObject(QPDF_Stream::create(
@@ -2207,9 +2213,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; obj_copier, bool top) @@ -2207,9 +2213,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; obj_copier, bool top)
2207 QTC::TC("qpdf", "QPDF copy indirect"); 2213 QTC::TC("qpdf", "QPDF copy indirect");
2208 if (obj_copier.object_map.count(foreign_og) == 0) { 2214 if (obj_copier.object_map.count(foreign_og) == 0) {
2209 obj_copier.to_copy.push_back(foreign); 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,9 +2533,7 @@ QPDF::getCompressibleObjGens()
2528 if (obj.isStream()) { 2533 if (obj.isStream()) {
2529 QPDFObjectHandle dict = obj.getDict(); 2534 QPDFObjectHandle dict = obj.getDict();
2530 std::set<std::string> keys = dict.getKeys(); 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 std::string const& key = *iter; 2537 std::string const& key = *iter;
2535 QPDFObjectHandle value = dict.getKey(key); 2538 QPDFObjectHandle value = dict.getKey(key);
2536 if (key == "/Length") { 2539 if (key == "/Length") {
@@ -2544,9 +2547,7 @@ QPDF::getCompressibleObjGens() @@ -2544,9 +2547,7 @@ QPDF::getCompressibleObjGens()
2544 } 2547 }
2545 } else if (obj.isDictionary()) { 2548 } else if (obj.isDictionary()) {
2546 std::set<std::string> keys = obj.getKeys(); 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 queue.push_front(obj.getKey(*iter)); 2551 queue.push_front(obj.getKey(*iter));
2551 } 2552 }
2552 } else if (obj.isArray()) { 2553 } else if (obj.isArray()) {
libqpdf/QPDFObjectHandle.cc
@@ -2128,7 +2128,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const&amp; data) @@ -2128,7 +2128,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const&amp; data)
2128 QPDFObjectHandle 2128 QPDFObjectHandle
2129 QPDFObjectHandle::newReserved(QPDF* qpdf) 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 void 2138 void