Coverage Report

Created: 2026-10-17 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpdf/libqpdf/qpdf/QPDFObjectHandle_private.hh
Line
Count
Source
1
#ifndef OBJECTHANDLE_PRIVATE_HH
2
#define OBJECTHANDLE_PRIVATE_HH
3
4
#include <qpdf/QPDFObjectHandle.hh>
5
6
#include <qpdf/QPDFObject_private.hh>
7
#include <qpdf/QPDF_private.hh>
8
#include <qpdf/QUtil.hh>
9
#include <qpdf/Util.hh>
10
11
#include <concepts>
12
#include <utility>
13
14
using namespace std::literals;
15
16
namespace qpdf
17
{
18
    class Array final: public BaseHandle
19
    {
20
      public:
21
35.1k
        Array() = default;
22
23
        explicit Array(std::vector<QPDFObjectHandle> const& items);
24
25
        explicit Array(std::vector<QPDFObjectHandle>&& items);
26
27
        Array(Array const& other) :
28
            BaseHandle(other.obj)
29
0
        {
30
0
        }
31
32
        static Array empty();
33
34
        Array&
35
        operator=(Array const& other)
36
35.1k
        {
37
35.1k
            if (obj != other.obj) {
38
35.1k
                obj = other.obj;
39
35.1k
            }
40
35.1k
            return *this;
41
35.1k
        }
42
43
        Array(Array&&) = default;
44
        Array& operator=(Array&&) = default;
45
46
        explicit Array(std::shared_ptr<QPDFObject> const& obj) :
47
33.2M
            BaseHandle(obj)
48
33.2M
        {
49
33.2M
        }
50
51
        explicit Array(std::shared_ptr<QPDFObject>&& obj) :
52
398k
            BaseHandle(std::move(obj))
53
398k
        {
54
398k
        }
55
56
        Array(QPDFObjectHandle const& oh) :
57
205M
            BaseHandle(oh.resolved_type_code() == ::ot_array ? oh : QPDFObjectHandle())
58
205M
        {
59
205M
        }
60
61
        Array&
62
        operator=(QPDFObjectHandle const& oh)
63
119k
        {
64
119k
            assign(::ot_array, oh);
65
119k
            return *this;
66
119k
        }
67
68
        Array(QPDFObjectHandle&& oh) :
69
1.44k
            BaseHandle(oh.resolved_type_code() == ::ot_array ? std::move(oh) : QPDFObjectHandle())
70
1.44k
        {
71
1.44k
        }
72
73
        Array&
74
        operator=(QPDFObjectHandle&& oh)
75
0
        {
76
0
            assign(::ot_array, std::move(oh));
77
0
            return *this;
78
0
        }
79
80
        QPDFObjectHandle const& operator[](size_t n) const;
81
82
        QPDFObjectHandle const& operator[](int n) const;
83
84
        using iterator = std::vector<QPDFObjectHandle>::iterator;
85
        using const_iterator = std::vector<QPDFObjectHandle>::const_iterator;
86
        using const_reverse_iterator = std::vector<QPDFObjectHandle>::const_reverse_iterator;
87
88
        iterator begin();
89
90
        iterator end();
91
92
        const_iterator cbegin();
93
94
        const_iterator cend();
95
96
        const_reverse_iterator crbegin();
97
98
        const_reverse_iterator crend();
99
100
        // Return the number of elements in the array. Return 0 if the object is not an array.
101
        size_t size() const;
102
        QPDFObjectHandle get(size_t n) const;
103
        QPDFObjectHandle get(int n) const;
104
        bool set(size_t at, QPDFObjectHandle const& oh);
105
        bool set(int at, QPDFObjectHandle const& oh);
106
        bool insert(size_t at, QPDFObjectHandle const& item);
107
        bool insert(int at, QPDFObjectHandle const& item);
108
        void push_back(QPDFObjectHandle const& item);
109
        bool erase(size_t at);
110
        bool erase(int at);
111
112
        std::vector<QPDFObjectHandle> getAsVector() const;
113
        void setFromVector(std::vector<QPDFObjectHandle> const& items);
114
115
      private:
116
        QPDF_Array* array() const;
117
        void checkOwnership(QPDFObjectHandle const& item) const;
118
        QPDFObjectHandle null() const;
119
120
        std::unique_ptr<std::vector<QPDFObjectHandle>> sp_elements{};
121
    };
122
123
    // BaseDictionary is only used as a base class. It does not contain any methods exposed in the
124
    // public API.
125
    class BaseDictionary: public BaseHandle
126
    {
127
      public:
128
        // The following methods are not part of the public API.
129
        std::set<std::string> getKeys();
130
        std::map<std::string, QPDFObjectHandle> const& getAsMap() const;
131
        void replace(std::string const& key, QPDFObjectHandle value);
132
133
        using iterator = std::map<std::string, QPDFObjectHandle>::iterator;
134
        using const_iterator = std::map<std::string, QPDFObjectHandle>::const_iterator;
135
        using reverse_iterator = std::map<std::string, QPDFObjectHandle>::reverse_iterator;
136
        using const_reverse_iterator =
137
            std::map<std::string, QPDFObjectHandle>::const_reverse_iterator;
138
139
        iterator
140
        begin()
141
201M
        {
142
201M
            if (auto d = as<QPDF_Dictionary>()) {
143
4.81M
                return d->items.begin();
144
4.81M
            }
145
196M
            return {};
146
201M
        }
147
148
        iterator
149
        end()
150
201M
        {
151
201M
            if (auto d = as<QPDF_Dictionary>()) {
152
4.81M
                return d->items.end();
153
4.81M
            }
154
196M
            return {};
155
201M
        }
156
157
        const_iterator
158
        cbegin()
159
0
        {
160
0
            if (auto d = as<QPDF_Dictionary>()) {
161
0
                return d->items.cbegin();
162
0
            }
163
0
            return {};
164
0
        }
165
166
        const_iterator
167
        cend()
168
0
        {
169
0
            if (auto d = as<QPDF_Dictionary>()) {
170
0
                return d->items.cend();
171
0
            }
172
0
            return {};
173
0
        }
174
175
        reverse_iterator
176
        rbegin()
177
0
        {
178
0
            if (auto d = as<QPDF_Dictionary>()) {
179
0
                return d->items.rbegin();
180
0
            }
181
0
            return {};
182
0
        }
183
184
        reverse_iterator
185
        rend()
186
0
        {
187
0
            if (auto d = as<QPDF_Dictionary>()) {
188
0
                return d->items.rend();
189
0
            }
190
0
            return {};
191
0
        }
192
193
        const_reverse_iterator
194
        crbegin()
195
430k
        {
196
430k
            if (auto d = as<QPDF_Dictionary>()) {
197
430k
                return d->items.crbegin();
198
430k
            }
199
0
            return {};
200
430k
        }
201
202
        const_reverse_iterator
203
        crend()
204
430k
        {
205
430k
            if (auto d = as<QPDF_Dictionary>()) {
206
430k
                return d->items.crend();
207
430k
            }
208
0
            return {};
209
430k
        }
210
211
      protected:
212
128k
        BaseDictionary() = default;
213
214
        explicit BaseDictionary(std::map<std::string, QPDFObjectHandle> const& dict) :
215
            BaseHandle(QPDFObject::create<QPDF_Dictionary>(dict))
216
0
        {
217
0
        }
218
219
        explicit BaseDictionary(std::map<std::string, QPDFObjectHandle>&& dict) :
220
142k
            BaseHandle(QPDFObject::create<QPDF_Dictionary>(std::move(dict)))
221
142k
        {
222
142k
        }
223
224
        explicit BaseDictionary(std::shared_ptr<QPDFObject> const& obj) :
225
3.82M
            BaseHandle(obj)
226
3.82M
        {
227
3.82M
        }
228
        explicit BaseDictionary(std::shared_ptr<QPDFObject>&& obj) :
229
            BaseHandle(std::move(obj))
230
0
        {
231
0
        }
232
384k
        BaseDictionary(BaseDictionary const&) = default;
233
28.5k
        BaseDictionary& operator=(BaseDictionary const&) = default;
234
12.2k
        BaseDictionary(BaseDictionary&&) = default;
235
152k
        BaseDictionary& operator=(BaseDictionary&&) = default;
236
237
        explicit BaseDictionary(QPDFObjectHandle const& oh) :
238
203M
            BaseHandle(oh.resolved_type_code() == ::ot_dictionary ? oh : QPDFObjectHandle())
239
203M
        {
240
203M
        }
241
242
        explicit BaseDictionary(QPDFObjectHandle&& oh) :
243
12.1M
            BaseHandle(
244
12.1M
                oh.resolved_type_code() == ::ot_dictionary ? std::move(oh) : QPDFObjectHandle())
245
12.1M
        {
246
12.1M
        }
247
        ~BaseDictionary() = default;
248
249
        QPDF_Dictionary* dict() const;
250
    };
251
252
    // Dictionary only defines con/destructors. All other methods are inherited from BaseDictionary.
253
    class Dictionary final: public BaseDictionary
254
    {
255
      public:
256
128k
        Dictionary() = default;
257
        explicit Dictionary(std::map<std::string, QPDFObjectHandle>&& dict);
258
        explicit Dictionary(std::shared_ptr<QPDFObject> const& obj);
259
260
        static Dictionary empty();
261
262
310k
        Dictionary(Dictionary const&) = default;
263
28.5k
        Dictionary& operator=(Dictionary const&) = default;
264
12.2k
        Dictionary(Dictionary&&) = default;
265
30.0k
        Dictionary& operator=(Dictionary&&) = default;
266
267
        Dictionary(QPDFObjectHandle const& oh) :
268
202M
            BaseDictionary(oh)
269
202M
        {
270
202M
        }
271
272
        Dictionary&
273
        operator=(QPDFObjectHandle const& oh)
274
131k
        {
275
131k
            assign(::ot_dictionary, oh);
276
131k
            return *this;
277
131k
        }
278
279
        Dictionary(QPDFObjectHandle&& oh) :
280
12.1M
            BaseDictionary(std::move(oh))
281
12.1M
        {
282
12.1M
        }
283
284
        Dictionary&
285
        operator=(QPDFObjectHandle&& oh)
286
940
        {
287
940
            assign(::ot_dictionary, std::move(oh));
288
940
            return *this;
289
940
        }
290
291
        ~Dictionary() = default;
292
    };
293
294
    class Integer final: public BaseHandle
295
    {
296
      public:
297
        Integer() = default;
298
        Integer(Integer const&) = default;
299
        Integer(Integer&&) = default;
300
        Integer& operator=(Integer const&) = default;
301
        Integer& operator=(Integer&&) = default;
302
        ~Integer() = default;
303
304
        explicit Integer(long long value);
305
306
        explicit Integer(std::integral auto value) :
307
90.6k
            Integer(static_cast<long long>(value))
308
90.6k
        {
309
            if constexpr (std::cmp_greater(
310
                              std::numeric_limits<decltype(value)>::max(),
311
90.6k
                              std::numeric_limits<long long>::max())) {
312
90.6k
                if (std::cmp_greater(value, std::numeric_limits<long long>::max())) {
313
0
                    throw std::overflow_error("overflow constructing Integer");
314
0
                }
315
90.6k
            }
316
90.6k
        }
Unexecuted instantiation: _ZN4qpdf7IntegerC2ITkNSt3__18integralEiEET_
_ZN4qpdf7IntegerC2ITkNSt3__18integralEmEET_
Line
Count
Source
307
90.6k
            Integer(static_cast<long long>(value))
308
90.6k
        {
309
            if constexpr (std::cmp_greater(
310
                              std::numeric_limits<decltype(value)>::max(),
311
90.6k
                              std::numeric_limits<long long>::max())) {
312
90.6k
                if (std::cmp_greater(value, std::numeric_limits<long long>::max())) {
313
0
                    throw std::overflow_error("overflow constructing Integer");
314
0
                }
315
90.6k
            }
316
90.6k
        }
317
318
        Integer(QPDFObjectHandle const& oh) :
319
3.51M
            BaseHandle(oh.type_code() == ::ot_integer ? oh : QPDFObjectHandle())
320
3.51M
        {
321
3.51M
        }
322
323
        Integer(QPDFObjectHandle&& oh) :
324
            BaseHandle(oh.type_code() == ::ot_integer ? std::move(oh) : QPDFObjectHandle())
325
0
        {
326
0
        }
327
328
        explicit
329
        operator bool() const
330
1.95M
        {
331
1.95M
            return obj != nullptr;
332
1.95M
        }
333
334
        // Return the integer value. If the object is not a valid Integer, throw a
335
        // std::invalid_argument exception. If the object is out of range for the target type,
336
        // throw a std::overflow_error or std::underflow_error exception.
337
        template <std::integral T>
338
        operator T() const
339
1.98M
        {
340
1.98M
            auto v = value();
341
342
1.98M
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
2.66k
                throw std::overflow_error("Integer conversion overflow");
344
2.66k
            }
345
1.98M
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
4.79k
                throw std::underflow_error("Integer conversion underflow");
347
4.79k
            }
348
1.98M
            return static_cast<T>(v);
349
1.98M
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEiEEv
Line
Count
Source
339
597k
        {
340
597k
            auto v = value();
341
342
597k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
1.45k
                throw std::overflow_error("Integer conversion overflow");
344
1.45k
            }
345
596k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
1.14k
                throw std::underflow_error("Integer conversion underflow");
347
1.14k
            }
