ptree_implementation.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  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. #ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
  12. #define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
  13. #include <boost/property_tree/ptree.hpp>
  14. #include <boost/iterator/iterator_adaptor.hpp>
  15. #include <boost/iterator/reverse_iterator.hpp>
  16. #include <boost/assert.hpp>
  17. #include <boost/core/invoke_swap.hpp>
  18. #include <boost/core/type_name.hpp>
  19. #include <memory>
  20. #if (defined(BOOST_MSVC) && \
  21. (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
  22. (defined(BOOST_INTEL_WIN) && \
  23. defined(BOOST_DINKUMWARE_STDLIB))
  24. #define BOOST_PROPERTY_TREE_PAIR_BUG
  25. #endif
  26. namespace boost { namespace property_tree
  27. {
  28. template <class K, class D, class C>
  29. struct basic_ptree<K, D, C>::subs
  30. {
  31. struct by_name {};
  32. // The actual child container.
  33. #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
  34. // MSVC 10 has moved std::pair's members to a base
  35. // class. Unfortunately this does break the interface.
  36. BOOST_STATIC_CONSTANT(unsigned,
  37. first_offset = offsetof(value_type, first));
  38. #endif
  39. typedef multi_index_container<value_type,
  40. multi_index::indexed_by<
  41. multi_index::sequenced<>,
  42. multi_index::ordered_non_unique<multi_index::tag<by_name>,
  43. #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
  44. multi_index::member_offset<value_type, const key_type,
  45. first_offset>,
  46. #else
  47. multi_index::member<value_type, const key_type,
  48. &value_type::first>,
  49. #endif
  50. key_compare
  51. >
  52. >
  53. > base_container;
  54. // The by-name lookup index.
  55. typedef typename base_container::template index<by_name>::type
  56. by_name_index;
  57. // Access functions for getting to the children of a tree.
  58. static base_container& ch(self_type *s) {
  59. return *static_cast<base_container*>(s->m_children);
  60. }
  61. static const base_container& ch(const self_type *s) {
  62. return *static_cast<const base_container*>(s->m_children);
  63. }
  64. static by_name_index& assoc(self_type *s) {
  65. return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
  66. }
  67. static const by_name_index& assoc(const self_type *s) {
  68. return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
  69. }
  70. };
  71. template <class K, class D, class C>
  72. class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
  73. iterator, typename subs::base_container::iterator, value_type>
  74. {
  75. friend class boost::iterator_core_access;
  76. typedef boost::iterator_adaptor<
  77. iterator, typename subs::base_container::iterator, value_type>
  78. baset;
  79. public:
  80. typedef typename baset::reference reference;
  81. iterator() {}
  82. explicit iterator(typename iterator::base_type b)
  83. : iterator::iterator_adaptor_(b)
  84. {}
  85. reference dereference() const
  86. {
  87. // multi_index doesn't allow modification of its values, because
  88. // indexes could sort by anything, and modification screws that up.
  89. // However, we only sort by the key, and it's protected against
  90. // modification in the value_type, so this const_cast is safe.
  91. return const_cast<reference>(*this->base_reference());
  92. }
  93. };
  94. template <class K, class D, class C>
  95. class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
  96. const_iterator, typename subs::base_container::const_iterator>
  97. {
  98. public:
  99. const_iterator() {}
  100. explicit const_iterator(typename const_iterator::base_type b)
  101. : const_iterator::iterator_adaptor_(b)
  102. {}
  103. const_iterator(iterator b)
  104. : const_iterator::iterator_adaptor_(b.base())
  105. {}
  106. };
  107. template <class K, class D, class C>
  108. class basic_ptree<K, D, C>::reverse_iterator
  109. : public boost::reverse_iterator<iterator>
  110. {
  111. public:
  112. reverse_iterator() {}
  113. explicit reverse_iterator(iterator b)
  114. : boost::reverse_iterator<iterator>(b)
  115. {}
  116. };
  117. template <class K, class D, class C>
  118. class basic_ptree<K, D, C>::const_reverse_iterator
  119. : public boost::reverse_iterator<const_iterator>
  120. {
  121. public:
  122. const_reverse_iterator() {}
  123. explicit const_reverse_iterator(const_iterator b)
  124. : boost::reverse_iterator<const_iterator>(b)
  125. {}
  126. const_reverse_iterator(
  127. typename basic_ptree<K, D, C>::reverse_iterator b)
  128. : boost::reverse_iterator<const_iterator>(b)
  129. {}
  130. };
  131. template <class K, class D, class C>
  132. class basic_ptree<K, D, C>::assoc_iterator
  133. : public boost::iterator_adaptor<assoc_iterator,
  134. typename subs::by_name_index::iterator,
  135. value_type>
  136. {
  137. friend class boost::iterator_core_access;
  138. typedef boost::iterator_adaptor<assoc_iterator,
  139. typename subs::by_name_index::iterator,
  140. value_type>
  141. baset;
  142. public:
  143. typedef typename baset::reference reference;
  144. assoc_iterator() {}
  145. explicit assoc_iterator(typename assoc_iterator::base_type b)
  146. : assoc_iterator::iterator_adaptor_(b)
  147. {}
  148. reference dereference() const
  149. {
  150. return const_cast<reference>(*this->base_reference());
  151. }
  152. };
  153. template <class K, class D, class C>
  154. class basic_ptree<K, D, C>::const_assoc_iterator
  155. : public boost::iterator_adaptor<const_assoc_iterator,
  156. typename subs::by_name_index::const_iterator>
  157. {
  158. public:
  159. const_assoc_iterator() {}
  160. explicit const_assoc_iterator(
  161. typename const_assoc_iterator::base_type b)
  162. : const_assoc_iterator::iterator_adaptor_(b)
  163. {}
  164. const_assoc_iterator(assoc_iterator b)
  165. : const_assoc_iterator::iterator_adaptor_(b.base())
  166. {}
  167. };
  168. // Big five
  169. // Perhaps the children collection could be created on-demand only, to
  170. // reduce heap traffic. But that's a lot more work to implement.
  171. template<class K, class D, class C> inline
  172. basic_ptree<K, D, C>::basic_ptree()
  173. : m_children(new typename subs::base_container)
  174. {
  175. }
  176. template<class K, class D, class C> inline
  177. basic_ptree<K, D, C>::basic_ptree(const data_type &d)
  178. : m_data(d), m_children(new typename subs::base_container)
  179. {
  180. }
  181. template<class K, class D, class C> inline
  182. basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
  183. : m_data(rhs.m_data),
  184. m_children(new typename subs::base_container(subs::ch(&rhs)))
  185. {
  186. }
  187. template<class K, class D, class C>
  188. basic_ptree<K, D, C> &
  189. basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
  190. {
  191. self_type(rhs).swap(*this);
  192. return *this;
  193. }
  194. template<class K, class D, class C>
  195. basic_ptree<K, D, C>::~basic_ptree()
  196. {
  197. delete &subs::ch(this);
  198. }
  199. template<class K, class D, class C> inline
  200. void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
  201. {
  202. boost::core::invoke_swap(m_data, rhs.m_data);
  203. // Void pointers, no ADL necessary
  204. std::swap(m_children, rhs.m_children);
  205. }
  206. // Container view
  207. template<class K, class D, class C> inline
  208. typename basic_ptree<K, D, C>::size_type
  209. basic_ptree<K, D, C>::size() const
  210. {
  211. return subs::ch(this).size();
  212. }
  213. template<class K, class D, class C> inline
  214. typename basic_ptree<K, D, C>::size_type
  215. basic_ptree<K, D, C>::max_size() const
  216. {
  217. return subs::ch(this).max_size();
  218. }
  219. template<class K, class D, class C> inline
  220. bool basic_ptree<K, D, C>::empty() const
  221. {
  222. return subs::ch(this).empty();
  223. }
  224. template<class K, class D, class C> inline
  225. typename basic_ptree<K, D, C>::iterator
  226. basic_ptree<K, D, C>::begin()
  227. {
  228. return iterator(subs::ch(this).begin());
  229. }
  230. template<class K, class D, class C> inline
  231. typename basic_ptree<K, D, C>::const_iterator
  232. basic_ptree<K, D, C>::begin() const
  233. {
  234. return const_iterator(subs::ch(this).begin());
  235. }
  236. template<class K, class D, class C> inline
  237. typename basic_ptree<K, D, C>::iterator
  238. basic_ptree<K, D, C>::end()
  239. {
  240. return iterator(subs::ch(this).end());
  241. }
  242. template<class K, class D, class C> inline
  243. typename basic_ptree<K, D, C>::const_iterator
  244. basic_ptree<K, D, C>::end() const
  245. {
  246. return const_iterator(subs::ch(this).end());
  247. }
  248. template<class K, class D, class C> inline
  249. typename basic_ptree<K, D, C>::reverse_iterator
  250. basic_ptree<K, D, C>::rbegin()
  251. {
  252. return reverse_iterator(this->end());
  253. }
  254. template<class K, class D, class C> inline
  255. typename basic_ptree<K, D, C>::const_reverse_iterator
  256. basic_ptree<K, D, C>::rbegin() const
  257. {
  258. return const_reverse_iterator(this->end());
  259. }
  260. template<class K, class D, class C> inline
  261. typename basic_ptree<K, D, C>::reverse_iterator
  262. basic_ptree<K, D, C>::rend()
  263. {
  264. return reverse_iterator(this->begin());
  265. }
  266. template<class K, class D, class C> inline
  267. typename basic_ptree<K, D, C>::const_reverse_iterator
  268. basic_ptree<K, D, C>::rend() const
  269. {
  270. return const_reverse_iterator(this->begin());
  271. }
  272. template<class K, class D, class C> inline
  273. typename basic_ptree<K, D, C>::value_type &
  274. basic_ptree<K, D, C>::front()
  275. {
  276. return const_cast<value_type&>(subs::ch(this).front());
  277. }
  278. template<class K, class D, class C> inline
  279. const typename basic_ptree<K, D, C>::value_type &
  280. basic_ptree<K, D, C>::front() const
  281. {
  282. return subs::ch(this).front();
  283. }
  284. template<class K, class D, class C> inline
  285. typename basic_ptree<K, D, C>::value_type &
  286. basic_ptree<K, D, C>::back()
  287. {
  288. return const_cast<value_type&>(subs::ch(this).back());
  289. }
  290. template<class K, class D, class C> inline
  291. const typename basic_ptree<K, D, C>::value_type &
  292. basic_ptree<K, D, C>::back() const
  293. {
  294. return subs::ch(this).back();
  295. }
  296. template<class K, class D, class C> inline
  297. typename basic_ptree<K, D, C>::iterator
  298. basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
  299. {
  300. return iterator(subs::ch(this).insert(where.base(), value).first);
  301. }
  302. template<class K, class D, class C>
  303. template<class It> inline
  304. void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
  305. {
  306. subs::ch(this).insert(where.base(), first, last);
  307. }
  308. template<class K, class D, class C> inline
  309. typename basic_ptree<K, D, C>::iterator
  310. basic_ptree<K, D, C>::erase(iterator where)
  311. {
  312. return iterator(subs::ch(this).erase(where.base()));
  313. }
  314. template<class K, class D, class C> inline
  315. typename basic_ptree<K, D, C>::iterator
  316. basic_ptree<K, D, C>::erase(iterator first, iterator last)
  317. {
  318. return iterator(subs::ch(this).erase(first.base(), last.base()));
  319. }
  320. template<class K, class D, class C> inline
  321. typename basic_ptree<K, D, C>::iterator
  322. basic_ptree<K, D, C>::push_front(const value_type &value)
  323. {
  324. return iterator(subs::ch(this).push_front(value).first);
  325. }
  326. template<class K, class D, class C> inline
  327. typename basic_ptree<K, D, C>::iterator
  328. basic_ptree<K, D, C>::push_back(const value_type &value)
  329. {
  330. return iterator(subs::ch(this).push_back(value).first);
  331. }
  332. template<class K, class D, class C> inline
  333. void basic_ptree<K, D, C>::pop_front()
  334. {
  335. subs::ch(this).pop_front();
  336. }
  337. template<class K, class D, class C> inline
  338. void basic_ptree<K, D, C>::pop_back()
  339. {
  340. subs::ch(this).pop_back();
  341. }
  342. template<class K, class D, class C> inline
  343. void basic_ptree<K, D, C>::reverse()
  344. {
  345. subs::ch(this).reverse();
  346. }
  347. namespace impl
  348. {
  349. struct by_first
  350. {
  351. template <typename P>
  352. bool operator ()(const P& lhs, const P& rhs) const {
  353. return lhs.first < rhs.first;
  354. }
  355. };
  356. template <typename C>
  357. struct equal_pred
  358. {
  359. template <typename P>
  360. bool operator ()(const P& lhs, const P& rhs) const {
  361. C c;
  362. return !c(lhs.first, rhs.first) &&
  363. !c(rhs.first, lhs.first) &&
  364. lhs.second == rhs.second;
  365. }
  366. };
  367. template <typename C, typename MI>
  368. bool equal_children(const MI& ch1, const MI& ch2) {
  369. // Assumes ch1.size() == ch2.size()
  370. return std::equal(ch1.begin(), ch1.end(),
  371. ch2.begin(), equal_pred<C>());
  372. }
  373. }
  374. template<class K, class D, class C> inline
  375. void basic_ptree<K, D, C>::sort()
  376. {
  377. sort(impl::by_first());
  378. }
  379. template<class K, class D, class C>
  380. template<class Compare> inline
  381. void basic_ptree<K, D, C>::sort(Compare comp)
  382. {
  383. subs::ch(this).sort(comp);
  384. }
  385. // Equality
  386. template<class K, class D, class C> inline
  387. bool basic_ptree<K, D, C>::operator ==(
  388. const basic_ptree<K, D, C> &rhs) const
  389. {
  390. // The size test is cheap, so add it as an optimization
  391. return size() == rhs.size() && data() == rhs.data() &&
  392. impl::equal_children<C>(subs::ch(this), subs::ch(&rhs));
  393. }
  394. template<class K, class D, class C> inline
  395. bool basic_ptree<K, D, C>::operator !=(
  396. const basic_ptree<K, D, C> &rhs) const
  397. {
  398. return !(*this == rhs);
  399. }
  400. // Associative view
  401. template<class K, class D, class C> inline
  402. typename basic_ptree<K, D, C>::assoc_iterator
  403. basic_ptree<K, D, C>::ordered_begin()
  404. {
  405. return assoc_iterator(subs::assoc(this).begin());
  406. }
  407. template<class K, class D, class C> inline
  408. typename basic_ptree<K, D, C>::const_assoc_iterator
  409. basic_ptree<K, D, C>::ordered_begin() const
  410. {
  411. return const_assoc_iterator(subs::assoc(this).begin());
  412. }
  413. template<class K, class D, class C> inline
  414. typename basic_ptree<K, D, C>::assoc_iterator
  415. basic_ptree<K, D, C>::not_found()
  416. {
  417. return assoc_iterator(subs::assoc(this).end());
  418. }
  419. template<class K, class D, class C> inline
  420. typename basic_ptree<K, D, C>::const_assoc_iterator
  421. basic_ptree<K, D, C>::not_found() const
  422. {
  423. return const_assoc_iterator(subs::assoc(this).end());
  424. }
  425. template<class K, class D, class C> inline
  426. typename basic_ptree<K, D, C>::assoc_iterator
  427. basic_ptree<K, D, C>::find(const key_type &key)
  428. {
  429. return assoc_iterator(subs::assoc(this).find(key));
  430. }
  431. template<class K, class D, class C> inline
  432. typename basic_ptree<K, D, C>::const_assoc_iterator
  433. basic_ptree<K, D, C>::find(const key_type &key) const
  434. {
  435. return const_assoc_iterator(subs::assoc(this).find(key));
  436. }
  437. template<class K, class D, class C> inline
  438. std::pair<
  439. typename basic_ptree<K, D, C>::assoc_iterator,
  440. typename basic_ptree<K, D, C>::assoc_iterator
  441. > basic_ptree<K, D, C>::equal_range(const key_type &key)
  442. {
  443. std::pair<typename subs::by_name_index::iterator,
  444. typename subs::by_name_index::iterator> r(
  445. subs::assoc(this).equal_range(key));
  446. return std::pair<assoc_iterator, assoc_iterator>(
  447. assoc_iterator(r.first), assoc_iterator(r.second));
  448. }
  449. template<class K, class D, class C> inline
  450. std::pair<
  451. typename basic_ptree<K, D, C>::const_assoc_iterator,
  452. typename basic_ptree<K, D, C>::const_assoc_iterator
  453. > basic_ptree<K, D, C>::equal_range(const key_type &key) const
  454. {
  455. std::pair<typename subs::by_name_index::const_iterator,
  456. typename subs::by_name_index::const_iterator> r(
  457. subs::assoc(this).equal_range(key));
  458. return std::pair<const_assoc_iterator, const_assoc_iterator>(
  459. const_assoc_iterator(r.first), const_assoc_iterator(r.second));
  460. }
  461. template<class K, class D, class C> inline
  462. typename basic_ptree<K, D, C>::size_type
  463. basic_ptree<K, D, C>::count(const key_type &key) const
  464. {
  465. return subs::assoc(this).count(key);
  466. }
  467. template<class K, class D, class C> inline
  468. typename basic_ptree<K, D, C>::size_type
  469. basic_ptree<K, D, C>::erase(const key_type &key)
  470. {
  471. return subs::assoc(this).erase(key);
  472. }
  473. template<class K, class D, class C> inline
  474. typename basic_ptree<K, D, C>::iterator
  475. basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
  476. {
  477. return iterator(subs::ch(this).
  478. BOOST_NESTED_TEMPLATE project<0>(ai.base()));
  479. }
  480. template<class K, class D, class C> inline
  481. typename basic_ptree<K, D, C>::const_iterator
  482. basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
  483. {
  484. return const_iterator(subs::ch(this).
  485. BOOST_NESTED_TEMPLATE project<0>(ai.base()));
  486. }
  487. // Property tree view
  488. template<class K, class D, class C> inline
  489. typename basic_ptree<K, D, C>::data_type &
  490. basic_ptree<K, D, C>::data()
  491. {
  492. return m_data;
  493. }
  494. template<class K, class D, class C> inline
  495. const typename basic_ptree<K, D, C>::data_type &
  496. basic_ptree<K, D, C>::data() const
  497. {
  498. return m_data;
  499. }
  500. template<class K, class D, class C> inline
  501. void basic_ptree<K, D, C>::clear()
  502. {
  503. m_data = data_type();
  504. subs::ch(this).clear();
  505. }
  506. template<class K, class D, class C>
  507. basic_ptree<K, D, C> &
  508. basic_ptree<K, D, C>::get_child(const path_type &path)
  509. {
  510. path_type p(path);
  511. self_type *n = walk_path(p);
  512. if (!n) {
  513. BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
  514. }
  515. return *n;
  516. }
  517. template<class K, class D, class C> inline
  518. const basic_ptree<K, D, C> &
  519. basic_ptree<K, D, C>::get_child(const path_type &path) const
  520. {
  521. return const_cast<self_type*>(this)->get_child(path);
  522. }
  523. template<class K, class D, class C> inline
  524. basic_ptree<K, D, C> &
  525. basic_ptree<K, D, C>::get_child(const path_type &path,
  526. self_type &default_value)
  527. {
  528. path_type p(path);
  529. self_type *n = walk_path(p);
  530. return n ? *n : default_value;
  531. }
  532. template<class K, class D, class C> inline
  533. const basic_ptree<K, D, C> &
  534. basic_ptree<K, D, C>::get_child(const path_type &path,
  535. const self_type &default_value) const
  536. {
  537. return const_cast<self_type*>(this)->get_child(path,
  538. const_cast<self_type&>(default_value));
  539. }
  540. template<class K, class D, class C>
  541. optional<basic_ptree<K, D, C> &>
  542. basic_ptree<K, D, C>::get_child_optional(const path_type &path)
  543. {
  544. path_type p(path);
  545. self_type *n = walk_path(p);
  546. if (!n) {
  547. return optional<self_type&>();
  548. }
  549. return *n;
  550. }
  551. template<class K, class D, class C>
  552. optional<const basic_ptree<K, D, C> &>
  553. basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
  554. {
  555. path_type p(path);
  556. self_type *n = walk_path(p);
  557. if (!n) {
  558. return optional<const self_type&>();
  559. }
  560. return *n;
  561. }
  562. template<class K, class D, class C>
  563. basic_ptree<K, D, C> &
  564. basic_ptree<K, D, C>::put_child(const path_type &path,
  565. const self_type &value)
  566. {
  567. path_type p(path);
  568. self_type &parent = force_path(p);
  569. // Got the parent. Now get the correct child.
  570. key_type fragment = p.reduce();
  571. assoc_iterator el = parent.find(fragment);
  572. // If the new child exists, replace it.
  573. if(el != parent.not_found()) {
  574. return el->second = value;
  575. } else {
  576. return parent.push_back(value_type(fragment, value))->second;
  577. }
  578. }
  579. template<class K, class D, class C>
  580. basic_ptree<K, D, C> &
  581. basic_ptree<K, D, C>::add_child(const path_type &path,
  582. const self_type &value)
  583. {
  584. path_type p(path);
  585. self_type &parent = force_path(p);
  586. // Got the parent.
  587. key_type fragment = p.reduce();
  588. return parent.push_back(value_type(fragment, value))->second;
  589. }
  590. template<class K, class D, class C>
  591. template<class Type, class Translator>
  592. typename boost::enable_if<detail::is_translator<Translator>, Type>::type
  593. basic_ptree<K, D, C>::get_value(Translator tr) const
  594. {
  595. if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
  596. return *o;
  597. }
  598. BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
  599. std::string("conversion of data to type \"") +
  600. boost::core::type_name<Type>() + "\" failed", data()));
  601. }
  602. template<class K, class D, class C>
  603. template<class Type> inline
  604. Type basic_ptree<K, D, C>::get_value() const
  605. {
  606. return get_value<Type>(
  607. typename translator_between<data_type, Type>::type());
  608. }
  609. template<class K, class D, class C>
  610. template<class Type, class Translator> inline
  611. Type basic_ptree<K, D, C>::get_value(const Type &default_value,
  612. Translator tr) const
  613. {
  614. return get_value_optional<Type>(tr).get_value_or(default_value);
  615. }
  616. template<class K, class D, class C>
  617. template <class Ch, class Translator>
  618. typename boost::enable_if<
  619. detail::is_character<Ch>,
  620. std::basic_string<Ch>
  621. >::type
  622. basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
  623. {
  624. return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
  625. }
  626. template<class K, class D, class C>
  627. template<class Type> inline
  628. typename boost::disable_if<detail::is_translator<Type>, Type>::type
  629. basic_ptree<K, D, C>::get_value(const Type &default_value) const
  630. {
  631. return get_value(default_value,
  632. typename translator_between<data_type, Type>::type());
  633. }
  634. template<class K, class D, class C>
  635. template <class Ch>
  636. typename boost::enable_if<
  637. detail::is_character<Ch>,
  638. std::basic_string<Ch>
  639. >::type
  640. basic_ptree<K, D, C>::get_value(const Ch *default_value) const
  641. {
  642. return get_value< std::basic_string<Ch> >(default_value);
  643. }
  644. template<class K, class D, class C>
  645. template<class Type, class Translator> inline
  646. optional<Type> basic_ptree<K, D, C>::get_value_optional(
  647. Translator tr) const
  648. {
  649. return tr.get_value(data());
  650. }
  651. template<class K, class D, class C>
  652. template<class Type> inline
  653. optional<Type> basic_ptree<K, D, C>::get_value_optional() const
  654. {
  655. return get_value_optional<Type>(
  656. typename translator_between<data_type, Type>::type());
  657. }
  658. template<class K, class D, class C>
  659. template<class Type, class Translator> inline
  660. typename boost::enable_if<detail::is_translator<Translator>, Type>::type
  661. basic_ptree<K, D, C>::get(const path_type &path,
  662. Translator tr) const
  663. {
  664. return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
  665. }
  666. template<class K, class D, class C>
  667. template<class Type> inline
  668. Type basic_ptree<K, D, C>::get(const path_type &path) const
  669. {
  670. return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
  671. }
  672. template<class K, class D, class C>
  673. template<class Type, class Translator> inline
  674. Type basic_ptree<K, D, C>::get(const path_type &path,
  675. const Type &default_value,
  676. Translator tr) const
  677. {
  678. return get_optional<Type>(path, tr).get_value_or(default_value);
  679. }
  680. template<class K, class D, class C>
  681. template <class Ch, class Translator>
  682. typename boost::enable_if<
  683. detail::is_character<Ch>,
  684. std::basic_string<Ch>
  685. >::type
  686. basic_ptree<K, D, C>::get(
  687. const path_type &path, const Ch *default_value, Translator tr) const
  688. {
  689. return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
  690. }
  691. template<class K, class D, class C>
  692. template<class Type> inline
  693. typename boost::disable_if<detail::is_translator<Type>, Type>::type
  694. basic_ptree<K, D, C>::get(const path_type &path,
  695. const Type &default_value) const
  696. {
  697. return get_optional<Type>(path).get_value_or(default_value);
  698. }
  699. template<class K, class D, class C>
  700. template <class Ch>
  701. typename boost::enable_if<
  702. detail::is_character<Ch>,
  703. std::basic_string<Ch>
  704. >::type
  705. basic_ptree<K, D, C>::get(
  706. const path_type &path, const Ch *default_value) const
  707. {
  708. return get< std::basic_string<Ch> >(path, default_value);
  709. }
  710. template<class K, class D, class C>
  711. template<class Type, class Translator>
  712. optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
  713. Translator tr) const
  714. {
  715. if (optional<const self_type&> child = get_child_optional(path))
  716. return child.get().
  717. BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
  718. else
  719. return optional<Type>();
  720. }
  721. template<class K, class D, class C>
  722. template<class Type>
  723. optional<Type> basic_ptree<K, D, C>::get_optional(
  724. const path_type &path) const
  725. {
  726. if (optional<const self_type&> child = get_child_optional(path))
  727. return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
  728. else
  729. return optional<Type>();
  730. }
  731. template<class K, class D, class C>
  732. template<class Type, class Translator>
  733. void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
  734. {
  735. if(optional<data_type> o = tr.put_value(value)) {
  736. data() = *o;
  737. } else {
  738. BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
  739. std::string("conversion of type \"") + boost::core::type_name<Type>() +
  740. "\" to data failed", boost::any()));
  741. }
  742. }
  743. template<class K, class D, class C>
  744. template<class Type> inline
  745. void basic_ptree<K, D, C>::put_value(const Type &value)
  746. {
  747. put_value(value, typename translator_between<data_type, Type>::type());
  748. }
  749. template<class K, class D, class C>
  750. template<class Type, typename Translator>
  751. basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
  752. const path_type &path, const Type &value, Translator tr)
  753. {
  754. if(optional<self_type &> child = get_child_optional(path)) {
  755. child.get().put_value(value, tr);
  756. return *child;
  757. } else {
  758. self_type &child2 = put_child(path, self_type());
  759. child2.put_value(value, tr);
  760. return child2;
  761. }
  762. }
  763. template<class K, class D, class C>
  764. template<class Type> inline
  765. basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
  766. const path_type &path, const Type &value)
  767. {
  768. return put(path, value,
  769. typename translator_between<data_type, Type>::type());
  770. }
  771. template<class K, class D, class C>
  772. template<class Type, typename Translator> inline
  773. basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
  774. const path_type &path, const Type &value, Translator tr)
  775. {
  776. self_type &child = add_child(path, self_type());
  777. child.put_value(value, tr);
  778. return child;
  779. }
  780. template<class K, class D, class C>
  781. template<class Type> inline
  782. basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
  783. const path_type &path, const Type &value)
  784. {
  785. return add(path, value,
  786. typename translator_between<data_type, Type>::type());
  787. }
  788. template<class K, class D, class C>
  789. basic_ptree<K, D, C> *
  790. basic_ptree<K, D, C>::walk_path(path_type &p) const
  791. {
  792. if(p.empty()) {
  793. // I'm the child we're looking for.
  794. return const_cast<basic_ptree*>(this);
  795. }
  796. // Recurse down the tree to find the path.
  797. key_type fragment = p.reduce();
  798. const_assoc_iterator el = find(fragment);
  799. if(el == not_found()) {
  800. // No such child.
  801. return 0;
  802. }
  803. // Not done yet, recurse.
  804. return el->second.walk_path(p);
  805. }
  806. template<class K, class D, class C>
  807. basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
  808. {
  809. BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
  810. if(p.single()) {
  811. // I'm the parent we're looking for.
  812. return *this;
  813. }
  814. key_type fragment = p.reduce();
  815. assoc_iterator el = find(fragment);
  816. // If we've found an existing child, go down that path. Else
  817. // create a new one.
  818. self_type& child = el == not_found() ?
  819. push_back(value_type(fragment, self_type()))->second : el->second;
  820. return child.force_path(p);
  821. }
  822. // Free functions
  823. template<class K, class D, class C>
  824. inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
  825. {
  826. pt1.swap(pt2);
  827. }
  828. } }
  829. #if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
  830. #undef BOOST_PROPERTY_TREE_PAIR_BUG
  831. #endif
  832. #endif