1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2002-2006 Marcin Kalicinski
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)
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 //////////////////////////////////////////////////////////////////////////////
16 #ifdef BOOST_PROPERTY_TREE_DEBUG
18 // Increment instances counter
19 #define BOOST_PROPERTY_TREE_DEBUG_INCREMENT_INSTANCES_COUNT() \
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() \
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
):
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
)
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 ///////////////////////////////////////////////////////////////////////////
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 ///////////////////////////////////////////////////////////////////////////
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()
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
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 ///////////////////////////////////////////////////////////////////////////
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
)
210 insert(end(), rhs
.begin(), rhs
.end());
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())
223 // Keys and children must be equal
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
)
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
)
255 for (iterator it
= begin(); it
!= end(); ++it
)
256 if (!comp(it
->first
, key
) && !comp(key
, it
->first
))
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
266 for (const_iterator it
= begin(); it
!= end(); ++it
)
267 if (!comp(it
->first
, key
) && !comp(key
, it
->first
))
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
278 for (const_iterator it
= begin(); it
!= end(); ++it
)
279 if (!comp(it
->first
, key
) && !comp(key
, it
->first
))
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();
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
>
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
)
320 iterator it
= m_container
.begin();
321 while (it
!= m_container
.end())
323 if (!comp(it
->first
, key
) && !comp(key
, it
->first
))
334 template<class C
, class K
, class P
, class D
, class X
>
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
);
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()
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();
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 ///////////////////////////////////////////////////////////////////////////
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);
404 BOOST_PROPERTY_TREE_THROW(ptree_bad_path("path does not exist", path
));
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
);
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);
426 return default_value
;
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
);
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);
448 return optional
<self_type
&>(*child
);
450 return optional
<self_type
&>();
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
);
461 return optional
<const self_type
&>(tmp
.get());
463 return optional
<const self_type
&>();
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
,
473 self_type
*child
= path
.put_child(*this, value
, do_not_replace
);
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
>
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
487 if (x
.get_value(*this, value
))
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
>
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
502 if (x
.get_value(*this, value
))
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
>
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
526 if (x
.get_value(*this, value
))
527 return optional
<Type
>(value
);
529 return optional
<Type
>();
532 // Get value from data of child ptree
533 template<class C
, class K
, class P
, class D
, class X
>
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
>
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
))
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
>
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
);
575 return optional
<Type
>();
578 // Put value in data of ptree
579 template<class C
, class K
, class P
, class D
, class X
>
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
>
591 basic_ptree
<C
, K
, P
, D
, X
> &
592 basic_ptree
<C
, K
, P
, D
, X
>::put(const path_type
&path
,
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
);
605 self_type
&child2
= put_child(path
, empty_ptree
<self_type
>(), do_not_replace
);
606 child2
.put_value(value
, x
);
611 ////////////////////////////////////////////////////////////////////////////
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
;
634 ///////////////////////////////////////////////////////////////////////////
637 template<class Ptree
>
638 inline const Ptree
&empty_ptree()
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
)
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