Chris@16: // ---------------------------------------------------------------------------- Chris@16: // Copyright (C) 2002-2006 Marcin Kalicinski Chris@16: // Copyright (C) 2009 Sebastian Redl Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // For more information, see www.boost.org Chris@16: // ---------------------------------------------------------------------------- Chris@16: Chris@16: #ifndef BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED Chris@16: #define BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // for std::pair Chris@16: Chris@16: namespace boost { namespace property_tree Chris@16: { Chris@16: Chris@16: /** Chris@16: * Property tree main structure. A property tree is a hierarchical data Chris@16: * structure which has one element of type @p Data in each node, as well Chris@16: * as an ordered sequence of sub-nodes, which are additionally identified Chris@16: * by a non-unique key of type @p Key. Chris@16: * Chris@16: * Key equivalency is defined by @p KeyCompare, a predicate defining a Chris@16: * strict weak ordering. Chris@16: * Chris@16: * Property tree defines a Container-like interface to the (key-node) pairs Chris@16: * of its direct sub-nodes. The iterators are bidirectional. The sequence Chris@16: * of nodes is held in insertion order, not key order. Chris@16: */ Chris@16: template Chris@16: class basic_ptree Chris@16: { Chris@16: #if defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED) Chris@16: public: Chris@16: #endif Chris@16: // Internal types Chris@16: /** Chris@16: * Simpler way to refer to this basic_ptree\ type. Chris@16: * Note that this is private, and made public only for doxygen. Chris@16: */ Chris@16: typedef basic_ptree self_type; Chris@16: Chris@16: public: Chris@16: // Basic types Chris@16: typedef Key key_type; Chris@16: typedef Data data_type; Chris@16: typedef KeyCompare key_compare; Chris@16: Chris@16: // Container view types Chris@16: typedef std::pair value_type; Chris@16: typedef std::size_t size_type; Chris@16: Chris@16: // The problem with the iterators is that I can't make them complete Chris@16: // until the container is complete. Sucks. Especially for the reverses. Chris@16: class iterator; Chris@16: class const_iterator; Chris@16: class reverse_iterator; Chris@16: class const_reverse_iterator; Chris@16: Chris@16: // Associative view types Chris@16: class assoc_iterator; Chris@16: class const_assoc_iterator; Chris@16: Chris@16: // Property tree view types Chris@16: typedef typename path_of::type path_type; Chris@16: Chris@16: Chris@16: // The big five Chris@16: Chris@16: /** Creates a node with no children and default-constructed data. */ Chris@16: basic_ptree(); Chris@16: /** Creates a node with no children and a copy of the given data. */ Chris@16: explicit basic_ptree(const data_type &data); Chris@16: basic_ptree(const self_type &rhs); Chris@16: ~basic_ptree(); Chris@16: /** Basic guarantee only. */ Chris@16: self_type &operator =(const self_type &rhs); Chris@16: Chris@16: /** Swap with other tree. Only constant-time and nothrow if the Chris@16: * data type's swap is. Chris@16: */ Chris@16: void swap(self_type &rhs); Chris@16: Chris@16: // Container view functions Chris@16: Chris@16: /** The number of direct children of this node. */ Chris@16: size_type size() const; Chris@16: size_type max_size() const; Chris@16: /** Whether there are any direct children. */ Chris@16: bool empty() const; Chris@16: Chris@16: iterator begin(); Chris@16: const_iterator begin() const; Chris@16: iterator end(); Chris@16: const_iterator end() const; Chris@16: reverse_iterator rbegin(); Chris@16: const_reverse_iterator rbegin() const; Chris@16: reverse_iterator rend(); Chris@16: const_reverse_iterator rend() const; Chris@16: Chris@16: value_type &front(); Chris@16: const value_type &front() const; Chris@16: value_type &back(); Chris@16: const value_type &back() const; Chris@16: Chris@16: /** Insert a copy of the given tree with its key just before the given Chris@16: * position in this node. This operation invalidates no iterators. Chris@16: * @return An iterator to the newly created child. Chris@16: */ Chris@16: iterator insert(iterator where, const value_type &value); Chris@16: Chris@16: /** Range insert. Equivalent to: Chris@16: * @code Chris@16: * for(; first != last; ++first) insert(where, *first); Chris@16: * @endcode Chris@16: */ Chris@16: template void insert(iterator where, It first, It last); Chris@16: Chris@16: /** Erase the child pointed at by the iterator. This operation Chris@16: * invalidates the given iterator, as well as its equivalent Chris@16: * assoc_iterator. Chris@16: * @return A valid iterator pointing to the element after the erased. Chris@16: */ Chris@16: iterator erase(iterator where); Chris@16: Chris@16: /** Range erase. Equivalent to: Chris@16: * @code Chris@16: * while(first != last;) first = erase(first); Chris@16: * @endcode Chris@16: */ Chris@16: iterator erase(iterator first, iterator last); Chris@16: Chris@16: /** Equivalent to insert(begin(), value). */ Chris@16: iterator push_front(const value_type &value); Chris@16: Chris@16: /** Equivalent to insert(end(), value). */ Chris@16: iterator push_back(const value_type &value); Chris@16: Chris@16: /** Equivalent to erase(begin()). */ Chris@16: void pop_front(); Chris@16: Chris@16: /** Equivalent to erase(boost::prior(end())). */ Chris@16: void pop_back(); Chris@16: Chris@16: /** Reverses the order of direct children in the property tree. */ Chris@16: void reverse(); Chris@16: Chris@16: /** Sorts the direct children of this node according to the predicate. Chris@16: * The predicate is passed the whole pair of key and child. Chris@16: */ Chris@16: template void sort(Compare comp); Chris@16: Chris@16: /** Sorts the direct children of this node according to key order. */ Chris@16: void sort(); Chris@16: Chris@16: // Equality Chris@16: Chris@16: /** Two property trees are the same if they have the same data, the keys Chris@16: * and order of their children are the same, and the children compare Chris@16: * equal, recursively. Chris@16: */ Chris@16: bool operator ==(const self_type &rhs) const; Chris@16: bool operator !=(const self_type &rhs) const; Chris@16: Chris@16: // Associative view Chris@16: Chris@16: /** Returns an iterator to the first child, in key order. */ Chris@16: assoc_iterator ordered_begin(); Chris@16: /** Returns an iterator to the first child, in key order. */ Chris@16: const_assoc_iterator ordered_begin() const; Chris@16: Chris@16: /** Returns the not-found iterator. Equivalent to end() in a real Chris@16: * associative container. Chris@16: */ Chris@16: assoc_iterator not_found(); Chris@16: /** Returns the not-found iterator. Equivalent to end() in a real Chris@16: * associative container. Chris@16: */ Chris@16: const_assoc_iterator not_found() const; Chris@16: Chris@16: /** Find a child with the given key, or not_found() if there is none. Chris@16: * There is no guarantee about which child is returned if multiple have Chris@16: * the same key. Chris@16: */ Chris@16: assoc_iterator find(const key_type &key); Chris@16: Chris@16: /** Find a child with the given key, or not_found() if there is none. Chris@16: * There is no guarantee about which child is returned if multiple have Chris@16: * the same key. Chris@16: */ Chris@16: const_assoc_iterator find(const key_type &key) const; Chris@16: Chris@16: /** Find the range of children that have the given key. */ Chris@16: std::pair Chris@16: equal_range(const key_type &key); Chris@16: Chris@16: /** Find the range of children that have the given key. */ Chris@16: std::pair Chris@16: equal_range(const key_type &key) const; Chris@16: Chris@16: /** Count the number of direct children with the given key. */ Chris@16: size_type count(const key_type &key) const; Chris@16: Chris@16: /** Erase all direct children with the given key and return the count. Chris@16: */ Chris@16: size_type erase(const key_type &key); Chris@16: Chris@16: /** Get the iterator that points to the same element as the argument. Chris@16: * @note A valid assoc_iterator range (a, b) does not imply that Chris@16: * (to_iterator(a), to_iterator(b)) is a valid range. Chris@16: */ Chris@16: iterator to_iterator(assoc_iterator it); Chris@16: Chris@16: /** Get the iterator that points to the same element as the argument. Chris@16: * @note A valid const_assoc_iterator range (a, b) does not imply that Chris@16: * (to_iterator(a), to_iterator(b)) is a valid range. Chris@16: */ Chris@16: const_iterator to_iterator(const_assoc_iterator it) const; Chris@16: Chris@16: // Property tree view Chris@16: Chris@16: /** Reference to the actual data in this node. */ Chris@16: data_type &data(); Chris@16: Chris@16: /** Reference to the actual data in this node. */ Chris@16: const data_type &data() const; Chris@16: Chris@16: /** Clear this tree completely, of both data and children. */ Chris@16: void clear(); Chris@16: Chris@16: /** Get the child at the given path, or throw @c ptree_bad_path. Chris@16: * @note Depending on the path, the result at each level may not be Chris@101: * completely deterministic, i.e. if the same key appears multiple Chris@16: * times, which child is chosen is not specified. This can lead Chris@16: * to the path not being resolved even though there is a Chris@16: * descendant with this path. Example: Chris@16: * @code Chris@16: * a -> b -> c Chris@16: * -> b Chris@16: * @endcode Chris@16: * The path "a.b.c" will succeed if the resolution of "b" chooses Chris@16: * the first such node, but fail if it chooses the second. Chris@16: */ Chris@16: self_type &get_child(const path_type &path); Chris@16: Chris@16: /** Get the child at the given path, or throw @c ptree_bad_path. */ Chris@16: const self_type &get_child(const path_type &path) const; Chris@16: Chris@16: /** Get the child at the given path, or return @p default_value. */ Chris@16: self_type &get_child(const path_type &path, self_type &default_value); Chris@16: Chris@16: /** Get the child at the given path, or return @p default_value. */ Chris@16: const self_type &get_child(const path_type &path, Chris@16: const self_type &default_value) const; Chris@16: Chris@16: /** Get the child at the given path, or return boost::null. */ Chris@16: optional get_child_optional(const path_type &path); Chris@16: Chris@16: /** Get the child at the given path, or return boost::null. */ Chris@16: optional Chris@16: get_child_optional(const path_type &path) const; Chris@16: Chris@16: /** Set the node at the given path to the given value. Create any Chris@16: * missing parents. If the node at the path already exists, replace it. Chris@16: * @return A reference to the inserted subtree. Chris@16: * @note Because of the way paths work, it is not generally guaranteed Chris@16: * that a node newly created can be accessed using the same path. Chris@16: * @note If the path could refer to multiple nodes, it is unspecified Chris@16: * which one gets replaced. Chris@16: */ Chris@16: self_type &put_child(const path_type &path, const self_type &value); Chris@16: Chris@16: /** Add the node at the given path. Create any missing parents. If there Chris@16: * already is a node at the path, add another one with the same key. Chris@16: * @param path Path to the child. The last fragment must not have an Chris@16: * index. Chris@16: * @return A reference to the inserted subtree. Chris@16: * @note Because of the way paths work, it is not generally guaranteed Chris@16: * that a node newly created can be accessed using the same path. Chris@16: */ Chris@16: self_type &add_child(const path_type &path, const self_type &value); Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the supplied translator. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: typename boost::enable_if, Type>::type Chris@16: get_value(Translator tr) const; Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the default translator. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: Type get_value() const; Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the supplied translator. Return @p default_value Chris@16: * if this fails. Chris@16: */ Chris@16: template Chris@16: Type get_value(const Type &default_value, Translator tr) const; Chris@16: Chris@16: /** Make get_value do the right thing for string literals. */ Chris@16: template Chris@16: typename boost::enable_if< Chris@16: detail::is_character, Chris@16: std::basic_string Chris@16: >::type Chris@16: get_value(const Ch *default_value, Translator tr) const; Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the default translator. Return @p default_value Chris@16: * if this fails. Chris@16: */ Chris@16: template Chris@16: typename boost::disable_if, Type>::type Chris@16: get_value(const Type &default_value) const; Chris@16: Chris@16: /** Make get_value do the right thing for string literals. */ Chris@16: template Chris@16: typename boost::enable_if< Chris@16: detail::is_character, Chris@16: std::basic_string Chris@16: >::type Chris@16: get_value(const Ch *default_value) const; Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the supplied translator. Return boost::null if Chris@16: * this fails. Chris@16: */ Chris@16: template Chris@16: optional get_value_optional(Translator tr) const; Chris@16: Chris@16: /** Take the value of this node and attempt to translate it to a Chris@16: * @c Type object using the default translator. Return boost::null if Chris@16: * this fails. Chris@16: */ Chris@16: template Chris@16: optional get_value_optional() const; Chris@16: Chris@16: /** Replace the value at this node with the given value, translated Chris@16: * to the tree's data type using the supplied translator. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: void put_value(const Type &value, Translator tr); Chris@16: Chris@16: /** Replace the value at this node with the given value, translated Chris@16: * to the tree's data type using the default translator. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: void put_value(const Type &value); Chris@16: Chris@16: /** Shorthand for get_child(path).get_value(tr). */ Chris@16: template Chris@16: typename boost::enable_if, Type>::type Chris@16: get(const path_type &path, Translator tr) const; Chris@16: Chris@16: /** Shorthand for get_child(path).get_value\(). */ Chris@16: template Chris@16: Type get(const path_type &path) const; Chris@16: Chris@16: /** Shorthand for get_child(path, empty_ptree()) Chris@16: * .get_value(default_value, tr). Chris@16: * That is, return the translated value if possible, and the default Chris@16: * value if the node doesn't exist or conversion fails. Chris@16: */ Chris@16: template Chris@16: Type get(const path_type &path, Chris@16: const Type &default_value, Chris@16: Translator tr) const; Chris@16: Chris@16: /** Make get do the right thing for string literals. */ Chris@16: template Chris@16: typename boost::enable_if< Chris@16: detail::is_character, Chris@16: std::basic_string Chris@16: >::type Chris@16: get(const path_type &path, const Ch *default_value, Translator tr)const; Chris@16: Chris@16: /** Shorthand for get_child(path, empty_ptree()) Chris@16: * .get_value(default_value). Chris@16: * That is, return the translated value if possible, and the default Chris@16: * value if the node doesn't exist or conversion fails. Chris@16: */ Chris@16: template Chris@16: typename boost::disable_if, Type>::type Chris@16: get(const path_type &path, const Type &default_value) const; Chris@16: Chris@16: /** Make get do the right thing for string literals. */ Chris@16: template Chris@16: typename boost::enable_if< Chris@16: detail::is_character, Chris@16: std::basic_string Chris@16: >::type Chris@16: get(const path_type &path, const Ch *default_value) const; Chris@16: Chris@16: /** Shorthand for: Chris@16: * @code Chris@16: * if(optional\ node = get_child_optional(path)) Chris@16: * return node->get_value_optional(tr); Chris@16: * return boost::null; Chris@16: * @endcode Chris@16: * That is, return the value if it exists and can be converted, or nil. Chris@16: */ Chris@16: template Chris@16: optional get_optional(const path_type &path, Translator tr) const; Chris@16: Chris@16: /** Shorthand for: Chris@16: * @code Chris@16: * if(optional\ node = get_child_optional(path)) Chris@16: * return node->get_value_optional(); Chris@16: * return boost::null; Chris@16: * @endcode Chris@16: * That is, return the value if it exists and can be converted, or nil. Chris@16: */ Chris@16: template Chris@16: optional get_optional(const path_type &path) const; Chris@16: Chris@16: /** Set the value of the node at the given path to the supplied value, Chris@16: * translated to the tree's data type. If the node doesn't exist, it is Chris@16: * created, including all its missing parents. Chris@16: * @return The node that had its value changed. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: self_type &put(const path_type &path, const Type &value, Translator tr); Chris@16: Chris@16: /** Set the value of the node at the given path to the supplied value, Chris@16: * translated to the tree's data type. If the node doesn't exist, it is Chris@16: * created, including all its missing parents. Chris@16: * @return The node that had its value changed. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: self_type &put(const path_type &path, const Type &value); Chris@16: Chris@16: /** If the node identified by the path does not exist, create it, Chris@16: * including all its missing parents. Chris@16: * If the node already exists, add a sibling with the same key. Chris@16: * Set the newly created node's value to the given paremeter, Chris@16: * translated with the supplied translator. Chris@16: * @param path Path to the child. The last fragment must not have an Chris@16: * index. Chris@16: * @param value The value to add. Chris@16: * @param tr The translator to use. Chris@16: * @return The node that was added. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: self_type &add(const path_type &path, Chris@16: const Type &value, Chris@16: Translator tr); Chris@16: Chris@16: /** If the node identified by the path does not exist, create it, Chris@16: * including all its missing parents. Chris@16: * If the node already exists, add a sibling with the same key. Chris@16: * Set the newly created node's value to the given paremeter, Chris@16: * translated with the supplied translator. Chris@16: * @param path Path to the child. The last fragment must not have an Chris@16: * index. Chris@16: * @param value The value to add. Chris@16: * @return The node that was added. Chris@16: * @throw ptree_bad_data if the conversion fails. Chris@16: */ Chris@16: template Chris@16: self_type &add(const path_type &path, const Type &value); Chris@16: Chris@16: private: Chris@16: // Hold the data of this node Chris@16: data_type m_data; Chris@16: // Hold the children - this is a void* because we can't complete the Chris@16: // container type within the class. Chris@16: void* m_children; Chris@16: Chris@16: // Getter tree-walk. Not const-safe! Gets the node the path refers to, Chris@16: // or null. Destroys p's value. Chris@16: self_type* walk_path(path_type& p) const; Chris@16: Chris@16: // Modifer tree-walk. Gets the parent of the node referred to by the Chris@16: // path, creating nodes as necessary. p is the path to the remaining Chris@16: // child. Chris@16: self_type& force_path(path_type& p); Chris@16: Chris@16: // This struct contains typedefs for the concrete types. Chris@16: struct subs; Chris@16: friend struct subs; Chris@16: friend class iterator; Chris@16: friend class const_iterator; Chris@16: friend class reverse_iterator; Chris@16: friend class const_reverse_iterator; Chris@16: }; Chris@16: Chris@16: }} Chris@16: Chris@16: #include Chris@16: Chris@16: #endif