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