Commit 183ff8b9206cfad2ad99661612460f15ab61945c

Authored by m-holger
Committed by GitHub
2 parents 8a1d34bb d8e4a081

Merge pull request #1366 from m-holger/qpdf-12

Break ABI
CMakeLists.txt
... ... @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.16)
7 7 # also find the version number here. generate_auto_job also reads the
8 8 # version from here.
9 9 project(qpdf
10   - VERSION 11.10.1
  10 + VERSION 12.0.0
11 11 LANGUAGES C CXX)
12 12  
13 13 # Enable correct rpath handling for MacOSX
... ... @@ -120,7 +120,6 @@ if(NOT (BUILD_STATIC_LIBS OR BUILD_SHARED_LIBS))
120 120 endif()
121 121  
122 122 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
123   -add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:POINTERHOLDER_TRANSITION=4>)
124 123  
125 124 if(ENABLE_QTC)
126 125 set(ENABLE_QTC_ARG)
... ...
ChangeLog
1 1 2025-02-15 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Disable PointerHolder by default.
  4 +
  5 +2025-02-15 Jay Berkenbilt <ejb@ql.org>
  6 +
3 7 * 11.10.1: release
4 8  
5 9 * Detect cygwin as Windows for fix-qdf tests that don't work on
... ...
cSpell.json
... ... @@ -643,7 +643,6 @@
643 643 "submatches",
644 644 "subparsers",
645 645 "subramanyam",
646   - "substract",
647 646 "swversion",
648 647 "sysnow",
649 648 "sysroot",
... ...
examples/pdf-custom-filter.cc
... ... @@ -179,7 +179,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
179 179  
180 180 private:
181 181 bool maybeReplace(
182   - QPDFObjGen const& og,
  182 + QPDFObjGen og,
183 183 QPDFObjectHandle& stream,
184 184 Pipeline* pipeline,
185 185 QPDFObjectHandle* dict_updates);
... ... @@ -204,10 +204,7 @@ StreamReplacer::StreamReplacer(QPDF* pdf) :
204 204  
205 205 bool
206 206 StreamReplacer::maybeReplace(
207   - QPDFObjGen const& og,
208   - QPDFObjectHandle& stream,
209   - Pipeline* pipeline,
210   - QPDFObjectHandle* dict_updates)
  207 + QPDFObjGen og, QPDFObjectHandle& stream, Pipeline* pipeline, QPDFObjectHandle* dict_updates)
