Brian Silverman | 836e90c | 2018-08-04 16:19:46 -0700 | [diff] [blame^] | 1 | // ---------------------------------------------------------------------------- |
| 2 | // Copyright (C) 2002-2006 Marcin Kalicinski |
| 3 | // Copyright (C) 2009 Sebastian Redl |
| 4 | // |
| 5 | // Distributed under the Boost Software License, Version 1.0. |
| 6 | // (See accompanying file LICENSE_1_0.txt or copy at |
| 7 | // http://www.boost.org/LICENSE_1_0.txt) |
| 8 | // |
| 9 | // For more information, see www.boost.org |
| 10 | // ---------------------------------------------------------------------------- |
| 11 | |
| 12 | #ifndef BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED |
| 13 | #define BOOST_PROPERTY_TREE_PTREE_HPP_INCLUDED |
| 14 | |
| 15 | #include <boost/property_tree/ptree_fwd.hpp> |
| 16 | #include <boost/property_tree/string_path.hpp> |
| 17 | #include <boost/property_tree/stream_translator.hpp> |
| 18 | #include <boost/property_tree/exceptions.hpp> |
| 19 | #include <boost/property_tree/detail/ptree_utils.hpp> |
| 20 | |
| 21 | #include <boost/multi_index_container.hpp> |
| 22 | #include <boost/multi_index/indexed_by.hpp> |
| 23 | #include <boost/multi_index/sequenced_index.hpp> |
| 24 | #include <boost/multi_index/ordered_index.hpp> |
| 25 | #include <boost/multi_index/member.hpp> |
| 26 | #include <boost/utility/enable_if.hpp> |
| 27 | #include <boost/throw_exception.hpp> |
| 28 | #include <boost/optional.hpp> |
| 29 | #include <utility> // for std::pair |
| 30 | |
| 31 | namespace boost { namespace property_tree |
| 32 | { |
| 33 | |
| 34 | /** |
| 35 | * Property tree main structure. A property tree is a hierarchical data |
| 36 | * structure which has one element of type @p Data in each node, as well |
| 37 | * as an ordered sequence of sub-nodes, which are additionally identified |
| 38 | * by a non-unique key of type @p Key. |
| 39 | * |
| 40 | * Key equivalency is defined by @p KeyCompare, a predicate defining a |
| 41 | * strict weak ordering. |
| 42 | * |
| 43 | * Property tree defines a Container-like interface to the (key-node) pairs |
| 44 | * of its direct sub-nodes. The iterators are bidirectional. The sequence |
| 45 | * of nodes is held in insertion order, not key order. |
| 46 | */ |
| 47 | template<class Key, class Data, class KeyCompare> |
| 48 | class basic_ptree |
| 49 | { |
| 50 | #if defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED) |
| 51 | public: |
| 52 | #endif |
| 53 | // Internal types |
| 54 | /** |
| 55 | * Simpler way to refer to this basic_ptree\<C,K,P,A\> type. |
| 56 | * Note that this is private, and made public only for doxygen. |
| 57 | */ |
| 58 | typedef basic_ptree<Key, Data, KeyCompare> self_type; |
| 59 | |
| 60 | public: |
| 61 | // Basic types |
| 62 | typedef Key key_type; |
| 63 | typedef Data data_type; |
| 64 | typedef KeyCompare key_compare; |
| 65 | |
| 66 | // Container view types |
| 67 | typedef std::pair<const Key, self_type> value_type; |
| 68 | typedef std::size_t size_type; |
| 69 | |
| 70 | // The problem with the iterators is that I can't make them complete |
| 71 | // until the container is complete. Sucks. Especially for the reverses. |
| 72 | class iterator; |
| 73 | class const_iterator; |
| 74 | class reverse_iterator; |
| 75 | class const_reverse_iterator; |
| 76 | |
| 77 | // Associative view types |
| 78 | class assoc_iterator; |
| 79 | class const_assoc_iterator; |
| 80 | |
| 81 | // Property tree view types |
| 82 | typedef typename path_of<Key>::type path_type; |
| 83 | |
| 84 | |
| 85 | // The big five |
| 86 | |
| 87 | /** Creates a node with no children and default-constructed data. */ |
| 88 | basic_ptree(); |
| 89 | /** Creates a node with no children and a copy of the given data. */ |
| 90 | explicit basic_ptree(const data_type &data); |
| 91 | basic_ptree(const self_type &rhs); |
| 92 | ~basic_ptree(); |
| 93 | /** Basic guarantee only. */ |
| 94 | self_type &operator =(const self_type &rhs); |
| 95 | |
| 96 | /** Swap with other tree. Only constant-time and nothrow if the |
| 97 | * data type's swap is. |
| 98 | */ |
| 99 | void swap(self_type &rhs); |
| 100 | |
| 101 | // Container view functions |
| 102 | |
| 103 | /** The number of direct children of this node. */ |
| 104 | size_type size() const; |
| 105 | size_type max_size() const; |
| 106 | /** Whether there are any direct children. */ |
| 107 | bool empty() const; |
| 108 | |
| 109 | iterator begin(); |
| 110 | const_iterator begin() const; |
| 111 | iterator end(); |
| 112 | const_iterator end() const; |
| 113 | reverse_iterator rbegin(); |
| 114 | const_reverse_iterator rbegin() const; |
| 115 | reverse_iterator rend(); |
| 116 | const_reverse_iterator rend() const; |
| 117 | |
| 118 | value_type &front(); |
| 119 | const value_type &front() const; |
| 120 | value_type &back(); |
| 121 | const value_type &back() const; |
| 122 | |
| 123 | /** Insert a copy of the given tree with its key just before the given |
| 124 | * position in this node. This operation invalidates no iterators. |
| 125 | * @return An iterator to the newly created child. |
| 126 | */ |
| 127 | iterator insert(iterator where, const value_type &value); |
| 128 | |
| 129 | /** Range insert. Equivalent to: |
| 130 | * @code |
| 131 | * for(; first != last; ++first) insert(where, *first); |
| 132 | * @endcode |
| 133 | */ |
| 134 | template<class It> void insert(iterator where, It first, It last); |
| 135 | |
| 136 | /** Erase the child pointed at by the iterator. This operation |
| 137 | * invalidates the given iterator, as well as its equivalent |
| 138 | * assoc_iterator. |
| 139 | * @return A valid iterator pointing to the element after the erased. |
| 140 | */ |
| 141 | iterator erase(iterator where); |
| 142 | |
| 143 | /** Range erase. Equivalent to: |
| 144 | * @code |
| 145 | * while(first != last;) first = erase(first); |
| 146 | * @endcode |
| 147 | */ |
| 148 | iterator erase(iterator first, iterator last); |
| 149 | |
| 150 | /** Equivalent to insert(begin(), value). */ |
| 151 | iterator push_front(const value_type &value); |
| 152 | |
| 153 | /** Equivalent to insert(end(), value). */ |
| 154 | iterator push_back(const value_type &value); |
| 155 | |
| 156 | /** Equivalent to erase(begin()). */ |
| 157 | void pop_front(); |
| 158 | |
| 159 | /** Equivalent to erase(boost::prior(end())). */ |
| 160 | void pop_back(); |
| 161 | |
| 162 | /** Reverses the order of direct children in the property tree. */ |
| 163 | void reverse(); |
| 164 | |
| 165 | /** Sorts the direct children of this node according to the predicate. |
| 166 | * The predicate is passed the whole pair of key and child. |
| 167 | */ |
| 168 | template<class Compare> void sort(Compare comp); |
| 169 | |
| 170 | /** Sorts the direct children of this node according to key order. */ |
| 171 | void sort(); |
| 172 | |
| 173 | // Equality |
| 174 | |
| 175 | /** Two property trees are the same if they have the same data, the keys |
| 176 | * and order of their children are the same, and the children compare |
| 177 | * equal, recursively. |
| 178 | */ |
| 179 | bool operator ==(const self_type &rhs) const; |
| 180 | bool operator !=(const self_type &rhs) const; |
| 181 | |
| 182 | // Associative view |
| 183 | |
| 184 | /** Returns an iterator to the first child, in key order. */ |
| 185 | assoc_iterator ordered_begin(); |
| 186 | /** Returns an iterator to the first child, in key order. */ |
| 187 | const_assoc_iterator ordered_begin() const; |
| 188 | |
| 189 | /** Returns the not-found iterator. Equivalent to end() in a real |
| 190 | * associative container. |
| 191 | */ |
| 192 | assoc_iterator not_found(); |
| 193 | /** Returns the not-found iterator. Equivalent to end() in a real |
| 194 | * associative container. |
| 195 | */ |
| 196 | const_assoc_iterator not_found() const; |
| 197 | |
| 198 | /** Find a child with the given key, or not_found() if there is none. |
| 199 | * There is no guarantee about which child is returned if multiple have |
| 200 | * the same key. |
| 201 | */ |
| 202 | assoc_iterator find(const key_type &key); |
| 203 | |
| 204 | /** Find a child with the given key, or not_found() if there is none. |
| 205 | * There is no guarantee about which child is returned if multiple have |
| 206 | * the same key. |
| 207 | */ |
| 208 | const_assoc_iterator find(const key_type &key) const; |
| 209 | |
| 210 | /** Find the range of children that have the given key. */ |
| 211 | std::pair<assoc_iterator, assoc_iterator> |
| 212 | equal_range(const key_type &key); |
| 213 | |
| 214 | /** Find the range of children that have the given key. */ |
| 215 | std::pair<const_assoc_iterator, const_assoc_iterator> |
| 216 | equal_range(const key_type &key) const; |
| 217 | |
| 218 | /** Count the number of direct children with the given key. */ |
| 219 | size_type count(const key_type &key) const; |
| 220 | |
| 221 | /** Erase all direct children with the given key and return the count. |
| 222 | */ |
| 223 | size_type erase(const key_type &key); |
| 224 | |
| 225 | /** Get the iterator that points to the same element as the argument. |
| 226 | * @note A valid assoc_iterator range (a, b) does not imply that |
| 227 | * (to_iterator(a), to_iterator(b)) is a valid range. |
| 228 | */ |
| 229 | iterator to_iterator(assoc_iterator it); |
| 230 | |
| 231 | /** Get the iterator that points to the same element as the argument. |
| 232 | * @note A valid const_assoc_iterator range (a, b) does not imply that |
| 233 | * (to_iterator(a), to_iterator(b)) is a valid range. |
| 234 | */ |
| 235 | const_iterator to_iterator(const_assoc_iterator it) const; |
| 236 | |
| 237 | // Property tree view |
| 238 | |
| 239 | /** Reference to the actual data in this node. */ |
| 240 | data_type &data(); |
| 241 | |
| 242 | /** Reference to the actual data in this node. */ |
| 243 | const data_type &data() const; |
| 244 | |
| 245 | /** Clear this tree completely, of both data and children. */ |
| 246 | void clear(); |
| 247 | |
| 248 | /** Get the child at the given path, or throw @c ptree_bad_path. |
| 249 | * @note Depending on the path, the result at each level may not be |
| 250 | * completely deterministic, i.e. if the same key appears multiple |
| 251 | * times, which child is chosen is not specified. This can lead |
| 252 | * to the path not being resolved even though there is a |
| 253 | * descendant with this path. Example: |
| 254 | * @code |
| 255 | * a -> b -> c |
| 256 | * -> b |
| 257 | * @endcode |
| 258 | * The path "a.b.c" will succeed if the resolution of "b" chooses |
| 259 | * the first such node, but fail if it chooses the second. |
| 260 | */ |
| 261 | self_type &get_child(const path_type &path); |
| 262 | |
| 263 | /** Get the child at the given path, or throw @c ptree_bad_path. */ |
| 264 | const self_type &get_child(const path_type &path) const; |
| 265 | |
| 266 | /** Get the child at the given path, or return @p default_value. */ |
| 267 | self_type &get_child(const path_type &path, self_type &default_value); |
| 268 | |
| 269 | /** Get the child at the given path, or return @p default_value. */ |
| 270 | const self_type &get_child(const path_type &path, |
| 271 | const self_type &default_value) const; |
| 272 | |
| 273 | /** Get the child at the given path, or return boost::null. */ |
| 274 | optional<self_type &> get_child_optional(const path_type &path); |
| 275 | |
| 276 | /** Get the child at the given path, or return boost::null. */ |
| 277 | optional<const self_type &> |
| 278 | get_child_optional(const path_type &path) const; |
| 279 | |
| 280 | /** Set the node at the given path to the given value. Create any |
| 281 | * missing parents. If the node at the path already exists, replace it. |
| 282 | * @return A reference to the inserted subtree. |
| 283 | * @note Because of the way paths work, it is not generally guaranteed |
| 284 | * that a node newly created can be accessed using the same path. |
| 285 | * @note If the path could refer to multiple nodes, it is unspecified |
| 286 | * which one gets replaced. |
| 287 | */ |
| 288 | self_type &put_child(const path_type &path, const self_type &value); |
| 289 | |
| 290 | /** Add the node at the given path. Create any missing parents. If there |
| 291 | * already is a node at the path, add another one with the same key. |
| 292 | * @param path Path to the child. The last fragment must not have an |
| 293 | * index. |
| 294 | * @return A reference to the inserted subtree. |
| 295 | * @note Because of the way paths work, it is not generally guaranteed |
| 296 | * that a node newly created can be accessed using the same path. |
| 297 | */ |
| 298 | self_type &add_child(const path_type &path, const self_type &value); |
| 299 | |
| 300 | /** Take the value of this node and attempt to translate it to a |
| 301 | * @c Type object using the supplied translator. |
| 302 | * @throw ptree_bad_data if the conversion fails. |
| 303 | */ |
| 304 | template<class Type, class Translator> |
| 305 | typename boost::enable_if<detail::is_translator<Translator>, Type>::type |
| 306 | get_value(Translator tr) const; |
| 307 | |
| 308 | /** Take the value of this node and attempt to translate it to a |
| 309 | * @c Type object using the default translator. |
| 310 | * @throw ptree_bad_data if the conversion fails. |
| 311 | */ |
| 312 | template<class Type> |
| 313 | Type get_value() const; |
| 314 | |
| 315 | /** Take the value of this node and attempt to translate it to a |
| 316 | * @c Type object using the supplied translator. Return @p default_value |
| 317 | * if this fails. |
| 318 | */ |
| 319 | template<class Type, class Translator> |
| 320 | Type get_value(const Type &default_value, Translator tr) const; |
| 321 | |
| 322 | /** Make get_value do the right thing for string literals. */ |
| 323 | template <class Ch, class Translator> |
| 324 | typename boost::enable_if< |
| 325 | detail::is_character<Ch>, |
| 326 | std::basic_string<Ch> |
| 327 | >::type |
| 328 | get_value(const Ch *default_value, Translator tr) const; |
| 329 | |
| 330 | /** Take the value of this node and attempt to translate it to a |
| 331 | * @c Type object using the default translator. Return @p default_value |
| 332 | * if this fails. |
| 333 | */ |
| 334 | template<class Type> |
| 335 | typename boost::disable_if<detail::is_translator<Type>, Type>::type |
| 336 | get_value(const Type &default_value) const; |
| 337 | |
| 338 | /** Make get_value do the right thing for string literals. */ |
| 339 | template <class Ch> |
| 340 | typename boost::enable_if< |
| 341 | detail::is_character<Ch>, |
| 342 | std::basic_string<Ch> |
| 343 | >::type |
| 344 | get_value(const Ch *default_value) const; |
| 345 | |
| 346 | /** Take the value of this node and attempt to translate it to a |
| 347 | * @c Type object using the supplied translator. Return boost::null if |
| 348 | * this fails. |
| 349 | */ |
| 350 | template<class Type, class Translator> |
| 351 | optional<Type> get_value_optional(Translator tr) const; |
| 352 | |
| 353 | /** Take the value of this node and attempt to translate it to a |
| 354 | * @c Type object using the default translator. Return boost::null if |
| 355 | * this fails. |
| 356 | */ |
| 357 | template<class Type> |
| 358 | optional<Type> get_value_optional() const; |
| 359 | |
| 360 | /** Replace the value at this node with the given value, translated |
| 361 | * to the tree's data type using the supplied translator. |
| 362 | * @throw ptree_bad_data if the conversion fails. |
| 363 | */ |
| 364 | template<class Type, class Translator> |
| 365 | void put_value(const Type &value, Translator tr); |
| 366 | |
| 367 | /** Replace the value at this node with the given value, translated |
| 368 | * to the tree's data type using the default translator. |
| 369 | * @throw ptree_bad_data if the conversion fails. |
| 370 | */ |
| 371 | template<class Type> |
| 372 | void put_value(const Type &value); |
| 373 | |
| 374 | /** Shorthand for get_child(path).get_value(tr). */ |
| 375 | template<class Type, class Translator> |
| 376 | typename boost::enable_if<detail::is_translator<Translator>, Type>::type |
| 377 | get(const path_type &path, Translator tr) const; |
| 378 | |
| 379 | /** Shorthand for get_child(path).get_value\<Type\>(). */ |
| 380 | template<class Type> |
| 381 | Type get(const path_type &path) const; |
| 382 | |
| 383 | /** Shorthand for get_child(path, empty_ptree()) |
| 384 | * .get_value(default_value, tr). |
| 385 | * That is, return the translated value if possible, and the default |
| 386 | * value if the node doesn't exist or conversion fails. |
| 387 | */ |
| 388 | template<class Type, class Translator> |
| 389 | Type get(const path_type &path, |
| 390 | const Type &default_value, |
| 391 | Translator tr) const; |
| 392 | |
| 393 | /** Make get do the right thing for string literals. */ |
| 394 | template <class Ch, class Translator> |
| 395 | typename boost::enable_if< |
| 396 | detail::is_character<Ch>, |
| 397 | std::basic_string<Ch> |
| 398 | >::type |
| 399 | get(const path_type &path, const Ch *default_value, Translator tr)const; |
| 400 | |
| 401 | /** Shorthand for get_child(path, empty_ptree()) |
| 402 | * .get_value(default_value). |
| 403 | * That is, return the translated value if possible, and the default |
| 404 | * value if the node doesn't exist or conversion fails. |
| 405 | */ |
| 406 | template<class Type> |
| 407 | typename boost::disable_if<detail::is_translator<Type>, Type>::type |
| 408 | get(const path_type &path, const Type &default_value) const; |
| 409 | |
| 410 | /** Make get do the right thing for string literals. */ |
| 411 | template <class Ch> |
| 412 | typename boost::enable_if< |
| 413 | detail::is_character<Ch>, |
| 414 | std::basic_string<Ch> |
| 415 | >::type |
| 416 | get(const path_type &path, const Ch *default_value) const; |
| 417 | |
| 418 | /** Shorthand for: |
| 419 | * @code |
| 420 | * if(optional\<self_type&\> node = get_child_optional(path)) |
| 421 | * return node->get_value_optional(tr); |
| 422 | * return boost::null; |
| 423 | * @endcode |
| 424 | * That is, return the value if it exists and can be converted, or nil. |
| 425 | */ |
| 426 | template<class Type, class Translator> |
| 427 | optional<Type> get_optional(const path_type &path, Translator tr) const; |
| 428 | |
| 429 | /** Shorthand for: |
| 430 | * @code |
| 431 | * if(optional\<const self_type&\> node = get_child_optional(path)) |
| 432 | * return node->get_value_optional(); |
| 433 | * return boost::null; |
| 434 | * @endcode |
| 435 | * That is, return the value if it exists and can be converted, or nil. |
| 436 | */ |
| 437 | template<class Type> |
| 438 | optional<Type> get_optional(const path_type &path) const; |
| 439 | |
| 440 | /** Set the value of the node at the given path to the supplied value, |
| 441 | * translated to the tree's data type. If the node doesn't exist, it is |
| 442 | * created, including all its missing parents. |
| 443 | * @return The node that had its value changed. |
| 444 | * @throw ptree_bad_data if the conversion fails. |
| 445 | */ |
| 446 | template<class Type, class Translator> |
| 447 | self_type &put(const path_type &path, const Type &value, Translator tr); |
| 448 | |
| 449 | /** Set the value of the node at the given path to the supplied value, |
| 450 | * translated to the tree's data type. If the node doesn't exist, it is |
| 451 | * created, including all its missing parents. |
| 452 | * @return The node that had its value changed. |
| 453 | * @throw ptree_bad_data if the conversion fails. |
| 454 | */ |
| 455 | template<class Type> |
| 456 | self_type &put(const path_type &path, const Type &value); |
| 457 | |
| 458 | /** If the node identified by the path does not exist, create it, |
| 459 | * including all its missing parents. |
| 460 | * If the node already exists, add a sibling with the same key. |
| 461 | * Set the newly created node's value to the given paremeter, |
| 462 | * translated with the supplied translator. |
| 463 | * @param path Path to the child. The last fragment must not have an |
| 464 | * index. |
| 465 | * @param value The value to add. |
| 466 | * @param tr The translator to use. |
| 467 | * @return The node that was added. |
| 468 | * @throw ptree_bad_data if the conversion fails. |
| 469 | */ |
| 470 | template<class Type, class Translator> |
| 471 | self_type &add(const path_type &path, |
| 472 | const Type &value, |
| 473 | Translator tr); |
| 474 | |
| 475 | /** If the node identified by the path does not exist, create it, |
| 476 | * including all its missing parents. |
| 477 | * If the node already exists, add a sibling with the same key. |
| 478 | * Set the newly created node's value to the given paremeter, |
| 479 | * translated with the supplied translator. |
| 480 | * @param path Path to the child. The last fragment must not have an |
| 481 | * index. |
| 482 | * @param value The value to add. |
| 483 | * @return The node that was added. |
| 484 | * @throw ptree_bad_data if the conversion fails. |
| 485 | */ |
| 486 | template<class Type> |
| 487 | self_type &add(const path_type &path, const Type &value); |
| 488 | |
| 489 | private: |
| 490 | // Hold the data of this node |
| 491 | data_type m_data; |
| 492 | // Hold the children - this is a void* because we can't complete the |
| 493 | // container type within the class. |
| 494 | void* m_children; |
| 495 | |
| 496 | // Getter tree-walk. Not const-safe! Gets the node the path refers to, |
| 497 | // or null. Destroys p's value. |
| 498 | self_type* walk_path(path_type& p) const; |
| 499 | |
| 500 | // Modifer tree-walk. Gets the parent of the node referred to by the |
| 501 | // path, creating nodes as necessary. p is the path to the remaining |
| 502 | // child. |
| 503 | self_type& force_path(path_type& p); |
| 504 | |
| 505 | // This struct contains typedefs for the concrete types. |
| 506 | struct subs; |
| 507 | friend struct subs; |
| 508 | friend class iterator; |
| 509 | friend class const_iterator; |
| 510 | friend class reverse_iterator; |
| 511 | friend class const_reverse_iterator; |
| 512 | }; |
| 513 | |
| 514 | }} |
| 515 | |
| 516 | #include <boost/property_tree/detail/ptree_implementation.hpp> |
| 517 | |
| 518 | #endif |