Coverage Report

Created: 2026-04-15 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
22.8k
        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
22.8k
        {
37
22.8k
            if (obj != other.obj) {
38
22.8k
                obj = other.obj;
39
22.8k
            }
40
22.8k
            return *this;
41
22.8k
        }
42
43
        Array(Array&&) = default;
44
        Array& operator=(Array&&) = default;
45
46
        explicit Array(std::shared_ptr<QPDFObject> const& obj) :
47
15.3M
            BaseHandle(obj)
48
15.3M
        {
49
15.3M
        }
50
51
        explicit Array(std::shared_ptr<QPDFObject>&& obj) :
52
278k
            BaseHandle(std::move(obj))
53
278k
        {
54
278k
        }
55
56
        Array(QPDFObjectHandle const& oh) :
57
66.3M
            BaseHandle(oh.resolved_type_code() == ::ot_array ? oh : QPDFObjectHandle())
58
66.3M
        {
59
66.3M
        }
60
61
        Array&
62
        operator=(QPDFObjectHandle const& oh)
63
90.1k
        {
64
90.1k
            assign(::ot_array, oh);
65
90.1k
            return *this;
66
90.1k
        }
67
68
        Array(QPDFObjectHandle&& oh) :
69
556
            BaseHandle(oh.resolved_type_code() == ::ot_array ? std::move(oh) : QPDFObjectHandle())
70
556
        {
71
556
        }
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
65.0M
        {
142
65.0M
            if (auto d = as<QPDF_Dictionary>()) {
143
3.86M
                return d->items.begin();
144
3.86M
            }
145
61.1M
            return {};
146
65.0M
        }
147
148
        iterator
149
        end()
150
65.0M
        {
151
65.0M
            if (auto d = as<QPDF_Dictionary>()) {
152
3.86M
                return d->items.end();
153
3.86M
            }
154
61.1M
            return {};
155
65.0M
        }
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
380k
        {
196
380k
            if (auto d = as<QPDF_Dictionary>()) {
197
380k
                return d->items.crbegin();
198
380k
            }
199
0
            return {};
200
380k
        }
201
202
        const_reverse_iterator
203
        crend()
204
380k
        {
205
380k
            if (auto d = as<QPDF_Dictionary>()) {
206
380k
                return d->items.crend();
207
380k
            }
208
0
            return {};
209
380k
        }
210
211
      protected:
212
92.1k
        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
90.3k
            BaseHandle(QPDFObject::create<QPDF_Dictionary>(std::move(dict)))
221
90.3k
        {
222
90.3k
        }
223
224
        explicit BaseDictionary(std::shared_ptr<QPDFObject> const& obj) :
225
3.93M
            BaseHandle(obj)
226
3.93M
        {
227
3.93M
        }
228
        explicit BaseDictionary(std::shared_ptr<QPDFObject>&& obj) :
229
            BaseHandle(std::move(obj))
230
0
        {
231
0
        }
232
269k
        BaseDictionary(BaseDictionary const&) = default;
233
20.7k
        BaseDictionary& operator=(BaseDictionary const&) = default;
234
9.00k
        BaseDictionary(BaseDictionary&&) = default;
235
107k
        BaseDictionary& operator=(BaseDictionary&&) = default;
236
237
        explicit BaseDictionary(QPDFObjectHandle const& oh) :
238
66.2M
            BaseHandle(oh.resolved_type_code() == ::ot_dictionary ? oh : QPDFObjectHandle())
239
66.2M
        {
240
66.2M
        }
241
242
        explicit BaseDictionary(QPDFObjectHandle&& oh) :
243
490k
            BaseHandle(
244
490k
                oh.resolved_type_code() == ::ot_dictionary ? std::move(oh) : QPDFObjectHandle())
245
490k
        {
246
490k
        }
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
92.1k
        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
217k
        Dictionary(Dictionary const&) = default;
263
20.7k
        Dictionary& operator=(Dictionary const&) = default;
264
9.00k
        Dictionary(Dictionary&&) = default;
265
10.2k
        Dictionary& operator=(Dictionary&&) = default;
266
267
        Dictionary(QPDFObjectHandle const& oh) :
268
65.9M
            BaseDictionary(oh)
269
65.9M
        {
270
65.9M
        }
271
272
        Dictionary&
273
        operator=(QPDFObjectHandle const& oh)
274
90.2k
        {
275
90.2k
            assign(::ot_dictionary, oh);
276
90.2k
            return *this;
277
90.2k
        }
