| // ---------------------------------------------------------------------------- |
| // 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 |