211 208 {
212 209 // As described in the class comments, this method is called twice. Before writing has started
213 210 // pipeline is nullptr, and dict_updates is provided. In this mode, we figure out whether we
... ...
include/qpdf/Buffer.hh
... ... @@ -21,7 +21,6 @@
21 21 #define BUFFER_HH
22 22  
23 23 #include <qpdf/DLL.h>
24   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
25 24  
26 25 #include <cstddef>
27 26 #include <memory>
... ... @@ -47,15 +46,13 @@ class Buffer
47 46 QPDF_DLL
48 47 Buffer(std::string& content);
49 48  
50   - [[deprecated("Move Buffer or use Buffer::copy instead")]] QPDF_DLL Buffer(Buffer const&);
51   - [[deprecated("Move Buffer or use Buffer::copy instead")]] QPDF_DLL Buffer&
52   - operator=(Buffer const&);
53   -
54 49 QPDF_DLL
55 50 Buffer(Buffer&&) noexcept;
56 51 QPDF_DLL
57 52 Buffer& operator=(Buffer&&) noexcept;
58 53 QPDF_DLL
  54 + ~Buffer();
  55 + QPDF_DLL
59 56 size_t getSize() const;
60 57 QPDF_DLL
61 58 unsigned char const* getBuffer() const;
... ... @@ -66,29 +63,8 @@ class Buffer
66 63 QPDF_DLL
67 64 Buffer copy() const;
68 65  
69   - // Only used during CI testing.
70   - // ABI: remove when removing copy constructor / assignment operator
71   - static void setTestMode() noexcept;
72   -
73 66 private:
74   - class Members
75   - {
76   - friend class Buffer;
77   -
78   - public:
79   - QPDF_DLL
80   - ~Members();
81   -
82   - private:
83   - Members(size_t size, unsigned char* buf, bool own_memory);
84   - Members(std::string&& content);
85   - Members(Members const&) = delete;
86   -
87   - std::string str;
88   - bool own_memory;
89   - size_t size;
90   - unsigned char* buf;
91   - };
  67 + class Members;
92 68  
93 69 void copy(Buffer const&);
94 70  
... ...
include/qpdf/ClosedFileInputSource.hh
... ... @@ -26,7 +26,6 @@
26 26 // merging large numbers of files.
27 27  
28 28 #include <qpdf/InputSource.hh>
29   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
30 29  
31 30 #include <memory>
32 31  
... ...
include/qpdf/DLL.h
... ... @@ -25,14 +25,14 @@
25 25 #define QPDF_DLL_HH
26 26  
27 27 /* The first version of qpdf to include the version constants is 10.6.0. */
28   -#define QPDF_MAJOR_VERSION 11
29   -#define QPDF_MINOR_VERSION 10
30   -#define QPDF_PATCH_VERSION 1
  28 +#define QPDF_MAJOR_VERSION 12
  29 +#define QPDF_MINOR_VERSION 0
  30 +#define QPDF_PATCH_VERSION 0
31 31  
32 32 #ifdef QPDF_FUTURE
33   -# define QPDF_VERSION "11.10.1+future"
  33 +# define QPDF_VERSION "12.0.0+future"
34 34 #else
35   -# define QPDF_VERSION "11.10.1"
  35 +# define QPDF_VERSION "12.0.0"
36 36 #endif
37 37  
38 38 /*
... ...
include/qpdf/InputSource.hh
... ... @@ -21,7 +21,6 @@
21 21 #define QPDF_INPUTSOURCE_HH
22 22  
23 23 #include <qpdf/DLL.h>
24   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
25 24 #include <qpdf/Types.h>
26 25  
27 26 #include <cstdio>
... ...
include/qpdf/JSON.hh
... ... @@ -30,7 +30,6 @@
30 30 // is also a good reason not to use this as a general-purpose JSON package.
31 31  
32 32 #include <qpdf/DLL.h>
33   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
34 33 #include <qpdf/Types.h>
35 34  
36 35 #include <functional>
... ...
include/qpdf/Pipeline.hh
... ... @@ -37,7 +37,6 @@
37 37 #define PIPELINE_HH
38 38  
39 39 #include <qpdf/DLL.h>
40   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
41 40  
42 41 #include <memory>
43 42 #include <string>
... ...
include/qpdf/Pl_Buffer.hh
... ... @@ -31,7 +31,6 @@
31 31  
32 32 #include <qpdf/Buffer.hh>
33 33 #include <qpdf/Pipeline.hh>
34   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
35 34  
36 35 #include <memory>
37 36 #include <string>
... ...
include/qpdf/Pl_QPDFTokenizer.hh
... ... @@ -23,7 +23,6 @@
23 23 #include <qpdf/Pipeline.hh>
24 24  
25 25 #include <qpdf/Pl_Buffer.hh>
26   -#include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
27 26 #include <qpdf/QPDFObjectHandle.hh>
28 27 #include <qpdf/QPDFTokenizer.hh>
29 28  
... ...
include/qpdf/PointerHolder.hh
... ... @@ -26,18 +26,12 @@
26 26 #define POINTERHOLDER_IS_SHARED_POINTER
27 27  
28 28 #ifndef POINTERHOLDER_TRANSITION
29   -
30   -// #define POINTERHOLDER_TRANSITION 0 to suppress this warning, and see below.
31   -// See also https://qpdf.readthedocs.io/en/stable/design.html#smart-pointers
32   -# warning "POINTERHOLDER_TRANSITION is not defined -- see qpdf/PointerHolder.hh"
33   -
34   -// undefined = define as 0 and issue a warning
35 29 // 0 = no deprecation warnings, backward-compatible API
36 30 // 1 = make PointerHolder<T>(T*) explicit
37 31 // 2 = warn for use of getPointer() and getRefcount()
38 32 // 3 = warn for all use of PointerHolder
39 33 // 4 = don't define PointerHolder at all
40   -# define POINTERHOLDER_TRANSITION 0
  34 +# define POINTERHOLDER_TRANSITION 4
41 35 #endif // !defined(POINTERHOLDER_TRANSITION)
42 36  
43 37 #if POINTERHOLDER_TRANSITION < 4
... ... @@ -50,15 +44,19 @@
50 44 // interface and is mutually assignable with std::shared_ptr. Code
51 45 // that uses containers of PointerHolder will require adjustment.
52 46  
  47 +// In qpdf 11, a backward-compatible PointerHolder was provided with a
  48 +// warning if POINTERHOLDER_TRANSITION was not defined. Starting in
  49 +// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not
  50 +// defined. In a future version of qpdf, PointerHolder will be removed
  51 +// outright if it becomes inconvenient to keep it around.
  52 +
53 53 // *** HOW TO TRANSITION ***
54 54  
55 55 // The symbol POINTERHOLDER_TRANSITION can be defined to help you
56 56 // transition your code away from PointerHolder. You can define it
57 57 // before including any qpdf header files or including its definition
58 58 // in your build configuration. If not defined, it automatically gets
59   -// defined to 0 (with a warning), which enables full backward
60   -// compatibility. That way, you don't have to take action for your
61   -// code to continue to work.
  59 +// defined to 4, which excludes PointerHolder entirely.
62 60  
63 61 // If you want to work gradually to transition your code away from
64 62 // PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the
... ... @@ -123,7 +121,8 @@
123 121  
124 122 // POINTERHOLDER_TRANSITION = 4
125 123 //
126   -// Suppress definition of the PointerHolder<T> type entirely.
  124 +// Suppress definition of the PointerHolder<T> type entirely. This is
  125 +// the default behavior starting with qpdf 12.
127 126  
128 127 // CONST BEHAVIOR
129 128  
... ...
include/qpdf/QIntC.hh
... ... @@ -278,10 +278,9 @@ namespace QIntC // QIntC = qpdf Integer Conversion
278 278 QIntC::range_check_error<T>(cur, delta);
279 279 }
280 280  
281   - // ABI: fix spelling error in function name. Also remove "substract" from spelling dictionary.
282 281 template <typename T>
283 282 void
284   - range_check_substract_error(T const& cur, T const& delta)
  283 + range_check_subtract_error(T const& cur, T const& delta)
285 284 {
286 285 if ((delta > 0) && ((std::numeric_limits<T>::min() + delta) > cur)) {
287 286 std::ostringstream msg;
... ... @@ -297,15 +296,14 @@ namespace QIntC // QIntC = qpdf Integer Conversion
297 296 }
298 297 }
299 298  
300   - // ABI: fix typo in function name
301 299 template <typename T>
302 300 inline void
303   - range_check_substract(T const& cur, T const& delta)
  301 + range_check_subtract(T const& cur, T const& delta)
304 302 {
305 303 if ((delta >= 0) == (cur >= 0)) {
306 304 return;
307 305 }
308   - QIntC::range_check_substract_error<T>(cur, delta);
  306 + QIntC::range_check_subtract_error<T>(cur, delta);
309 307 }
310 308 }; // namespace QIntC
311 309  
... ...
include/qpdf/QPDF.hh
... ... @@ -367,13 +367,13 @@ class QPDF
367 367 // Retrieve an object by object ID and generation. Returns an indirect reference to it. The
368 368 // getObject() methods were added for qpdf 11.
369 369 QPDF_DLL
370   - QPDFObjectHandle getObject(QPDFObjGen const&);
  370 + QPDFObjectHandle getObject(QPDFObjGen);
371 371 QPDF_DLL
372 372 QPDFObjectHandle getObject(int objid, int generation);
373 373 // These are older methods, but there is no intention to deprecate
374 374 // them.
375 375 QPDF_DLL
376   - QPDFObjectHandle getObjectByObjGen(QPDFObjGen const&);
  376 + QPDFObjectHandle getObjectByObjGen(QPDFObjGen);
377 377 QPDF_DLL
378 378 QPDFObjectHandle getObjectByID(int objid, int generation);
379 379  
... ... @@ -387,14 +387,14 @@ class QPDF
387 387 // object is treated as a null object. To replace a reserved object, call replaceReserved
388 388 // instead.
389 389 QPDF_DLL
390   - void replaceObject(QPDFObjGen const& og, QPDFObjectHandle);
  390 + void replaceObject(QPDFObjGen og, QPDFObjectHandle);
391 391 QPDF_DLL
392 392 void replaceObject(int objid, int generation, QPDFObjectHandle);
393 393  
394 394 // Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that
395 395 // reference them objects not notice the swap, but this was fixed in 10.2.1.
396 396 QPDF_DLL
397   - void swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2);
  397 + void swapObjects(QPDFObjGen og1, QPDFObjGen og2);
398 398 QPDF_DLL
399 399 void swapObjects(int objid1, int generation1, int objid2, int generation2);
400 400  
... ... @@ -694,7 +694,7 @@ class QPDF
694 694 // into the array returned by getAllPages() for that page. An exception is thrown if the page is
695 695 // not found.
696 696 QPDF_DLL
697   - int findPage(QPDFObjGen const& og);
  697 + int findPage(QPDFObjGen og);
698 698 QPDF_DLL
699 699 int findPage(QPDFObjectHandle& page);
700 700  
... ... @@ -859,7 +859,7 @@ class QPDF
859 859 static bool
860 860 pipeStreamData(
861 861 QPDF* qpdf,
862   - QPDFObjGen const& og,
  862 + QPDFObjGen og,
863 863 qpdf_offset_t offset,
864 864 size_t length,
865 865 QPDFObjectHandle dict,
... ... @@ -964,7 +964,7 @@ class QPDF
964 964 ForeignStreamData(
965 965 std::shared_ptr<EncryptionParameters> encp,
966 966 std::shared_ptr<InputSource> file,
967   - QPDFObjGen const& foreign_og,
  967 + QPDFObjGen foreign_og,
968 968 qpdf_offset_t offset,
969 969 size_t length,
970 970 QPDFObjectHandle local_dict);
... ... @@ -1002,7 +1002,7 @@ class QPDF
1002 1002 friend class QPDF;
1003 1003  
1004 1004 public:
1005   - StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
  1005 + StringDecrypter(QPDF* qpdf, QPDFObjGen og);
1006 1006 ~StringDecrypter() override = default;
1007 1007 void decryptString(std::string& val) override;
1008 1008  
... ... @@ -1014,7 +1014,7 @@ class QPDF
1014 1014 class ResolveRecorder
1015 1015 {
1016 1016 public:
1017   - ResolveRecorder(QPDF* qpdf, QPDFObjGen const& og) :
  1017 + ResolveRecorder(QPDF* qpdf, QPDFObjGen og) :
1018 1018 qpdf(qpdf),
1019 1019 iter(qpdf->m->resolving.insert(og).first)
1020 1020 {
... ... @@ -1054,14 +1054,14 @@ class QPDF
1054 1054 void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2);
1055 1055 void insertFreeXrefEntry(QPDFObjGen);
1056 1056 void insertReconstructedXrefEntry(int obj, qpdf_offset_t f1, int f2);
1057   - void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
  1057 + void setLastObjectDescription(std::string const& description, QPDFObjGen og);
1058 1058 QPDFObjectHandle readTrailer();
1059 1059 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og);
1060 1060 void readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset);
1061 1061 void validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset);
1062 1062 QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj);
1063 1063 size_t recoverStreamLength(
1064   - std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset);
  1064 + std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset);
1065 1065 QPDFTokenizer::Token readToken(InputSource&, size_t max_len = 0);
1066 1066  
1067 1067 QPDFObjectHandle readObjectAtOffset(
... ... @@ -1075,15 +1075,15 @@ class QPDF
1075 1075 void resolveObjectsInStream(int obj_stream_number);
1076 1076 void stopOnError(std::string const& message);
1077 1077 QPDFObjGen nextObjGen();
1078   - QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
  1078 + QPDFObjectHandle newIndirect(QPDFObjGen, std::shared_ptr<QPDFObject> const&);
1079 1079 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
1080   - bool isCached(QPDFObjGen const& og);
1081   - bool isUnresolved(QPDFObjGen const& og);
  1080 + bool isCached(QPDFObjGen og);
  1081 + bool isUnresolved(QPDFObjGen og);
1082 1082 std::shared_ptr<QPDFObject> getObjectForParser(int id, int gen, bool parse_pdf);
1083 1083 std::shared_ptr<QPDFObject> getObjectForJSON(int id, int gen);
1084 1084 void removeObject(QPDFObjGen og);
1085 1085 void updateCache(
1086   - QPDFObjGen const& og,
  1086 + QPDFObjGen og,
1087 1087 std::shared_ptr<QPDFObject> const& object,
1088 1088 qpdf_offset_t end_before_space,
1089 1089 qpdf_offset_t end_after_space);
... ... @@ -1100,7 +1100,7 @@ class QPDF
1100 1100  
1101 1101 // Calls finish() on the pipeline when done but does not delete it
1102 1102 bool pipeStreamData(
1103   - QPDFObjGen const& og,
  1103 + QPDFObjGen og,
1104 1104 qpdf_offset_t offset,
1105 1105 size_t length,
1106 1106 QPDFObjectHandle dict,
... ... @@ -1113,7 +1113,7 @@ class QPDF
1113 1113 std::shared_ptr<QPDF::EncryptionParameters> encp,
1114 1114 std::shared_ptr<InputSource> file,
1115 1115 QPDF& qpdf_for_warning,
1116   - QPDFObjGen const& og,
  1116 + QPDFObjGen og,
1117 1117 qpdf_offset_t offset,
1118 1118 size_t length,
1119 1119 QPDFObjectHandle dict,
... ... @@ -1174,8 +1174,8 @@ class QPDF
1174 1174 interpretCF(std::shared_ptr<EncryptionParameters> encp, QPDFObjectHandle);
1175 1175 void initializeEncryption();
1176 1176 static std::string
1177   - getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen const& og, bool use_aes);
1178   - void decryptString(std::string&, QPDFObjGen const& og);
  1177 + getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen og, bool use_aes);
  1178 + void decryptString(std::string&, QPDFObjGen og);
1179 1179 static std::string
1180 1180 compute_encryption_key_from_password(std::string const& password, EncryptionData const& data);
1181 1181 static std::string
... ... @@ -1187,7 +1187,7 @@ class QPDF
1187 1187 std::shared_ptr<InputSource> file,
1188 1188 QPDF& qpdf_for_warning,
1189 1189 Pipeline*& pipeline,
1190   - QPDFObjGen const& og,
  1190 + QPDFObjGen og,
1191 1191 QPDFObjectHandle& stream_dict,
1192 1192 std::unique_ptr<Pipeline>& heap);
1193 1193  
... ... @@ -1408,7 +1408,7 @@ class QPDF
1408 1408 void readHSharedObject(BitStream);
1409 1409 void readHGeneric(BitStream, HGeneric&);
1410 1410 qpdf_offset_t maxEnd(ObjUser const& ou);
1411   - qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
  1411 + qpdf_offset_t getLinearizationOffset(QPDFObjGen);
1412 1412 QPDFObjectHandle
1413 1413 getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
1414 1414 QPDFObjectHandle getUncompressedObject(QPDFObjectHandle&, QPDFWriter::ObjTable const& obj);
... ...
include/qpdf/QPDFObjGen.hh
... ... @@ -21,8 +21,10 @@
21 21 #define QPDFOBJGEN_HH
22 22  
23 23 #include <qpdf/DLL.h>
  24 +
24 25 #include <iostream>
25 26 #include <set>
  27 +#include <string>
26 28  
27 29 class QPDFObjectHandle;
28 30 class QPDFObjectHelper;
... ... @@ -33,13 +35,10 @@ class QPDFObjectHelper;
33 35 class QPDFObjGen
34 36 {
35 37 public:
36   - // ABI: change to default.
37 38 QPDF_DLL
38   - QPDFObjGen()
39   - {
40   - }
  39 + QPDFObjGen() = default;
41 40 QPDF_DLL
42   - explicit QPDFObjGen(int obj, int gen) :
  41 + QPDFObjGen(int obj, int gen) :
43 42 obj(obj),
44 43 gen(gen)
45 44 {
... ... @@ -48,19 +47,19 @@ class QPDFObjGen
48 47 bool
49 48 operator<(QPDFObjGen const& rhs) const
50 49 {
51   - return (obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen));
  50 + return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen);
52 51 }
53 52 QPDF_DLL
54 53 bool
55 54 operator==(QPDFObjGen const& rhs) const
56 55 {
57   - return (obj == rhs.obj) && (gen == rhs.gen);
  56 + return obj == rhs.obj && gen == rhs.gen;
58 57 }
59 58 QPDF_DLL
60 59 bool
61 60 operator!=(QPDFObjGen const& rhs) const
62 61 {
63   - return (obj != rhs.obj) || (gen != rhs.gen);
  62 + return !(*this == rhs);
64 63 }
65 64 QPDF_DLL
66 65 int
... ... @@ -81,9 +80,18 @@ class QPDFObjGen
81 80 return obj != 0;
82 81 }
83 82 QPDF_DLL
84   - std::string unparse(char separator = ',') const;
  83 + std::string
  84 + unparse(char separator = ',') const
  85 + {
  86 + return std::to_string(obj) + separator + std::to_string(gen);
  87 + }
85 88 QPDF_DLL
86   - friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og);
  89 + friend std::ostream&
  90 + operator<<(std::ostream& os, QPDFObjGen og)
  91 + {
  92 + os << og.obj << "," << og.gen;
  93 + return os;
  94 + }
87 95  
88 96 // Convenience class for loop detection when processing objects.
89 97 //
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -23,27 +23,22 @@
23 23 #ifndef QPDFOBJECTHANDLE_HH
24 24 #define QPDFOBJECTHANDLE_HH
25 25  
26   -#ifdef QPDF_FUTURE
27   -# include <qpdf/QPDFObjectHandle_future.hh>
28   -#else
29   -
30   -# include <qpdf/Constants.h>
31   -# include <qpdf/DLL.h>
32   -# include <qpdf/Types.h>
33   -
34   -# include <functional>
35   -# include <map>
36   -# include <memory>
37   -# include <set>
38   -# include <string>
39   -# include <vector>
40   -
41   -# include <qpdf/Buffer.hh>
42   -# include <qpdf/InputSource.hh>
43   -# include <qpdf/JSON.hh>
44   -# include <qpdf/PointerHolder.hh> // unused -- remove in qpdf 12 (see #785)
45   -# include <qpdf/QPDFObjGen.hh>
46   -# include <qpdf/QPDFTokenizer.hh>
  26 +#include <qpdf/Constants.h>
  27 +#include <qpdf/DLL.h>
  28 +#include <qpdf/Types.h>
  29 +
  30 +#include <functional>
  31 +#include <map>
  32 +#include <memory>
  33 +#include <set>
  34 +#include <string>
  35 +#include <vector>
  36 +
  37 +#include <qpdf/Buffer.hh>
  38 +#include <qpdf/InputSource.hh>
  39 +#include <qpdf/JSON.hh>
  40 +#include <qpdf/QPDFObjGen.hh>
  41 +#include <qpdf/QPDFTokenizer.hh>
47 42  
48 43 class Pipeline;
49 44 class QPDF;
... ... @@ -296,53 +291,58 @@ class QPDFObjectHandle
296 291 QPDF_DLL
297 292 QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
298 293  
  294 + QPDF_DLL
  295 + QPDFObjectHandle(QPDFObjectHandle&&) = default;
  296 + QPDF_DLL
  297 + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
  298 +
299 299 // Return true if the QPDFObjectHandle is initialized. This allows object handles to be used in
300 300 // if statements with initializer.
301 301 QPDF_DLL
302 302 explicit inline operator bool() const noexcept;
303 303  
304   - [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const;
  304 + [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const noexcept;
305 305  
306 306 // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying
307 307 // object, meaning that changes to one are reflected in the other, or "if you paint one, the
308 308 // other one changes color." This does not perform a structural comparison of the contents of
309 309 // the objects.
310 310 QPDF_DLL
311   - bool isSameObjectAs(QPDFObjectHandle const&) const;
  311 + bool isSameObjectAs(QPDFObjectHandle const&) const noexcept;
312 312  
313 313 // Return type code and type name of underlying object. These are useful for doing rapid type
314 314 // tests (like switch statements) or for testing and debugging.
315 315 QPDF_DLL
316   - qpdf_object_type_e getTypeCode();
  316 + qpdf_object_type_e getTypeCode() const;
317 317 QPDF_DLL
318   - char const* getTypeName();
  318 + char const* getTypeName() const;
319 319  
320 320 // Exactly one of these will return true for any initialized object. Operator and InlineImage
321 321 // are only allowed in content streams.
322 322 QPDF_DLL
323   - bool isBool();
  323 + bool isBool() const;
324 324 QPDF_DLL
325   - bool isNull();
  325 + bool isNull() const;
326 326 QPDF_DLL
327   - bool isInteger();
  327 + bool isInteger() const;
328 328 QPDF_DLL
329   - bool isReal();
  329 + bool isReal() const;
330 330 QPDF_DLL
331   - bool isName();
  331 + bool isName() const;
332 332 QPDF_DLL
333   - bool isString();
  333 + bool isString() const;
334 334 QPDF_DLL
335   - bool isOperator();
  335 + bool isOperator() const;
336 336 QPDF_DLL
337   - bool isInlineImage();
  337 + bool isInlineImage() const;
338 338 QPDF_DLL
339   - bool isArray();
  339 + bool isArray() const;
340 340 QPDF_DLL
341   - bool isDictionary();
  341 + bool isDictionary() const;
342 342 QPDF_DLL
343   - bool isStream();
  343 + bool isStream() const;
344 344 QPDF_DLL
345   - bool isReserved();
  345 + bool isReserved() const;
346 346  
347 347 // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
348 348 // for internal use, but it can be used as an efficient way to check for nulls that are not
... ... @@ -357,23 +357,23 @@ class QPDFObjectHandle
357 357 // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
358 358 // such an object will throw a logic_error.
359 359 QPDF_DLL
360   - bool isDestroyed();
  360 + bool isDestroyed() const;
361 361  
362 362 // True for everything except array, dictionary, stream, word, and inline image.
363 363 QPDF_DLL
364   - bool isScalar();
  364 + bool isScalar() const;
365 365  
366 366 // True if the object is a name object representing the provided name.
367 367 QPDF_DLL
368   - bool isNameAndEquals(std::string const& name);
  368 + bool isNameAndEquals(std::string const& name) const;
369 369  
370 370 // True if the object is a dictionary of the specified type and subtype, if any.
371 371 QPDF_DLL
372   - bool isDictionaryOfType(std::string const& type, std::string const& subtype = "");
  372 + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
373 373  
374 374 // True if the object is a stream of the specified type and subtype, if any.
375 375 QPDF_DLL
376   - bool isStreamOfType(std::string const& type, std::string const& subtype = "");
  376 + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
377 377  
378 378 // Public factory methods
379 379  
... ... @@ -418,7 +418,7 @@ class QPDFObjectHandle
418 418 // object was created without parsing. If the object is in a stream, the offset is from the
419 419 // beginning of the stream. Otherwise, the offset is from the beginning of the file.
420 420 QPDF_DLL
421   - qpdf_offset_t getParsedOffset();
  421 + qpdf_offset_t getParsedOffset() const;
422 422  
423 423 // Older method: stream_or_array should be the value of /Contents from a page object. It's more
424 424 // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
... ... @@ -590,7 +590,7 @@ class QPDFObjectHandle
590 590 QPDF_DLL
591 591 void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
592 592 QPDF_DLL
593   - bool hasObjectDescription();
  593 + bool hasObjectDescription() const;
594 594  
595 595 // Accessor methods
596 596 //
... ... @@ -640,57 +640,57 @@ class QPDFObjectHandle
640 640  
641 641 // Methods for bool objects
642 642 QPDF_DLL
643   - bool getBoolValue();
  643 + bool getBoolValue() const;
644 644 QPDF_DLL
645   - bool getValueAsBool(bool&);
  645 + bool getValueAsBool(bool&) const;
646 646  
647 647 // Methods for integer objects. Note: if an integer value is too big (too far away from zero in
648 648 // either direction) to fit in the requested return type, the maximum or minimum value for that
649 649 // return type may be returned. For example, on a system with 32-bit int, a numeric object with
650 650 // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
651 651 QPDF_DLL
652   - long long getIntValue();
  652 + long long getIntValue() const;
653 653 QPDF_DLL
654   - bool getValueAsInt(long long&);
  654 + bool getValueAsInt(long long&) const;
655 655 QPDF_DLL
656   - int getIntValueAsInt();
  656 + int getIntValueAsInt() const;
657 657 QPDF_DLL
658   - bool getValueAsInt(int&);
  658 + bool getValueAsInt(int&) const;
659 659 QPDF_DLL
660   - unsigned long long getUIntValue();
  660 + unsigned long long getUIntValue() const;
661 661 QPDF_DLL
662   - bool getValueAsUInt(unsigned long long&);
  662 + bool getValueAsUInt(unsigned long long&) const;
663 663 QPDF_DLL
664   - unsigned int getUIntValueAsUInt();
  664 + unsigned int getUIntValueAsUInt() const;
665 665 QPDF_DLL
666   - bool getValueAsUInt(unsigned int&);
  666 + bool getValueAsUInt(unsigned int&) const;
667 667  
668 668 // Methods for real objects
669 669 QPDF_DLL
670   - std::string getRealValue();
  670 + std::string getRealValue() const;
671 671 QPDF_DLL
672   - bool getValueAsReal(std::string&);
  672 + bool getValueAsReal(std::string&) const;
673 673  
674 674 // Methods that work for both integer and real objects
675 675 QPDF_DLL
676   - bool isNumber();
  676 + bool isNumber() const;
677 677 QPDF_DLL
678   - double getNumericValue();
  678 + double getNumericValue() const;
679 679 QPDF_DLL
680   - bool getValueAsNumber(double&);
  680 + bool getValueAsNumber(double&) const;
681 681  
682 682 // Methods for name objects. The returned name value is in qpdf's canonical form with all
683 683 // escaping resolved. See comments for newName() for details.
684 684 QPDF_DLL
685   - std::string getName();
  685 + std::string getName() const;
686 686 QPDF_DLL
687   - bool getValueAsName(std::string&);
  687 + bool getValueAsName(std::string&) const;
688 688  
689 689 // Methods for string objects
690 690 QPDF_DLL
691   - std::string getStringValue();
  691 + std::string getStringValue() const;
692 692 QPDF_DLL
693   - bool getValueAsString(std::string&);
  693 + bool getValueAsString(std::string&) const;
694 694  
695 695 // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
696 696 // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
... ... @@ -698,19 +698,19 @@ class QPDFObjectHandle
698 698 // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
699 699 // unmapped.
700 700 QPDF_DLL
701   - std::string getUTF8Value();
  701 + std::string getUTF8Value() const;
702 702 QPDF_DLL
703   - bool getValueAsUTF8(std::string&);
  703 + bool getValueAsUTF8(std::string&) const;
704 704  
705 705 // Methods for content stream objects
706 706 QPDF_DLL
707   - std::string getOperatorValue();
  707 + std::string getOperatorValue() const;
708 708 QPDF_DLL
709   - bool getValueAsOperator(std::string&);
  709 + bool getValueAsOperator(std::string&) const;
710 710 QPDF_DLL
711   - std::string getInlineImageValue();
  711 + std::string getInlineImageValue() const;
712 712 QPDF_DLL
713   - bool getValueAsInlineImage(std::string&);
  713 + bool getValueAsInlineImage(std::string&) const;
714 714  
715 715 // Methods for array objects; see also name and array objects.
716 716  
... ... @@ -725,26 +725,26 @@ class QPDFObjectHandle
725 725 QPDFArrayItems aitems();
726 726  
727 727 QPDF_DLL
728   - int getArrayNItems();
  728 + int getArrayNItems() const;
729 729 QPDF_DLL
730   - QPDFObjectHandle getArrayItem(int n);
  730 + QPDFObjectHandle getArrayItem(int n) const;
731 731 // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
732 732 // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
733 733 // nulls.
734 734 QPDF_DLL
735   - std::vector<QPDFObjectHandle> getArrayAsVector();
  735 + std::vector<QPDFObjectHandle> getArrayAsVector() const;
736 736 QPDF_DLL
737   - bool isRectangle();
  737 + bool isRectangle() const;
738 738 // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
739 739 // rectangle [0, 0, 0, 0]
740 740 QPDF_DLL
741   - Rectangle getArrayAsRectangle();
  741 + Rectangle getArrayAsRectangle() const;
742 742 QPDF_DLL
743   - bool isMatrix();
  743 + bool isMatrix() const;
744 744 // If the array is an array of six numeric values, return as a matrix. Otherwise, return the
745 745 // matrix [1, 0, 0, 1, 0, 0]
746 746 QPDF_DLL
747   - Matrix getArrayAsMatrix();
  747 + Matrix getArrayAsMatrix() const;
748 748  
749 749 // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
750 750 // canonical name strings starting with a leading slash and not containing any PDF syntax
... ... @@ -764,27 +764,27 @@ class QPDFObjectHandle
764 764 // Return true if key is present. Keys with null values are treated as if they are not present.
765 765 // This is as per the PDF spec.
766 766 QPDF_DLL
767   - bool hasKey(std::string const&);
  767 + bool hasKey(std::string const&) const;
768 768 // Return the value for the key. If the key is not present, null is returned.
769 769 QPDF_DLL
770   - QPDFObjectHandle getKey(std::string const&);
  770 + QPDFObjectHandle getKey(std::string const&) const;
771 771 // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
772 772 // lower-level dictionaries, as in
773 773 // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
774 774 QPDF_DLL
775   - QPDFObjectHandle getKeyIfDict(std::string const&);
  775 + QPDFObjectHandle getKeyIfDict(std::string const&) const;
776 776 // Return all keys. Keys with null values are treated as if they are not present. This is as
777 777 // per the PDF spec.
778 778 QPDF_DLL
779   - std::set<std::string> getKeys();
  779 + std::set<std::string> getKeys() const;
780 780 // Return dictionary as a map. Entries with null values are included.
781 781 QPDF_DLL
782   - std::map<std::string, QPDFObjectHandle> getDictAsMap();
  782 + std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
783 783  
784 784 // Methods for name and array objects. The name value is in qpdf's canonical form with all
785 785 // escaping resolved. See comments for newName() for details.
786 786 QPDF_DLL
787   - bool isOrHasName(std::string const&);
  787 + bool isOrHasName(std::string const&) const;
788 788  
789 789 // Make all resources in a resource dictionary indirect. This just goes through all entries of
790 790 // top-level subdictionaries and converts any direct objects to indirect objects. This can be
... ... @@ -834,7 +834,7 @@ class QPDFObjectHandle
834 834 // method returns a set of all the keys in all top-level subdictionaries. For resources
835 835 // dictionaries, this is the collection of names that may be referenced in the content stream.
836 836 QPDF_DLL
837   - std::set<std::string> getResourceNames();
  837 + std::set<std::string> getResourceNames() const;
838 838  
839 839 // Find a unique name within a resource dictionary starting with a given prefix. This method
840 840 // works by appending a number to the given prefix. It searches starting with min_suffix and
... ... @@ -849,7 +849,7 @@ class QPDFObjectHandle
849 849 std::string getUniqueResourceName(
850 850 std::string const& prefix,
851 851 int& min_suffix,
852   - std::set<std::string>* resource_names = nullptr);
  852 + std::set<std::string>* resource_names = nullptr) const;
853 853  
854 854 // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
855 855 // object. Indirect objects always have an owning QPDF. Direct objects that are read from the
... ... @@ -969,7 +969,7 @@ class QPDFObjectHandle
969 969  
970 970 // Methods for stream objects
971 971 QPDF_DLL
972   - QPDFObjectHandle getDict();
  972 + QPDFObjectHandle getDict() const;
973 973  
974 974 // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
975 975 // level, whether compression is enabled, and its ability to filter. Passing false will prevent
... ... @@ -1158,12 +1158,12 @@ class QPDFObjectHandle
1158 1158 inline int getGeneration() const;
1159 1159  
1160 1160 QPDF_DLL
1161   - std::string unparse();
  1161 + std::string unparse() const;
1162 1162 QPDF_DLL
1163   - std::string unparseResolved();
  1163 + std::string unparseResolved() const;
1164 1164 // For strings only, force binary representation. Otherwise, same as unparse.
1165 1165 QPDF_DLL
1166   - std::string unparseBinary();
  1166 + std::string unparseBinary() const;
1167 1167  
1168 1168 // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
1169 1169 // JSON version. The JSON is generated as follows:
... ... @@ -1197,19 +1197,14 @@ class QPDFObjectHandle
1197 1197 // the object. The effect of dereference_indirect applies only to this object. It is not
1198 1198 // recursive.
1199 1199 QPDF_DLL
1200   - JSON getJSON(int json_version, bool dereference_indirect = false);
  1200 + JSON getJSON(int json_version, bool dereference_indirect = false) const;
1201 1201  
1202 1202 // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
1203 1203 // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
1204 1204 // documentation for getJSON and JSON::write for further detail.
1205 1205 QPDF_DLL
1206   - void
1207   - writeJSON(int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0);
1208   -
1209   - // Deprecated version uses v1 for backward compatibility.
1210   - // ABI: remove for qpdf 12
1211   - [[deprecated("Use getJSON(int version)")]] QPDF_DLL JSON
1212   - getJSON(bool dereference_indirect = false);
  1206 + void writeJSON(
  1207 + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
1213 1208  
1214 1209 // This method can be called on a stream to get a more extended JSON representation of the
1215 1210 // stream that includes the stream's data. The JSON object returned is always a dictionary whose
... ... @@ -1262,7 +1257,7 @@ class QPDFObjectHandle
1262 1257 // normally from the file have descriptions. See comments on setObjectDescription for additional
1263 1258 // details.
1264 1259 QPDF_DLL
1265   - void warnIfPossible(std::string const& warning);
  1260 + void warnIfPossible(std::string const& warning) const;
1266 1261  
1267 1262 // Provide access to specific classes for recursive disconnected().
1268 1263 class DisconnectAccess
... ... @@ -1285,55 +1280,55 @@ class QPDFObjectHandle
1285 1280 void assertInitialized() const;
1286 1281  
1287 1282 QPDF_DLL
1288   - void assertNull();
  1283 + void assertNull() const;
1289 1284 QPDF_DLL
1290   - void assertBool();
  1285 + void assertBool() const;
1291 1286 QPDF_DLL
1292   - void assertInteger();
  1287 + void assertInteger() const;
1293 1288 QPDF_DLL
1294   - void assertReal();
  1289 + void assertReal() const;
1295 1290 QPDF_DLL
1296   - void assertName();
  1291 + void assertName() const;
1297 1292 QPDF_DLL
1298   - void assertString();
  1293 + void assertString() const;
1299 1294 QPDF_DLL
1300   - void assertOperator();
  1295 + void assertOperator() const;
1301 1296 QPDF_DLL
1302   - void assertInlineImage();
  1297 + void assertInlineImage() const;
1303 1298 QPDF_DLL
1304   - void assertArray();
  1299 + void assertArray() const;
1305 1300 QPDF_DLL
1306   - void assertDictionary();
  1301 + void assertDictionary() const;
1307 1302 QPDF_DLL
1308   - void assertStream();
  1303 + void assertStream() const;
1309 1304 QPDF_DLL
1310   - void assertReserved();
  1305 + void assertReserved() const;
1311 1306  
1312 1307 QPDF_DLL
1313   - void assertIndirect();
  1308 + void assertIndirect() const;
1314 1309 QPDF_DLL
1315   - void assertScalar();
  1310 + void assertScalar() const;
1316 1311 QPDF_DLL
1317   - void assertNumber();
  1312 + void assertNumber() const;
1318 1313  
1319 1314 // The isPageObject method checks the /Type key of the object. This is not completely reliable
1320 1315 // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
1321 1316 // slightly more accepting but may still return false here when treating the object as a page
1322 1317 // would work. Use this sparingly.
1323 1318 QPDF_DLL
1324   - bool isPageObject();
  1319 + bool isPageObject() const;
1325 1320 QPDF_DLL
1326   - bool isPagesObject();
  1321 + bool isPagesObject() const;
1327 1322 QPDF_DLL
1328   - void assertPageObject();
  1323 + void assertPageObject() const;
1329 1324  
1330 1325 QPDF_DLL
1331   - bool isFormXObject();
  1326 + bool isFormXObject() const;
1332 1327  
1333 1328 // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
1334 1329 // images.
1335 1330 QPDF_DLL
1336   - bool isImage(bool exclude_imagemask = true);
  1331 + bool isImage(bool exclude_imagemask = true) const;
1337 1332  
1338 1333 // The following methods do not form part of the public API and are for internal use only.
1339 1334  
... ... @@ -1362,7 +1357,7 @@ class QPDFObjectHandle
1362 1357 return obj.get();
1363 1358 }
1364 1359  
1365   - void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false);
  1360 + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
1366 1361  
1367 1362 private:
1368 1363 QPDF_Array* asArray() const;
... ... @@ -1401,7 +1396,7 @@ class QPDFObjectHandle
1401 1396 std::shared_ptr<QPDFObject> obj;
1402 1397 };
1403 1398  
1404   -# ifndef QPDF_NO_QPDF_STRING
  1399 +#ifndef QPDF_NO_QPDF_STRING
1405 1400 // This is short for QPDFObjectHandle::parse, so you can do
1406 1401  
1407 1402 // auto oh = "<< /Key (value) >>"_qpdf;
... ... @@ -1410,14 +1405,14 @@ class QPDFObjectHandle
1410 1405 // from being here.
1411 1406  
1412 1407 /* clang-format off */
1413   -// Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
1414   -// of the file as a string if clang-format removes the space after "operator", and as of
1415   -// clang-format 15, there's no way to prevent it from doing so.
1416   -QPDF_DLL
1417   -QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
  1408 + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
  1409 + // of the file as a string if clang-format removes the space after "operator", and as of
  1410 + // clang-format 15, there's no way to prevent it from doing so.
  1411 + QPDF_DLL
  1412 + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
1418 1413 /* clang-format on */
1419 1414  
1420   -# endif // QPDF_NO_QPDF_STRING
  1415 +#endif // QPDF_NO_QPDF_STRING
1421 1416  
1422 1417 class QPDFObjectHandle::QPDFDictItems
1423 1418 {
... ... @@ -1634,7 +1629,7 @@ QPDFObjectHandle::isIndirect() const
1634 1629 }
1635 1630  
1636 1631 inline bool
1637   -QPDFObjectHandle::isInitialized() const
  1632 +QPDFObjectHandle::isInitialized() const noexcept
1638 1633 {
1639 1634 return obj != nullptr;
1640 1635 }
... ... @@ -1645,5 +1640,4 @@ operator bool() const noexcept
1645 1640 return static_cast<bool>(obj);
1646 1641 }
1647 1642  
1648   -#endif // QPDF_FUTURE
1649 1643 #endif // QPDFOBJECTHANDLE_HH
... ...
include/qpdf/QPDFObjectHandle_future.hh
1   -// Copyright (c) 2005-2021 Jay Berkenbilt
2   -// Copyright (c) 2022-2025 Jay Berkenbilt and Manfred Holger
3   -//
4   -// This file is part of qpdf.
5   -//
6   -// Licensed under the Apache License, Version 2.0 (the "License");
7   -// you may not use this file except in compliance with the License.
8   -// You may obtain a copy of the License at
9   -//
10   -// http://www.apache.org/licenses/LICENSE-2.0
11   -//
12   -// Unless required by applicable law or agreed to in writing, software
13   -// distributed under the License is distributed on an "AS IS" BASIS,
14   -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   -// See the License for the specific language governing permissions and
16   -// limitations under the License.
17   -//
18   -// Versions of qpdf prior to version 7 were released under the terms
19   -// of version 2.0 of the Artistic License. At your option, you may
20   -// continue to consider qpdf to be licensed under those terms. Please
21   -// see the manual for additional information.
22   -
23   -#ifndef QPDFOBJECTHANDLE_FUTURE_HH
24   -#define QPDFOBJECTHANDLE_FUTURE_HH
25   -
26   -#include <qpdf/Constants.h>
27   -#include <qpdf/DLL.h>
28   -#include <qpdf/Types.h>
29   -
30   -#include <functional>
31   -#include <map>
32   -#include <memory>
33   -#include <set>
34   -#include <string>
35   -#include <vector>
36   -
37   -#include <qpdf/Buffer.hh>
38   -#include <qpdf/InputSource.hh>
39   -#include <qpdf/JSON.hh>
40   -#include <qpdf/QPDFObjGen.hh>
41   -#include <qpdf/QPDFTokenizer.hh>
42   -
43   -class Pipeline;
44   -class QPDF;
45   -class QPDF_Array;
46   -class QPDF_Bool;
47   -class QPDF_Dictionary;
48   -class QPDF_InlineImage;
49   -class QPDF_Integer;
50   -class QPDF_Name;
51   -class QPDF_Null;
52   -class QPDF_Operator;
53   -class QPDF_Real;
54   -class QPDF_Reserved;
55   -class QPDF_Stream;
56   -class QPDF_String;
57   -class QPDFObject;
58   -class QPDFTokenizer;
59   -class QPDFExc;
60   -class Pl_QPDFTokenizer;
61   -class QPDFMatrix;
62   -class QPDFParser;
63   -
64   -class QPDFObjectHandle
65   -{
66   - friend class QPDFParser;
67   -
68   - public:
69   - // This class is used by replaceStreamData. It provides an alternative way of associating
70   - // stream data with a stream. See comments on replaceStreamData and newStream for additional
71   - // details.
72   - class QPDF_DLL_CLASS StreamDataProvider
73   - {
74   - public:
75   - QPDF_DLL
76   - StreamDataProvider(bool supports_retry = false);
77   -
78   - QPDF_DLL
79   - virtual ~StreamDataProvider();
80   - // The implementation of this function must write stream data to the given pipeline. The
81   - // stream data must conform to whatever filters are explicitly associated with the stream.
82   - // QPDFWriter may, in some cases, add compression, but if it does, it will update the
83   - // filters as needed. Every call to provideStreamData for a given stream must write the same
84   - // data. Note that, when writing linearized files, qpdf will call your provideStreamData
85   - // twice, and if it generates different output, you risk generating invalid output or having
86   - // qpdf throw an exception. The object ID and generation passed to this method are those
87   - // that belong to the stream on behalf of which the provider is called. They may be ignored
88   - // or used by the implementation for indexing or other purposes. This information is made
89   - // available just to make it more convenient to use a single StreamDataProvider object to
90   - // provide data for multiple streams.
91   -
92   - // A few things to keep in mind:
93   - //
94   - // * Stream data providers must not modify any objects since they may be called after some
95   - // parts of the file have already been written.
96   - //
97   - // * Since qpdf may call provideStreamData multiple times when writing linearized files, if
98   - // the work done by your stream data provider is slow or computationally intensive, you
99   - // might want to implement your own cache.
100   - //
101   - // * Once you have called replaceStreamData, the original stream data is no longer directly
102   - // accessible from the stream, but this is easy to work around by copying the stream to
103   - // a separate QPDF object. The qpdf library implements this very efficiently without
104   - // actually making a copy of the stream data. You can find examples of this pattern in
105   - // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc.
106   -
107   - // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or
108   - // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by
109   - // allowing an alternative provideStreamData to be implemented. You must implement at least
110   - // one of the versions of provideStreamData below. If you implement the version that
111   - // supports retry and returns a value, you should pass true as the value of supports_retry
112   - // in the base class constructor. This will cause the library to call that version of the
113   - // method, which should also return a boolean indicating whether it ran without errors.
114   - QPDF_DLL
115   - virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
116   - QPDF_DLL
117   - virtual bool provideStreamData(
118   - QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
119   - QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline);
120   - QPDF_DLL virtual bool provideStreamData(
121   - int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
122   - QPDF_DLL
123   - bool supportsRetry();
124   -
125   - private:
126   - bool supports_retry;
127   - };
128   -
129   - // The TokenFilter class provides a way to filter content streams in a lexically aware fashion.
130   - // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter
131   - // methods or can be applied on the spot by filterPageContents. You may also use
132   - // Pl_QPDFTokenizer directly if you need full control.
133   - //
134   - // The handleToken method is called for each token, including the eof token, and then handleEOF
135   - // is called at the very end. Handlers may call write (or writeToken) to pass data downstream.
136   - // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of
137   - // using TokenFilters.
138   - //
139   - // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you
140   - // get the canonical, "parsed" representation of the token. For a string, this means that there
141   - // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits)
142   - // has been resolved. qpdf's internal representation of a name includes the leading slash. As
143   - // such, you can't write the value of token.getValue() directly to output that is supposed to be
144   - // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can
145   - // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new
146   - // string or name token from a canonical representation, use
147   - // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or
148   - // QPDFTokenizer::Token(QPDFTokenizer::tt_name,
149   - // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can
150   - // still write them with writeToken(). Example:
151   - // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain"))
152   - // would write `/text#2fplain`, and
153   - // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`.
154   - class QPDF_DLL_CLASS TokenFilter
155   - {
156   - public:
157   - QPDF_DLL
158   - TokenFilter() = default;
159   - QPDF_DLL
160   - virtual ~TokenFilter() = default;
161   - virtual void handleToken(QPDFTokenizer::Token const&) = 0;
162   - QPDF_DLL
163   - virtual void handleEOF();
164   -
165   - class PipelineAccessor
166   - {
167   - friend class Pl_QPDFTokenizer;
168   -
169   - private:
170   - static void
171   - setPipeline(TokenFilter* f, Pipeline* p)
172   - {
173   - f->setPipeline(p);
174   - }
175   - };
176   -
177   - protected:
178   - QPDF_DLL
179   - void write(char const* data, size_t len);
180   - QPDF_DLL
181   - void write(std::string const& str);
182   - QPDF_DLL
183   - void writeToken(QPDFTokenizer::Token const&);
184   -
185   - private:
186   - QPDF_DLL_PRIVATE
187   - void setPipeline(Pipeline*);
188   -
189   - Pipeline* pipeline;
190   - };
191   -
192   - // This class is used by parse to decrypt strings when reading an object that contains encrypted
193   - // strings.
194   - class StringDecrypter
195   - {
196   - public:
197   - QPDF_DLL
198   - virtual ~StringDecrypter() = default;
199   - virtual void decryptString(std::string& val) = 0;
200   - };
201   -
202   - // This class is used by parsePageContents. Callers must instantiate a subclass of this with
203   - // handlers defined to accept QPDFObjectHandles that are parsed from the stream.
204   - class QPDF_DLL_CLASS ParserCallbacks
205   - {
206   - public:
207   - QPDF_DLL
208   - virtual ~ParserCallbacks() = default;
209   - // One of the handleObject methods must be overridden.
210   - QPDF_DLL
211   - virtual void handleObject(QPDFObjectHandle);
212   - QPDF_DLL
213   - virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length);
214   -
215   - virtual void handleEOF() = 0;
216   -
217   - // Override this if you want to know the full size of the contents, possibly after
218   - // concatenation of multiple streams. This is called before the first call to handleObject.
219   - QPDF_DLL
220   - virtual void contentSize(size_t);
221   -
222   - protected:
223   - // Implementors may call this method during parsing to terminate parsing early. This method
224   - // throws an exception that is caught by parsePageContents, so its effect is immediate.
225   - QPDF_DLL
226   - void terminateParsing();
227   - };
228   -
229   - // Convenience object for rectangles
230   - class Rectangle
231   - {
232   - public:
233   - Rectangle() :
234   - llx(0.0),
235   - lly(0.0),
236   - urx(0.0),
237   - ury(0.0)
238   - {
239   - }
240   - Rectangle(double llx, double lly, double urx, double ury) :
241   - llx(llx),
242   - lly(lly),
243   - urx(urx),
244   - ury(ury)
245   - {
246   - }
247   -
248   - double llx;
249   - double lly;
250   - double urx;
251   - double ury;
252   - };
253   -
254   - // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't
255   - // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity
256   - // transform matrix and this one is all zeroes.
257   - class Matrix
258   - {
259   - public:
260   - Matrix() :
261   - a(0.0),
262   - b(0.0),
263   - c(0.0),
264   - d(0.0),
265   - e(0.0),
266   - f(0.0)
267   - {
268   - }
269   - Matrix(double a, double b, double c, double d, double e, double f) :
270   - a(a),
271   - b(b),
272   - c(c),
273   - d(d),
274   - e(e),
275   - f(f)
276   - {
277   - }
278   -
279   - double a;
280   - double b;
281   - double c;
282   - double d;
283   - double e;
284   - double f;
285   - };
286   -
287   - QPDF_DLL
288   - QPDFObjectHandle() = default;
289   - QPDF_DLL
290   - QPDFObjectHandle(QPDFObjectHandle const&) = default;
291   - QPDF_DLL
292   - QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
293   -
294   - QPDF_DLL
295   - QPDFObjectHandle(QPDFObjectHandle&&) = default;
296   - QPDF_DLL
297   - QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
298   -
299   - // Return true if the QPDFObjectHandle is initialized. This allows object handles to be used in
300   - // if statements with initializer.
301   - QPDF_DLL
302   - explicit inline operator bool() const noexcept;
303   -
304   - [[deprecated("use operator bool()")]] QPDF_DLL inline bool isInitialized() const noexcept;
305   -
306   - // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying
307   - // object, meaning that changes to one are reflected in the other, or "if you paint one, the
308   - // other one changes color." This does not perform a structural comparison of the contents of
309   - // the objects.
310   - QPDF_DLL
311   - bool isSameObjectAs(QPDFObjectHandle const&) const noexcept;
312   -
313   - // Return type code and type name of underlying object. These are useful for doing rapid type
314   - // tests (like switch statements) or for testing and debugging.
315   - QPDF_DLL
316   - qpdf_object_type_e getTypeCode() const;
317   - QPDF_DLL
318   - char const* getTypeName() const;
319   -
320   - // Exactly one of these will return true for any initialized object. Operator and InlineImage
321   - // are only allowed in content streams.
322   - QPDF_DLL
323   - bool isBool() const;
324   - QPDF_DLL
325   - bool isNull() const;
326   - QPDF_DLL
327   - bool isInteger() const;
328   - QPDF_DLL
329   - bool isReal() const;
330   - QPDF_DLL
331   - bool isName() const;
332   - QPDF_DLL
333   - bool isString() const;
334   - QPDF_DLL
335   - bool isOperator() const;
336   - QPDF_DLL
337   - bool isInlineImage() const;
338   - QPDF_DLL
339   - bool isArray() const;
340   - QPDF_DLL
341   - bool isDictionary() const;
342   - QPDF_DLL
343   - bool isStream() const;
344   - QPDF_DLL
345   - bool isReserved() const;
346   -
347   - // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
348   - // for internal use, but it can be used as an efficient way to check for nulls that are not
349   - // indirect objects.
350   - QPDF_DLL
351   - bool isDirectNull() const;
352   -
353   - // This returns true in addition to the query for the specific type for indirect objects.
354   - QPDF_DLL
355   - inline bool isIndirect() const;
356   -
357   - // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
358   - // such an object will throw a logic_error.
359   - QPDF_DLL
360   - bool isDestroyed() const;
361   -
362   - // True for everything except array, dictionary, stream, word, and inline image.
363   - QPDF_DLL
364   - bool isScalar() const;
365   -
366   - // True if the object is a name object representing the provided name.
367   - QPDF_DLL
368   - bool isNameAndEquals(std::string const& name) const;
369   -
370   - // True if the object is a dictionary of the specified type and subtype, if any.
371   - QPDF_DLL
372   - bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
373   -
374   - // True if the object is a stream of the specified type and subtype, if any.
375   - QPDF_DLL
376   - bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
377   -
378   - // Public factory methods
379   -
380   - // Wrap an object in an array if it is not already an array. This is a helper for cases in which
381   - // something in a PDF may either be a single item or an array of items, which is a common idiom.
382   - QPDF_DLL
383   - QPDFObjectHandle wrapInArray();
384   -
385   - // Construct an object of any type from a string representation of the object. Throws QPDFExc
386   - // with an empty filename and an offset into the string if there is an error. Any indirect
387   - // object syntax (obj gen R) will cause a logic_error exception to be thrown. If
388   - // object_description is provided, it will appear in the message of any QPDFExc exception thrown
389   - // for invalid syntax. See also the global `operator ""_qpdf` defined below.
390   - QPDF_DLL
391   - static QPDFObjectHandle
392   - parse(std::string const& object_str, std::string const& object_description = "");
393   -
394   - // Construct an object of any type from a string representation of the object. Indirect object
395   - // syntax (obj gen R) is allowed and will create indirect references within the passed-in
396   - // context. If object_description is provided, it will appear in the message of any QPDFExc
397   - // exception thrown for invalid syntax. Note that you can't parse an indirect object reference
398   - // all by itself as parse will stop at the end of the first complete object, which will just be
399   - // the first number and will report that there is trailing data at the end of the string.
400   - QPDF_DLL
401   - static QPDFObjectHandle
402   - parse(QPDF* context, std::string const& object_str, std::string const& object_description = "");
403   -
404   - // Construct an object as above by reading from the given InputSource at its current position
405   - // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted.
406   - // This method was intended to be called by QPDF for parsing objects that are ready from the
407   - // object's input stream.
408   - QPDF_DLL
409   - static QPDFObjectHandle parse(
410   - std::shared_ptr<InputSource> input,
411   - std::string const& object_description,
412   - QPDFTokenizer&,
413   - bool& empty,
414   - StringDecrypter* decrypter,
415   - QPDF* context);
416   -
417   - // Return the offset where the object was found when parsed. A negative value means that the
418   - // object was created without parsing. If the object is in a stream, the offset is from the
419   - // beginning of the stream. Otherwise, the offset is from the beginning of the file.
420   - QPDF_DLL
421   - qpdf_offset_t getParsedOffset() const;
422   -
423   - // Older method: stream_or_array should be the value of /Contents from a page object. It's more
424   - // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
425   - // messages will also be more useful because the page object information will be known.
426   - QPDF_DLL
427   - static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
428   -
429   - // When called on a stream or stream array that is some page's content streams, do the same as
430   - // pipePageContents. This method is a lower level way to do what
431   - // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a
432   - // contents object that is disconnected from a page object. The description argument should
433   - // describe the containing page and is used in error messages. The all_description argument is
434   - // initialized to something that could be used to describe the result of the pipeline. It is the
435   - // description amended with the identifiers of the underlying objects. Please note that if there
436   - // is an array of content streams, p->finish() is called after each stream. If you pass a
437   - // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an
438   - // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the
439   - // end.
440   - QPDF_DLL
441   - void
442   - pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description);
443   -
444   - // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream
445   - // data is passed through the token filter after all original filters but before content stream
446   - // normalization if requested. This is a low-level interface to add it to a stream. You will
447   - // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be
448   - // applied to a page object, and which will automatically handle the case of pages whose
449   - // contents are split across multiple streams.
450   - QPDF_DLL
451   - void addTokenFilter(std::shared_ptr<TokenFilter> token_filter);
452   -
453   - // Legacy helpers for parsing content streams. These methods are not going away, but newer code
454   - // should call the correspond methods in QPDFPageObjectHelper instead. The specification and
455   - // behavior of these methods are the same as the identically named methods in that class, but
456   - // newer functionality will be added there.
457   - QPDF_DLL
458   - void parsePageContents(ParserCallbacks* callbacks);
459   - QPDF_DLL
460   - void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr);
461   - // See comments for QPDFPageObjectHelper::pipeContents.
462   - QPDF_DLL
463   - void pipePageContents(Pipeline* p);
464   - QPDF_DLL
465   - void addContentTokenFilter(std::shared_ptr<TokenFilter> token_filter);
466   - // End legacy content stream helpers
467   -
468   - // Called on a stream to filter the stream as if it were page contents. This can be used to
469   - // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream.
470   - QPDF_DLL
471   - void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr);
472   - // Called on a stream to parse the stream as page contents. This can be used to parse a form
473   - // XObject.
474   - QPDF_DLL
475   - void parseAsContents(ParserCallbacks* callbacks);
476   -
477   - // Type-specific factories
478   - QPDF_DLL
479   - static QPDFObjectHandle newNull();
480   - QPDF_DLL
481   - static QPDFObjectHandle newBool(bool value);
482   - QPDF_DLL
483   - static QPDFObjectHandle newInteger(long long value);
484   - QPDF_DLL
485   - static QPDFObjectHandle newReal(std::string const& value);
486   - QPDF_DLL
487   - static QPDFObjectHandle
488   - newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true);
489   - // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes,
490   - // excluding the NUL character, and starting with a slash. Name objects as represented in the
491   - // PDF specification can contain characters escaped with #, but such escaping is not of concern
492   - // when calling QPDFObjectHandle methods not directly relating to parsing. For example,
493   - // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return
494   - // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse()
495   - // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and
496   - // modifying objects, you want to work with the internal, canonical representation. For names
497   - // containing alphanumeric characters, dashes, and underscores, there is no difference between
498   - // the two representations. For a lengthy discussion, see
499   - // https://github.com/qpdf/qpdf/discussions/625.
500   - QPDF_DLL
501   - static QPDFObjectHandle newName(std::string const& name);
502   - QPDF_DLL
503   - static QPDFObjectHandle newString(std::string const& str);
504   - // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in
505   - // PDF files outside of content streams, such as in document metadata form field values, page
506   - // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16
507   - // as needed to successfully encode all the characters.
508   - QPDF_DLL
509   - static QPDFObjectHandle newUnicodeString(std::string const& utf8_str);
510   - QPDF_DLL
511   - static QPDFObjectHandle newOperator(std::string const&);
512   - QPDF_DLL
513   - static QPDFObjectHandle newInlineImage(std::string const&);
514   - QPDF_DLL
515   - static QPDFObjectHandle newArray();
516   - QPDF_DLL
517   - static QPDFObjectHandle newArray(std::vector<QPDFObjectHandle> const& items);
518   - QPDF_DLL
519   - static QPDFObjectHandle newArray(Rectangle const&);
520   - QPDF_DLL
521   - static QPDFObjectHandle newArray(Matrix const&);
522   - QPDF_DLL
523   - static QPDFObjectHandle newArray(QPDFMatrix const&);
524   - QPDF_DLL
525   - static QPDFObjectHandle newDictionary();
526   - QPDF_DLL
527   - static QPDFObjectHandle newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
528   -
529   - // Create an array from a rectangle. Equivalent to the rectangle form of newArray.
530   - QPDF_DLL
531   - static QPDFObjectHandle newFromRectangle(Rectangle const&);
532   - // Create an array from a matrix. Equivalent to the matrix form of newArray.
533   - QPDF_DLL
534   - static QPDFObjectHandle newFromMatrix(Matrix const&);
535   - QPDF_DLL
536   - static QPDFObjectHandle newFromMatrix(QPDFMatrix const&);
537   -
538   - // Note: new stream creation methods have were added to the QPDF class starting with
539   - // version 11.2.0. The ones in this class are here for backward compatibility.
540   -
541   - // Create a new stream and associate it with the given qpdf object. A subsequent call must be
542   - // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be
543   - // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively,
544   - // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can
545   - // call QPDF::newStream() instead.
546   - QPDF_DLL
547   - static QPDFObjectHandle newStream(QPDF* qpdf);
548   -
549   - // Create a new stream and associate it with the given qpdf object. Use the given buffer as the
550   - // stream data. The stream dictionary's /Length key will automatically be set to the size of the
551   - // data buffer. If additional keys are required, the stream's dictionary may be retrieved by
552   - // calling getDict(), and the resulting dictionary may be modified. This method is just a
553   - // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience
554   - // methods for streams that require no parameters beyond the stream length. Note that you don't
555   - // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will
556   - // automatically compress uncompressed stream data. Example programs are provided that
557   - // illustrate this. From QPDF 11.2, you can call QPDF::newStream()
558   - // instead.
559   - QPDF_DLL
560   - static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr<Buffer> data);
561   -
562   - // Create new stream with data from string. This method will create a copy of the data rather
563   - // than using the user-provided buffer as in the std::shared_ptr<Buffer> version of newStream.
564   - // From QPDF 11.2, you can call QPDF::newStream() instead.
565   - QPDF_DLL
566   - static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data);
567   -
568   - // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is
569   - // going to be added to the QPDF object. Normally you don't have to use this type since you can
570   - // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects
571   - // with circular references, you may need to create a reserved object so that you can have a
572   - // reference to it and then replace the object later. Reserved objects have the special
573   - // property that they can't be resolved to direct objects. This makes it possible to replace a
574   - // reserved object with a new object while preserving existing references to them. When you are
575   - // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this
576   - // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a
577   - // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call
578   - // QPDF::newReserved() instead.
579   - QPDF_DLL
580   - static QPDFObjectHandle newReserved(QPDF* qpdf);
581   -
582   - // Provide an owning qpdf and object description. The library does this automatically with
583   - // objects that are read from the input PDF and with objects that are created programmatically
584   - // and inserted into the QPDF as a new indirect object. Most end user code will not need to call
585   - // this. If an object has an owning qpdf and object description, it enables qpdf to give
586   - // warnings with proper context in some cases where it would otherwise raise exceptions. It is
587   - // okay to add objects without an owning_qpdf to objects that have one, but it is an error to
588   - // have a QPDF contain objects with owning_qpdf set to something else. To add objects from
589   - // another qpdf, use copyForeignObject instead.
590   - QPDF_DLL
591   - void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
592   - QPDF_DLL
593   - bool hasObjectDescription() const;
594   -
595   - // Accessor methods
596   - //
597   - // (Note: this comment is referenced in qpdf-c.h and the manual.)
598   - //
599   - // In PDF files, objects have specific types, but there is nothing that prevents PDF files from
600   - // containing objects of types that aren't expected by the specification.
601   - //
602   - // There are two flavors of accessor methods:
603   - //
604   - // * getSomethingValue() returns the value and issues a type warning if the type is incorrect.
605   - //
606   - // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns
607   - // true and initializes a reference of the appropriate type. These methods never issue type
608   - // warnings.
609   - //
610   - // The getSomethingValue() accessors and some of the other methods expect objects of a
611   - // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as
612   - // trying to get a dictionary key from an array, trying to get the string value of a number,
613   - // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using
614   - // the following behavior:
615   - //
616   - // * Requesting a value of the wrong type (int value from string, array item from a scalar or
617   - // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for
618   - // number, the empty string for string, or the null object for an object handle.
619   - //
620   - // * Accessing an array item that is out of bounds will return a null object.
621   - //
622   - // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to
623   - // a scalar or array) will be ignored.
624   - //
625   - // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5,
626   - // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code
627   - // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case
628   - // for all objects whose origin was a PDF file), the warning is issued using the normal warning
629   - // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them.
630   - // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created
631   - // programmatically), an exception will be thrown.
632   - //
633   - // The way to avoid getting any type warnings or exceptions, even when working with malformed
634   - // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for
635   - // example, make sure that isString() returns true before calling getStringValue()) and to
636   - // always be sure that any array indices are in bounds.
637   - //
638   - // For additional discussion and rationale for this behavior, see the section in the QPDF manual
639   - // entitled "Object Accessor Methods".
640   -
641   - // Methods for bool objects
642   - QPDF_DLL
643   - bool getBoolValue() const;
644   - QPDF_DLL
645   - bool getValueAsBool(bool&) const;
646   -
647   - // Methods for integer objects. Note: if an integer value is too big (too far away from zero in
648   - // either direction) to fit in the requested return type, the maximum or minimum value for that
649   - // return type may be returned. For example, on a system with 32-bit int, a numeric object with
650   - // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
651   - QPDF_DLL
652   - long long getIntValue() const;
653   - QPDF_DLL
654   - bool getValueAsInt(long long&) const;
655   - QPDF_DLL
656   - int getIntValueAsInt() const;
657   - QPDF_DLL
658   - bool getValueAsInt(int&) const;
659   - QPDF_DLL
660   - unsigned long long getUIntValue() const;
661   - QPDF_DLL
662   - bool getValueAsUInt(unsigned long long&) const;
663   - QPDF_DLL
664   - unsigned int getUIntValueAsUInt() const;
665   - QPDF_DLL
666   - bool getValueAsUInt(unsigned int&) const;
667   -
668   - // Methods for real objects
669   - QPDF_DLL
670   - std::string getRealValue() const;
671   - QPDF_DLL
672   - bool getValueAsReal(std::string&) const;
673   -
674   - // Methods that work for both integer and real objects
675   - QPDF_DLL
676   - bool isNumber() const;
677   - QPDF_DLL
678   - double getNumericValue() const;
679   - QPDF_DLL
680   - bool getValueAsNumber(double&) const;
681   -
682   - // Methods for name objects. The returned name value is in qpdf's canonical form with all
683   - // escaping resolved. See comments for newName() for details.
684   - QPDF_DLL
685   - std::string getName() const;
686   - QPDF_DLL
687   - bool getValueAsName(std::string&) const;
688   -
689   - // Methods for string objects
690   - QPDF_DLL
691   - std::string getStringValue() const;
692   - QPDF_DLL
693   - bool getValueAsString(std::string&) const;
694   -
695   - // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
696   - // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
697   - // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters
698   - // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
699   - // unmapped.
700   - QPDF_DLL
701   - std::string getUTF8Value() const;
702   - QPDF_DLL
703   - bool getValueAsUTF8(std::string&) const;
704   -
705   - // Methods for content stream objects
706   - QPDF_DLL
707   - std::string getOperatorValue() const;
708   - QPDF_DLL
709   - bool getValueAsOperator(std::string&) const;
710   - QPDF_DLL
711   - std::string getInlineImageValue() const;
712   - QPDF_DLL
713   - bool getValueAsInlineImage(std::string&) const;
714   -
715   - // Methods for array objects; see also name and array objects.
716   -
717   - // Return an object that enables iteration over members. You can do
718   - //
719   - // for (auto iter: obj.aitems())
720   - // {
721   - // // iter is an array element
722   - // }
723   - class QPDFArrayItems;
724   - QPDF_DLL
725   - QPDFArrayItems aitems();
726   -
727   - QPDF_DLL
728   - int getArrayNItems() const;
729   - QPDF_DLL
730   - QPDFObjectHandle getArrayItem(int n) const;
731   - // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
732   - // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
733   - // nulls.
734   - QPDF_DLL
735   - std::vector<QPDFObjectHandle> getArrayAsVector() const;
736   - QPDF_DLL
737   - bool isRectangle() const;
738   - // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
739   - // rectangle [0, 0, 0, 0]
740   - QPDF_DLL
741   - Rectangle getArrayAsRectangle() const;
742   - QPDF_DLL
743   - bool isMatrix() const;
744   - // If the array is an array of six numeric values, return as a matrix. Otherwise, return the
745   - // matrix [1, 0, 0, 1, 0, 0]
746   - QPDF_DLL
747   - Matrix getArrayAsMatrix() const;
748   -
749   - // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
750   - // canonical name strings starting with a leading slash and not containing any PDF syntax
751   - // escaping. See comments for getName() for details.
752   -
753   - // Return an object that enables iteration over members. You can do
754   - //
755   - // for (auto iter: obj.ditems())
756   - // {
757   - // // iter.first is the key
758   - // // iter.second is the value
759   - // }
760   - class QPDFDictItems;
761   - QPDF_DLL
762   - QPDFDictItems ditems();
763   -
764   - // Return true if key is present. Keys with null values are treated as if they are not present.
765   - // This is as per the PDF spec.
766   - QPDF_DLL
767   - bool hasKey(std::string const&) const;
768   - // Return the value for the key. If the key is not present, null is returned.
769   - QPDF_DLL
770   - QPDFObjectHandle getKey(std::string const&) const;
771   - // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
772   - // lower-level dictionaries, as in
773   - // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
774   - QPDF_DLL
775   - QPDFObjectHandle getKeyIfDict(std::string const&) const;
776   - // Return all keys. Keys with null values are treated as if they are not present. This is as
777   - // per the PDF spec.
778   - QPDF_DLL
779   - std::set<std::string> getKeys() const;
780   - // Return dictionary as a map. Entries with null values are included.
781   - QPDF_DLL
782   - std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
783   -
784   - // Methods for name and array objects. The name value is in qpdf's canonical form with all
785   - // escaping resolved. See comments for newName() for details.
786   - QPDF_DLL
787   - bool isOrHasName(std::string const&) const;
788   -
789   - // Make all resources in a resource dictionary indirect. This just goes through all entries of
790   - // top-level subdictionaries and converts any direct objects to indirect objects. This can be
791   - // useful to call before mergeResources if it is going to be called multiple times to prevent
792   - // resources from being copied multiple times.
793   - QPDF_DLL
794   - void makeResourcesIndirect(QPDF& owning_qpdf);
795   -
796   - // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in
797   - // dictionary subitems are resolved, and "conflicts" is initialized to a map such that
798   - // conflicts[resource_type][old_key] == [new_key]
799   - //
800   - // See also makeResourcesIndirect, which can be useful to call before calling this.
801   - //
802   - // This method does nothing if both this object and the other object are not dictionaries.
803   - // Otherwise, it has following behavior, where "object" refers to the object whose method is
804   - // invoked, and "other" refers to the argument:
805   - //
806   - // * For each key in "other" whose value is an array:
807   - // * If "object" does not have that entry, shallow copy it.
808   - // * Otherwise, if "object" has an array in the same place, append to that array any objects
809   - // in "other"'s array that are not already present.
810   - // * For each key in "other" whose value is a dictionary:
811   - // * If "object" does not have that entry, shallow copy it.
812   - // * Otherwise, for each key in the subdictionary:
813   - // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if
814   - // indirect.
815   - // * Otherwise, if conflicts are being detected:
816   - // * If there is a key (oldkey) already in the dictionary that points to the same indirect
817   - // destination as key, indicate that key was replaced by oldkey. This would happen if
818   - // these two resource dictionaries have previously been merged.
819   - // * Otherwise pick a new key (newkey) that is unique within the resource dictionary,
820   - // store that in the resource dictionary with key's destination as its destination, and
821   - // indicate that key was replaced by newkey.
822   - //
823   - // The primary purpose of this method is to facilitate merging of resource dictionaries that are
824   - // supposed to have the same scope as each other. For example, this can be used to merge a form
825   - // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The
826   - // "conflicts" parameter may be previously initialized. This method adds to whatever is already
827   - // there, which can be useful when merging with multiple things.
828   - QPDF_DLL
829   - void mergeResources(
830   - QPDFObjectHandle other,
831   - std::map<std::string, std::map<std::string, std::string>>* conflicts = nullptr);
832   -
833   - // Get all resource names from a resource dictionary. If this object is a dictionary, this
834   - // method returns a set of all the keys in all top-level subdictionaries. For resources
835   - // dictionaries, this is the collection of names that may be referenced in the content stream.
836   - QPDF_DLL
837   - std::set<std::string> getResourceNames() const;
838   -
839   - // Find a unique name within a resource dictionary starting with a given prefix. This method
840   - // works by appending a number to the given prefix. It searches starting with min_suffix and
841   - // sets min_suffix to selected value upon return. This can be used to increase efficiency if
842   - // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next
843   - // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling
844   - // this multiple times on the same resource dictionary, you can initialize resource_names by
845   - // calling getResourceNames(), incrementally update it as you add resources, and keep passing it
846   - // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time
847   - // it's called.
848   - QPDF_DLL
849   - std::string getUniqueResourceName(
850   - std::string const& prefix,
851   - int& min_suffix,
852   - std::set<std::string>* resource_names = nullptr) const;
853   -
854   - // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
855   - // object. Indirect objects always have an owning QPDF. Direct objects that are read from the
856   - // input source will also have an owning QPDF. Programmatically created objects will only have
857   - // one if setObjectDescription was called.
858   - //
859   - // When the QPDF object that owns an object is destroyed, the object is changed into a null, and
860   - // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the
861   - // life of the QPDF. If in doubt, ask for it each time you need it.
862   -
863   - // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it
864   - // returns a null pointer. Use this when you are able to handle the case of an object that
865   - // doesn't have an owning QPDF.
866   - QPDF_DLL
867   - QPDF* getOwningQPDF() const;
868   - // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a
869   - // runtime_error. Use this when you know the object has to have an owning QPDF, such as when
870   - // it's a known indirect object. Since streams are always indirect objects, this method can be
871   - // used safely for streams. If error_msg is specified, it will be used at the contents of the
872   - // runtime_error if there is now owner.
873   - QPDF_DLL
874   - QPDF& getQPDF(std::string const& error_msg = "") const;
875   -
876   - // Create a shallow copy of an object as a direct object, but do not traverse across indirect
877   - // object boundaries. That means that, for dictionaries and arrays, any keys or items that were
878   - // indirect objects will still be indirect objects that point to the same place. In the
879   - // strictest sense, this is not a shallow copy because it recursively descends arrays and
880   - // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You
881   - // can't copy a stream this way. See copyStream() instead.
882   - QPDF_DLL
883   - QPDFObjectHandle shallowCopy();
884   -
885   - // Create a true shallow copy of an array or dictionary, just copying the immediate items
886   - // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in
887   - // the copy, you are modifying the original, which is almost never what you want. However, if
888   - // your intention is merely to *replace* top-level items or keys and not to modify lower-level
889   - // items in the copy, this method is much faster than shallowCopy().
890   - QPDF_DLL
891   - QPDFObjectHandle unsafeShallowCopy();
892   -
893   - // Create a copy of this stream. The new stream and the old stream are independent: after the
894   - // copy, either the original or the copy's dictionary or data can be modified without affecting
895   - // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's
896   - // data are made. If the source stream's data is already being provided by a StreamDataProvider,
897   - // the new stream will use the same one, so you have to make sure your StreamDataProvider can
898   - // handle that case. But if you're already using a StreamDataProvider, you probably don't need
899   - // to call this method.
900   - QPDF_DLL
901   - QPDFObjectHandle copyStream();
902   -
903   - // Mutator methods.
904   -
905   - // Since qpdf 11: for mutators that may add or remove an item, there are additional versions
906   - // whose names contain "AndGet" that return the added or removed item. For example:
907   - //
908   - // auto new_dict = dict.replaceKeyAndGetNew(
909   - // "/New", QPDFObjectHandle::newDictionary());
910   - //
911   - // auto old_value = dict.replaceKeyAndGetOld(
912   - // "/New", "(something)"_qpdf);
913   -
914   - // Recursively copy this object, making it direct. An exception is thrown if a loop is detected.
915   - // With allow_streams true, keep indirect object references to streams. Otherwise, throw an
916   - // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream
917   - // is found, the resulting object is still associated with the containing qpdf. When
918   - // allow_streams is false, the object will no longer be connected to the original QPDF object
919   - // after this call completes successfully.
920   - QPDF_DLL
921   - void makeDirect(bool allow_streams = false);
922   -
923   - // Mutator methods for array objects
924   - QPDF_DLL
925   - void setArrayItem(int, QPDFObjectHandle const&);
926   - QPDF_DLL
927   - void setArrayFromVector(std::vector<QPDFObjectHandle> const& items);
928   - // Insert an item before the item at the given position ("at") so that it has that position
929   - // after insertion. If "at" is equal to the size of the array, insert the item at the end.
930   - QPDF_DLL
931   - void insertItem(int at, QPDFObjectHandle const& item);
932   - // Like insertItem but return the item that was inserted.
933   - QPDF_DLL
934   - QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item);
935   - // Append an item to an array.
936   - QPDF_DLL
937   - void appendItem(QPDFObjectHandle const& item);
938   - // Append an item, and return the newly added item.
939   - QPDF_DLL
940   - QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item);
941   - // Remove the item at that position, reducing the size of the array by one.
942   - QPDF_DLL
943   - void eraseItem(int at);
944   - // Erase and item and return the item that was removed.
945   - QPDF_DLL
946   - QPDFObjectHandle eraseItemAndGetOld(int at);
947   -
948   - // Mutator methods for dictionary objects
949   -
950   - // Replace value of key, adding it if it does not exist. If value is null, remove the key.
951   - QPDF_DLL
952   - void replaceKey(std::string const& key, QPDFObjectHandle const& value);
953   - // Replace value of key and return the value.
954   - QPDF_DLL
955   - QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value);
956   - // Replace value of key and return the old value, or null if the key was previously not present.
957   - QPDF_DLL
958   - QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value);
959   - // Remove key, doing nothing if key does not exist.
960   - QPDF_DLL
961   - void removeKey(std::string const& key);
962   - // Remove key and return the old value. If the old value didn't exist, return a null object.
963   - QPDF_DLL
964   - QPDFObjectHandle removeKeyAndGetOld(std::string const& key);
965   -
966   - // ABI: Remove in qpdf 12
967   - [[deprecated("use replaceKey -- it does the same thing")]] QPDF_DLL void
968   - replaceOrRemoveKey(std::string const& key, QPDFObjectHandle const&);
969   -
970   - // Methods for stream objects
971   - QPDF_DLL
972   - QPDFObjectHandle getDict() const;
973   -
974   - // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
975   - // level, whether compression is enabled, and its ability to filter. Passing false will prevent
976   - // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding
977   - // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and
978   - // recompressing a stream that it knows how to operate on for any application-specific reason,
979   - // such as that you have already optimized its filtering. Note that this doesn't affect any
980   - // other ways to get the stream's data, such as pipeStreamData or getStreamData.
981   - QPDF_DLL
982   - void setFilterOnWrite(bool);
983   - QPDF_DLL
984   - bool getFilterOnWrite();
985   -
986   - // If addTokenFilter has been called for this stream, then the original data should be
987   - // considered to be modified. This means we should avoid optimizations such as not filtering a
988   - // stream that is already compressed.
989   - QPDF_DLL
990   - bool isDataModified();
991   -
992   - // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered
993   - // and we can't decode it.
994   - QPDF_DLL
995   - std::shared_ptr<Buffer> getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
996   -
997   - // Returns unfiltered (raw) stream data.
998   - QPDF_DLL
999   - std::shared_ptr<Buffer> getRawStreamData();
1000   -
1001   - // Write stream data through the given pipeline. A null pipeline value may be used if all you
1002   - // want to do is determine whether a stream is filterable and would be filtered based on the
1003   - // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags
1004   - // alter the behavior in the following way:
1005   - //
1006   - // encode_flags:
1007   - //
1008   - // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are
1009   - // applied.
1010   - //
1011   - // qpdf_sf_normalize -- tokenize as content stream and normalize tokens
1012   - //
1013   - // decode_level:
1014   - //
1015   - // qpdf_dl_none -- do not decode any streams.
1016   - //
1017   - // qpdf_dl_generalized -- decode supported general-purpose filters. This includes
1018   - // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode.
1019   - //
1020   - // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy
1021   - // specialized filters. This includes /RunLengthDecode.
1022   - //
1023   - // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported
1024   - // lossy filters. This includes /DCTDecode.
1025   - //
1026   - // If, based on the flags and the filters and decode parameters, we determine that we know how
1027   - // to apply all requested filters, do so and return true if we are successful.
1028   - //
1029   - // The exact meaning of the return value differs the different versions of this function, but
1030   - // for any version, the meaning has been the same. For the main version, added in qpdf 10, the
1031   - // return value indicates whether the overall operation succeeded. The filter parameter, if
1032   - // specified, will be set to whether or not filtering was attempted. If filtering was not
1033   - // requested, this value will be false even if the overall operation succeeded.
1034   - //
1035   - // If filtering is requested but this method returns false, it means there was some error in the
1036   - // filtering, in which case the resulting data is likely partially filtered and/or incomplete
1037   - // and may not be consistent with the configured filters. QPDFWriter handles this by attempting
1038   - // to get the stream data without filtering, but callers should consider a false return value
1039   - // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry
1040   - // in that case, pass true as the value of will_retry. This changes the warning issued by the
1041   - // library to indicate that the operation will be retried without filtering to avoid data loss.
1042   -
1043   - // Return value is overall success, even if filtering is not requested.
1044   - QPDF_DLL
1045   - bool pipeStreamData(
1046   - Pipeline*,
1047   - bool* filtering_attempted,
1048   - int encode_flags,
1049   - qpdf_stream_decode_level_e decode_level,
1050   - bool suppress_warnings = false,
1051   - bool will_retry = false);
1052   -
1053   - // Legacy version. Return value is whether filtering was attempted. There is no way to determine
1054   - // success if filtering was not attempted.
1055   - QPDF_DLL
1056   - bool pipeStreamData(
1057   - Pipeline*,
1058   - int encode_flags,
1059   - qpdf_stream_decode_level_e decode_level,
1060   - bool suppress_warnings = false,
1061   - bool will_retry = false);
1062   -
1063   - // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows:
1064   - // filter = false -> encode_flags = 0
1065   - // filter = true -> decode_level = qpdf_dl_generalized
1066   - // normalize = true -> encode_flags |= qpdf_sf_normalize
1067   - // compress = true -> encode_flags |= qpdf_sf_compress
1068   - // Return value is whether filtering was attempted.
1069   - QPDF_DLL
1070   - bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress);
1071   -
1072   - // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data.
1073   - // This is most appropriately used when creating streams from scratch that will use a stream
1074   - // data provider and therefore start with an empty dictionary. It may be more convenient in
1075   - // this case than calling getDict and modifying it for each key. The pdf-create example does
1076   - // this.
1077   - QPDF_DLL
1078   - void replaceDict(QPDFObjectHandle const&);
1079   -
1080   - // REPLACING STREAM DATA
1081   -
1082   - // Note about all replaceStreamData methods: whatever values are passed as filter and
1083   - // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object
1084   - // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf
1085   - // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing
1086   - // values untouched.
1087   -
1088   - // Replace this stream's stream data with the given data buffer. The stream's /Length key is
1089   - // replaced with the length of the data buffer. The stream is interpreted as if the data read
1090   - // from the file, after any decryption filters have been applied, is as presented.
1091   - QPDF_DLL
1092   - void replaceStreamData(
1093   - std::shared_ptr<Buffer> data,
1094   - QPDFObjectHandle const& filter,
1095   - QPDFObjectHandle const& decode_parms);
1096   -
1097   - // Replace the stream's stream data with the given string. This method will create a copy of the
1098   - // data rather than using the user-provided buffer as in the std::shared_ptr<Buffer> version of
1099   - // replaceStreamData.
1100   - QPDF_DLL
1101   - void replaceStreamData(
1102   - std::string const& data,
1103   - QPDFObjectHandle const& filter,
1104   - QPDFObjectHandle const& decode_parms);
1105   -
1106   - // As above, replace this stream's stream data. Instead of directly providing a buffer with the
1107   - // stream data, call the given provider's provideStreamData method. See comments on the
1108   - // StreamDataProvider class (defined above) for details on the method. The data must be
1109   - // consistent with filter and decode_parms as provided. Although it is more complex to use this
1110   - // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid
1111   - // allocating memory for the stream data. Example programs are provided that use both forms of
1112   - // replaceStreamData.
1113   -
1114   - // Note about stream length: for any given stream, the provider must provide the same amount of
1115   - // data each time it is called. This is critical for making linearization work properly.
1116   - // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with
1117   - // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data
1118   - // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is
1119   - // enforced that the length be the same as the first time.
1120   -
1121   - // If you have gotten a compile error here while building code that worked with older versions
1122   - // of qpdf, just omit the length parameter. You can also simplify your code by not having to
1123   - // compute the length in advance.
1124   - QPDF_DLL
1125   - void replaceStreamData(
1126   - std::shared_ptr<StreamDataProvider> provider,
1127   - QPDFObjectHandle const& filter,
1128   - QPDFObjectHandle const& decode_parms);
1129   -
1130   - // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider.
1131   -
1132   - // The provider should write the stream data to the pipeline. For a one-liner to replace stream
1133   - // data with the contents of a file, pass QUtil::file_provider(filename) as provider.
1134   - QPDF_DLL
1135   - void replaceStreamData(
1136   - std::function<void(Pipeline*)> provider,
1137   - QPDFObjectHandle const& filter,
1138   - QPDFObjectHandle const& decode_parms);
1139   - // The provider should write the stream data to the pipeline, returning true if it succeeded
1140   - // without errors.
1141   - QPDF_DLL
1142   - void replaceStreamData(
1143   - std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)> provider,
1144   - QPDFObjectHandle const& filter,
1145   - QPDFObjectHandle const& decode_parms);
1146   -
1147   - // Access object ID and generation. For direct objects, return object ID 0.
1148   -
1149   - // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to
1150   - // the pattern of depending on object ID or generation without the other. In general, when
1151   - // keeping track of object IDs, it's better to use QPDFObjGen instead.
1152   -
1153   - QPDF_DLL
1154   - QPDFObjGen getObjGen() const;
1155   - QPDF_DLL
1156   - inline int getObjectID() const;
1157   - QPDF_DLL
1158   - inline int getGeneration() const;
1159   -
1160   - QPDF_DLL
1161   - std::string unparse() const;
1162   - QPDF_DLL
1163   - std::string unparseResolved() const;
1164   - // For strings only, force binary representation. Otherwise, same as unparse.
1165   - QPDF_DLL
1166   - std::string unparseBinary() const;
1167   -
1168   - // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
1169   - // JSON version. The JSON is generated as follows:
1170   - // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their
1171   - // native JSON types.
1172   - // * Names are encoded as strings representing the canonical representation (after parsing #xx)
1173   - // and preceded by a slash, just as unparse() returns. For example, the JSON for the
1174   - // PDF-syntax name /Text#2fPlain would be "/Text/Plain".
1175   - // * Indirect references are encoded as strings containing "obj gen R"
1176   - // * Strings
1177   - // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters
1178   - // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode
1179   - // mappings are not reversible. There is no way to tell the difference between a string that
1180   - // looks like a name or indirect object from an actual name or indirect object.
1181   - // * JSON v2:
1182   - // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally
1183   - // mapped to Unicode (which is all strings without undefined characters) are represented
1184   - // as "u:" followed by the UTF-8 encoded string. Example:
1185   - // "u:potato".
1186   - // * All other strings are represented as "b:" followed by a hexadecimal encoding of the
1187   - // string. Example: "b:0102cacb"
1188   - // * Streams
1189   - // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a
1190   - // dictionary other than context.
1191   - // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the
1192   - // stream's dictionary. Since "dict" does not otherwise represent anything, this is
1193   - // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data.
1194   - // * Object types that are only valid in content streams (inline image, operator) are serialized
1195   - // as "null". Attempting to serialize a "reserved" object is an error.
1196   - // If dereference_indirect is true and this is an indirect object, show the actual contents of
1197   - // the object. The effect of dereference_indirect applies only to this object. It is not
1198   - // recursive.
1199   - QPDF_DLL
1200   - JSON getJSON(int json_version, bool dereference_indirect = false) const;
1201   -
1202   - // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
1203   - // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
1204   - // documentation for getJSON and JSON::write for further detail.
1205   - QPDF_DLL
1206   - void writeJSON(
1207   - int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
1208   -
1209   - // Deprecated version uses v1 for backward compatibility.
1210   - // ABI: remove for qpdf 12
1211   - [[deprecated("Use getJSON(int version)")]] QPDF_DLL JSON
1212   - getJSON(bool dereference_indirect = false) const;
1213   -
1214   - // This method can be called on a stream to get a more extended JSON representation of the
1215   - // stream that includes the stream's data. The JSON object returned is always a dictionary whose
1216   - // "dict" key is an encoding of the stream's dictionary. The representation of the data is
1217   - // determined by the json_data field.
1218   - //
1219   - // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file.
1220   - //
1221   - // If json_data is qpdf_sj_none, stream data is not represented.
1222   - //
1223   - // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on
1224   - // the value of decode_level, which has the same meaning as with pipeStreamData.
1225   - //
1226   - // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data"
1227   - // field of the dictionary that is returned.
1228   - //
1229   - // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be
1230   - // supplied. The value of data_filename is stored in the resulting json in the "datafile" key
1231   - // but is not otherwise use. The stream data itself (raw or filtered depending on decode level),
1232   - // is written to the pipeline via pipeStreamData().
1233   - //
1234   - // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must
1235   - // remain valid until after the JSON object is written.
1236   - QPDF_DLL
1237   - JSON getStreamJSON(
1238   - int json_version,
1239   - qpdf_json_stream_data_e json_data,
1240   - qpdf_stream_decode_level_e decode_level,
1241   - Pipeline* p,
1242   - std::string const& data_filename);
1243   -
1244   - // Legacy helper methods for commonly performed operations on pages. Newer code should use
1245   - // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as
1246   - // the identically named methods in that class, but newer functionality will be added there.
1247   - QPDF_DLL
1248   - std::map<std::string, QPDFObjectHandle> getPageImages();
1249   - QPDF_DLL
1250   - std::vector<QPDFObjectHandle> getPageContents();
1251   - QPDF_DLL
1252   - void addPageContents(QPDFObjectHandle contents, bool first);
1253   - QPDF_DLL
1254   - void rotatePage(int angle, bool relative);
1255   - QPDF_DLL
1256   - void coalesceContentStreams();
1257   - // End legacy page helpers
1258   -
1259   - // Issue a warning about this object if possible. If the object has a description, a warning
1260   - // will be issued using the owning QPDF as context. Otherwise, a message will be written to the
1261   - // default logger's error stream, which is standard error if not overridden. Objects read
1262   - // normally from the file have descriptions. See comments on setObjectDescription for additional
1263   - // details.
1264   - QPDF_DLL
1265   - void warnIfPossible(std::string const& warning) const;
1266   -
1267   - // Provide access to specific classes for recursive disconnected().
1268   - class DisconnectAccess
1269   - {
1270   - friend class QPDF_Dictionary;
1271   - friend class QPDF_Stream;
1272   -
1273   - private:
1274   - static void
1275   - disconnect(QPDFObjectHandle o)
1276   - {
1277   - o.disconnect();
1278   - }
1279   - };
1280   -
1281   - // Convenience routine: Throws if the assumption is violated. Your code will be better if you
1282   - // call one of the isType methods and handle the case of the type being wrong, but these can be
1283   - // convenient if you have already verified the type.
1284   - QPDF_DLL
1285   - void assertInitialized() const;
1286   -
1287   - QPDF_DLL
1288   - void assertNull() const;
1289   - QPDF_DLL
1290   - void assertBool() const;
1291   - QPDF_DLL
1292   - void assertInteger() const;
1293   - QPDF_DLL
1294   - void assertReal() const;
1295   - QPDF_DLL
1296   - void assertName() const;
1297   - QPDF_DLL
1298   - void assertString() const;
1299   - QPDF_DLL
1300   - void assertOperator() const;
1301   - QPDF_DLL
1302   - void assertInlineImage() const;
1303   - QPDF_DLL
1304   - void assertArray() const;
1305   - QPDF_DLL
1306   - void assertDictionary() const;
1307   - QPDF_DLL
1308   - void assertStream() const;
1309   - QPDF_DLL
1310   - void assertReserved() const;
1311   -
1312   - QPDF_DLL
1313   - void assertIndirect() const;
1314   - QPDF_DLL
1315   - void assertScalar() const;
1316   - QPDF_DLL
1317   - void assertNumber() const;
1318   -
1319   - // The isPageObject method checks the /Type key of the object. This is not completely reliable
1320   - // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
1321   - // slightly more accepting but may still return false here when treating the object as a page
1322   - // would work. Use this sparingly.
1323   - QPDF_DLL
1324   - bool isPageObject() const;
1325   - QPDF_DLL
1326   - bool isPagesObject() const;
1327   - QPDF_DLL
1328   - void assertPageObject() const;
1329   -
1330   - QPDF_DLL
1331   - bool isFormXObject() const;
1332   -
1333   - // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
1334   - // images.
1335   - QPDF_DLL
1336   - bool isImage(bool exclude_imagemask = true) const;
1337   -
1338   - // The following methods do not form part of the public API and are for internal use only.
1339   -
1340   - QPDFObjectHandle(std::shared_ptr<QPDFObject> const& obj) :
1341   - obj(obj)
1342   - {
1343   - }
1344   - std::shared_ptr<QPDFObject>
1345   - getObj()
1346   - {
1347   - return obj;
1348   - }
1349   - std::shared_ptr<QPDFObject>
1350   - getObj() const
1351   - {
1352   - return obj;
1353   - }
1354   - QPDFObject*
1355   - getObjectPtr()
1356   - {
1357   - return obj.get();
1358   - }
1359   - QPDFObject* const
1360   - getObjectPtr() const
1361   - {
1362   - return obj.get();
1363   - }
1364   -
1365   - void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
1366   -
1367   - private:
1368   - QPDF_Array* asArray() const;
1369   - QPDF_Bool* asBool() const;
1370   - QPDF_Dictionary* asDictionary() const;
1371   - QPDF_InlineImage* asInlineImage() const;
1372   - QPDF_Integer* asInteger() const;
1373   - QPDF_Name* asName() const;
1374   - QPDF_Null* asNull() const;
1375   - QPDF_Operator* asOperator() const;
1376   - QPDF_Real* asReal() const;
1377   - QPDF_Reserved* asReserved() const;
1378   - QPDF_Stream* asStream() const;
1379   - QPDF_Stream* asStreamWithAssert() const;
1380   - QPDF_String* asString() const;
1381   -
1382   - void typeWarning(char const* expected_type, std::string const& warning) const;
1383   - void objectWarning(std::string const& warning) const;
1384   - void assertType(char const* type_name, bool istype) const;
1385   - void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
1386   - void disconnect();
1387   - void setParsedOffset(qpdf_offset_t offset);
1388   - void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
1389   - static void parseContentStream_data(
1390   - std::shared_ptr<Buffer>,
1391   - std::string const& description,
1392   - ParserCallbacks* callbacks,
1393   - QPDF* context);
1394   - std::vector<QPDFObjectHandle>
1395   - arrayOrStreamToStreamArray(std::string const& description, std::string& all_description);
1396   - static void warn(QPDF*, QPDFExc const&);
1397   - void checkOwnership(QPDFObjectHandle const&) const;
1398   -
1399   - // Moving members of QPDFObjectHandle into a smart pointer incurs a substantial performance
1400   - // penalty since QPDFObjectHandle objects are copied around so frequently.
1401   - std::shared_ptr<QPDFObject> obj;
1402   -};
1403   -
1404   -#ifndef QPDF_NO_QPDF_STRING
1405   -// This is short for QPDFObjectHandle::parse, so you can do
1406   -
1407   -// auto oh = "<< /Key (value) >>"_qpdf;
1408   -
1409   -// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration
1410   -// from being here.
1411   -
1412   -/* clang-format off */
1413   - // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
1414   - // of the file as a string if clang-format removes the space after "operator", and as of
1415   - // clang-format 15, there's no way to prevent it from doing so.
1416   - QPDF_DLL
1417   - QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
1418   -/* clang-format on */
1419   -
1420   -#endif // QPDF_NO_QPDF_STRING
1421   -
1422   -class QPDFObjectHandle::QPDFDictItems
1423   -{
1424   - // This class allows C++-style iteration, including range-for iteration, around dictionaries.
1425   - // You can write
1426   -
1427   - // for (auto iter: QPDFDictItems(dictionary_obj))
1428   - // {
1429   - // // iter.first is a string
1430   - // // iter.second is a QPDFObjectHandle
1431   - // }
1432   -
1433   - // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1434   -
1435   - public:
1436   - QPDF_DLL
1437   - QPDFDictItems(QPDFObjectHandle const& oh);
1438   -
1439   - class iterator
1440   - {
1441   - friend class QPDFDictItems;
1442   -
1443   - public:
1444   - typedef std::pair<std::string, QPDFObjectHandle> T;
1445   - using iterator_category = std::bidirectional_iterator_tag;
1446   - using value_type = T;
1447   - using difference_type = long;
1448   - using pointer = T*;
1449   - using reference = T&;
1450   -
1451   - QPDF_DLL
1452   - virtual ~iterator() = default;
1453   - QPDF_DLL
1454   - iterator& operator++();
1455   - QPDF_DLL
1456   - iterator
1457   - operator++(int)
1458   - {
1459   - iterator t = *this;
1460   - ++(*this);
1461   - return t;
1462   - }
1463   - QPDF_DLL
1464   - iterator& operator--();
1465   - QPDF_DLL
1466   - iterator
1467   - operator--(int)
1468   - {
1469   - iterator t = *this;
1470   - --(*this);
1471   - return t;
1472   - }
1473   - QPDF_DLL
1474   - reference operator*();
1475   - QPDF_DLL
1476   - pointer operator->();
1477   - QPDF_DLL
1478   - bool operator==(iterator const& other) const;
1479   - QPDF_DLL
1480   - bool
1481   - operator!=(iterator const& other) const
1482   - {
1483   - return !operator==(other);
1484   - }
1485   -
1486   - private:
1487   - iterator(QPDFObjectHandle& oh, bool for_begin);
1488   - void updateIValue();
1489   -
1490   - class Members
1491   - {
1492   - friend class QPDFDictItems::iterator;
1493   -
1494   - public:
1495   - QPDF_DLL
1496   - ~Members() = default;
1497   -
1498   - private:
1499   - Members(QPDFObjectHandle& oh, bool for_begin);
1500   - Members() = delete;
1501   - Members(Members const&) = delete;
1502   -
1503   - QPDFObjectHandle& oh;
1504   - std::set<std::string> keys;
1505   - std::set<std::string>::iterator iter;
1506   - bool is_end;
1507   - };
1508   - std::shared_ptr<Members> m;
1509   - value_type ivalue;
1510   - };
1511   -
1512   - QPDF_DLL
1513   - iterator begin();
1514   - QPDF_DLL
1515   - iterator end();
1516   -
1517   - private:
1518   - QPDFObjectHandle oh;
1519   -};
1520   -
1521   -class QPDFObjectHandle::QPDFArrayItems
1522   -{
1523   - // This class allows C++-style iteration, including range-for iteration, around arrays. You can
1524   - // write
1525   -
1526   - // for (auto iter: QPDFArrayItems(array_obj))
1527   - // {
1528   - // // iter is a QPDFObjectHandle
1529   - // }
1530   -
1531   - // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1532   -
1533   - public:
1534   - QPDF_DLL
1535   - QPDFArrayItems(QPDFObjectHandle const& oh);
1536   -
1537   - class iterator
1538   - {
1539   - friend class QPDFArrayItems;
1540   -
1541   - public:
1542   - typedef QPDFObjectHandle T;
1543   - using iterator_category = std::bidirectional_iterator_tag;
1544   - using value_type = T;
1545   - using difference_type = long;
1546   - using pointer = T*;
1547   - using reference = T&;
1548   -
1549   - QPDF_DLL
1550   - virtual ~iterator() = default;
1551   - QPDF_DLL
1552   - iterator& operator++();
1553   - QPDF_DLL
1554   - iterator
1555   - operator++(int)
1556   - {
1557   - iterator t = *this;
1558   - ++(*this);
1559   - return t;
1560   - }
1561   - QPDF_DLL
1562   - iterator& operator--();
1563   - QPDF_DLL
1564   - iterator
1565   - operator--(int)
1566   - {
1567   - iterator t = *this;
1568   - --(*this);
1569   - return t;
1570   - }
1571   - QPDF_DLL
1572   - reference operator*();
1573   - QPDF_DLL
1574   - pointer operator->();
1575   - QPDF_DLL
1576   - bool operator==(iterator const& other) const;
1577   - QPDF_DLL
1578   - bool
1579   - operator!=(iterator const& other) const
1580   - {
1581   - return !operator==(other);
1582   - }
1583   -
1584   - private:
1585   - iterator(QPDFObjectHandle& oh, bool for_begin);
1586   - void updateIValue();
1587   -
1588   - class Members
1589   - {
1590   - friend class QPDFArrayItems::iterator;
1591   -
1592   - public:
1593   - QPDF_DLL
1594   - ~Members() = default;
1595   -
1596   - private:
1597   - Members(QPDFObjectHandle& oh, bool for_begin);
1598   - Members() = delete;
1599   - Members(Members const&) = delete;
1600   -
1601   - QPDFObjectHandle& oh;
1602   - int item_number;
1603   - bool is_end;
1604   - };
1605   - std::shared_ptr<Members> m;
1606   - value_type ivalue;
1607   - };
1608   -
1609   - QPDF_DLL
1610   - iterator begin();
1611   - QPDF_DLL
1612   - iterator end();
1613   -
1614   - private:
1615   - QPDFObjectHandle oh;
1616   -};
1617   -
1618   -inline int
1619   -QPDFObjectHandle::getObjectID() const
1620   -{
1621   - return getObjGen().getObj();
1622   -}
1623   -
1624   -inline int
1625   -QPDFObjectHandle::getGeneration() const
1626   -{
1627   - return getObjGen().getGen();
1628   -}
1629   -
1630   -inline bool
1631   -QPDFObjectHandle::isIndirect() const
1632   -{
1633   - return (obj != nullptr) && (getObjectID() != 0);
1634   -}
1635   -
1636   -inline bool
1637   -QPDFObjectHandle::isInitialized() const noexcept
1638   -{
1639   - return obj != nullptr;
1640   -}
1641   -
1642   -inline QPDFObjectHandle::
1643   -operator bool() const noexcept
1644   -{
1645   - return static_cast<bool>(obj);
1646   -}
1647   -
1648   -#endif // QPDFOBJECTHANDLE_FUTURE_HH
include/qpdf/QPDFOutlineDocumentHelper.hh
... ... @@ -58,16 +58,14 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
58 58  
59 59 // Return a list outlines that are known to target the specified page.
60 60 QPDF_DLL
61   - std::vector<QPDFOutlineObjectHelper> getOutlinesForPage(QPDFObjGen const&);
  61 + std::vector<QPDFOutlineObjectHelper> getOutlinesForPage(QPDFObjGen);
