Coverage Report

Created: 2026-07-16 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpdf/include/qpdf/QPDFNameTreeObjectHelper.hh
Line
Count
Source
1
// Copyright (c) 2005-2021 Jay Berkenbilt
2
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
3
//
4
// This file is part of qpdf.
5
//
6
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7
// in compliance with the License. You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software distributed under the License
12
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13
// or implied. See the License for the specific language governing permissions and limitations under
14
// the License.
15
//
16
// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic
17
// License. At your option, you may continue to consider qpdf to be licensed under those terms.
18
// Please see the manual for additional information.
19
20
#ifndef QPDFNAMETREEOBJECTHELPER_HH
21
#define QPDFNAMETREEOBJECTHELPER_HH
22
23
#include <qpdf/QPDFObjGen.hh>
24
#include <qpdf/QPDFObjectHelper.hh>
25
#include <iterator>
26
#include <map>
27
#include <memory>
28
29
#include <qpdf/DLL.h>
30
31
class NNTreeImpl;
32
class NNTreeIterator;
33
class NNTreeDetails;
34
35
// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a
36
// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names
37
// are normalized for lookup purposes.
38
//
39
// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper.
40
class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper
41
{
42
  public:
43
    // The qpdf object is required so that this class can issue warnings, attempt repairs, and add
44
    // indirect objects.
45
    QPDF_DLL
46
    QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true);
47
48
    QPDF_DLL
49
    QPDFNameTreeObjectHelper(
50
        QPDFObjectHandle,
51
        QPDF&,
52
        std::function<bool(QPDFObjectHandle const&)> value_validator,
53
        bool auto_repair);
54
55
    // Validate the name tree. Returns true if the tree is valid.
56
    //
57
    // If the tree is not valid and auto_repair is true, attempt to repair the tree.
58
    QPDF_DLL
59
    bool validate(bool repair = true);
60
61
    // Create an empty name tree
62
    QPDF_DLL
63
    static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
64
65
    QPDF_DLL
66
    ~QPDFNameTreeObjectHelper() override;
67
68
    // Return whether the name tree has an explicit entry for this name.
69
    QPDF_DLL
70
    bool hasName(std::string const& utf8);
71
72
    // Find an object by name. If found, returns true and initializes oh. See also find().
73
    QPDF_DLL
74
    bool findObject(std::string const& utf8, QPDFObjectHandle& oh);
75
76
    class QPDF_DLL_PRIVATE iterator
77
    {
78
        friend class QPDFNameTreeObjectHelper;
79
80
      public:
81
        typedef std::pair<std::string, QPDFObjectHandle> T;
82
        using iterator_category = std::bidirectional_iterator_tag;
83
        using value_type = T;
84
        using difference_type = long;
85
        using pointer = T*;
86
        using reference = T&;
87
88
4.22k
        virtual ~iterator() = default;
89
        QPDF_DLL
90
        bool valid() const;
91
        QPDF_DLL
92
        iterator& operator++();
93
        iterator
94
        operator++(int)
95
0
        {
96
0
            iterator t = *this;
97
0
            ++(*this);
98
0
            return t;
99
0
        }
100
        QPDF_DLL
101
        iterator& operator--();
102
        iterator
103
        operator--(int)
104
0
        {
105
0
            iterator t = *this;
106
0
            --(*this);
107
0
            return t;
108
0
        }
109
        QPDF_DLL
110
        reference operator*();
111
        QPDF_DLL
112
        pointer operator->();
113
        QPDF_DLL
114
        bool operator==(iterator const& other) const;
115
        bool
116
        operator!=(iterator const& other) const
117
0
        {
118
0
            return !operator==(other);
119
0
        }
120
121
        // DANGER: this method can create inconsistent trees if not used properly! Insert a new item
122
        // immediately after the current iterator and increment so that it points to the new item.
123
        // If the current iterator is end(), insert at the beginning. This method does not check for
124
        // proper ordering, so if you use it, you must ensure that the item you are inserting
125
        // belongs where you are putting it. The reason for this method is that it is more efficient
126
        // than insert() and can be used safely when you are creating a new tree and inserting items
127
        // in sorted order.
128
        QPDF_DLL
129
        void insertAfter(std::string const& key, QPDFObjectHandle value);
130
131
        // Remove the current item and advance the iterator to the next item.
132
        QPDF_DLL
133
        void remove();
134
135
      private:
136
        void updateIValue();
137
138
        iterator(std::shared_ptr<NNTreeIterator> const&);
139
        std::shared_ptr<NNTreeIterator> impl;
140
        value_type ivalue;
141
    };
142
143
    // The iterator looks like map iterator, so i.first is a string and i.second is a
144
    // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings
145
    // you to the last item.
146
    QPDF_DLL
147
    iterator begin() const;
148
    QPDF_DLL
149
    iterator end() const;
150
    // Return a bidirectional iterator that points to the last item.
151
    QPDF_DLL
152
    iterator last() const;
153
154
    // Find the entry with the given key. If return_prev_if_not_found is true and the item is not
155
    // found, return the next lower item.
156
    QPDF_DLL
157
    iterator find(std::string const& key, bool return_prev_if_not_found = false);
158
159
    // Insert a new item. If the key already exists, it is replaced.
160
    QPDF_DLL
161
    iterator insert(std::string const& key, QPDFObjectHandle value);
162
163
    // Remove an item. Return true if the item was found and removed; otherwise return false. If
164
    // value is not nullptr, initialize it to the value that was removed.
165
    QPDF_DLL
166
    bool remove(std::string const& key, QPDFObjectHandle* value = nullptr);
167
168
    // Return the contents of the name tree as a map. Note that name trees may be very large, so
169
    // this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator.
170
    QPDF_DLL
171
    std::map<std::string, QPDFObjectHandle> getAsMap() const;
172
173
    // Split a node if the number of items exceeds this value. There's no real reason to ever set
174
    // this except for testing.
175
    QPDF_DLL
176
    void setSplitThreshold(int);
177
178
  private:
179
    class QPDF_DLL_PRIVATE Members;
180
181
    std::shared_ptr<Members> m;
182
};
183
184
#endif // QPDFNAMETREEOBJECTHELPER_HH