Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:17

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