62 62  
63 63 class Accessor
64 64 {
65 65 friend class QPDFOutlineObjectHelper;
66 66  
67   - // ABI: remove QPDF_DLL and pass og by value.
68   - QPDF_DLL
69 67 static bool
70   - checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen const& og)
  68 + checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og)
71 69 {
72 70 return !dh.m->seen.add(og);
73 71 }
... ...
include/qpdf/QPDFWriter.hh
... ... @@ -485,7 +485,7 @@ class QPDFWriter
485 485 void writeStringQDF(std::string_view str);
486 486 void writeStringNoQDF(std::string_view str);
487 487 void writePad(size_t nspaces);
488   - void assignCompressedObjectNumbers(QPDFObjGen const& og);
  488 + void assignCompressedObjectNumbers(QPDFObjGen og);
489 489 void enqueueObject(QPDFObjectHandle object);
490 490 void writeObjectStreamOffsets(std::vector<qpdf_offset_t>& offsets, int first_obj);
491 491 void writeObjectStream(QPDFObjectHandle object);
... ...
job.sums
1 1 # Generated by generate_auto_job
2   -CMakeLists.txt e08751e992a61aee8a2944c98c4a2c7574edc1138133f81b5a3340512da0f24c
  2 +CMakeLists.txt f0819695e4867e4f4389d38b0c124e79aa3ec9ace50f16ad8c751ff7f1ec6690
