/src/qpdf/include/qpdf/QPDFNumberTreeObjectHelper.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 QPDFNUMBERTREEOBJECTHELPER_HH |
21 | | #define QPDFNUMBERTREEOBJECTHELPER_HH |
22 | | |
23 | | #include <qpdf/QPDFObjGen.hh> |
24 | | #include <qpdf/QPDFObjectHelper.hh> |
25 | | #include <map> |
26 | | #include <memory> |
27 | | |
28 | | #include <qpdf/DLL.h> |
29 | | |
30 | | class NNTreeImpl; |
31 | | class NNTreeIterator; |
32 | | class NNTreeDetails; |
33 | | |
34 | | // This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a |
35 | | // description of number trees. |
36 | | // |
37 | | // See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper. |
38 | | class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper |
39 | | { |
40 | | public: |
41 | | // The qpdf object is required so that this class can issue warnings, attempt repairs, and add |
42 | | // indirect objects. |
43 | | QPDF_DLL |
44 | | QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); |
45 | | |
46 | | QPDF_DLL |
47 | | QPDFNumberTreeObjectHelper( |
48 | | QPDFObjectHandle, |
49 | | QPDF&, |
50 | | std::function<bool(QPDFObjectHandle const&)> value_validator, |
51 | | bool auto_repair); |
52 | | |
53 | | QPDF_DLL |
54 | | ~QPDFNumberTreeObjectHelper() override; |
55 | | |
56 | | // Create an empty number tree |
57 | | QPDF_DLL |
58 | | static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); |
59 | | |
60 | | typedef long long int numtree_number; |
61 | | |
62 | | // Validate the name tree. Returns true if the tree is valid. |
63 | | // |
64 | | // If the tree is not valid and auto_repair is true, attempt to repair the tree. |
65 | | QPDF_DLL |
66 | | bool validate(bool repair = true); |
67 | | |
68 | | // Return overall minimum and maximum indices |
69 | | QPDF_DLL |
70 | | numtree_number getMin(); |
71 | | QPDF_DLL |
72 | | numtree_number getMax(); |
73 | | |
74 | | // Return whether the number tree has an explicit entry for this number. |
75 | | QPDF_DLL |
76 | | bool hasIndex(numtree_number idx); |
77 | | |
78 | | // Find an object with a specific index. If found, returns true and initializes oh. See also |
79 | | // find(). |
80 | | QPDF_DLL |
81 | | bool findObject(numtree_number idx, QPDFObjectHandle& oh); |
82 | | // Find the object at the index or, if not found, the object whose index is the highest index |
83 | | // less than the requested index. If the requested index is less than the minimum, return false. |
84 | | // Otherwise, return true, initialize oh to the object, and set offset to the difference between |
85 | | // the requested index and the actual index. For example, if a number tree has values for 3 and |
86 | | // 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and |
87 | | // set offset to 2 (5 - 3). See also find(). |
88 | | QPDF_DLL |
89 | | bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset); |
90 | | |
91 | | class QPDF_DLL_PRIVATE iterator |
92 | | { |
93 | | friend class QPDFNumberTreeObjectHelper; |
94 | | |
95 | | public: |
96 | | typedef std::pair<numtree_number, QPDFObjectHandle> T; |
97 | | using iterator_category = std::bidirectional_iterator_tag; |
98 | | using value_type = T; |
99 | | using difference_type = long; |
100 | | using pointer = T*; |
101 | | using reference = T&; |
102 | | |
103 | 7.45k | virtual ~iterator() = default; |
104 | | QPDF_DLL |
105 | | bool valid() const; |
106 | | QPDF_DLL |
107 | | iterator& operator++(); |
108 | | iterator |
109 | | operator++(int) |
110 | 0 | { |
111 | 0 | iterator t = *this; |
112 | 0 | ++(*this); |
113 | 0 | return t; |
114 | 0 | } |
115 | | QPDF_DLL |
116 | | iterator& operator--(); |
117 | | iterator |
118 | | operator--(int) |
119 | 0 | { |
120 | 0 | iterator t = *this; |
121 | 0 | --(*this); |
122 | 0 | return t; |
123 | 0 | } |
124 | | QPDF_DLL |
125 | | reference operator*(); |
126 | | QPDF_DLL |
127 | | pointer operator->(); |
128 | | QPDF_DLL |
129 | | bool operator==(iterator const& other) const; |
130 | | bool |
131 | | operator!=(iterator const& other) const |
132 | 0 | { |
133 | 0 | return !operator==(other); |
134 | 0 | } |
135 | | |
136 | | // DANGER: this method can create inconsistent trees if not used properly! Insert a new item |
137 | | // immediately after the current iterator and increment so that it points to the new item. |
138 | | // If the current iterator is end(), insert at the beginning. This method does not check for |
139 | | // proper ordering, so if you use it, you must ensure that the item you are inserting |
140 | | // belongs where you are putting it. The reason for this method is that it is more efficient |
141 | | // than insert() and can be used safely when you are creating a new tree and inserting items |
142 | | // in sorted order. |
143 | | QPDF_DLL |
144 | | void insertAfter(numtree_number key, QPDFObjectHandle value); |
145 | | |
146 | | // Remove the current item and advance the iterator to the next item. |
147 | | QPDF_DLL |
148 | | void remove(); |
149 | | |
150 | | private: |
151 | | void updateIValue(); |
152 | | |
153 | | iterator(std::shared_ptr<NNTreeIterator> const&); |
154 | | std::shared_ptr<NNTreeIterator> impl; |
155 | | value_type ivalue; |
156 | | }; |
157 | | |
158 | | // The iterator looks like map iterator, so i.first is a numtree_number and i.second is a |
159 | | // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings |
160 | | // you to the last item. |
161 | | QPDF_DLL |
162 | | iterator begin() const; |
163 | | QPDF_DLL |
164 | | iterator end() const; |
165 | | // Return a bidirectional iterator that points to the last item. |
166 | | QPDF_DLL |
167 | | iterator last() const; |
168 | | |
169 | | // Find the entry with the given key. If return_prev_if_not_found is true and the item is not |
170 | | // found, return the next lower item. |
171 | | QPDF_DLL |
172 | | iterator find(numtree_number key, bool return_prev_if_not_found = false); |
173 | | |
174 | | // Insert a new item. If the key already exists, it is replaced. |
175 | | QPDF_DLL |
176 | | iterator insert(numtree_number key, QPDFObjectHandle value); |
177 | | |
178 | | // Remove an item. Return true if the item was found and removed; otherwise return false. If |
179 | | // value is not nullptr, initialize it to the value that was removed. |
180 | | QPDF_DLL |
181 | | bool remove(numtree_number key, QPDFObjectHandle* value = nullptr); |
182 | | |
183 | | // Return the contents of the number tree as a map. Note that number trees may be very large, so |
184 | | // this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator. |
185 | | typedef std::map<numtree_number, QPDFObjectHandle> idx_map; |
186 | | QPDF_DLL |
187 | | idx_map getAsMap() const; |
188 | | |
189 | | // Split a node if the number of items exceeds this value. There's no real reason to ever set |
190 | | // this except for testing. |
191 | | QPDF_DLL |
192 | | void setSplitThreshold(int); |
193 | | |
194 | | private: |
195 | | class QPDF_DLL_PRIVATE Members; |
196 | | |
197 | | std::shared_ptr<Members> m; |
198 | | }; |
199 | | |
200 | | #endif // QPDFNUMBERTREEOBJECTHELPER_HH |