Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53799 - in branches/sredl_2009_05_proptree_update/boost/property_tree: . detail
From: sebastian.redl_at_[hidden]
Date: 2009-06-11 18:20:07


Author: cornedbee
Date: 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
New Revision: 53799
URL: http://svn.boost.org/trac/boost/changeset/53799

Log:
This is the fat rewrite. It compiles and the main test case passes. Peripherals (like parsers) not yet converted. This time in the correct directory.
Added:
   branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exception_implementation.hpp (contents, props changed)
   branches/sredl_2009_05_proptree_update/boost/property_tree/exceptions.hpp (contents, props changed)
   branches/sredl_2009_05_proptree_update/boost/property_tree/id_translator.hpp (contents, props changed)
   branches/sredl_2009_05_proptree_update/boost/property_tree/stream_translator.hpp (contents, props changed)
   branches/sredl_2009_05_proptree_update/boost/property_tree/string_path.hpp (contents, props changed)
Removed:
   branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exceptions_implementation.hpp
Text files modified:
   branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_implementation.hpp | 791 +++++++++++++++++++++++----------------
   branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_utils.hpp | 18
   branches/sredl_2009_05_proptree_update/boost/property_tree/ptree.hpp | 148 ++++---
   branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_fwd.hpp | 70 +-
   branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_serialization.hpp | 25
   5 files changed, 623 insertions(+), 429 deletions(-)

