Commit 05a49cecf1b1caa12575fa34fa478560ba25e31b
1 parent
a85635b8
Add new method QPDF::newReserved
Showing
4 changed files
with
37 additions
and
13 deletions
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& 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& 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 | ... | ... |