1
// ----------------------------------------------------------------------------
2
// Copyright (C) 2002-2006 Marcin Kalicinski
3
// Copyright (C) 2009 Sebastian Redl
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)
9
// For more information, see www.boost.org
10
// ----------------------------------------------------------------------------
11
#ifndef LIBLAS_BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
12
#define LIBLAS_BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
14
#include <boost/iterator/iterator_adaptor.hpp>
15
#include <boost/iterator/reverse_iterator.hpp>
18
#if defined(BOOST_MSVC) && \
19
(_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)
20
#define BOOST_PROPERTY_TREE_PAIR_BUG
23
namespace liblas { namespace property_tree
25
template <class K, class D, class C>
26
struct basic_ptree<K, D, C>::subs
29
// The actual child container.
30
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
31
// MSVC 10 has moved std::pair's members to a base
32
// class. Unfortunately this does break the interface.
33
BOOST_STATIC_CONSTANT(unsigned,
34
first_offset = offsetof(value_type, first));
35
typedef ::boost::multi_index_container<value_type,
36
::boost::multi_index::indexed_by<
37
::boost::multi_index::sequenced<>,
38
::boost::multi_index::ordered_non_unique< ::boost::multi_index::tag<by_name>,
39
::boost::multi_index::member_offset<value_type, const key_type,
46
typedef ::boost::multi_index_container<value_type,
47
::boost::multi_index::indexed_by<
48
::boost::multi_index::sequenced<>,
49
::boost::multi_index::ordered_non_unique< ::boost::multi_index::tag<by_name>,
50
::boost::multi_index::member<value_type, const key_type,
57
// The by-name lookup index.
58
typedef typename base_container::template index<by_name>::type
61
// Access functions for getting to the children of a tree.
62
static base_container& ch(self_type *s) {
63
return *static_cast<base_container*>(s->m_children);
65
static const base_container& ch(const self_type *s) {
66
return *static_cast<const base_container*>(s->m_children);
68
static by_name_index& assoc(self_type *s) {
69
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
71
static const by_name_index& assoc(const self_type *s) {
72
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
75
template <class K, class D, class C>
76
class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
77
iterator, typename subs::base_container::iterator, value_type>
79
friend class boost::iterator_core_access;
80
typedef boost::iterator_adaptor<
81
iterator, typename subs::base_container::iterator, value_type>
84
typedef typename baset::reference reference;
86
explicit iterator(typename iterator::base_type b)
87
: iterator::iterator_adaptor_(b)
89
reference dereference() const
91
// multi_index doesn't allow modification of its values, because
92
// indexes could sort by anything, and modification screws that up.
93
// However, we only sort by the key, and it's protected against
94
// modification in the value_type, so this const_cast is safe.
95
return const_cast<reference>(*this->base_reference());
98
template <class K, class D, class C>
99
class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
100
const_iterator, typename subs::base_container::const_iterator>
104
explicit const_iterator(typename const_iterator::base_type b)
105
: const_iterator::iterator_adaptor_(b)
107
const_iterator(iterator b)
108
: const_iterator::iterator_adaptor_(b.base())
111
template <class K, class D, class C>
112
class basic_ptree<K, D, C>::reverse_iterator
113
: public boost::reverse_iterator<iterator>
116
reverse_iterator() {}
117
explicit reverse_iterator(iterator b)
118
: boost::reverse_iterator<iterator>(b)
121
template <class K, class D, class C>
122
class basic_ptree<K, D, C>::const_reverse_iterator
123
: public boost::reverse_iterator<const_iterator>
126
const_reverse_iterator() {}
127
explicit const_reverse_iterator(const_iterator b)
128
: boost::reverse_iterator<const_iterator>(b)
130
const_reverse_iterator(
131
typename basic_ptree<K, D, C>::reverse_iterator b)
132
: boost::reverse_iterator<const_iterator>(b)
135
template <class K, class D, class C>
136
class basic_ptree<K, D, C>::assoc_iterator
137
: public boost::iterator_adaptor<assoc_iterator,
138
typename subs::by_name_index::iterator,
141
friend class boost::iterator_core_access;
142
typedef boost::iterator_adaptor<assoc_iterator,
143
typename subs::by_name_index::iterator,
147
typedef typename baset::reference reference;
149
explicit assoc_iterator(typename assoc_iterator::base_type b)
150
: assoc_iterator::iterator_adaptor_(b)
152
reference dereference() const
154
return const_cast<reference>(*this->base_reference());
157
template <class K, class D, class C>
158
class basic_ptree<K, D, C>::const_assoc_iterator
159
: public boost::iterator_adaptor<const_assoc_iterator,
160
typename subs::by_name_index::const_iterator>
163
const_assoc_iterator() {}
164
explicit const_assoc_iterator(
165
typename const_assoc_iterator::base_type b)
166
: const_assoc_iterator::iterator_adaptor_(b)
168
const_assoc_iterator(assoc_iterator b)
169
: const_assoc_iterator::iterator_adaptor_(b.base())
176
// Perhaps the children collection could be created on-demand only, to
177
// reduce heap traffic. But that's a lot more work to implement.
179
template<class K, class D, class C> inline
180
basic_ptree<K, D, C>::basic_ptree()
181
: m_children(new typename subs::base_container)
185
template<class K, class D, class C> inline
186
basic_ptree<K, D, C>::basic_ptree(const data_type &d)
187
: m_data(d), m_children(new typename subs::base_container)
191
template<class K, class D, class C> inline
192
basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
193
: m_data(rhs.m_data),
194
m_children(new typename subs::base_container(subs::ch(&rhs)))
198
template<class K, class D, class C>
199
basic_ptree<K, D, C> &
200
basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
202
self_type(rhs).swap(*this);
206
template<class K, class D, class C>
207
basic_ptree<K, D, C>::~basic_ptree()
209
delete &subs::ch(this);
212
template<class K, class D, class C> inline
213
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
215
m_data.swap(rhs.m_data);
216
// Void pointers, no ADL necessary
217
std::swap(m_children, rhs.m_children);
222
template<class K, class D, class C> inline
223
typename basic_ptree<K, D, C>::size_type
224
basic_ptree<K, D, C>::size() const
226
return subs::ch(this).size();
229
template<class K, class D, class C> inline
230
typename basic_ptree<K, D, C>::size_type
231
basic_ptree<K, D, C>::max_size() const
233
return subs::ch(this).max_size();
236
template<class K, class D, class C> inline
237
bool basic_ptree<K, D, C>::empty() const
239
return subs::ch(this).empty();
242
template<class K, class D, class C> inline
243
typename basic_ptree<K, D, C>::iterator
244
basic_ptree<K, D, C>::begin()
246
return iterator(subs::ch(this).begin());
249
template<class K, class D, class C> inline
250
typename basic_ptree<K, D, C>::const_iterator
251
basic_ptree<K, D, C>::begin() const
253
return const_iterator(subs::ch(this).begin());
256
template<class K, class D, class C> inline
257
typename basic_ptree<K, D, C>::iterator
258
basic_ptree<K, D, C>::end()
260
return iterator(subs::ch(this).end());
263
template<class K, class D, class C> inline
264
typename basic_ptree<K, D, C>::const_iterator
265
basic_ptree<K, D, C>::end() const
267
return const_iterator(subs::ch(this).end());
270
template<class K, class D, class C> inline
271
typename basic_ptree<K, D, C>::reverse_iterator
272
basic_ptree<K, D, C>::rbegin()
274
return reverse_iterator(this->end());
277
template<class K, class D, class C> inline
278
typename basic_ptree<K, D, C>::const_reverse_iterator
279
basic_ptree<K, D, C>::rbegin() const
281
return const_reverse_iterator(this->end());
284
template<class K, class D, class C> inline
285
typename basic_ptree<K, D, C>::reverse_iterator
286
basic_ptree<K, D, C>::rend()
288
return reverse_iterator(this->begin());
291
template<class K, class D, class C> inline
292
typename basic_ptree<K, D, C>::const_reverse_iterator
293
basic_ptree<K, D, C>::rend() const
295
return const_reverse_iterator(this->begin());
298
template<class K, class D, class C> inline
299
typename basic_ptree<K, D, C>::value_type &
300
basic_ptree<K, D, C>::front()
302
return const_cast<value_type&>(subs::ch(this).front());
305
template<class K, class D, class C> inline
306
const typename basic_ptree<K, D, C>::value_type &
307
basic_ptree<K, D, C>::front() const
309
return subs::ch(this).front();
312
template<class K, class D, class C> inline
313
typename basic_ptree<K, D, C>::value_type &
314
basic_ptree<K, D, C>::back()
316
return const_cast<value_type&>(subs::ch(this).back());
319
template<class K, class D, class C> inline
320
const typename basic_ptree<K, D, C>::value_type &
321
basic_ptree<K, D, C>::back() const
323
return subs::ch(this).back();
326
template<class K, class D, class C> inline
327
typename basic_ptree<K, D, C>::iterator
328
basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
330
return iterator(subs::ch(this).insert(where.base(), value).first);
333
template<class K, class D, class C>
334
template<class It> inline
335
void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
337
subs::ch(this).insert(where.base(), first, last);
340
template<class K, class D, class C> inline
341
typename basic_ptree<K, D, C>::iterator
342
basic_ptree<K, D, C>::erase(iterator where)
344
return iterator(subs::ch(this).erase(where.base()));
347
template<class K, class D, class C> inline
348
typename basic_ptree<K, D, C>::iterator
349
basic_ptree<K, D, C>::erase(iterator first, iterator last)
351
return iterator(subs::ch(this).erase(first.base(), last.base()));
354
template<class K, class D, class C> inline
355
typename basic_ptree<K, D, C>::iterator
356
basic_ptree<K, D, C>::push_front(const value_type &value)
358
return iterator(subs::ch(this).push_front(value).first);
361
template<class K, class D, class C> inline
362
typename basic_ptree<K, D, C>::iterator
363
basic_ptree<K, D, C>::push_back(const value_type &value)
365
return iterator(subs::ch(this).push_back(value).first);
368
template<class K, class D, class C> inline
369
void basic_ptree<K, D, C>::pop_front()
371
subs::ch(this).pop_front();
374
template<class K, class D, class C> inline
375
void basic_ptree<K, D, C>::pop_back()
377
subs::ch(this).pop_back();
380
template<class K, class D, class C> inline
381
void basic_ptree<K, D, C>::reverse()
383
subs::ch(this).reverse();
386
template<class K, class D, class C> inline
387
void basic_ptree<K, D, C>::sort()
389
subs::ch(this).sort();
392
template<class K, class D, class C>
393
template<class Compare> inline
394
void basic_ptree<K, D, C>::sort(Compare comp)
396
subs::ch(this).sort(comp);
401
template<class K, class D, class C> inline
402
bool basic_ptree<K, D, C>::operator ==(
403
const basic_ptree<K, D, C> &rhs) const
405
// The size test is cheap, so add it as an optimization
406
return size() == rhs.size() && data() == rhs.data() &&
407
subs::ch(this) == subs::ch(&rhs);
410
template<class K, class D, class C> inline
411
bool basic_ptree<K, D, C>::operator !=(
412
const basic_ptree<K, D, C> &rhs) const
414
return !(*this == rhs);
419
template<class K, class D, class C> inline
420
typename basic_ptree<K, D, C>::assoc_iterator
421
basic_ptree<K, D, C>::ordered_begin()
423
return assoc_iterator(subs::assoc(this).begin());
426
template<class K, class D, class C> inline
427
typename basic_ptree<K, D, C>::const_assoc_iterator
428
basic_ptree<K, D, C>::ordered_begin() const
430
return const_assoc_iterator(subs::assoc(this).begin());
433
template<class K, class D, class C> inline
434
typename basic_ptree<K, D, C>::assoc_iterator
435
basic_ptree<K, D, C>::not_found()
437
return assoc_iterator(subs::assoc(this).end());
440
template<class K, class D, class C> inline
441
typename basic_ptree<K, D, C>::const_assoc_iterator
442
basic_ptree<K, D, C>::not_found() const
444
return const_assoc_iterator(subs::assoc(this).end());
447
template<class K, class D, class C> inline
448
typename basic_ptree<K, D, C>::assoc_iterator
449
basic_ptree<K, D, C>::find(const key_type &key)
451
return assoc_iterator(subs::assoc(this).find(key));
454
template<class K, class D, class C> inline
455
typename basic_ptree<K, D, C>::const_assoc_iterator
456
basic_ptree<K, D, C>::find(const key_type &key) const
458
return const_assoc_iterator(subs::assoc(this).find(key));
461
template<class K, class D, class C> inline
463
typename basic_ptree<K, D, C>::assoc_iterator,
464
typename basic_ptree<K, D, C>::assoc_iterator
465
> basic_ptree<K, D, C>::equal_range(const key_type &key)
467
std::pair<typename subs::by_name_index::iterator,
468
typename subs::by_name_index::iterator> r(
469
subs::assoc(this).equal_range(key));
470
return std::pair<assoc_iterator, assoc_iterator>(
471
assoc_iterator(r.first), assoc_iterator(r.second));
474
template<class K, class D, class C> inline
476
typename basic_ptree<K, D, C>::const_assoc_iterator,
477
typename basic_ptree<K, D, C>::const_assoc_iterator
478
> basic_ptree<K, D, C>::equal_range(const key_type &key) const
480
std::pair<typename subs::by_name_index::const_iterator,
481
typename subs::by_name_index::const_iterator> r(
482
subs::assoc(this).equal_range(key));
483
return std::pair<const_assoc_iterator, const_assoc_iterator>(
484
const_assoc_iterator(r.first), const_assoc_iterator(r.second));
487
template<class K, class D, class C> inline
488
typename basic_ptree<K, D, C>::size_type
489
basic_ptree<K, D, C>::count(const key_type &key) const
491
return subs::assoc(this).count(key);
494
template<class K, class D, class C> inline
495
typename basic_ptree<K, D, C>::size_type
496
basic_ptree<K, D, C>::erase(const key_type &key)
498
return subs::assoc(this).erase(key);
501
template<class K, class D, class C> inline
502
typename basic_ptree<K, D, C>::iterator
503
basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
505
return iterator(subs::ch(this).
506
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
509
template<class K, class D, class C> inline
510
typename basic_ptree<K, D, C>::const_iterator
511
basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
513
return const_iterator(subs::ch(this).
514
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
517
// Property tree view
519
template<class K, class D, class C> inline
520
typename basic_ptree<K, D, C>::data_type &
521
basic_ptree<K, D, C>::data()
526
template<class K, class D, class C> inline
527
const typename basic_ptree<K, D, C>::data_type &
528
basic_ptree<K, D, C>::data() const
533
template<class K, class D, class C> inline
534
void basic_ptree<K, D, C>::clear()
536
m_data = data_type();
537
subs::ch(this).clear();
540
template<class K, class D, class C>
541
basic_ptree<K, D, C> &
542
basic_ptree<K, D, C>::get_child(const path_type &path)
545
self_type *n = walk_path(p);
547
BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
552
template<class K, class D, class C> inline
553
const basic_ptree<K, D, C> &
554
basic_ptree<K, D, C>::get_child(const path_type &path) const
556
return const_cast<self_type*>(this)->get_child(path);
559
template<class K, class D, class C> inline
560
basic_ptree<K, D, C> &
561
basic_ptree<K, D, C>::get_child(const path_type &path,
562
self_type &default_value)
565
self_type *n = walk_path(p);
566
return n ? *n : default_value;
569
template<class K, class D, class C> inline
570
const basic_ptree<K, D, C> &
571
basic_ptree<K, D, C>::get_child(const path_type &path,
572
const self_type &default_value) const
574
return const_cast<self_type*>(this)->get_child(path,
575
const_cast<self_type&>(default_value));
579
template<class K, class D, class C>
580
::boost::optional<basic_ptree<K, D, C> &>
581
basic_ptree<K, D, C>::get_child_optional(const path_type &path)
584
self_type *n = walk_path(p);
586
return ::boost::optional<self_type&>();
591
template<class K, class D, class C>
592
::boost::optional<const basic_ptree<K, D, C> &>
593
basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
596
self_type *n = walk_path(p);
598
return ::boost::optional<const self_type&>();
603
template<class K, class D, class C>
604
basic_ptree<K, D, C> &
605
basic_ptree<K, D, C>::put_child(const path_type &path,
606
const self_type &value)
609
self_type &parent = force_path(p);
610
// Got the parent. Now get the correct child.
611
key_type fragment = p.reduce();
612
assoc_iterator el = parent.find(fragment);
613
// If the new child exists, replace it.
614
if(el != parent.not_found()) {
615
return el->second = value;
617
return parent.push_back(value_type(fragment, value))->second;
621
template<class K, class D, class C>
622
basic_ptree<K, D, C> &
623
basic_ptree<K, D, C>::add_child(const path_type &path,
624
const self_type &value)
627
self_type &parent = force_path(p);
629
key_type fragment = p.reduce();
630
return parent.push_back(value_type(fragment, value))->second;
634
#pragma warning(push)
635
#pragma warning(disable: 4715)
637
template<class K, class D, class C>
638
template<class Type, class Translator>
639
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
640
basic_ptree<K, D, C>::get_value(Translator tr) const
642
if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
645
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
646
std::string("conversion of data to type \"") +
647
typeid(Type).name() + "\" failed", data()));
652
template<class K, class D, class C>
653
template<class Type> inline
654
Type basic_ptree<K, D, C>::get_value() const
656
return get_value<Type>(
657
typename translator_between<data_type, Type>::type());
660
template<class K, class D, class C>
661
template<class Type, class Translator> inline
662
Type basic_ptree<K, D, C>::get_value(const Type &default_value,
665
return get_value_optional<Type>(tr).get_value_or(default_value);
668
template<class K, class D, class C>
669
template <class Ch, class Translator>
670
typename boost::enable_if<
671
detail::is_character<Ch>,
672
std::basic_string<Ch>
674
basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
676
return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
679
template<class K, class D, class C>
680
template<class Type> inline
681
typename boost::disable_if<detail::is_translator<Type>, Type>::type
682
basic_ptree<K, D, C>::get_value(const Type &default_value) const
684
return get_value(default_value,
685
typename translator_between<data_type, Type>::type());
688
template<class K, class D, class C>
690
typename boost::enable_if<
691
detail::is_character<Ch>,
692
std::basic_string<Ch>
694
basic_ptree<K, D, C>::get_value(const Ch *default_value) const
696
return get_value< std::basic_string<Ch> >(default_value);
699
template<class K, class D, class C>
700
template<class Type, class Translator> inline
701
::boost::optional<Type> basic_ptree<K, D, C>::get_value_optional(
704
return tr.get_value(data());
707
template<class K, class D, class C>
708
template<class Type> inline
709
::boost::optional<Type> basic_ptree<K, D, C>::get_value_optional() const
711
return get_value_optional<Type>(
712
typename translator_between<data_type, Type>::type());
715
template<class K, class D, class C>
716
template<class Type, class Translator> inline
717
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
718
basic_ptree<K, D, C>::get(const path_type &path,
721
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
724
template<class K, class D, class C>
725
template<class Type> inline
726
Type basic_ptree<K, D, C>::get(const path_type &path) const
728
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
731
template<class K, class D, class C>
732
template<class Type, class Translator> inline
733
Type basic_ptree<K, D, C>::get(const path_type &path,
734
const Type &default_value,
737
return get_optional<Type>(path, tr).get_value_or(default_value);
740
template<class K, class D, class C>
741
template <class Ch, class Translator>
742
typename boost::enable_if<
743
detail::is_character<Ch>,
744
std::basic_string<Ch>
746
basic_ptree<K, D, C>::get(
747
const path_type &path, const Ch *default_value, Translator tr) const
749
return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
752
template<class K, class D, class C>
753
template<class Type> inline
754
typename boost::disable_if<detail::is_translator<Type>, Type>::type
755
basic_ptree<K, D, C>::get(const path_type &path,
756
const Type &default_value) const
758
return get_optional<Type>(path).get_value_or(default_value);
761
template<class K, class D, class C>
763
typename boost::enable_if<
764
detail::is_character<Ch>,
765
std::basic_string<Ch>
767
basic_ptree<K, D, C>::get(
768
const path_type &path, const Ch *default_value) const
770
return get< std::basic_string<Ch> >(path, default_value);
773
template<class K, class D, class C>
774
template<class Type, class Translator>
775
::boost::optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
778
if (::boost::optional<const self_type&> child = get_child_optional(path))
780
BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
782
return ::boost::optional<Type>();
785
template<class K, class D, class C>
787
::boost::optional<Type> basic_ptree<K, D, C>::get_optional(
788
const path_type &path) const
790
if (::boost::optional<const self_type&> child = get_child_optional(path))
791
return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
793
return ::boost::optional<Type>();
796
template<class K, class D, class C>
797
template<class Type, class Translator>
798
void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
800
if(::boost::optional<data_type> o = tr.put_value(value)) {
803
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
804
std::string("conversion of type \"") + typeid(Type).name() +
805
"\" to data failed", boost::any()));
809
template<class K, class D, class C>
810
template<class Type> inline
811
void basic_ptree<K, D, C>::put_value(const Type &value)
813
put_value(value, typename translator_between<data_type, Type>::type());
816
template<class K, class D, class C>
817
template<class Type, typename Translator>
818
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
819
const path_type &path, const Type &value, Translator tr)
821
if(::boost::optional<self_type &> child = get_child_optional(path)) {
822
child.get().put_value(value, tr);
825
self_type &child2 = put_child(path, self_type());
826
child2.put_value(value, tr);
831
template<class K, class D, class C>
832
template<class Type> inline
833
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
834
const path_type &path, const Type &value)
836
return put(path, value,
837
typename translator_between<data_type, Type>::type());
840
template<class K, class D, class C>
841
template<class Type, typename Translator> inline
842
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
843
const path_type &path, const Type &value, Translator tr)
845
self_type &child = add_child(path, self_type());
846
child.put_value(value, tr);
850
template<class K, class D, class C>
851
template<class Type> inline
852
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
853
const path_type &path, const Type &value)
855
return add(path, value,
856
typename translator_between<data_type, Type>::type());
860
template<class K, class D, class C>
861
basic_ptree<K, D, C> *
862
basic_ptree<K, D, C>::walk_path(path_type &p) const
865
// I'm the child we're looking for.
866
return const_cast<basic_ptree*>(this);
868
// Recurse down the tree to find the path.
869
key_type fragment = p.reduce();
870
const_assoc_iterator el = find(fragment);
871
if(el == not_found()) {
875
// Not done yet, recurse.
876
return el->second.walk_path(p);
879
template<class K, class D, class C>
880
basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
882
assert(!p.empty() && "Empty path not allowed for put_child.");
884
// I'm the parent we're looking for.
887
key_type fragment = p.reduce();
888
assoc_iterator el = find(fragment);
889
// If we've found an existing child, go down that path. Else
891
self_type& child = el == not_found() ?
892
push_back(value_type(fragment, self_type()))->second : el->second;
893
return child.force_path(p);
898
template<class K, class D, class C>
899
inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
906
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
907
#undef BOOST_PROPERTY_TREE_PAIR_BUG