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