/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 |