fix doc example typo
[boost.git] / boost / property_tree / detail / ptree_implementation.hpp
blob2bd8d4e7c09891a39ed29c8c664e851e3bb21265
1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2002-2006 Marcin Kalicinski
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // For more information, see www.boost.org
9 // ----------------------------------------------------------------------------
10 #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
11 #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
13 //////////////////////////////////////////////////////////////////////////////
14 // Debug macros
16 #ifdef BOOST_PROPERTY_TREE_DEBUG
18 // Increment instances counter
19 #define BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT() \
20 { \
21 typedef boost::detail::lightweight_mutex::scoped_lock lock; \
22 lock l(debug_mutex); \
23 ++debug_instances_count; \
26 // Decrement instances counter
27 #define BOOST_PROPERTY_TREE_DEBUG_DECREMENT_INSTANCES_COUNT() \
28 { \
29 typedef boost::detail::lightweight_mutex::scoped_lock lock; \
30 lock l(debug_mutex); \
31 BOOST_ASSERT(debug_instances_count > 0); \
32 --debug_instances_count; \
35 #else // BOOST_PROPERTY_TREE_DEBUG
37 #define BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT() static_cast<void>(0)
38 #define BOOST_PROPERTY_TREE_DEBUG_DECREMENT_INSTANCES_COUNT() static_cast<void>(0)
40 #endif // BOOST_PROPERTY_TREE_DEBUG
42 namespace boost { namespace property_tree
45 ///////////////////////////////////////////////////////////////////////////
46 // Construction & destruction
48 template<class C, class K, class P, class D, class X>
49 basic_ptree<C, K, P, D, X>::basic_ptree()
51 BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT();
54 template<class C, class K, class P, class D, class X>
55 basic_ptree<C, K, P, D, X>::basic_ptree(const data_type &rhs):
56 m_data(rhs)
58 BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT();
61 template<class C, class K, class P, class D, class X>
62 basic_ptree<C, K, P, D, X>::basic_ptree(const basic_ptree<C, K, P, D, X> &rhs)
64 m_data = rhs.m_data;
65 insert(end(), rhs.begin(), rhs.end());
66 BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT();
69 template<class C, class K, class P, class D, class X>
70 basic_ptree<C, K, P, D, X>::~basic_ptree()
72 BOOST_PROPERTY_TREE_DEBUG_DECREMENT_INSTANCES_COUNT();
75 ///////////////////////////////////////////////////////////////////////////
76 // Iterator access
78 template<class C, class K, class P, class D, class X>
79 typename basic_ptree<C, K, P, D, X>::iterator
80 basic_ptree<C, K, P, D, X>::begin()
82 return m_container.begin();
85 template<class C, class K, class P, class D, class X>
86 typename basic_ptree<C, K, P, D, X>::const_iterator
87 basic_ptree<C, K, P, D, X>::begin() const
89 return m_container.begin();
92 template<class C, class K, class P, class D, class X>
93 typename basic_ptree<C, K, P, D, X>::iterator
94 basic_ptree<C, K, P, D, X>::end()
96 return m_container.end();
99 template<class C, class K, class P, class D, class X>
100 typename basic_ptree<C, K, P, D, X>::const_iterator
101 basic_ptree<C, K, P, D, X>::end() const
103 return m_container.end();
106 template<class C, class K, class P, class D, class X>
107 typename basic_ptree<C, K, P, D, X>::reverse_iterator
108 basic_ptree<C, K, P, D, X>::rbegin()
110 return m_container.rbegin();
113 template<class C, class K, class P, class D, class X>
114 typename basic_ptree<C, K, P, D, X>::const_reverse_iterator
115 basic_ptree<C, K, P, D, X>::rbegin() const
117 return m_container.rbegin();
120 template<class C, class K, class P, class D, class X>
121 typename basic_ptree<C, K, P, D, X>::reverse_iterator
122 basic_ptree<C, K, P, D, X>::rend()
124 return m_container.rend();
127 template<class C, class K, class P, class D, class X>
128 typename basic_ptree<C, K, P, D, X>::const_reverse_iterator
129 basic_ptree<C, K, P, D, X>::rend() const
131 return m_container.rend();
134 ///////////////////////////////////////////////////////////////////////////
135 // Data access
137 template<class C, class K, class P, class D, class X>
138 typename basic_ptree<C, K, P, D, X>::size_type
139 basic_ptree<C, K, P, D, X>::size() const
141 return m_container.size();
144 template<class C, class K, class P, class D, class X>
145 typename basic_ptree<C, K, P, D, X>::size_type
146 basic_ptree<C, K, P, D, X>::max_size() const
148 return m_container.max_size();
151 template<class C, class K, class P, class D, class X>
152 bool basic_ptree<C, K, P, D, X>::empty() const
154 return m_container.empty();
157 template<class C, class K, class P, class D, class X>
158 typename basic_ptree<C, K, P, D, X>::data_type &
159 basic_ptree<C, K, P, D, X>::data()
161 return m_data;
164 template<class C, class K, class P, class D, class X>
165 const typename basic_ptree<C, K, P, D, X>::data_type &
166 basic_ptree<C, K, P, D, X>::data() const
168 return m_data;
171 template<class C, class K, class P, class D, class X>
172 typename basic_ptree<C, K, P, D, X>::value_type &
173 basic_ptree<C, K, P, D, X>::front()
175 return m_container.front();
178 template<class C, class K, class P, class D, class X>
179 const typename basic_ptree<C, K, P, D, X>::value_type &
180 basic_ptree<C, K, P, D, X>::front() const
182 return m_container.front();
185 template<class C, class K, class P, class D, class X>
186 typename basic_ptree<C, K, P, D, X>::value_type &
187 basic_ptree<C, K, P, D, X>::back()
189 return m_container.back();
192 template<class C, class K, class P, class D, class X>
193 const typename basic_ptree<C, K, P, D, X>::value_type &
194 basic_ptree<C, K, P, D, X>::back() const
196 return m_container.back();
199 ///////////////////////////////////////////////////////////////////////////
200 // Operators
202 template<class C, class K, class P, class D, class X>
203 basic_ptree<C, K, P, D, X> &
204 basic_ptree<C, K, P, D, X>::operator =(const basic_ptree<C, K, P, D, X> &rhs)
206 if (&rhs != this)
208 clear();
209 data() = rhs.data();
210 insert(end(), rhs.begin(), rhs.end());
212 return *this;
215 template<class C, class K, class P, class D, class X>
216 bool basic_ptree<C, K, P, D, X>::operator ==(const basic_ptree<C, K, P, D, X> &rhs) const
219 // Data and sizes must be equal
220 if (size() != rhs.size() || data() != rhs.data())
221 return false;
223 // Keys and children must be equal
224 C comp;
225 const_iterator it = begin();
226 const_iterator it_rhs = rhs.begin();
227 const_iterator it_end = end();
228 for (; it != it_end; ++it, ++it_rhs)
229 if (comp(it->first, it_rhs->first)
230 || comp(it_rhs->first, it->first)
231 || it->second != it_rhs->second)
233 return false;
236 // Equal
237 return true;
241 template<class C, class K, class P, class D, class X>
242 bool basic_ptree<C, K, P, D, X>::operator !=(const basic_ptree<C, K, P, D, X> &rhs) const
244 return !operator ==(rhs);
247 ///////////////////////////////////////////////////////////////////////////
248 // Container operations
250 template<class C, class K, class P, class D, class X>
251 typename basic_ptree<C, K, P, D, X>::iterator
252 basic_ptree<C, K, P, D, X>::find(const key_type &key)
254 C comp;
255 for (iterator it = begin(); it != end(); ++it)
256 if (!comp(it->first, key) && !comp(key, it->first))
257 return it;
258 return end();
261 template<class C, class K, class P, class D, class X>
262 typename basic_ptree<C, K, P, D, X>::const_iterator
263 basic_ptree<C, K, P, D, X>::find(const key_type &key) const
265 C comp;
266 for (const_iterator it = begin(); it != end(); ++it)
267 if (!comp(it->first, key) && !comp(key, it->first))
268 return it;
269 return end();
272 template<class C, class K, class P, class D, class X>
273 typename basic_ptree<C, K, P, D, X>::size_type
274 basic_ptree<C, K, P, D, X>::count(const key_type &key) const
276 C comp;
277 size_type count = 0;
278 for (const_iterator it = begin(); it != end(); ++it)
279 if (!comp(it->first, key) && !comp(key, it->first))
280 ++count;
281 return count;
284 template<class C, class K, class P, class D, class X>
285 void basic_ptree<C, K, P, D, X>::clear()
287 m_data = data_type();
288 m_container.clear();
291 template<class C, class K, class P, class D, class X>
292 typename basic_ptree<C, K, P, D, X>::iterator
293 basic_ptree<C, K, P, D, X>::insert(iterator where,
294 const value_type &value)
296 return m_container.insert(where, value);
299 template<class C, class K, class P, class D, class X>
300 template<class It>
301 void basic_ptree<C, K, P, D, X>::insert(iterator where, It first, It last)
303 for (; first != last; ++first, ++where)
304 where = insert(where, value_type(first->first, first->second));
307 template<class C, class K, class P, class D, class X>
308 typename basic_ptree<C, K, P, D, X>::iterator
309 basic_ptree<C, K, P, D, X>::erase(iterator where)
311 return m_container.erase(where);
314 template<class C, class K, class P, class D, class X>
315 typename basic_ptree<C, K, P, D, X>::size_type
316 basic_ptree<C, K, P, D, X>::erase(const key_type &key)
318 C comp;
319 size_type count = 0;
320 iterator it = m_container.begin();
321 while (it != m_container.end())
323 if (!comp(it->first, key) && !comp(key, it->first))
325 it = erase(it);
326 ++count;
328 else
329 ++it;
331 return count;
334 template<class C, class K, class P, class D, class X>
335 template<class It>
336 typename basic_ptree<C, K, P, D, X>::iterator
337 basic_ptree<C, K, P, D, X>::erase(It first, It last)
339 while (first != last)
340 first = erase(first);
341 return first;
344 template<class C, class K, class P, class D, class X>
345 typename basic_ptree<C, K, P, D, X>::iterator
346 basic_ptree<C, K, P, D, X>::push_front(const value_type &value)
348 return insert(begin(), value);
351 template<class C, class K, class P, class D, class X>
352 typename basic_ptree<C, K, P, D, X>::iterator
353 basic_ptree<C, K, P, D, X>::push_back(const value_type &value)
355 return insert(end(), value);
358 template<class C, class K, class P, class D, class X>
359 void basic_ptree<C, K, P, D, X>::pop_front()
361 erase(begin());
364 template<class C, class K, class P, class D, class X>
365 void basic_ptree<C, K, P, D, X>::pop_back()
367 iterator last = end();
368 --last;
369 erase(last);
372 template<class C, class K, class P, class D, class X>
373 void basic_ptree<C, K, P, D, X>::swap(basic_ptree<C, K, P, D, X> &rhs)
375 m_data.swap(rhs.m_data);
376 m_container.swap(rhs.m_container);
379 template<class C, class K, class P, class D, class X>
380 void basic_ptree<C, K, P, D, X>::reverse()
382 m_container.reverse();
385 template<class C, class K, class P, class D, class X>
386 template<class SortTr>
387 void basic_ptree<C, K, P, D, X>::sort(SortTr tr)
389 m_container.sort(tr);
392 ///////////////////////////////////////////////////////////////////////////
393 // ptree operations
395 // Get child ptree
396 template<class C, class K, class P, class D, class X>
397 basic_ptree<C, K, P, D, X> &
398 basic_ptree<C, K, P, D, X>::get_child(const path_type &path)
400 self_type *child = path.get_child(*this);
401 if (child)
402 return *child;
403 else
404 BOOST_PROPERTY_TREE_THROW(ptree_bad_path("path does not exist", path));
407 // Get child ptree
408 template<class C, class K, class P, class D, class X>
409 const basic_ptree<C, K, P, D, X> &
410 basic_ptree<C, K, P, D, X>::get_child(const path_type &path) const
412 self_type *nc_this = const_cast<self_type *>(this);
413 return nc_this->get_child(path);
416 // Get child ptree
417 template<class C, class K, class P, class D, class X>
418 basic_ptree<C, K, P, D, X> &
419 basic_ptree<C, K, P, D, X>::get_child(const path_type &path,
420 basic_ptree<C, K, P, D, X> &default_value)
422 self_type *child = path.get_child(*this);
423 if (child)
424 return *child;
425 else
426 return default_value;
429 // Get child ptree
430 template<class C, class K, class P, class D, class X>
431 const basic_ptree<C, K, P, D, X> &
432 basic_ptree<C, K, P, D, X>::get_child(const path_type &path,
433 const basic_ptree<C, K, P, D, X> &default_value) const
435 self_type *nc_this = const_cast<self_type *>(this);
436 self_type &nc_default_value = const_cast<self_type &>(default_value);
437 return nc_this->get_child(path, nc_default_value);
441 // Get child ptree
442 template<class C, class K, class P, class D, class X>
443 optional<basic_ptree<C, K, P, D, X> &>
444 basic_ptree<C, K, P, D, X>::get_child_optional(const path_type &path)
446 self_type *child = path.get_child(*this);
447 if (child)
448 return optional<self_type &>(*child);
449 else
450 return optional<self_type &>();
453 // Get child ptree
454 template<class C, class K, class P, class D, class X>
455 optional<const basic_ptree<C, K, P, D, X> &>
456 basic_ptree<C, K, P, D, X>::get_child_optional(const path_type &path) const
458 self_type *nc_this = const_cast<self_type *>(this);
459 optional<self_type &> tmp = nc_this->get_child_optional(path);
460 if (tmp)
461 return optional<const self_type &>(tmp.get());
462 else
463 return optional<const self_type &>();
466 // Put child ptree
467 template<class C, class K, class P, class D, class X>
468 basic_ptree<C, K, P, D, X> &
469 basic_ptree<C, K, P, D, X>::put_child(const path_type &path,
470 const basic_ptree<C, K, P, D, X> &value,
471 bool do_not_replace)
473 self_type *child = path.put_child(*this, value, do_not_replace);
474 if (child)
475 return *child;
476 else
477 BOOST_PROPERTY_TREE_THROW(ptree_bad_path("path does not exist", path));
480 // Get value from data of ptree
481 template<class C, class K, class P, class D, class X>
482 template<class Type>
483 Type basic_ptree<C, K, P, D, X>::get_value(const translator_type &x) const
485 BOOST_STATIC_ASSERT(boost::is_pointer<Type>::value == false); // Disallow pointer types, they are unsafe
486 Type value;
487 if (x.get_value(*this, value))
488 return value;
489 else
490 BOOST_PROPERTY_TREE_THROW(ptree_bad_data(std::string("conversion of data into type \"") +
491 typeid(Type).name() + "\" failed", data()));
494 // Get value from data of ptree
495 template<class C, class K, class P, class D, class X>
496 template<class Type>
497 Type basic_ptree<C, K, P, D, X>::get_value(const Type &default_value,
498 const translator_type &x) const
500 BOOST_STATIC_ASSERT(boost::is_pointer<Type>::value == false); // Disallow pointer types, they are unsafe
501 Type value;
502 if (x.get_value(*this, value))
503 return value;
504 else
505 return default_value;
508 // Get value from data of ptree
509 template<class C, class K, class P, class D, class X>
510 template<class CharType>
511 std::basic_string<CharType>
512 basic_ptree<C, K, P, D, X>::get_value(const CharType *default_value,
513 const translator_type &x) const
515 return get_value(std::basic_string<CharType>(default_value), x);
518 // Get value from data of ptree
519 template<class C, class K, class P, class D, class X>
520 template<class Type>
521 optional<Type>
522 basic_ptree<C, K, P, D, X>::get_value_optional(const translator_type &x) const
524 BOOST_STATIC_ASSERT(boost::is_pointer<Type>::value == false); // Disallow pointer types, they are unsafe
525 Type value;
526 if (x.get_value(*this, value))
527 return optional<Type>(value);
528 else
529 return optional<Type>();
532 // Get value from data of child ptree
533 template<class C, class K, class P, class D, class X>
534 template<class Type>
535 Type basic_ptree<C, K, P, D, X>::get(const path_type &path,
536 const translator_type &x) const
538 return get_child(path).get_value<Type>(x);
541 // Get value from data of child ptree
542 template<class C, class K, class P, class D, class X>
543 template<class Type>
544 Type basic_ptree<C, K, P, D, X>::get(const path_type &path,
545 const Type &default_value,
546 const translator_type &x) const
548 if (optional<Type> result = get_optional<Type>(path, x))
549 return *result;
550 else
551 return default_value;
554 // Get value from data of child ptree
555 template<class C, class K, class P, class D, class X>
556 template<class CharType>
557 std::basic_string<CharType>
558 basic_ptree<C, K, P, D, X>::get(const path_type &path,
559 const CharType *default_value,
560 const translator_type &x) const
562 return get(path, std::basic_string<CharType>(default_value), x);
565 // Get value from data of child ptree
566 template<class C, class K, class P, class D, class X>
567 template<class Type>
568 optional<Type>
569 basic_ptree<C, K, P, D, X>::get_optional(const path_type &path,
570 const translator_type &x) const
572 if (optional<const basic_ptree<C, K, P, D, X> &> child = get_child_optional(path))
573 return child.get().get_value_optional<Type>(x);
574 else
575 return optional<Type>();
578 // Put value in data of ptree
579 template<class C, class K, class P, class D, class X>
580 template<class Type>
581 void basic_ptree<C, K, P, D, X>::put_value(const Type &value, const translator_type &x)
583 if (!x.put_value(*this, value))
584 BOOST_PROPERTY_TREE_THROW(ptree_bad_data(std::string("conversion of type \"") + typeid(Type).name() +
585 "\" into data failed", boost::any()));
588 // Put value in data of child ptree
589 template<class C, class K, class P, class D, class X>
590 template<class Type>
591 basic_ptree<C, K, P, D, X> &
592 basic_ptree<C, K, P, D, X>::put(const path_type &path,
593 const Type &value,
594 bool do_not_replace,
595 const translator_type &x)
597 optional<self_type &> child;
598 if (!do_not_replace && (child = get_child_optional(path)))
600 child.get().put_value(value, x);
601 return *child;
603 else
605 self_type &child2 = put_child(path, empty_ptree<self_type>(), do_not_replace);
606 child2.put_value(value, x);
607 return child2;
611 ////////////////////////////////////////////////////////////////////////////
612 // Debugging
614 #ifdef BOOST_PROPERTY_TREE_DEBUG
616 template<class C, class K, class P, class D, class X>
617 typename basic_ptree<C, K, P, D, X>::size_type
618 basic_ptree<C, K, P, D, X>::debug_get_instances_count()
620 empty_ptree<basic_ptree<C, K, P, D, X> >(); // Make sure empty ptree exists
621 return debug_instances_count - 1; // Do not count empty ptree
624 template<class C, class K, class P, class D, class X>
625 typename basic_ptree<C, K, P, D, X>::size_type
626 basic_ptree<C, K, P, D, X>::debug_instances_count;
628 template<class C, class K, class P, class D, class X>
629 boost::detail::lightweight_mutex
630 basic_ptree<C, K, P, D, X>::debug_mutex;
632 #endif
634 ///////////////////////////////////////////////////////////////////////////
635 // Free functions
637 template<class Ptree>
638 inline const Ptree &empty_ptree()
640 static Ptree pt;
641 return pt;
644 template<class C, class K, class P, class D, class X>
645 inline void swap(basic_ptree<C, K, P, D, X> &pt1, basic_ptree<C, K, P, D, X> &pt2)
647 pt1.swap(pt2);
652 // Undefine debug macros
653 #ifdef BOOST_PROPERTY_TREE_DEBUG
654 # undef BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT
655 # undef BOOST_PROPERTY_TREE_DEBUG_DECREMENT_INSTANCES_COUNT
656 #endif
658 #endif