348
595k
            return static_cast<T>(v);
349
596k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralExEEv
Line
Count
Source
339
895k
        {
340
895k
            auto v = value();
341
342
895k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
0
                throw std::overflow_error("Integer conversion overflow");
344
0
            }
345
895k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
0
                throw std::underflow_error("Integer conversion underflow");
347
0
            }
348
895k
            return static_cast<T>(v);
349
895k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEyEEv
Line
Count
Source
339
391k
        {
340
391k
            auto v = value();
341
342
391k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
0
                throw std::overflow_error("Integer conversion overflow");
344
0
            }
345
391k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
1.98k
                throw std::underflow_error("Integer conversion underflow");
347
1.98k
            }
348
389k
            return static_cast<T>(v);
349
391k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEjEEv
Line
Count
Source
339
102k
        {
340
102k
            auto v = value();
341
342
102k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
1.20k
                throw std::overflow_error("Integer conversion overflow");
344
1.20k
            }
345
101k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
1.65k
                throw std::underflow_error("Integer conversion underflow");
347
1.65k
            }
348
99.8k
            return static_cast<T>(v);
349
101k
        }
Unexecuted instantiation: _ZNK4qpdf7IntegercvT_ITkNSt3__18integralEmEEv
Unexecuted instantiation: _ZNK4qpdf7IntegercvT_ITkNSt3__18integralElEEv
350
351
        // Return the integer value. If the object is not a valid integer, throw a
