Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 08:29:05

0001 // ----------------------------------------------------------------------------
0002 // Copyright (C) 2002-2006 Marcin Kalicinski
0003 // Copyright (C) 2009 Sebastian Redl
0004 //
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // (See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // For more information, see www.boost.org
0010 // ----------------------------------------------------------------------------
0011 #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
0012 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
0013 
0014 #include <boost/property_tree/ptree.hpp>
0015 #include <boost/iterator/iterator_adaptor.hpp>
0016 #include <boost/iterator/reverse_iterator.hpp>
0017 #include <boost/assert.hpp>
0018 #include <boost/core/invoke_swap.hpp>
0019 #include <boost/core/type_name.hpp>
0020 #include <memory>
0021 
0022 #if (defined(BOOST_MSVC) && \
0023      (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
0024     (defined(BOOST_INTEL_WIN) && \
0025      defined(BOOST_DINKUMWARE_STDLIB))
0026 #define BOOST_PROPERTY_TREE_PAIR_BUG
0027 #endif
0028 
0029 namespace boost { namespace property_tree
0030 {
0031     template <class K, class D, class C>
0032     struct basic_ptree<K, D, C>::subs
0033     {
0034         struct by_name {};
0035         // The actual child container.
0036 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
0037         // MSVC 10 has moved std::pair's members to a base
0038         // class. Unfortunately this does break the interface.
0039         BOOST_STATIC_CONSTANT(unsigned,
0040             first_offset = offsetof(value_type, first));
0041 #endif
0042         typedef multi_index_container<value_type,
0043             multi_index::indexed_by<
0044                 multi_index::sequenced<>,
0045                 multi_index::ordered_non_unique<multi_index::tag<by_name>,
0046 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
0047                     multi_index::member_offset<value_type, const key_type,
0048                                         first_offset>,
0049 #else
0050                     multi_index::member<value_type, const key_type,
0051                                         &value_type::first>,
0052 #endif
0053                     key_compare
0054                 >
0055             >
0056         > base_container;
0057 
0058         // The by-name lookup index.
0059         typedef typename base_container::template index<by_name>::type
0060             by_name_index;
0061 
0062         // Access functions for getting to the children of a tree.
0063         static base_container& ch(self_type *s) {
0064             return *static_cast<base_container*>(s->m_children);
0065         }
0066         static const base_container& ch(const self_type *s) {
0067             return *static_cast<const base_container*>(s->m_children);
0068         }
0069         static by_name_index& assoc(self_type *s) {
0070             return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
0071         }
0072         static const by_name_index& assoc(const self_type *s) {
0073             return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
0074         }
0075     };
0076     template <class K, class D, class C>
0077     class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
0078         iterator, typename subs::base_container::iterator, value_type>
0079     {
0080         friend class boost::iterator_core_access;
0081         typedef boost::iterator_adaptor<
0082             iterator, typename subs::base_container::iterator, value_type>
0083             baset;
0084     public:
0085         typedef typename baset::reference reference;
0086         iterator() {}
0087         explicit iterator(typename iterator::base_type b)
0088             : iterator::iterator_adaptor_(b)
0089         {}
0090         reference dereference() const
0091         {
0092             // multi_index doesn't allow modification of its values, because
0093             // indexes could sort by anything, and modification screws that up.
0094             // However, we only sort by the key, and it's protected against
0095             // modification in the value_type, so this const_cast is safe.
0096             return const_cast<reference>(*this->base_reference());
0097         }
0098     };
0099     template <class K, class D, class C>
0100     class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
0101         const_iterator, typename subs::base_container::const_iterator>
0102     {
0103     public:
0104         const_iterator() {}
0105         explicit const_iterator(typename const_iterator::base_type b)
0106             : const_iterator::iterator_adaptor_(b)
0107         {}
0108         const_iterator(iterator b)
0109             : const_iterator::iterator_adaptor_(b.base())
0110         {}
0111     };
0112     template <class K, class D, class C>
0113     class basic_ptree<K, D, C>::reverse_iterator
0114         : public boost::reverse_iterator<iterator>
0115     {
0116     public:
0117         reverse_iterator() {}
0118         explicit reverse_iterator(iterator b)
0119             : boost::reverse_iterator<iterator>(b)
0120         {}
0121     };
0122     template <class K, class D, class C>
0123     class basic_ptree<K, D, C>::const_reverse_iterator
0124         : public boost::reverse_iterator<const_iterator>
0125     {
0126     public:
0127         const_reverse_iterator() {}
0128         explicit const_reverse_iterator(const_iterator b)
0129             : boost::reverse_iterator<const_iterator>(b)
0130         {}
0131         const_reverse_iterator(
0132             typename basic_ptree<K, D, C>::reverse_iterator b)
0133             : boost::reverse_iterator<const_iterator>(b)
0134         {}
0135     };
0136     template <class K, class D, class C>
0137     class basic_ptree<K, D, C>::assoc_iterator
0138         : public boost::iterator_adaptor<assoc_iterator,
0139                                          typename subs::by_name_index::iterator,
0140                                          value_type>
0141     {
0142         friend class boost::iterator_core_access;
0143         typedef boost::iterator_adaptor<assoc_iterator,
0144                                          typename subs::by_name_index::iterator,
0145                                          value_type>
0146             baset;
0147     public:
0148         typedef typename baset::reference reference;
0149         assoc_iterator() {}
0150         explicit assoc_iterator(typename assoc_iterator::base_type b)
0151             : assoc_iterator::iterator_adaptor_(b)
0152         {}
0153         reference dereference() const
0154         {
0155             return const_cast<reference>(*this->base_reference());
0156         }
0157     };
0158     template <class K, class D, class C>
0159     class basic_ptree<K, D, C>::const_assoc_iterator
0160         : public boost::iterator_adaptor<const_assoc_iterator,
0161                                    typename subs::by_name_index::const_iterator>
0162     {
0163     public:
0164         const_assoc_iterator() {}
0165         explicit const_assoc_iterator(
0166             typename const_assoc_iterator::base_type b)
0167             : const_assoc_iterator::iterator_adaptor_(b)
0168         {}
0169         const_assoc_iterator(assoc_iterator b)
0170             : const_assoc_iterator::iterator_adaptor_(b.base())
0171         {}
0172     };
0173 
0174 
0175     // Big five
0176 
0177     // Perhaps the children collection could be created on-demand only, to
0178     // reduce heap traffic. But that's a lot more work to implement.
0179 
0180     template<class K, class D, class C> inline
0181     basic_ptree<K, D, C>::basic_ptree()
0182         : m_children(new typename subs::base_container)
0183     {
0184     }
0185 
0186     template<class K, class D, class C> inline
0187     basic_ptree<K, D, C>::basic_ptree(const data_type &d)
0188         : m_data(d), m_children(new typename subs::base_container)
0189     {
0190     }
0191 
0192     template<class K, class D, class C> inline
0193     basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
0194         : m_data(rhs.m_data),
0195           m_children(new typename subs::base_container(subs::ch(&rhs)))
0196     {
0197     }
0198 
0199     template<class K, class D, class C>
0200     basic_ptree<K, D, C> &
0201         basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
0202     {
0203         self_type(rhs).swap(*this);
0204         return *this;
0205     }
0206 
0207     template<class K, class D, class C>
0208     basic_ptree<K, D, C>::~basic_ptree()
0209     {
0210         delete &subs::ch(this);
0211     }
0212 
0213     template<class K, class D, class C> inline
0214     void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
0215     {
0216         boost::core::invoke_swap(m_data, rhs.m_data);
0217         // Void pointers, no ADL necessary
0218         std::swap(m_children, rhs.m_children);
0219     }
0220 
0221     // Container view
0222 
0223     template<class K, class D, class C> inline
0224     typename basic_ptree<K, D, C>::size_type
0225         basic_ptree<K, D, C>::size() const
0226     {
0227         return subs::ch(this).size();
0228     }
0229 
0230     template<class K, class D, class C> inline
0231     typename basic_ptree<K, D, C>::size_type
0232         basic_ptree<K, D, C>::max_size() const
0233     {
0234         return subs::ch(this).max_size();
0235     }
0236 
0237     template<class K, class D, class C> inline
0238     bool basic_ptree<K, D, C>::empty() const
0239     {
0240         return subs::ch(this).empty();
0241     }
0242 
0243     template<class K, class D, class C> inline
0244     typename basic_ptree<K, D, C>::iterator
0245         basic_ptree<K, D, C>::begin()
0246     {
0247         return iterator(subs::ch(this).begin());
0248     }
0249 
0250     template<class K, class D, class C> inline
0251     typename basic_ptree<K, D, C>::const_iterator
0252         basic_ptree<K, D, C>::begin() const
0253     {
0254         return const_iterator(subs::ch(this).begin());
0255     }
0256 
0257     template<class K, class D, class C> inline
0258     typename basic_ptree<K, D, C>::iterator
0259         basic_ptree<K, D, C>::end()
0260     {
0261         return iterator(subs::ch(this).end());
0262     }
0263 
0264     template<class K, class D, class C> inline
0265     typename basic_ptree<K, D, C>::const_iterator
0266         basic_ptree<K, D, C>::end() const
0267     {
0268         return const_iterator(subs::ch(this).end());
0269     }
0270 
0271     template<class K, class D, class C> inline
0272     typename basic_ptree<K, D, C>::reverse_iterator
0273         basic_ptree<K, D, C>::rbegin()
0274     {
0275         return reverse_iterator(this->end());
0276     }
0277 
0278     template<class K, class D, class C> inline
0279     typename basic_ptree<K, D, C>::const_reverse_iterator
0280         basic_ptree<K, D, C>::rbegin() const
0281     {
0282         return const_reverse_iterator(this->end());
0283     }
0284 
0285     template<class K, class D, class C> inline
0286     typename basic_ptree<K, D, C>::reverse_iterator
0287         basic_ptree<K, D, C>::rend()
0288     {
0289         return reverse_iterator(this->begin());
0290     }
0291 
0292     template<class K, class D, class C> inline
0293     typename basic_ptree<K, D, C>::const_reverse_iterator
0294         basic_ptree<K, D, C>::rend() const
0295     {
0296         return const_reverse_iterator(this->begin());
0297     }
0298 
0299     template<class K, class D, class C> inline
0300     typename basic_ptree<K, D, C>::value_type &
0301         basic_ptree<K, D, C>::front()
0302     {
0303         return const_cast<value_type&>(subs::ch(this).front());
0304     }
0305 
0306     template<class K, class D, class C> inline
0307     const typename basic_ptree<K, D, C>::value_type &
0308         basic_ptree<K, D, C>::front() const
0309     {
0310         return subs::ch(this).front();
0311     }
0312 
0313     template<class K, class D, class C> inline
0314     typename basic_ptree<K, D, C>::value_type &
0315         basic_ptree<K, D, C>::back()
0316     {
0317         return const_cast<value_type&>(subs::ch(this).back());
0318     }
0319 
0320     template<class K, class D, class C> inline
0321     const typename basic_ptree<K, D, C>::value_type &
0322         basic_ptree<K, D, C>::back() const
0323     {
0324         return subs::ch(this).back();
0325     }
0326 
0327     template<class K, class D, class C> inline
0328     typename basic_ptree<K, D, C>::iterator
0329     basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
0330     {
0331         return iterator(subs::ch(this).insert(where.base(), value).first);
0332     }
0333 
0334     template<class K, class D, class C>
0335     template<class It> inline
0336     void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
0337     {
0338         subs::ch(this).insert(where.base(), first, last);
0339     }
0340 
0341     template<class K, class D, class C> inline
0342     typename basic_ptree<K, D, C>::iterator
0343         basic_ptree<K, D, C>::erase(iterator where)
0344     {
0345         return iterator(subs::ch(this).erase(where.base()));
0346     }
0347 
0348     template<class K, class D, class C> inline
0349     typename basic_ptree<K, D, C>::iterator
0350         basic_ptree<K, D, C>::erase(iterator first, iterator last)
0351     {
0352         return iterator(subs::ch(this).erase(first.base(), last.base()));
0353     }
0354 
0355     template<class K, class D, class C> inline
0356     typename basic_ptree<K, D, C>::iterator
0357         basic_ptree<K, D, C>::push_front(const value_type &value)
0358     {
0359         return iterator(subs::ch(this).push_front(value).first);
0360     }
0361 
0362     template<class K, class D, class C> inline
0363     typename basic_ptree<K, D, C>::iterator
0364         basic_ptree<K, D, C>::push_back(const value_type &value)
0365     {
0366         return iterator(subs::ch(this).push_back(value).first);
0367     }
0368 
0369     template<class K, class D, class C> inline
0370     void basic_ptree<K, D, C>::pop_front()
0371     {
0372         subs::ch(this).pop_front();
0373     }
0374 
0375     template<class K, class D, class C> inline
0376     void basic_ptree<K, D, C>::pop_back()
0377     {
0378         subs::ch(this).pop_back();
0379     }
0380 
0381     template<class K, class D, class C> inline
0382     void basic_ptree<K, D, C>::reverse()
0383     {
0384         subs::ch(this).reverse();
0385     }
0386 
0387     namespace impl
0388     {
0389         struct by_first
0390         {
0391             template <typename P>
0392             bool operator ()(const P& lhs, const P& rhs) const {
0393               return lhs.first < rhs.first;
0394             }
0395         };
0396 
0397         template <typename C>
0398         struct equal_pred
0399         {
0400             template <typename P>
0401             bool operator ()(const P& lhs, const P& rhs) const {
0402                 C c;
0403                 return !c(lhs.first, rhs.first) &&
0404                        !c(rhs.first, lhs.first) &&
0405                        lhs.second == rhs.second;
0406             }
0407         };
0408 
0409         template <typename C, typename MI>
0410         bool equal_children(const MI& ch1, const MI& ch2) {
0411             // Assumes ch1.size() == ch2.size()
0412             return std::equal(ch1.begin(), ch1.end(),
0413                 ch2.begin(), equal_pred<C>());
0414         }
0415     }
0416 
0417     template<class K, class D, class C> inline
0418     void basic_ptree<K, D, C>::sort()
0419     {
0420         sort(impl::by_first());
0421     }
0422 
0423     template<class K, class D, class C>
0424     template<class Compare> inline
0425     void basic_ptree<K, D, C>::sort(Compare comp)
0426     {
0427         subs::ch(this).sort(comp);
0428     }
0429 
0430     // Equality
0431 
0432     template<class K, class D, class C> inline
0433     bool basic_ptree<K, D, C>::operator ==(
0434                                   const basic_ptree<K, D, C> &rhs) const
0435     {
0436         // The size test is cheap, so add it as an optimization
0437         return size() == rhs.size() && data() == rhs.data() &&
0438             impl::equal_children<C>(subs::ch(this), subs::ch(&rhs));
0439     }
0440 
0441     template<class K, class D, class C> inline
0442     bool basic_ptree<K, D, C>::operator !=(
0443                                   const basic_ptree<K, D, C> &rhs) const
0444     {
0445         return !(*this == rhs);
0446     }
0447 
0448     // Associative view
0449 
0450     template<class K, class D, class C> inline
0451     typename basic_ptree<K, D, C>::assoc_iterator
0452         basic_ptree<K, D, C>::ordered_begin()
0453     {
0454         return assoc_iterator(subs::assoc(this).begin());
0455     }
0456 
0457     template<class K, class D, class C> inline
0458     typename basic_ptree<K, D, C>::const_assoc_iterator
0459         basic_ptree<K, D, C>::ordered_begin() const
0460     {
0461         return const_assoc_iterator(subs::assoc(this).begin());
0462     }
0463 
0464     template<class K, class D, class C> inline
0465     typename basic_ptree<K, D, C>::assoc_iterator
0466         basic_ptree<K, D, C>::not_found()
0467     {
0468         return assoc_iterator(subs::assoc(this).end());
0469     }
0470 
0471     template<class K, class D, class C> inline
0472     typename basic_ptree<K, D, C>::const_assoc_iterator
0473         basic_ptree<K, D, C>::not_found() const
0474     {
0475         return const_assoc_iterator(subs::assoc(this).end());
0476     }
0477 
0478     template<class K, class D, class C> inline
0479     typename basic_ptree<K, D, C>::assoc_iterator
0480         basic_ptree<K, D, C>::find(const key_type &key)
0481     {
0482         return assoc_iterator(subs::assoc(this).find(key));
0483     }
0484 
0485     template<class K, class D, class C> inline
0486     typename basic_ptree<K, D, C>::const_assoc_iterator
0487         basic_ptree<K, D, C>::find(const key_type &key) const
0488     {
0489         return const_assoc_iterator(subs::assoc(this).find(key));
0490     }
0491 
0492     template<class K, class D, class C> inline
0493     std::pair<
0494         typename basic_ptree<K, D, C>::assoc_iterator,
0495         typename basic_ptree<K, D, C>::assoc_iterator
0496     > basic_ptree<K, D, C>::equal_range(const key_type &key)
0497     {
0498         std::pair<typename subs::by_name_index::iterator,
0499                   typename subs::by_name_index::iterator> r(
0500             subs::assoc(this).equal_range(key));
0501         return std::pair<assoc_iterator, assoc_iterator>(
0502           assoc_iterator(r.first), assoc_iterator(r.second));
0503     }
0504 
0505     template<class K, class D, class C> inline
0506     std::pair<
0507         typename basic_ptree<K, D, C>::const_assoc_iterator,
0508         typename basic_ptree<K, D, C>::const_assoc_iterator
0509     > basic_ptree<K, D, C>::equal_range(const key_type &key) const
0510     {
0511         std::pair<typename subs::by_name_index::const_iterator,
0512                   typename subs::by_name_index::const_iterator> r(
0513             subs::assoc(this).equal_range(key));
0514         return std::pair<const_assoc_iterator, const_assoc_iterator>(
0515             const_assoc_iterator(r.first), const_assoc_iterator(r.second));
0516     }
0517 
0518     template<class K, class D, class C> inline
0519     typename basic_ptree<K, D, C>::size_type
0520         basic_ptree<K, D, C>::count(const key_type &key) const
0521     {
0522         return subs::assoc(this).count(key);
0523     }
0524 
0525     template<class K, class D, class C> inline
0526     typename basic_ptree<K, D, C>::size_type
0527         basic_ptree<K, D, C>::erase(const key_type &key)
0528     {
0529         return subs::assoc(this).erase(key);
0530     }
0531 
0532     template<class K, class D, class C> inline
0533     typename basic_ptree<K, D, C>::iterator
0534         basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
0535     {
0536         return iterator(subs::ch(this).
0537             BOOST_NESTED_TEMPLATE project<0>(ai.base()));
0538     }
0539 
0540     template<class K, class D, class C> inline
0541     typename basic_ptree<K, D, C>::const_iterator
0542         basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
0543     {
0544         return const_iterator(subs::ch(this).
0545             BOOST_NESTED_TEMPLATE project<0>(ai.base()));
0546     }
0547 
0548     // Property tree view
0549 
0550     template<class K, class D, class C> inline
0551     typename basic_ptree<K, D, C>::data_type &
0552         basic_ptree<K, D, C>::data()
0553     {
0554         return m_data;
0555     }
0556 
0557     template<class K, class D, class C> inline
0558     const typename basic_ptree<K, D, C>::data_type &
0559         basic_ptree<K, D, C>::data() const
0560     {
0561         return m_data;
0562     }
0563 
0564     template<class K, class D, class C> inline
0565     void basic_ptree<K, D, C>::clear()
0566     {
0567         m_data = data_type();
0568         subs::ch(this).clear();
0569     }
0570 
0571     template<class K, class D, class C>
0572     basic_ptree<K, D, C> &
0573         basic_ptree<K, D, C>::get_child(const path_type &path)
0574     {
0575         path_type p(path);
0576         self_type *n = walk_path(p);
0577         if (!n) {
0578             BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
0579         }
0580         return *n;
0581     }
0582 
0583     template<class K, class D, class C> inline
0584     const basic_ptree<K, D, C> &
0585         basic_ptree<K, D, C>::get_child(const path_type &path) const
0586     {
0587         return const_cast<self_type*>(this)->get_child(path);
0588     }
0589 
0590     template<class K, class D, class C> inline
0591     basic_ptree<K, D, C> &
0592         basic_ptree<K, D, C>::get_child(const path_type &path,
0593                                         self_type &default_value)
0594     {
0595         path_type p(path);
0596         self_type *n = walk_path(p);
0597         return n ? *n : default_value;
0598     }
0599 
0600     template<class K, class D, class C> inline
0601     const basic_ptree<K, D, C> &
0602         basic_ptree<K, D, C>::get_child(const path_type &path,
0603                                         const self_type &default_value) const
0604     {
0605         return const_cast<self_type*>(this)->get_child(path,
0606             const_cast<self_type&>(default_value));
0607     }
0608 
0609 
0610     template<class K, class D, class C>
0611     optional<basic_ptree<K, D, C> &>
0612         basic_ptree<K, D, C>::get_child_optional(const path_type &path)
0613     {
0614         path_type p(path);
0615         self_type *n = walk_path(p);
0616         if (!n) {
0617             return optional<self_type&>();
0618         }
0619         return *n;
0620     }
0621 
0622     template<class K, class D, class C>
0623     optional<const basic_ptree<K, D, C> &>
0624         basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
0625     {
0626         path_type p(path);
0627         self_type *n = walk_path(p);
0628         if (!n) {
0629             return optional<const self_type&>();
0630         }
0631         return *n;
0632     }
0633 
0634     template<class K, class D, class C>
0635     basic_ptree<K, D, C> &
0636         basic_ptree<K, D, C>::put_child(const path_type &path,
0637                                         const self_type &value)
0638     {
0639         path_type p(path);
0640         self_type &parent = force_path(p);
0641         // Got the parent. Now get the correct child.
0642         key_type fragment = p.reduce();
0643         assoc_iterator el = parent.find(fragment);
0644         // If the new child exists, replace it.
0645         if(el != parent.not_found()) {
0646             return el->second = value;
0647         } else {
0648             return parent.push_back(value_type(fragment, value))->second;
0649         }
0650     }
0651 
0652     template<class K, class D, class C>
0653     basic_ptree<K, D, C> &
0654         basic_ptree<K, D, C>::add_child(const path_type &path,
0655                                         const self_type &value)
0656     {
0657         path_type p(path);
0658         self_type &parent = force_path(p);
0659         // Got the parent.
0660         key_type fragment = p.reduce();
0661         return parent.push_back(value_type(fragment, value))->second;
0662     }
0663 
0664     template<class K, class D, class C>
0665     template<class Type, class Translator>
0666     typename boost::enable_if<detail::is_translator<Translator>, Type>::type
0667     basic_ptree<K, D, C>::get_value(Translator tr) const
0668     {
0669         if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
0670             return *o;
0671         }
0672         BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
0673             std::string("conversion of data to type \"") +
0674             boost::core::type_name<Type>() + "\" failed", data()));
0675     }
0676 
0677     template<class K, class D, class C>
0678     template<class Type> inline
0679     Type basic_ptree<K, D, C>::get_value() const
0680     {
0681         return get_value<Type>(
0682             typename translator_between<data_type, Type>::type());
0683     }
0684 
0685     template<class K, class D, class C>
0686     template<class Type, class Translator> inline
0687     Type basic_ptree<K, D, C>::get_value(const Type &default_value,
0688                                          Translator tr) const
0689     {
0690         return get_value_optional<Type>(tr).get_value_or(default_value);
0691     }
0692 
0693     template<class K, class D, class C>
0694     template <class Ch, class Translator>
0695     typename boost::enable_if<
0696         detail::is_character<Ch>,
0697         std::basic_string<Ch>
0698     >::type
0699     basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
0700     {
0701         return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
0702     }
0703 
0704     template<class K, class D, class C>
0705     template<class Type> inline
0706     typename boost::disable_if<detail::is_translator<Type>, Type>::type
0707     basic_ptree<K, D, C>::get_value(const Type &default_value) const
0708     {
0709         return get_value(default_value,
0710                          typename translator_between<data_type, Type>::type());
0711     }
0712 
0713     template<class K, class D, class C>
0714     template <class Ch>
0715     typename boost::enable_if<
0716         detail::is_character<Ch>,
0717         std::basic_string<Ch>
0718     >::type
0719     basic_ptree<K, D, C>::get_value(const Ch *default_value) const
0720     {
0721         return get_value< std::basic_string<Ch> >(default_value);
0722     }
0723 
0724     template<class K, class D, class C>
0725     template<class Type, class Translator> inline
0726     optional<Type> basic_ptree<K, D, C>::get_value_optional(
0727                                                 Translator tr) const
0728     {
0729         return tr.get_value(data());
0730     }
0731 
0732     template<class K, class D, class C>
0733     template<class Type> inline
0734     optional<Type> basic_ptree<K, D, C>::get_value_optional() const
0735     {
0736         return get_value_optional<Type>(
0737             typename translator_between<data_type, Type>::type());
0738     }
0739 
0740     template<class K, class D, class C>
0741     template<class Type, class Translator> inline
0742     typename boost::enable_if<detail::is_translator<Translator>, Type>::type
0743     basic_ptree<K, D, C>::get(const path_type &path,
0744                               Translator tr) const
0745     {
0746         return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
0747     }
0748 
0749     template<class K, class D, class C>
0750     template<class Type> inline
0751     Type basic_ptree<K, D, C>::get(const path_type &path) const
0752     {
0753         return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
0754     }
0755 
0756     template<class K, class D, class C>
0757     template<class Type, class Translator> inline
0758     Type basic_ptree<K, D, C>::get(const path_type &path,
0759                                    const Type &default_value,
0760                                    Translator tr) const
0761     {
0762         return get_optional<Type>(path, tr).get_value_or(default_value);
0763     }
0764 
0765     template<class K, class D, class C>
0766     template <class Ch, class Translator>
0767     typename boost::enable_if<
0768         detail::is_character<Ch>,
0769         std::basic_string<Ch>
0770     >::type
0771     basic_ptree<K, D, C>::get(
0772         const path_type &path, const Ch *default_value, Translator tr) const
0773     {
0774         return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
0775     }
0776 
0777     template<class K, class D, class C>
0778     template<class Type> inline
0779     typename boost::disable_if<detail::is_translator<Type>, Type>::type
0780     basic_ptree<K, D, C>::get(const path_type &path,
0781                               const Type &default_value) const
0782     {
0783         return get_optional<Type>(path).get_value_or(default_value);
0784     }
0785 
0786     template<class K, class D, class C>
0787     template <class Ch>
0788     typename boost::enable_if<
0789         detail::is_character<Ch>,
0790         std::basic_string<Ch>
0791     >::type
0792     basic_ptree<K, D, C>::get(
0793         const path_type &path, const Ch *default_value) const
0794     {
0795         return get< std::basic_string<Ch> >(path, default_value);
0796     }
0797 
0798     template<class K, class D, class C>
0799     template<class Type, class Translator>
0800     optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
0801                                                          Translator tr) const
0802     {
0803         if (optional<const self_type&> child = get_child_optional(path))
0804             return child.get().
0805                 BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
0806         else
0807             return optional<Type>();
0808     }
0809 
0810     template<class K, class D, class C>
0811     template<class Type>
0812     optional<Type> basic_ptree<K, D, C>::get_optional(
0813                                                 const path_type &path) const
0814     {
0815         if (optional<const self_type&> child = get_child_optional(path))
0816             return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
0817         else
0818             return optional<Type>();
0819     }
0820 
0821     template<class K, class D, class C>
0822     template<class Type, class Translator>
0823     void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
0824     {
0825         if(optional<data_type> o = tr.put_value(value)) {
0826             data() = *o;
0827         } else {
0828             BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
0829                 std::string("conversion of type \"") + boost::core::type_name<Type>() +
0830                 "\" to data failed", boost::any()));
0831         }
0832     }
0833 
0834     template<class K, class D, class C>
0835     template<class Type> inline
0836     void basic_ptree<K, D, C>::put_value(const Type &value)
0837     {
0838         put_value(value, typename translator_between<data_type, Type>::type());
0839     }
0840 
0841     template<class K, class D, class C>
0842     template<class Type, typename Translator>
0843     basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
0844         const path_type &path, const Type &value, Translator tr)
0845     {
0846         if(optional<self_type &> child = get_child_optional(path)) {
0847             child.get().put_value(value, tr);
0848             return *child;
0849         } else {
0850             self_type &child2 = put_child(path, self_type());
0851             child2.put_value(value, tr);
0852             return child2;
0853         }
0854     }
0855 
0856     template<class K, class D, class C>
0857     template<class Type> inline
0858     basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
0859         const path_type &path, const Type &value)
0860     {
0861         return put(path, value,
0862                    typename translator_between<data_type, Type>::type());
0863     }
0864 
0865     template<class K, class D, class C>
0866     template<class Type, typename Translator> inline
0867     basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
0868         const path_type &path, const Type &value, Translator tr)
0869     {
0870         self_type &child = add_child(path, self_type());
0871         child.put_value(value, tr);
0872         return child;
0873     }
0874 
0875     template<class K, class D, class C>
0876     template<class Type> inline
0877     basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
0878         const path_type &path, const Type &value)
0879     {
0880         return add(path, value,
0881                    typename translator_between<data_type, Type>::type());
0882     }
0883 
0884 
0885     template<class K, class D, class C>
0886     basic_ptree<K, D, C> *
0887     basic_ptree<K, D, C>::walk_path(path_type &p) const
0888     {
0889         if(p.empty()) {
0890             // I'm the child we're looking for.
0891             return const_cast<basic_ptree*>(this);
0892         }
0893         // Recurse down the tree to find the path.
0894         key_type fragment = p.reduce();
0895         const_assoc_iterator el = find(fragment);
0896         if(el == not_found()) {
0897             // No such child.
0898             return 0;
0899         }
0900         // Not done yet, recurse.
0901         return el->second.walk_path(p);
0902     }
0903 
0904     template<class K, class D, class C>
0905     basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
0906     {
0907         BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
0908         if(p.single()) {
0909             // I'm the parent we're looking for.
0910             return *this;
0911         }
0912         key_type fragment = p.reduce();
0913         assoc_iterator el = find(fragment);
0914         // If we've found an existing child, go down that path. Else
0915         // create a new one.
0916         self_type& child = el == not_found() ?
0917             push_back(value_type(fragment, self_type()))->second : el->second;
0918         return child.force_path(p);
0919     }
0920 
0921     // Free functions
0922 
0923     template<class K, class D, class C>
0924     inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
0925     {
0926         pt1.swap(pt2);
0927     }
0928 
0929 } }
0930 
0931 #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
0932 #undef BOOST_PROPERTY_TREE_PAIR_BUG
0933 #endif
0934 
0935 #endif