/src/qpdf/libqpdf/QPDFNumberTreeObjectHelper.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include <qpdf/QPDFNumberTreeObjectHelper.hh> |
2 | | |
3 | | #include <qpdf/NNTree.hh> |
4 | | #include <qpdf/QIntC.hh> |
5 | | |
6 | | namespace |
7 | | { |
8 | | class NumberTreeDetails: public NNTreeDetails |
9 | | { |
10 | | public: |
11 | | std::string const& |
12 | | itemsKey() const override |
13 | 1.48M | { |
14 | 1.48M | static std::string k("/Nums"); |
15 | 1.48M | return k; |
16 | 1.48M | } |
17 | | bool |
18 | | keyValid(QPDFObjectHandle oh) const override |
19 | 1.81M | { |
20 | 1.81M | return oh.isInteger(); |
21 | 1.81M | } |
22 | | int |
23 | | compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const override |
24 | 528k | { |
25 | 528k | if (!(keyValid(a) && keyValid(b))) { |
26 | | // We don't call this without calling keyValid first |
27 | 0 | throw std::logic_error("comparing invalid keys"); |
28 | 0 | } |
29 | 528k | auto as = a.getIntValue(); |
30 | 528k | auto bs = b.getIntValue(); |
31 | 528k | return ((as < bs) ? -1 : (as > bs) ? 1 : 0); |
32 | 528k | } |
33 | | }; |
34 | | } // namespace |
35 | | |
36 | | static NumberTreeDetails number_tree_details; |
37 | | |
38 | | QPDFNumberTreeObjectHelper::~QPDFNumberTreeObjectHelper() // NOLINT (modernize-use-equals-default) |
39 | 578 | { |
40 | | // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer. For this specific |
41 | | // class, see github issue #745. |
42 | 578 | } |
43 | | |
44 | | QPDFNumberTreeObjectHelper::Members::Members(QPDFObjectHandle& oh, QPDF& q, bool auto_repair) : |
45 | | impl(std::make_shared<NNTreeImpl>(number_tree_details, q, oh, auto_repair)) |
46 | 578 | { |
47 | 578 | } |
48 | | |
49 | | QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper( |
50 | | QPDFObjectHandle oh, QPDF& q, bool auto_repair) : |
51 | | QPDFObjectHelper(oh), |
52 | | m(new Members(oh, q, auto_repair)) |
53 | 578 | { |
54 | 578 | } |
55 | | |
56 | | QPDFNumberTreeObjectHelper |
57 | | QPDFNumberTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair) |
58 | 0 | { |
59 | 0 | return {qpdf.makeIndirectObject("<< /Nums [] >>"_qpdf), qpdf, auto_repair}; |
60 | 0 | } |
61 | | |
62 | | QPDFNumberTreeObjectHelper::iterator::iterator(std::shared_ptr<NNTreeIterator> const& i) : |
63 | | impl(i) |
64 | 33.7k | { |
65 | 33.7k | } |
66 | | |
67 | | bool |
68 | | QPDFNumberTreeObjectHelper::iterator::valid() const |
69 | 0 | { |
70 | 0 | return impl->valid(); |
71 | 0 | } |
72 | | |
73 | | QPDFNumberTreeObjectHelper::iterator& |
74 | | QPDFNumberTreeObjectHelper::iterator::operator++() |
75 | 0 | { |
76 | 0 | ++(*impl); |
77 | 0 | updateIValue(); |
78 | 0 | return *this; |
79 | 0 | } |
80 | | |
81 | | QPDFNumberTreeObjectHelper::iterator& |
82 | | QPDFNumberTreeObjectHelper::iterator::operator--() |
83 | 0 | { |
84 | 0 | --(*impl); |
85 | 0 | updateIValue(); |
86 | 0 | return *this; |
87 | 0 | } |
88 | | |
89 | | void |
90 | | QPDFNumberTreeObjectHelper::iterator::updateIValue() |
91 | 41.4k | { |
92 | 41.4k | if (impl->valid()) { |
93 | 41.4k | auto p = *impl; |
94 | 41.4k | this->ivalue.first = p->first.getIntValue(); |
95 | 41.4k | this->ivalue.second = p->second; |
96 | 41.4k | } else { |
97 | 0 | this->ivalue.first = 0; |
98 | 0 | this->ivalue.second = QPDFObjectHandle(); |
99 | 0 | } |
100 | 41.4k | } |
101 | | |
102 | | QPDFNumberTreeObjectHelper::iterator::reference |
103 | | QPDFNumberTreeObjectHelper::iterator::operator*() |
104 | 0 | { |
105 | 0 | updateIValue(); |
106 | 0 | return this->ivalue; |
107 | 0 | } |
108 | | |
109 | | QPDFNumberTreeObjectHelper::iterator::pointer |
110 | | QPDFNumberTreeObjectHelper::iterator::operator->() |
111 | 41.4k | { |
112 | 41.4k | updateIValue(); |
113 | 41.4k | return &this->ivalue; |
114 | 41.4k | } |
115 | | |
116 | | bool |
117 | | QPDFNumberTreeObjectHelper::iterator::operator==(iterator const& other) const |
118 | 16.8k | { |
119 | 16.8k | return *(impl) == *(other.impl); |
120 | 16.8k | } |
121 | | |
122 | | void |
123 | | QPDFNumberTreeObjectHelper::iterator::insertAfter(numtree_number key, QPDFObjectHandle value) |
124 | 0 | { |
125 | 0 | impl->insertAfter(QPDFObjectHandle::newInteger(key), value); |
126 | 0 | updateIValue(); |
127 | 0 | } |
128 | | |
129 | | void |
130 | | QPDFNumberTreeObjectHelper::iterator::remove() |
131 | 0 | { |
132 | 0 | impl->remove(); |
133 | 0 | updateIValue(); |
134 | 0 | } |
135 | | |
136 | | QPDFNumberTreeObjectHelper::iterator |
137 | | QPDFNumberTreeObjectHelper::begin() const |
138 | 0 | { |
139 | 0 | return {std::make_shared<NNTreeIterator>(m->impl->begin())}; |
140 | 0 | } |
141 | | |
142 | | QPDFNumberTreeObjectHelper::iterator |
143 | | QPDFNumberTreeObjectHelper::end() const |
144 | 16.8k | { |
145 | 16.8k | return {std::make_shared<NNTreeIterator>(m->impl->end())}; |
146 | 16.8k | } |
147 | | |
148 | | QPDFNumberTreeObjectHelper::iterator |
149 | | QPDFNumberTreeObjectHelper::last() const |
150 | 0 | { |
151 | 0 | return {std::make_shared<NNTreeIterator>(m->impl->last())}; |
152 | 0 | } |
153 | | |
154 | | QPDFNumberTreeObjectHelper::iterator |
155 | | QPDFNumberTreeObjectHelper::find(numtree_number key, bool return_prev_if_not_found) |
156 | 19.8k | { |
157 | 19.8k | auto i = m->impl->find(QPDFObjectHandle::newInteger(key), return_prev_if_not_found); |
158 | 19.8k | return {std::make_shared<NNTreeIterator>(i)}; |
159 | 19.8k | } |
160 | | |
161 | | QPDFNumberTreeObjectHelper::iterator |
162 | | QPDFNumberTreeObjectHelper::insert(numtree_number key, QPDFObjectHandle value) |
163 | 0 | { |
164 | 0 | auto i = m->impl->insert(QPDFObjectHandle::newInteger(key), value); |
165 | 0 | return {std::make_shared<NNTreeIterator>(i)}; |
166 | 0 | } |
167 | | |
168 | | bool |
169 | | QPDFNumberTreeObjectHelper::remove(numtree_number key, QPDFObjectHandle* value) |
170 | 0 | { |
171 | 0 | return m->impl->remove(QPDFObjectHandle::newInteger(key), value); |
172 | 0 | } |
173 | | |
174 | | QPDFNumberTreeObjectHelper::numtree_number |
175 | | QPDFNumberTreeObjectHelper::getMin() |
176 | 0 | { |
177 | 0 | auto i = begin(); |
178 | 0 | if (i == end()) { |
179 | 0 | return 0; |
180 | 0 | } |
181 | 0 | return i->first; |
182 | 0 | } |
183 | | |
184 | | QPDFNumberTreeObjectHelper::numtree_number |
185 | | QPDFNumberTreeObjectHelper::getMax() |
186 | 0 | { |
187 | 0 | auto i = last(); |
188 | 0 | if (i == end()) { |
189 | 0 | return 0; |
190 | 0 | } |
191 | 0 | return i->first; |
192 | 0 | } |
193 | | |
194 | | bool |
195 | | QPDFNumberTreeObjectHelper::hasIndex(numtree_number idx) |
196 | 0 | { |
197 | 0 | auto i = find(idx); |
198 | 0 | return (i != this->end()); |
199 | 0 | } |
200 | | |
201 | | bool |
202 | | QPDFNumberTreeObjectHelper::findObject(numtree_number idx, QPDFObjectHandle& oh) |
203 | 0 | { |
204 | 0 | auto i = find(idx); |
205 | 0 | if (i == end()) { |
206 | 0 | return false; |
207 | 0 | } |
208 | 0 | oh = i->second; |
209 | 0 | return true; |
210 | 0 | } |
211 | | |
212 | | bool |
213 | | QPDFNumberTreeObjectHelper::findObjectAtOrBelow( |
214 | | numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset) |
215 | 19.8k | { |
216 | 19.8k | auto i = find(idx, true); |
217 | 19.8k | if (i == end()) { |
218 | 3.05k | return false; |
219 | 3.05k | } |
220 | 16.8k | oh = i->second; |
221 | 16.8k | QIntC::range_check_substract(idx, i->first); |
222 | 16.8k | offset = idx - i->first; |
223 | 16.8k | return true; |
224 | 19.8k | } |
225 | | |
226 | | void |
227 | | QPDFNumberTreeObjectHelper::setSplitThreshold(int t) |
228 | 0 | { |
229 | 0 | m->impl->setSplitThreshold(t); |
230 | 0 | } |
231 | | |
232 | | std::map<QPDFNumberTreeObjectHelper::numtree_number, QPDFObjectHandle> |
233 | | QPDFNumberTreeObjectHelper::getAsMap() const |
234 | 0 | { |
235 | 0 | std::map<numtree_number, QPDFObjectHandle> result; |
236 | 0 | result.insert(begin(), end()); |
237 | 0 | return result; |
238 | 0 | } |