278
279
        Dictionary(QPDFObjectHandle&& oh) :
280
490k
            BaseDictionary(std::move(oh))
281
490k
        {
282
490k
        }
283
284
        Dictionary&
285
        operator=(QPDFObjectHandle&& oh)
286
597
        {
287
597
            assign(::ot_dictionary, std::move(oh));
288
597
            return *this;
289
597
        }
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
63.7k
            Integer(static_cast<long long>(value))
308
63.7k
        {
309
            if constexpr (std::cmp_greater(
310
                              std::numeric_limits<decltype(value)>::max(),
311
63.7k
                              std::numeric_limits<long long>::max())) {
312
63.7k
                if (std::cmp_greater(value, std::numeric_limits<long long>::max())) {
313
0
                    throw std::overflow_error("overflow constructing Integer");
314
0
                }
315
63.7k
            }
316
63.7k
        }
Unexecuted instantiation: _ZN4qpdf7IntegerC2ITkNSt3__18integralEiEET_
_ZN4qpdf7IntegerC2ITkNSt3__18integralEmEET_
Line
Count
Source
307
63.7k
            Integer(static_cast<long long>(value))
308
63.7k
        {
309
            if constexpr (std::cmp_greater(
310
                              std::numeric_limits<decltype(value)>::max(),
311
63.7k
                              std::numeric_limits<long long>::max())) {
312
63.7k
                if (std::cmp_greater(value, std::numeric_limits<long long>::max())) {
313
0
                    throw std::overflow_error("overflow constructing Integer");
314
0
                }
315
63.7k
            }
316
63.7k
        }
317
318
        Integer(QPDFObjectHandle const& oh) :
319
2.90M
            BaseHandle(oh.type_code() == ::ot_integer ? oh : QPDFObjectHandle())
320
2.90M
        {
321
2.90M
        }
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.72M
        {
331
1.72M
            return obj != nullptr;
332
1.72M
        }
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.74M
        {
340
1.74M
            auto v = value();
341
342
1.74M
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
1.85k
                throw std::overflow_error("Integer conversion overflow");
344
1.85k
            }
345
1.73M
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
3.67k
                throw std::underflow_error("Integer conversion underflow");
347
3.67k
            }
348
1.73M
            return static_cast<T>(v);
349
1.73M
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEiEEv
Line
Count
Source
339
451k
        {
340
451k
            auto v = value();
341
342
451k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
919
                throw std::overflow_error("Integer conversion overflow");
344
919
            }
345
450k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
852
                throw std::underflow_error("Integer conversion underflow");
347
852
            }
348
450k
            return static_cast<T>(v);
349
450k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralExEEv
Line
Count
Source
339
920k
        {
340
920k
            auto v = value();
341
342
920k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
0
                throw std::overflow_error("Integer conversion overflow");
344
0
            }
345
920k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
0
                throw std::underflow_error("Integer conversion underflow");
347
0
            }
348
920k
            return static_cast<T>(v);
349
920k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEyEEv
Line
Count
Source
339
292k
        {
340
292k
            auto v = value();
341
342
292k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
0
                throw std::overflow_error("Integer conversion overflow");
344
0
            }
345
292k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
1.69k
                throw std::underflow_error("Integer conversion underflow");
347
1.69k
            }
348
290k
            return static_cast<T>(v);
349
292k
        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEjEEv
Line
Count
Source
339
76.0k
        {
340
76.0k
            auto v = value();
341
342
76.0k
            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
343
935
                throw std::overflow_error("Integer conversion overflow");
344
935
            }
345
75.1k
            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
346
1.12k
                throw std::underflow_error("Integer conversion underflow");
347
1.12k
            }
348
73.9k
            return static_cast<T>(v);