3 3 generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86
4 4 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
5 5 include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
... ... @@ -16,5 +16,5 @@ libqpdf/qpdf/auto_job_json_init.hh 344c2fb473f88fe829c93b1efe6c70a0e4796537b8eb3
16 16 libqpdf/qpdf/auto_job_schema.hh 6d3eef5137b8828eaa301a1b3cf75cb7bb812aa6e2d8301de865b42d238d7a7c
17 17 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
18 18 manual/cli.rst 67357688f9a52fafa9a4f231fe4ce74c3cd8977130da7501efe54439a1ee22d4
19   -manual/qpdf.1 50102b93fd9afa8d605702ff2d19440dbed369c1c4660f14b71a4a162227c58e
  19 +manual/qpdf.1 78bad33f9b3f246f1800bce365f7be06d3545d89f08b8923dd8489031b5af43e
20 20 manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b
... ...
libqpdf/Buffer.cc
... ... @@ -4,16 +4,23 @@
4 4  
5 5 #include <cstring>
6 6  
7   -bool test_mode = false;
8   -
9   -// During CI the Buffer copy constructor and copy assignment operator throw an assertion error to
10   -// detect their accidental use. Call setTestMode to surpress the assertion errors for testing of
11   -// copy construction and assignment.
12   -void
13   -Buffer::setTestMode() noexcept
  7 +class Buffer::Members