Added: branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exception_implementation.hpp
==============================================================================
--- (empty file)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exception_implementation.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -0,0 +1,83 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2002-2006 Marcin Kalicinski
+// Copyright (C) 2009 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+#ifndef BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
+
+namespace boost { namespace property_tree
+{
+
+ namespace detail
+ {
+
+ // Helper for preparing what string in ptree_bad_path exception
+ template<class P> inline
+ std::string prepare_bad_path_what(const std::string &what,
+ const P &path)
+ {
+ return what + " (" + path.dump() + ")";
+ }
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ptree_error
+
+ inline ptree_error::ptree_error(const std::string &what):
+ std::runtime_error(what)
+ {
+ }
+
+ inline ptree_error::~ptree_error() throw()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ptree_bad_data
+
+ template<class D> inline
+ ptree_bad_data::ptree_bad_data(const std::string &what, const D &data):
+ ptree_error(what), m_data(data)
+ {
+ }
+
+ inline ptree_bad_data::~ptree_bad_data() throw()
+ {
+ }
+
+ template<class D> inline
+ D ptree_bad_data::data()
+ {
+ return boost::any_cast<D>(m_data);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ptree_bad_path
+
+ template<class P> inline
+ ptree_bad_path::ptree_bad_path(const std::string &what, const P &path):
+ ptree_error(detail::prepare_bad_path_what(what, path)), m_path(path)
+ {
+
+ }
+
+ inline ptree_bad_path::~ptree_bad_path() throw()
+ {
+ }
+
+ template<class P> inline
+ P ptree_bad_path::path()
+ {
+ return boost::any_cast<P>(m_path);
+ }
+
+}}
+
+#endif

Deleted: branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exceptions_implementation.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/detail/exceptions_implementation.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
+++ (empty file)
@@ -1,111 +0,0 @@
-// ----------------------------------------------------------------------------
-// Copyright (C) 2002-2006 Marcin Kalicinski
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// For more information, see www.boost.org
-// ----------------------------------------------------------------------------
-#ifndef BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
-#define BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
-
-namespace boost { namespace property_tree
-{
-
- namespace detail
- {
-
- // Default path-to-string converter; this is overridden for default path
- template<class P>
- std::string path_to_string(const P &path)
- {
- return std::string("<cannot convert path to string>");
- }
-
- // Helper for preparing what string in ptree_bad_path exception
- template<class P>
- std::string prepare_bad_path_what(const std::string &what,
- const P &path)
- {
- // To allow correct resolution of path_to_string()
- using namespace detail;
- return what + " (" + path_to_string(path) + ")";
- }
-
- // Default data-to-string converter; this is overridden for default
- // data (string)
- template<class D>
- std::string data_to_string(const D &data)
- {
- return std::string("<cannot convert data to string>");
- }
-
- // Helper for preparing what string in ptree_bad_data exception
- template<class D>
- std::string prepare_bad_data_what(const std::string &what,
- const D &data)
- {
- // To allow correct resolution of data_to_string()
- using namespace detail;
- return what + " (" + data_to_string(data) + ")";
- }
-
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // ptree_error
-
- inline ptree_error::ptree_error(const std::string &what):
- std::runtime_error(what)
- {
- }
-
- inline ptree_error::~ptree_error() throw()
- {
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // ptree_bad_data
-
- template<class D>
- ptree_bad_data::ptree_bad_data(const std::string &what, const D &data):
- ptree_error(detail::prepare_bad_data_what(what, data)),
- m_data(data)
- {
- }
-
- inline ptree_bad_data::~ptree_bad_data() throw()
- {
- }
-
- template<class D>
- D ptree_bad_data::data()
- {
- return boost::any_cast<D>(m_data);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // ptree_bad_path
-
- template<class P>
- ptree_bad_path::ptree_bad_path(const std::string &what, const P &path):
- ptree_error(detail::prepare_bad_path_what(what, path)),
- m_path(path)
- {
-
- }
-
- inline ptree_bad_path::~ptree_bad_path() throw()
- {
- }
-
- template<class P>
- P ptree_bad_path::path()
- {
- return boost::any_cast<P>(m_path);
- }
-
-} }
-
-#endif

Modified: branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_implementation.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_implementation.hpp (original)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_implementation.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -11,388 +11,528 @@
 #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
 
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/reverse_iterator.hpp>
+#include <memory>
+
 namespace boost { namespace property_tree
 {
+ template <class K, class D, class C>
+ struct basic_ptree<K, D, C>::subs
+ {
+ struct by_name {};
+ // The actual child container.
+ typedef multi_index_container<value_type,
+ multi_index::indexed_by<
+ multi_index::sequenced<>,
+ multi_index::ordered_non_unique<multi_index::tag<by_name>,
+ multi_index::member<value_type, const key_type,
+ &value_type::first>,
+ key_compare
+ >
+ >
+ > base_container;
+ // The by-name lookup index.
+ typedef typename base_container::template index<by_name>::type
+ by_name_index;
+
+ // Access functions for getting to the children of a tree.
+ static base_container& ch(self_type *s) {
+ return *static_cast<base_container*>(s->m_children);
+ }
+ static const base_container& ch(const self_type *s) {
+ return *static_cast<const base_container*>(s->m_children);
+ }
+ static by_name_index& assoc(self_type *s) {
+ return ch(s).get<by_name>();
+ }
+ static const by_name_index& assoc(const self_type *s) {
+ return ch(s).get<by_name>();
+ }
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
+ iterator, typename subs::base_container::iterator, value_type>
+ {
+ friend class boost::iterator_core_access;
+ public:
+ iterator() {}
+ explicit iterator(typename iterator::base_type b)
+ : iterator::iterator_adaptor_(b)
+ {}
+ typename iterator::reference dereference() const
+ {
+ // multi_index doesn't allow modification of its values, because
+ // indexes could sort by anything, and modification screws that up.
+ // However, we only sort by the key, and it's protected against
+ // modification in the value_type, so this const_cast is safe.
+ return const_cast<typename iterator::reference>(
+ *this->base_reference());
+ }
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
+ const_iterator, typename subs::base_container::const_iterator>
+ {
+ public:
+ const_iterator() {}
+ explicit const_iterator(typename const_iterator::base_type b)
+ : const_iterator::iterator_adaptor_(b)
+ {}
+ const_iterator(iterator b)
+ : const_iterator::iterator_adaptor_(b.base())
+ {}
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::reverse_iterator
+ : public boost::reverse_iterator<iterator>
+ {
+ public:
+ reverse_iterator() {}
+ explicit reverse_iterator(iterator b)
+ : boost::reverse_iterator<iterator>(b)
+ {}
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::const_reverse_iterator
+ : public boost::reverse_iterator<const_iterator>
+ {
+ public:
+ const_reverse_iterator() {}
+ explicit const_reverse_iterator(const_iterator b)
+ : boost::reverse_iterator<const_iterator>(b)
+ {}
+ const_reverse_iterator(reverse_iterator b)
+ : boost::reverse_iterator<const_iterator>(b)
+ {}
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::assoc_iterator
+ : public boost::iterator_adaptor<assoc_iterator,
+ typename subs::by_name_index::iterator,
+ value_type>
+ {
+ friend class boost::iterator_core_access;
+ public:
+ assoc_iterator() {}
+ explicit assoc_iterator(typename assoc_iterator::base_type b)
+ : assoc_iterator::iterator_adaptor_(b)
+ {}
+ typename assoc_iterator::reference dereference() const
+ {
+ return const_cast<typename assoc_iterator::reference>(
+ *this->base_reference());
+ }
+ };
+ template <class K, class D, class C>
+ class basic_ptree<K, D, C>::const_assoc_iterator
+ : public boost::iterator_adaptor<const_assoc_iterator,
+ typename subs::by_name_index::const_iterator>
+ {
+ public:
+ const_assoc_iterator() {}
+ explicit const_assoc_iterator(
+ typename const_assoc_iterator::base_type b)
+ : const_assoc_iterator::iterator_adaptor_(b)
+ {}
+ const_assoc_iterator(assoc_iterator b)
+ : const_assoc_iterator::iterator_adaptor_(b.base())
+ {}
+ };
+
+
+ // Big five
 
- // Big four
+ // Perhaps the children collection could be created on-demand only, to
+ // reduce heap traffic. But that's a lot more work to implement.
 
- template<class K, class D, class C, class A> inline
- basic_ptree<K, D, C, A>::basic_ptree(allocator_type)
+ template<class K, class D, class C> inline
+ basic_ptree<K, D, C>::basic_ptree()
+ : m_children(new typename subs::base_container)
     {
- // FIXME: use allocator
     }
 
- template<class K, class D, class C, class A> inline
- basic_ptree<K, D, C, A>::basic_ptree(const data_type &data,
- allocator_type)
- : m_data(rhs)
+ template<class K, class D, class C> inline
+ basic_ptree<K, D, C>::basic_ptree(const data_type &data)
+ : m_data(data), m_children(new typename subs::base_container)
     {
- // FIXME: use allocator
     }
 
- template<class K, class D, class C, class A> inline
- basic_ptree<K, D, C, A>::basic_ptree(const basic_ptree<K, D, C, A> &rhs)
+ template<class K, class D, class C> inline
+ basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
+ : m_data(rhs.m_data),
+ m_children(new typename subs::base_container(subs::ch(&rhs)))
     {
- m_data = rhs.m_data;
- insert(end(), rhs.begin(), rhs.end());
     }
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::operator =(const basic_ptree<K, D, C, A> &rhs)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
     {
- if (&rhs != this)
- {
- clear();
- data() = rhs.data();
- insert(end(), rhs.begin(), rhs.end());
- }
+ self_type(rhs).swap(*this);
         return *this;
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::swap(basic_ptree<K, D, C, A> &rhs)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C>::~basic_ptree()
+ {
+ delete &subs::ch(this);
+ }
+
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
     {
         m_data.swap(rhs.m_data);
- m_children.swap(rhs.m_children);
+ // Void pointers, no ADL necessary
+ std::swap(m_children, rhs.m_children);
     }
 
     // Container view
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::size_type
- basic_ptree<K, D, C, A>::size() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::size_type
+ basic_ptree<K, D, C>::size() const
     {
- return m_children.size();
+ return subs::ch(this).size();
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::size_type
- basic_ptree<K, D, C, A>::max_size() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::size_type
+ basic_ptree<K, D, C>::max_size() const
     {
- return m_children.max_size();
+ return subs::ch(this).max_size();
     }
 
- template<class K, class D, class C, class A> inline
- bool basic_ptree<K, D, C, A>::empty() const
+ template<class K, class D, class C> inline
+ bool basic_ptree<K, D, C>::empty() const
     {
- return m_children.empty();
+ return subs::ch(this).empty();
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::begin()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::begin()
     {
- return m_children.begin();
+ return iterator(subs::ch(this).begin());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_iterator
- basic_ptree<K, D, C, A>::begin() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_iterator
+ basic_ptree<K, D, C>::begin() const
     {
- return m_children.begin();
+ return const_iterator(subs::ch(this).begin());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::end()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::end()
     {
- return m_children.end();
+ return iterator(subs::ch(this).end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_iterator
- basic_ptree<K, D, C, A>::end() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_iterator
+ basic_ptree<K, D, C>::end() const
     {
- return m_children.end();
+ return const_iterator(subs::ch(this).end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::reverse_iterator
- basic_ptree<K, D, C, A>::rbegin()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::reverse_iterator
+ basic_ptree<K, D, C>::rbegin()
     {
- return m_children.rbegin();
+ return reverse_iterator(this->end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_reverse_iterator
- basic_ptree<K, D, C, A>::rbegin() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_reverse_iterator
+ basic_ptree<K, D, C>::rbegin() const
     {
- return m_children.rbegin();
+ return const_reverse_iterator(this->end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::reverse_iterator
- basic_ptree<K, D, C, A>::rend()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::reverse_iterator
+ basic_ptree<K, D, C>::rend()
     {
- return m_children.rend();
+ return reverse_iterator(this->begin());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_reverse_iterator
- basic_ptree<K, D, C, A>::rend() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_reverse_iterator
+ basic_ptree<K, D, C>::rend() const
     {
- return m_children.rend();
+ return const_reverse_iterator(this->begin());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::value_type &
- basic_ptree<K, D, C, A>::front()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::front()
     {
- return m_children.front();
+ return const_cast<value_type&>(subs::ch(this).front());
     }
 
- template<class K, class D, class C, class A> inline
- const typename basic_ptree<K, D, C, A>::value_type &
- basic_ptree<K, D, C, A>::front() const
+ template<class K, class D, class C> inline
+ const typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::front() const
     {
- return m_children.front();
+ return subs::ch(this).front();
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::value_type &
- basic_ptree<K, D, C, A>::back()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::back()
     {
- return m_children.back();
+ return const_cast<value_type&>(subs::ch(this).back());
     }
 
- template<class K, class D, class C, class A> inline
- const typename basic_ptree<K, D, C, A>::value_type &
- basic_ptree<K, D, C, A>::back() const
+ template<class K, class D, class C> inline
+ const typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::back() const
     {
- return m_children.back();
+ return subs::ch(this).back();
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::insert(iterator where, const value_type &value)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
     {
- return m_children.insert(where, value).first;
+ return iterator(subs::ch(this).insert(where.base(), value).first);
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class It> inline
- void basic_ptree<K, D, C, A>::insert(iterator where, It first, It last)
+ void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
     {
- m_children.insert(where, first, last);
+ subs::ch(this).insert(where.base(), first, last);
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::erase(iterator where)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::erase(iterator where)
     {
- return m_children.erase(where);
+ return iterator(subs::ch(this).erase(where.base()));
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::erase(iterator first, iterator last)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::erase(iterator first, iterator last)
     {
- return m_children.erase(first, last);
+ return iterator(subs::ch(this).erase(first.base(), last.base()));
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::push_front(const value_type &value)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::push_front(const value_type &value)
     {
- return m_children.push_front(value).first;
+ return iterator(subs::ch(this).push_front(value).first);
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::push_back(const value_type &value)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::push_back(const value_type &value)
     {
- return m_children.push_back(value).first;
+ return iterator(subs::ch(this).push_back(value).first);
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::pop_front()
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::pop_front()
     {
- m_children.pop_front();
+ subs::ch(this).pop_front();
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::pop_back()
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::pop_back()
     {
- m_children.pop_back();
+ subs::ch(this).pop_back();
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::reverse()
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::reverse()
     {
- m_children.reverse();
+ subs::ch(this).reverse();
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::sort()
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::sort()
     {
- m_children.sort();
+ subs::ch(this).sort();
     }
 
- template<class K, class D, class C, class A> inline
- template<class Compare>
- void basic_ptree<K, D, C, A>::sort(Compare comp)
+ template<class K, class D, class C>
+ template<class Compare> inline
+ void basic_ptree<K, D, C>::sort(Compare comp)
     {
- m_children.sort(comp);
+ subs::ch(this).sort(comp);
     }
 
     // Equality
 
- template<class K, class D, class C, class A> inline
- bool basic_ptree<K, D, C, A>::operator ==(
- const basic_ptree<K, D, C, A> &rhs) const
+ template<class K, class D, class C> inline
+ bool basic_ptree<K, D, C>::operator ==(
+ const basic_ptree<K, D, C> &rhs) const
     {
         // The size test is cheap, so add it as an optimization
         return size() == rhs.size() && data() == rhs.data() &&
- m_children == rhs.m_children;
+ subs::ch(this) == subs::ch(&rhs);
     }
 
- template<class K, class D, class C, class A> inline
- bool basic_ptree<K, D, C, A>::operator !=(
- const basic_ptree<K, D, C, A> &rhs) const
+ template<class K, class D, class C> inline
+ bool basic_ptree<K, D, C>::operator !=(
+ const basic_ptree<K, D, C> &rhs) const
     {
         return !(*this == rhs);
     }
 
     // Associative view
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::assoc_iterator not_found()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::assoc_iterator
+ basic_ptree<K, D, C>::not_found()
     {
- return assoc().end();
+ return assoc_iterator(subs::assoc(this).end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_assoc_iterator not_found() const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_assoc_iterator
+ basic_ptree<K, D, C>::not_found() const
     {
- return assoc().end();
+ return const_assoc_iterator(subs::assoc(this).end());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::assoc_iterator
- basic_ptree<K, D, C, A>::find(const key_type &key)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::assoc_iterator
+ basic_ptree<K, D, C>::find(const key_type &key)
     {
- return assoc().find(key);
+ return assoc_iterator(subs::assoc(this).find(key));
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_assoc_iterator
- basic_ptree<K, D, C, A>::find(const key_type &key) const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_assoc_iterator
+ basic_ptree<K, D, C>::find(const key_type &key) const
     {
- return assoc().find(key);
+ return const_assoc_iterator(subs::assoc(this).find(key));
     }
 
- template<class K, class D, class C, class A> inline
+ template<class K, class D, class C> inline
     std::pair<
- typename basic_ptree<K, D, C, A>::assoc_iterator,
- typename basic_ptree<K, D, C, A>::assoc_iterator
- > basic_ptree<K, D, C, A>::equal_range(const key_type &key)
- {
- return assoc().equal_range(key);
+ typename basic_ptree<K, D, C>::assoc_iterator,
+ typename basic_ptree<K, D, C>::assoc_iterator
+ > basic_ptree<K, D, C>::equal_range(const key_type &key)
+ {
+ std::pair<typename subs::by_name_index::iterator,
+ typename subs::by_name_index::iterator> r(
+ subs::assoc(this).equal_range(key));
+ return std::pair<assoc_iterator, assoc_iterator>(r.first.base(),
+ r.second.base());
     }
 
- template<class K, class D, class C, class A> inline
+ template<class K, class D, class C> inline
     std::pair<
- typename basic_ptree<K, D, C, A>::const_assoc_iterator,
- typename basic_ptree<K, D, C, A>::const_assoc_iterator
- > basic_ptree<K, D, C, A>::equal_range(const key_type &key) const
+ typename basic_ptree<K, D, C>::const_assoc_iterator,
+ typename basic_ptree<K, D, C>::const_assoc_iterator
+ > basic_ptree<K, D, C>::equal_range(const key_type &key) const
     {
- return assoc().equal_range(key);
+ std::pair<typename subs::by_name_index::const_iterator,
+ typename subs::by_name_index::const_iterator> r(
+ subs::assoc(this).equal_range(key));
+ return std::pair<const_assoc_iterator, const_assoc_iterator>(
+ r.first.base(), r.second.base());
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::size_type
- basic_ptree<K, D, C, A>::count(const key_type &key) const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::size_type
+ basic_ptree<K, D, C>::count(const key_type &key) const
     {
- return assoc().count(key);
+ return subs::assoc(this).count(key);
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::size_type
- basic_ptree<K, D, C, A>::erase(const key_type &key)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::size_type
+ basic_ptree<K, D, C>::erase(const key_type &key)
     {
- return assoc().erase(key);
+ return subs::assoc(this).erase(key);
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::iterator
- basic_ptree<K, D, C, A>::to_iterator(assoc_iterator ai)
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
     {
- return m_children.project<0>(ai);
+ return iterator(subs::ch(this).project<0>(ai.base()));
     }
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::const_iterator
- basic_ptree<K, D, C, A>::to_iterator(const_assoc_iterator ai) const
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_iterator
+ basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
     {
- return m_children.project<0>(ai);
+ return const_iterator(subs::ch(this).project<0>(ai.base()));
     }
 
- // Property tree view
+ // Property tree view
 
- template<class K, class D, class C, class A> inline
- typename basic_ptree<K, D, C, A>::data_type &
- basic_ptree<K, D, C, A>::data()
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::data_type &
+ basic_ptree<K, D, C>::data()
     {
         return m_data;
     }
 
- template<class K, class D, class C, class A> inline
- const typename basic_ptree<K, D, C, A>::data_type &
- basic_ptree<K, D, C, A>::data() const
+ template<class K, class D, class C> inline
+ const typename basic_ptree<K, D, C>::data_type &
+ basic_ptree<K, D, C>::data() const
     {
         return m_data;
     }
 
- template<class K, class D, class C, class A> inline
- void basic_ptree<K, D, C, A>::clear()
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::clear()
     {
         m_data = data_type();
- m_children.clear();
+ subs::ch(this).clear();
     }
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::get_child(const path_type &path)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::get_child(const path_type &path)
     {
         path_type p(path);
         self_type *n = walk_path(p);
         if (!n) {
- BOOST_PROPERTY_TREE_THROW(ptree_bad_path(path));
+ BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
         }
         return *n;
     }
 
- template<class K, class D, class C, class A> inline
- const basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::get_child(const path_type &path) const
+ template<class K, class D, class C> inline
+ const basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::get_child(const path_type &path) const
     {
         return const_cast<self_type*>(this)->get_child(path);
     }
 
- template<class K, class D, class C, class A> inline
- basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::get_child(const path_type &path,
- self_type &default_value)
+ template<class K, class D, class C> inline
+ basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::get_child(const path_type &path,
+ self_type &default_value)
     {
         path_type p(path);
         self_type *n = walk_path(p);
         return n ? *n : default_value;
     }
 
- template<class K, class D, class C, class A> inline
- const basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::get_child(const path_type &path,
- const self_type &default_value) const
+ template<class K, class D, class C> inline
+ const basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::get_child(const path_type &path,
+ const self_type &default_value) const
     {
         return const_cast<self_type*>(this)->get_child(path,
- onst_cast<self_type&>(default_value));
+ const_cast<self_type&>(default_value));
     }
 
 
- template<class K, class D, class C, class A>
- optional<basic_ptree<K, D, C, A> &>
- basic_ptree<K, D, C, A>::get_child_optional(const path_type &path)
+ template<class K, class D, class C>
+ optional<basic_ptree<K, D, C> &>
+ basic_ptree<K, D, C>::get_child_optional(const path_type &path)
     {
         path_type p(path);
         self_type *n = walk_path(p);
@@ -402,9 +542,9 @@
         return *n;
     }
 
- template<class K, class D, class C, class A>
- optional<const basic_ptree<K, D, C, A> &>
- basic_ptree<K, D, C, A>::get_child_optional(const path_type &path) const
+ template<class K, class D, class C>
+ optional<const basic_ptree<K, D, C> &>
+ basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
     {
         path_type p(path);
         self_type *n = walk_path(p);
@@ -414,56 +554,42 @@
         return *n;
     }
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::put_child(const path_type &path,
- const self_type &value)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::put_child(const path_type &path,
+ const self_type &value)
     {
         path_type p(path);
         self_type &parent = force_path(p);
         // Got the parent. Now get the correct child.
- std::pair<key_type, std::size_t> fragment = p.reduce();
- std::pair<assoc_iterator, assoc_iterator> range =
- parent.equal_range(fragment.first);
- std::size_t n = fragment.second;
- // If the path specifies an index, walk the range.
- while(n > 0 && range.first != range.second) {
- --n;
- ++range.first;
- }
- // If there's still something of the index left, add default-constructed
- // elements.
- while(n > 0) {
- parent->push_back(self_type());
- }
- // We've finally reached the position for the new child. If it exists,
- // replace it.
- if(range.first != range.second) {
- return *range.first = value;
+ key_type fragment = p.reduce();
+ assoc_iterator el = parent.find(fragment);
+ // If the new child exists, replace it.
+ if(el != parent.not_found()) {
+ return el->second = value;
         } else {
- return parent->push_back(value_type(fragment.first, value));
+ return parent.push_back(value_type(fragment, value))->second;
         }
     }
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> &
- basic_ptree<K, D, C, A>::add_child(const path_type &path,
- const self_type &value)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> &
+ basic_ptree<K, D, C>::add_child(const path_type &path,
+ const self_type &value)
     {
         path_type p(path);
         self_type &parent = force_path(p);
         // Got the parent.
- std::pair<key_type, std::size_t> fragment = p.reduce();
- assert(fragment.second == 0 &&
- "Cannot specify an index for the last fragment of the path");
- return parent->push_back(value_type(fragment.first, value));
+ key_type fragment = p.reduce();
+ return parent.push_back(value_type(fragment, value))->second;
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, class Translator>
- Type basic_ptree<K, D, C, A>::get_value(Translator tr) const
+ typename boost::enable_if<detail::is_translator<Translator>, Type>::type
+ basic_ptree<K, D, C>::get_value(Translator tr) const
     {
- if(boost::optional<Type> o = get_value_optional(tr)) {
+ if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
             return *o;
         }
         BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
@@ -471,80 +597,130 @@
             typeid(Type).name() + "\" failed", data()));
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- Type basic_ptree<K, D, C, A>::get_value() const
+ Type basic_ptree<K, D, C>::get_value() const
     {
- return get_value(typename translator_between<data_type, Type>::type());
+ return get_value<Type>(
+ typename translator_between<data_type, Type>::type());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, class Translator> inline
- Type basic_ptree<K, D, C, A>::get_value(const Type &default_value,
- Translator tr) const
+ Type basic_ptree<K, D, C>::get_value(const Type &default_value,
+ Translator tr) const
     {
- return get_value_optional(tr).get_value_or(default_value);
+ return get_value_optional<Type>(tr).get_value_or(default_value);
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
+ template <class Ch, class Translator>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
+ {
+ return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
+ }
+
+ template<class K, class D, class C>
     template<class Type> inline
- Type basic_ptree<K, D, C, A>::get_value(const Type &default_value) const
+ typename boost::disable_if<detail::is_translator<Type>, Type>::type
+ basic_ptree<K, D, C>::get_value(const Type &default_value) const
     {
         return get_value(default_value,
                          typename translator_between<data_type, Type>::type());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
+ template <class Ch>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ basic_ptree<K, D, C>::get_value(const Ch *default_value) const
+ {
+ return get_value< std::basic_string<Ch> >(default_value);
+ }
+
+ template<class K, class D, class C>
     template<class Type, class Translator> inline
- optional<Type> basic_ptree<K, D, C, A>::get_value_optional(
+ optional<Type> basic_ptree<K, D, C>::get_value_optional(
                                                 Translator tr) const
     {
         return tr.get_value(data());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- optional<Type> basic_ptree<K, D, C, A>::get_value_optional() const
+ optional<Type> basic_ptree<K, D, C>::get_value_optional() const
     {
- return get_value_optional(
+ return get_value_optional<Type>(
             typename translator_between<data_type, Type>::type());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, class Translator> inline
- Type basic_ptree<K, D, C, A>::get(const path_type &path,
- Translator tr) const
+ typename boost::enable_if<detail::is_translator<Translator>, Type>::type
+ basic_ptree<K, D, C>::get(const path_type &path,
+ Translator tr) const
     {
         return get_child(path).get_value<Type>(tr);
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- Type basic_ptree<K, D, C, A>::get(const path_type &path) const
+ Type basic_ptree<K, D, C>::get(const path_type &path) const
     {
         return get_child(path).get_value<Type>();
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, class Translator> inline
- Type basic_ptree<K, D, C, A>::get(const path_type &path,
- const Type &default_value,
- Translator tr) const
+ Type basic_ptree<K, D, C>::get(const path_type &path,
+ const Type &default_value,
+ Translator tr) const
     {
         return get_optional<Type>(path, tr).get_value_or(default_value);
     }
 
- template<class K, class D, class C, class A>
- template<class Type, class Translator> inline
- Type basic_ptree<K, D, C, A>::get(const path_type &path,
- const Type &default_value) const
+ template<class K, class D, class C>
+ template <class Ch, class Translator>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ basic_ptree<K, D, C>::get(
+ const path_type &path, const Ch *default_value, Translator tr) const
+ {
+ return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ typename boost::disable_if<detail::is_translator<Type>, Type>::type
+ basic_ptree<K, D, C>::get(const path_type &path,
+ const Type &default_value) const
     {
         return get_optional<Type>(path).get_value_or(default_value);
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
+ template <class Ch>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ basic_ptree<K, D, C>::get(
+ const path_type &path, const Ch *default_value) const
+ {
+ return get< std::basic_string<Ch> >(path, default_value);
+ }
+
+ template<class K, class D, class C>
     template<class Type, class Translator>
- optional<Type> basic_ptree<K, D, C, A>::get_optional(const path_type &path,
+ optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
                                                          Translator tr) const
     {
         if (optional<const self_type&> child = get_child_optional(path))
@@ -553,9 +729,9 @@
             return optional<Type>();
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type>
- optional<Type> basic_ptree<K, D, C, A>::get_optional(
+ optional<Type> basic_ptree<K, D, C>::get_optional(
                                                 const path_type &path) const
     {
         if (optional<const self_type&> child = get_child_optional(path))
@@ -564,9 +740,9 @@
             return optional<Type>();
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, class Translator>
- void basic_ptree<K, D, C, A>::put_value(const Type &value, Translator tr)
+ void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
     {
         if(optional<data_type> o = tr.put_value(value)) {
             data() = *o;
@@ -577,16 +753,16 @@
         }
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- void basic_ptree<K, D, C, A>::put_value(const Type &value)
+ void basic_ptree<K, D, C>::put_value(const Type &value)
     {
         put_value(value, typename translator_between<data_type, Type>::type());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, typename Translator>
- basic_ptree<K, D, C, A> & basic_ptree<K, D, C, A>::put(
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
         const path_type &path, const Type &value, Translator tr)
     {
         if(optional<self_type &> child = get_child_optional(path)) {
@@ -599,28 +775,28 @@
         }
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- basic_ptree<K, D, C, A> & basic_ptree<K, D, C, A>::put(
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
         const path_type &path, const Type &value)
     {
         return put(path, value,
                    typename translator_between<data_type, Type>::type());
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type, typename Translator> inline
- basic_ptree<K, D, C, A> & basic_ptree<K, D, C, A>::add(
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
         const path_type &path, const Type &value, Translator tr)
     {
- self_type &child = put_child(path, self_type());
+ self_type &child = add_child(path, self_type());
         child.put_value(value, tr);
         return child;
     }
 
- template<class K, class D, class C, class A>
+ template<class K, class D, class C>
     template<class Type> inline
- basic_ptree<K, D, C, A> & basic_ptree<K, D, C, A>::add(
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
         const path_type &path, const Type &value)
     {
         return add(path, value,
@@ -628,65 +804,46 @@
     }
 
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> *
- basic_ptree<K, D, C, A>::walk_path(path_type &p) const
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> *
+ basic_ptree<K, D, C>::walk_path(path_type &p) const
     {
         if(p.empty()) {
             // I'm the child we're looking for.
- return this;
+ return const_cast<basic_ptree*>(this);
         }
         // Recurse down the tree to find the path.
- std::pair<key_type, std::size_t> fragment = p.reduce();
- std::pair<const_assoc_iterator, const_assoc_iterator> range =
- equal_range(fragment.first);
- std::size_t n = fragment.second;
- // If the path specifies an index, walk the range.
- while(n > 0 && range.first != range.second) {
- --n;
- ++range.first;
- }
- if(range.first == range.second) {
+ key_type fragment = p.reduce();
+ const_assoc_iterator el = find(fragment);
+ if(el == not_found()) {
             // No such child.
             return 0;
         }
         // Not done yet, recurse.
- return range.first->walk_path(p);
+ return el->second.walk_path(p);
     }
 
- template<class K, class D, class C, class A>
- basic_ptree<K, D, C, A> & basic_ptree<K, D, C, A>::force_path(path_type &p)
+ template<class K, class D, class C>
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
     {
         assert(!p.empty() && "Empty path not allowed for put_child.");
         if(p.single()) {
             // I'm the parent we're looking for.
             return *this;
         }
- std::pair<key_type, std::size_t> fragment = p.reduce();
- std::pair<const_assoc_iterator, const_assoc_iterator> range =
- equal_range(fragment.first);
- std::size_t n = fragment.second;
- // If the path specifies an index, walk the range.
- while(n > 0 && range.first != range.second) {
- --n;
- ++range.first;
- }
- // If there's still something of the index left, add default-constructed
- // elements.
- while(n > 0) {
- push_back(self_type());
- }
- // Now if we've found an existing child, go down that path. Else
+ key_type fragment = p.reduce();
+ assoc_iterator el = find(fragment);
+ // If we've found an existing child, go down that path. Else
         // create a new one.
- self_type& child = range.first == range.second ?
- push_back(self_type()) : *range.first;
+ self_type& child = el == not_found() ?
+ push_back(value_type(fragment, self_type()))->second : el->second;
         return child.force_path(p);
     }
 
     // Free functions
 
- template<class K, class D, class C, class A>
- inline void swap(basic_ptree<K, D, C, A> &pt1, basic_ptree<K, D, C, A> &pt2)
+ template<class K, class D, class C>
+ inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
     {
         pt1.swap(pt2);
     }

Modified: branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_utils.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_utils.hpp (original)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/detail/ptree_utils.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -11,6 +11,9 @@
 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_UTILS_HPP_INCLUDED
 
 #include <boost/limits.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/and.hpp>
 #include <string>
 #include <algorithm>
 #include <locale>
@@ -34,6 +37,21 @@
         }
     };
 
+ template <typename Ch>
+ struct is_character : public boost::false_type {};
+ template <>
+ struct is_character<char> : public boost::true_type {};
+ template <>
+ struct is_character<wchar_t> : public boost::true_type {};
+
+
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(internal_type)
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(external_type)
+ template <typename T>
+ struct is_translator : public boost::mpl::and_<
+ has_internal_type<T>, has_external_type<T> > {};
+
+
 
     // Naively convert narrow string to another character type
     template<class Ch>

Added: branches/sredl_2009_05_proptree_update/boost/property_tree/exceptions.hpp
==============================================================================
--- (empty file)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/exceptions.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -0,0 +1,84 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2002-2006 Marcin Kalicinski
+// Copyright (C) 2009 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+
+#ifndef BOOST_PROPERTY_TREE_EXCEPTIONS_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_EXCEPTIONS_HPP_INCLUDED
+
+#include <boost/property_tree/ptree_fwd.hpp>
+
+#include <boost/any.hpp>
+#include <string>
+#include <stdexcept>
+
+namespace boost { namespace property_tree
+{
+
+ /// Base class for all property tree errors. Derives from
+ /// @c std::runtime_error. Call member function @c what to get human
+ /// readable message associated with the error.
+ class ptree_error : public std::runtime_error
+ {
+ public:
+ /// Instantiate a ptree_error instance with the given message.
+ /// @param what The message to associate with this error.
+ ptree_error(const std::string &what);
+
+ ~ptree_error() throw();
+ };
+
+
+ /// Error indicating that translation from given value to the property tree
+ /// data_type (or vice versa) failed. Derives from ptree_error.
+ class ptree_bad_data : public ptree_error
+ {
+ public:
+ /// Instantiate a ptree_bad_data instance with the given message and
+ /// data.
+ /// @param what The message to associate with this error.
+ /// @param data The value associated with this error that was the source
+ /// of the translation failure.
+ template<class T> ptree_bad_data(const std::string &what,
+ const T &data);
+
+ ~ptree_bad_data() throw();
+
+ /// Retrieve the data associated with this error. This is the source
+ /// value that failed to be translated.
+ template<class T> T data();
+ private:
+ boost::any m_data;
+ };
+
+
+ /// Error indicating that specified path does not exist. Derives from
+ /// ptree_error.
+ class ptree_bad_path : public ptree_error
+ {
+ public:
+ /// Instantiate a ptree_bad_path with the given message and path data.
+ /// @param what The message to associate with this error.
+ /// @param path The path that could not be found in the property_tree.
+ template<class T> ptree_bad_path(const std::string &what,
+ const T &path);
+
+ ~ptree_bad_path() throw();
+
+ /// Retrieve the invalid path.
+ template<class T> T path();
+ private:
+ boost::any m_path;
+ };
+
+}}
+
+#include <boost/property_tree/detail/exception_implementation.hpp>
+
+#endif

Added: branches/sredl_2009_05_proptree_update/boost/property_tree/id_translator.hpp
==============================================================================
--- (empty file)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/id_translator.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -0,0 +1,51 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2009 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+
+#ifndef BOOST_PROPERTY_TREE_ID_TRANSLATOR_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_ID_TRANSLATOR_HPP_INCLUDED
+
+#include <boost/property_tree/ptree_fwd.hpp>
+
+#include <boost/optional.hpp>
+#include <string>
+
+namespace boost { namespace property_tree
+{
+
+ /// Simple implementation of the Translator concept. It does no translation.
+ template <typename T>
+ struct id_translator
+ {
+ typedef T internal_type;
+ typedef T external_type;
+
+ boost::optional<T> get_value(const T &v) { return v; }
+ boost::optional<T> put_value(const T &v) { return v; }
+ };
+
+ // This is the default translator whenever you get two equal types.
+ template <typename T>
+ struct translator_between<T, T>
+ {
+ typedef id_translator<T> type;
+ };
+
+ // A more specific specialization for std::basic_string. Otherwise,
+ // stream_translator's specialization wins.
+ template <typename Ch, typename Traits, typename Alloc>
+ struct translator_between< std::basic_string<Ch, Traits, Alloc>,
+ std::basic_string<Ch, Traits, Alloc> >
+ {
+ typedef id_translator< std::basic_string<Ch, Traits, Alloc> > type;
+ };
+
+}}
+
+#endif

Modified: branches/sredl_2009_05_proptree_update/boost/property_tree/ptree.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/ptree.hpp (original)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/ptree.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -9,29 +9,25 @@
 // For more information, see www.boost.org
 // ----------------------------------------------------------------------------
 
-/// This header contains definition of basic_ptree class template and
-/// supporting definitions.
-
 #ifndef BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED
 #define BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED
 
 #include <boost/property_tree/ptree_fwd.hpp>
+#include <boost/property_tree/string_path.hpp>
+#include <boost/property_tree/stream_translator.hpp>
+#include <boost/property_tree/exceptions.hpp>
 #include <boost/property_tree/detail/ptree_utils.hpp>
 
 #include <boost/multi_index_container.hpp>
+#include <boost/multi_index/indexed_by.hpp>
 #include <boost/multi_index/sequenced_index.hpp>
 #include <boost/multi_index/ordered_index.hpp>
 #include <boost/multi_index/member.hpp>
-
+#include <boost/utility/enable_if.hpp>
+#include <boost/throw_exception.hpp>
 #include <boost/optional.hpp>
-
 #include <utility> // for std::pair
 
-#if !defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED)
- // Throwing macro to avoid no return warnings portably
-# define BOOST_PROPERTY_TREE_THROW(e) { throw_exception(e); std::exit(1); }
-#endif
-
 namespace boost { namespace property_tree
 {
 
@@ -44,13 +40,11 @@
      * Key equivalency is defined by @p KeyCompare, a predicate defining a
      * strict weak ordering.
      *
- * All data structures are allocated with some version of @p Allocator.
- *
      * Property tree defines a Container-like interface to the (key-node) pairs
      * of its direct sub-nodes. The iterators are bidirectional. The sequence
      * of nodes is held in insertion order, not key order.
      */
- template<class Key, class Data, class KeyCompare, class Allocator>
+ template<class Key, class Data, class KeyCompare>
     class basic_ptree
     {
 #if defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED)
@@ -61,60 +55,41 @@
          * Simpler way to refer to this basic_ptree\<C,K,P,A\> type.
          * Note that this is private, and made public only for doxygen.
          */
- typedef basic_ptree<Key, Data, KeyCompare, Allocator> self_type;
+ typedef basic_ptree<Key, Data, KeyCompare> self_type;
 
     public:
         // Basic types
         typedef Key key_type;
         typedef Data data_type;
         typedef KeyCompare key_compare;
- typedef Allocator allocator_type;
 
         // Container view types
- typedef std::pair<Key, self_type> value_type;
- typedef typename Allocator::size_type size_type;
-
- private:
- struct by_name {};
- // The actual child container.
- typedef multi_index_container<value_type,
- indexed_by<
- multi_index::sequenced<>,
- multi_index::ordered_non_unique<multi_index::tag<by_name>,
- multi_index::member<value_type, key_type,
- &value_type::first>,
- key_compare
- >
- >
- > base_container;
- // The by-name lookup index.
- typedef typename base_container::template index<by_name>::type
- by_name_index;
+ typedef std::pair<const Key, self_type> value_type;
+ typedef std::size_t size_type;
 
- public:
- // More container view types
- typedef typename base_container::iterator iterator;
- typedef typename base_container::const_iterator const_iterator;
- typedef typename base_container::reverse_iterator reverse_iterator;
- typedef typename base_container::const_reverse_iterator
- const_reverse_iterator;
+ // The problem with the iterators is that I can't make them complete
+ // until the container is complete. Sucks. Especially for the reverses.
+ class iterator;
+ class const_iterator;
+ class reverse_iterator;
+ class const_reverse_iterator;
 
         // Associative view types
- typedef typename by_name_index::iterator assoc_iterator;
- typedef typename by_name_index::const_iterator const_assoc_iterator;
+ class assoc_iterator;
+ class const_assoc_iterator;
 
         // Property tree view types
         typedef typename path_of<Key>::type path_type;
 
 
- // The big four
+ // The big five
 
         /** Creates a node with no children and default-constructed data. */
- explicit basic_ptree(allocator_type alloc = allocator_type());
+ basic_ptree();
         /** Creates a node with no children and a copy of the given data. */
- explicit basic_ptree(const data_type &data,
- allocator_type alloc = allocator_type());
+ explicit basic_ptree(const data_type &data);
         basic_ptree(const self_type &rhs);
+ ~basic_ptree();
         /** Basic guarantee only. */
         self_type &operator =(const self_type &rhs);
 
@@ -238,8 +213,9 @@
         /** Count the number of direct children with the given key. */
         size_type count(const key_type &key) const;
 
- /** Erase all direct children with the given key. */
- void erase(const key_type &key);
+ /** Erase all direct children with the given key and return the count.
+ */
+ size_type erase(const key_type &key);
 
         /** Get the iterator that points to the same element as the argument.
          * @note A valid assoc_iterator range (a, b) does not imply that
@@ -251,7 +227,7 @@
          * @note A valid const_assoc_iterator range (a, b) does not imply that
          * (to_iterator(a), to_iterator(b)) is a valid range.
          */
- const_iterator to_iterator(const_assoc_iterator it);
+ const_iterator to_iterator(const_assoc_iterator it) const;
 
         // Property tree view
 
@@ -321,8 +297,8 @@
          * @throw ptree_bad_data if the conversion fails.
          */
         template<class Type, class Translator>
- Type get_value(Translator tr =
- typename translator_between<data_type, Type>::type()) const;
+ typename boost::enable_if<detail::is_translator<Translator>, Type>::type
+ get_value(Translator tr) const;
 
         /** Take the value of this node and attempt to translate it to a
          * @c Type object using the default translator.
@@ -338,12 +314,29 @@
         template<class Type, class Translator>
         Type get_value(const Type &default_value, Translator tr) const;
 
+ /** Make get_value do the right thing for string literals. */
+ template <class Ch, class Translator>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ get_value(const Ch *default_value, Translator tr) const;
+
         /** Take the value of this node and attempt to translate it to a
          * @c Type object using the default translator. Return @p default_value
          * if this fails.
          */
         template<class Type>
- Type get_value(const Type &default_value) const;
+ typename boost::disable_if<detail::is_translator<Type>, Type>::type
+ get_value(const Type &default_value) const;
+
+ /** Make get_value do the right thing for string literals. */
+ template <class Ch>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ get_value(const Ch *default_value) const;
 
         /** Take the value of this node and attempt to translate it to a
          * @c Type object using the supplied translator. Return boost::null if
@@ -375,7 +368,8 @@
 
         /** Shorthand for get_child(path).get_value(tr). */
         template<class Type, class Translator>
- Type get(const path_type &path, Translator tr) const;
+ typename boost::enable_if<detail::is_translator<Translator>, Type>::type
+ get(const path_type &path, Translator tr) const;
 
         /** Shorthand for get_child(path).get_value\<Type\>(). */
         template<class Type>
@@ -391,13 +385,30 @@
                  const Type &default_value,
                  Translator tr) const;
 
+ /** Make get do the right thing for string literals. */
+ template <class Ch, class Translator>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ get(const path_type &path, const Ch *default_value, Translator tr)const;
+
         /** Shorthand for get_child(path, empty_ptree())
          * .get_value(default_value).
          * That is, return the translated value if possible, and the default
          * value if the node doesn't exist or conversion fails.
          */
         template<class Type>
- Type get(const path_type &path, const Type &default_value) const;
+ typename boost::disable_if<detail::is_translator<Type>, Type>::type
+ get(const path_type &path, const Type &default_value) const;
+
+ /** Make get do the right thing for string literals. */
+ template <class Ch>
+ typename boost::enable_if<
+ detail::is_character<Ch>,
+ std::basic_string<Ch>
+ >::type
+ get(const path_type &path, const Ch *default_value) const;
 
         /** Shorthand for:
          * @code
@@ -405,9 +416,10 @@
          * return node->get_value_optional(tr);
          * return boost::null;
          * @endcode
+ * That is, return the value if it exists and can be converted, or nil.
         */
         template<class Type, class Translator>
- Type get_optional(const path_type &path, Translator tr) const;
+ optional<Type> get_optional(const path_type &path, Translator tr) const;
 
         /** Shorthand for:
          * @code
@@ -417,7 +429,7 @@
          * @endcode
         */
         template<class Type>
- Type get_optional(const path_type &path) const;
+ optional<Type> get_optional(const path_type &path) const;
 
         /** Set the value of the node at the given path to the supplied value,
          * translated to the tree's data type. If the node doesn't exist, it is
@@ -471,14 +483,9 @@
     private:
         // Hold the data of this node
         data_type m_data;
- // Hold the children
- base_container m_children;
-
- // Convenience
- by_name_index& assoc() { return m_children.get<by_name>(); }
- const by_name_index& assoc() const {
- return m_children.get<by_name>();
- }
+ // Hold the children - this is a void* because we can't complete the
+ // container type within the class.
+ void* m_children;
 
         // Getter tree-walk. Not const-safe! Gets the node the path refers to,
         // or null. Destroys p's value.
@@ -488,11 +495,18 @@
         // path, creating nodes as necessary. p is the path to the remaining
         // child.
         self_type& force_path(path_type& p);
+
+ // This struct contains typedefs for the concrete types.
+ struct subs;
+ friend struct subs;
+ friend class iterator;
+ friend class const_iterator;
+ friend class reverse_iterator;
+ friend class const_reverse_iterator;
     };
 
-} }
+}}
 
-// Include implementations
 #include <boost/property_tree/detail/ptree_implementation.hpp>
 
 #endif

Modified: branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_fwd.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_fwd.hpp (original)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_fwd.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -12,8 +12,10 @@
 #define BOOST_PROPERTY_TREE_PTREE_FWD_HPP_INCLUDED
 
 #include <boost/config.hpp>
+#include <boost/optional/optional_fwd.hpp>
 #include <functional> // for std::less
 #include <memory> // for std::allocator
+#include <string>
 
 namespace boost { namespace property_tree
 {
@@ -21,14 +23,12 @@
         template <typename T> struct less_nocase;
     }
 
- ///////////////////////////////////////////////////////////////////////////
     // Classes
 
- template <class Key, class Data,
- class KeyCompare = std::less<Key>,
- class Allocator = std::allocator<Data>>
+ template < class Key, class Data, class KeyCompare = std::less<Key> >
     class basic_ptree;
 
+ template <typename T>
     struct id_translator;
 
     template <typename String, typename Translator>
@@ -36,23 +36,33 @@
 
     // We'll want to do this with concepts in C++0x.
 #if 0
- concept PropertyTreePath<Path> {
- // The key type for which this path works.
- typedef key_type;
- // Return the key and index that the first segment of the path name.
- // Split the head off the state.
- std::pair<key_type, std::size_t> Path::reduce();
+ concept PropertyTreePath<class Path> {
+ // The key type for which this path works.
+ typename key_type;
+ // Return the key that the first segment of the path names.
+ // Split the head off the state.
+ key_type Path::reduce();
 
- // Return true if the path is empty.
- bool Path::empty();
+ // Return true if the path is empty.
+ bool Path::empty() const;
 
- // Return true if the path contains a single element.
- bool Path::single();
+ // Return true if the path contains a single element.
+ bool Path::single() const;
+
+ // Dump as a std::string, for exception messages.
+ std::string Path::dump() const;
     }
- concept PropertyTreeKey<Key> {
+ concept PropertyTreeKey<class Key> {
         PropertyTreePath path;
         requires SameType<Key, PropertyTreePath<path>::key_type>;
     }
+ concept PropertyTreeTranslator<class Tr> {
+ typename internal_type;
+ typename external_type;
+
+ boost::optional<external_type> Tr::get_value(internal_type);
+ boost::optional<internal_type> Tr::put_value(external_type);
+ }
 #endif
     /// If you want to use a custom key type, specialize this struct for it
     /// and give it a 'type' typedef that specifies your path type. The path
@@ -62,24 +72,23 @@
     struct path_of;
 
     /// Specialize this struct to specify a default translator between the data
- /// in a tree whose data_type is TreeData, and the external data_type
+ /// in a tree whose data_type is Internal, and the external data_type
     /// specified in a get_value, get, put_value or put operation.
- /// This is already specialized for TreeData being std::basic_string.
- template <typename TreeData, typename External>
+ /// This is already specialized for Internal being std::basic_string.
+ template <typename Internal, typename External>
     struct translator_between;
 
     class ptree_error;
     class ptree_bad_data;
     class ptree_bad_path;
 
- ///////////////////////////////////////////////////////////////////////////
     // Typedefs
 
     /** Implements a path using a std::string as the key. */
- typedef string_path<std::string, id_translator> path;
+ typedef string_path<std::string, id_translator<std::string> > path;
 
     /** Implements a path using a std::wstring as the key. */
- typedef string_path<std::wstring, id_translator> wpath;
+ typedef string_path<std::wstring, id_translator<std::wstring> > wpath;
 
     /**
      * A property tree with std::string for key and data, and default
@@ -113,22 +122,21 @@
         wiptree;
 #endif
 
- ///////////////////////////////////////////////////////////////////////////
     // Free functions
 
     /**
      * Swap two property tree instances.
      */
- template<class K, class D, class C, class A>
- void swap(basic_ptree<K, D, C, A> &pt1,
- basic_ptree<K, D, C, A> &pt2);
-
- /** Join two string_path objects. */
- template <typename String, typename Translator>
- string_path<String, Translator> operator /(
- const string_path<String, Translator> &p1,
- const string_path<String, Translator> &p2);
+ template<class K, class D, class C>
+ void swap(basic_ptree<K, D, C> &pt1,
+ basic_ptree<K, D, C> &pt2);
 
 } }
 
+
+#if !defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED)
+ // Throwing macro to avoid no return warnings portably
+# define BOOST_PROPERTY_TREE_THROW(e) { throw_exception(e); std::exit(1); }
+#endif
+
 #endif

Modified: branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_serialization.hpp
==============================================================================
--- branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_serialization.hpp (original)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/ptree_serialization.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -38,14 +38,13 @@
      * @param file_version file_version for the archive.
      * @post @c ar will contain the serialized form of @c t.
      */
- template<class Archive, class D, class K,
- class C, class A, class P, class X>
+ template<class Archive, class K, class D, class C>
     inline void save(Archive &ar,
- const basic_ptree<D, K, C, A, P, X> &t,
+ const basic_ptree<K, D, C> &t,
                      const unsigned int file_version)
     {
         using namespace boost::serialization;
- stl::save_collection<Archive, basic_ptree<D, K, C, A, P, X> >(ar, t);
+ stl::save_collection<Archive, basic_ptree<K, D, C> >(ar, t);
         ar << make_nvp("data", t.data());
     }
 
@@ -62,24 +61,23 @@
      * @param file_version file_version for the archive.
      * @post @c t will contain the de-serialized data from @c ar.
      */
- template<class Archive, class D, class K,
- class C, class A, class P, class X>
+ template<class Archive, class K, class D, class C>
     inline void load(Archive &ar,
- basic_ptree<D, K, C, A, P, X> &t,
+ basic_ptree<K, D, C> &t,
                      const unsigned int file_version)
     {
         using namespace boost::serialization;
         // Load children
         stl::load_collection<Archive,
- basic_ptree<D, K, C, A, P, X>,
+ basic_ptree<K, D, C>,
                              stl::archive_input_seq<Archive,
- basic_ptree<D, K, C, A, P, X> >,
+ basic_ptree<K, D, C> >,
                              stl::no_reserve_imp<
- basic_ptree<D, K, C, A, P, X> >
+ basic_ptree<K, D, C> >
>(ar, t);
 
         // Load data (must be after load_collection, as it calls clear())
- ar >> serialization::make_nvp("data", t.data());
+ ar >> make_nvp("data", t.data());
     }
 
     /**
@@ -90,10 +88,9 @@
      * @param t The property tree to load or save.
      * @param file_version file_version for the archive.
      */
- template<class Archive, class D, class K,
- class C, class A, class P, class X>
+ template<class Archive, class K, class D, class C>
     inline void serialize(Archive &ar,
- basic_ptree<D, K, C, A, P, X> &t,
+ basic_ptree<K, D, C> &t,
                           const unsigned int file_version)
     {
         using namespace boost::serialization;

Added: branches/sredl_2009_05_proptree_update/boost/property_tree/stream_translator.hpp
==============================================================================
--- (empty file)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/stream_translator.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -0,0 +1,188 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2009 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+
+#ifndef BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
+
+#include <boost/property_tree/ptree_fwd.hpp>
+
+#include <boost/optional.hpp>
+#include <boost/optional/optional_io.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <sstream>
+#include <string>
+#include <locale>
+#include <limits>
+
+namespace boost { namespace property_tree
+{
+
+ template <typename Ch, typename Traits, typename E, typename Enabler = void>
+ struct customize_stream
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, const E& e) {
+ s << e;
+ }
+ static void extract(std::basic_istream<Ch, Traits>& s, E& e) {
+ s >> e;
+ if(!s.eof()) {
+ s >> std::ws;
+ }
+ }
+ };
+
+ // No whitespace skipping for single characters.
+ template <typename Ch, typename Traits>
+ struct customize_stream<Ch, Traits, Ch, void>
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, Ch e) {
+ s << e;
+ }
+ static void extract(std::basic_istream<Ch, Traits>& s, Ch& e) {
+ s.unsetf(std::ios_base::skipws);
+ s >> e;
+ }
+ };
+
+ template <typename Ch, typename Traits, typename F>
+ struct customize_stream<Ch, Traits, F,
+ typename boost::enable_if_c<
+ std::numeric_limits<typename boost::decay<F>::type>::is_specialized
+ && !std::numeric_limits<typename boost::decay<F>::type>::is_exact
+ >::type
+ >
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, const F& e) {
+ s.precision(std::numeric_limits<F>::digits10 + 1);
+ s << e;
+ }
+ static void extract(std::basic_istream<Ch, Traits>& s, F& e) {
+ s >> e;
+ if(!s.eof()) {
+ s >> std::ws;
+ }
+ }
+ };
+
+ template <typename Ch, typename Traits>
+ struct customize_stream<Ch, Traits, bool, void>
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, bool e) {
+ s.setf(std::ios_base::boolalpha);
+ s << e;
+ }
+ static void extract(std::basic_istream<Ch, Traits>& s, bool& e) {
+ s >> e;
+ if(s.fail()) {
+ // Try again in word form.
+ s.clear();
+ s.setf(std::ios_base::boolalpha);
+ s >> e;
+ }
+ if(!s.eof()) {
+ s >> std::ws;
+ }
+ }
+ };
+
+ template <typename Ch, typename Traits>
+ struct customize_stream<Ch, Traits, signed char, void>
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, signed char e) {
+ s << (int)e;
+ }
+ static void extract(std::basic_istream<Ch, Traits>& s, signed char& e) {
+ int i;
+ s >> i;
+ // out of range?
+ if(i > std::numeric_limits<signed char>::max() ||
+ i < std::numeric_limits<signed char>::min())
+ {
+ s.clear(); // guarantees eof to be unset
+ return;
+ }
+ e = (signed char)i;
+ if(!s.eof()) {
+ s >> std::ws;
+ }
+ }
+ };
+
+ template <typename Ch, typename Traits>
+ struct customize_stream<Ch, Traits, unsigned char, void>
+ {
+ static void insert(std::basic_ostream<Ch, Traits>& s, unsigned char e) {
+ s << (unsigned)e;
+ }
+ static void extract(std::basic_istream<Ch,Traits>& s, unsigned char& e){
+ unsigned i;
+ s >> i;
+ // out of range?
+ if(i > std::numeric_limits<unsigned char>::max()) {
+ s.clear(); // guarantees eof to be unset
+ return;
+ }
+ e = (unsigned char)i;
+ if(!s.eof()) {
+ s >> std::ws;
+ }
+ }
+ };
+
+ /// Implementation of Translator that uses the stream overloads.
+ template <typename Ch, typename Traits, typename Alloc, typename E>
+ class stream_translator
+ {
+ typedef customize_stream<Ch, Traits, E> customized;
+ public:
+ typedef std::basic_string<Ch, Traits, Alloc> internal_type;
+ typedef E external_type;
+
+ explicit stream_translator(std::locale loc = std::locale())
+ : m_loc(loc)
+ {}
+
+ boost::optional<E> get_value(const internal_type &v) {
+ std::basic_istringstream<Ch, Traits, Alloc> iss(v);
+ iss.imbue(m_loc);
+ E e;
+ customized::extract(iss, e);
+ if(iss.fail() || iss.bad() || iss.get() != Traits::eof()) {
+ return boost::optional<E>();
+ }
+ return e;
+ }
+ boost::optional<internal_type> put_value(const E &v) {
+ std::basic_ostringstream<Ch, Traits, Alloc> oss;
+ oss.imbue(m_loc);
+ customized::insert(oss, v);
+ if(oss) {
+ return oss.str();
+ }
+ return boost::optional<internal_type>();
+ }
+
+ private:
+ std::locale m_loc;
+ };
+
+ // This is the default translator when basic_string is the internal type.
+ // Unless the external type is also basic_string, in which case
+ // id_translator takes over.
+ template <typename Ch, typename Traits, typename Alloc, typename E>
+ struct translator_between<std::basic_string<Ch, Traits, Alloc>, E>
+ {
+ typedef stream_translator<Ch, Traits, Alloc, E> type;
+ };
+
+}}
+
+#endif

Added: branches/sredl_2009_05_proptree_update/boost/property_tree/string_path.hpp
==============================================================================
--- (empty file)
+++ branches/sredl_2009_05_proptree_update/boost/property_tree/string_path.hpp 2009-06-11 18:20:05 EDT (Thu, 11 Jun 2009)
@@ -0,0 +1,270 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2009 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+
+#ifndef BOOST_PROPERTY_TREE_STRING_PATH_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_STRING_PATH_HPP_INCLUDED
+
+#include <boost/property_tree/ptree_fwd.hpp>
+#include <boost/property_tree/id_translator.hpp>
+#include <boost/property_tree/exceptions.hpp>
+#include <boost/property_tree/detail/ptree_utils.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/optional.hpp>
+#include <boost/throw_exception.hpp>
+#include <algorithm>
+#include <string>
+#include <iterator>
+
+namespace boost { namespace property_tree
+{
+ namespace detail
+ {
+ template <typename Sequence, typename Iterator>
+ void append_and_preserve_iter(Sequence &s, const Sequence &r,
+ Iterator &, std::forward_iterator_tag)
+ {
+ // Here we boldly assume that anything that is not random-access
+ // preserves validity. This is valid for the STL sequences.
+ s.insert(s.end(), r.begin(), r.end());
+ }
+ template <typename Sequence, typename Iterator>
+ void append_and_preserve_iter(Sequence &s, const Sequence &r,
+ Iterator &it,
+ std::random_access_iterator_tag)
+ {
+ // Convert the iterator to an index, and later back.
+ typename std::iterator_traits<Iterator>::difference_type idx =
+ it - s.begin();
+ s.insert(s.end(), r.begin(), r.end());
+ it = s.begin() + idx;
+ }
+
+ template <typename Sequence>
+ std::string dump_sequence(const Sequence &)
+ {
+ return "<undumpable sequence>";
+ }
+ std::string dump_sequence(const std::string &s)
+ {
+ return s;
+ }
+ std::string dump_sequence(const std::wstring &s)
+ {
+ return narrow(s.c_str());
+ }
+ }
+
+ /// Default path class. A path is a sequence of values. Groups of values
+ /// are separated by the separator value, which defaults to '.' cast to
+ /// the sequence's value type. The group of values is then passed to the
+ /// translator to get a key.
+ ///
+ /// If instantiated with std::string and id_translator\<std::string\>,
+ /// it accepts paths of the form "one.two.three.four".
+ ///
+ /// @tparam String Any Sequence. If the sequence does not support random-
+ /// access iteration, concatenation of paths assumes that
+ /// insertions at the end preserve iterator validity.
+ /// @tparam Translator A translator with internal_type == String.
+ template <typename String, typename Translator>
+ class string_path
+ {
+ BOOST_STATIC_ASSERT((is_same<String,
+ typename Translator::internal_type>::value));
+ public:
+ typedef typename Translator::external_type key_type;
+ typedef typename String::value_type char_type;
+
+ /// Create an empty path.
+ string_path();
+ /// Create a path by parsing the given string.
+ /// @param value A sequence, possibly with separators, that describes
+ /// the path, e.g. "one.two.three".
+ /// @param separator The separator used in parsing. Defaults to '.'.
+ /// @param tr The translator used by this path to convert the individual
+ /// parts to keys.
+ string_path(const String &value, char_type separator = char_type('.'),
+ Translator tr = Translator());
+ /// Create a path by parsing the given string.
+ /// @param value A zero-terminated array of values. Only use if zero-
+ /// termination makes sense for your type, and your
+ /// sequence supports construction from it. Intended for
+ /// string literals.
+ /// @param separator The separator used in parsing. Defaults to '.'.
+ /// @param tr The translator used by this path to convert the individual
+ /// parts to keys.
+ string_path(const char_type *value,
+ char_type separator = char_type('.'),
+ Translator tr = Translator());
+
+ // Default copying doesn't do the right thing with the iterator
+ string_path(const string_path &o);
+ string_path& operator =(const string_path &o);
+
+ /// Take a single element off the path at the front and return it.
+ key_type reduce();
+
+ /// Test if the path is empty.
+ bool empty() const;
+
+ /// Test if the path contains a single element, i.e. no separators.
+ bool single() const;
+
+ std::string dump() const {
+ return detail::dump_sequence(m_value);
+ }
+
+ /// Append a second path to this one.
+ /// @pre o's separator is the same as this one's, or o has no separators
+ string_path& operator /=(const string_path &o) {
+ // If it's single, there's no separator. This allows to do
+ // p /= "piece";
+ // even for non-default separators.
+ assert((m_separator == o.m_separator || o.empty() || o.single())
+ && "Incompatible paths.");
+ if(!o.empty()) {
+ String sub;
+ if(!this->empty()) {
+ sub.push_back(m_separator);
+ }
+ sub.insert(sub.end(), o.cstart(), o.m_value.end());
+ detail::append_and_preserve_iter(m_value, sub, m_start,
+ typename std::iterator_traits<s_iter>::iterator_category());
+ }
+ return *this;
+ }
+
+ private:
+ typedef typename String::iterator s_iter;
+ typedef typename String::const_iterator s_c_iter;
+ String m_value;
+ char_type m_separator;
+ Translator m_tr;
+ s_iter m_start;
+ s_c_iter cstart() const { return m_start; }
+ };
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator>::string_path()
+ : m_start(m_value.begin())
+ {}
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator>::string_path(const String &value,
+ char_type separator,
+ Translator tr)
+ : m_value(value), m_separator(separator),
+ m_tr(tr), m_start(m_value.begin())
+ {}
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator>::string_path(const char_type *value,
+ char_type separator,
+ Translator tr)
+ : m_value(value), m_separator(separator),
+ m_tr(tr), m_start(m_value.begin())
+ {}
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator>::string_path(const string_path &o)
+ : m_value(o.m_value), m_separator(o.m_separator),
+ m_tr(o.m_tr), m_start(m_value.begin())
+ {
+ std::advance(m_start, std::distance(o.m_value.begin(), o.cstart()));
+ }
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator>&
+ string_path<String, Translator>::operator =(const string_path &o)
+ {
+ m_value = o.m_value;
+ m_separator = o.m_separator;
+ m_tr = o.m_tr;
+ m_start = m_value.begin();
+ std::advance(m_start, std::distance(o.m_value.begin(), o.cstart()));
+ return *this;
+ }
+
+ template <typename String, typename Translator>
+ typename Translator::external_type string_path<String, Translator>::reduce()
+ {
+ assert(!empty() && "Reducing empty path");
+
+ s_iter next_sep = std::find(m_start, m_value.end(), m_separator);
+ String part(m_start, next_sep);
+ m_start = next_sep;
+ if(!empty()) {
+ // Unless we're at the end, skip the separator we found.
+ ++m_start;
+ }
+
+ if(optional<key_type> key = m_tr.get_value(part)) {
+ return *key;
+ }
+ BOOST_PROPERTY_TREE_THROW(ptree_bad_path("Path syntax error", *this));
+ }
+
+ template <typename String, typename Translator> inline
+ bool string_path<String, Translator>::empty() const
+ {
+ return m_start == m_value.end();
+ }
+
+ template <typename String, typename Translator> inline
+ bool string_path<String, Translator>::single() const
+ {
+ return std::find(static_cast<s_c_iter>(m_start),
+ m_value.end(), m_separator)
+ == m_value.end();
+ }
+
+ // By default, this is the path for strings. You can override this by
+ // specializing path_of for a more specific form of std::basic_string.
+ template <typename Ch, typename Traits, typename Alloc>
+ struct path_of< std::basic_string<Ch, Traits, Alloc> >
+ {
+ typedef std::basic_string<Ch, Traits, Alloc> _string;
+ typedef string_path< _string, id_translator<_string> > type;
+ };
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator> operator /(
+ string_path<String, Translator> p1,
+ const string_path<String, Translator> &p2)
+ {
+ p1 /= p2;
+ return p1;
+ }
+
+ // These shouldn't be necessary, but GCC won't find the one above.
+ template <typename String, typename Translator> inline
+ string_path<String, Translator> operator /(
+ string_path<String, Translator> p1,
+ const typename String::value_type *p2)
+ {
+ p1 /= p2;
+ return p1;
+ }
+
+ template <typename String, typename Translator> inline
+ string_path<String, Translator> operator /(
+ const typename String::value_type *p1,
+ const string_path<String, Translator> &p2)
+ {
+ string_path<String, Translator> t(p1);
+ t /= p2;
+ return t;
+ }
+
+}}
+
+#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk