ptree_implementation.hpp 31 KB

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