14 8 {
15   - test_mode = true;
16   -}
  9 + friend class Buffer;
  10 +
  11 + public:
  12 + ~Members();
  13 +
  14 + private:
  15 + Members(size_t size, unsigned char* buf, bool own_memory);
  16 + Members(std::string&& content);
  17 + Members(Members const&) = delete;
  18 +
  19 + std::string str;
  20 + bool own_memory;
  21 + size_t size;
  22 + unsigned char* buf;
  23 +};
17 24  
18 25 Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) :
19 26 own_memory(own_memory),
... ... @@ -67,20 +74,6 @@ Buffer::Buffer(std::string&amp; content) :
67 74 {
68 75 }
69 76  
70   -Buffer::Buffer(Buffer const& rhs)
71   -{
72   - assert(test_mode);
73   - copy(rhs);
74   -}
75   -
76   -Buffer&
77   -Buffer::operator=(Buffer const& rhs)
78   -{
79   - assert(test_mode);
80   - copy(rhs);
81   - return *this;
82   -}
83   -
84 77 Buffer::Buffer(Buffer&& rhs) noexcept :
85 78 m(std::move(rhs.m))
86 79 {
... ... @@ -93,6 +86,8 @@ Buffer::operator=(Buffer&amp;&amp; rhs) noexcept
93 86 return *this;
94 87 }
95 88  
  89 +Buffer::~Buffer() = default;
  90 +