352
        // std::invalid_argument exception.
353
        int64_t value() const;
354
355
        // Return the integer value. If the object is not a valid integer, throw a
356
        // std::invalid_argument exception. If the object is out of range for the target type,
357
        // replicate the existing QPDFObjectHandle behavior.
358
        template <std::integral T>
359
        T
360
        value() const
361
1.06M
        {
362
1.06M
            try {
363
1.06M
                return static_cast<T>(*this);
364
1.06M
            } catch (std::underflow_error&) {
365
4.79k
                if constexpr (std::is_same_v<T, int>) {
366
1.14k
                    warn("requested value of integer is too small; returning INT_MIN");
367
1.65k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
1.65k
                    warn("unsigned integer value request for negative number; returning 0");
369
1.98k
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
1.98k
                    warn("unsigned value request for negative number; returning 0");
371
1.98k
                } else {
372
0
                    warn(
373
0
                        "underflow while converting integer object; returning smallest possible "
374
0
                        "value");
375
0
                }
376
4.79k
                return std::numeric_limits<T>::min();
377
4.79k
            } catch (std::overflow_error&) {
378
2.64k
                if constexpr (std::is_same_v<T, int>) {
379
1.43k
                    warn("requested value of integer is too big; returning INT_MAX");
380
1.43k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
1.20k
                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
382
1.20k
                } else {
383
0
                    warn(
384
0
                        "overflow while converting integer object; returning largest possible "
385
0
                        "value");
386
0
                }
387
2.64k
                return std::numeric_limits<T>::max();
388
2.64k
            }
389
1.06M
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEiEET_v
Line
Count
Source
361
573k
        {
362
573k
            try {
363
573k
                return static_cast<T>(*this);
364
573k
            } catch (std::underflow_error&) {
365
1.14k
                if constexpr (std::is_same_v<T, int>) {
366
1.14k
                    warn("requested value of integer is too small; returning INT_MIN");
367
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
                    warn("unsigned integer value request for negative number; returning 0");
369
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
                    warn("unsigned value request for negative number; returning 0");
371
                } else {
372
                    warn(
373
                        "underflow while converting integer object; returning smallest possible "
374
                        "value");
375
                }
376
1.14k
                return std::numeric_limits<T>::min();
377
1.43k
            } catch (std::overflow_error&) {
378
1.43k
                if constexpr (std::is_same_v<T, int>) {
379
1.43k
                    warn("requested value of integer is too big; returning INT_MAX");
380
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
382
                } else {
383
                    warn(
384
                        "overflow while converting integer object; returning largest possible "
385
                        "value");
386
                }
387
1.43k
                return std::numeric_limits<T>::max();
388
1.43k
            }
389
573k
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEyEET_v
Line
Count
Source
361
391k
        {
362
391k
            try {
363
391k
                return static_cast<T>(*this);
364
391k
            } catch (std::underflow_error&) {
365
                if constexpr (std::is_same_v<T, int>) {
366
                    warn("requested value of integer is too small; returning INT_MIN");
367
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
                    warn("unsigned integer value request for negative number; returning 0");
369
1.98k
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
1.98k
                    warn("unsigned value request for negative number; returning 0");
371
                } else {
372
                    warn(
373
                        "underflow while converting integer object; returning smallest possible "
374
                        "value");
375
                }
376
1.98k
                return std::numeric_limits<T>::min();
377
1.98k
            } catch (std::overflow_error&) {
378
                if constexpr (std::is_same_v<T, int>) {
379
                    warn("requested value of integer is too big; returning INT_MAX");
380
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
382
0
                } else {
383
0
                    warn(
384
0
                        "overflow while converting integer object; returning largest possible "
385
0
                        "value");
386
0
                }
387
0
                return std::numeric_limits<T>::max();
388
0
            }
389
391k
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEjEET_v
Line
Count
Source
361
102k
        {
362
102k
            try {
363
102k
                return static_cast<T>(*this);
364
102k
            } catch (std::underflow_error&) {
365
                if constexpr (std::is_same_v<T, int>) {
366
                    warn("requested value of integer is too small; returning INT_MIN");
367
1.65k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
1.65k
                    warn("unsigned integer value request for negative number; returning 0");
369
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
                    warn("unsigned value request for negative number; returning 0");
371
                } else {
372
                    warn(
373
                        "underflow while converting integer object; returning smallest possible "
374
                        "value");
375
                }
376
1.65k
                return std::numeric_limits<T>::min();
377
1.65k
            } catch (std::overflow_error&) {
378
                if constexpr (std::is_same_v<T, int>) {
379
                    warn("requested value of integer is too big; returning INT_MAX");
380
1.20k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
1.20k
                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
382
                } else {
383
                    warn(
384
                        "overflow while converting integer object; returning largest possible "
385
                        "value");
386
                }
387
1.20k
                return std::numeric_limits<T>::max();
388
1.20k
            }
389
102k
        }
Unexecuted instantiation: _ZNK4qpdf7Integer5valueITkNSt3__18integralEmEET_v
390
391
        // Return true if object value is equal to the 'rhs' value. Return false if the object is
392
        // not a valid Integer.
393
        friend bool
394
        operator==(Integer const& lhs, std::integral auto rhs)
395
410k
        {
396
410k
            return lhs && std::cmp_equal(lhs.value(), rhs);
397
410k
        }
Unexecuted instantiation: _ZN4qpdfeqITkNSt3__18integralExEEbRKNS_7IntegerET_
_ZN4qpdfeqITkNSt3__18integralEiEEbRKNS_7IntegerET_
Line
Count
Source
395
410k
        {
396
410k
            return lhs && std::cmp_equal(lhs.value(), rhs);
397
410k
        }
Unexecuted instantiation: _ZN4qpdfeqITkNSt3__18integralEmEEbRKNS_7IntegerET_
398
399
        // Compare the object value to the 'rhs' value. Throw a std::invalid_argument exception if
400
        // the object is not a valid Integer.
401
        friend std::strong_ordering
402
        operator<=>(Integer const& lhs, std::integral auto rhs)
403
0
        {
404
0
            if (!lhs) {
405
0
                throw lhs.invalid_error("Integer");
406
0
            }
407
0
            if (std::cmp_less(lhs.value(), rhs)) {
408
0
                return std::strong_ordering::less;
409
0
            }
410
0
            return std::cmp_greater(lhs.value(), rhs) ? std::strong_ordering::greater
411
0
                                                      : std::strong_ordering::equal;
412
0
        }
Unexecuted instantiation: _ZN4qpdfssITkNSt3__18integralEiEENS1_15strong_orderingERKNS_7IntegerET_
Unexecuted instantiation: _ZN4qpdfssITkNSt3__18integralEmEENS1_15strong_orderingERKNS_7IntegerET_
413
    }; // class Integer
414
415
    bool
416
    operator==(std::integral auto lhs, Integer const& rhs)
417
0
    {
418
0
        return rhs == lhs;
419
0
    }
420
421
    std::strong_ordering
422
    operator<=>(std::integral auto lhs, Integer const& rhs)
423
    {
424
        return rhs <=> lhs;
425
    }
426
427
    class Name final: public BaseHandle
428
    {
429
      public:
430
        // Put # into strings with characters unsuitable for name token
431
        static std::string normalize(std::string const& name);
432
433
        // Check whether name is valid utf-8 and whether it contains characters that require
434
        // escaping. Return {false, false} if the name is not valid utf-8, otherwise return {true,
435
        // true} if no characters require or {true, false} if escaping is required.
436
        static std::pair<bool, bool> analyzeJSONEncoding(std::string const& name);
437
438
        Name() = default;
439
        Name(Name const&) = default;
440
        Name(Name&&) = default;
441
        Name& operator=(Name const&) = default;
442
        Name& operator=(Name&&) = default;
443
        ~Name() = default;
444
445
        explicit Name(std::string const&);
446
        explicit Name(std::string&&);
447
448
        Name(QPDFObjectHandle const& oh) :
449
6.51M
            BaseHandle(oh.type_code() == ::ot_name ? oh : QPDFObjectHandle())
450
6.51M
        {
451
6.51M
        }
452
453
        Name(QPDFObjectHandle&& oh) :
454
            BaseHandle(oh.type_code() == ::ot_name ? std::move(oh) : QPDFObjectHandle())
455
0
        {
456
0
        }
457
458
        // Return the name value. If the object is not a valid Name, throw a std::invalid_argument
459
        // exception.
460
        operator std::string() const&
461
316k
        {
462
316k
            return value();
463
316k
        }
464
465
        // Return the name value. If the object is not a valid name, throw a std::invalid_argument
466
        // exception.
467
        std::string const& value() const;
468
469
        // Return true if object value is equal to the 'rhs' value. Return false if the object is
470
        // not a valid Name.
471
        friend bool
472
        operator==(Name const& lhs, std::string_view rhs)
473
4.94M
        {
474
4.94M
            return lhs && lhs.value() == rhs;
475
4.94M
        }
476
    };
477
478
    class Null final: public BaseHandle
479
    {
480
      public:
481
        // Unlike other types, the Null default constructor creates a valid null object.
482
        Null() :
483
28
            BaseHandle(QPDFObject::create<QPDF_Null>())
484
28
        {
485
28
        }
486
487
        Null(Null const&) = default;
488
        Null(Null&&) = default;
489
        Null& operator=(Null const&) = default;
490
        Null& operator=(Null&&) = default;
491
        ~Null() = default;
492
493
        // For legacy support, return a Null object to be used as a temporary return value.
494
        static QPDFObjectHandle
495
        temp()
496
157k
        {
497
157k
            return temp_.oh();
498
157k
        }
499
500
        // For legacy support, return an explicit temporary Null object if oh is null.
501
        static QPDFObjectHandle
502
        if_null(QPDFObjectHandle oh)
503
29.2k
        {
504
29.2k
            return oh ? std::move(oh) : Null::temp();
505
29.2k
        }
506
507
      private:
508
        static const Null temp_;
509
    }; // class Null
510
511
    class Stream final: public BaseHandle
512
    {
513
      public:
514
        explicit Stream(std::shared_ptr<QPDFObject> const& obj) :
515
3.92M
            BaseHandle(obj)
516
3.92M
        {
517
3.92M
        }
518
519
        explicit Stream(std::shared_ptr<QPDFObject>&& obj) :
520
1.59M
            BaseHandle(std::move(obj))
521
1.59M
        {
522
1.59M
        }
523
524
        Stream() = default;
525
0
        Stream(Stream const&) = default;
526
0
        Stream(Stream&&) = default;
527
0
        Stream& operator=(Stream const&) = default;
528
14.3k
        Stream& operator=(Stream&&) = default;
529
        ~Stream() = default;
530
531
        Stream(QPDFObjectHandle const& oh) :
532
0
            BaseHandle(oh.type_code() == ::ot_stream ? oh : QPDFObjectHandle())
533
0
        {
534
0
        }
535
536
        Stream(QPDFObjectHandle&& oh) :
537
488k
            BaseHandle(oh.type_code() == ::ot_stream ? std::move(oh) : QPDFObjectHandle())
538
488k
        {
539
488k
        }
540
541
        Stream(
542
            QPDF& qpdf,
543
            QPDFObjGen og,
544
            QPDFObjectHandle stream_dict,
545
            qpdf_offset_t offset,
546
            size_t length);
547
548
        Stream copy();
549
550
        void copy_data_to(Stream& target);
551
552
        Dictionary
553
        getDict() const
554
1.97M
        {
555
1.97M
            return {stream()->stream_dict};
556
1.97M
        }
557
558
        /// @brief Returns the stream dictionary's `/Length` entry.
559
        ///
560
        /// @return A typed Integer handle for `/Length`, or an invalid Integer if not present.
561
        Integer
562
        Length() const
563
9.30k
        {
564
9.30k
            return {getDict()["/Length"]};
565
9.30k
        }
566
567
        /// @brief Sets the stream dictionary's `/Length` entry.
568
        ///
569
        /// @param val The typed Integer handle to store as `/Length`.
570
        void
571
        Length(Integer val)
572
0
        {
573
0
            qpdf_expect(val);
574
0
            getDict().replace("/Length", val);
575
0
        }
576
577
        /// @brief Sets the stream dictionary's `/Length` entry.
578
        ///
579
        /// @param val The value to store as `/Length`.
580
        void
581
        Length(std::integral auto val)
582
62.6k
        {
583
62.6k
            qpdf_expect(val >= 0);
584
62.6k
            getDict().replace("/Length", Integer(val));
585
62.6k
        }
_ZN4qpdf6Stream6LengthITkNSt3__18integralExEEvT_
Line
Count
Source
582
9.30k
        {
583
9.30k
            qpdf_expect(val >= 0);
584
9.30k
            getDict().replace("/Length", Integer(val));
585
9.30k
        }
_ZN4qpdf6Stream6LengthITkNSt3__18integralEmEEvT_
Line
Count
Source
582
53.3k
        {
583
53.3k
            qpdf_expect(val >= 0);
584
53.3k
            getDict().replace("/Length", Integer(val));
585
53.3k
        }
586
587
        /// @brief Returns the stream dictionary's `/Subtype` entry.
588
        ///
589
        /// @return A typed Name handle for `/Subtype`, or an invalid Name if not present.
590
        Name
591
        Subtype() const
592
20.0k
        {
593
20.0k
            return {getDict()["/Subtype"]};
594
20.0k
        }
595
596
        /// @brief Returns the stream dictionary's `/Type` entry.
597
        ///
598
        /// @return A typed Name handle for `/Type`, or an invalid Name if not present.
599
        Name
600
        Type() const
601
528k
        {
602
528k
            return {getDict()["/Type"]};
603
528k
        }
604
605
        bool
606
        isDataModified() const
607
423k
        {
608
423k
            return !stream()->token_filters.empty();
609
423k
        }
610
        void
611
        setFilterOnWrite(bool val)
612
110k
        {
613
110k
            stream()->filter_on_write = val;
614
110k
        }
615
        bool
616
        getFilterOnWrite() const
617
410k
        {
618
410k
            return stream()->filter_on_write;
619
410k
        }
620
621
        // Methods to help QPDF copy foreign streams
622
        size_t
623
        getLength() const
624
2.05k
        {
625
2.05k
            return stream()->length;
626
2.05k
        }
627
        std::shared_ptr<Buffer>
628
        getStreamDataBuffer() const
629
0
        {
630
0
            return stream()->stream_data;
631
0
        }
632
        std::shared_ptr<QPDFObjectHandle::StreamDataProvider>
633
        getStreamDataProvider() const
634
0
        {
635
0
            return stream()->stream_provider;
636
0
        }
637
638
        // See comments in QPDFObjectHandle.hh for these methods.
639
        bool pipeStreamData(
640
            Pipeline* p,
641
            bool* tried_filtering,
642
            int encode_flags,
643
            qpdf_stream_decode_level_e decode_level,
644
            bool suppress_warnings,
645
            bool will_retry);
646
        std::string getStreamData(qpdf_stream_decode_level_e level);
647
        std::string getRawStreamData();
648
        void replaceStreamData(
649
            std::string&& data,
650
            QPDFObjectHandle const& filter,
651
            QPDFObjectHandle const& decode_parms);
652
        void replaceStreamData(
653
            std::shared_ptr<Buffer> data,
654
            QPDFObjectHandle const& filter,
655
            QPDFObjectHandle const& decode_parms);
656
        void replaceStreamData(
657
            std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider,
658
            QPDFObjectHandle const& filter,
659
            QPDFObjectHandle const& decode_parms);
660
        void
661
        addTokenFilter(std::shared_ptr<QPDFObjectHandle::TokenFilter> token_filter)
662
0
        {
663
0
            stream()->token_filters.emplace_back(token_filter);
664
0
        }
665
        JSON getStreamJSON(
666
            int json_version,
667
            qpdf_json_stream_data_e json_data,
668
            qpdf_stream_decode_level_e decode_level,
669
            Pipeline* p,
670
            std::string const& data_filename);
671
        qpdf_stream_decode_level_e writeStreamJSON(
672
            int json_version,
673
            JSON::Writer& jw,
674
            qpdf_json_stream_data_e json_data,
675
            qpdf_stream_decode_level_e decode_level,
676
            Pipeline* p,
677
            std::string const& data_filename,
678
            bool no_data_key = false);
679
        void
680
        replaceDict(QPDFObjectHandle const& new_dict)
681
17.9k
        {
682
17.9k
            auto s = stream();
683
17.9k
            s->stream_dict = new_dict;
684
17.9k
            setDictDescription();
685
17.9k
        }
686
        bool isRootMetadata() const;
687
688
        void setDictDescription();
689
690
        static void registerStreamFilter(
691
            std::string const& filter_name,
692
            std::function<std::shared_ptr<QPDFStreamFilter>()> factory);
693
694
      private:
695
        QPDF_Stream::Members*
696
        stream() const
697
6.08M
        {
698
6.08M
            if (auto s = as<QPDF_Stream>()) {
699
6.08M
                if (auto ptr = s->m.get()) {
700
6.08M
                    return ptr;
701
6.08M
                }
702
53
                throw std::logic_error("QPDF_Stream: unexpected nullptr");
703
6.08M
            }
704
0
            throw std::runtime_error("operation for stream attempted on non-stream object");
705
0
            return nullptr; // unreachable
706
6.08M
        }
707
        bool filterable(
708
            qpdf_stream_decode_level_e decode_level,
709
            std::vector<std::shared_ptr<QPDFStreamFilter>>& filters);
710
        void replaceFilterData(
711
            QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length);
712
713
        void warn(std::string const& message);
714
715
        static std::map<std::string, std::string> filter_abbreviations;
716
    }; // class Stream
717
718
    class String final: public BaseHandle
719
    {
720
      public:
721
        String() = default;
722
        String(String const&) = default;
723
        String(String&&) = default;
724
        String& operator=(String const&) = default;
725
        String& operator=(String&&) = default;
726
        ~String() = default;
727
728
        explicit String(std::string const&);
729
        explicit String(std::string&&);
730
731
        String(QPDFObjectHandle const& oh) :
732
195k
            BaseHandle(oh.type_code() == ::ot_string ? oh : QPDFObjectHandle())
733
195k
        {
734
195k
        }
735
736
        String(QPDFObjectHandle&& oh) :
737
1.99M
            BaseHandle(oh.type_code() == ::ot_string ? std::move(oh) : QPDFObjectHandle())
738
1.99M
        {
739
1.99M
        }
740
741
        static String utf16(std::string const&);
742
743
        // Return the string value. If the object is not a valid string, throw a
744
        // std::invalid_argument exception.
745
        operator std::string() const&
746
10.0k
        {
747
10.0k
            return value();
748
10.0k
        }
749
750
        // Return the string value. If the object is not a valid string, throw a
751
        // std::invalid_argument exception.
752
        std::string const& value() const;
753
754
        // Return the string value. If the object is not a valid string, throw a
755
        // std::invalid_argument exception.
756
        std::string utf8_value() const;
757
758
        // Return true if object value is equal to the 'rhs' value. Return false if the object is
759
        // not a valid String.
760
        friend bool
761
        operator==(String const& lhs, std::string_view rhs)
762
0
        {
763
0
            return lhs && lhs.value() == rhs;
764
0
        }
765
    }; // class String
766
767
    template <typename T>
768
    T*
769
    BaseHandle::as() const
770
539M
    {
771
539M
        if (!obj) {
772
394M
            return nullptr;
773
394M
        }
774
144M
        if (std::holds_alternative<T>(obj->value)) {
775
91.1M
            return &std::get<T>(obj->value);
776
91.1M
        }
777
53.7M
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
2.84k
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
2.84k
        }
780
53.7M
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
53.7M
        return nullptr;
785
53.7M
    }
QPDF_Dictionary* qpdf::BaseHandle::as<QPDF_Dictionary>() const
Line
Count
Source
770
426M
    {
771
426M
        if (!obj) {
772
393M
            return nullptr;
773
393M
        }
774
32.5M
        if (std::holds_alternative<T>(obj->value)) {
775
31.6M
            return &std::get<T>(obj->value);
776
31.6M
        }
777
860k
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
2.84k
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
2.84k
        }
780
857k
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
857k
        return nullptr;
785
857k
    }
