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