96 91 void
97 92 Buffer::copy(Buffer const& rhs)
98 93 {
... ...
libqpdf/QPDF.cc
... ... @@ -112,7 +112,7 @@ namespace
112 112 QPDF::ForeignStreamData::ForeignStreamData(
113 113 std::shared_ptr<EncryptionParameters> encp,
114 114 std::shared_ptr<InputSource> file,
115   - QPDFObjGen const& foreign_og,
  115 + QPDFObjGen foreign_og,
116 116 qpdf_offset_t offset,
117 117 size_t length,
118 118 QPDFObjectHandle local_dict) :
... ... @@ -164,7 +164,7 @@ QPDF::CopiedStreamDataProvider::registerForeignStream(
164 164 this->foreign_stream_data[local_og] = foreign_stream;
165 165 }
166 166  
167   -QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) :
  167 +QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen og) :
168 168 qpdf(qpdf),
169 169 og(og)
170 170 {
... ... @@ -1463,7 +1463,7 @@ QPDF::getAllObjects()
1463 1463 }
1464 1464  
1465 1465 void
1466   -QPDF::setLastObjectDescription(std::string const& description, QPDFObjGen const& og)
  1466 +QPDF::setLastObjectDescription(std::string const& description, QPDFObjGen og)
1467 1467 {
1468 1468 m->last_object_description.clear();
1469 1469 if (!description.empty()) {
... ... @@ -1650,7 +1650,7 @@ QPDF::findEndstream()
1650 1650  
1651 1651 size_t
1652 1652 QPDF::recoverStreamLength(
1653   - std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset)
  1653 + std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset)
1654 1654 {
1655 1655 // Try to reconstruct stream length by looking for endstream or endobj
1656 1656 warn(damagedPDF(*input, stream_offset, "attempting to recover stream length"));
... ... @@ -2023,7 +2023,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
2023 2023 }
2024 2024  
2025 2025 QPDFObjectHandle
2026   -QPDF::newIndirect(QPDFObjGen const& og, std::shared_ptr<QPDFObject> const& obj)
  2026 +QPDF::newIndirect(QPDFObjGen og, std::shared_ptr<QPDFObject> const& obj)
2027 2027 {
2028 2028 obj->setDefaultDescription(this, og);
2029 2029 return {obj};
... ... @@ -2031,7 +2031,7 @@ QPDF::newIndirect(QPDFObjGen const&amp; og, std::shared_ptr&lt;QPDFObject&gt; const&amp; obj)
2031 2031  
2032 2032 void
2033 2033 QPDF::updateCache(
2034   - QPDFObjGen const& og,
  2034 + QPDFObjGen og,
2035 2035 std::shared_ptr<QPDFObject> const& object,
2036 2036 qpdf_offset_t end_before_space,
2037 2037 qpdf_offset_t end_after_space)
... ... @@ -2048,13 +2048,13 @@ QPDF::updateCache(
2048 2048 }
2049 2049  
2050 2050 bool
2051   -QPDF::isCached(QPDFObjGen const& og)
  2051 +QPDF::isCached(QPDFObjGen og)
2052 2052 {
2053 2053 return m->obj_cache.count(og) != 0;
2054 2054 }
2055 2055  
2056 2056 bool
2057   -QPDF::isUnresolved(QPDFObjGen const& og)
  2057 +QPDF::isUnresolved(QPDFObjGen og)
2058 2058 {
2059 2059 return !isCached(og) || m->obj_cache[og].object->isUnresolved();
2060 2060 }
... ... @@ -2152,7 +2152,7 @@ QPDF::getObjectForJSON(int id, int gen)
2152 2152 }
2153 2153  
2154 2154 QPDFObjectHandle
2155   -QPDF::getObject(QPDFObjGen const& og)
  2155 +QPDF::getObject(QPDFObjGen og)
2156 2156 {
2157 2157 if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) {
2158 2158 return {it->second.object};
... ... @@ -2171,7 +2171,7 @@ QPDF::getObject(int objid, int generation)
2171 2171 }
2172 2172  
2173 2173 QPDFObjectHandle
2174   -QPDF::getObjectByObjGen(QPDFObjGen const& og)
  2174 +QPDF::getObjectByObjGen(QPDFObjGen og)
2175 2175 {
2176 2176 return getObject(og);
2177 2177 }
... ... @@ -2189,7 +2189,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2189 2189 }
2190 2190  
2191 2191 void
2192   -QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
  2192 +QPDF::replaceObject(QPDFObjGen og, QPDFObjectHandle oh)
