1 #include <qpdf/QPDFNameTreeObjectHelper.hh>
2 #include <qpdf/NNTree.hh>
3
4 class NameTreeDetails: public NNTreeDetails
5 {
6 public:
itemsKey() const7 virtual std::string const& itemsKey() const override
8 {
9 static std::string k("/Names");
10 return k;
11 }
keyValid(QPDFObjectHandle oh) const12 virtual bool keyValid(QPDFObjectHandle oh) const override
13 {
14 return oh.isString();
15 }
compareKeys(QPDFObjectHandle a,QPDFObjectHandle b) const16 virtual int compareKeys(
17 QPDFObjectHandle a, QPDFObjectHandle b) const override
18 {
19 if (! (keyValid(a) && keyValid(b)))
20 {
21 // We don't call this without calling keyValid first
22 throw std::logic_error("comparing invalid keys");
23 }
24 auto as = a.getUTF8Value();
25 auto bs = b.getUTF8Value();
26 return ((as < bs) ? -1 : (as > bs) ? 1 : 0);
27 }
28 };
29
30 static NameTreeDetails name_tree_details;
31
~Members()32 QPDFNameTreeObjectHelper::Members::~Members()
33 {
34 }
35
Members(QPDFObjectHandle & oh,QPDF * q,bool auto_repair)36 QPDFNameTreeObjectHelper::Members::Members(
37 QPDFObjectHandle& oh, QPDF* q, bool auto_repair) :
38 impl(std::make_shared<NNTreeImpl>(name_tree_details, q, oh, auto_repair))
39 {
40 }
41
QPDFNameTreeObjectHelper(QPDFObjectHandle oh,QPDF & q,bool auto_repair)42 QPDFNameTreeObjectHelper::QPDFNameTreeObjectHelper(
43 QPDFObjectHandle oh, QPDF& q, bool auto_repair) :
44 QPDFObjectHelper(oh),
45 m(new Members(oh, &q, auto_repair))
46 {
47 }
48
QPDFNameTreeObjectHelper(QPDFObjectHandle oh)49 QPDFNameTreeObjectHelper::QPDFNameTreeObjectHelper(QPDFObjectHandle oh) :
50 QPDFObjectHelper(oh),
51 m(new Members(oh, nullptr, false))
52 {
53 }
54
~QPDFNameTreeObjectHelper()55 QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper()
56 {
57 }
58
59 QPDFNameTreeObjectHelper
newEmpty(QPDF & qpdf,bool auto_repair)60 QPDFNameTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair)
61 {
62 return QPDFNameTreeObjectHelper(
63 qpdf.makeIndirectObject(
64 QPDFObjectHandle::parse("<< /Names [] >>")), qpdf, auto_repair);
65 }
66
iterator(std::shared_ptr<NNTreeIterator> const & i)67 QPDFNameTreeObjectHelper::iterator::iterator(
68 std::shared_ptr<NNTreeIterator> const& i) :
69 impl(i)
70 {
71 }
72
73 bool
valid() const74 QPDFNameTreeObjectHelper::iterator::valid() const
75 {
76 return impl->valid();
77 }
78
79 QPDFNameTreeObjectHelper::iterator&
operator ++()80 QPDFNameTreeObjectHelper::iterator::operator++()
81 {
82 ++(*impl);
83 updateIValue();
84 return *this;
85 }
86
87 QPDFNameTreeObjectHelper::iterator&
operator --()88 QPDFNameTreeObjectHelper::iterator::operator--()
89 {
90 --(*impl);
91 updateIValue();
92 return *this;
93 }
94
95 void
updateIValue()96 QPDFNameTreeObjectHelper::iterator::updateIValue()
97 {
98 if (impl->valid())
99 {
100 auto p = *impl;
101 this->ivalue.first = p->first.getUTF8Value();
102 this->ivalue.second = p->second;
103 }
104 else
105 {
106 this->ivalue.first = "";
107 this->ivalue.second = QPDFObjectHandle();
108 }
109 }
110
111 QPDFNameTreeObjectHelper::iterator::reference
operator *()112 QPDFNameTreeObjectHelper::iterator::operator*()
113 {
114 updateIValue();
115 return this->ivalue;
116 }
117
118 QPDFNameTreeObjectHelper::iterator::pointer
operator ->()119 QPDFNameTreeObjectHelper::iterator::operator->()
120 {
121 updateIValue();
122 return &this->ivalue;
123 }
124
125 bool
operator ==(iterator const & other) const126 QPDFNameTreeObjectHelper::iterator::operator==(iterator const& other) const
127 {
128 return *(impl) == *(other.impl);
129 }
130
131 void
insertAfter(std::string const & key,QPDFObjectHandle value)132 QPDFNameTreeObjectHelper::iterator::insertAfter(
133 std::string const& key, QPDFObjectHandle value)
134 {
135 impl->insertAfter(QPDFObjectHandle::newUnicodeString(key), value);
136 updateIValue();
137 }
138
139 void
remove()140 QPDFNameTreeObjectHelper::iterator::remove()
141 {
142 impl->remove();
143 updateIValue();
144 }
145
146 QPDFNameTreeObjectHelper::iterator
begin() const147 QPDFNameTreeObjectHelper::begin() const
148 {
149 return iterator(std::make_shared<NNTreeIterator>(this->m->impl->begin()));
150 }
151
152 QPDFNameTreeObjectHelper::iterator
end() const153 QPDFNameTreeObjectHelper::end() const
154 {
155 return iterator(std::make_shared<NNTreeIterator>(this->m->impl->end()));
156 }
157
158 QPDFNameTreeObjectHelper::iterator
last() const159 QPDFNameTreeObjectHelper::last() const
160 {
161 return iterator(std::make_shared<NNTreeIterator>(this->m->impl->last()));
162 }
163
164 QPDFNameTreeObjectHelper::iterator
find(std::string const & key,bool return_prev_if_not_found)165 QPDFNameTreeObjectHelper::find(std::string const& key,
166 bool return_prev_if_not_found)
167 {
168 auto i = this->m->impl->find(QPDFObjectHandle::newUnicodeString(key),
169 return_prev_if_not_found);
170 return iterator(std::make_shared<NNTreeIterator>(i));
171 }
172
173 QPDFNameTreeObjectHelper::iterator
insert(std::string const & key,QPDFObjectHandle value)174 QPDFNameTreeObjectHelper::insert(std::string const& key,
175 QPDFObjectHandle value)
176 {
177 auto i = this->m->impl->insert(
178 QPDFObjectHandle::newUnicodeString(key), value);
179 return iterator(std::make_shared<NNTreeIterator>(i));
180 }
181
182 bool
remove(std::string const & key,QPDFObjectHandle * value)183 QPDFNameTreeObjectHelper::remove(std::string const& key,
184 QPDFObjectHandle* value)
185 {
186 return this->m->impl->remove(
187 QPDFObjectHandle::newUnicodeString(key), value);
188 }
189
190 bool
hasName(std::string const & name)191 QPDFNameTreeObjectHelper::hasName(std::string const& name)
192 {
193 auto i = find(name);
194 return (i != end());
195 }
196
197 bool
findObject(std::string const & name,QPDFObjectHandle & oh)198 QPDFNameTreeObjectHelper::findObject(
199 std::string const& name, QPDFObjectHandle& oh)
200 {
201 auto i = find(name);
202 if (i == end())
203 {
204 return false;
205 }
206 oh = i->second;
207 return true;
208 }
209
210 void
setSplitThreshold(int t)211 QPDFNameTreeObjectHelper::setSplitThreshold(int t)
212 {
213 this->m->impl->setSplitThreshold(t);
214 }
215
216 std::map<std::string, QPDFObjectHandle>
getAsMap() const217 QPDFNameTreeObjectHelper::getAsMap() const
218 {
219 std::map<std::string, QPDFObjectHandle> result;
220 result.insert(begin(), end());
221 return result;
222 }
223