Chris@16
|
1 // ----------------------------------------------------------------------------
|
Chris@16
|
2 // Copyright (C) 2002-2006 Marcin Kalicinski
|
Chris@16
|
3 // Copyright (C) 2009 Sebastian Redl
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
6 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //
|
Chris@16
|
9 // For more information, see www.boost.org
|
Chris@16
|
10 // ----------------------------------------------------------------------------
|
Chris@16
|
11 #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
Chris@16
|
12 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/iterator/iterator_adaptor.hpp>
|
Chris@16
|
15 #include <boost/iterator/reverse_iterator.hpp>
|
Chris@16
|
16 #include <boost/assert.hpp>
|
Chris@16
|
17 #include <boost/utility/swap.hpp>
|
Chris@16
|
18 #include <memory>
|
Chris@16
|
19
|
Chris@16
|
20 #if (defined(BOOST_MSVC) && \
|
Chris@16
|
21 (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
|
Chris@16
|
22 (defined(BOOST_INTEL_WIN) && \
|
Chris@16
|
23 defined(BOOST_DINKUMWARE_STDLIB))
|
Chris@16
|
24 #define BOOST_PROPERTY_TREE_PAIR_BUG
|
Chris@16
|
25 #endif
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost { namespace property_tree
|
Chris@16
|
28 {
|
Chris@16
|
29 template <class K, class D, class C>
|
Chris@16
|
30 struct basic_ptree<K, D, C>::subs
|
Chris@16
|
31 {
|
Chris@16
|
32 struct by_name {};
|
Chris@16
|
33 // The actual child container.
|
Chris@16
|
34 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
Chris@16
|
35 // MSVC 10 has moved std::pair's members to a base
|
Chris@16
|
36 // class. Unfortunately this does break the interface.
|
Chris@16
|
37 BOOST_STATIC_CONSTANT(unsigned,
|
Chris@16
|
38 first_offset = offsetof(value_type, first));
|
Chris@16
|
39 #endif
|
Chris@16
|
40 typedef multi_index_container<value_type,
|
Chris@16
|
41 multi_index::indexed_by<
|
Chris@16
|
42 multi_index::sequenced<>,
|
Chris@16
|
43 multi_index::ordered_non_unique<multi_index::tag<by_name>,
|
Chris@16
|
44 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
Chris@16
|
45 multi_index::member_offset<value_type, const key_type,
|
Chris@16
|
46 first_offset>,
|
Chris@16
|
47 #else
|
Chris@16
|
48 multi_index::member<value_type, const key_type,
|
Chris@16
|
49 &value_type::first>,
|
Chris@16
|
50 #endif
|
Chris@16
|
51 key_compare
|
Chris@16
|
52 >
|
Chris@16
|
53 >
|
Chris@16
|
54 > base_container;
|
Chris@16
|
55
|
Chris@16
|
56 // The by-name lookup index.
|
Chris@16
|
57 typedef typename base_container::template index<by_name>::type
|
Chris@16
|
58 by_name_index;
|
Chris@16
|
59
|
Chris@16
|
60 // Access functions for getting to the children of a tree.
|
Chris@16
|
61 static base_container& ch(self_type *s) {
|
Chris@16
|
62 return *static_cast<base_container*>(s->m_children);
|
Chris@16
|
63 }
|
Chris@16
|
64 static const base_container& ch(const self_type *s) {
|
Chris@16
|
65 return *static_cast<const base_container*>(s->m_children);
|
Chris@16
|
66 }
|
Chris@16
|
67 static by_name_index& assoc(self_type *s) {
|
Chris@16
|
68 return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
Chris@16
|
69 }
|
Chris@16
|
70 static const by_name_index& assoc(const self_type *s) {
|
Chris@16
|
71 return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
Chris@16
|
72 }
|
Chris@16
|
73 };
|
Chris@16
|
74 template <class K, class D, class C>
|
Chris@16
|
75 class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
|
Chris@16
|
76 iterator, typename subs::base_container::iterator, value_type>
|
Chris@16
|
77 {
|
Chris@16
|
78 friend class boost::iterator_core_access;
|
Chris@16
|
79 typedef boost::iterator_adaptor<
|
Chris@16
|
80 iterator, typename subs::base_container::iterator, value_type>
|
Chris@16
|
81 baset;
|
Chris@16
|
82 public:
|
Chris@16
|
83 typedef typename baset::reference reference;
|
Chris@16
|
84 iterator() {}
|
Chris@16
|
85 explicit iterator(typename iterator::base_type b)
|
Chris@16
|
86 : iterator::iterator_adaptor_(b)
|
Chris@16
|
87 {}
|
Chris@16
|
88 reference dereference() const
|
Chris@16
|
89 {
|
Chris@16
|
90 // multi_index doesn't allow modification of its values, because
|
Chris@16
|
91 // indexes could sort by anything, and modification screws that up.
|
Chris@16
|
92 // However, we only sort by the key, and it's protected against
|
Chris@16
|
93 // modification in the value_type, so this const_cast is safe.
|
Chris@16
|
94 return const_cast<reference>(*this->base_reference());
|
Chris@16
|
95 }
|
Chris@16
|
96 };
|
Chris@16
|
97 template <class K, class D, class C>
|
Chris@16
|
98 class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
|
Chris@16
|
99 const_iterator, typename subs::base_container::const_iterator>
|
Chris@16
|
100 {
|
Chris@16
|
101 public:
|
Chris@16
|
102 const_iterator() {}
|
Chris@16
|
103 explicit const_iterator(typename const_iterator::base_type b)
|
Chris@16
|
104 : const_iterator::iterator_adaptor_(b)
|
Chris@16
|
105 {}
|
Chris@16
|
106 const_iterator(iterator b)
|
Chris@16
|
107 : const_iterator::iterator_adaptor_(b.base())
|
Chris@16
|
108 {}
|
Chris@16
|
109 };
|
Chris@16
|
110 template <class K, class D, class C>
|
Chris@16
|
111 class basic_ptree<K, D, C>::reverse_iterator
|
Chris@16
|
112 : public boost::reverse_iterator<iterator>
|
Chris@16
|
113 {
|
Chris@16
|
114 public:
|
Chris@16
|
115 reverse_iterator() {}
|
Chris@16
|
116 explicit reverse_iterator(iterator b)
|
Chris@16
|
117 : boost::reverse_iterator<iterator>(b)
|
Chris@16
|
118 {}
|
Chris@16
|
119 };
|
Chris@16
|
120 template <class K, class D, class C>
|
Chris@16
|
121 class basic_ptree<K, D, C>::const_reverse_iterator
|
Chris@16
|
122 : public boost::reverse_iterator<const_iterator>
|
Chris@16
|
123 {
|
Chris@16
|
124 public:
|
Chris@16
|
125 const_reverse_iterator() {}
|
Chris@16
|
126 explicit const_reverse_iterator(const_iterator b)
|
Chris@16
|
127 : boost::reverse_iterator<const_iterator>(b)
|
Chris@16
|
128 {}
|
Chris@16
|
129 const_reverse_iterator(
|
Chris@16
|
130 typename basic_ptree<K, D, C>::reverse_iterator b)
|
Chris@16
|
131 : boost::reverse_iterator<const_iterator>(b)
|
Chris@16
|
132 {}
|
Chris@16
|
133 };
|
Chris@16
|
134 template <class K, class D, class C>
|
Chris@16
|
135 class basic_ptree<K, D, C>::assoc_iterator
|
Chris@16
|
136 : public boost::iterator_adaptor<assoc_iterator,
|
Chris@16
|
137 typename subs::by_name_index::iterator,
|
Chris@16
|
138 value_type>
|
Chris@16
|
139 {
|
Chris@16
|
140 friend class boost::iterator_core_access;
|
Chris@16
|
141 typedef boost::iterator_adaptor<assoc_iterator,
|
Chris@16
|
142 typename subs::by_name_index::iterator,
|
Chris@16
|
143 value_type>
|
Chris@16
|
144 baset;
|
Chris@16
|
145 public:
|
Chris@16
|
146 typedef typename baset::reference reference;
|
Chris@16
|
147 assoc_iterator() {}
|
Chris@16
|
148 explicit assoc_iterator(typename assoc_iterator::base_type b)
|
Chris@16
|
149 : assoc_iterator::iterator_adaptor_(b)
|
Chris@16
|
150 {}
|
Chris@16
|
151 reference dereference() const
|
Chris@16
|
152 {
|
Chris@16
|
153 return const_cast<reference>(*this->base_reference());
|
Chris@16
|
154 }
|
Chris@16
|
155 };
|
Chris@16
|
156 template <class K, class D, class C>
|
Chris@16
|
157 class basic_ptree<K, D, C>::const_assoc_iterator
|
Chris@16
|
158 : public boost::iterator_adaptor<const_assoc_iterator,
|
Chris@16
|
159 typename subs::by_name_index::const_iterator>
|
Chris@16
|
160 {
|
Chris@16
|
161 public:
|
Chris@16
|
162 const_assoc_iterator() {}
|
Chris@16
|
163 explicit const_assoc_iterator(
|
Chris@16
|
164 typename const_assoc_iterator::base_type b)
|
Chris@16
|
165 : const_assoc_iterator::iterator_adaptor_(b)
|
Chris@16
|
166 {}
|
Chris@16
|
167 const_assoc_iterator(assoc_iterator b)
|
Chris@16
|
168 : const_assoc_iterator::iterator_adaptor_(b.base())
|
Chris@16
|
169 {}
|
Chris@16
|
170 };
|
Chris@16
|
171
|
Chris@16
|
172
|
Chris@16
|
173 // Big five
|
Chris@16
|
174
|
Chris@16
|
175 // Perhaps the children collection could be created on-demand only, to
|
Chris@16
|
176 // reduce heap traffic. But that's a lot more work to implement.
|
Chris@16
|
177
|
Chris@16
|
178 template<class K, class D, class C> inline
|
Chris@16
|
179 basic_ptree<K, D, C>::basic_ptree()
|
Chris@16
|
180 : m_children(new typename subs::base_container)
|
Chris@16
|
181 {
|
Chris@16
|
182 }
|
Chris@16
|
183
|
Chris@16
|
184 template<class K, class D, class C> inline
|
Chris@16
|
185 basic_ptree<K, D, C>::basic_ptree(const data_type &d)
|
Chris@16
|
186 : m_data(d), m_children(new typename subs::base_container)
|
Chris@16
|
187 {
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 template<class K, class D, class C> inline
|
Chris@16
|
191 basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
|
Chris@16
|
192 : m_data(rhs.m_data),
|
Chris@16
|
193 m_children(new typename subs::base_container(subs::ch(&rhs)))
|
Chris@16
|
194 {
|
Chris@16
|
195 }
|
Chris@16
|
196
|
Chris@16
|
197 template<class K, class D, class C>
|
Chris@16
|
198 basic_ptree<K, D, C> &
|
Chris@16
|
199 basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
|
Chris@16
|
200 {
|
Chris@16
|
201 self_type(rhs).swap(*this);
|
Chris@16
|
202 return *this;
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 template<class K, class D, class C>
|
Chris@16
|
206 basic_ptree<K, D, C>::~basic_ptree()
|
Chris@16
|
207 {
|
Chris@16
|
208 delete &subs::ch(this);
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 template<class K, class D, class C> inline
|
Chris@16
|
212 void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
|
Chris@16
|
213 {
|
Chris@16
|
214 boost::swap(m_data, rhs.m_data);
|
Chris@16
|
215 // Void pointers, no ADL necessary
|
Chris@16
|
216 std::swap(m_children, rhs.m_children);
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 // Container view
|
Chris@16
|
220
|
Chris@16
|
221 template<class K, class D, class C> inline
|
Chris@16
|
222 typename basic_ptree<K, D, C>::size_type
|
Chris@16
|
223 basic_ptree<K, D, C>::size() const
|
Chris@16
|
224 {
|
Chris@16
|
225 return subs::ch(this).size();
|
Chris@16
|
226 }
|
Chris@16
|
227
|
Chris@16
|
228 template<class K, class D, class C> inline
|
Chris@16
|
229 typename basic_ptree<K, D, C>::size_type
|
Chris@16
|
230 basic_ptree<K, D, C>::max_size() const
|
Chris@16
|
231 {
|
Chris@16
|
232 return subs::ch(this).max_size();
|
Chris@16
|
233 }
|
Chris@16
|
234
|
Chris@16
|
235 template<class K, class D, class C> inline
|
Chris@16
|
236 bool basic_ptree<K, D, C>::empty() const
|
Chris@16
|
237 {
|
Chris@16
|
238 return subs::ch(this).empty();
|
Chris@16
|
239 }
|
Chris@16
|
240
|
Chris@16
|
241 template<class K, class D, class C> inline
|
Chris@16
|
242 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
243 basic_ptree<K, D, C>::begin()
|
Chris@16
|
244 {
|
Chris@16
|
245 return iterator(subs::ch(this).begin());
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 template<class K, class D, class C> inline
|
Chris@16
|
249 typename basic_ptree<K, D, C>::const_iterator
|
Chris@16
|
250 basic_ptree<K, D, C>::begin() const
|
Chris@16
|
251 {
|
Chris@16
|
252 return const_iterator(subs::ch(this).begin());
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 template<class K, class D, class C> inline
|
Chris@16
|
256 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
257 basic_ptree<K, D, C>::end()
|
Chris@16
|
258 {
|
Chris@16
|
259 return iterator(subs::ch(this).end());
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 template<class K, class D, class C> inline
|
Chris@16
|
263 typename basic_ptree<K, D, C>::const_iterator
|
Chris@16
|
264 basic_ptree<K, D, C>::end() const
|
Chris@16
|
265 {
|
Chris@16
|
266 return const_iterator(subs::ch(this).end());
|
Chris@16
|
267 }
|
Chris@16
|
268
|
Chris@16
|
269 template<class K, class D, class C> inline
|
Chris@16
|
270 typename basic_ptree<K, D, C>::reverse_iterator
|
Chris@16
|
271 basic_ptree<K, D, C>::rbegin()
|
Chris@16
|
272 {
|
Chris@16
|
273 return reverse_iterator(this->end());
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 template<class K, class D, class C> inline
|
Chris@16
|
277 typename basic_ptree<K, D, C>::const_reverse_iterator
|
Chris@16
|
278 basic_ptree<K, D, C>::rbegin() const
|
Chris@16
|
279 {
|
Chris@16
|
280 return const_reverse_iterator(this->end());
|
Chris@16
|
281 }
|
Chris@16
|
282
|
Chris@16
|
283 template<class K, class D, class C> inline
|
Chris@16
|
284 typename basic_ptree<K, D, C>::reverse_iterator
|
Chris@16
|
285 basic_ptree<K, D, C>::rend()
|
Chris@16
|
286 {
|
Chris@16
|
287 return reverse_iterator(this->begin());
|
Chris@16
|
288 }
|
Chris@16
|
289
|
Chris@16
|
290 template<class K, class D, class C> inline
|
Chris@16
|
291 typename basic_ptree<K, D, C>::const_reverse_iterator
|
Chris@16
|
292 basic_ptree<K, D, C>::rend() const
|
Chris@16
|
293 {
|
Chris@16
|
294 return const_reverse_iterator(this->begin());
|
Chris@16
|
295 }
|
Chris@16
|
296
|
Chris@16
|
297 template<class K, class D, class C> inline
|
Chris@16
|
298 typename basic_ptree<K, D, C>::value_type &
|
Chris@16
|
299 basic_ptree<K, D, C>::front()
|
Chris@16
|
300 {
|
Chris@16
|
301 return const_cast<value_type&>(subs::ch(this).front());
|
Chris@16
|
302 }
|
Chris@16
|
303
|
Chris@16
|
304 template<class K, class D, class C> inline
|
Chris@16
|
305 const typename basic_ptree<K, D, C>::value_type &
|
Chris@16
|
306 basic_ptree<K, D, C>::front() const
|
Chris@16
|
307 {
|
Chris@16
|
308 return subs::ch(this).front();
|
Chris@16
|
309 }
|
Chris@16
|
310
|
Chris@16
|
311 template<class K, class D, class C> inline
|
Chris@16
|
312 typename basic_ptree<K, D, C>::value_type &
|
Chris@16
|
313 basic_ptree<K, D, C>::back()
|
Chris@16
|
314 {
|
Chris@16
|
315 return const_cast<value_type&>(subs::ch(this).back());
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 template<class K, class D, class C> inline
|
Chris@16
|
319 const typename basic_ptree<K, D, C>::value_type &
|
Chris@16
|
320 basic_ptree<K, D, C>::back() const
|
Chris@16
|
321 {
|
Chris@16
|
322 return subs::ch(this).back();
|
Chris@16
|
323 }
|
Chris@16
|
324
|
Chris@16
|
325 template<class K, class D, class C> inline
|
Chris@16
|
326 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
327 basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
|
Chris@16
|
328 {
|
Chris@16
|
329 return iterator(subs::ch(this).insert(where.base(), value).first);
|
Chris@16
|
330 }
|
Chris@16
|
331
|
Chris@16
|
332 template<class K, class D, class C>
|
Chris@16
|
333 template<class It> inline
|
Chris@16
|
334 void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
|
Chris@16
|
335 {
|
Chris@16
|
336 subs::ch(this).insert(where.base(), first, last);
|
Chris@16
|
337 }
|
Chris@16
|
338
|
Chris@16
|
339 template<class K, class D, class C> inline
|
Chris@16
|
340 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
341 basic_ptree<K, D, C>::erase(iterator where)
|
Chris@16
|
342 {
|
Chris@16
|
343 return iterator(subs::ch(this).erase(where.base()));
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346 template<class K, class D, class C> inline
|
Chris@16
|
347 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
348 basic_ptree<K, D, C>::erase(iterator first, iterator last)
|
Chris@16
|
349 {
|
Chris@16
|
350 return iterator(subs::ch(this).erase(first.base(), last.base()));
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 template<class K, class D, class C> inline
|
Chris@16
|
354 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
355 basic_ptree<K, D, C>::push_front(const value_type &value)
|
Chris@16
|
356 {
|
Chris@16
|
357 return iterator(subs::ch(this).push_front(value).first);
|
Chris@16
|
358 }
|
Chris@16
|
359
|
Chris@16
|
360 template<class K, class D, class C> inline
|
Chris@16
|
361 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
362 basic_ptree<K, D, C>::push_back(const value_type &value)
|
Chris@16
|
363 {
|
Chris@16
|
364 return iterator(subs::ch(this).push_back(value).first);
|
Chris@16
|
365 }
|
Chris@16
|
366
|
Chris@16
|
367 template<class K, class D, class C> inline
|
Chris@16
|
368 void basic_ptree<K, D, C>::pop_front()
|
Chris@16
|
369 {
|
Chris@16
|
370 subs::ch(this).pop_front();
|
Chris@16
|
371 }
|
Chris@16
|
372
|
Chris@16
|
373 template<class K, class D, class C> inline
|
Chris@16
|
374 void basic_ptree<K, D, C>::pop_back()
|
Chris@16
|
375 {
|
Chris@16
|
376 subs::ch(this).pop_back();
|
Chris@16
|
377 }
|
Chris@16
|
378
|
Chris@16
|
379 template<class K, class D, class C> inline
|
Chris@16
|
380 void basic_ptree<K, D, C>::reverse()
|
Chris@16
|
381 {
|
Chris@16
|
382 subs::ch(this).reverse();
|
Chris@16
|
383 }
|
Chris@16
|
384
|
Chris@16
|
385 namespace impl
|
Chris@16
|
386 {
|
Chris@16
|
387 struct by_first
|
Chris@16
|
388 {
|
Chris@16
|
389 template <typename P>
|
Chris@16
|
390 bool operator ()(const P& lhs, const P& rhs) const {
|
Chris@16
|
391 return lhs.first < rhs.first;
|
Chris@16
|
392 }
|
Chris@16
|
393 };
|
Chris@101
|
394
|
Chris@101
|
395 template <typename C>
|
Chris@101
|
396 struct equal_pred
|
Chris@101
|
397 {
|
Chris@101
|
398 template <typename P>
|
Chris@101
|
399 bool operator ()(const P& lhs, const P& rhs) const {
|
Chris@101
|
400 C c;
|
Chris@101
|
401 return !c(lhs.first, rhs.first) &&
|
Chris@101
|
402 !c(rhs.first, lhs.first) &&
|
Chris@101
|
403 lhs.second == rhs.second;
|
Chris@101
|
404 }
|
Chris@101
|
405 };
|
Chris@101
|
406
|
Chris@101
|
407 template <typename C, typename MI>
|
Chris@101
|
408 bool equal_children(const MI& ch1, const MI& ch2) {
|
Chris@101
|
409 // Assumes ch1.size() == ch2.size()
|
Chris@101
|
410 return std::equal(ch1.begin(), ch1.end(),
|
Chris@101
|
411 ch2.begin(), equal_pred<C>());
|
Chris@101
|
412 }
|
Chris@16
|
413 }
|
Chris@16
|
414
|
Chris@16
|
415 template<class K, class D, class C> inline
|
Chris@16
|
416 void basic_ptree<K, D, C>::sort()
|
Chris@16
|
417 {
|
Chris@16
|
418 sort(impl::by_first());
|
Chris@16
|
419 }
|
Chris@16
|
420
|
Chris@16
|
421 template<class K, class D, class C>
|
Chris@16
|
422 template<class Compare> inline
|
Chris@16
|
423 void basic_ptree<K, D, C>::sort(Compare comp)
|
Chris@16
|
424 {
|
Chris@16
|
425 subs::ch(this).sort(comp);
|
Chris@16
|
426 }
|
Chris@16
|
427
|
Chris@16
|
428 // Equality
|
Chris@16
|
429
|
Chris@16
|
430 template<class K, class D, class C> inline
|
Chris@16
|
431 bool basic_ptree<K, D, C>::operator ==(
|
Chris@16
|
432 const basic_ptree<K, D, C> &rhs) const
|
Chris@16
|
433 {
|
Chris@16
|
434 // The size test is cheap, so add it as an optimization
|
Chris@16
|
435 return size() == rhs.size() && data() == rhs.data() &&
|
Chris@101
|
436 impl::equal_children<C>(subs::ch(this), subs::ch(&rhs));
|
Chris@16
|
437 }
|
Chris@16
|
438
|
Chris@16
|
439 template<class K, class D, class C> inline
|
Chris@16
|
440 bool basic_ptree<K, D, C>::operator !=(
|
Chris@16
|
441 const basic_ptree<K, D, C> &rhs) const
|
Chris@16
|
442 {
|
Chris@16
|
443 return !(*this == rhs);
|
Chris@16
|
444 }
|
Chris@16
|
445
|
Chris@16
|
446 // Associative view
|
Chris@16
|
447
|
Chris@16
|
448 template<class K, class D, class C> inline
|
Chris@16
|
449 typename basic_ptree<K, D, C>::assoc_iterator
|
Chris@16
|
450 basic_ptree<K, D, C>::ordered_begin()
|
Chris@16
|
451 {
|
Chris@16
|
452 return assoc_iterator(subs::assoc(this).begin());
|
Chris@16
|
453 }
|
Chris@16
|
454
|
Chris@16
|
455 template<class K, class D, class C> inline
|
Chris@16
|
456 typename basic_ptree<K, D, C>::const_assoc_iterator
|
Chris@16
|
457 basic_ptree<K, D, C>::ordered_begin() const
|
Chris@16
|
458 {
|
Chris@16
|
459 return const_assoc_iterator(subs::assoc(this).begin());
|
Chris@16
|
460 }
|
Chris@16
|
461
|
Chris@16
|
462 template<class K, class D, class C> inline
|
Chris@16
|
463 typename basic_ptree<K, D, C>::assoc_iterator
|
Chris@16
|
464 basic_ptree<K, D, C>::not_found()
|
Chris@16
|
465 {
|
Chris@16
|
466 return assoc_iterator(subs::assoc(this).end());
|
Chris@16
|
467 }
|
Chris@16
|
468
|
Chris@16
|
469 template<class K, class D, class C> inline
|
Chris@16
|
470 typename basic_ptree<K, D, C>::const_assoc_iterator
|
Chris@16
|
471 basic_ptree<K, D, C>::not_found() const
|
Chris@16
|
472 {
|
Chris@16
|
473 return const_assoc_iterator(subs::assoc(this).end());
|
Chris@16
|
474 }
|
Chris@16
|
475
|
Chris@16
|
476 template<class K, class D, class C> inline
|
Chris@16
|
477 typename basic_ptree<K, D, C>::assoc_iterator
|
Chris@16
|
478 basic_ptree<K, D, C>::find(const key_type &key)
|
Chris@16
|
479 {
|
Chris@16
|
480 return assoc_iterator(subs::assoc(this).find(key));
|
Chris@16
|
481 }
|
Chris@16
|
482
|
Chris@16
|
483 template<class K, class D, class C> inline
|
Chris@16
|
484 typename basic_ptree<K, D, C>::const_assoc_iterator
|
Chris@16
|
485 basic_ptree<K, D, C>::find(const key_type &key) const
|
Chris@16
|
486 {
|
Chris@16
|
487 return const_assoc_iterator(subs::assoc(this).find(key));
|
Chris@16
|
488 }
|
Chris@16
|
489
|
Chris@16
|
490 template<class K, class D, class C> inline
|
Chris@16
|
491 std::pair<
|
Chris@16
|
492 typename basic_ptree<K, D, C>::assoc_iterator,
|
Chris@16
|
493 typename basic_ptree<K, D, C>::assoc_iterator
|
Chris@16
|
494 > basic_ptree<K, D, C>::equal_range(const key_type &key)
|
Chris@16
|
495 {
|
Chris@16
|
496 std::pair<typename subs::by_name_index::iterator,
|
Chris@16
|
497 typename subs::by_name_index::iterator> r(
|
Chris@16
|
498 subs::assoc(this).equal_range(key));
|
Chris@16
|
499 return std::pair<assoc_iterator, assoc_iterator>(
|
Chris@16
|
500 assoc_iterator(r.first), assoc_iterator(r.second));
|
Chris@16
|
501 }
|
Chris@16
|
502
|
Chris@16
|
503 template<class K, class D, class C> inline
|
Chris@16
|
504 std::pair<
|
Chris@16
|
505 typename basic_ptree<K, D, C>::const_assoc_iterator,
|
Chris@16
|
506 typename basic_ptree<K, D, C>::const_assoc_iterator
|
Chris@16
|
507 > basic_ptree<K, D, C>::equal_range(const key_type &key) const
|
Chris@16
|
508 {
|
Chris@16
|
509 std::pair<typename subs::by_name_index::const_iterator,
|
Chris@16
|
510 typename subs::by_name_index::const_iterator> r(
|
Chris@16
|
511 subs::assoc(this).equal_range(key));
|
Chris@16
|
512 return std::pair<const_assoc_iterator, const_assoc_iterator>(
|
Chris@16
|
513 const_assoc_iterator(r.first), const_assoc_iterator(r.second));
|
Chris@16
|
514 }
|
Chris@16
|
515
|
Chris@16
|
516 template<class K, class D, class C> inline
|
Chris@16
|
517 typename basic_ptree<K, D, C>::size_type
|
Chris@16
|
518 basic_ptree<K, D, C>::count(const key_type &key) const
|
Chris@16
|
519 {
|
Chris@16
|
520 return subs::assoc(this).count(key);
|
Chris@16
|
521 }
|
Chris@16
|
522
|
Chris@16
|
523 template<class K, class D, class C> inline
|
Chris@16
|
524 typename basic_ptree<K, D, C>::size_type
|
Chris@16
|
525 basic_ptree<K, D, C>::erase(const key_type &key)
|
Chris@16
|
526 {
|
Chris@16
|
527 return subs::assoc(this).erase(key);
|
Chris@16
|
528 }
|
Chris@16
|
529
|
Chris@16
|
530 template<class K, class D, class C> inline
|
Chris@16
|
531 typename basic_ptree<K, D, C>::iterator
|
Chris@16
|
532 basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
|
Chris@16
|
533 {
|
Chris@16
|
534 return iterator(subs::ch(this).
|
Chris@16
|
535 BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
Chris@16
|
536 }
|
Chris@16
|
537
|
Chris@16
|
538 template<class K, class D, class C> inline
|
Chris@16
|
539 typename basic_ptree<K, D, C>::const_iterator
|
Chris@16
|
540 basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
|
Chris@16
|
541 {
|
Chris@16
|
542 return const_iterator(subs::ch(this).
|
Chris@16
|
543 BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
Chris@16
|
544 }
|
Chris@16
|
545
|
Chris@16
|
546 // Property tree view
|
Chris@16
|
547
|
Chris@16
|
548 template<class K, class D, class C> inline
|
Chris@16
|
549 typename basic_ptree<K, D, C>::data_type &
|
Chris@16
|
550 basic_ptree<K, D, C>::data()
|
Chris@16
|
551 {
|
Chris@16
|
552 return m_data;
|
Chris@16
|
553 }
|
Chris@16
|
554
|
Chris@16
|
555 template<class K, class D, class C> inline
|
Chris@16
|
556 const typename basic_ptree<K, D, C>::data_type &
|
Chris@16
|
557 basic_ptree<K, D, C>::data() const
|
Chris@16
|
558 {
|
Chris@16
|
559 return m_data;
|
Chris@16
|
560 }
|
Chris@16
|
561
|
Chris@16
|
562 template<class K, class D, class C> inline
|
Chris@16
|
563 void basic_ptree<K, D, C>::clear()
|
Chris@16
|
564 {
|
Chris@16
|
565 m_data = data_type();
|
Chris@16
|
566 subs::ch(this).clear();
|
Chris@16
|
567 }
|
Chris@16
|
568
|
Chris@16
|
569 template<class K, class D, class C>
|
Chris@16
|
570 basic_ptree<K, D, C> &
|
Chris@16
|
571 basic_ptree<K, D, C>::get_child(const path_type &path)
|
Chris@16
|
572 {
|
Chris@16
|
573 path_type p(path);
|
Chris@16
|
574 self_type *n = walk_path(p);
|
Chris@16
|
575 if (!n) {
|
Chris@16
|
576 BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
|
Chris@16
|
577 }
|
Chris@16
|
578 return *n;
|
Chris@16
|
579 }
|
Chris@16
|
580
|
Chris@16
|
581 template<class K, class D, class C> inline
|
Chris@16
|
582 const basic_ptree<K, D, C> &
|
Chris@16
|
583 basic_ptree<K, D, C>::get_child(const path_type &path) const
|
Chris@16
|
584 {
|
Chris@16
|
585 return const_cast<self_type*>(this)->get_child(path);
|
Chris@16
|
586 }
|
Chris@16
|
587
|
Chris@16
|
588 template<class K, class D, class C> inline
|
Chris@16
|
589 basic_ptree<K, D, C> &
|
Chris@16
|
590 basic_ptree<K, D, C>::get_child(const path_type &path,
|
Chris@16
|
591 self_type &default_value)
|
Chris@16
|
592 {
|
Chris@16
|
593 path_type p(path);
|
Chris@16
|
594 self_type *n = walk_path(p);
|
Chris@16
|
595 return n ? *n : default_value;
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 template<class K, class D, class C> inline
|
Chris@16
|
599 const basic_ptree<K, D, C> &
|
Chris@16
|
600 basic_ptree<K, D, C>::get_child(const path_type &path,
|
Chris@16
|
601 const self_type &default_value) const
|
Chris@16
|
602 {
|
Chris@16
|
603 return const_cast<self_type*>(this)->get_child(path,
|
Chris@16
|
604 const_cast<self_type&>(default_value));
|
Chris@16
|
605 }
|
Chris@16
|
606
|
Chris@16
|
607
|
Chris@16
|
608 template<class K, class D, class C>
|
Chris@16
|
609 optional<basic_ptree<K, D, C> &>
|
Chris@16
|
610 basic_ptree<K, D, C>::get_child_optional(const path_type &path)
|
Chris@16
|
611 {
|
Chris@16
|
612 path_type p(path);
|
Chris@16
|
613 self_type *n = walk_path(p);
|
Chris@16
|
614 if (!n) {
|
Chris@16
|
615 return optional<self_type&>();
|
Chris@16
|
616 }
|
Chris@16
|
617 return *n;
|
Chris@16
|
618 }
|
Chris@16
|
619
|
Chris@16
|
620 template<class K, class D, class C>
|
Chris@16
|
621 optional<const basic_ptree<K, D, C> &>
|
Chris@16
|
622 basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
|
Chris@16
|
623 {
|
Chris@16
|
624 path_type p(path);
|
Chris@16
|
625 self_type *n = walk_path(p);
|
Chris@16
|
626 if (!n) {
|
Chris@16
|
627 return optional<const self_type&>();
|
Chris@16
|
628 }
|
Chris@16
|
629 return *n;
|
Chris@16
|
630 }
|
Chris@16
|
631
|
Chris@16
|
632 template<class K, class D, class C>
|
Chris@16
|
633 basic_ptree<K, D, C> &
|
Chris@16
|
634 basic_ptree<K, D, C>::put_child(const path_type &path,
|
Chris@16
|
635 const self_type &value)
|
Chris@16
|
636 {
|
Chris@16
|
637 path_type p(path);
|
Chris@16
|
638 self_type &parent = force_path(p);
|
Chris@16
|
639 // Got the parent. Now get the correct child.
|
Chris@16
|
640 key_type fragment = p.reduce();
|
Chris@16
|
641 assoc_iterator el = parent.find(fragment);
|
Chris@16
|
642 // If the new child exists, replace it.
|
Chris@16
|
643 if(el != parent.not_found()) {
|
Chris@16
|
644 return el->second = value;
|
Chris@16
|
645 } else {
|
Chris@16
|
646 return parent.push_back(value_type(fragment, value))->second;
|
Chris@16
|
647 }
|
Chris@16
|
648 }
|
Chris@16
|
649
|
Chris@16
|
650 template<class K, class D, class C>
|
Chris@16
|
651 basic_ptree<K, D, C> &
|
Chris@16
|
652 basic_ptree<K, D, C>::add_child(const path_type &path,
|
Chris@16
|
653 const self_type &value)
|
Chris@16
|
654 {
|
Chris@16
|
655 path_type p(path);
|
Chris@16
|
656 self_type &parent = force_path(p);
|
Chris@16
|
657 // Got the parent.
|
Chris@16
|
658 key_type fragment = p.reduce();
|
Chris@16
|
659 return parent.push_back(value_type(fragment, value))->second;
|
Chris@16
|
660 }
|
Chris@16
|
661
|
Chris@16
|
662 template<class K, class D, class C>
|
Chris@16
|
663 template<class Type, class Translator>
|
Chris@16
|
664 typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
Chris@16
|
665 basic_ptree<K, D, C>::get_value(Translator tr) const
|
Chris@16
|
666 {
|
Chris@16
|
667 if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
|
Chris@16
|
668 return *o;
|
Chris@16
|
669 }
|
Chris@16
|
670 BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
Chris@16
|
671 std::string("conversion of data to type \"") +
|
Chris@16
|
672 typeid(Type).name() + "\" failed", data()));
|
Chris@16
|
673 }
|
Chris@16
|
674
|
Chris@16
|
675 template<class K, class D, class C>
|
Chris@16
|
676 template<class Type> inline
|
Chris@16
|
677 Type basic_ptree<K, D, C>::get_value() const
|
Chris@16
|
678 {
|
Chris@16
|
679 return get_value<Type>(
|
Chris@16
|
680 typename translator_between<data_type, Type>::type());
|
Chris@16
|
681 }
|
Chris@16
|
682
|
Chris@16
|
683 template<class K, class D, class C>
|
Chris@16
|
684 template<class Type, class Translator> inline
|
Chris@16
|
685 Type basic_ptree<K, D, C>::get_value(const Type &default_value,
|
Chris@16
|
686 Translator tr) const
|
Chris@16
|
687 {
|
Chris@16
|
688 return get_value_optional<Type>(tr).get_value_or(default_value);
|
Chris@16
|
689 }
|
Chris@16
|
690
|
Chris@16
|
691 template<class K, class D, class C>
|
Chris@16
|
692 template <class Ch, class Translator>
|
Chris@16
|
693 typename boost::enable_if<
|
Chris@16
|
694 detail::is_character<Ch>,
|
Chris@16
|
695 std::basic_string<Ch>
|
Chris@16
|
696 >::type
|
Chris@16
|
697 basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
|
Chris@16
|
698 {
|
Chris@16
|
699 return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 template<class K, class D, class C>
|
Chris@16
|
703 template<class Type> inline
|
Chris@16
|
704 typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
Chris@16
|
705 basic_ptree<K, D, C>::get_value(const Type &default_value) const
|
Chris@16
|
706 {
|
Chris@16
|
707 return get_value(default_value,
|
Chris@16
|
708 typename translator_between<data_type, Type>::type());
|
Chris@16
|
709 }
|
Chris@16
|
710
|
Chris@16
|
711 template<class K, class D, class C>
|
Chris@16
|
712 template <class Ch>
|
Chris@16
|
713 typename boost::enable_if<
|
Chris@16
|
714 detail::is_character<Ch>,
|
Chris@16
|
715 std::basic_string<Ch>
|
Chris@16
|
716 >::type
|
Chris@16
|
717 basic_ptree<K, D, C>::get_value(const Ch *default_value) const
|
Chris@16
|
718 {
|
Chris@16
|
719 return get_value< std::basic_string<Ch> >(default_value);
|
Chris@16
|
720 }
|
Chris@16
|
721
|
Chris@16
|
722 template<class K, class D, class C>
|
Chris@16
|
723 template<class Type, class Translator> inline
|
Chris@16
|
724 optional<Type> basic_ptree<K, D, C>::get_value_optional(
|
Chris@16
|
725 Translator tr) const
|
Chris@16
|
726 {
|
Chris@16
|
727 return tr.get_value(data());
|
Chris@16
|
728 }
|
Chris@16
|
729
|
Chris@16
|
730 template<class K, class D, class C>
|
Chris@16
|
731 template<class Type> inline
|
Chris@16
|
732 optional<Type> basic_ptree<K, D, C>::get_value_optional() const
|
Chris@16
|
733 {
|
Chris@16
|
734 return get_value_optional<Type>(
|
Chris@16
|
735 typename translator_between<data_type, Type>::type());
|
Chris@16
|
736 }
|
Chris@16
|
737
|
Chris@16
|
738 template<class K, class D, class C>
|
Chris@16
|
739 template<class Type, class Translator> inline
|
Chris@16
|
740 typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
Chris@16
|
741 basic_ptree<K, D, C>::get(const path_type &path,
|
Chris@16
|
742 Translator tr) const
|
Chris@16
|
743 {
|
Chris@16
|
744 return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
|
Chris@16
|
745 }
|
Chris@16
|
746
|
Chris@16
|
747 template<class K, class D, class C>
|
Chris@16
|
748 template<class Type> inline
|
Chris@16
|
749 Type basic_ptree<K, D, C>::get(const path_type &path) const
|
Chris@16
|
750 {
|
Chris@16
|
751 return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
|
Chris@16
|
752 }
|
Chris@16
|
753
|
Chris@16
|
754 template<class K, class D, class C>
|
Chris@16
|
755 template<class Type, class Translator> inline
|
Chris@16
|
756 Type basic_ptree<K, D, C>::get(const path_type &path,
|
Chris@16
|
757 const Type &default_value,
|
Chris@16
|
758 Translator tr) const
|
Chris@16
|
759 {
|
Chris@16
|
760 return get_optional<Type>(path, tr).get_value_or(default_value);
|
Chris@16
|
761 }
|
Chris@16
|
762
|
Chris@16
|
763 template<class K, class D, class C>
|
Chris@16
|
764 template <class Ch, class Translator>
|
Chris@16
|
765 typename boost::enable_if<
|
Chris@16
|
766 detail::is_character<Ch>,
|
Chris@16
|
767 std::basic_string<Ch>
|
Chris@16
|
768 >::type
|
Chris@16
|
769 basic_ptree<K, D, C>::get(
|
Chris@16
|
770 const path_type &path, const Ch *default_value, Translator tr) const
|
Chris@16
|
771 {
|
Chris@16
|
772 return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
|
Chris@16
|
773 }
|
Chris@16
|
774
|
Chris@16
|
775 template<class K, class D, class C>
|
Chris@16
|
776 template<class Type> inline
|
Chris@16
|
777 typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
Chris@16
|
778 basic_ptree<K, D, C>::get(const path_type &path,
|
Chris@16
|
779 const Type &default_value) const
|
Chris@16
|
780 {
|
Chris@16
|
781 return get_optional<Type>(path).get_value_or(default_value);
|
Chris@16
|
782 }
|
Chris@16
|
783
|
Chris@16
|
784 template<class K, class D, class C>
|
Chris@16
|
785 template <class Ch>
|
Chris@16
|
786 typename boost::enable_if<
|
Chris@16
|
787 detail::is_character<Ch>,
|
Chris@16
|
788 std::basic_string<Ch>
|
Chris@16
|
789 >::type
|
Chris@16
|
790 basic_ptree<K, D, C>::get(
|
Chris@16
|
791 const path_type &path, const Ch *default_value) const
|
Chris@16
|
792 {
|
Chris@16
|
793 return get< std::basic_string<Ch> >(path, default_value);
|
Chris@16
|
794 }
|
Chris@16
|
795
|
Chris@16
|
796 template<class K, class D, class C>
|
Chris@16
|
797 template<class Type, class Translator>
|
Chris@16
|
798 optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
|
Chris@16
|
799 Translator tr) const
|
Chris@16
|
800 {
|
Chris@16
|
801 if (optional<const self_type&> child = get_child_optional(path))
|
Chris@16
|
802 return child.get().
|
Chris@16
|
803 BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
|
Chris@16
|
804 else
|
Chris@16
|
805 return optional<Type>();
|
Chris@16
|
806 }
|
Chris@16
|
807
|
Chris@16
|
808 template<class K, class D, class C>
|
Chris@16
|
809 template<class Type>
|
Chris@16
|
810 optional<Type> basic_ptree<K, D, C>::get_optional(
|
Chris@16
|
811 const path_type &path) const
|
Chris@16
|
812 {
|
Chris@16
|
813 if (optional<const self_type&> child = get_child_optional(path))
|
Chris@16
|
814 return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
|
Chris@16
|
815 else
|
Chris@16
|
816 return optional<Type>();
|
Chris@16
|
817 }
|
Chris@16
|
818
|
Chris@16
|
819 template<class K, class D, class C>
|
Chris@16
|
820 template<class Type, class Translator>
|
Chris@16
|
821 void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
|
Chris@16
|
822 {
|
Chris@16
|
823 if(optional<data_type> o = tr.put_value(value)) {
|
Chris@16
|
824 data() = *o;
|
Chris@16
|
825 } else {
|
Chris@16
|
826 BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
Chris@16
|
827 std::string("conversion of type \"") + typeid(Type).name() +
|
Chris@16
|
828 "\" to data failed", boost::any()));
|
Chris@16
|
829 }
|
Chris@16
|
830 }
|
Chris@16
|
831
|
Chris@16
|
832 template<class K, class D, class C>
|
Chris@16
|
833 template<class Type> inline
|
Chris@16
|
834 void basic_ptree<K, D, C>::put_value(const Type &value)
|
Chris@16
|
835 {
|
Chris@16
|
836 put_value(value, typename translator_between<data_type, Type>::type());
|
Chris@16
|
837 }
|
Chris@16
|
838
|
Chris@16
|
839 template<class K, class D, class C>
|
Chris@16
|
840 template<class Type, typename Translator>
|
Chris@16
|
841 basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
Chris@16
|
842 const path_type &path, const Type &value, Translator tr)
|
Chris@16
|
843 {
|
Chris@16
|
844 if(optional<self_type &> child = get_child_optional(path)) {
|
Chris@16
|
845 child.get().put_value(value, tr);
|
Chris@16
|
846 return *child;
|
Chris@16
|
847 } else {
|
Chris@16
|
848 self_type &child2 = put_child(path, self_type());
|
Chris@16
|
849 child2.put_value(value, tr);
|
Chris@16
|
850 return child2;
|
Chris@16
|
851 }
|
Chris@16
|
852 }
|
Chris@16
|
853
|
Chris@16
|
854 template<class K, class D, class C>
|
Chris@16
|
855 template<class Type> inline
|
Chris@16
|
856 basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
Chris@16
|
857 const path_type &path, const Type &value)
|
Chris@16
|
858 {
|
Chris@16
|
859 return put(path, value,
|
Chris@16
|
860 typename translator_between<data_type, Type>::type());
|
Chris@16
|
861 }
|
Chris@16
|
862
|
Chris@16
|
863 template<class K, class D, class C>
|
Chris@16
|
864 template<class Type, typename Translator> inline
|
Chris@16
|
865 basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
Chris@16
|
866 const path_type &path, const Type &value, Translator tr)
|
Chris@16
|
867 {
|
Chris@16
|
868 self_type &child = add_child(path, self_type());
|
Chris@16
|
869 child.put_value(value, tr);
|
Chris@16
|
870 return child;
|
Chris@16
|
871 }
|
Chris@16
|
872
|
Chris@16
|
873 template<class K, class D, class C>
|
Chris@16
|
874 template<class Type> inline
|
Chris@16
|
875 basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
Chris@16
|
876 const path_type &path, const Type &value)
|
Chris@16
|
877 {
|
Chris@16
|
878 return add(path, value,
|
Chris@16
|
879 typename translator_between<data_type, Type>::type());
|
Chris@16
|
880 }
|
Chris@16
|
881
|
Chris@16
|
882
|
Chris@16
|
883 template<class K, class D, class C>
|
Chris@16
|
884 basic_ptree<K, D, C> *
|
Chris@16
|
885 basic_ptree<K, D, C>::walk_path(path_type &p) const
|
Chris@16
|
886 {
|
Chris@16
|
887 if(p.empty()) {
|
Chris@16
|
888 // I'm the child we're looking for.
|
Chris@16
|
889 return const_cast<basic_ptree*>(this);
|
Chris@16
|
890 }
|
Chris@16
|
891 // Recurse down the tree to find the path.
|
Chris@16
|
892 key_type fragment = p.reduce();
|
Chris@16
|
893 const_assoc_iterator el = find(fragment);
|
Chris@16
|
894 if(el == not_found()) {
|
Chris@16
|
895 // No such child.
|
Chris@16
|
896 return 0;
|
Chris@16
|
897 }
|
Chris@16
|
898 // Not done yet, recurse.
|
Chris@16
|
899 return el->second.walk_path(p);
|
Chris@16
|
900 }
|
Chris@16
|
901
|
Chris@16
|
902 template<class K, class D, class C>
|
Chris@16
|
903 basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
|
Chris@16
|
904 {
|
Chris@16
|
905 BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
|
Chris@16
|
906 if(p.single()) {
|
Chris@16
|
907 // I'm the parent we're looking for.
|
Chris@16
|
908 return *this;
|
Chris@16
|
909 }
|
Chris@16
|
910 key_type fragment = p.reduce();
|
Chris@16
|
911 assoc_iterator el = find(fragment);
|
Chris@16
|
912 // If we've found an existing child, go down that path. Else
|
Chris@16
|
913 // create a new one.
|
Chris@16
|
914 self_type& child = el == not_found() ?
|
Chris@16
|
915 push_back(value_type(fragment, self_type()))->second : el->second;
|
Chris@16
|
916 return child.force_path(p);
|
Chris@16
|
917 }
|
Chris@16
|
918
|
Chris@16
|
919 // Free functions
|
Chris@16
|
920
|
Chris@16
|
921 template<class K, class D, class C>
|
Chris@16
|
922 inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
|
Chris@16
|
923 {
|
Chris@16
|
924 pt1.swap(pt2);
|
Chris@16
|
925 }
|
Chris@16
|
926
|
Chris@16
|
927 } }
|
Chris@16
|
928
|
Chris@16
|
929 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
Chris@16
|
930 #undef BOOST_PROPERTY_TREE_PAIR_BUG
|
Chris@16
|
931 #endif
|
Chris@16
|
932
|
Chris@16
|
933 #endif
|