QPDF_Stream* qpdf::BaseHandle::as<QPDF_Stream>() const
Line
Count
Source
770
6.08M
    {
771
6.08M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
6.08M
        if (std::holds_alternative<T>(obj->value)) {
775
6.08M
            return &std::get<T>(obj->value);
776
6.08M
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
QPDF_Bool* qpdf::BaseHandle::as<QPDF_Bool>() const
Line
Count
Source
770
10.7k
    {
771
10.7k
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
10.7k
        if (std::holds_alternative<T>(obj->value)) {
775
10.7k
            return &std::get<T>(obj->value);
776
10.7k
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
QPDF_Integer* qpdf::BaseHandle::as<QPDF_Integer>() const
Line
Count
Source
770
2.33M
    {
771
2.33M
        if (!obj) {
772
14.9k
            return nullptr;
773
14.9k
        }
774
2.31M
        if (std::holds_alternative<T>(obj->value)) {
775
2.31M
            return &std::get<T>(obj->value);
776
2.31M
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
QPDF_Real* qpdf::BaseHandle::as<QPDF_Real>() const
Line
Count
Source
770
257k
    {
771
257k
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
257k
        if (std::holds_alternative<T>(obj->value)) {
775
257k
            return &std::get<T>(obj->value);
776
257k
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
QPDF_Name* qpdf::BaseHandle::as<QPDF_Name>() const
Line
Count
Source
770
3.52M
    {
771
3.52M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
3.52M
        if (std::holds_alternative<T>(obj->value)) {
775
3.51M
            return &std::get<T>(obj->value);
776
3.51M
        }
777
7.04k
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
2
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
2
        }
780
7.04k
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
7.04k
        return nullptr;
785
7.04k
    }
QPDF_String* qpdf::BaseHandle::as<QPDF_String>() const
Line
Count
Source
770
1.95M
    {
771
1.95M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
1.95M
        if (std::holds_alternative<T>(obj->value)) {
775
1.95M
            return &std::get<T>(obj->value);
776
1.95M
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
QPDF_Operator* qpdf::BaseHandle::as<QPDF_Operator>() const
Line
Count
Source
770
23.3M
    {
771
23.3M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
23.3M
        if (std::holds_alternative<T>(obj->value)) {
775
23.3M
            return &std::get<T>(obj->value);
776
23.3M
        }
777
0
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
0
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
0
        return nullptr;
785
0
    }
Unexecuted instantiation: QPDF_InlineImage* qpdf::BaseHandle::as<QPDF_InlineImage>() const
QPDF_Array* qpdf::BaseHandle::as<QPDF_Array>() const
Line
Count
Source
770
75.8M
    {
771
75.8M
        if (!obj) {
772
924k
            return nullptr;
773
924k
        }
774
74.9M
        if (std::holds_alternative<T>(obj->value)) {
775
22.0M
            return &std::get<T>(obj->value);
776
22.0M
        }
777
52.9M
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
0
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
0
        }
780
52.9M
        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
781
            // see comment in QPDF_Reference.
782
0
            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
783
0
        }
784
52.9M
        return nullptr;
785
52.9M
    }
786
787
    inline BaseHandle::BaseHandle(QPDFObjectHandle const& oh) :
788
418M
        obj(oh.obj)
789
418M
    {
790
418M
    }
791
792
    inline BaseHandle::BaseHandle(QPDFObjectHandle&& oh) :
793
14.5M
        obj(std::move(oh.obj))
794
14.5M
    {
795
14.5M
    }
796
797
    inline std::shared_ptr<QPDFObject> const&
798
    BaseHandle::obj_sp() const
799
5.61M
    {
800
5.61M
        return obj;
801
5.61M
    }
802
803
    inline QPDFObjectHandle
804
    BaseHandle::oh() const
805
1.12M
    {
806
1.12M
        return {obj};
807
1.12M
    }
808
809
    /// @brief Retrieve the QPDFObjectHandle for the object referenced by a reference object.
810
    ///
811
    /// Look up and return the object from the document's object table using QPDF::getObject(). The
812
    /// returned value is a QPDFObjectHandle that wraps the shared pointer to the underlying
813
    /// QPDFObject held in the document's cache.
814
    ///
815
    /// @note We must perform the lookup because qpdf represents certain replacements using
816
    ///       QPDF_Reference. In particular, `QPDF::makeIndirectObject` used to make the input
817
    ///       object indirect and then return the original input object. To replicate that
818
    ///       existing behavior the implementation now makes the input object indirect and
819
    ///       returns it, while modifying the input object to become a reference to the
820
    ///       newly-created indirect object. Looking up the resulting indirect object in the
821
    ///       document's object table via `QPDF::getObject()` ensures callers receive the
822
    ///       cached object and avoids surprises if the indirect object is subsequently
823
    ///       replaced.
824
    ///
825
    /// @return The QPDFObjectHandle for the object referenced by a reference object.
826
    ///
827
    /// @since 12.3.3
828
    inline QPDFObjectHandle
829
    BaseHandle::referenced_object() const
830
0
    {
831
0
        qpdf_expect(resolved_type_code() == ::ot_reserved);
832
0
        qpdf_expect(obj->qpdf);
833
0
        return obj->qpdf->getObject(obj->og);
834
0
    }
835
836
    inline void
837
    BaseHandle::assign(qpdf_object_type_e required, BaseHandle const& other)
838
251k
    {
839
251k
        if (obj != other.obj) {
840
118k
            obj = other.resolved_type_code() == required ? other.obj : nullptr;
841
118k
        }
842
251k
    }
843
844
    inline void
845
    BaseHandle::assign(qpdf_object_type_e required, BaseHandle&& other)
846
940
    {
847
940
        if (obj != other.obj) {
848
505
            obj = other.resolved_type_code() == required ? std::move(other.obj) : nullptr;
849
505
        }
850
940
    }
851
852
    inline QPDFObjGen
853
    BaseHandle::id_gen() const
854
4.02M
    {
855
4.02M
        return obj ? obj->og : QPDFObjGen();
856
4.02M
    }
857
858
    inline bool
859
    BaseHandle::indirect() const
860
308M
    {
861
308M
        return obj ? obj->og.isIndirect() : false;
862
308M
    }
863
864
    inline void
865
    BaseHandle::no_ci_stop_if(bool condition, std::string const& message) const
866
0
    {
867
0
        if (condition) {
868
0
            if (qpdf()) {
869
0
                throw QPDFExc(qpdf_e_damaged_pdf, "", description(), 0, message);
870
0
            }
871
0
            throw std::runtime_error(message);
872
0
        }
873
0
    }
874
875
    inline void
876
    BaseHandle::no_ci_stop_damaged_if(bool condition, std::string const& message) const
877
12.2k
    {
878
12.2k
        if (condition) {
879
0
            throw std::runtime_error(message);
880
0
        }
881
12.2k
    }
882
883
    inline void
884
    BaseHandle::no_ci_warn_if(bool condition, std::string const& warning) const
885
28.5k
    {
886
28.5k
        if (condition) {
887
0
            warn(warning);
888
0
        }
889
28.5k
    }
890
891
    /// @brief Retrieves the QPDFObjectHandle const& associated with the given key.
892
    ///
893
    /// This method provides a convenience alternative to the direct use of the subscript operator
894
    /// "(*this)[key]" or "oh()[key]" in derived classes, enabling a simplified and readable way to
895
    /// access object handles by key.
896
    ///
897
    /// @param key The string key used to look up the corresponding QPDFObjectHandle.
898
    /// @return A constant reference to the QPDFObjectHandle associated with the specified key.
899
    inline QPDFObjectHandle const&
900
    BaseHandle::get(std::string const& key) const
901
6.91M
    {
902
6.91M
        return (*this)[key];
903
6.91M
    }
904
905
    inline bool
906
    BaseHandle::null() const
907
26.2M
    {
908
26.2M
        return !obj || type_code() == ::ot_null;
909
26.2M
    }
910
911
    inline void
912
    BaseHandle::nullify()
913
0
    {
914
0
        if (obj) {
915
0
            obj = QPDFObject::create<QPDF_Null>();
916
0
        }
917
0
    }
918
919
    inline qpdf_offset_t
920
    BaseHandle::offset() const
921
1.47M
    {
922
1.47M
        return obj ? obj->parsed_offset : -1;
923
1.47M
    }
924
925
    inline QPDF*
926
    BaseHandle::qpdf() const
927
25.8M
    {
928
25.8M
        return obj ? obj->qpdf : nullptr;
929
25.8M
    }
930
931
    inline qpdf_object_type_e
932
    BaseHandle::raw_type_code() const
933
1.60G
    {
934
1.60G
        return obj ? static_cast<qpdf_object_type_e>(obj->value.index()) : ::ot_uninitialized;
935
1.60G
    }
936
937
    inline qpdf_object_type_e
938
    BaseHandle::resolved_type_code() const
939
460M
    {
940
460M
        if (!obj) {
941
694k
            return ::ot_uninitialized;
942
694k
        }
943
460M
        if (raw_type_code() == ::ot_unresolved) {
944
5.77k
            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
945
5.77k
        }
946
460M
        return raw_type_code();
947
460M
    }
948
949
    inline qpdf_object_type_e
950
    BaseHandle::type_code() const
951
204M
    {
952
204M
        if (!obj) {
953
3.79M
            return ::ot_uninitialized;
954
3.79M
        }
955
200M
        if (raw_type_code() == ::ot_unresolved) {
956
3.10M
            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
957
3.10M
        }
958
197M
        if (raw_type_code() == ::ot_reference) {
959
1.38k
            return std::get<QPDF_Reference>(obj->value).obj->getTypeCode();
960
1.38k
        }
961
197M
        return raw_type_code();
962
197M
    }
963
964
} // namespace qpdf
965
966
inline QPDF_Dictionary::QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items) :
967
2.63M
    items(std::move(items))
968
2.63M
{
969
2.63M
}
970
971
inline std::shared_ptr<QPDFObject>
972
QPDF_Null::create(
973
    std::shared_ptr<QPDFObject> parent, std::string_view const& static_descr, std::string var_descr)
974
2.60M
{
975
2.60M
    auto n = QPDFObject::create<QPDF_Null>();
976
2.60M
    n->setChildDescription(parent->getQPDF(), parent, static_descr, var_descr);
977
2.60M
    return n;
978
2.60M
}
979
980
inline QPDF_Real::QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes) :
981
433k
    val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes))
982
433k
{
983
433k
}
984
985
template <typename T, typename... Args>
986
inline std::shared_ptr<QPDFObject>
987
QPDFObject::create(Args&&... args)
988
147M
{
989
147M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
147M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Null>()
Line
Count
Source
988
8.29M
{
989
8.29M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
8.29M
}
Unexecuted instantiation: std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Reserved>()
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Dictionary, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > > const&>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > > const&)
Line
Count
Source
988
839k
{
989
839k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
839k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Dictionary, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > > >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > >&&)
Line
Count
Source
988
2.63M
{
989
2.63M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
2.63M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Bool, bool&>(bool&)
Line
Count
Source
988
10.9k
{
989
10.9k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
10.9k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Integer, long long&>(long long&)
Line
Count
Source
988
37.8M
{
989
37.8M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
37.8M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Real, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
988
124k
{
989
124k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
124k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_String, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
988
571k
{
989
571k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
571k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Name, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Line
Count
Source
988
652k
{
989
652k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
652k
}
Unexecuted instantiation: std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, QPDF_Array const&>(QPDF_Array const&)
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, QPDF_Array>(QPDF_Array&&)
Line
Count
Source
988
1.23k
{
989
1.23k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.23k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> >, bool>(std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> >&&, bool&&)
Line
Count
Source
988
86.9k
{
989
86.9k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
86.9k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Dictionary, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > >&>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, QPDFObjectHandle, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, QPDFObjectHandle> > >&)
Line
Count
Source
988
134k
{
989
134k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
134k
}
Unexecuted instantiation: std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Operator, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_InlineImage, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Name, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
988
62.4M
{
989
62.4M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
62.4M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Name, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
988
295k
{
989
295k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
295k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_String, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
988
2.56M
{
989
2.56M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
2.56M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_String, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
988
10.5k
{
989
10.5k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
10.5k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Real, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
988
1.63M
{
989
1.63M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.63M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Real, double&, int&, bool&>(double&, int&, bool&)
Line
Count
Source
988
433k
{
989
433k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
433k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Operator, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
988
24.4M
{
989
24.4M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
24.4M
}
Unexecuted instantiation: std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_InlineImage, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> > const&>(std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> > const&)
Line
Count
Source
988
198k
{
989
198k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
198k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> >&>(std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> >&)
Line
Count
Source
988
36.9k
{
989
36.9k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
36.9k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Bool, bool>(bool&&)
Line
Count
Source
988
155k
{
989
155k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
155k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Integer, long long>(long long&&)
Line
Count
Source
988
2.09M
{
989
2.09M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
2.09M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Array, std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> > >(std::__1::vector<QPDFObjectHandle, std::__1::allocator<QPDFObjectHandle> >&&)
Line
Count
Source
988
1.64M
{
989
1.64M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.64M
}
991
992
inline qpdf_object_type_e
993
QPDFObject::getResolvedTypeCode() const
994
0
{
995
0
    if (getTypeCode() == ::ot_unresolved) {
996
0
        return QPDF::Doc::Resolver::resolved(qpdf, og)->getTypeCode();
997
0
    }
998
0
    if (getTypeCode() == ::ot_reference) {
999
0
        return std::get<QPDF_Reference>(value).obj->getTypeCode();
1000
0
    }
1001
0
    return getTypeCode();
1002
0
}
1003
1004
inline qpdf::Array
1005
QPDFObjectHandle::as_array(qpdf::typed options) const
1006
33.6M
{
1007
33.6M
    if (options & qpdf::error) {
1008
0
        assertType("array", false);
1009
0
    }
1010
33.6M
    if (options & qpdf::any_flag || type_code() == ::ot_array ||
1011
33.2M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1012
33.2M
        return qpdf::Array(obj);
1013
33.2M
    }
1014
398k
    return qpdf::Array(std::shared_ptr<QPDFObject>());
1015
33.6M
}
1016
1017
inline qpdf::Dictionary
1018
QPDFObjectHandle::as_dictionary(qpdf::typed options) const
1019
3.82M
{
1020
3.82M
    if (options & qpdf::any_flag || type_code() == ::ot_dictionary ||
1021
3.71M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1022
3.71M
        return qpdf::Dictionary(obj);
1023
3.71M
    }
1024
108k
    if (options & qpdf::error) {
1025
0
        assertType("dictionary", false);
1026
0
    }
1027
108k
    return qpdf::Dictionary(std::shared_ptr<QPDFObject>());
1028
3.82M
}
1029
1030
inline qpdf::Stream
1031
QPDFObjectHandle::as_stream(qpdf::typed options) const
1032
5.55M
{
1033
5.55M
    if (options & qpdf::any_flag || type_code() == ::ot_stream ||
1034
3.92M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1035
3.92M
        return qpdf::Stream(obj);
1036
3.92M
    }
1037
1.63M
    if (options & qpdf::error) {
1038
381
        assertType("stream", false);
1039
381
    }
1040
1.63M
    return qpdf::Stream(std::shared_ptr<QPDFObject>());
1041
5.55M
}
1042
1043
#endif // OBJECTHANDLE_PRIVATE_HH