349
75.1k
        }
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
806k
        {
362
806k
            try {
363
806k
                return static_cast<T>(*this);
364
806k
            } catch (std::underflow_error&) {
365
3.67k
                if constexpr (std::is_same_v<T, int>) {
366
852
                    warn("requested value of integer is too small; returning INT_MIN");
367
1.12k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
1.12k
                    warn("unsigned integer value request for negative number; returning 0");
369
1.69k
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
1.69k
                    warn("unsigned value request for negative number; returning 0");
371
1.69k
                } else {
372
0
                    warn(
373
0
                        "underflow while converting integer object; returning smallest possible "
374
0
                        "value");
375
0
                }
376
3.67k
                return std::numeric_limits<T>::min();
377
3.67k
            } catch (std::overflow_error&) {
378
1.85k
                if constexpr (std::is_same_v<T, int>) {
379
916
                    warn("requested value of integer is too big; returning INT_MAX");
380
935
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
935
                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
382
935
                } else {
383
0
                    warn(
384
0
                        "overflow while converting integer object; returning largest possible "
385
0
                        "value");
386
0
                }
387
1.85k
                return std::numeric_limits<T>::max();
388
1.85k
            }
389
806k
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEiEET_v
Line
Count
Source
361
437k
        {
362
437k
            try {
363
437k
                return static_cast<T>(*this);
364
437k
            } catch (std::underflow_error&) {
365
852
                if constexpr (std::is_same_v<T, int>) {
366
852
                    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
852
                return std::numeric_limits<T>::min();
377
916
            } catch (std::overflow_error&) {
378
916
                if constexpr (std::is_same_v<T, int>) {
379
916
                    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
916
                return std::numeric_limits<T>::max();
388
916
            }
389
437k
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEyEET_v
Line
Count
Source
361
292k
        {
362
292k
            try {
363
292k
                return static_cast<T>(*this);
364
292k
            } 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.69k
                } else if constexpr (std::is_same_v<T, unsigned long long>) {
370
1.69k
                    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.69k
                return std::numeric_limits<T>::min();
377
1.69k
            } 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
292k
        }
_ZNK4qpdf7Integer5valueITkNSt3__18integralEjEET_v
Line
Count
Source
361
76.0k
        {
362
76.0k
            try {
363
76.0k
                return static_cast<T>(*this);
364
76.0k
            } 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.12k
                } else if constexpr (std::is_same_v<T, unsigned int>) {
368
1.12k
                    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.12k
                return std::numeric_limits<T>::min();
377
1.12k
            } 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
935
                } else if constexpr (std::is_same_v<T, unsigned int>) {
381
935
                    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
935
                return std::numeric_limits<T>::max();
388
935
            }
389
76.0k
        }
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
307k
        {
396
307k
            return lhs && std::cmp_equal(lhs.value(), rhs);
397
307k
        }
Unexecuted instantiation: _ZN4qpdfeqITkNSt3__18integralExEEbRKNS_7IntegerET_
_ZN4qpdfeqITkNSt3__18integralEiEEbRKNS_7IntegerET_
Line
Count
Source
395
307k
        {
396
307k
            return lhs && std::cmp_equal(lhs.value(), rhs);
397
307k
        }
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
5.03M
            BaseHandle(oh.type_code() == ::ot_name ? oh : QPDFObjectHandle())
450
5.03M
        {
451
5.03M
        }
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
192k
        {
462
192k
            return value();
463
192k
        }
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.64M
        {
474
4.64M
            return lhs && lhs.value() == rhs;
475
4.64M
        }
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
103k
        {
497
103k
            return temp_.oh();
498
103k
        }
499
500
        // For legacy support, return an explicit temporary Null object if oh is null.
501
        static QPDFObjectHandle
502
        if_null(QPDFObjectHandle oh)
503
17.2k
        {
504
17.2k
            return oh ? std::move(oh) : Null::temp();
505
17.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
2.94M
            BaseHandle(obj)
516
2.94M
        {
517
2.94M
        }
518
519
        explicit Stream(std::shared_ptr<QPDFObject>&& obj) :
520
1.40M
            BaseHandle(std::move(obj))
521
1.40M
        {
522
1.40M
        }
523
524
        Stream() = default;
525
0
        Stream(Stream const&) = default;
526
0
        Stream(Stream&&) = default;
527
0
        Stream& operator=(Stream const&) = default;
528
8.27k
        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
296k
            BaseHandle(oh.type_code() == ::ot_stream ? std::move(oh) : QPDFObjectHandle())
538
296k
        {
539
296k
        }
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.48M
        {
555
1.48M
            return {stream()->stream_dict};
556
1.48M
        }
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
5.96k
        {
564
5.96k
            return {getDict()["/Length"]};
565
5.96k
        }
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
39.6k
        {
583
39.6k
            qpdf_expect(val >= 0);
584
39.6k
            getDict().replace("/Length", Integer(val));
585
39.6k
        }
_ZN4qpdf6Stream6LengthITkNSt3__18integralExEEvT_
Line
Count
Source
582
5.96k
        {
583
5.96k
            qpdf_expect(val >= 0);
584
5.96k
            getDict().replace("/Length", Integer(val));
585
5.96k
        }
_ZN4qpdf6Stream6LengthITkNSt3__18integralEmEEvT_
Line
Count
Source
582
33.6k
        {
583
33.6k
            qpdf_expect(val >= 0);
584
33.6k
            getDict().replace("/Length", Integer(val));
585
33.6k
        }
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
14.1k
        {
593
14.1k
            return {getDict()["/Subtype"]};
594
14.1k
        }
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
389k
        {
602
389k
            return {getDict()["/Type"]};
603
389k
        }
604
605
        bool
606
        isDataModified() const
607
336k
        {
608
336k
            return !stream()->token_filters.empty();
609
336k
        }
610
        void
611
        setFilterOnWrite(bool val)
612
77.4k
        {
613
77.4k
            stream()->filter_on_write = val;
614
77.4k
        }
615
        bool
616
        getFilterOnWrite() const
617
307k
        {
618
307k
            return stream()->filter_on_write;
619
307k
        }
620
621
        // Methods to help QPDF copy foreign streams
622
        size_t
623
        getLength() const
624
416
        {
625
416
            return stream()->length;
626
416
        }
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
12.5k
        {
682
12.5k
            auto s = stream();
683
12.5k
            s->stream_dict = new_dict;
684
12.5k
            setDictDescription();
685
12.5k
        }
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
4.44M
        {
698
4.44M
            if (auto s = as<QPDF_Stream>()) {
699
4.44M
                if (auto ptr = s->m.get()) {
700
4.44M
                    return ptr;
701
4.44M
                }
702
100
                throw std::logic_error("QPDF_Stream: unexpected nullptr");
703
4.44M
            }
704
0
            throw std::runtime_error("operation for stream attempted on non-stream object");
705
0
            return nullptr; // unreachable
706
4.44M
        }
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
207k
            BaseHandle(oh.type_code() == ::ot_string ? oh : QPDFObjectHandle())
733
207k
        {
734
207k
        }
735
736
        String(QPDFObjectHandle&& oh) :
737
1.29M
            BaseHandle(oh.type_code() == ::ot_string ? std::move(oh) : QPDFObjectHandle())
738
1.29M
        {
739
1.29M
        }
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
0
        {
747
0
            return value();
748
0
        }
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
196M
    {
771
196M
        if (!obj) {
772
123M
            return nullptr;
773
123M
        }
774
73.1M
        if (std::holds_alternative<T>(obj->value)) {
775
52.0M
            return &std::get<T>(obj->value);
776
52.0M
        }
777
21.0M
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
1.95k
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
1.95k
        }
780
21.0M
        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
21.0M
        return nullptr;
785
21.0M
    }
QPDF_Dictionary* qpdf::BaseHandle::as<QPDF_Dictionary>() const
Line
Count
Source
770
147M
    {
771
147M
        if (!obj) {
772
122M
            return nullptr;
773
122M
        }
774
25.4M
        if (std::holds_alternative<T>(obj->value)) {
775
25.3M
            return &std::get<T>(obj->value);
776
25.3M
        }
777
140k
        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
778
1.95k
            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
779
1.95k
        }
780
138k
        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
138k
        return nullptr;
785
138k
    }
