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