summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-03-11 20:22:35 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-03-11 22:22:04 (GMT)
commit59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89 (patch)
treee450b95ff4c0ba7f770723402a2634773f1a0451 /3rdParty/Boost/src/boost/property_tree
parent3ff52013d810f94b6095e93f550f58133e2df239 (diff)
downloadswift-contrib-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.zip
swift-contrib-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.tar.bz2
Store JID->Avatar mappings.
Resolves: #653
Diffstat (limited to '3rdParty/Boost/src/boost/property_tree')
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/exception_implementation.hpp83
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/file_parser_error.hpp88
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/ptree_implementation.hpp905
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/ptree_utils.hpp106
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/rapidxml.hpp2582
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_error.hpp33
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_flags.hpp31
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_read_rapidxml.hpp144
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_utils.hpp136
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_write.hpp194
-rw-r--r--3rdParty/Boost/src/boost/property_tree/detail/xml_parser_writer_settings.hpp62
-rw-r--r--3rdParty/Boost/src/boost/property_tree/exceptions.hpp84
-rw-r--r--3rdParty/Boost/src/boost/property_tree/id_translator.hpp51
-rw-r--r--3rdParty/Boost/src/boost/property_tree/ptree.hpp517
-rw-r--r--3rdParty/Boost/src/boost/property_tree/ptree_fwd.hpp143
-rw-r--r--3rdParty/Boost/src/boost/property_tree/stream_translator.hpp221
-rw-r--r--3rdParty/Boost/src/boost/property_tree/string_path.hpp273
-rw-r--r--3rdParty/Boost/src/boost/property_tree/xml_parser.hpp153
18 files changed, 5806 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/exception_implementation.hpp b/3rdParty/Boost/src/boost/property_tree/detail/exception_implementation.hpp
new file mode 100644
index 0000000..551e10c
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/exception_implementation.hpp
@@ -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 &w):
+ std::runtime_error(w)
+ {
+ }
+
+ inline ptree_error::~ptree_error() throw()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ptree_bad_data
+
+ template<class D> inline
+ ptree_bad_data::ptree_bad_data(const std::string &w, const D &d):
+ ptree_error(w), m_data(d)
+ {
+ }
+
+ 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 &w, const P &p):
+ ptree_error(detail::prepare_bad_path_what(w, p)), m_path(p)
+ {
+
+ }
+
+ 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
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/file_parser_error.hpp b/3rdParty/Boost/src/boost/property_tree/detail/file_parser_error.hpp
new file mode 100644
index 0000000..ff90583
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/file_parser_error.hpp
@@ -0,0 +1,88 @@
+// ----------------------------------------------------------------------------
+// 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_FILE_PARSER_ERROR_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_FILE_PARSER_ERROR_HPP_INCLUDED
+
+#include <boost/property_tree/ptree.hpp>
+#include <string>
+
+namespace boost { namespace property_tree
+{
+
+ //! File parse error
+ class file_parser_error: public ptree_error
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ // Construct error
+ file_parser_error(const std::string &msg,
+ const std::string &file,
+ unsigned long l) :
+ ptree_error(format_what(msg, file, l)),
+ m_message(msg), m_filename(file), m_line(l)
+ {
+ }
+
+ ~file_parser_error() throw()
+ // gcc 3.4.2 complains about lack of throw specifier on compiler
+ // generated dtor
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Data access
+
+ // Get error message (without line and file - use what() to get
+ // full message)
+ std::string message() const
+ {
+ return m_message;
+ }
+
+ // Get error filename
+ std::string filename() const
+ {
+ return m_filename;
+ }
+
+ // Get error line number
+ unsigned long line() const
+ {
+ return m_line;
+ }
+
+ private:
+
+ std::string m_message;
+ std::string m_filename;
+ unsigned long m_line;
+
+ // Format error message to be returned by std::runtime_error::what()
+ static std::string format_what(const std::string &msg,
+ const std::string &file,
+ unsigned long l)
+ {
+ std::stringstream stream;
+ stream << (file.empty() ? "<unspecified file>" : file.c_str());
+ if (l > 0)
+ stream << '(' << l << ')';
+ stream << ": " << msg;
+ return stream.str();
+ }
+
+ };
+
+} }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/ptree_implementation.hpp b/3rdParty/Boost/src/boost/property_tree/detail/ptree_implementation.hpp
new file mode 100644
index 0000000..4220002
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/ptree_implementation.hpp
@@ -0,0 +1,905 @@
+// ----------------------------------------------------------------------------
+// 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_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>
+#include <cassert>
+
+#if defined(BOOST_MSVC) && \
+ (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)
+#define BOOST_PROPERTY_TREE_PAIR_BUG
+#endif
+
+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.
+#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
+ // MSVC 10 has moved std::pair's members to a base
+ // class. Unfortunately this does break the interface.
+ BOOST_STATIC_CONSTANT(unsigned,
+ first_offset = offsetof(value_type, first));
+ 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_offset<value_type, const key_type,
+ first_offset>,
+ key_compare
+ >
+ >
+ > base_container;
+#else
+ 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;
+#endif
+ // 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).BOOST_NESTED_TEMPLATE get<by_name>();
+ }
+ static const by_name_index& assoc(const self_type *s) {
+ return ch(s).BOOST_NESTED_TEMPLATE 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;
+ typedef boost::iterator_adaptor<
+ iterator, typename subs::base_container::iterator, value_type>
+ baset;
+ public:
+ typedef typename baset::reference reference;
+ iterator() {}
+ explicit iterator(typename iterator::base_type b)
+ : iterator::iterator_adaptor_(b)
+ {}
+ 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<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(
+ typename basic_ptree<K, D, C>::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;
+ typedef boost::iterator_adaptor<assoc_iterator,
+ typename subs::by_name_index::iterator,
+ value_type>
+ baset;
+ public:
+ typedef typename baset::reference reference;
+ assoc_iterator() {}
+ explicit assoc_iterator(typename assoc_iterator::base_type b)
+ : assoc_iterator::iterator_adaptor_(b)
+ {}
+ reference dereference() const
+ {
+ return const_cast<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
+
+ // 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> inline
+ basic_ptree<K, D, C>::basic_ptree()
+ : m_children(new typename subs::base_container)
+ {
+ }
+
+ template<class K, class D, class C> inline
+ basic_ptree<K, D, C>::basic_ptree(const data_type &d)
+ : m_data(d), m_children(new typename subs::base_container)
+ {
+ }
+
+ 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)))
+ {
+ }
+
+ 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)
+ {
+ self_type(rhs).swap(*this);
+ return *this;
+ }
+
+ 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);
+ // Void pointers, no ADL necessary
+ std::swap(m_children, rhs.m_children);
+ }
+
+ // Container view
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::size_type
+ basic_ptree<K, D, C>::size() const
+ {
+ return subs::ch(this).size();
+ }
+
+ 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 subs::ch(this).max_size();
+ }
+
+ template<class K, class D, class C> inline
+ bool basic_ptree<K, D, C>::empty() const
+ {
+ return subs::ch(this).empty();
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::begin()
+ {
+ return iterator(subs::ch(this).begin());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_iterator
+ basic_ptree<K, D, C>::begin() const
+ {
+ return const_iterator(subs::ch(this).begin());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::end()
+ {
+ return iterator(subs::ch(this).end());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_iterator
+ basic_ptree<K, D, C>::end() const
+ {
+ return const_iterator(subs::ch(this).end());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::reverse_iterator
+ basic_ptree<K, D, C>::rbegin()
+ {
+ return reverse_iterator(this->end());
+ }
+
+ 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 const_reverse_iterator(this->end());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::reverse_iterator
+ basic_ptree<K, D, C>::rend()
+ {
+ return reverse_iterator(this->begin());
+ }
+
+ 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 const_reverse_iterator(this->begin());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::front()
+ {
+ return const_cast<value_type&>(subs::ch(this).front());
+ }
+
+ 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 subs::ch(this).front();
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::value_type &
+ basic_ptree<K, D, C>::back()
+ {
+ return const_cast<value_type&>(subs::ch(this).back());
+ }
+
+ 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 subs::ch(this).back();
+ }
+
+ 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 iterator(subs::ch(this).insert(where.base(), value).first);
+ }
+
+ template<class K, class D, class C>
+ template<class It> inline
+ void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
+ {
+ subs::ch(this).insert(where.base(), first, last);
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::iterator
+ basic_ptree<K, D, C>::erase(iterator where)
+ {
+ return iterator(subs::ch(this).erase(where.base()));
+ }
+
+ 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 iterator(subs::ch(this).erase(first.base(), last.base()));
+ }
+
+ 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 iterator(subs::ch(this).push_front(value).first);
+ }
+
+ 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 iterator(subs::ch(this).push_back(value).first);
+ }
+
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::pop_front()
+ {
+ subs::ch(this).pop_front();
+ }
+
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::pop_back()
+ {
+ subs::ch(this).pop_back();
+ }
+
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::reverse()
+ {
+ subs::ch(this).reverse();
+ }
+
+ template<class K, class D, class C> inline
+ void basic_ptree<K, D, C>::sort()
+ {
+ subs::ch(this).sort();
+ }
+
+ template<class K, class D, class C>
+ template<class Compare> inline
+ void basic_ptree<K, D, C>::sort(Compare comp)
+ {
+ subs::ch(this).sort(comp);
+ }
+
+ // Equality
+
+ 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() &&
+ subs::ch(this) == subs::ch(&rhs);
+ }
+
+ 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> inline
+ typename basic_ptree<K, D, C>::assoc_iterator
+ basic_ptree<K, D, C>::ordered_begin()
+ {
+ return assoc_iterator(subs::assoc(this).begin());
+ }
+
+ template<class K, class D, class C> inline
+ typename basic_ptree<K, D, C>::const_assoc_iterator
+ basic_ptree<K, D, C>::ordered_begin() const
+ {
+ return const_assoc_iterator(subs::assoc(this).begin());
+ }
+
+ 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_iterator(subs::assoc(this).end());
+ }
+
+ 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 const_assoc_iterator(subs::assoc(this).end());
+ }
+
+ 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_iterator(subs::assoc(this).find(key));
+ }
+
+ 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 const_assoc_iterator(subs::assoc(this).find(key));
+ }
+
+ template<class K, class D, class C> inline
+ std::pair<
+ 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>(
+ assoc_iterator(r.first), assoc_iterator(r.second));
+ }
+
+ template<class K, class D, class C> inline
+ std::pair<
+ 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
+ {
+ 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>(
+ const_assoc_iterator(r.first), const_assoc_iterator(r.second));
+ }
+
+ 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 subs::assoc(this).count(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 subs::assoc(this).erase(key);
+ }
+
+ 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 iterator(subs::ch(this).
+ BOOST_NESTED_TEMPLATE project<0>(ai.base()));
+ }
+
+ 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 const_iterator(subs::ch(this).
+ BOOST_NESTED_TEMPLATE project<0>(ai.base()));
+ }
+
+ // Property tree view
+
+ 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> 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> inline
+ void basic_ptree<K, D, C>::clear()
+ {
+ m_data = data_type();
+ subs::ch(this).clear();
+ }
+
+ 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("No such node", path));
+ }
+ return *n;
+ }
+
+ 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> 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> 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,
+ const_cast<self_type&>(default_value));
+ }
+
+
+ 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);
+ if (!n) {
+ return optional<self_type&>();
+ }
+ return *n;
+ }
+
+ 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);
+ if (!n) {
+ return optional<const self_type&>();
+ }
+ return *n;
+ }
+
+ 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.
+ 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, value))->second;
+ }
+ }
+
+ 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.
+ key_type fragment = p.reduce();
+ return parent.push_back(value_type(fragment, value))->second;
+ }
+
+ template<class K, class D, class C>
+ template<class Type, class Translator>
+ 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<Type>(tr)) {
+ return *o;
+ }
+ BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
+ std::string("conversion of data to type \"") +
+ typeid(Type).name() + "\" failed", data()));
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ Type basic_ptree<K, D, C>::get_value() const
+ {
+ return get_value<Type>(
+ typename translator_between<data_type, Type>::type());
+ }
+
+ template<class K, class D, class C>
+ template<class Type, class Translator> inline
+ Type basic_ptree<K, D, C>::get_value(const Type &default_value,
+ Translator tr) const
+ {
+ return get_value_optional<Type>(tr).get_value_or(default_value);
+ }
+
+ 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
+ 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>
+ 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>::get_value_optional(
+ Translator tr) const
+ {
+ return tr.get_value(data());
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ optional<Type> basic_ptree<K, D, C>::get_value_optional() const
+ {
+ return get_value_optional<Type>(
+ typename translator_between<data_type, Type>::type());
+ }
+
+ template<class K, class D, class C>
+ template<class Type, class Translator> inline
+ 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).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ Type basic_ptree<K, D, C>::get(const path_type &path) const
+ {
+ return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
+ }
+
+ template<class K, class D, class C>
+ template<class Type, class Translator> inline
+ 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>
+ 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>
+ 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>::get_optional(const path_type &path,
+ Translator tr) const
+ {
+ if (optional<const self_type&> child = get_child_optional(path))
+ return child.get().
+ BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
+ else
+ return optional<Type>();
+ }
+
+ template<class K, class D, class C>
+ template<class Type>
+ optional<Type> basic_ptree<K, D, C>::get_optional(
+ const path_type &path) const
+ {
+ if (optional<const self_type&> child = get_child_optional(path))
+ return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
+ else
+ return optional<Type>();
+ }
+
+ template<class K, class D, class C>
+ template<class Type, class Translator>
+ void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
+ {
+ if(optional<data_type> o = tr.put_value(value)) {
+ data() = *o;
+ } else {
+ BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
+ std::string("conversion of type \"") + typeid(Type).name() +
+ "\" to data failed", boost::any()));
+ }
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ 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>
+ template<class Type, typename Translator>
+ 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)) {
+ child.get().put_value(value, tr);
+ return *child;
+ } else {
+ self_type &child2 = put_child(path, self_type());
+ child2.put_value(value, tr);
+ return child2;
+ }
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ 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>
+ template<class Type, typename Translator> inline
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
+ const path_type &path, const Type &value, Translator tr)
+ {
+ self_type &child = add_child(path, self_type());
+ child.put_value(value, tr);
+ return child;
+ }
+
+ template<class K, class D, class C>
+ template<class Type> inline
+ basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
+ const path_type &path, const Type &value)
+ {
+ return add(path, value,
+ typename translator_between<data_type, Type>::type());
+ }
+
+
+ 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 const_cast<basic_ptree*>(this);
+ }
+ // Recurse down the tree to find the path.
+ 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 el->second.walk_path(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;
+ }
+ 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 = 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>
+ inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
+ {
+ pt1.swap(pt2);
+ }
+
+} }
+
+#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
+#undef BOOST_PROPERTY_TREE_PAIR_BUG
+#endif
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/ptree_utils.hpp b/3rdParty/Boost/src/boost/property_tree/detail/ptree_utils.hpp
new file mode 100644
index 0000000..7e56c8f
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/ptree_utils.hpp
@@ -0,0 +1,106 @@
+// ----------------------------------------------------------------------------
+// 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_PTREE_UTILS_HPP_INCLUDED
+#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>
+
+namespace boost { namespace property_tree { namespace detail
+{
+
+ template<class T>
+ struct less_nocase
+ {
+ typedef typename T::value_type Ch;
+ std::locale m_locale;
+ inline bool operator()(Ch c1, Ch c2) const
+ {
+ return std::toupper(c1, m_locale) < std::toupper(c2, m_locale);
+ }
+ inline bool operator()(const T &t1, const T &t2) const
+ {
+ return std::lexicographical_compare(t1.begin(), t1.end(),
+ t2.begin(), t2.end(), *this);
+ }
+ };
+
+ 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>
+ std::basic_string<Ch> widen(const char *text)
+ {
+ std::basic_string<Ch> result;
+ while (*text)
+ {
+ result += Ch(*text);
+ ++text;
+ }
+ return result;
+ }
+
+ // Naively convert string to narrow character type
+ template<class Ch>
+ std::string narrow(const Ch *text)
+ {
+ std::string result;
+ while (*text)
+ {
+ if (*text < 0 || *text > (std::numeric_limits<char>::max)())
+ result += '*';
+ else
+ result += char(*text);
+ ++text;
+ }
+ return result;
+ }
+
+ // Remove trailing and leading spaces
+ template<class Ch>
+ std::basic_string<Ch> trim(const std::basic_string<Ch> &s,
+ const std::locale &loc = std::locale())
+ {
+ typename std::basic_string<Ch>::const_iterator first = s.begin();
+ typename std::basic_string<Ch>::const_iterator end = s.end();
+ while (first != end && std::isspace(*first, loc))
+ ++first;
+ if (first == end)
+ return std::basic_string<Ch>();
+ typename std::basic_string<Ch>::const_iterator last = end;
+ do --last; while (std::isspace(*last, loc));
+ if (first != s.begin() || last + 1 != end)
+ return std::basic_string<Ch>(first, last + 1);
+ else
+ return s;
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/rapidxml.hpp b/3rdParty/Boost/src/boost/property_tree/detail/rapidxml.hpp
new file mode 100644
index 0000000..712bf3f
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/rapidxml.hpp
@@ -0,0 +1,2582 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2006, 2009 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_RAPIDXML_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_RAPIDXML_HPP_INCLUDED
+
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+#include <cstdlib> // For std::size_t
+#include <cassert> // For assert
+#include <new> // For placement new
+
+// On MSVC, disable "conditional expression is constant" warning (level 4).
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR
+
+#include <exception> // For std::exception
+
+#define BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace boost { namespace property_tree { namespace detail {namespace rapidxml
+{
+
+ //! Parse error exception.
+ //! This exception is thrown by the parser when an error occurs.
+ //! Use what() function to get human-readable error message.
+ //! Use where() function to get a pointer to position within source text where error was detected.
+ //! <br><br>
+ //! If throwing exceptions by the parser is undesirable,
+ //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+ //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+ //! This function must be defined by the user.
+ //! <br><br>
+ //! This class derives from <code>std::exception</code> class.
+ class parse_error: public std::exception
+ {
+
+ public:
+
+ //! Constructs parse error
+ parse_error(const char *wa, void *we)
+ : m_what(wa)
+ , m_where(we)
+ {
+ }
+
+ //! Gets human readable description of error.
+ //! \return Pointer to null terminated description of the error.
+ virtual const char *what() const throw()
+ {
+ return m_what;
+ }
+
+ //! Gets pointer to character data where error happened.
+ //! Ch should be the same as char type of xml_document that produced the error.
+ //! \return Pointer to location within the parsed string where error occured.
+ template<class Ch>
+ Ch *where() const
+ {
+ return reinterpret_cast<Ch *>(m_where);
+ }
+
+ private:
+
+ const char *m_what;
+ void *m_where;
+
+ };
+}}}}
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE
+ // Size of static memory block of memory_pool.
+ // Define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+ #define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE
+ // Size of dynamic memory block of memory_pool.
+ // Define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+ #define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT
+ // Memory allocation alignment.
+ // Define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+ // All memory allocations for nodes, attributes and strings will be aligned to this value.
+ // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+ #define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace boost { namespace property_tree { namespace detail {namespace rapidxml
+{
+ // Forward declarations
+ template<class Ch> class xml_node;
+ template<class Ch> class xml_attribute;
+ template<class Ch> class xml_document;
+
+ //! Enumeration listing all node types produced by the parser.
+ //! Use xml_node::type() function to query node type.
+ enum node_type
+ {
+ node_document, //!< A document node. Name and value are empty.
+ node_element, //!< An element node. Name contains element name. Value contains text of first data node.
+ node_data, //!< A data node. Name is empty. Value contains data text.
+ node_cdata, //!< A CDATA node. Name is empty. Value contains data text.
+ node_comment, //!< A comment node. Name is empty. Value contains comment text.
+ node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+ node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+ node_pi //!< A PI node. Name contains target. Value contains instructions.
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Parsing flags
+
+ //! Parse flag instructing the parser to not create data nodes.
+ //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_data_nodes = 0x1;
+
+ //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+ //! Can be combined with other flags by use of | operator.
+ //! Note that child data nodes of element node take precendence over its value when printing.
+ //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+ //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_element_values = 0x2;
+
+ //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+ //! By default zero terminators are placed, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_string_terminators = 0x4;
+
+ //! Parse flag instructing the parser to not translate entities in the source text.
+ //! By default entities are translated, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_entity_translation = 0x8;
+
+ //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+ //! By default, UTF-8 handling is enabled.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_utf8 = 0x10;
+
+ //! Parse flag instructing the parser to create XML declaration node.
+ //! By default, declaration node is not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_declaration_node = 0x20;
+
+ //! Parse flag instructing the parser to create comments nodes.
+ //! By default, comment nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_comment_nodes = 0x40;
+
+ //! Parse flag instructing the parser to create DOCTYPE node.
+ //! By default, doctype node is not created.
+ //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_doctype_node = 0x80;
+
+ //! Parse flag instructing the parser to create PI nodes.
+ //! By default, PI nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_pi_nodes = 0x100;
+
+ //! Parse flag instructing the parser to validate closing tag names.
+ //! If not set, name inside closing tag is irrelevant to the parser.
+ //! By default, closing tags are not validated.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_validate_closing_tags = 0x200;
+
+ //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+ //! By default, whitespace is not trimmed.
+ //! This flag does not cause the parser to modify source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_trim_whitespace = 0x400;
+
+ //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+ //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+ //! By default, whitespace is not normalized.
+ //! If this flag is specified, source text will be modified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_normalize_whitespace = 0x800;
+
+ // Compound flags
+
+ //! Parse flags which represent default behaviour of the parser.
+ //! This is always equal to 0, so that all other flags can be simply ored together.
+ //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+ //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
+ //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+ //! and using the flag will disable it.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_default = 0;
+
+ //! A combination of parse flags that forbids any modifications of the source text.
+ //! This also results in faster parsing. However, note that the following will occur:
+ //! <ul>
+ //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+ //! <li>entities will not be translated</li>
+ //! <li>whitespace will not be normalized</li>
+ //! </ul>
+ //! See xml_document::parse() function.
+ const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+
+ //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+
+ //! A combination of parse flags resulting in largest amount of data being extracted.
+ //! This usually results in slowest parsing.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internals
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Struct that contains lookup tables for the parser
+ // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+ template<int Dummy>
+ struct lookup_tables
+ {
+ static const unsigned char lookup_whitespace[256]; // Whitespace table
+ static const unsigned char lookup_node_name[256]; // Node name table
+ static const unsigned char lookup_text[256]; // Text table
+ static const unsigned char lookup_text_pure_no_ws[256]; // Text table
+ static const unsigned char lookup_text_pure_with_ws[256]; // Text table
+ static const unsigned char lookup_attribute_name[256]; // Attribute name table
+ static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_digits[256]; // Digits
+ static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters
+ };
+
+ // Find length of the string
+ template<class Ch>
+ inline std::size_t measure(const Ch *p)
+ {
+ const Ch *tmp = p;
+ while (*tmp)
+ ++tmp;
+ return tmp - p;
+ }
+
+ // Compare strings for equality
+ template<class Ch>
+ inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+ {
+ if (size1 != size2)
+ return false;
+ if (case_sensitive)
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (*p1 != *p2)
+ return false;
+ }
+ else
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+ return false;
+ }
+ return true;
+ }
+
+ template<class Ch>
+ inline size_t get_index(const Ch c)
+ {
+ // If not ASCII char, its sematic is same as plain 'z'
+ if (c > 255)
+ {
+ return 'z';
+ }
+ return c;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////
+ // Memory pool
+
+ //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+ //! In most cases, you will not need to use this class directly.
+ //! However, if you need to create nodes manually or modify names/values of nodes,
+ //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
+ //! Not only is this faster than allocating them by using <code>new</code> operator,
+ //! but also their lifetime will be tied to the lifetime of document,
+ //! possibly simplyfing memory management.
+ //! <br><br>
+ //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
+ //! You can also call allocate_string() function to allocate strings.
+ //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+ //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
+ //! or when the pool is destroyed.
+ //! <br><br>
+ //! It is also possible to create a standalone memory_pool, and use it
+ //! to allocate nodes, whose lifetime will not be tied to any document.
+ //! <br><br>
+ //! Pool maintains <code>BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
+ //! Until static memory is exhausted, no dynamic memory allocations are done.
+ //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+ //! by using global <code>new[]</code> and <code>delete[]</code> operators.
+ //! This behaviour can be changed by setting custom allocation routines.
+ //! Use set_allocator() function to set them.
+ //! <br><br>
+ //! Allocations for nodes, attributes and strings are aligned at <code>BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT</code> bytes.
+ //! This value defaults to the size of pointer on target architecture.
+ //! <br><br>
+ //! To obtain absolutely top performance from the parser,
+ //! it is important that all nodes are allocated from a single, contiguous block of memory.
+ //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+ //! If required, you can tweak <code>BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE</code>, <code>BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT</code>
+ //! to obtain best wasted memory to performance compromise.
+ //! To do it, define their values before rapidxml.hpp file is included.
+ //! \param Ch Character type of created nodes.
+ template<class Ch = char>
+ class memory_pool
+ {
+
+ public:
+
+ //! \cond internal
+ typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
+ typedef void (free_func)(void *); // Type of user-defined function used to free memory
+ //! \endcond
+
+ //! Constructs empty pool with default allocator functions.
+ memory_pool()
+ : m_alloc_func(0)
+ , m_free_func(0)
+ {
+ init();
+ }
+
+ //! Destroys pool and frees all the memory.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Nodes allocated from the pool are no longer valid.
+ ~memory_pool()
+ {
+ clear();
+ }
+
+ //! Allocates a new node from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param type Type of node to create.
+ //! \param name Name to assign to the node, or 0 to assign no name.
+ //! \param value Value to assign to the node, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated node. This pointer will never be NULL.
+ xml_node<Ch> *allocate_node(node_type type,
+ const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+ xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+ if (name)
+ {
+ if (name_size > 0)
+ node->name(name, name_size);
+ else
+ node->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ node->value(value, value_size);
+ else
+ node->value(value);
+ }
+ return node;
+ }
+
+ //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param name Name to assign to the attribute, or 0 to assign no name.
+ //! \param value Value to assign to the attribute, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated attribute. This pointer will never be NULL.
+ xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+ xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+ if (name)
+ {
+ if (name_size > 0)
+ attribute->name(name, name_size);
+ else
+ attribute->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ attribute->value(value, value_size);
+ else
+ attribute->value(value);
+ }
+ return attribute;
+ }
+
+ //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+ //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+ //! \return Pointer to allocated char array. This pointer will never be NULL.
+ Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+ {
+ assert(source || size); // Either source or size (or both) must be specified
+ if (size == 0)
+ size = internal::measure(source) + 1;
+ Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+ if (source)
+ for (std::size_t i = 0; i < size; ++i)
+ result[i] = source[i];
+ return result;
+ }
+
+ //! Clones an xml_node and its hierarchy of child nodes and attributes.
+ //! Nodes and attributes are allocated from this memory pool.
+ //! Names and values are not cloned, they are shared between the clone and the source.
+ //! Result node can be optionally specified as a second parameter,
+ //! in which case its contents will be replaced with cloned source node.
+ //! This is useful when you want to clone entire document.
+ //! \param source Node to clone.
+ //! \param result Node to put results in, or 0 to automatically allocate result node
+ //! \return Pointer to cloned node. This pointer will never be NULL.
+ xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+ {
+ // Prepare result node
+ if (result)
+ {
+ result->remove_all_attributes();
+ result->remove_all_nodes();
+ result->type(source->type());
+ }
+ else
+ result = allocate_node(source->type());
+
+ // Clone name and value
+ result->name(source->name(), source->name_size());
+ result->value(source->value(), source->value_size());
+
+ // Clone child nodes and attributes
+ for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+ result->append_node(clone_node(child));
+ for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+ result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+ return result;
+ }
+
+ //! Clears the pool.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Any nodes or strings allocated from the pool will no longer be valid.
+ void clear()
+ {
+ while (m_begin != m_static_memory)
+ {
+ char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+ if (m_free_func)
+ m_free_func(m_begin);
+ else
+ delete[] m_begin;
+ m_begin = previous_begin;
+ }
+ init();
+ }
+
+ //! Sets or resets the user-defined memory allocation functions for the pool.
+ //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+ //! Allocation function must not return invalid pointer on failure. It should either throw,
+ //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
+ //! If it returns invalid pointer, results are undefined.
+ //! <br><br>
+ //! User defined allocation functions must have the following forms:
+ //! <br><code>
+ //! <br>void *allocate(std::size_t size);
+ //! <br>void free(void *pointer);
+ //! </code><br>
+ //! \param af Allocation function, or 0 to restore default function
+ //! \param ff Free function, or 0 to restore default function
+ void set_allocator(alloc_func *af, free_func *ff)
+ {
+ assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet
+ m_alloc_func = af;
+ m_free_func = ff;
+ }
+
+ private:
+
+ struct header
+ {
+ char *previous_begin;
+ };
+
+ void init()
+ {
+ m_begin = m_static_memory;
+ m_ptr = align(m_begin);
+ m_end = m_static_memory + sizeof(m_static_memory);
+ }
+
+ char *align(char *ptr)
+ {
+ std::size_t alignment = ((BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1))) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1));
+ return ptr + alignment;
+ }
+
+ char *allocate_raw(std::size_t size)
+ {
+ // Allocate
+ void *memory;
+ if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[]
+ {
+ memory = m_alloc_func(size);
+ assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+ }
+ else
+ {
+ memory = new char[size];
+ }
+ return static_cast<char *>(memory);
+ }
+
+ void *allocate_aligned(std::size_t size)
+ {
+ // Calculate aligned pointer
+ char *result = align(m_ptr);
+
+ // If not enough memory left in current pool, allocate a new pool
+ if (result + size > m_end)
+ {
+ // Calculate required pool size (may be bigger than BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE)
+ std::size_t pool_size = BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE;
+ if (pool_size < size)
+ pool_size = size;
+
+ // Allocate
+ std::size_t alloc_size = sizeof(header) + (2 * BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation
+ char *raw_memory = allocate_raw(alloc_size);
+
+ // Setup new pool in allocated memory
+ char *pool = align(raw_memory);
+ header *new_header = reinterpret_cast<header *>(pool);
+ new_header->previous_begin = m_begin;
+ m_begin = raw_memory;
+ m_ptr = pool + sizeof(header);
+ m_end = raw_memory + alloc_size;
+
+ // Calculate aligned pointer again using new pool
+ result = align(m_ptr);
+ }
+
+ // Update pool and return aligned pointer
+ m_ptr = result + size;
+ return result;
+ }
+
+ char *m_begin; // Start of raw memory making up current pool
+ char *m_ptr; // First free byte in current pool
+ char *m_end; // One past last available byte in current pool
+ char m_static_memory[BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
+ alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
+ free_func *m_free_func; // Free function, or 0 if default is to be used
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML base
+
+ //! Base class for xml_node and xml_attribute implementing common functions:
+ //! name(), name_size(), value(), value_size() and parent().
+ //! \param Ch Character type to use
+ template<class Ch = char>
+ class xml_base
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ // Construct a base with empty name, value and parent
+ xml_base()
+ : m_name(0)
+ , m_value(0)
+ , m_parent(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets name of the node.
+ //! Interpretation of name depends on type of node.
+ //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use name_size() function to determine length of the name.
+ //! \return Name of node, or empty string if node has no name.
+ Ch *name() const
+ {
+ return m_name ? m_name : nullstr();
+ }
+
+ //! Gets size of node name, not including terminator character.
+ //! This function works correctly irrespective of whether name is or is not zero terminated.
+ //! \return Size of node name, in characters.
+ std::size_t name_size() const
+ {
+ return m_name ? m_name_size : 0;
+ }
+
+ //! Gets value of node.
+ //! Interpretation of value depends on type of node.
+ //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use value_size() function to determine length of the value.
+ //! \return Value of node, or empty string if node has no value.
+ Ch *value() const
+ {
+ return m_value ? m_value : nullstr();
+ }
+
+ //! Gets size of node value, not including terminator character.
+ //! This function works correctly irrespective of whether value is or is not zero terminated.
+ //! \return Size of node value, in characters.
+ std::size_t value_size() const
+ {
+ return m_value ? m_value_size : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets name of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of name must be specified separately, because name does not have to be zero terminated.
+ //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! \param n Name of node to set. Does not have to be zero terminated.
+ //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+ void name(const Ch *n, std::size_t size)
+ {
+ m_name = const_cast<Ch *>(n);
+ m_name_size = size;
+ }
+
+ //! Sets name of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+ //! \param n Name of node to set. Must be zero terminated.
+ void name(const Ch *n)
+ {
+ name(n, internal::measure(n));
+ }
+
+ //! Sets value of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of value must be specified separately, because it does not have to be zero terminated.
+ //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! <br><br>
+ //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+ //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+ //! \param val value of node to set. Does not have to be zero terminated.
+ //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+ void value(const Ch *val, std::size_t size)
+ {
+ m_value = const_cast<Ch *>(val);
+ m_value_size = size;
+ }
+
+ //! Sets value of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+ //! \param val Vame of node to set. Must be zero terminated.
+ void value(const Ch *val)
+ {
+ this->value(val, internal::measure(val));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets node parent.
+ //! \return Pointer to parent node, or 0 if there is no parent.
+ xml_node<Ch> *parent() const
+ {
+ return m_parent;
+ }
+
+ protected:
+
+ // Return empty string
+ static Ch *nullstr()
+ {
+ static Ch zero = Ch('\0');
+ return &zero;
+ }
+
+ Ch *m_name; // Name of node, or 0 if no name
+ Ch *m_value; // Value of node, or 0 if no value
+ std::size_t m_name_size; // Length of node name, or undefined of no name
+ std::size_t m_value_size; // Length of node value, or undefined if no value
+ xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none
+
+ };
+
+ //! Class representing attribute node of XML document.
+ //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+ //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
+ //! Thus, this text must persist in memory for the lifetime of attribute.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_attribute: public xml_base<Ch>
+ {
+
+ friend class xml_node<Ch>;
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty attribute with the specified type.
+ //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+ xml_attribute()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which attribute is a child.
+ //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ if (xml_node<Ch> *node = this->parent())
+ {
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+ else
+ return 0;
+ }
+
+ //! Gets previous attribute, optionally matching attribute name.
+ //! \param n Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *previous_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_prev_attribute : 0;
+ }
+
+ //! Gets next attribute, optionally matching attribute name.
+ //! \param n Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *next_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_next_attribute : 0;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+ xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML node
+
+ //! Class representing a node of XML document.
+ //! Each node may have associated name and value strings, which are available through name() and value() functions.
+ //! Interpretation of name and value depends on type of the node.
+ //! Type of node can be determined by using type() function.
+ //! <br><br>
+ //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
+ //! Thus, this text must persist in the memory for the lifetime of node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_node: public xml_base<Ch>
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty node with the specified type.
+ //! Consider using memory_pool of appropriate document to allocate nodes manually.
+ //! \param t Type of node to construct.
+ xml_node(node_type t)
+ : m_type(t)
+ , m_first_node(0)
+ , m_first_attribute(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets type of node.
+ //! \return Type of node.
+ node_type type() const
+ {
+ return m_type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which node is a child.
+ //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+
+ //! Gets first child node, optionally matching node name.
+ //! \param n Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *first_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+ if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_first_node;
+ }
+
+ //! Gets last child node, optionally matching node name.
+ //! Behaviour is undefined if node has no children.
+ //! Use first_node() to test if node has children.
+ //! \param n Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *last_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ assert(m_first_node); // Cannot query for last child if node has no children
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+ if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_last_node;
+ }
+
+ //! Gets previous sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param n Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *previous_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_prev_sibling;
+ }
+
+ //! Gets next sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param n Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *next_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_next_sibling;
+ }
+
+ //! Gets first attribute of node, optionally matching attribute name.
+ //! \param n Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *first_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute;
+ }
+
+ //! Gets last attribute of node, optionally matching attribute name.
+ //! \param n Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero
+ //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *last_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const
+ {
+ if (n)
+ {
+ if (nsize == 0)
+ nsize = internal::measure(n);
+ for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute ? m_last_attribute : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets type of node.
+ //! \param t Type of node to set.
+ void type(node_type t)
+ {
+ m_type = t;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node manipulation
+
+ //! Prepends a new child node.
+ //! The prepended child becomes the first child, and all existing children are moved one position back.
+ //! \param child Node to prepend.
+ void prepend_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_next_sibling = m_first_node;
+ m_first_node->m_prev_sibling = child;
+ }
+ else
+ {
+ child->m_next_sibling = 0;
+ m_last_node = child;
+ }
+ m_first_node = child;
+ child->m_parent = this;
+ child->m_prev_sibling = 0;
+ }
+
+ //! Appends a new child node.
+ //! The appended child becomes the last child.
+ //! \param child Node to append.
+ void append_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_prev_sibling = m_last_node;
+ m_last_node->m_next_sibling = child;
+ }
+ else
+ {
+ child->m_prev_sibling = 0;
+ m_first_node = child;
+ }
+ m_last_node = child;
+ child->m_parent = this;
+ child->m_next_sibling = 0;
+ }
+
+ //! Inserts a new child node at specified place inside the node.
+ //! All children after and including the specified node are moved one position back.
+ //! \param where Place where to insert the child, or 0 to insert at the back.
+ //! \param child Node to insert.
+ void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+ {
+ assert(!where || where->parent() == this);
+ assert(child && !child->parent() && child->type() != node_document);
+ if (where == m_first_node)
+ prepend_node(child);
+ else if (where == 0)
+ append_node(child);
+ else
+ {
+ child->m_prev_sibling = where->m_prev_sibling;
+ child->m_next_sibling = where;
+ where->m_prev_sibling->m_next_sibling = child;
+ where->m_prev_sibling = child;
+ child->m_parent = this;
+ }
+ }
+
+ //! Removes first child node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_first_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_first_node;
+ m_first_node = child->m_next_sibling;
+ if (child->m_next_sibling)
+ child->m_next_sibling->m_prev_sibling = 0;
+ else
+ m_last_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes last child of the node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_last_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_last_node;
+ if (child->m_prev_sibling)
+ {
+ m_last_node = child->m_prev_sibling;
+ child->m_prev_sibling->m_next_sibling = 0;
+ }
+ else
+ m_first_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes specified child from the node
+ // \param where Pointer to child to be removed.
+ void remove_node(xml_node<Ch> *where)
+ {
+ assert(where && where->parent() == this);
+ assert(first_node());
+ if (where == m_first_node)
+ remove_first_node();
+ else if (where == m_last_node)
+ remove_last_node();
+ else
+ {
+ where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+ where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all child nodes (but not attributes).
+ void remove_all_nodes()
+ {
+ for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+ node->m_parent = 0;
+ m_first_node = 0;
+ }
+
+ //! Prepends a new attribute to the node.
+ //! \param attribute Attribute to prepend.
+ void prepend_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_next_attribute = m_first_attribute;
+ m_first_attribute->m_prev_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_next_attribute = 0;
+ m_last_attribute = attribute;
+ }
+ m_first_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_prev_attribute = 0;
+ }
+
+ //! Appends a new attribute to the node.
+ //! \param attribute Attribute to append.
+ void append_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_prev_attribute = m_last_attribute;
+ m_last_attribute->m_next_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_prev_attribute = 0;
+ m_first_attribute = attribute;
+ }
+ m_last_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_next_attribute = 0;
+ }
+
+ //! Inserts a new attribute at specified place inside the node.
+ //! All attributes after and including the specified attribute are moved one position back.
+ //! \param where Place where to insert the attribute, or 0 to insert at the back.
+ //! \param attribute Attribute to insert.
+ void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+ {
+ assert(!where || where->parent() == this);
+ assert(attribute && !attribute->parent());
+ if (where == m_first_attribute)
+ prepend_attribute(attribute);
+ else if (where == 0)
+ append_attribute(attribute);
+ else
+ {
+ attribute->m_prev_attribute = where->m_prev_attribute;
+ attribute->m_next_attribute = where;
+ where->m_prev_attribute->m_next_attribute = attribute;
+ where->m_prev_attribute = attribute;
+ attribute->m_parent = this;
+ }
+ }
+
+ //! Removes first attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_first_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_first_attribute;
+ if (attribute->m_next_attribute)
+ {
+ attribute->m_next_attribute->m_prev_attribute = 0;
+ }
+ else
+ m_last_attribute = 0;
+ attribute->m_parent = 0;
+ m_first_attribute = attribute->m_next_attribute;
+ }
+
+ //! Removes last attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_last_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_last_attribute;
+ if (attribute->m_prev_attribute)
+ {
+ attribute->m_prev_attribute->m_next_attribute = 0;
+ m_last_attribute = attribute->m_prev_attribute;
+ }
+ else
+ m_first_attribute = 0;
+ attribute->m_parent = 0;
+ }
+
+ //! Removes specified attribute from node.
+ //! \param where Pointer to attribute to be removed.
+ void remove_attribute(xml_attribute<Ch> *where)
+ {
+ assert(first_attribute() && where->parent() == this);
+ if (where == m_first_attribute)
+ remove_first_attribute();
+ else if (where == m_last_attribute)
+ remove_last_attribute();
+ else
+ {
+ where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+ where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all attributes of node.
+ void remove_all_attributes()
+ {
+ for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+ attribute->m_parent = 0;
+ m_first_attribute = 0;
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Restrictions
+
+ // No copying
+ xml_node(const xml_node &);
+ void operator =(const xml_node &);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Data members
+
+ // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+ // This is required for maximum performance, as it allows the parser to omit initialization of
+ // unneded/redundant values.
+ //
+ // The rules are as follows:
+ // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+ // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+ // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+ node_type m_type; // Type of node; always valid
+ xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid
+ xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+ xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
+ xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+ xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+ xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML document
+
+ //! This class represents root of the DOM hierarchy.
+ //! It is also an xml_node and a memory_pool through public inheritance.
+ //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+ //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
+ //! which are inherited from memory_pool.
+ //! To access root node of the document, use the document itself, as if it was an xml_node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+ {
+
+ public:
+
+ //! Constructs empty XML document
+ xml_document()
+ : xml_node<Ch>(node_document)
+ {
+ }
+
+ //! Parses zero-terminated XML string according to given flags.
+ //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+ //! The string must persist for the lifetime of the document.
+ //! In case of error, rapidxml::parse_error exception will be thrown.
+ //! <br><br>
+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+ //! Make sure that data is zero-terminated.
+ //! <br><br>
+ //! Document can be parsed into multiple times.
+ //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+ //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+ template<int Flags>
+ void parse(Ch *text)
+ {
+ assert(text);
+
+ // Remove current contents
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+
+ // Parse BOM, if any
+ parse_bom<Flags>(text);
+
+ // Parse children
+ while (1)
+ {
+ // Skip whitespace before node
+ skip<whitespace_pred, Flags>(text);
+ if (*text == 0)
+ break;
+
+ // Parse and append new child
+ if (*text == Ch('<'))
+ {
+ ++text; // Skip '<'
+ if (xml_node<Ch> *node = parse_node<Flags>(text))
+ this->append_node(node);
+ }
+ else
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected <", text);
+ }
+
+ }
+
+ //! Clears the document by deleting all nodes and clearing the memory pool.
+ //! All nodes owned by document pool are destroyed.
+ void clear()
+ {
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+ memory_pool<Ch>::clear();
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal character utility functions
+
+ // Detect whitespace character
+ struct whitespace_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_whitespace[internal::get_index(ch)];
+ }
+ };
+
+ // Detect node name character
+ struct node_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_node_name[internal::get_index(ch)];
+ }
+ };
+
+ // Detect attribute name character
+ struct attribute_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_attribute_name[internal::get_index(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA)
+ struct text_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text[internal::get_index(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_no_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_no_ws[internal::get_index(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_with_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_with_ws[internal::get_index(ch)];
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1[internal::get_index(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2[internal::get_index(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pure_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1_pure[internal::get_index(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2_pure[internal::get_index(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Insert coded character, using UTF8 or 8-bit ASCII
+ template<int Flags>
+ static void insert_coded_character(Ch *&text, unsigned long code)
+ {
+ if (Flags & parse_no_utf8)
+ {
+ // Insert 8-bit ASCII character
+ // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else
+ {
+ // Insert UTF8 sequence
+ if (code < 0x80) // 1 byte sequence
+ {
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else if (code < 0x800) // 2 byte sequence
+ {
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xC0);
+ text += 2;
+ }
+ else if (code < 0x10000) // 3 byte sequence
+ {
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xE0);
+ text += 3;
+ }
+ else if (code < 0x110000) // 4 byte sequence
+ {
+ text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xF0);
+ text += 4;
+ }
+ else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+ {
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+ }
+ }
+ }
+
+ // Skip characters until predicate evaluates to true
+ template<class StopPred, int Flags>
+ static void skip(Ch *&text)
+ {
+ Ch *tmp = text;
+ while (StopPred::test(*tmp))
+ ++tmp;
+ text = tmp;
+ }
+
+ // Skip characters until predicate evaluates to true while doing the following:
+ // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+ // - condensing whitespace sequences to single space character
+ template<class StopPred, class StopPredPure, int Flags>
+ static Ch *skip_and_expand_character_refs(Ch *&text)
+ {
+ // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+ if (Flags & parse_no_entity_translation &&
+ !(Flags & parse_normalize_whitespace) &&
+ !(Flags & parse_trim_whitespace))
+ {
+ skip<StopPred, Flags>(text);
+ return text;
+ }
+
+ // Use simple skip until first modification is detected
+ skip<StopPredPure, Flags>(text);
+
+ // Use translation skip
+ Ch *src = text;
+ Ch *dest = src;
+ while (StopPred::test(*src))
+ {
+ // If entity translation is enabled
+ if (!(Flags & parse_no_entity_translation))
+ {
+ // Test if replacement is needed
+ if (src[0] == Ch('&'))
+ {
+ switch (src[1])
+ {
+
+ // &amp; &apos;
+ case Ch('a'):
+ if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+ {
+ *dest = Ch('&');
+ ++dest;
+ src += 5;
+ continue;
+ }
+ if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+ {
+ *dest = Ch('\'');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // &quot;
+ case Ch('q'):
+ if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+ {
+ *dest = Ch('"');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // &gt;
+ case Ch('g'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('>');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &lt;
+ case Ch('l'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('<');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &#...; - assumes ASCII
+ case Ch('#'):
+ if (src[2] == Ch('x'))
+ {
+ unsigned long code = 0;
+ src += 3; // Skip &#x
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 16 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ else
+ {
+ unsigned long code = 0;
+ src += 2; // Skip &#
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 10 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ if (*src == Ch(';'))
+ ++src;
+ else
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ;", src);
+ continue;
+
+ // Something else
+ default:
+ // Ignore, just copy '&' verbatim
+ break;
+
+ }
+ }
+ }
+
+ // If whitespace condensing is enabled
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Test if condensing is needed
+ if (whitespace_pred::test(*src))
+ {
+ *dest = Ch(' '); ++dest; // Put single space in dest
+ ++src; // Skip first whitespace char
+ // Skip remaining whitespace chars
+ while (whitespace_pred::test(*src))
+ ++src;
+ continue;
+ }
+ }
+
+ // No replacement, only copy character
+ *dest++ = *src++;
+
+ }
+
+ // Return new end
+ text = src;
+ return dest;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal parsing functions
+
+ // Parse BOM, if any
+ template<int Flags>
+ void parse_bom(Ch *&text)
+ {
+ // UTF-8?
+ if (static_cast<unsigned char>(text[0]) == 0xEF &&
+ static_cast<unsigned char>(text[1]) == 0xBB &&
+ static_cast<unsigned char>(text[2]) == 0xBF)
+ {
+ text += 3; // Skip utf-8 bom
+ }
+ }
+
+ // Parse XML declaration (<?xml...)
+ template<int Flags>
+ xml_node<Ch> *parse_xml_declaration(Ch *&text)
+ {
+ // If parsing of declaration is disabled
+ if (!(Flags & parse_declaration_node))
+ {
+ // Skip until end of declaration
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (!text[0])
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+
+ // Create declaration
+ xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+ // Skip whitespace before attributes or ?>
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse declaration attributes
+ parse_node_attributes<Flags>(text, declaration);
+
+ // Skip ?>
+ if (text[0] != Ch('?') || text[1] != Ch('>'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ?>", text);
+ text += 2;
+
+ return declaration;
+ }
+
+ // Parse XML comment (<!--...)
+ template<int Flags>
+ xml_node<Ch> *parse_comment(Ch *&text)
+ {
+ // If parsing of comments is disabled
+ if (!(Flags & parse_comment_nodes))
+ {
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip '-->'
+ return 0; // Do not produce comment node
+ }
+
+ // Remember value start
+ Ch *val = text;
+
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create comment node
+ xml_node<Ch> *comment = this->allocate_node(node_comment);
+ comment->value(val, text - val);
+
+ // Place zero terminator after comment value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip '-->'
+ return comment;
+ }
+
+ // Parse DOCTYPE
+ template<int Flags>
+ xml_node<Ch> *parse_doctype(Ch *&text)
+ {
+ // Remember value start
+ Ch *val = text;
+
+ // Skip to >
+ while (*text != Ch('>'))
+ {
+ // Determine character type
+ switch (*text)
+ {
+
+ // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+ // This works for all W3C test files except for 2 most wicked
+ case Ch('['):
+ {
+ ++text; // Skip '['
+ int depth = 1;
+ while (depth > 0)
+ {
+ switch (*text)
+ {
+ case Ch('['): ++depth; break;
+ case Ch(']'): --depth; break;
+ case 0: BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ default: break;
+ }
+ ++text;
+ }
+ break;
+ }
+
+ // Error on end of text
+ case Ch('\0'):
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Other character, skip it
+ default:
+ ++text;
+
+ }
+ }
+
+ // If DOCTYPE nodes enabled
+ if (Flags & parse_doctype_node)
+ {
+ // Create a new doctype node
+ xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+ doctype->value(val, text - val);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 1; // skip '>'
+ return doctype;
+ }
+ else
+ {
+ text += 1; // skip '>'
+ return 0;
+ }
+
+ }
+
+ // Parse PI
+ template<int Flags>
+ xml_node<Ch> *parse_pi(Ch *&text)
+ {
+ // If creation of PI nodes is enabled
+ if (Flags & parse_pi_nodes)
+ {
+ // Create pi node
+ xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+ // Extract PI target name
+ Ch *n = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == n)
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected PI target", text);
+ pi->name(n, text - n);
+
+ // Skip whitespace between pi target and pi
+ skip<whitespace_pred, Flags>(text);
+
+ // Remember start of pi
+ Ch *val = text;
+
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Set pi value (verbatim, no entity expansion or whitespace normalization)
+ pi->value(val, text - val);
+
+ // Place zero terminator after name and value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ pi->name()[pi->name_size()] = Ch('\0');
+ pi->value()[pi->value_size()] = Ch('\0');
+ }
+
+ text += 2; // Skip '?>'
+ return pi;
+ }
+ else
+ {
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+ }
+
+ // Parse and append data
+ // Return character that ends data.
+ // This is necessary because this character might have been overwritten by a terminating 0
+ template<int Flags>
+ Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+ {
+ // Backup to contents start if whitespace trimming is disabled
+ if (!(Flags & parse_trim_whitespace))
+ text = contents_start;
+
+ // Skip until end of data
+ Ch *val = text, *end;
+ if (Flags & parse_normalize_whitespace)
+ end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
+ else
+ end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+ // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+ if (Flags & parse_trim_whitespace)
+ {
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+ if (*(end - 1) == Ch(' '))
+ --end;
+ }
+ else
+ {
+ // Backup until non-whitespace character is found
+ while (whitespace_pred::test(*(end - 1)))
+ --end;
+ }
+ }
+
+ // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+ // Create new data node
+ if (!(Flags & parse_no_data_nodes))
+ {
+ xml_node<Ch> *data = this->allocate_node(node_data);
+ data->value(val, end - val);
+ node->append_node(data);
+ }
+
+ // Add data to parent node if no data exists yet
+ if (!(Flags & parse_no_element_values))
+ if (*node->value() == Ch('\0'))
+ node->value(val, end - val);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ Ch ch = *text;
+ *end = Ch('\0');
+ return ch; // Return character that ends data; this is required because zero terminator overwritten it
+ }
+
+ // Return character that ends data
+ return *text;
+ }
+
+ // Parse CDATA
+ template<int Flags>
+ xml_node<Ch> *parse_cdata(Ch *&text)
+ {
+ // If CDATA is disabled
+ if (Flags & parse_no_data_nodes)
+ {
+ // Skip until end of cdata
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip ]]>
+ return 0; // Do not produce CDATA node
+ }
+
+ // Skip until end of cdata
+ Ch *val = text;
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create new cdata node
+ xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+ cdata->value(val, text - val);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip ]]>
+ return cdata;
+ }
+
+ // Parse element node
+ template<int Flags>
+ xml_node<Ch> *parse_element(Ch *&text)
+ {
+ // Create element node
+ xml_node<Ch> *element = this->allocate_node(node_element);
+
+ // Extract element name
+ Ch *n = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == n)
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected element name", text);
+ element->name(n, text - n);
+
+ // Skip whitespace between element name and attributes or >
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse attributes, if any
+ parse_node_attributes<Flags>(text, element);
+
+ // Determine ending type
+ if (*text == Ch('>'))
+ {
+ ++text;
+ parse_node_contents<Flags>(text, element);
+ }
+ else if (*text == Ch('/'))
+ {
+ ++text;
+ if (*text != Ch('>'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text;
+ }
+ else
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text);
+
+ // Place zero terminator after name
+ if (!(Flags & parse_no_string_terminators))
+ element->name()[element->name_size()] = Ch('\0');
+
+ // Return parsed element
+ return element;
+ }
+
+ // Determine node type, and parse it
+ template<int Flags>
+ xml_node<Ch> *parse_node(Ch *&text)
+ {
+ // Parse proper node type
+ switch (text[0])
+ {
+
+ // <...
+ default:
+ // Parse and append element node
+ return parse_element<Flags>(text);
+
+ // <?...
+ case Ch('?'):
+ ++text; // Skip ?
+ if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+ (text[1] == Ch('m') || text[1] == Ch('M')) &&
+ (text[2] == Ch('l') || text[2] == Ch('L')) &&
+ whitespace_pred::test(text[3]))
+ {
+ // '<?xml ' - xml declaration
+ text += 4; // Skip 'xml '
+ return parse_xml_declaration<Flags>(text);
+ }
+ else
+ {
+ // Parse PI
+ return parse_pi<Flags>(text);
+ }
+
+ // <!...
+ case Ch('!'):
+
+ // Parse proper subset of <! node
+ switch (text[1])
+ {
+
+ // <!-
+ case Ch('-'):
+ if (text[2] == Ch('-'))
+ {
+ // '<!--' - xml comment
+ text += 3; // Skip '!--'
+ return parse_comment<Flags>(text);
+ }
+ break;
+
+ // <![
+ case Ch('['):
+ if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
+ text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+ {
+ // '<![CDATA[' - cdata
+ text += 8; // Skip '![CDATA['
+ return parse_cdata<Flags>(text);
+ }
+ break;
+
+ // <!D
+ case Ch('D'):
+ if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
+ text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
+ whitespace_pred::test(text[8]))
+ {
+ // '<!DOCTYPE ' - doctype
+ text += 9; // skip '!DOCTYPE '
+ return parse_doctype<Flags>(text);
+ }
+ break;
+
+ default: break;
+
+ } // switch
+
+ // Attempt to skip other, unrecognized node types starting with <!
+ ++text; // Skip !
+ while (*text != Ch('>'))
+ {
+ if (*text == 0)
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ ++text; // Skip '>'
+ return 0; // No node recognized
+
+ }
+ }
+
+ // Parse contents of the node - children, data etc.
+ template<int Flags>
+ void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all children and text
+ while (1)
+ {
+ // Skip whitespace between > and node contents
+ Ch *contents_start = text; // Store start of node contents before whitespace is skipped
+ if (Flags & parse_trim_whitespace)
+ skip<whitespace_pred, Flags>(text);
+ Ch next_char = *text;
+
+ // After data nodes, instead of continuing the loop, control jumps here.
+ // This is because zero termination inside parse_and_append_data() function
+ // would wreak havoc with the above code.
+ // Also, skipping whitespace after data nodes is unnecessary.
+ after_data_node:
+
+ // Determine what comes next: node closing, child node, data node, or 0?
+ switch (next_char)
+ {
+
+ // Node closing or child node
+ case Ch('<'):
+ if (text[1] == Ch('/'))
+ {
+ // Node closing
+ text += 2; // Skip '</'
+ if (Flags & parse_validate_closing_tags)
+ {
+ // Skip and validate closing tag name
+ Ch *closing_name = text;
+ skip<node_name_pred, Flags>(text);
+ if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+ }
+ else
+ {
+ // No validation, just skip name
+ skip<node_name_pred, Flags>(text);
+ }
+ // Skip remaining whitespace after node name
+ skip<whitespace_pred, Flags>(text);
+ if (*text != Ch('>'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text; // Skip '>'
+ return; // Node closed, finished parsing contents
+ }
+ else
+ {
+ // Child node
+ ++text; // Skip '<'
+ if (xml_node<Ch> *child = parse_node<Flags>(text))
+ node->append_node(child);
+ }
+ break;
+
+ // End of data - error
+ case Ch('\0'):
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Data node
+ default:
+ next_char = parse_and_append_data<Flags>(node, text, contents_start);
+ goto after_data_node; // Bypass regular processing after data nodes
+
+ }
+ }
+ }
+
+ // Parse XML attributes of the node
+ template<int Flags>
+ void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all attributes
+ while (attribute_name_pred::test(*text))
+ {
+ // Extract attribute name
+ Ch *n = text;
+ ++text; // Skip first character of attribute name
+ skip<attribute_name_pred, Flags>(text);
+ if (text == n)
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected attribute name", n);
+
+ // Create new attribute
+ xml_attribute<Ch> *attribute = this->allocate_attribute();
+ attribute->name(n, text - n);
+ node->append_attribute(attribute);
+
+ // Skip whitespace after attribute name
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip =
+ if (*text != Ch('='))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected =", text);
+ ++text;
+
+ // Add terminating zero after name
+ if (!(Flags & parse_no_string_terminators))
+ attribute->name()[attribute->name_size()] = 0;
+
+ // Skip whitespace after =
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip quote and remember if it was ' or "
+ Ch quote = *text;
+ if (quote != Ch('\'') && quote != Ch('"'))
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text;
+
+ // Extract attribute value and expand char refs in it
+ Ch *val = text, *end;
+ const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
+ if (quote == Ch('\''))
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+ else
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+
+ // Set attribute value
+ attribute->value(val, end - val);
+
+ // Make sure that end quote is present
+ if (*text != quote)
+ BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text; // Skip quote
+
+ // Add terminating zero after value
+ if (!(Flags & parse_no_string_terminators))
+ attribute->value()[attribute->value_size()] = 0;
+
+ // Skip whitespace after attribute value
+ skip<whitespace_pred, Flags>(text);
+ }
+ }
+
+ };
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Whitespace (space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
+ };
+
+ // Node name (anything but space \n \r \t / > ? \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) (anything but < \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+ // (anything but < \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+ // (anything but < \0 & space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote (anything but ' \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote that does not require processing (anything but ' \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote (anything but " \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote that does not require processing (anything but " \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Digits (dec and hex, 255 denotes end of numeric character reference)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F
+ };
+
+ // Upper case conversion
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
+ {
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F
+ };
+ }
+ //! \endcond
+
+}}}}
+
+// Undefine internal macros
+#undef BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_error.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_error.hpp
new file mode 100644
index 0000000..c79835c
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_error.hpp
@@ -0,0 +1,33 @@
+// ----------------------------------------------------------------------------
+// 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_XML_PARSER_ERROR_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_ERROR_HPP_INCLUDED
+
+#include <boost/property_tree/detail/file_parser_error.hpp>
+#include <string>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ //! Xml parser error
+ class xml_parser_error: public file_parser_error
+ {
+ public:
+ xml_parser_error(const std::string &msg,
+ const std::string &file,
+ unsigned long l):
+ file_parser_error(msg, file, l)
+ {
+ }
+ };
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_flags.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_flags.hpp
new file mode 100644
index 0000000..9340fe2
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_flags.hpp
@@ -0,0 +1,31 @@
+// ----------------------------------------------------------------------------
+// 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_XML_PARSER_FLAGS_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_FLAGS_HPP_INCLUDED
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ /// Text elements should be put in separate keys,
+ /// not concatenated in parent data.
+ static const int no_concat_text = 0x1;
+ /// Comments should be omitted.
+ static const int no_comments = 0x2;
+ /// Whitespace should be collapsed and trimmed.
+ static const int trim_whitespace = 0x4;
+
+ inline bool validate_flags(int flags)
+ {
+ return (flags & ~(no_concat_text | no_comments | trim_whitespace)) == 0;
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_read_rapidxml.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_read_rapidxml.hpp
new file mode 100644
index 0000000..acec34d9
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_read_rapidxml.hpp
@@ -0,0 +1,144 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2007 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_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/detail/xml_parser_error.hpp>
+#include <boost/property_tree/detail/xml_parser_flags.hpp>
+#include <boost/property_tree/detail/xml_parser_utils.hpp>
+#include <boost/property_tree/detail/rapidxml.hpp>
+#include <vector>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ template<class Ptree, class Ch>
+ void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
+ Ptree &pt, int flags)
+ {
+ using namespace detail::rapidxml;
+ switch (node->type())
+ {
+ // Element nodes
+ case node_element:
+ {
+ // Create node
+ Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
+ Ptree()))->second;
+
+ // Copy attributes
+ if (node->first_attribute())
+ {
+ Ptree &pt_attr_root = pt_node.push_back(
+ std::make_pair(xmlattr<Ch>(), Ptree()))->second;
+ for (xml_attribute<Ch> *attr = node->first_attribute();
+ attr; attr = attr->next_attribute())
+ {
+ Ptree &pt_attr = pt_attr_root.push_back(
+ std::make_pair(attr->name(), Ptree()))->second;
+ pt_attr.data() = attr->value();
+ }
+ }
+
+ // Copy children
+ for (xml_node<Ch> *child = node->first_node();
+ child; child = child->next_sibling())
+ read_xml_node(child, pt_node, flags);
+ }
+ break;
+
+ // Data nodes
+ case node_data:
+ case node_cdata:
+ {
+ if (flags & no_concat_text)
+ pt.push_back(std::make_pair(xmltext<Ch>(),
+ Ptree(node->value())));
+ else
+ pt.data() += node->value();
+ }
+ break;
+
+ // Comment nodes
+ case node_comment:
+ {
+ if (!(flags & no_comments))
+ pt.push_back(std::make_pair(xmlcomment<Ch>(),
+ Ptree(node->value())));
+ }
+ break;
+
+ default:
+ // Skip other node types
+ break;
+ }
+ }
+
+ template<class Ptree>
+ void read_xml_internal(std::basic_istream<
+ typename Ptree::key_type::value_type> &stream,
+ Ptree &pt,
+ int flags,
+ const std::string &filename)
+ {
+ typedef typename Ptree::key_type::value_type Ch;
+ using namespace detail::rapidxml;
+
+ // Load data into vector
+ stream.unsetf(std::ios::skipws);
+ std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
+ std::istreambuf_iterator<Ch>());
+ if (!stream.good())
+ BOOST_PROPERTY_TREE_THROW(
+ xml_parser_error("read error", filename, 0));
+ v.push_back(0); // zero-terminate
+
+ try {
+ // Parse using appropriate flags
+ const int f_tws = parse_normalize_whitespace
+ | parse_trim_whitespace;
+ const int f_c = parse_comment_nodes;
+ // Some compilers don't like the bitwise or in the template arg.
+ const int f_tws_c = parse_normalize_whitespace
+ | parse_trim_whitespace
+ | parse_comment_nodes;
+ xml_document<Ch> doc;
+ if (flags & no_comments) {
+ if (flags & trim_whitespace)
+ doc.BOOST_NESTED_TEMPLATE parse<f_tws>(&v.front());
+ else
+ doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
+ } else {
+ if (flags & trim_whitespace)
+ doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
+ else
+ doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
+ }
+
+ // Create ptree from nodes
+ Ptree local;
+ for (xml_node<Ch> *child = doc.first_node();
+ child; child = child->next_sibling())
+ read_xml_node(child, local, flags);
+
+ // Swap local and result ptrees
+ pt.swap(local);
+ } catch (parse_error &e) {
+ long line = static_cast<long>(
+ std::count(&v.front(), e.where<Ch>(), Ch('\n')) + 1);
+ BOOST_PROPERTY_TREE_THROW(
+ xml_parser_error(e.what(), filename, line));
+ }
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_utils.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_utils.hpp
new file mode 100644
index 0000000..7c8a6e1
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_utils.hpp
@@ -0,0 +1,136 @@
+// ----------------------------------------------------------------------------
+// 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_XML_PARSER_UTILS_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED
+
+#include <boost/property_tree/detail/ptree_utils.hpp>
+#include <boost/property_tree/detail/xml_parser_error.hpp>
+#include <boost/property_tree/detail/xml_parser_writer_settings.hpp>
+#include <string>
+#include <algorithm>
+#include <locale>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ template<class Ch>
+ std::basic_string<Ch> condense(const std::basic_string<Ch> &s)
+ {
+ std::basic_string<Ch> r;
+ std::locale loc;
+ bool space = false;
+ typename std::basic_string<Ch>::const_iterator end = s.end();
+ for (typename std::basic_string<Ch>::const_iterator it = s.begin();
+ it != end; ++it)
+ {
+ if (isspace(*it, loc) || *it == Ch('\n'))
+ {
+ if (!space)
+ r += Ch(' '), space = true;
+ }
+ else
+ r += *it, space = false;
+ }
+ return r;
+ }
+
+ template<class Ch>
+ std::basic_string<Ch> encode_char_entities(const std::basic_string<Ch> &s)
+ {
+ // Don't do anything for empty strings.
+ if(s.empty()) return s;
+
+ typedef typename std::basic_string<Ch> Str;
+ Str r;
+ // To properly round-trip spaces and not uglify the XML beyond
+ // recognition, we have to encode them IF the text contains only spaces.
+ Str sp(1, Ch(' '));
+ if(s.find_first_not_of(sp) == Str::npos) {
+ // The first will suffice.
+ r = detail::widen<Ch>("&#32;");
+ r += Str(s.size() - 1, Ch(' '));
+ } else {
+ typename Str::const_iterator end = s.end();
+ for (typename Str::const_iterator it = s.begin(); it != end; ++it)
+ {
+ switch (*it)
+ {
+ case Ch('<'): r += detail::widen<Ch>("&lt;"); break;
+ case Ch('>'): r += detail::widen<Ch>("&gt;"); break;
+ case Ch('&'): r += detail::widen<Ch>("&amp;"); break;
+ case Ch('"'): r += detail::widen<Ch>("&quot;"); break;
+ case Ch('\''): r += detail::widen<Ch>("&apos;"); break;
+ default: r += *it; break;
+ }
+ }
+ }
+ return r;
+ }
+
+ template<class Ch>
+ std::basic_string<Ch> decode_char_entities(const std::basic_string<Ch> &s)
+ {
+ typedef typename std::basic_string<Ch> Str;
+ Str r;
+ typename Str::const_iterator end = s.end();
+ for (typename Str::const_iterator it = s.begin(); it != end; ++it)
+ {
+ if (*it == Ch('&'))
+ {
+ typename Str::const_iterator semicolon = std::find(it + 1, end, Ch(';'));
+ if (semicolon == end)
+ BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0));
+ Str ent(it + 1, semicolon);
+ if (ent == detail::widen<Ch>("lt")) r += Ch('<');
+ else if (ent == detail::widen<Ch>("gt")) r += Ch('>');
+ else if (ent == detail::widen<Ch>("amp")) r += Ch('&');
+ else if (ent == detail::widen<Ch>("quot")) r += Ch('"');
+ else if (ent == detail::widen<Ch>("apos")) r += Ch('\'');
+ else
+ BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0));
+ it = semicolon;
+ }
+ else
+ r += *it;
+ }
+ return r;
+ }
+
+ template<class Ch>
+ const std::basic_string<Ch> &xmldecl()
+ {
+ static std::basic_string<Ch> s = detail::widen<Ch>("<?xml>");
+ return s;
+ }
+
+ template<class Ch>
+ const std::basic_string<Ch> &xmlattr()
+ {
+ static std::basic_string<Ch> s = detail::widen<Ch>("<xmlattr>");
+ return s;
+ }
+
+ template<class Ch>
+ const std::basic_string<Ch> &xmlcomment()
+ {
+ static std::basic_string<Ch> s = detail::widen<Ch>("<xmlcomment>");
+ return s;
+ }
+
+ template<class Ch>
+ const std::basic_string<Ch> &xmltext()
+ {
+ static std::basic_string<Ch> s = detail::widen<Ch>("<xmltext>");
+ return s;
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_write.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_write.hpp
new file mode 100644
index 0000000..614854e
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_write.hpp
@@ -0,0 +1,194 @@
+// ----------------------------------------------------------------------------
+// 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_XML_PARSER_WRITE_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITE_HPP_INCLUDED
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/detail/xml_parser_utils.hpp>
+#include <string>
+#include <ostream>
+#include <iomanip>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+ template<class Ch>
+ void write_xml_indent(std::basic_ostream<Ch> &stream,
+ int indent,
+ const xml_writer_settings<Ch> & settings
+ )
+ {
+ stream << std::basic_string<Ch>(indent * settings.indent_count, settings.indent_char);
+ }
+
+ template<class Ch>
+ void write_xml_comment(std::basic_ostream<Ch> &stream,
+ const std::basic_string<Ch> &s,
+ int indent,
+ bool separate_line,
+ const xml_writer_settings<Ch> & settings
+ )
+ {
+ typedef typename std::basic_string<Ch> Str;
+ if (separate_line)
+ write_xml_indent(stream,indent,settings);
+ stream << Ch('<') << Ch('!') << Ch('-') << Ch('-');
+ stream << s;
+ stream << Ch('-') << Ch('-') << Ch('>');
+ if (separate_line)
+ stream << Ch('\n');
+ }
+
+ template<class Ch>
+ void write_xml_text(std::basic_ostream<Ch> &stream,
+ const std::basic_string<Ch> &s,
+ int indent,
+ bool separate_line,
+ const xml_writer_settings<Ch> & settings
+ )
+ {
+ if (separate_line)
+ write_xml_indent(stream,indent,settings);
+ stream << encode_char_entities(s);
+ if (separate_line)
+ stream << Ch('\n');
+ }
+
+ template<class Ptree>
+ void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
+ const std::basic_string<typename Ptree::key_type::value_type> &key,
+ const Ptree &pt,
+ int indent,
+ const xml_writer_settings<typename Ptree::key_type::value_type> & settings)
+ {
+
+ typedef typename Ptree::key_type::value_type Ch;
+ typedef typename std::basic_string<Ch> Str;
+ typedef typename Ptree::const_iterator It;
+
+ bool want_pretty = settings.indent_count > 0;
+ // Find if elements present
+ bool has_elements = false;
+ bool has_attrs_only = pt.data().empty();
+ for (It it = pt.begin(), end = pt.end(); it != end; ++it)
+ {
+ if (it->first != xmlattr<Ch>() )
+ {
+ has_attrs_only = false;
+ if (it->first != xmltext<Ch>())
+ {
+ has_elements = true;
+ break;
+ }
+ }
+ }
+
+ // Write element
+ if (pt.data().empty() && pt.empty()) // Empty key
+ {
+ if (indent >= 0)
+ {
+ write_xml_indent(stream,indent,settings);
+ stream << Ch('<') << key <<
+ Ch('/') << Ch('>');
+ if (want_pretty)
+ stream << Ch('\n');
+ }
+ }
+ else // Nonempty key
+ {
+
+ // Write opening tag, attributes and data
+ if (indent >= 0)
+ {
+
+ // Write opening brace and key
+ write_xml_indent(stream,indent,settings);
+ stream << Ch('<') << key;
+
+ // Write attributes
+ if (optional<const Ptree &> attribs = pt.get_child_optional(xmlattr<Ch>()))
+ for (It it = attribs.get().begin(); it != attribs.get().end(); ++it)
+ stream << Ch(' ') << it->first << Ch('=') <<
+ Ch('"') << it->second.template get_value<std::basic_string<Ch> >() << Ch('"');
+
+ if ( has_attrs_only )
+ {
+ // Write closing brace
+ stream << Ch('/') << Ch('>');
+ if (want_pretty)
+ stream << Ch('\n');
+ }
+ else
+ {
+ // Write closing brace
+ stream << Ch('>');
+
+ // Break line if needed and if we want pretty-printing
+ if (has_elements && want_pretty)
+ stream << Ch('\n');
+ }
+ }
+
+ // Write data text, if present
+ if (!pt.data().empty())
+ write_xml_text(stream,
+ pt.template get_value<std::basic_string<Ch> >(),
+ indent + 1, has_elements && want_pretty, settings);
+
+ // Write elements, comments and texts
+ for (It it = pt.begin(); it != pt.end(); ++it)
+ {
+ if (it->first == xmlattr<Ch>())
+ continue;
+ else if (it->first == xmlcomment<Ch>())
+ write_xml_comment(stream,
+ it->second.template get_value<std::basic_string<Ch> >(),
+ indent + 1, want_pretty, settings);
+ else if (it->first == xmltext<Ch>())
+ write_xml_text(stream,
+ it->second.template get_value<std::basic_string<Ch> >(),
+ indent + 1, has_elements && want_pretty, settings);
+ else
+ write_xml_element(stream, it->first, it->second,
+ indent + 1, settings);
+ }
+
+ // Write closing tag
+ if (indent >= 0 && !has_attrs_only)
+ {
+ if (has_elements)
+ write_xml_indent(stream,indent,settings);
+ stream << Ch('<') << Ch('/') << key << Ch('>');
+ if (want_pretty)
+ stream << Ch('\n');
+ }
+
+ }
+ }
+
+ template<class Ptree>
+ void write_xml_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
+ const Ptree &pt,
+ const std::string &filename,
+ const xml_writer_settings<typename Ptree::key_type::value_type> & settings)
+ {
+ typedef typename Ptree::key_type::value_type Ch;
+ typedef typename std::basic_string<Ch> Str;
+ stream << detail::widen<Ch>("<?xml version=\"1.0\" encoding=\"")
+ << settings.encoding
+ << detail::widen<Ch>("\"?>\n");
+ write_xml_element(stream, Str(), pt, -1, settings);
+ if (!stream)
+ BOOST_PROPERTY_TREE_THROW(xml_parser_error("write error", filename, 0));
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_writer_settings.hpp b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_writer_settings.hpp
new file mode 100644
index 0000000..f22d85e
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/detail/xml_parser_writer_settings.hpp
@@ -0,0 +1,62 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2002-2007 Marcin Kalicinski
+// Copyright (C) 2007 Alexey Baskakov
+//
+// 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_XML_PARSER_WRITER_SETTINGS_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITER_SETTINGS_HPP_INCLUDED
+
+#include <string>
+#include <boost/property_tree/detail/ptree_utils.hpp>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ // Naively convert narrow string to another character type
+ template<class Ch>
+ std::basic_string<Ch> widen(const char *text)
+ {
+ std::basic_string<Ch> result;
+ while (*text)
+ {
+ result += Ch(*text);
+ ++text;
+ }
+ return result;
+ }
+
+ //! Xml writer settings. The default settings lead to no pretty printing.
+ template<class Ch>
+ class xml_writer_settings
+ {
+ public:
+ xml_writer_settings(Ch inchar = Ch(' '),
+ typename std::basic_string<Ch>::size_type incount = 0,
+ const std::basic_string<Ch> &enc = widen<Ch>("utf-8"))
+ : indent_char(inchar)
+ , indent_count(incount)
+ , encoding(enc)
+ {
+ }
+
+ Ch indent_char;
+ typename std::basic_string<Ch>::size_type indent_count;
+ std::basic_string<Ch> encoding;
+ };
+
+ template <class Ch>
+ xml_writer_settings<Ch> xml_writer_make_settings(Ch indent_char = Ch(' '),
+ typename std::basic_string<Ch>::size_type indent_count = 0,
+ const std::basic_string<Ch> &encoding = widen<Ch>("utf-8"))
+ {
+ return xml_writer_settings<Ch>(indent_char, indent_count, encoding);
+ }
+
+} } }
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/exceptions.hpp b/3rdParty/Boost/src/boost/property_tree/exceptions.hpp
new file mode 100644
index 0000000..42e2cbd
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/exceptions.hpp
@@ -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
diff --git a/3rdParty/Boost/src/boost/property_tree/id_translator.hpp b/3rdParty/Boost/src/boost/property_tree/id_translator.hpp
new file mode 100644
index 0000000..02fdf44
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/id_translator.hpp
@@ -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
diff --git a/3rdParty/Boost/src/boost/property_tree/ptree.hpp b/3rdParty/Boost/src/boost/property_tree/ptree.hpp
new file mode 100644
index 0000000..243a9b6
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/ptree.hpp
@@ -0,0 +1,517 @@
+// ----------------------------------------------------------------------------
+// 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_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
+
+namespace boost { namespace property_tree
+{
+
+ /**
+ * Property tree main structure. A property tree is a hierarchical data
+ * structure which has one element of type @p Data in each node, as well
+ * as an ordered sequence of sub-nodes, which are additionally identified
+ * by a non-unique key of type @p Key.
+ *
+ * Key equivalency is defined by @p KeyCompare, a predicate defining a
+ * strict weak ordering.
+ *
+ * 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 basic_ptree
+ {
+#if defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED)
+ public:
+#endif
+ // Internal types
+ /**
+ * 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> self_type;
+
+ public:
+ // Basic types
+ typedef Key key_type;
+ typedef Data data_type;
+ typedef KeyCompare key_compare;
+
+ // Container view types
+ typedef std::pair<const Key, self_type> value_type;
+ typedef std::size_t size_type;
+
+ // 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
+ class assoc_iterator;
+ class const_assoc_iterator;
+
+ // Property tree view types
+ typedef typename path_of<Key>::type path_type;
+
+
+ // The big five
+
+ /** Creates a node with no children and default-constructed data. */
+ basic_ptree();
+ /** Creates a node with no children and a copy of the given data. */
+ 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);
+
+ /** Swap with other tree. Only constant-time and nothrow if the
+ * data type's swap is.
+ */
+ void swap(self_type &rhs);
+
+ // Container view functions
+
+ /** The number of direct children of this node. */
+ size_type size() const;
+ size_type max_size() const;
+ /** Whether there are any direct children. */
+ bool empty() const;
+
+ iterator begin();
+ const_iterator begin() const;
+ iterator end();
+ const_iterator end() const;
+ reverse_iterator rbegin();
+ const_reverse_iterator rbegin() const;
+ reverse_iterator rend();
+ const_reverse_iterator rend() const;
+
+ value_type &front();
+ const value_type &front() const;
+ value_type &back();
+ const value_type &back() const;
+
+ /** Insert a copy of the given tree with its key just before the given
+ * position in this node. This operation invalidates no iterators.
+ * @return An iterator to the newly created child.
+ */
+ iterator insert(iterator where, const value_type &value);
+
+ /** Range insert. Equivalent to:
+ * @code
+ * for(; first != last; ++first) insert(where, *first);
+ * @endcode
+ */
+ template<class It> void insert(iterator where, It first, It last);
+
+ /** Erase the child pointed at by the iterator. This operation
+ * invalidates the given iterator, as well as its equivalent
+ * assoc_iterator.
+ * @return A valid iterator pointing to the element after the erased.
+ */
+ iterator erase(iterator where);
+
+ /** Range erase. Equivalent to:
+ * @code
+ * while(first != last;) first = erase(first);
+ * @endcode
+ */
+ iterator erase(iterator first, iterator last);
+
+ /** Equivalent to insert(begin(), value). */
+ iterator push_front(const value_type &value);
+
+ /** Equivalent to insert(end(), value). */
+ iterator push_back(const value_type &value);
+
+ /** Equivalent to erase(begin()). */
+ void pop_front();
+
+ /** Equivalent to erase(boost::prior(end())). */
+ void pop_back();
+
+ /** Reverses the order of direct children in the property tree. */
+ void reverse();
+
+ /** Sorts the direct children of this node according to the predicate.
+ * The predicate is passed the whole pair of key and child.
+ */
+ template<class Compare> void sort(Compare comp);
+
+ /** Sorts the direct children of this node according to key order. */
+ void sort();
+
+ // Equality
+
+ /** Two property trees are the same if they have the same data, the keys
+ * and order of their children are the same, and the children compare
+ * equal, recursively.
+ */
+ bool operator ==(const self_type &rhs) const;
+ bool operator !=(const self_type &rhs) const;
+
+ // Associative view
+
+ /** Returns an iterator to the first child, in order. */
+ assoc_iterator ordered_begin();
+ /** Returns an iterator to the first child, in order. */
+ const_assoc_iterator ordered_begin() const;
+
+ /** Returns the not-found iterator. Equivalent to end() in a real
+ * associative container.
+ */
+ assoc_iterator not_found();
+ /** Returns the not-found iterator. Equivalent to end() in a real
+ * associative container.
+ */
+ const_assoc_iterator not_found() const;
+
+ /** Find a child with the given key, or not_found() if there is none.
+ * There is no guarantee about which child is returned if multiple have
+ * the same key.
+ */
+ assoc_iterator find(const key_type &key);
+
+ /** Find a child with the given key, or not_found() if there is none.
+ * There is no guarantee about which child is returned if multiple have
+ * the same key.
+ */
+ const_assoc_iterator find(const key_type &key) const;
+
+ /** Find the range of children that have the given key. */
+ std::pair<assoc_iterator, assoc_iterator>
+ equal_range(const key_type &key);
+
+ /** Find the range of children that have the given key. */
+ std::pair<const_assoc_iterator, const_assoc_iterator>
+ equal_range(const key_type &key) const;
+
+ /** 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 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
+ * (to_iterator(a), to_iterator(b)) is a valid range.
+ */
+ iterator to_iterator(assoc_iterator it);
+
+ /** Get the iterator that points to the same element as the argument.
+ * @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;
+
+ // Property tree view
+
+ /** Reference to the actual data in this node. */
+ data_type &data();
+
+ /** Reference to the actual data in this node. */
+ const data_type &data() const;
+
+ /** Clear this tree completely, of both data and children. */
+ void clear();
+
+ /** Get the child at the given path, or throw @c ptree_bad_path.
+ * @note Depending on the path, the result at each level may not be
+ * completely determinate, i.e. if the same key appears multiple
+ * times, which child is chosen is not specified. This can lead
+ * to the path not being resolved even though there is a
+ * descendant with this path. Example:
+ * @code
+ * a -> b -> c
+ * -> b
+ * @endcode
+ * The path "a.b.c" will succeed if the resolution of "b" chooses
+ * the first such node, but fail if it chooses the second.
+ */
+ self_type &get_child(const path_type &path);
+
+ /** Get the child at the given path, or throw @c ptree_bad_path. */
+ const self_type &get_child(const path_type &path) const;
+
+ /** Get the child at the given path, or return @p default_value. */
+ self_type &get_child(const path_type &path, self_type &default_value);
+
+ /** Get the child at the given path, or return @p default_value. */
+ const self_type &get_child(const path_type &path,
+ const self_type &default_value) const;
+
+ /** Get the child at the given path, or return boost::null. */
+ optional<self_type &> get_child_optional(const path_type &path);
+
+ /** Get the child at the given path, or return boost::null. */
+ optional<const self_type &>
+ get_child_optional(const path_type &path) const;
+
+ /** Set the node at the given path to the given value. Create any
+ * missing parents. If the node at the path already exists, replace it.
+ * @return A reference to the inserted subtree.
+ * @note Because of the way paths work, it is not generally guaranteed
+ * that a node newly created can be accessed using the same path.
+ * @note If the path could refer to multiple nodes, it is unspecified
+ * which one gets replaced.
+ */
+ self_type &put_child(const path_type &path, const self_type &value);
+
+ /** Add the node at the given path. Create any missing parents. If there
+ * already is a node at the path, add another one with the same key.
+ * @param path Path to the child. The last fragment must not have an
+ * index.
+ * @return A reference to the inserted subtree.
+ * @note Because of the way paths work, it is not generally guaranteed
+ * that a node newly created can be accessed using the same path.
+ */
+ self_type &add_child(const path_type &path, const self_type &value);
+
+ /** Take the value of this node and attempt to translate it to a
+ * @c Type object using the supplied translator.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type, class Translator>
+ 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.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type>
+ Type get_value() const;
+
+ /** Take the value of this node and attempt to translate it to a
+ * @c Type object using the supplied translator. Return @p default_value
+ * if this fails.
+ */
+ 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>
+ 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
+ * this fails.
+ */
+ template<class Type, class Translator>
+ optional<Type> get_value_optional(Translator tr) const;
+
+ /** Take the value of this node and attempt to translate it to a
+ * @c Type object using the default translator. Return boost::null if
+ * this fails.
+ */
+ template<class Type>
+ optional<Type> get_value_optional() const;
+
+ /** Replace the value at this node with the given value, translated
+ * to the tree's data type using the supplied translator.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type, class Translator>
+ void put_value(const Type &value, Translator tr);
+
+ /** Replace the value at this node with the given value, translated
+ * to the tree's data type using the default translator.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type>
+ void put_value(const Type &value);
+
+ /** Shorthand for get_child(path).get_value(tr). */
+ template<class Type, class Translator>
+ 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>
+ Type get(const path_type &path) const;
+
+ /** Shorthand for get_child(path, empty_ptree())
+ * .get_value(default_value, tr).
+ * That is, return the translated value if possible, and the default
+ * value if the node doesn't exist or conversion fails.
+ */
+ template<class Type, class Translator>
+ Type get(const path_type &path,
+ 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>
+ 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
+ * if(optional\<self_type&\> node = get_child_optional(path))
+ * 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>
+ optional<Type> get_optional(const path_type &path, Translator tr) const;
+
+ /** Shorthand for:
+ * @code
+ * if(optional\<const self_type&\> node = get_child_optional(path))
+ * return node->get_value_optional();
+ * return boost::null;
+ * @endcode
+ */
+ template<class Type>
+ 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
+ * created, including all its missing parents.
+ * @return The node that had its value changed.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type, class Translator>
+ self_type &put(const path_type &path, const Type &value, Translator tr);
+
+ /** 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
+ * created, including all its missing parents.
+ * @return The node that had its value changed.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type>
+ self_type &put(const path_type &path, const Type &value);
+
+ /** If the node identified by the path does not exist, create it,
+ * including all its missing parents.
+ * If the node already exists, add a sibling with the same key.
+ * Set the newly created node's value to the given paremeter,
+ * translated with the supplied translator.
+ * @param path Path to the child. The last fragment must not have an
+ * index.
+ * @param value The value to add.
+ * @param tr The translator to use.
+ * @return The node that was added.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type, class Translator>
+ self_type &add(const path_type &path,
+ const Type &value,
+ Translator tr);
+
+ /** If the node identified by the path does not exist, create it,
+ * including all its missing parents.
+ * If the node already exists, add a sibling with the same key.
+ * Set the newly created node's value to the given paremeter,
+ * translated with the supplied translator.
+ * @param path Path to the child. The last fragment must not have an
+ * index.
+ * @param value The value to add.
+ * @return The node that was added.
+ * @throw ptree_bad_data if the conversion fails.
+ */
+ template<class Type>
+ self_type &add(const path_type &path, const Type &value);
+
+ private:
+ // Hold the data of this node
+ data_type m_data;
+ // 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.
+ self_type* walk_path(path_type& p) const;
+
+ // Modifer tree-walk. Gets the parent of the node referred to by the
+ // 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 <boost/property_tree/detail/ptree_implementation.hpp>
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/ptree_fwd.hpp b/3rdParty/Boost/src/boost/property_tree/ptree_fwd.hpp
new file mode 100644
index 0000000..fe36741
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/ptree_fwd.hpp
@@ -0,0 +1,143 @@
+// ----------------------------------------------------------------------------
+// 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_PTREE_FWD_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_PTREE_FWD_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/optional/optional_fwd.hpp>
+#include <boost/throw_exception.hpp>
+#include <functional> // for std::less
+#include <memory> // for std::allocator
+#include <string>
+
+namespace boost { namespace property_tree
+{
+ namespace detail {
+ template <typename T> struct less_nocase;
+ }
+
+ // Classes
+
+ template < class Key, class Data, class KeyCompare = std::less<Key> >
+ class basic_ptree;
+
+ template <typename T>
+ struct id_translator;
+
+ template <typename String, typename Translator>
+ class string_path;
+
+ // Texas-style concepts for documentation only.
+#if 0
+ 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() const;
+
+ // 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<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
+ /// type must conform to the Path concept described in the documentation.
+ /// This is already specialized for std::basic_string.
+ template <typename Key>
+ struct path_of;
+
+ /// Specialize this struct to specify a default translator between the data
+ /// 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 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<std::string> > path;
+
+ /**
+ * A property tree with std::string for key and data, and default
+ * comparison.
+ */
+ typedef basic_ptree<std::string, std::string> ptree;
+
+ /**
+ * A property tree with std::string for key and data, and case-insensitive
+ * comparison.
+ */
+ typedef basic_ptree<std::string, std::string,
+ detail::less_nocase<std::string> >
+ iptree;
+
+#ifndef BOOST_NO_STD_WSTRING
+ /** Implements a path using a std::wstring as the key. */
+ typedef string_path<std::wstring, id_translator<std::wstring> > wpath;
+
+ /**
+ * A property tree with std::wstring for key and data, and default
+ * comparison.
+ * @note The type only exists if the platform supports @c wchar_t.
+ */
+ typedef basic_ptree<std::wstring, std::wstring> wptree;
+
+ /**
+ * A property tree with std::wstring for key and data, and case-insensitive
+ * comparison.
+ * @note The type only exists if the platform supports @c wchar_t.
+ */
+ typedef basic_ptree<std::wstring, std::wstring,
+ detail::less_nocase<std::wstring> >
+ wiptree;
+#endif
+
+ // Free functions
+
+ /**
+ * Swap two property tree instances.
+ */
+ 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) BOOST_THROW_EXCEPTION(e)
+#endif
+
+#endif
diff --git a/3rdParty/Boost/src/boost/property_tree/stream_translator.hpp b/3rdParty/Boost/src/boost/property_tree/stream_translator.hpp
new file mode 100644
index 0000000..c7fabfa
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/stream_translator.hpp
@@ -0,0 +1,221 @@
+// ----------------------------------------------------------------------------
+// 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 <boost/type_traits/integral_constant.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;
+ }
+ };
+
+ // Ugly workaround for numeric_traits that don't have members when not
+ // specialized, e.g. MSVC.
+ namespace detail
+ {
+ template <bool is_specialized>
+ struct is_inexact_impl
+ {
+ template <typename T>
+ struct test
+ {
+ typedef boost::false_type type;
+ };
+ };
+ template <>
+ struct is_inexact_impl<true>
+ {
+ template <typename T>
+ struct test
+ {
+ typedef boost::integral_constant<bool,
+ !std::numeric_limits<T>::is_exact> type;
+ };
+ };
+
+ template <typename F>
+ struct is_inexact
+ {
+ typedef typename boost::decay<F>::type decayed;
+ typedef typename is_inexact_impl<
+ std::numeric_limits<decayed>::is_specialized
+ >::BOOST_NESTED_TEMPLATE test<decayed>::type type;
+ static const bool value = type::value;
+ };
+ }
+
+ template <typename Ch, typename Traits, typename F>
+ struct customize_stream<Ch, Traits, F,
+ typename boost::enable_if< detail::is_inexact<F> >::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
diff --git a/3rdParty/Boost/src/boost/property_tree/string_path.hpp b/3rdParty/Boost/src/boost/property_tree/string_path.hpp
new file mode 100644
index 0000000..07ec6b0
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/string_path.hpp
@@ -0,0 +1,273 @@
+// ----------------------------------------------------------------------------
+// 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>
+#include <cassert>
+
+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>
+ inline std::string dump_sequence(const Sequence &)
+ {
+ return "<undumpable sequence>";
+ }
+ inline std::string dump_sequence(const std::string &s)
+ {
+ return s;
+ }
+#ifndef BOOST_NO_STD_WSTRING
+ inline std::string dump_sequence(const std::wstring &s)
+ {
+ return narrow(s.c_str());
+ }
+#endif
+ }
+
+ /// 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.
+ explicit string_path(char_type separator = char_type('.'));
+ /// 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(char_type separator)
+ : m_separator(separator), 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
diff --git a/3rdParty/Boost/src/boost/property_tree/xml_parser.hpp b/3rdParty/Boost/src/boost/property_tree/xml_parser.hpp
new file mode 100644
index 0000000..4f36e9a
--- /dev/null
+++ b/3rdParty/Boost/src/boost/property_tree/xml_parser.hpp
@@ -0,0 +1,153 @@
+// ----------------------------------------------------------------------------
+// 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_XML_PARSER_HPP_INCLUDED
+#define BOOST_PROPERTY_TREE_XML_PARSER_HPP_INCLUDED
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/detail/xml_parser_write.hpp>
+#include <boost/property_tree/detail/xml_parser_error.hpp>
+#include <boost/property_tree/detail/xml_parser_writer_settings.hpp>
+#include <boost/property_tree/detail/xml_parser_flags.hpp>
+#include <boost/property_tree/detail/xml_parser_read_rapidxml.hpp>
+
+#include <fstream>
+#include <string>
+#include <locale>
+
+namespace boost { namespace property_tree { namespace xml_parser
+{
+
+ /**
+ * Reads XML from an input stream and translates it to property tree.
+ * @note Clears existing contents of property tree. In case of error the
+ * property tree unmodified.
+ * @note XML attributes are placed under keys named @c \<xmlattr\>.
+ * @throw xml_parser_error In case of error deserializing the property tree.
+ * @param stream Stream from which to read in the property tree.
+ * @param[out] pt The property tree to populate.
+ * @param flags Flags controlling the behaviour of the parser.
+ * The following flags are supported:
+ * @li @c no_concat_text -- Prevents concatenation of text nodes into
+ * datastring of property tree. Puts them in
+ * separate @c \<xmltext\> strings instead.
+ * @li @c no_comments -- Skip XML comments.
+ * @li @c trim_whitespace -- Trim leading and trailing whitespace from text,
+ * and collapse sequences of whitespace.
+ */
+ template<class Ptree>
+ void read_xml(std::basic_istream<
+ typename Ptree::key_type::value_type
+ > &stream,
+ Ptree &pt,
+ int flags = 0)
+ {
+ read_xml_internal(stream, pt, flags, std::string());
+ }
+
+ /**
+ * Reads XML from a file using the given locale and translates it to
+ * property tree.
+ * @note Clears existing contents of property tree. In case of error the
+ * property tree unmodified.
+ * @note XML attributes are placed under keys named @c \<xmlattr\>.
+ * @throw xml_parser_error In case of error deserializing the property tree.
+ * @param filename The file from which to read in the property tree.
+ * @param[out] pt The property tree to populate.
+ * @param flags Flags controlling the bahviour of the parser.
+ * The following flags are supported:
+ * @li @c no_concat_text -- Prevents concatenation of text nodes into
+ * datastring of property tree. Puts them in
+ * separate @c \<xmltext\> strings instead.
+ * @li @c no_comments -- Skip XML comments.
+ * @param loc The locale to use when reading in the file contents.
+ */
+ template<class Ptree>
+ void read_xml(const std::string &filename,
+ Ptree &pt,
+ int flags = 0,
+ const std::locale &loc = std::locale())
+ {
+ BOOST_ASSERT(validate_flags(flags));
+ std::basic_ifstream<typename Ptree::key_type::value_type>
+ stream(filename.c_str());
+ if (!stream)
+ BOOST_PROPERTY_TREE_THROW(xml_parser_error(
+ "cannot open file", filename, 0));
+ stream.imbue(loc);
+ read_xml_internal(stream, pt, flags, filename);
+ }
+
+ /**
+ * Translates the property tree to XML and writes it the given output
+ * stream.
+ * @throw xml_parser_error In case of error translating the property tree to
+ * XML or writing to the output stream.
+ * @param stream The stream to which to write the XML representation of the
+ * property tree.
+ * @param pt The property tree to tranlsate to XML and output.
+ * @param settings The settings to use when writing out the property tree as
+ * XML.
+ */
+ template<class Ptree>
+ void write_xml(std::basic_ostream<
+ typename Ptree::key_type::value_type
+ > &stream,
+ const Ptree &pt,
+ const xml_writer_settings<
+ typename Ptree::key_type::value_type
+ > & settings = xml_writer_settings<
+ typename Ptree::key_type::value_type>() )
+ {
+ write_xml_internal(stream, pt, std::string(), settings);
+ }
+
+ /**
+ * Translates the property tree to XML and writes it the given file.
+ * @throw xml_parser_error In case of error translating the property tree to
+ * XML or writing to the output stream.
+ * @param filename The file to which to write the XML representation of the
+ * property tree.
+ * @param pt The property tree to tranlsate to XML and output.
+ * @param loc The locale to use when writing the output to file.
+ * @param settings The settings to use when writing out the property tree as
+ * XML.
+ */
+ template<class Ptree>
+ void write_xml(const std::string &filename,
+ const Ptree &pt,
+ const std::locale &loc = std::locale(),
+ const xml_writer_settings<
+ typename Ptree::key_type::value_type
+ > & settings = xml_writer_settings<
+ typename Ptree::key_type::value_type>())
+ {
+ std::basic_ofstream<typename Ptree::key_type::value_type>
+ stream(filename.c_str());
+ if (!stream)
+ BOOST_PROPERTY_TREE_THROW(xml_parser_error(
+ "cannot open file", filename, 0));
+ stream.imbue(loc);
+ write_xml_internal(stream, pt, filename, settings);
+ }
+
+} } }
+
+namespace boost { namespace property_tree
+{
+ using xml_parser::read_xml;
+ using xml_parser::write_xml;
+ using xml_parser::xml_parser_error;
+
+ using xml_parser::xml_writer_settings;
+ using xml_parser::xml_writer_make_settings;
+} }
+
+#endif