2193 2193 {
2194 2194 if (!oh || (oh.isIndirect() && !(oh.isStream() && oh.getObjGen() == og))) {
2195 2195 QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
... ... @@ -2493,7 +2493,7 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
2493 2493 }
2494 2494  
2495 2495 void
2496   -QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
  2496 +QPDF::swapObjects(QPDFObjGen og1, QPDFObjGen og2)
2497 2497 {
2498 2498 // Force objects to be read from the input source if needed, then swap them in the cache.
2499 2499 resolve(og1);
... ... @@ -2727,7 +2727,7 @@ QPDF::pipeStreamData(
2727 2727 std::shared_ptr<EncryptionParameters> encp,
2728 2728 std::shared_ptr<InputSource> file,
2729 2729 QPDF& qpdf_for_warning,
2730   - QPDFObjGen const& og,
  2730 + QPDFObjGen og,
2731 2731 qpdf_offset_t offset,
2732 2732 size_t length,
2733 2733 QPDFObjectHandle stream_dict,
... ... @@ -2789,7 +2789,7 @@ QPDF::pipeStreamData(
2789 2789  
2790 2790 bool
2791 2791 QPDF::pipeStreamData(
2792   - QPDFObjGen const& og,
  2792 + QPDFObjGen og,
2793 2793 qpdf_offset_t offset,
2794 2794 size_t length,
2795 2795 QPDFObjectHandle stream_dict,
... ...
libqpdf/QPDFNumberTreeObjectHelper.cc
... ... @@ -218,7 +218,7 @@ QPDFNumberTreeObjectHelper::findObjectAtOrBelow(
218 218 return false;
219 219 }
220 220 oh = i->second;
221   - QIntC::range_check_substract(idx, i->first);
  221 + QIntC::range_check_subtract(idx, i->first);
222 222 offset = idx - i->first;
223 223 return true;
224 224 }
... ...
libqpdf/QPDFObjGen.cc
... ... @@ -6,21 +6,6 @@
6 6  
7 7 #include <stdexcept>
8 8  
9   -// ABI: inline and pass og by value
10   -std::ostream&
11   -operator<<(std::ostream& os, const QPDFObjGen& og)
12   -{
13   - os << og.obj << "," << og.gen;
14   - return os;
15   -}
16   -
17   -// ABI: inline
18   -std::string
19   -QPDFObjGen::unparse(char separator) const
20   -{
21   - return std::to_string(obj) + separator + std::to_string(gen);
22   -}
23   -
24 9 bool
25 10 QPDFObjGen::set::add(QPDFObjectHandle const& oh)
26 11 {
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -221,19 +221,11 @@ LastChar::getLastChar()
221 221 return this->last_char;
222 222 }
223 223  
224   -#ifndef QPDF_FUTURE
225   -bool
226   -QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const
227   -{
228   - return this->obj == rhs.obj;
229   -}
230   -#else
231 224 bool
232 225 QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const noexcept
233 226 {
234 227 return this->obj == rhs.obj;
235 228 }
236   -#endif
237 229 void
238 230 QPDFObjectHandle::disconnect()
239 231 {
... ... @@ -245,24 +237,14 @@ QPDFObjectHandle::disconnect()
245 237 }
246 238 }
247 239  
248   -#ifndef QPDF_FUTURE
249   -qpdf_object_type_e
250   -QPDFObjectHandle::getTypeCode()
251   -#else
252 240 qpdf_object_type_e
253 241 QPDFObjectHandle::getTypeCode() const
254   -#endif
255 242 {
256 243 return obj ? obj->getResolvedTypeCode() : ::ot_uninitialized;
257 244 }
258 245  
259   -#ifndef QPDF_FUTURE
260   -char const*
261   -QPDFObjectHandle::getTypeName()
262   -#else
263 246 char const*
264 247 QPDFObjectHandle::getTypeName() const
265   -#endif
266 248 {
267 249 static constexpr std::array<char const*, 15> tn{
268 250 "uninitialized",
... ... @@ -363,24 +345,14 @@ QPDFObjectHandle::asString() const
363 345 return obj ? obj->as<QPDF_String>() : nullptr;
364 346 }
365 347  
366   -#ifndef QPDF_FUTURE
367   -bool
368   -QPDFObjectHandle::isDestroyed()
369   -#else
370 348 bool
371 349 QPDFObjectHandle::isDestroyed() const
372   -#endif
373 350 {
374 351 return obj && obj->getResolvedTypeCode() == ::ot_destroyed;
375 352 }
376 353  
377   -#ifndef QPDF_FUTURE
378   -bool
379   -QPDFObjectHandle::isBool()
380   -#else
381 354 bool
382 355 QPDFObjectHandle::isBool() const
383   -#endif
384 356 {
385 357 return obj && obj->getResolvedTypeCode() == ::ot_boolean;
386 358 }
... ... @@ -393,57 +365,32 @@ QPDFObjectHandle::isDirectNull() const
393 365 return (obj && getObjectID() == 0 && obj->getTypeCode() == ::ot_null);
394 366 }
395 367  
396   -#ifndef QPDF_FUTURE
397   -bool
398   -QPDFObjectHandle::isNull()
399   -#else
400 368 bool
401 369 QPDFObjectHandle::isNull() const
402   -#endif
403 370 {
404 371 return obj && obj->getResolvedTypeCode() == ::ot_null;
405 372 }
406 373  
407   -#ifndef QPDF_FUTURE
408   -bool
409   -QPDFObjectHandle::isInteger()
410   -#else
411 374 bool
412 375 QPDFObjectHandle::isInteger() const
413   -#endif
414 376 {
415 377 return obj && obj->getResolvedTypeCode() == ::ot_integer;
416 378 }
417 379  
418   -#ifndef QPDF_FUTURE
419   -bool
420   -QPDFObjectHandle::isReal()
421   -#else
422 380 bool
423 381 QPDFObjectHandle::isReal() const
424   -#endif
425 382 {
426 383 return obj && obj->getResolvedTypeCode() == ::ot_real;
427 384 }
428 385  
429   -#ifndef QPDF_FUTURE
430   -bool
431   -QPDFObjectHandle::isNumber()
432   -#else
433 386 bool
434 387 QPDFObjectHandle::isNumber() const
435   -#endif
436 388 {
437 389 return (isInteger() || isReal());
438 390 }
439 391  
440   -#ifndef QPDF_FUTURE
441   -double
442   -QPDFObjectHandle::getNumericValue()
443   -#else
444 392 double
445 393 QPDFObjectHandle::getNumericValue() const
446   -#endif
447 394 {
448 395 if (isInteger()) {
449 396 return static_cast<double>(getIntValue());
... ... @@ -456,13 +403,8 @@ QPDFObjectHandle::getNumericValue() const
456 403 }
457 404 }
458 405  
459   -#ifndef QPDF_FUTURE
460   -bool
461   -QPDFObjectHandle::getValueAsNumber(double& value)
462   -#else
463 406 bool
464 407 QPDFObjectHandle::getValueAsNumber(double& value) const
465   -#endif
466 408 {
467 409 if (!isNumber()) {
468 410 return false;
... ... @@ -471,148 +413,83 @@ QPDFObjectHandle::getValueAsNumber(double&amp; value) const
471 413 return true;
472 414 }
473 415  
474   -#ifndef QPDF_FUTURE
475   -bool
476   -QPDFObjectHandle::isName()
477   -#else
478 416 bool
479 417 QPDFObjectHandle::isName() const
480   -#endif
481 418 {
482 419 return obj && obj->getResolvedTypeCode() == ::ot_name;
483 420 }
484 421  
485   -#ifndef QPDF_FUTURE
486   -bool
487   -QPDFObjectHandle::isString()
488   -#else
489 422 bool
490 423 QPDFObjectHandle::isString() const
491   -#endif
492 424 {
493 425 return obj && obj->getResolvedTypeCode() == ::ot_string;
494 426 }
495 427  
496   -#ifndef QPDF_FUTURE
497   -bool
498   -QPDFObjectHandle::isOperator()
499   -#else
500 428 bool
501 429 QPDFObjectHandle::isOperator() const
502   -#endif
503 430 {
504 431 return obj && obj->getResolvedTypeCode() == ::ot_operator;
505 432 }
506 433  
507   -#ifndef QPDF_FUTURE
508   -bool
509   -QPDFObjectHandle::isInlineImage()
510   -#else
511 434 bool
512 435 QPDFObjectHandle::isInlineImage() const
513   -#endif
514 436 {
515 437 return obj && obj->getResolvedTypeCode() == ::ot_inlineimage;
516 438 }
517 439  
518   -#ifndef QPDF_FUTURE
519   -bool
520   -QPDFObjectHandle::isArray()
521   -#else
522 440 bool
523 441 QPDFObjectHandle::isArray() const
524   -#endif
525 442 {
526 443 return obj && obj->getResolvedTypeCode() == ::ot_array;
527 444 }
528 445  
529   -#ifndef QPDF_FUTURE
530   -bool
531   -QPDFObjectHandle::isDictionary()
532   -#else
533 446 bool
534 447 QPDFObjectHandle::isDictionary() const
535   -#endif
536 448 {
537 449 return obj && obj->getResolvedTypeCode() == ::ot_dictionary;
538 450 }
539 451  
540   -#ifndef QPDF_FUTURE
541   -bool
542   -QPDFObjectHandle::isStream()
543   -#else
544 452 bool
545 453 QPDFObjectHandle::isStream() const
546   -#endif
547 454 {
548 455 return obj && obj->getResolvedTypeCode() == ::ot_stream;
549 456 }
550 457  
551   -#ifndef QPDF_FUTURE
552   -bool
553   -QPDFObjectHandle::isReserved()
554   -#else
555 458 bool
556 459 QPDFObjectHandle::isReserved() const
557   -#endif
558 460 {
559 461 return obj && obj->getResolvedTypeCode() == ::ot_reserved;
560 462 }
561 463  
562   -#ifndef QPDF_FUTURE
563   -bool
564   -QPDFObjectHandle::isScalar()
565   -#else
566 464 bool
567 465 QPDFObjectHandle::isScalar() const
568   -#endif
569 466 {
570 467 return isBool() || isInteger() || isName() || isNull() || isReal() || isString();
571 468 }
572 469  
573   -#ifndef QPDF_FUTURE
574   -bool
575   -QPDFObjectHandle::isNameAndEquals(std::string const& name)
576   -#else
577 470 bool
578 471 QPDFObjectHandle::isNameAndEquals(std::string const& name) const
579   -#endif
580 472 {
581 473 return isName() && (getName() == name);
582 474 }
583 475  
584   -#ifndef QPDF_FUTURE
585   -bool
586   -QPDFObjectHandle::isDictionaryOfType(std::string const& type, std::string const& subtype)
587   -#else
588 476 bool
589 477 QPDFObjectHandle::isDictionaryOfType(std::string const& type, std::string const& subtype) const
590   -#endif
591 478 {
592 479 return isDictionary() && (type.empty() || getKey("/Type").isNameAndEquals(type)) &&
593 480 (subtype.empty() || getKey("/Subtype").isNameAndEquals(subtype));
594 481 }
595 482  
596   -#ifndef QPDF_FUTURE
597   -bool
598   -QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& subtype)
599   -#else
600 483 bool
601 484 QPDFObjectHandle::isStreamOfType(std::string const& type, std::string const& subtype) const
602   -#endif
603 485 {
604 486 return isStream() && getDict().isDictionaryOfType(type, subtype);
605 487 }
606 488  
607 489 // Bool accessors
608 490  
609   -#ifndef QPDF_FUTURE
610   -bool
611   -QPDFObjectHandle::getBoolValue()
612   -#else
613 491 bool
614 492 QPDFObjectHandle::getBoolValue() const
615   -#endif
616 493 {
617 494 auto boolean = asBool();
618 495 if (boolean) {
... ... @@ -624,13 +501,8 @@ QPDFObjectHandle::getBoolValue() const
624 501 }
625 502 }
626 503  
627   -#ifndef QPDF_FUTURE
628   -bool
629   -QPDFObjectHandle::getValueAsBool(bool& value)
630   -#else
631 504 bool
632 505 QPDFObjectHandle::getValueAsBool(bool& value) const
633   -#endif
634 506 {
635 507 auto boolean = asBool();
636 508 if (boolean == nullptr) {
... ... @@ -642,13 +514,8 @@ QPDFObjectHandle::getValueAsBool(bool&amp; value) const
642 514  
643 515 // Integer accessors
644 516  
645   -#ifndef QPDF_FUTURE
646   -long long
647   -QPDFObjectHandle::getIntValue()
648   -#else
649 517 long long
650 518 QPDFObjectHandle::getIntValue() const
651   -#endif
652 519 {
653 520 auto integer = asInteger();
654 521 if (integer) {
... ... @@ -660,13 +527,8 @@ QPDFObjectHandle::getIntValue() const
660 527 }
661 528 }
662 529  
663   -#ifndef QPDF_FUTURE
664   -bool
665   -QPDFObjectHandle::getValueAsInt(long long& value)
666   -#else
667 530 bool
668 531 QPDFObjectHandle::getValueAsInt(long long& value) const
669   -#endif
670 532 {
671 533 auto integer = asInteger();
672 534 if (integer == nullptr) {
... ... @@ -676,13 +538,8 @@ QPDFObjectHandle::getValueAsInt(long long&amp; value) const
676 538 return true;
677 539 }
678 540  
679   -#ifndef QPDF_FUTURE
680   -int
681   -QPDFObjectHandle::getIntValueAsInt()
682   -#else
683 541 int
684 542 QPDFObjectHandle::getIntValueAsInt() const
685   -#endif
686 543 {
687 544 int result = 0;
688 545 long long v = getIntValue();
... ... @@ -700,13 +557,8 @@ QPDFObjectHandle::getIntValueAsInt() const
700 557 return result;
701 558 }
702 559  
703   -#ifndef QPDF_FUTURE
704   -bool
705   -QPDFObjectHandle::getValueAsInt(int& value)
706   -#else
707 560 bool
708 561 QPDFObjectHandle::getValueAsInt(int& value) const
709   -#endif
710 562 {
711 563 if (!isInteger()) {
712 564 return false;
... ... @@ -715,13 +567,8 @@ QPDFObjectHandle::getValueAsInt(int&amp; value) const
715 567 return true;
716 568 }
717 569  
718   -#ifndef QPDF_FUTURE
719   -unsigned long long
720   -QPDFObjectHandle::getUIntValue()
721   -#else
722 570 unsigned long long
723 571 QPDFObjectHandle::getUIntValue() const
724   -#endif
725 572 {
726 573 long long v = getIntValue();
727 574 if (v < 0) {
... ... @@ -733,13 +580,8 @@ QPDFObjectHandle::getUIntValue() const
733 580 }
734 581 }
735 582  
736   -#ifndef QPDF_FUTURE
737   -bool
738   -QPDFObjectHandle::getValueAsUInt(unsigned long long& value)
739   -#else
740 583 bool
741 584 QPDFObjectHandle::getValueAsUInt(unsigned long long& value) const
742   -#endif
743 585 {
744 586 if (!isInteger()) {
745 587 return false;
... ... @@ -748,13 +590,8 @@ QPDFObjectHandle::getValueAsUInt(unsigned long long&amp; value) const
748 590 return true;
749 591 }
750 592  
751   -#ifndef QPDF_FUTURE
752   -unsigned int
753   -QPDFObjectHandle::getUIntValueAsUInt()
754   -#else
755 593 unsigned int
756 594 QPDFObjectHandle::getUIntValueAsUInt() const
757   -#endif
758 595 {
759 596 long long v = getIntValue();
760 597 if (v < 0) {
... ... @@ -770,13 +607,8 @@ QPDFObjectHandle::getUIntValueAsUInt() const
770 607 }
771 608 }
772 609  
773   -#ifndef QPDF_FUTURE
774   -bool
775   -QPDFObjectHandle::getValueAsUInt(unsigned int& value)
776   -#else
777 610 bool
778 611 QPDFObjectHandle::getValueAsUInt(unsigned int& value) const
779   -#endif
780 612 {
781 613 if (!isInteger()) {
782 614 return false;
... ... @@ -787,13 +619,8 @@ QPDFObjectHandle::getValueAsUInt(unsigned int&amp; value) const
787 619  
788 620 // Real accessors
789 621  
790   -#ifndef QPDF_FUTURE
791   -std::string
792   -QPDFObjectHandle::getRealValue()
793   -#else
794 622 std::string
795 623 QPDFObjectHandle::getRealValue() const
796   -#endif
797 624 {
798 625 if (isReal()) {
799 626 return obj->getStringValue();
... ... @@ -804,13 +631,8 @@ QPDFObjectHandle::getRealValue() const
804 631 }
805 632 }
806 633  
807   -#ifndef QPDF_FUTURE
808   -bool
809   -QPDFObjectHandle::getValueAsReal(std::string& value)
810   -#else
811 634 bool
812 635 QPDFObjectHandle::getValueAsReal(std::string& value) const
813   -#endif
814 636 {
815 637 if (!isReal()) {
816 638 return false;
... ... @@ -821,13 +643,8 @@ QPDFObjectHandle::getValueAsReal(std::string&amp; value) const
821 643  
822 644 // Name accessors
823 645  
824   -#ifndef QPDF_FUTURE
825   -std::string
826   -QPDFObjectHandle::getName()
827   -#else
828 646 std::string
829 647 QPDFObjectHandle::getName() const
830   -#endif
831 648 {
832 649 if (isName()) {
833 650 return obj->getStringValue();
... ... @@ -838,13 +655,8 @@ QPDFObjectHandle::getName() const
838 655 }
839 656 }
840 657  
841   -#ifndef QPDF_FUTURE
842   -bool
843   -QPDFObjectHandle::getValueAsName(std::string& value)
844   -#else
845 658 bool
846 659 QPDFObjectHandle::getValueAsName(std::string& value) const
847   -#endif
848 660 {
849 661 if (!isName()) {
850 662 return false;
... ... @@ -855,13 +667,8 @@ QPDFObjectHandle::getValueAsName(std::string&amp; value) const
855 667  
856 668 // String accessors
857 669  
858   -#ifndef QPDF_FUTURE
859   -std::string
860   -QPDFObjectHandle::getStringValue()
861   -#else
862 670 std::string
863 671 QPDFObjectHandle::getStringValue() const
864   -#endif
865 672 {
866 673 if (isString()) {
867 674 return obj->getStringValue();
... ... @@ -872,13 +679,8 @@ QPDFObjectHandle::getStringValue() const
872 679 }
873 680 }
874 681  
875   -#ifndef QPDF_FUTURE
876   -bool
877   -QPDFObjectHandle::getValueAsString(std::string& value)
878   -#else
879 682 bool
880 683 QPDFObjectHandle::getValueAsString(std::string& value) const
881   -#endif
882 684 {
883 685 if (!isString()) {
884 686 return false;
... ... @@ -887,13 +689,8 @@ QPDFObjectHandle::getValueAsString(std::string&amp; value) const
887 689 return true;
888 690 }
889 691  
890   -#ifndef QPDF_FUTURE
891   -std::string
892   -QPDFObjectHandle::getUTF8Value()
893   -#else
894 692 std::string
895 693 QPDFObjectHandle::getUTF8Value() const
896   -#endif
897 694 {
898 695 auto str = asString();
899 696 if (str) {
... ... @@ -905,13 +702,8 @@ QPDFObjectHandle::getUTF8Value() const
905 702 }
906 703 }
907 704  
908   -#ifndef QPDF_FUTURE
909   -bool
910   -QPDFObjectHandle::getValueAsUTF8(std::string& value)
911   -#else
912 705 bool
913 706 QPDFObjectHandle::getValueAsUTF8(std::string& value) const
914   -#endif
915 707 {
916 708 auto str = asString();
917 709 if (str == nullptr) {
... ... @@ -923,13 +715,8 @@ QPDFObjectHandle::getValueAsUTF8(std::string&amp; value) const
923 715  
924 716 // Operator and Inline Image accessors
925 717  
926   -#ifndef QPDF_FUTURE
927   -std::string
928   -QPDFObjectHandle::getOperatorValue()
929   -#else
930 718 std::string
931 719 QPDFObjectHandle::getOperatorValue() const
932   -#endif
933 720 {
934 721 if (isOperator()) {
935 722 return obj->getStringValue();
... ... @@ -940,13 +727,8 @@ QPDFObjectHandle::getOperatorValue() const
940 727 }
941 728 }
942 729  
943   -#ifndef QPDF_FUTURE
944   -bool
945   -QPDFObjectHandle::getValueAsOperator(std::string& value)
946   -#else
947 730 bool
948 731 QPDFObjectHandle::getValueAsOperator(std::string& value) const
949   -#endif
950 732 {
951 733 if (!isOperator()) {
952 734 return false;
... ... @@ -955,13 +737,8 @@ QPDFObjectHandle::getValueAsOperator(std::string&amp; value) const
955 737 return true;
956 738 }
957 739  
958   -#ifndef QPDF_FUTURE
959   -std::string
960   -QPDFObjectHandle::getInlineImageValue()
961   -#else
962 740 std::string
963 741 QPDFObjectHandle::getInlineImageValue() const
964   -#endif
965 742 {
966 743 if (isInlineImage()) {
967 744 return obj->getStringValue();
... ... @@ -972,13 +749,8 @@ QPDFObjectHandle::getInlineImageValue() const
972 749 }
973 750 }
974 751  
975   -#ifndef QPDF_FUTURE
976   -bool
977   -QPDFObjectHandle::getValueAsInlineImage(std::string& value)
978   -#else
979 752 bool
980 753 QPDFObjectHandle::getValueAsInlineImage(std::string& value) const
981   -#endif
982 754 {
983 755 if (!isInlineImage()) {
984 756 return false;
... ... @@ -995,13 +767,8 @@ QPDFObjectHandle::aitems()
995 767 return *this;
996 768 }
997 769  
998   -#ifndef QPDF_FUTURE
999   -int
1000   -QPDFObjectHandle::getArrayNItems()
1001   -#else
1002 770 int
1003 771 QPDFObjectHandle::getArrayNItems() const
1004   -#endif
1005 772 {
1006 773 if (auto array = asArray()) {
1007 774 return array->size();
... ... @@ -1012,13 +779,8 @@ QPDFObjectHandle::getArrayNItems() const
1012 779 }
1013 780 }
1014 781  
1015   -#ifndef QPDF_FUTURE
1016   -QPDFObjectHandle
1017   -QPDFObjectHandle::getArrayItem(int n)
1018   -#else
1019 782 QPDFObjectHandle
1020 783 QPDFObjectHandle::getArrayItem(int n) const
1021   -#endif
1022 784 {
1023 785 if (auto array = asArray()) {
1024 786 auto result = array->at(n);
... ... @@ -1036,13 +798,8 @@ QPDFObjectHandle::getArrayItem(int n) const
1036 798 return QPDF_Null::create(obj, msg, "");
1037 799 }
1038 800  
1039   -#ifndef QPDF_FUTURE
1040   -bool
1041   -QPDFObjectHandle::isRectangle()
1042   -#else
1043 801 bool
1044 802 QPDFObjectHandle::isRectangle() const
1045   -#endif
1046 803 {
1047 804 if (auto array = asArray()) {
1048 805 for (int i = 0; i < 4; ++i) {
... ... @@ -1055,13 +812,8 @@ QPDFObjectHandle::isRectangle() const
1055 812 return false;
1056 813 }
1057 814  
1058   -#ifndef QPDF_FUTURE
1059   -bool
1060   -QPDFObjectHandle::isMatrix()
1061   -#else
1062 815 bool
1063 816 QPDFObjectHandle::isMatrix() const
1064   -#endif
1065 817 {
1066 818 if (auto array = asArray()) {
1067 819 for (int i = 0; i < 6; ++i) {
... ... @@ -1074,13 +826,8 @@ QPDFObjectHandle::isMatrix() const
1074 826 return false;
1075 827 }
1076 828  
1077   -#ifndef QPDF_FUTURE
1078   -QPDFObjectHandle::Rectangle
1079   -QPDFObjectHandle::getArrayAsRectangle()
1080   -#else
1081 829 QPDFObjectHandle::Rectangle
1082 830 QPDFObjectHandle::getArrayAsRectangle() const
1083   -#endif
1084 831 {
1085 832 if (auto array = asArray()) {
1086 833 if (array->size() != 4) {
... ... @@ -1101,13 +848,8 @@ QPDFObjectHandle::getArrayAsRectangle() const
1101 848 return {};
1102 849 }
1103 850  
1104   -#ifndef QPDF_FUTURE
1105   -QPDFObjectHandle::Matrix
1106   -QPDFObjectHandle::getArrayAsMatrix()
1107   -#else
1108 851 QPDFObjectHandle::Matrix
1109 852 QPDFObjectHandle::getArrayAsMatrix() const
1110   -#endif
1111 853 {
1112 854 if (auto array = asArray()) {
1113 855 if (array->size() != 6) {
... ... @@ -1124,13 +866,8 @@ QPDFObjectHandle::getArrayAsMatrix() const
1124 866 return {};
1125 867 }
1126 868  
1127   -#ifndef QPDF_FUTURE
1128   -std::vector<QPDFObjectHandle>
1129   -QPDFObjectHandle::getArrayAsVector()
1130   -#else
1131 869 std::vector<QPDFObjectHandle>
1132 870 QPDFObjectHandle::getArrayAsVector() const
1133   -#endif
1134 871 {
1135 872 auto array = asArray();
1136 873 if (array) {
... ... @@ -1238,13 +975,8 @@ QPDFObjectHandle::ditems()
1238 975 return {*this};
1239 976 }
1240 977  
1241   -#ifndef QPDF_FUTURE
1242   -bool
1243   -QPDFObjectHandle::hasKey(std::string const& key)
1244   -#else
1245 978 bool
1246 979 QPDFObjectHandle::hasKey(std::string const& key) const
1247   -#endif
1248 980 {
1249 981 auto dict = asDictionary();
1250 982 if (dict) {
... ... @@ -1256,13 +988,8 @@ QPDFObjectHandle::hasKey(std::string const&amp; key) const
1256 988 }
1257 989 }
1258 990  
1259   -#ifndef QPDF_FUTURE
1260   -QPDFObjectHandle
1261   -QPDFObjectHandle::getKey(std::string const& key)
1262   -#else
1263 991 QPDFObjectHandle
1264 992 QPDFObjectHandle::getKey(std::string const& key) const
1265   -#endif
1266 993 {
1267 994 if (auto dict = asDictionary()) {
1268 995 return dict->getKey(key);
... ... @@ -1274,24 +1001,14 @@ QPDFObjectHandle::getKey(std::string const&amp; key) const
1274 1001 }
1275 1002 }
1276 1003  
1277   -#ifndef QPDF_FUTURE
1278   -QPDFObjectHandle
1279   -QPDFObjectHandle::getKeyIfDict(std::string const& key)
1280   -#else
1281 1004 QPDFObjectHandle
1282 1005 QPDFObjectHandle::getKeyIfDict(std::string const& key) const
1283   -#endif
1284 1006 {
1285 1007 return isNull() ? newNull() : getKey(key);
1286 1008 }
1287 1009  
1288   -#ifndef QPDF_FUTURE
1289   -std::set<std::string>
1290   -QPDFObjectHandle::getKeys()
1291   -#else
1292 1010 std::set<std::string>
1293 1011 QPDFObjectHandle::getKeys() const
1294   -#endif
1295 1012 {
1296 1013 std::set<std::string> result;
1297 1014 auto dict = asDictionary();
... ... @@ -1304,13 +1021,8 @@ QPDFObjectHandle::getKeys() const
1304 1021 return result;
1305 1022 }
1306 1023  
1307   -#ifndef QPDF_FUTURE
1308   -std::map<std::string, QPDFObjectHandle>
1309   -QPDFObjectHandle::getDictAsMap()
1310   -#else
1311 1024 std::map<std::string, QPDFObjectHandle>
1312 1025 QPDFObjectHandle::getDictAsMap() const
1313   -#endif
1314 1026 {
1315 1027 std::map<std::string, QPDFObjectHandle> result;
1316 1028 auto dict = asDictionary();
... ... @@ -1324,13 +1036,9 @@ QPDFObjectHandle::getDictAsMap() const
1324 1036 }
1325 1037  
1326 1038 // Array and Name accessors
1327   -#ifndef QPDF_FUTURE
1328   -bool
1329   -QPDFObjectHandle::isOrHasName(std::string const& value)
1330   -#else
  1039 +
1331 1040 bool
1332 1041 QPDFObjectHandle::isOrHasName(std::string const& value) const
1333   -#endif
1334 1042 {
1335 1043 if (isNameAndEquals(value)) {
1336 1044 return true;
... ... @@ -1458,13 +1166,8 @@ QPDFObjectHandle::mergeResources(
1458 1166 }
1459 1167 }
1460 1168  
1461   -#ifndef QPDF_FUTURE
1462   -std::set<std::string>
1463   -QPDFObjectHandle::getResourceNames()
1464   -#else
1465 1169 std::set<std::string>
1466 1170 QPDFObjectHandle::getResourceNames() const
1467   -#endif
1468 1171 {
1469 1172 // Return second-level dictionary keys
1470 1173 std::set<std::string> result;
... ... @@ -1482,16 +1185,9 @@ QPDFObjectHandle::getResourceNames() const
1482 1185 return result;
1483 1186 }
1484 1187  
1485   -#ifndef QPDF_FUTURE
1486   -std::string
1487   -QPDFObjectHandle::getUniqueResourceName(
1488   - std::string const& prefix, int& min_suffix, std::set<std::string>* namesp)
1489   -#else
1490 1188 std::string
1491 1189 QPDFObjectHandle::getUniqueResourceName(
1492 1190 std::string const& prefix, int& min_suffix, std::set<std::string>* namesp) const
1493   -#endif
1494   -
1495 1191 {
1496 1192 std::set<std::string> names = (namesp ? *namesp : getResourceNames());
1497 1193 int max_suffix = min_suffix + QIntC::to_int(names.size());
... ... @@ -1573,13 +1269,9 @@ QPDFObjectHandle::replaceOrRemoveKey(std::string const&amp; key, QPDFObjectHandle co
1573 1269 }
1574 1270  
1575 1271 // Stream accessors
1576   -#ifndef QPDF_FUTURE
1577   -QPDFObjectHandle
1578   -QPDFObjectHandle::getDict()
1579   -#else
  1272 +
1580 1273 QPDFObjectHandle
1581 1274 QPDFObjectHandle::getDict() const
1582   -#endif
1583 1275 {
1584 1276 return asStreamWithAssert()->getDict();
1585 1277 }
... ... @@ -1894,13 +1586,8 @@ QPDFObjectHandle::coalesceContentStreams()
1894 1586 new_contents.replaceStreamData(provider, newNull(), newNull());
1895 1587 }
1896 1588  
1897   -#ifndef QPDF_FUTURE
1898   -std::string
1899   -QPDFObjectHandle::unparse()
1900   -#else
1901 1589 std::string
1902 1590 QPDFObjectHandle::unparse() const
1903   -#endif
1904 1591 {
1905 1592 if (this->isIndirect()) {
1906 1593 return getObjGen().unparse(' ') + " R";
... ... @@ -1909,13 +1596,8 @@ QPDFObjectHandle::unparse() const
1909 1596 }
1910 1597 }
1911 1598  
1912   -#ifndef QPDF_FUTURE
1913   -std::string
1914   -QPDFObjectHandle::unparseResolved()
1915   -#else
1916 1599 std::string
1917 1600 QPDFObjectHandle::unparseResolved() const
1918   -#endif
1919 1601 {
1920 1602 if (!obj) {
1921 1603 throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle");
... ... @@ -1923,13 +1605,8 @@ QPDFObjectHandle::unparseResolved() const
1923 1605 return obj->unparse();
1924 1606 }
1925 1607  
1926   -#ifndef QPDF_FUTURE
1927   -std::string
1928   -QPDFObjectHandle::unparseBinary()
1929   -#else
1930 1608 std::string
1931 1609 QPDFObjectHandle::unparseBinary() const
1932   -#endif
1933 1610 {
1934 1611 if (auto str = asString()) {
1935 1612 return str->unparse(true);
... ... @@ -1938,25 +1615,8 @@ QPDFObjectHandle::unparseBinary() const
1938 1615 }
1939 1616 }
1940 1617  
1941   -// Deprecated versionless getJSON to be removed in qpdf 12
1942   -#ifndef QPDF_FUTURE
1943   -JSON
1944   -QPDFObjectHandle::getJSON(bool dereference_indirect)
1945   -#else
1946   -JSON
1947   -QPDFObjectHandle::getJSON(bool dereference_indirect) const
1948   -#endif
1949   -{
1950   - return getJSON(1, dereference_indirect);
1951   -}
1952   -
1953   -#ifndef QPDF_FUTURE
1954   -JSON
1955   -QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1956   -#else
1957 1618 JSON
1958 1619 QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) const
1959   -#endif
1960 1620 {
1961 1621 if ((!dereference_indirect) && isIndirect()) {
1962 1622 return JSON::makeString(unparse());
... ... @@ -1971,13 +1631,8 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) const
1971 1631 }
1972 1632 }
1973 1633  
1974   -#ifndef QPDF_FUTURE
1975   -void
1976   -QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect)
1977   -#else
1978 1634 void
1979 1635 QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect) const
1980   -#endif
1981 1636 {
1982 1637 if (!dereference_indirect && isIndirect()) {
1983 1638 p << "\"" << getObjGen().unparse(' ') << " R\"";
... ... @@ -1988,14 +1643,9 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer&amp; p, bool dereference_
1988 1643 }
1989 1644 }
1990 1645  
1991   -#ifndef QPDF_FUTURE
1992   -void
1993   -QPDFObjectHandle::writeJSON(int json_version, Pipeline* p, bool dereference_indirect, size_t depth)
1994   -#else
1995 1646 void
1996 1647 QPDFObjectHandle::writeJSON(
1997 1648 int json_version, Pipeline* p, bool dereference_indirect, size_t depth) const
1998   -#endif
1999 1649 {
2000 1650 JSON::Writer jw{p, depth};
2001 1651 writeJSON(json_version, jw, dereference_indirect);
... ... @@ -2229,13 +1879,8 @@ QPDFObjectHandle::parse(
2229 1879 .parse(empty, false);
2230 1880 }
2231 1881  
2232   -#ifndef QPDF_FUTURE
2233   -qpdf_offset_t
2234   -QPDFObjectHandle::getParsedOffset()
2235   -#else
2236 1882 qpdf_offset_t
2237 1883 QPDFObjectHandle::getParsedOffset() const
2238   -#endif
2239 1884 {
2240 1885 return obj ? obj->getParsedOffset() : -1;
2241 1886 }
... ... @@ -2420,13 +2065,8 @@ QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const&amp; obj
2420 2065 }
2421 2066 }
2422 2067  
2423   -#ifndef QPDF_FUTURE
2424   -bool
2425   -QPDFObjectHandle::hasObjectDescription()
2426   -#else
2427 2068 bool
2428 2069 QPDFObjectHandle::hasObjectDescription() const
2429   -#endif
2430 2070 {
2431 2071 return obj && obj->hasDescription();
2432 2072 }
... ... @@ -2550,13 +2190,8 @@ QPDFObjectHandle::typeWarning(char const* expected_type, std::string const&amp; warn
2550 2190 QPDFObjectHandle(*this).getTypeName() + ": " + warning));
2551 2191 }
2552 2192  
2553   -#ifndef QPDF_FUTURE
2554   -void
2555   -QPDFObjectHandle::warnIfPossible(std::string const& warning)
2556   -#else
2557 2193 void
2558 2194 QPDFObjectHandle::warnIfPossible(std::string const& warning) const
2559   -#endif
2560 2195 {
2561 2196 QPDF* context = nullptr;
2562 2197 std::string description;
... ... @@ -2588,180 +2223,100 @@ QPDFObjectHandle::assertType(char const* type_name, bool istype) const
2588 2223 }
2589 2224 }
2590 2225  
2591   -#ifndef QPDF_FUTURE
2592   -void
2593   -QPDFObjectHandle::assertNull()
2594   -#else
2595 2226 void
2596 2227 QPDFObjectHandle::assertNull() const
2597   -#endif
2598 2228 {
2599 2229 assertType("null", isNull());
2600 2230 }
2601 2231  
2602   -#ifndef QPDF_FUTURE
2603   -void
2604   -QPDFObjectHandle::assertBool()
2605   -#else
2606 2232 void
2607 2233 QPDFObjectHandle::assertBool() const
2608   -#endif
2609 2234 {
2610 2235 assertType("boolean", isBool());
2611 2236 }
2612 2237  
2613   -#ifndef QPDF_FUTURE
2614   -void
2615   -QPDFObjectHandle::assertInteger()
2616   -#else
2617 2238 void
2618 2239 QPDFObjectHandle::assertInteger() const
2619   -#endif
2620 2240 {
2621 2241 assertType("integer", isInteger());
2622 2242 }
2623 2243  
2624   -#ifndef QPDF_FUTURE
2625   -void
2626   -QPDFObjectHandle::assertReal()
2627   -#else
2628 2244 void
2629 2245 QPDFObjectHandle::assertReal() const
2630   -#endif
2631 2246 {
2632 2247 assertType("real", isReal());
2633 2248 }
2634 2249  
2635   -#ifndef QPDF_FUTURE
2636   -void
2637   -QPDFObjectHandle::assertName()
2638   -#else
2639 2250 void
2640 2251 QPDFObjectHandle::assertName() const
2641   -#endif
2642 2252 {
2643 2253 assertType("name", isName());
2644 2254 }
2645 2255  
2646   -#ifndef QPDF_FUTURE
2647   -void
2648   -QPDFObjectHandle::assertString()
2649   -#else
2650 2256 void
2651 2257 QPDFObjectHandle::assertString() const
2652   -#endif
2653 2258 {
2654 2259 assertType("string", isString());
2655 2260 }
2656 2261  
2657   -#ifndef QPDF_FUTURE
2658   -void
2659   -QPDFObjectHandle::assertOperator()
2660   -#else
2661 2262 void
2662 2263 QPDFObjectHandle::assertOperator() const
2663   -#endif
2664 2264 {
2665 2265 assertType("operator", isOperator());
2666 2266 }
2667 2267  
2668   -#ifndef QPDF_FUTURE
2669   -void
2670   -QPDFObjectHandle::assertInlineImage()
2671   -#else
2672 2268 void
2673 2269 QPDFObjectHandle::assertInlineImage() const
2674   -#endif
2675 2270 {
2676 2271 assertType("inlineimage", isInlineImage());
2677 2272 }
2678 2273  
2679   -#ifndef QPDF_FUTURE
2680   -void
2681   -QPDFObjectHandle::assertArray()
2682   -#else
2683 2274 void
2684 2275 QPDFObjectHandle::assertArray() const
2685   -#endif
2686 2276 {
2687 2277 assertType("array", isArray());
2688 2278 }
2689 2279  
2690   -#ifndef QPDF_FUTURE
2691   -void
2692   -QPDFObjectHandle::assertDictionary()
2693   -#else
2694 2280 void
2695 2281 QPDFObjectHandle::assertDictionary() const
2696   -#endif
2697 2282 {
2698 2283 assertType("dictionary", isDictionary());
2699 2284 }
2700 2285  
2701   -#ifndef QPDF_FUTURE
2702   -void
2703   -QPDFObjectHandle::assertStream()
2704   -#else
2705 2286 void
2706 2287 QPDFObjectHandle::assertStream() const
2707   -#endif
2708 2288 {
2709 2289 assertType("stream", isStream());
2710 2290 }
2711 2291  
2712   -#ifndef QPDF_FUTURE
2713   -void
2714   -QPDFObjectHandle::assertReserved()
2715   -#else
2716 2292 void
2717 2293 QPDFObjectHandle::assertReserved() const
2718   -#endif
2719 2294 {
2720 2295 assertType("reserved", isReserved());
2721 2296 }
2722 2297  
2723   -#ifndef QPDF_FUTURE
2724   -void
2725   -QPDFObjectHandle::assertIndirect()
2726   -#else
2727 2298 void
2728 2299 QPDFObjectHandle::assertIndirect() const
2729   -#endif
2730 2300 {
2731 2301 if (!isIndirect()) {
2732 2302 throw std::logic_error("operation for indirect object attempted on direct object");
2733 2303 }
2734 2304 }
2735 2305  
2736   -#ifndef QPDF_FUTURE
2737   -void
2738   -QPDFObjectHandle::assertScalar()
2739   -#else
2740 2306 void
2741 2307 QPDFObjectHandle::assertScalar() const
2742   -#endif
2743 2308 {
2744 2309 assertType("scalar", isScalar());
2745 2310 }
2746 2311  
2747   -#ifndef QPDF_FUTURE
2748   -void
2749   -QPDFObjectHandle::assertNumber()
2750   -#else
2751 2312 void
2752 2313 QPDFObjectHandle::assertNumber() const
2753   -#endif
2754 2314 {
2755 2315 assertType("number", isNumber());
2756 2316 }
2757 2317  
2758   -#ifndef QPDF_FUTURE
2759   -bool
2760   -QPDFObjectHandle::isPageObject()
2761   -#else
2762 2318 bool
2763 2319 QPDFObjectHandle::isPageObject() const
2764   -#endif
2765 2320 {
2766 2321 // See comments in QPDFObjectHandle.hh.
2767 2322 if (getOwningQPDF() == nullptr) {
... ... @@ -2772,13 +2327,8 @@ QPDFObjectHandle::isPageObject() const
2772 2327 return isDictionaryOfType("/Page");
2773 2328 }
2774 2329  
2775   -#ifndef QPDF_FUTURE
2776   -bool
2777   -QPDFObjectHandle::isPagesObject()
2778   -#else
2779 2330 bool
2780 2331 QPDFObjectHandle::isPagesObject() const
2781   -#endif
2782 2332 {
2783 2333 if (getOwningQPDF() == nullptr) {
2784 2334 return false;
... ... @@ -2788,24 +2338,14 @@ QPDFObjectHandle::isPagesObject() const
2788 2338 return isDictionaryOfType("/Pages");
2789 2339 }
2790 2340  
2791   -#ifndef QPDF_FUTURE
2792   -bool
2793   -QPDFObjectHandle::isFormXObject()
2794   -#else
2795 2341 bool
2796 2342 QPDFObjectHandle::isFormXObject() const
2797   -#endif
2798 2343 {
2799 2344 return isStreamOfType("", "/Form");
2800 2345 }
2801 2346  
2802   -#ifndef QPDF_FUTURE
2803   -bool
2804   -QPDFObjectHandle::isImage(bool exclude_imagemask)
2805   -#else
2806 2347 bool
2807 2348 QPDFObjectHandle::isImage(bool exclude_imagemask) const
2808   -#endif
2809 2349 {
2810 2350 return (
2811 2351 isStreamOfType("", "/Image") &&
... ... @@ -2827,13 +2367,8 @@ QPDFObjectHandle::checkOwnership(QPDFObjectHandle const&amp; item) const
2827 2367 }
2828 2368 }
2829 2369  
2830   -#ifndef QPDF_FUTURE
2831   -void
2832   -QPDFObjectHandle::assertPageObject()
2833   -#else
2834 2370 void
2835 2371 QPDFObjectHandle::assertPageObject() const
2836   -#endif
2837 2372 {
2838 2373 if (!isPageObject()) {
2839 2374 throw std::runtime_error("page operation called on non-Page object");
... ...
libqpdf/QPDFOutlineDocumentHelper.cc
... ... @@ -50,7 +50,7 @@ QPDFOutlineDocumentHelper::initializeByPage()
50 50 }
51 51  
52 52 std::vector<QPDFOutlineObjectHelper>
53   -QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen const& og)
  53 +QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen og)
54 54 {
55 55 if (m->by_page.empty()) {
56 56 initializeByPage();
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1058,7 +1058,7 @@ QPDFWriter::closeObject(int objid)
1058 1058 }
1059 1059  
1060 1060 void
1061   -QPDFWriter::assignCompressedObjectNumbers(QPDFObjGen const& og)
  1061 +QPDFWriter::assignCompressedObjectNumbers(QPDFObjGen og)
1062 1062 {
1063 1063 int objid = og.getObj();
1064 1064 if ((og.getGen() != 0) || (m->object_stream_to_objects.count(objid) == 0)) {
... ...
libqpdf/QPDF_Unresolved.cc
... ... @@ -3,13 +3,13 @@
3 3 #include <qpdf/QPDF.hh>
4 4 #include <qpdf/QPDFObject_private.hh>
5 5  
6   -QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og) :
  6 +QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen og) :
7 7 QPDFValue(::ot_unresolved, qpdf, og)
8 8 {
9 9 }
10 10  
11 11 std::shared_ptr<QPDFObject>
12   -QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og)
  12 +QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen og)
13 13 {
14 14 return do_create(new QPDF_Unresolved(qpdf, og));
15 15 }
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -952,8 +952,7 @@ QPDF::initializeEncryption()
952 952 }
953 953  
954 954 std::string
955   -QPDF::getKeyForObject(
956   - std::shared_ptr<EncryptionParameters> encp, QPDFObjGen const& og, bool use_aes)
  955 +QPDF::getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen og, bool use_aes)
957 956 {
958 957 if (!encp->encrypted) {
959 958 throw std::logic_error("request for encryption key in non-encrypted PDF");
... ... @@ -974,7 +973,7 @@ QPDF::getKeyForObject(
974 973 }
975 974  
976 975 void
977   -QPDF::decryptString(std::string& str, QPDFObjGen const& og)
  976 +QPDF::decryptString(std::string& str, QPDFObjGen og)
978 977 {
979 978 if (!og.isIndirect()) {
980 979 return;
... ... @@ -1048,7 +1047,7 @@ QPDF::decryptStream(
1048 1047 std::shared_ptr<InputSource> file,
1049 1048 QPDF& qpdf_for_warning,
1050 1049 Pipeline*& pipeline,
1051   - QPDFObjGen const& og,
  1050 + QPDFObjGen og,
1052 1051 QPDFObjectHandle& stream_dict,
1053 1052 std::unique_ptr<Pipeline>& decrypt_pipeline)
1054 1053 {
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -557,7 +557,7 @@ QPDF::maxEnd(ObjUser const&amp; ou)
557 557 }
558 558  
559 559 qpdf_offset_t
560   -QPDF::getLinearizationOffset(QPDFObjGen const& og)
  560 +QPDF::getLinearizationOffset(QPDFObjGen og)
561 561 {
562 562 QPDFXRefEntry entry = m->xref_table[og];
563 563 qpdf_offset_t result = 0;
... ...
libqpdf/QPDF_pages.cc
... ... @@ -323,7 +323,7 @@ QPDF::findPage(QPDFObjectHandle&amp; page)
323 323 }
324 324  
325 325 int
326   -QPDF::findPage(QPDFObjGen const& og)
  326 +QPDF::findPage(QPDFObjGen og)
327 327 {
328 328 flattenPagesTree();
329 329 auto it = m->pageobj_to_pages_pos.find(og);
... ...
libqpdf/qpdf/QPDFObject_private.hh
... ... @@ -132,13 +132,13 @@ class QPDFObject
132 132 }
133 133  
134 134 void
135   - setDefaultDescription(QPDF* qpdf, QPDFObjGen const& og)
  135 + setDefaultDescription(QPDF* qpdf, QPDFObjGen og)
136 136 {
137 137 // Intended for use by the QPDF class
138 138 value->setDefaultDescription(qpdf, og);
139 139 }
140 140 void
141   - setObjGen(QPDF* qpdf, QPDFObjGen const& og)
  141 + setObjGen(QPDF* qpdf, QPDFObjGen og)
142 142 {
143 143 value->qpdf = qpdf;
144 144 value->og = og;
... ...
libqpdf/qpdf/QPDFValue.hh
... ... @@ -65,7 +65,7 @@ class QPDFValue: public std::enable_shared_from_this&lt;QPDFValue&gt;
65 65 setParsedOffset(offset);
66 66 }
67 67 void
68   - setDefaultDescription(QPDF* a_qpdf, QPDFObjGen const& a_og)
  68 + setDefaultDescription(QPDF* a_qpdf, QPDFObjGen a_og)
69 69 {
70 70 qpdf = a_qpdf;
71 71 og = a_og;
... ...
libqpdf/qpdf/QPDF_Unresolved.hh
... ... @@ -7,14 +7,14 @@ class QPDF_Unresolved: public QPDFValue
7 7 {
8 8 public:
9 9 ~QPDF_Unresolved() override = default;
10   - static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen const& og);
  10 + static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen og);
11 11 std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
12 12 std::string unparse() override;
13 13 void writeJSON(int json_version, JSON::Writer& p) override;
14 14 std::string getStringValue() const override;
15 15  
16 16 private:
17   - QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og);
  17 + QPDF_Unresolved(QPDF* qpdf, QPDFObjGen og);
18 18 };
19 19  
20 20 #endif // QPDF_UNRESOLVED_HH
... ...
libtests/buffer.cc
... ... @@ -18,130 +18,65 @@ uc(char const* s)
18 18 int
19 19 main()
20 20 {
21   - {
22   - // Test that buffers can be copied by value using Buffer::copy.
23   - Buffer bc1(2);
24   - unsigned char* bc1p = bc1.getBuffer();
25   - bc1p[0] = 'Q';
26   - bc1p[1] = 'W';
27   - Buffer bc2(bc1.copy());
28   - bc1p[0] = 'R';
29   - unsigned char* bc2p = bc2.getBuffer();
30   - assert(bc2p != bc1p);
31   - assert(bc2p[0] == 'Q');
32   - assert(bc2p[1] == 'W');
33   - bc2 = bc1.copy();
34   - bc2p = bc2.getBuffer();
35   - assert(bc2p != bc1p);
36   - assert(bc2p[0] == 'R');
37   - assert(bc2p[1] == 'W');
38   -
39   - // Test Buffer(std:string&&)
40   - Buffer bc3("QW");
41   - unsigned char* bc3p = bc3.getBuffer();
42   - Buffer bc4(bc3.copy());
43   - bc3p[0] = 'R';
44   - unsigned char* bc4p = bc4.getBuffer();
45   - assert(bc4p != bc3p);
46   - assert(bc4p[0] == 'Q');
47   - assert(bc4p[1] == 'W');
48   - bc4 = bc3.copy();
49   - bc4p = bc4.getBuffer();
50   - assert(bc4p != bc3p);
51   - assert(bc4p[0] == 'R');
52   - assert(bc4p[1] == 'W');
53   - }
54   -
55   -#ifdef _MSC_VER
56   -# pragma warning(disable : 4996)
57   -#endif
58   -#if (defined(__GNUC__) || defined(__clang__))
59   -# pragma GCC diagnostic push
60   -# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
61   -#endif
62   - {
63   - // Test that buffers can be copied by value using copy construction / assignment.
64   - Buffer::setTestMode();
65   - Buffer bc1(2);
66   - unsigned char* bc1p = bc1.getBuffer();
67   - bc1p[0] = 'Q';
68   - bc1p[1] = 'W';
69   - Buffer bc2(bc1);
70   - bc1p[0] = 'R';
71   - unsigned char* bc2p = bc2.getBuffer();
72   - assert(bc2p != bc1p);
73   - assert(bc2p[0] == 'Q');
74   - assert(bc2p[1] == 'W');
75   - bc2 = bc1;
76   - bc2p = bc2.getBuffer();
77   - assert(bc2p != bc1p);
78   - assert(bc2p[0] == 'R');
79   - assert(bc2p[1] == 'W');
80   -
81   - // Test Buffer(std:string&&)
82   - Buffer bc3("QW");
83   - unsigned char* bc3p = bc3.getBuffer();
84   - Buffer bc4(bc3);
85   - bc3p[0] = 'R';
86   - unsigned char* bc4p = bc4.getBuffer();
87   - assert(bc4p != bc3p);
88   - assert(bc4p[0] == 'Q');
89   - assert(bc4p[1] == 'W');
90   - bc4 = bc3;
91   - bc4p = bc4.getBuffer();
92   - assert(bc4p != bc3p);
93   - assert(bc2p[0] == 'R');
94   - assert(bc2p[1] == 'W');
95   -
96   - // Test Buffer(std:string&)
97   - std::string s{"QW"};
98   - Buffer bc5(s);
99   - unsigned char* bc5p = bc5.getBuffer();
100   - Buffer bc6(bc5);
101   - bc5p[0] = 'R';
102   - unsigned char* bc6p = bc6.getBuffer();
103   - assert(bc6p != bc5p);
104   - assert(bc6p[0] == 'Q');
105   - assert(bc6p[1] == 'W');
106   - bc6 = bc5;
107   - bc6p = bc6.getBuffer();
108   - assert(bc6p != bc5p);
109   - assert(bc2p[0] == 'R');
110   - assert(bc2p[1] == 'W');
111   - }
112   -#if (defined(__GNUC__) || defined(__clang__))
113   -# pragma GCC diagnostic pop
114   -#endif
115   -
116   - {
117   - // Test that buffers can be moved.
118   - Buffer bm1(2);
119   - unsigned char* bm1p = bm1.getBuffer();
120   - bm1p[0] = 'Q';
121   - bm1p[1] = 'W';
122   - Buffer bm2(std::move(bm1));
123   - bm1p[0] = 'R';
124   - unsigned char* bm2p = bm2.getBuffer();
125   - assert(bm2p == bm1p);
126   - assert(bm2p[0] == 'R');
127   -
128   - Buffer bm3 = std::move(bm2);
129   - unsigned char* bm3p = bm3.getBuffer();
130   - assert(bm3p == bm2p);
131   -
132   - // Test Buffer(dtd::string&&)
133   - Buffer bm4("QW");
134   - unsigned char* bm4p = bm4.getBuffer();
135   - Buffer bm5(std::move(bm4));
136   - bm4p[0] = 'R';
137   - unsigned char* bm5p = bm5.getBuffer();
138   - assert(bm5p == bm4p);
139   - assert(bm5p[0] == 'R');
140   -
141   - Buffer bm6 = std::move(bm5);
142   - unsigned char* bm6p = bm6.getBuffer();
143   - assert(bm6p == bm5p);
144   - }
  21 + // Test that buffers can be copied by value using Buffer::copy.
  22 + Buffer bc1(2);
  23 + unsigned char* bc1p = bc1.getBuffer();
  24 + bc1p[0] = 'Q';
  25 + bc1p[1] = 'W';
  26 + Buffer bc2(bc1.copy());
  27 + bc1p[0] = 'R';
  28 + unsigned char* bc2p = bc2.getBuffer();
  29 + assert(bc2p != bc1p);
  30 + assert(bc2p[0] == 'Q');
  31 + assert(bc2p[1] == 'W');
  32 + bc2 = bc1.copy();
  33 + bc2p = bc2.getBuffer();
  34 + assert(bc2p != bc1p);
  35 + assert(bc2p[0] == 'R');
  36 + assert(bc2p[1] == 'W');
  37 +
  38 + // Test Buffer(std:string&&)
  39 + Buffer bc3("QW");
  40 + unsigned char* bc3p = bc3.getBuffer();
  41 + Buffer bc4(bc3.copy());
  42 + bc3p[0] = 'R';
  43 + unsigned char* bc4p = bc4.getBuffer();
  44 + assert(bc4p != bc3p);
  45 + assert(bc4p[0] == 'Q');
  46 + assert(bc4p[1] == 'W');
  47 + bc4 = bc3.copy();
  48 + bc4p = bc4.getBuffer();
  49 + assert(bc4p != bc3p);
  50 + assert(bc4p[0] == 'R');
  51 + assert(bc4p[1] == 'W');
  52 +
  53 + // Test that buffers can be moved.
  54 + Buffer bm1(2);
  55 + unsigned char* bm1p = bm1.getBuffer();
  56 + bm1p[0] = 'Q';
  57 + bm1p[1] = 'W';
  58 + Buffer bm2(std::move(bm1));
  59 + bm1p[0] = 'R';
  60 + unsigned char* bm2p = bm2.getBuffer();
  61 + assert(bm2p == bm1p);
  62 + assert(bm2p[0] == 'R');
  63 +
  64 + Buffer bm3 = std::move(bm2);
  65 + unsigned char* bm3p = bm3.getBuffer();
  66 + assert(bm3p == bm2p);
  67 +
  68 + // Test Buffer(dtd::string&&)
  69 + Buffer bm4("QW");
  70 + unsigned char* bm4p = bm4.getBuffer();
  71 + Buffer bm5(std::move(bm4));
  72 + bm4p[0] = 'R';
  73 + unsigned char* bm5p = bm5.getBuffer();
  74 + assert(bm5p == bm4p);
  75 + assert(bm5p[0] == 'R');
  76 +
  77 + Buffer bm6 = std::move(bm5);
  78 + unsigned char* bm6p = bm6.getBuffer();
  79 + assert(bm6p == bm5p);
145 80  
146 81 try {
147 82 Pl_Discard discard;
... ...
libtests/qintc.cc
... ... @@ -48,7 +48,7 @@ try_range_check_subtract_real(char const* description, bool exp_pass, T const&amp; a
48 48 {
49 49 bool passed = false;
50 50 try {
51   - QIntC::range_check_substract(a, b);
  51 + QIntC::range_check_subtract(a, b);
52 52 std::cout << description << ": okay";
53 53 passed = true;
54 54 } catch (std::range_error& e) {
... ...
manual/design.rst
... ... @@ -860,8 +860,8 @@ modification of code.
860 860  
861 861 The ``POINTERHOLDER_TRANSITION`` preprocessor symbol was introduced in
862 862 qpdf 10.6.0 to help people transition from ``PointerHolder`` to
863   -``std::shared_ptr``. If you don't define this, you will get a compiler
864   -warning. Defining it to any value will suppress the warning. An
  863 +``std::shared_ptr``. If you don't define this, ``PointerHolder`` will
  864 +be completely excluded from the API (starting with qpdf 12).An
865 865 explanation appears below of the different possible values for this
866 866 symbol and what they mean.
867 867  
... ... @@ -1003,7 +1003,7 @@ without consulting this manual.
1003 1003 - meaning
1004 1004  
1005 1005 - - undefined
1006   - - Same as ``0`` but issues a warning
  1006 + - Same as ``4``: ``PointerHolder`` is not defined.
1007 1007  
1008 1008 - - ``0``
1009 1009 - Provide a backward compatible ``PointerHolder`` and suppress
... ...
manual/qpdf.1
... ... @@ -3,7 +3,7 @@
3 3 .\" Edits will be automatically overwritten if the build is
4 4 .\" run in maintainer mode.
5 5 .\"
6   -.TH QPDF "1" "" "qpdf version 11.10.1" "User Commands"
  6 +.TH QPDF "1" "" "qpdf version 12.0.0" "User Commands"
7 7 .SH NAME
8 8 qpdf \- PDF transformation software
9 9 .SH SYNOPSIS
... ...
manual/release-notes.rst
... ... @@ -6,29 +6,45 @@ Release Notes
6 6 For a detailed list of changes, please see the file
7 7 :file:`ChangeLog` in the source distribution.
8 8  
9   -If you are a developer and want to test your code against future API
10   -changes that are under consideration, you can build qpdf locally and
11   -enable the ``FUTURE`` build option (see :ref:`build-options`).
12   -
13   -Planned changes for future 12.x (subject to change):
14   - - ``QPDFObjectHandle`` will support move construction/assignment.
15   - This change will be invisible to most developers but may break
16   - your code if you rely on specific behavior around how many
17   - references to a QPDFObjectHandle's underlying object exist. You
18   - would have to write code specifically to do that, so if you're not
19   - sure, then you shouldn't have to worry.
20   -
21   - - ``Buffer`` copy constructor and assignment operator will be
22   - removed. ``Buffer`` copy operations are expensive as they always
23   - involve copying the buffer content. Use ``buffer2 =
24   - buffer1.copy();`` or ``Buffer buffer2{buffer1.copy()};`` to make
25   - it explicit that copying is intended.
26   -
27   - - ``QIntC.hh`` contains the type ``substract``, which will be fixed
28   - to ``subtract``. (Not enabled with ``FUTURE`` option.)
29   -
30 9 .. x.y.z: not yet released
31 10  
  11 +12.0.0: not yet released
  12 + - API: breaking changes
  13 +
  14 + - Deprecated versionless overload of ``QPDFObjectHandle::getJSON``
  15 + has been removed.
  16 +
  17 + - ``Buffer`` copy constructor and assignment operator have been
  18 + removed. ``Buffer`` copy operations are expensive as they always
  19 + involve copying the buffer content. Use ``buffer2 = buffer1.copy();``
  20 + or ``Buffer buffer2{buffer1.copy()};`` to make it explicit that
  21 + copying is intended.
  22 +
  23 + - ``QIntC.hh`` contained the typ0 ``substract`` in function names,
  24 + which has been fixed to ``subtract``.
  25 +
  26 + - Library Enhancements
  27 +
  28 + - ``QPDFObjectHandle`` supports move construction/assignment.
  29 + This change is invisible to most developers but may break
  30 + your code if you rely on specific behavior around how many
  31 + references to a QPDFObjectHandle's underlying object exist. You
  32 + would have to write code specifically to do that, so if you're not
  33 + sure, then you shouldn't have to worry.
  34 +
  35 + - Most ``QPDFObjectHandle`` accessor methods are now const qualified.
  36 +
  37 + - Build Changes
  38 +
  39 + - If ``POINTERHOLDER_TRANSITION`` is not defined, define it to
  40 + ``4``, which completely removes ``PointerHolder`` from the API.
  41 + Stop including it from any headers that used to include it. This
  42 + means code that hasn't completed its ``PointerHolder``
  43 + transition will get errors unless it defines
  44 + ``POINTERHOLDER_TRANSITION``, and any file that uses
  45 + ``PointerHolder`` will have to explicitly include it rather than
  46 + relying on other headers to bring it along.
  47 +
32 48 11.10.1: February 15, 2025
33 49 - Build fixes
34 50  
... ...
pkg-test/qpdf-version.cc
1   -#ifndef POINTERHOLDER_TRANSITION
2   -# define POINTERHOLDER_TRANSITION 4
3   -#endif
4   -
5 1 #include <qpdf/QPDF.hh>
6 2 #include <iostream>
7 3  
... ...