QPDF_Stream* qpdf::BaseHandle::as<QPDF_Stream>() const
Line
Count
Source
770
4.44M
    {
771
4.44M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
4.44M
        if (std::holds_alternative<T>(obj->value)) {
775
4.44M
            return &std::get<T>(obj->value);
776
4.44M
        }
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
5.21k
    {
771
5.21k
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
5.21k
        if (std::holds_alternative<T>(obj->value)) {
775
5.21k
            return &std::get<T>(obj->value);
776
5.21k
        }
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
1.99M
    {
771
1.99M
        if (!obj) {
772
11.3k
            return nullptr;
773
11.3k
        }
774
1.98M
        if (std::holds_alternative<T>(obj->value)) {
775
1.98M
            return &std::get<T>(obj->value);
776
1.98M
        }
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
158k
    {
771
158k
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
158k
        if (std::holds_alternative<T>(obj->value)) {
775
158k
            return &std::get<T>(obj->value);
776
158k
        }
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
2.81M
    {
771
2.81M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
2.81M
        if (std::holds_alternative<T>(obj->value)) {
775
2.81M
            return &std::get<T>(obj->value);
776
2.81M
        }
777
4.31k
        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
4.31k
        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
4.31k
        return nullptr;
785
4.31k
    }
QPDF_String* qpdf::BaseHandle::as<QPDF_String>() const
Line
Count
Source
770
1.38M
    {
771
1.38M
        if (!obj) {
772
1.20k
            return nullptr;
773
1.20k
        }
774
1.38M
        if (std::holds_alternative<T>(obj->value)) {
775
1.38M
            return &std::get<T>(obj->value);
776
1.38M
        }
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
2.09M
    {
771
2.09M
        if (!obj) {
772
0
            return nullptr;
773
0
        }
774
2.09M
        if (std::holds_alternative<T>(obj->value)) {
775
2.09M
            return &std::get<T>(obj->value);
776
2.09M
        }
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
35.4M
    {
771
35.4M
        if (!obj) {
772
682k
            return nullptr;
773
682k
        }
774
34.7M
        if (std::holds_alternative<T>(obj->value)) {
775
13.8M
            return &std::get<T>(obj->value);
776
13.8M
        }
777
20.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
20.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
20.9M
        return nullptr;
785
20.9M
    }
786
787
    inline BaseHandle::BaseHandle(QPDFObjectHandle const& oh) :
788
140M
        obj(oh.obj)
789
140M
    {
790
140M
    }
791
792
    inline BaseHandle::BaseHandle(QPDFObjectHandle&& oh) :
793
2.05M
        obj(std::move(oh.obj))
794
2.05M
    {
795
2.05M
    }
796
797
    inline std::shared_ptr<QPDFObject> const&
798
    BaseHandle::obj_sp() const
799
4.01M
    {
800
4.01M
        return obj;
801
4.01M
    }
802
803
    inline QPDFObjectHandle
804
    BaseHandle::oh() const
805
855k
    {
806
855k
        return {obj};
807
855k
    }
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
180k
    {
839
180k
        if (obj != other.obj) {
840
81.4k
            obj = other.resolved_type_code() == required ? other.obj : nullptr;
841
81.4k
        }
842
180k
    }
843
844
    inline void
845
    BaseHandle::assign(qpdf_object_type_e required, BaseHandle&& other)
846
597
    {
847
597
        if (obj != other.obj) {
848
420
            obj = other.resolved_type_code() == required ? std::move(other.obj) : nullptr;
849
420
        }
850
597
    }
851
852
    inline QPDFObjGen
853
    BaseHandle::id_gen() const
854
1.93M
    {
855
1.93M
        return obj ? obj->og : QPDFObjGen();
856
1.93M
    }
857
858
    inline bool
859
    BaseHandle::indirect() const
860
126M
    {
861
126M
        return obj ? obj->og.isIndirect() : false;
862
126M
    }
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
7.85k
    {
878
7.85k
        if (condition) {
879
0
            throw std::runtime_error(message);
880
0
        }
881
7.85k
    }
882
883
    inline void
884
    BaseHandle::no_ci_warn_if(bool condition, std::string const& warning) const
885
15.8k
    {
886
15.8k
        if (condition) {
887
0
            warn(warning);
888
0
        }
889
15.8k
    }
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
5.28M
    {
902
5.28M
        return (*this)[key];
903
5.28M
    }
904
905
    inline bool
906
    BaseHandle::null() const
907
19.5M
    {
908
19.5M
        return !obj || type_code() == ::ot_null;
909
19.5M
    }
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.03M
    {
922
1.03M
        return obj ? obj->parsed_offset : -1;
923
1.03M
    }
924
925
    inline QPDF*
926
    BaseHandle::qpdf() const
927
18.3M
    {
928
18.3M
        return obj ? obj->qpdf : nullptr;
929
18.3M
    }
930
931
    inline qpdf_object_type_e
932
    BaseHandle::raw_type_code() const
933
740M
    {
934
740M
        return obj ? static_cast<qpdf_object_type_e>(obj->value.index()) : ::ot_uninitialized;
935
740M
    }
936
937
    inline qpdf_object_type_e
938
    BaseHandle::resolved_type_code() const
939
152M
    {
940
152M
        if (!obj) {
941
307k
            return ::ot_uninitialized;
942
307k
        }
943
152M
        if (raw_type_code() == ::ot_unresolved) {
944
5.86k
            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
945
5.86k
        }
946
152M
        return raw_type_code();
947
152M
    }
948
949
    inline qpdf_object_type_e
950
    BaseHandle::type_code() const
951
134M
    {
952
134M
        if (!obj) {
953
2.75M
            return ::ot_uninitialized;
954
2.75M
        }
955
131M
        if (raw_type_code() == ::ot_unresolved) {
956
2.35M
            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
957
2.35M
        }
958
129M
        if (raw_type_code() == ::ot_reference) {
959
1.69k
            return std::get<QPDF_Reference>(obj->value).obj->getTypeCode();
960
1.69k
        }
961
129M
        return raw_type_code();
962
129M
    }
963
964
} // namespace qpdf
965
966
inline QPDF_Dictionary::QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items) :
967
2.10M
    items(std::move(items))
968
2.10M
{
969
2.10M
}
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
1.97M
{
975
1.97M
    auto n = QPDFObject::create<QPDF_Null>();
976
1.97M
    n->setChildDescription(parent->getQPDF(), parent, static_descr, var_descr);
977
1.97M
    return n;
978
1.97M
}
979
980
inline QPDF_Real::QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes) :
981
319k
    val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes))
982
319k
{
983
319k
}
984
985
template <typename T, typename... Args>
986
inline std::shared_ptr<QPDFObject>
987
QPDFObject::create(Args&&... args)
988
84.7M
{
989
84.7M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
84.7M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Null>()
Line
Count
Source
988
5.59M
{
989
5.59M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
5.59M
}
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
615k
{
989
615k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
615k
}
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.10M
{
989
2.10M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
2.10M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Bool, bool&>(bool&)
Line
Count
Source
988
7.21k
{
989
7.21k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
7.21k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Integer, long long&>(long long&)
Line
Count
Source
988
29.2M
{
989
29.2M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
29.2M
}
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
100k
{
989
100k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
100k
}
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
516k
{
989
516k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
516k
}
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
553k
{
989
553k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
553k
}
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
887
{
989
887
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
887
}
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
70.9k
{
989
70.9k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
70.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
115k
{
989
115k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
115k
}
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
37.5M
{
989
37.5M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
37.5M
}
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
213k
{
989
213k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
213k
}
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
1.80M
{
989
1.80M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.80M
}
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
9.95k
{
989
9.95k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
9.95k
}
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.07M
{
989
1.07M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.07M
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Real, double&, int&, bool&>(double&, int&, bool&)
Line
Count
Source
988
319k
{
989
319k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
319k
}
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
2.45M
{
989
2.45M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
2.45M
}
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
151k
{
989
151k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
151k
}
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
27.3k
{
989
27.3k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
27.3k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Bool, bool>(bool&&)
Line
Count
Source
988
121k
{
989
121k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
121k
}
std::__1::shared_ptr<QPDFObject> QPDFObject::create<QPDF_Integer, long long>(long long&&)
Line
Count
Source
988
948k
{
989
948k
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
948k
}
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.15M
{
989
1.15M
    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
990
1.15M
}
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
15.5M
{
1007
15.5M
    if (options & qpdf::error) {
1008
0
        assertType("array", false);
1009
0
    }
1010
15.5M
    if (options & qpdf::any_flag || type_code() == ::ot_array ||
1011
15.2M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1012
15.2M
        return qpdf::Array(obj);
1013
15.2M
    }
1014
278k
    return qpdf::Array(std::shared_ptr<QPDFObject>());
1015
15.5M
}
1016
1017
inline qpdf::Dictionary
1018
QPDFObjectHandle::as_dictionary(qpdf::typed options) const
1019
3.93M
{
1020
3.93M
    if (options & qpdf::any_flag || type_code() == ::ot_dictionary ||
1021
3.84M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1022
3.84M
        return qpdf::Dictionary(obj);
1023
3.84M
    }
1024
86.4k
    if (options & qpdf::error) {
1025
0
        assertType("dictionary", false);
1026
0
    }
1027
86.4k
    return qpdf::Dictionary(std::shared_ptr<QPDFObject>());
1028
3.93M
}
1029
1030
inline qpdf::Stream
1031
QPDFObjectHandle::as_stream(qpdf::typed options) const
1032
4.38M
{
1033
4.38M
    if (options & qpdf::any_flag || type_code() == ::ot_stream ||
1034
2.94M
        (options & qpdf::optional && type_code() == ::ot_null)) {
1035
2.94M
        return qpdf::Stream(obj);
1036
2.94M
    }
1037
1.44M
    if (options & qpdf::error) {
1038
265
        assertType("stream", false);
1039
265
    }
1040
1.44M
    return qpdf::Stream(std::shared_ptr<QPDFObject>());
1041
4.38M
}
1042
1043
#endif // OBJECTHANDLE_PRIVATE_HH