]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/support/utree/detail/utree_detail2.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / support / utree / detail / utree_detail2.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 Bryce Lelbach
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#if !defined(BOOST_SPIRIT_UTREE_DETAIL2)
10#define BOOST_SPIRIT_UTREE_DETAIL2
11
12#if defined(BOOST_MSVC)
13# pragma warning(push)
14# pragma warning(disable: 4800)
15#endif
16
17#include <boost/type_traits/remove_pointer.hpp>
18#include <boost/type_traits/is_pointer.hpp>
19#include <boost/utility/enable_if.hpp>
20#include <boost/throw_exception.hpp>
21#include <boost/iterator/iterator_traits.hpp>
92f5a8d4 22#include <cstring> // for std::memcpy
7c673cae
FG
23
24namespace boost { namespace spirit { namespace detail
25{
26 inline char& fast_string::info()
27 {
28 return buff[small_string_size];
29 }
30
31 inline char fast_string::info() const
32 {
33 return buff[small_string_size];
34 }
35
36 inline int fast_string::get_type() const
37 {
38 return info() >> 1;
39 }
40
41 inline void fast_string::set_type(int t)
42 {
43 info() = (t << 1) | (info() & 1);
44 }
45
46 inline short fast_string::tag() const
47 {
92f5a8d4
TL
48 boost::int16_t tmp;
49 std::memcpy(&tmp, &buff[small_string_size-2], sizeof(tmp));
50 return tmp;
7c673cae
FG
51 }
52
53 inline void fast_string::tag(short tag)
54 {
92f5a8d4
TL
55 boost::int16_t tmp = tag;
56 std::memcpy(&buff[small_string_size-2], &tmp, sizeof(tmp));
7c673cae
FG
57 }
58
59 inline bool fast_string::is_heap_allocated() const
60 {
61 return info() & 1;
62 }
63
64 inline std::size_t fast_string::size() const
65 {
66 if (is_heap_allocated())
67 return heap.size;
68 else
69 return max_string_len - buff[max_string_len];
70 }
71
72 inline char const* fast_string::str() const
73 {
74 if (is_heap_allocated())
75 return heap.str;
76 else
77 return buff;
78 }
79
80 template <typename Iterator>
81 inline void fast_string::construct(Iterator f, Iterator l)
82 {
11fdf7f2 83 std::size_t const size = static_cast<std::size_t>(l-f);
7c673cae
FG
84 char* str;
85 if (size < max_string_len)
86 {
87 // if it fits, store it in-situ; small_string_size minus the length
88 // of the string is placed in buff[small_string_size - 1]
89 str = buff;
90 buff[max_string_len] = static_cast<char>(max_string_len - size);
91 info() &= ~0x1;
92 }
93 else
94 {
95 // else, store it in the heap
96 str = new char[size + 1]; // add one for the null char
97 heap.str = str;
98 heap.size = size;
99 info() |= 0x1;
100 }
101 for (std::size_t i = 0; i != size; ++i)
102 {
103 *str++ = *f++;
104 }
105 *str = '\0'; // add the null char
106 }
107
108 inline void fast_string::swap(fast_string& other)
109 {
110 std::swap(*this, other);
111 }
112
113 inline void fast_string::free()
114 {
115 if (is_heap_allocated())
116 {
117 delete [] heap.str;
118 }
119 }
120
121 inline void fast_string::copy(fast_string const& other)
122 {
123 construct(other.str(), other.str() + other.size());
124 }
125
126 inline void fast_string::initialize()
127 {
128 for (std::size_t i = 0; i != buff_size / (sizeof(long)/sizeof(char)); ++i)
129 lbuff[i] = 0;
130 }
131
132 struct list::node : boost::noncopyable
133 {
134 template <typename T>
135 node(T const& val, node* next, node* prev)
136 : val(val), next(next), prev(prev) {}
137
138 void unlink()
139 {
140 prev->next = next;
141 next->prev = prev;
142 }
143
144 utree val;
145 node* next;
146 node* prev;
147 };
148
149 template <typename Value>
150 class list::node_iterator
151 : public boost::iterator_facade<
152 node_iterator<Value>
153 , Value
154 , boost::bidirectional_traversal_tag>
155 {
156 public:
157
158 node_iterator()
159 : node(0), prev(0) {}
160
161 node_iterator(list::node* node, list::node* prev)
162 : node(node), prev(prev) {}
163
164 private:
165
166 friend class boost::iterator_core_access;
167 friend class boost::spirit::utree;
168 friend struct boost::spirit::detail::list;
169
170 void increment()
171 {
172 if (node != 0) // not at end
173 {
174 prev = node;
175 node = node->next;
176 }
177 }
178
179 void decrement()
180 {
181 if (prev != 0) // not at begin
182 {
183 node = prev;
184 prev = prev->prev;
185 }
186 }
187
188 bool equal(node_iterator const& other) const
189 {
190 return node == other.node;
191 }
192
193 typename node_iterator::reference dereference() const
194 {
195 return node->val;
196 }
197
198 list::node* node;
199 list::node* prev;
200 };
201
202 template <typename Value>
203 class list::node_iterator<boost::reference_wrapper<Value> >
204 : public boost::iterator_facade<
205 node_iterator<boost::reference_wrapper<Value> >
206 , boost::reference_wrapper<Value>
207 , boost::bidirectional_traversal_tag>
208 {
209 public:
210
211 node_iterator()
212 : node(0), prev(0), curr(nil_node) {}
213
214 node_iterator(list::node* node, list::node* prev)
215 : node(node), prev(prev), curr(node ? node->val : nil_node) {}
216
217 private:
218
219 friend class boost::iterator_core_access;
220 friend class boost::spirit::utree;
221 friend struct boost::spirit::detail::list;
222
223 void increment()
224 {
225 if (node != 0) // not at end
226 {
227 prev = node;
228 node = node->next;
229 curr = boost::ref(node ? node->val : nil_node);
230 }
231 }
232
233 void decrement()
234 {
235 if (prev != 0) // not at begin
236 {
237 node = prev;
238 prev = prev->prev;
239 curr = boost::ref(node ? node->val : nil_node);
240 }
241 }
242
243 bool equal(node_iterator const& other) const
244 {
245 return node == other.node;
246 }
247
248 typename node_iterator::reference dereference() const
249 {
250 return curr;
251 }
252
253 list::node* node;
254 list::node* prev;
255
256 static Value nil_node;
257 mutable boost::reference_wrapper<Value> curr;
258 };
259
260 template <typename Value>
261 Value list::node_iterator<boost::reference_wrapper<Value> >::nil_node = Value();
262
263 inline void list::free()
264 {
265 node* p = first;
266 while (p != 0)
267 {
268 node* next = p->next;
269 delete p;
270 p = next;
271 }
272 }
273
274 inline void list::copy(list const& other)
275 {
276 node* p = other.first;
277 while (p != 0)
278 {
279 push_back(p->val);
280 p = p->next;
281 }
282 }
283
284 inline void list::default_construct()
285 {
286 first = last = 0;
287 size = 0;
288 }
289
290 template <typename T, typename Iterator>
291 inline void list::insert(T const& val, Iterator pos)
292 {
293 if (!pos.node)
294 {
295 push_back(val);
296 return;
297 }
298
299 detail::list::node* new_node =
300 new detail::list::node(val, pos.node, pos.node->prev);
301
302 if (pos.node->prev)
303 pos.node->prev->next = new_node;
304 else
305 first = new_node;
306
307 pos.node->prev = new_node;
308 ++size;
309 }
310
311 template <typename T>
312 inline void list::push_front(T const& val)
313 {
314 detail::list::node* new_node;
315 if (first == 0)
316 {
317 new_node = new detail::list::node(val, 0, 0);
318 first = last = new_node;
319 ++size;
320 }
321 else
322 {
323 new_node = new detail::list::node(val, first, first->prev);
324 first->prev = new_node;
325 first = new_node;
326 ++size;
327 }
328 }
329
330 template <typename T>
331 inline void list::push_back(T const& val)
332 {
333 if (last == 0)
334 push_front(val);
335 else {
336 detail::list::node* new_node =
337 new detail::list::node(val, last->next, last);
338 last->next = new_node;
339 last = new_node;
340 ++size;
341 }
342 }
343
344 inline void list::pop_front()
345 {
346 BOOST_ASSERT(size != 0);
347 if (first == last) // there's only one item
348 {
349 delete first;
350 size = 0;
351 first = last = 0;
352 }
353 else
354 {
355 node* np = first;
356 first = first->next;
357 first->prev = 0;
358 delete np;
359 --size;
360 }
361 }
362
363 inline void list::pop_back()
364 {
365 BOOST_ASSERT(size != 0);
366 if (first == last) // there's only one item
367 {
368 delete first;
369 size = 0;
370 first = last = 0;
371 }
372 else
373 {
374 node* np = last;
375 last = last->prev;
376 last->next = 0;
377 delete np;
378 --size;
379 }
380 }
381
382 inline list::node* list::erase(node* pos)
383 {
384 BOOST_ASSERT(pos != 0);
385 if (pos == first)
386 {
387 pop_front();
388 return first;
389 }
390 else if (pos == last)
391 {
392 pop_back();
393 return 0;
394 }
395 else
396 {
397 node* next(pos->next);
398 pos->unlink();
399 delete pos;
400 --size;
401 return next;
402 }
403 }
404
405 ///////////////////////////////////////////////////////////////////////////
406 // simple binder for binary visitation (we don't want to bring in the big guns)
407 template <typename F, typename X>
408 struct bind_impl
409 {
410 typedef typename F::result_type result_type;
411 X& x; // always by reference
412 F f;
413 bind_impl(F f, X& x) : x(x), f(f) {}
414
415 template <typename Y>
416 typename F::result_type operator()(Y& y) const
417 {
418 return f(x, y);
419 }
420
421 template <typename Y>
422 typename F::result_type operator()(Y const& y) const
423 {
424 return f(x, y);
425 }
426 };
427
428 template <typename F, typename X>
429 bind_impl<F, X const> bind(F f, X const& x)
430 {
431 return bind_impl<F, X const>(f, x);
432 }
433
434 template <typename F, typename X>
435 bind_impl<F, X> bind(F f, X& x)
436 {
437 return bind_impl<F, X>(f, x);
438 }
439
440 template <typename UTreeX, typename UTreeY = UTreeX>
441 struct visit_impl
442 {
443 template <typename F>
444 typename F::result_type
445 static apply(UTreeX& x, F f) // single dispatch
446 {
447 typedef typename
448 boost::mpl::if_<boost::is_const<UTreeX>,
449 typename UTreeX::const_iterator,
450 typename UTreeX::iterator>::type
451 iterator;
452
453 typedef boost::iterator_range<iterator> list_range;
454 typedef utree_type type;
455
456 switch (x.get_type())
457 {
458 default:
459 BOOST_THROW_EXCEPTION(
460 bad_type_exception("corrupt utree type", x.get_type()));
461 break;
462
463 case type::invalid_type:
464 return f(invalid);
465
466 case type::nil_type:
467 return f(nil);
468
469 case type::bool_type:
470 return f(x.b);
471
472 case type::int_type:
473 return f(x.i);
474
475 case type::double_type:
476 return f(x.d);
477
478 case type::list_type:
479 return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
480
481 case type::range_type:
482 return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
483
484 case type::string_type:
485 return f(utf8_string_range_type(x.s.str(), x.s.size()));
486
487 case type::string_range_type:
488 return f(utf8_string_range_type(x.sr.first, x.sr.last));
489
490 case type::symbol_type:
491 return f(utf8_symbol_range_type(x.s.str(), x.s.size()));
492
493 case type::binary_type:
494 return f(binary_range_type(x.s.str(), x.s.size()));
495
496 case type::reference_type:
497 return apply(*x.p, f);
498
499 case type::any_type:
500 return f(any_ptr(x.v.p, x.v.i));
501
502 case type::function_type:
503 return f(*x.pf);
504 }
505 }
506
507 template <typename F>
508 typename F::result_type
509 static apply(UTreeX& x, UTreeY& y, F f) // double dispatch
510 {
511 typedef typename
512 boost::mpl::if_<boost::is_const<UTreeX>,
513 typename UTreeX::const_iterator,
514 typename UTreeX::iterator>::type
515 iterator;
516
517 typedef boost::iterator_range<iterator> list_range;
518 typedef utree_type type;
519
520 switch (x.get_type())
521 {
522 default:
523 BOOST_THROW_EXCEPTION(
524 bad_type_exception("corrupt utree type", x.get_type()));
525 break;
526
527 case type::invalid_type:
528 return visit_impl::apply(y, detail::bind(f, invalid));
529
530 case type::nil_type:
531 return visit_impl::apply(y, detail::bind(f, nil));
532
533 case type::bool_type:
534 return visit_impl::apply(y, detail::bind(f, x.b));
535
536 case type::int_type:
537 return visit_impl::apply(y, detail::bind(f, x.i));
538
539 case type::double_type:
540 return visit_impl::apply(y, detail::bind(f, x.d));
541
542 case type::list_type:
543 return visit_impl::apply(
544 y, detail::bind<F, list_range>(f,
545 list_range(iterator(x.l.first, 0), iterator(0, x.l.last))));
546
547 case type::range_type:
548 return visit_impl::apply(
549 y, detail::bind<F, list_range>(f,
550 list_range(iterator(x.r.first, 0), iterator(0, x.r.last))));
551
552 case type::string_type:
553 return visit_impl::apply(y, detail::bind(
554 f, utf8_string_range_type(x.s.str(), x.s.size())));
555
556 case type::string_range_type:
557 return visit_impl::apply(y, detail::bind(
558 f, utf8_string_range_type(x.sr.first, x.sr.last)));
559
560 case type::symbol_type:
561 return visit_impl::apply(y, detail::bind(
562 f, utf8_symbol_range_type(x.s.str(), x.s.size())));
563
564 case type::binary_type:
565 return visit_impl::apply(y, detail::bind(
566 f, binary_range_type(x.s.str(), x.s.size())));
567
568 case type::reference_type:
569 return apply(*x.p, y, f);
570
571 case type::any_type:
572 return visit_impl::apply(
573 y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
574
575 case type::function_type:
576 return visit_impl::apply(y, detail::bind(f, *x.pf));
577 }
578 }
579 };
580
581 struct index_impl
582 {
583 static utree& apply(utree& ut, std::size_t i)
584 {
585 switch (ut.get_type())
586 {
587 case utree_type::reference_type:
588 return apply(ut.deref(), i);
589 case utree_type::range_type:
590 return apply(ut.r.first, i);
591 case utree_type::list_type:
592 return apply(ut.l.first, i);
593 default:
594 BOOST_THROW_EXCEPTION(
595 bad_type_exception
596 ("index operation performed on non-list utree type",
597 ut.get_type()));
598 }
599 }
600
601 static utree const& apply(utree const& ut, std::size_t i)
602 {
603 switch (ut.get_type())
604 {
605 case utree_type::reference_type:
606 return apply(ut.deref(), i);
607 case utree_type::range_type:
608 return apply(ut.r.first, i);
609 case utree_type::list_type:
610 return apply(ut.l.first, i);
611 default:
612 BOOST_THROW_EXCEPTION(
613 bad_type_exception
614 ("index operation performed on non-list utree type",
615 ut.get_type()));
616 }
617 }
618
619 static utree& apply(list::node* node, std::size_t i)
620 {
621 for (; i > 0; --i)
622 node = node->next;
623 return node->val;
624 }
625
626 static utree const& apply(list::node const* node, std::size_t i)
627 {
628 for (; i > 0; --i)
629 node = node->next;
630 return node->val;
631 }
632 };
633}}}
634
635namespace boost { namespace spirit
636{
637 template <typename F>
638 stored_function<F>::stored_function(F f)
639 : f(f)
640 {
641 }
642
643 template <typename F>
644 stored_function<F>::~stored_function()
645 {
646 }
647
648 template <typename F>
649 utree stored_function<F>::operator()(utree const& env) const
650 {
651 return f(env);
652 }
653
654 template <typename F>
655 utree stored_function<F>::operator()(utree& env) const
656 {
657 return f(env);
658 }
659
660 template <typename F>
661 function_base*
662 stored_function<F>::clone() const
663 {
664 return new stored_function<F>(f);
665 }
666
667 template <typename F>
668 referenced_function<F>::referenced_function(F& f)
669 : f(f)
670 {
671 }
672
673 template <typename F>
674 referenced_function<F>::~referenced_function()
675 {
676 }
677
678 template <typename F>
679 utree referenced_function<F>::operator()(utree const& env) const
680 {
681 return f(env);
682 }
683
684 template <typename F>
685 utree referenced_function<F>::operator()(utree& env) const
686 {
687 return f(env);
688 }
689
690 template <typename F>
691 function_base*
692 referenced_function<F>::clone() const
693 {
694 return new referenced_function<F>(f);
695 }
696
697 inline utree::utree(utree::invalid_type)
698 {
699 s.initialize();
700 set_type(type::invalid_type);
701 }
702
703 inline utree::utree(utree::nil_type)
704 {
705 s.initialize();
706 set_type(type::nil_type);
707 }
708
709 inline utree::utree(bool b_)
710 {
711 s.initialize();
712 b = b_;
713 set_type(type::bool_type);
714 }
715
716 inline utree::utree(char c)
717 {
718 s.initialize();
719 // char constructs a single element string
720 s.construct(&c, &c+1);
721 set_type(type::string_type);
722 }
723
724 inline utree::utree(unsigned int i_)
725 {
726 s.initialize();
727 i = i_;
728 set_type(type::int_type);
729 }
730
731 inline utree::utree(int i_)
732 {
733 s.initialize();
734 i = i_;
735 set_type(type::int_type);
736 }
737
738 inline utree::utree(double d_)
739 {
740 s.initialize();
741 d = d_;
742 set_type(type::double_type);
743 }
744
745 inline utree::utree(char const* str)
746 {
747 s.initialize();
748 s.construct(str, str + strlen(str));
749 set_type(type::string_type);
750 }
751
752 inline utree::utree(char const* str, std::size_t len)
753 {
754 s.initialize();
755 s.construct(str, str + len);
756 set_type(type::string_type);
757 }
758
759 inline utree::utree(std::string const& str)
760 {
761 s.initialize();
762 s.construct(str.begin(), str.end());
763 set_type(type::string_type);
764 }
765
766 template <typename Base, utree_type::info type_>
767 inline utree::utree(basic_string<Base, type_> const& bin)
768 {
769 s.initialize();
770 s.construct(bin.begin(), bin.end());
771 set_type(type_);
772 }
773
774 inline utree::utree(boost::reference_wrapper<utree> ref)
775 {
776 s.initialize();
777 p = ref.get_pointer();
778 set_type(type::reference_type);
779 }
780
781 inline utree::utree(any_ptr const& p)
782 {
783 s.initialize();
784 v.p = p.p;
785 v.i = p.i;
786 set_type(type::any_type);
787 }
788
789 inline utree::utree(function_base const& pf_)
790 {
791 s.initialize();
792 pf = pf_.clone();
793 set_type(type::function_type);
794 }
795
796 inline utree::utree(function_base* pf_)
797 {
798 s.initialize();
799 pf = pf_;
800 set_type(type::function_type);
801 }
802
803 template <typename Iter>
804 inline utree::utree(boost::iterator_range<Iter> r)
805 {
806 s.initialize();
807
808 assign(r.begin(), r.end());
809 }
810
811 inline utree::utree(range r, shallow_tag)
812 {
813 s.initialize();
814 this->r.first = r.begin().node;
815 this->r.last = r.end().prev;
816 set_type(type::range_type);
817 }
818
819 inline utree::utree(const_range r, shallow_tag)
820 {
821 s.initialize();
822 this->r.first = r.begin().node;
823 this->r.last = r.end().prev;
824 set_type(type::range_type);
825 }
826
827 inline utree::utree(utf8_string_range_type const& str, shallow_tag)
828 {
829 s.initialize();
830 this->sr.first = str.begin();
831 this->sr.last = str.end();
832 set_type(type::string_range_type);
833 }
834
835 inline utree::utree(utree const& other)
836 {
837 s.initialize();
838 copy(other);
839 }
840
841 inline utree::~utree()
842 {
843 free();
844 }
845
846 inline utree& utree::operator=(utree const& other)
847 {
848 if (this != &other)
849 {
850 free();
851 copy(other);
852 }
853 return *this;
854 }
855
856 inline utree& utree::operator=(nil_type)
857 {
858 free();
859 set_type(type::nil_type);
860 return *this;
861 }
862
863 inline utree& utree::operator=(bool b_)
864 {
865 free();
866 b = b_;
867 set_type(type::bool_type);
868 return *this;
869 }
870
871 inline utree& utree::operator=(char c)
872 {
873 // char constructs a single element string
874 free();
875 s.construct(&c, &c+1);
876 set_type(type::string_type);
877 return *this;
878 }
879
880 inline utree& utree::operator=(unsigned int i_)
881 {
882 free();
883 i = i_;
884 set_type(type::int_type);
885 return *this;
886 }
887
888 inline utree& utree::operator=(int i_)
889 {
890 free();
891 i = i_;
892 set_type(type::int_type);
893 return *this;
894 }
895
896 inline utree& utree::operator=(double d_)
897 {
898 free();
899 d = d_;
900 set_type(type::double_type);
901 return *this;
902 }
903
904 inline utree& utree::operator=(char const* s_)
905 {
906 free();
907 s.construct(s_, s_ + strlen(s_));
908 set_type(type::string_type);
909 return *this;
910 }
911
912 inline utree& utree::operator=(std::string const& s_)
913 {
914 free();
915 s.construct(s_.begin(), s_.end());
916 set_type(type::string_type);
917 return *this;
918 }
919
920 template <typename Base, utree_type::info type_>
921 inline utree& utree::operator=(basic_string<Base, type_> const& bin)
922 {
923 free();
924 s.construct(bin.begin(), bin.end());
925 set_type(type_);
926 return *this;
927 }
928
929 inline utree& utree::operator=(boost::reference_wrapper<utree> ref)
930 {
931 free();
932 p = ref.get_pointer();
933 set_type(type::reference_type);
934 return *this;
935 }
936
92f5a8d4 937 inline utree& utree::operator=(any_ptr const& p_)
7c673cae
FG
938 {
939 free();
92f5a8d4
TL
940 v.p = p_.p;
941 v.i = p_.i;
7c673cae
FG
942 set_type(type::any_type);
943 return *this;
944 }
945
946 inline utree& utree::operator=(function_base const& pf_)
947 {
948 free();
949 pf = pf_.clone();
950 set_type(type::function_type);
951 return *this;
952 }
953
954 inline utree& utree::operator=(function_base* pf_)
955 {
956 free();
957 pf = pf_;
958 set_type(type::function_type);
959 return *this;
960 }
961
962 template <typename Iter>
963 inline utree& utree::operator=(boost::iterator_range<Iter> r)
964 {
965 free();
966 assign(r.begin(), r.end());
967 return *this;
968 }
969
970 template <typename F>
971 typename boost::result_of<F(utree const&)>::type
972 inline utree::visit(utree const& x, F f)
973 {
974 return detail::visit_impl<utree const>::apply(x, f);
975 }
976
977 template <typename F>
978 typename boost::result_of<F(utree&)>::type
979 inline utree::visit(utree& x, F f)
980 {
981 return detail::visit_impl<utree>::apply(x, f);
982 }
983
984 template <typename F>
985 typename boost::result_of<F(utree const&, utree const&)>::type
986 inline utree::visit(utree const& x, utree const& y, F f)
987 {
988 return detail::visit_impl<utree const, utree const>::apply(x, y, f);
989 }
990
991 template <typename F>
992 typename boost::result_of<F(utree const&, utree&)>::type
993 inline utree::visit(utree const& x, utree& y, F f)
994 {
995 return detail::visit_impl<utree const, utree>::apply(x, y, f);
996 }
997
998 template <typename F>
999 typename boost::result_of<F(utree&, utree const&)>::type
1000 inline utree::visit(utree& x, utree const& y, F f)
1001 {
1002 return detail::visit_impl<utree, utree const>::apply(x, y, f);
1003 }
1004
1005 template <typename F>
1006 typename boost::result_of<F(utree&, utree&)>::type
1007 inline utree::visit(utree& x, utree& y, F f)
1008 {
1009 return detail::visit_impl<utree, utree>::apply(x, y, f);
1010 }
1011
1012 inline utree::reference get(utree::reference ut, utree::size_type i)
1013 { return detail::index_impl::apply(ut, i); }
1014
1015 inline utree::const_reference
1016 get(utree::const_reference ut, utree::size_type i)
1017 { return detail::index_impl::apply(ut, i); }
1018
1019 template <typename T>
1020 inline void utree::push_front(T const& val)
1021 {
1022 if (get_type() == type::reference_type)
1023 return p->push_front(val);
1024
1025 ensure_list_type("push_front()");
1026 l.push_front(val);
1027 }
1028
1029 template <typename T>
1030 inline void utree::push_back(T const& val)
1031 {
1032 if (get_type() == type::reference_type)
1033 return p->push_back(val);
1034
1035 ensure_list_type("push_back()");
1036 l.push_back(val);
1037 }
1038
1039 template <typename T>
1040 inline utree::iterator utree::insert(iterator pos, T const& val)
1041 {
1042 if (get_type() == type::reference_type)
1043 return p->insert(pos, val);
1044
1045 ensure_list_type("insert()");
1046 if (!pos.node)
1047 {
1048 l.push_back(val);
1049 return utree::iterator(l.last, l.last->prev);
1050 }
1051 l.insert(val, pos);
1052 return utree::iterator(pos.node->prev, pos.node->prev->prev);
1053 }
1054
1055 template <typename T>
1056 inline void utree::insert(iterator pos, std::size_t n, T const& val)
1057 {
1058 if (get_type() == type::reference_type)
1059 return p->insert(pos, n, val);
1060
1061 ensure_list_type("insert()");
1062 for (std::size_t i = 0; i != n; ++i)
1063 insert(pos, val);
1064 }
1065
1066 template <typename Iterator>
1067 inline void utree::insert(iterator pos, Iterator first, Iterator last)
1068 {
1069 if (get_type() == type::reference_type)
1070 return p->insert(pos, first, last);
1071
1072 ensure_list_type("insert()");
1073 while (first != last)
1074 insert(pos, *first++);
1075 }
1076
1077 template <typename Iterator>
1078 inline void utree::assign(Iterator first, Iterator last)
1079 {
1080 if (get_type() == type::reference_type)
1081 return p->assign(first, last);
1082
1083 clear();
1084 set_type(type::list_type);
1085
1086 while (first != last)
1087 {
1088 push_back(*first);
1089 ++first;
1090 }
1091 }
1092
1093 inline void utree::clear()
1094 {
1095 if (get_type() == type::reference_type)
1096 return p->clear();
1097
1098 // clear will always make this an invalid type
1099 free();
1100 set_type(type::invalid_type);
1101 }
1102
1103 inline void utree::pop_front()
1104 {
1105 if (get_type() == type::reference_type)
1106 return p->pop_front();
1107 if (get_type() != type::list_type)
1108 BOOST_THROW_EXCEPTION(
1109 bad_type_exception
1110 ("pop_front() called on non-list utree type",
1111 get_type()));
1112
1113 l.pop_front();
1114 }
1115
1116 inline void utree::pop_back()
1117 {
1118 if (get_type() == type::reference_type)
1119 return p->pop_back();
1120 if (get_type() != type::list_type)
1121 BOOST_THROW_EXCEPTION(
1122 bad_type_exception
1123 ("pop_back() called on non-list utree type",
1124 get_type()));
1125
1126 l.pop_back();
1127 }
1128
1129 inline utree::iterator utree::erase(iterator pos)
1130 {
1131 if (get_type() == type::reference_type)
1132 return p->erase(pos);
1133 if (get_type() != type::list_type)
1134 BOOST_THROW_EXCEPTION(
1135 bad_type_exception
1136 ("erase() called on non-list utree type",
1137 get_type()));
1138
1139 detail::list::node* np = l.erase(pos.node);
1140 return iterator(np, np?np->prev:l.last);
1141 }
1142
1143 inline utree::iterator utree::erase(iterator first, iterator last)
1144 {
1145 if (get_type() == type::reference_type)
1146 return p->erase(first, last);
1147
1148 if (get_type() != type::list_type)
1149 BOOST_THROW_EXCEPTION(
1150 bad_type_exception
1151 ("erase() called on non-list utree type",
1152 get_type()));
1153 while (first != last)
1154 erase(first++);
1155 return last;
1156 }
1157
1158 inline utree::iterator utree::begin()
1159 {
1160 if (get_type() == type::reference_type)
1161 return p->begin();
1162 else if (get_type() == type::range_type)
1163 return iterator(r.first, 0);
1164
1165 // otherwise...
1166 ensure_list_type("begin()");
1167 return iterator(l.first, 0);
1168 }
1169
1170 inline utree::iterator utree::end()
1171 {
1172 if (get_type() == type::reference_type)
1173 return p->end();
1174 else if (get_type() == type::range_type)
1175 return iterator(0, r.first);
1176
1177 // otherwise...
1178 ensure_list_type("end()");
1179 return iterator(0, l.last);
1180 }
1181
1182 inline utree::ref_iterator utree::ref_begin()
1183 {
1184 if (get_type() == type::reference_type)
1185 return p->ref_begin();
1186 else if (get_type() == type::range_type)
1187 return ref_iterator(r.first, 0);
1188
1189 // otherwise...
1190 ensure_list_type("ref_begin()");
1191 return ref_iterator(l.first, 0);
1192 }
1193
1194 inline utree::ref_iterator utree::ref_end()
1195 {
1196 if (get_type() == type::reference_type)
1197 return p->ref_end();
1198 else if (get_type() == type::range_type)
1199 return ref_iterator(0, r.first);
1200
1201 // otherwise...
1202 ensure_list_type("ref_end()");
1203 return ref_iterator(0, l.last);
1204 }
1205
1206 inline utree::const_iterator utree::begin() const
1207 {
1208 if (get_type() == type::reference_type)
1209 return ((utree const*)p)->begin();
1210 if (get_type() == type::range_type)
1211 return const_iterator(r.first, 0);
1212
1213 // otherwise...
1214 if (get_type() != type::list_type)
1215 BOOST_THROW_EXCEPTION(
1216 bad_type_exception
1217 ("begin() called on non-list utree type",
1218 get_type()));
1219
1220 return const_iterator(l.first, 0);
1221 }
1222
1223 inline utree::const_iterator utree::end() const
1224 {
1225 if (get_type() == type::reference_type)
1226 return ((utree const*)p)->end();
1227 if (get_type() == type::range_type)
1228 return const_iterator(0, r.first);
1229
1230 // otherwise...
1231 if (get_type() != type::list_type)
1232 BOOST_THROW_EXCEPTION(
1233 bad_type_exception
1234 ("end() called on non-list utree type",
1235 get_type()));
1236
1237 return const_iterator(0, l.last);
1238 }
1239
1240 inline bool utree::empty() const
1241 {
1242 type::info t = get_type();
1243 if (t == type::reference_type)
1244 return ((utree const*)p)->empty();
1245
1246 if (t == type::range_type)
1247 return r.first == 0;
1248 if (t == type::list_type)
1249 return l.size == 0;
1250
1251 return t == type::nil_type || t == type::invalid_type;
1252 }
1253
1254 inline std::size_t utree::size() const
1255 {
1256 type::info t = get_type();
1257 if (t == type::reference_type)
1258 return ((utree const*)p)->size();
1259
1260 if (t == type::range_type)
1261 {
1262 // FIXME: O(n), and we have the room to store the size of a range
1263 // in the union if we compute it when assigned/constructed.
1264 std::size_t size = 0;
1265 detail::list::node* n = r.first;
1266 while (n)
1267 {
1268 n = n->next;
1269 ++size;
1270 }
1271 return size;
1272 }
1273 if (t == type::list_type)
1274 return l.size;
1275
1276 if (t == type::string_type)
1277 return s.size();
1278
1279 if (t == type::symbol_type)
1280 return s.size();
1281
1282 if (t == type::binary_type)
1283 return s.size();
1284
1285 if (t == type::string_range_type)
1286 return sr.last - sr.first;
1287
1288 if (t != type::nil_type)
1289 BOOST_THROW_EXCEPTION(
1290 bad_type_exception
1291 ("size() called on non-list and non-string utree type",
1292 get_type()));
1293
1294 return 0;
1295 }
1296
1297 inline utree_type::info utree::which() const
1298 {
1299 return get_type();
1300 }
1301
1302 inline utree& utree::front()
1303 {
1304 if (get_type() == type::reference_type)
1305 return p->front();
1306 if (get_type() == type::range_type)
1307 {
1308 if (!r.first)
1309 BOOST_THROW_EXCEPTION(
1310 empty_exception("front() called on empty utree range"));
1311 return r.first->val;
1312 }
1313
1314 // otherwise...
1315 if (get_type() != type::list_type)
1316 BOOST_THROW_EXCEPTION(
1317 bad_type_exception
1318 ("front() called on non-list utree type", get_type()));
1319 else if (!l.first)
1320 BOOST_THROW_EXCEPTION(
1321 empty_exception("front() called on empty utree list"));
1322
1323 return l.first->val;
1324 }
1325
1326 inline utree& utree::back()
1327 {
1328 if (get_type() == type::reference_type)
1329 return p->back();
1330 if (get_type() == type::range_type)
1331 {
1332 if (!r.last)
1333 BOOST_THROW_EXCEPTION(
1334 empty_exception("back() called on empty utree range"));
1335 return r.last->val;
1336 }
1337
1338 // otherwise...
1339 if (get_type() != type::list_type)
1340 BOOST_THROW_EXCEPTION(
1341 bad_type_exception
1342 ("back() called on non-list utree type", get_type()));
1343 else if (!l.last)
1344 BOOST_THROW_EXCEPTION(
1345 empty_exception("back() called on empty utree list"));
1346
1347 return l.last->val;
1348 }
1349
1350 inline utree const& utree::front() const
1351 {
1352 if (get_type() == type::reference_type)
1353 return ((utree const*)p)->front();
1354 if (get_type() == type::range_type)
1355 {
1356 if (!r.first)
1357 BOOST_THROW_EXCEPTION(
1358 empty_exception("front() called on empty utree range"));
1359 return r.first->val;
1360 }
1361
1362 // otherwise...
1363 if (get_type() != type::list_type)
1364 BOOST_THROW_EXCEPTION(
1365 bad_type_exception
1366 ("front() called on non-list utree type", get_type()));
1367 else if (!l.first)
1368 BOOST_THROW_EXCEPTION(
1369 empty_exception("front() called on empty utree list"));
1370
1371 return l.first->val;
1372 }
1373
1374 inline utree const& utree::back() const
1375 {
1376 if (get_type() == type::reference_type)
1377 return ((utree const*)p)->back();
1378 if (get_type() == type::range_type)
1379 {
1380 if (!r.last)
1381 BOOST_THROW_EXCEPTION(
1382 empty_exception("back() called on empty utree range"));
1383 return r.last->val;
1384 }
1385
1386 // otherwise...
1387 if (get_type() != type::list_type)
1388 BOOST_THROW_EXCEPTION(
1389 bad_type_exception
1390 ("back() called on non-list utree type", get_type()));
1391 else if (!l.last)
1392 BOOST_THROW_EXCEPTION(
1393 empty_exception("back() called on empty utree list"));
1394
1395 return l.last->val;
1396 }
1397
1398 inline void utree::swap(utree& other)
1399 {
1400 s.swap(other.s);
1401 }
1402
1403 inline utree::type::info utree::get_type() const
1404 {
1405 // the fast string holds the type info
1406 return static_cast<utree::type::info>(s.get_type());
1407 }
1408
1409 inline void utree::set_type(type::info t)
1410 {
1411 // the fast string holds the type info
1412 s.set_type(t);
1413 }
1414
1415 inline void utree::ensure_list_type(char const* failed_in)
1416 {
1417 type::info t = get_type();
1418 if (t == type::invalid_type)
1419 {
1420 set_type(type::list_type);
1421 l.default_construct();
1422 }
1423 else if (get_type() != type::list_type)
1424 {
1425 std::string msg = failed_in;
1426 msg += "called on non-list and non-invalid utree type";
1427 BOOST_THROW_EXCEPTION(bad_type_exception(msg.c_str(), get_type()));
1428 }
1429 }
1430
1431 inline void utree::free()
1432 {
1433 switch (get_type())
1434 {
1435 case type::binary_type:
1436 case type::symbol_type:
1437 case type::string_type:
1438 s.free();
1439 break;
1440 case type::list_type:
1441 l.free();
1442 break;
1443 case type::function_type:
1444 delete pf;
1445 break;
1446 default:
1447 break;
1448 };
1449 s.initialize();
1450 }
1451
1452 inline void utree::copy(utree const& other)
1453 {
1454 set_type(other.get_type());
1455 switch (other.get_type())
1456 {
1457 default:
1458 BOOST_THROW_EXCEPTION(
1459 bad_type_exception("corrupt utree type", other.get_type()));
1460 break;
1461 case type::invalid_type:
1462 case type::nil_type:
1463 s.tag(other.s.tag());
1464 break;
1465 case type::bool_type:
1466 b = other.b;
1467 s.tag(other.s.tag());
1468 break;
1469 case type::int_type:
1470 i = other.i;
1471 s.tag(other.s.tag());
1472 break;
1473 case type::double_type:
1474 d = other.d;
1475 s.tag(other.s.tag());
1476 break;
1477 case type::reference_type:
1478 p = other.p;
1479 s.tag(other.s.tag());
1480 break;
1481 case type::any_type:
1482 v = other.v;
1483 s.tag(other.s.tag());
1484 break;
1485 case type::range_type:
1486 r = other.r;
1487 s.tag(other.s.tag());
1488 break;
1489 case type::string_range_type:
1490 sr = other.sr;
1491 s.tag(other.s.tag());
1492 break;
1493 case type::function_type:
1494 pf = other.pf->clone();
1495 s.tag(other.s.tag());
1496 break;
1497 case type::string_type:
1498 case type::symbol_type:
1499 case type::binary_type:
1500 s.copy(other.s);
1501 s.tag(other.s.tag());
1502 break;
1503 case type::list_type:
1504 l.copy(other.l);
1505 s.tag(other.s.tag());
1506 break;
1507 }
1508 }
1509
1510 template <typename T>
1511 struct is_iterator_range
1512 : boost::mpl::false_
1513 {};
1514
1515 template <typename Iterator>
1516 struct is_iterator_range<boost::iterator_range<Iterator> >
1517 : boost::mpl::true_
1518 {};
1519
1520 template <typename To>
1521 struct utree_cast
1522 {
1523 typedef To result_type;
1524
1525 template <typename From>
1526 To dispatch(From const& val, boost::mpl::true_) const
1527 {
1528 return To(val); // From is convertible to To
1529 }
1530
1531 template <typename From>
1532 To dispatch(From const&, boost::mpl::false_) const
1533 {
1534 // From is NOT convertible to To !!!
1535 throw std::bad_cast();
1536 return To();
1537 }
1538
1539 template <typename From>
1540 To operator()(From const& val) const
1541 {
1542 // boost::iterator_range has a templated constructor, accepting
1543 // any argument and hence any type is 'convertible' to it.
1544 typedef typename boost::mpl::eval_if<
1545 is_iterator_range<To>
1546 , boost::is_same<From, To>, boost::is_convertible<From, To>
1547 >::type is_convertible;
1548 return dispatch(val, is_convertible());
1549 }
1550 };
1551
1552 template <typename T>
1553 struct utree_cast<T*>
1554 {
1555 typedef T* result_type;
1556
1557 template <typename From>
1558 T* operator()(From const&) const
1559 {
1560 // From is NOT convertible to T !!!
1561 throw std::bad_cast();
1562 return 0;
1563 }
1564
1565 T* operator()(any_ptr const& p) const
1566 {
1567 return p.get<T*>();
1568 }
1569 };
1570
1571 template <typename T>
1572 inline T utree::get() const
1573 {
1574 return utree::visit(*this, utree_cast<T>());
1575 }
1576
1577 inline utree& utree::deref()
1578 {
1579 return (get_type() == type::reference_type) ? *p : *this;
1580 }
1581
1582 inline utree const& utree::deref() const
1583 {
1584 return (get_type() == type::reference_type) ? *p : *this;
1585 }
1586
1587 inline short utree::tag() const
1588 {
1589 return s.tag();
1590 }
1591
1592 inline void utree::tag(short tag)
1593 {
1594 s.tag(tag);
1595 }
1596
1597 inline utree utree::eval(utree const& env) const
1598 {
1599 if (get_type() == type::reference_type)
1600 return deref().eval(env);
1601
1602 if (get_type() != type::function_type)
1603 BOOST_THROW_EXCEPTION(
1604 bad_type_exception(
1605 "eval() called on non-function utree type", get_type()));
1606 return (*pf)(env);
1607 }
1608
1609 inline utree utree::eval(utree& env) const
1610 {
1611 if (get_type() == type::reference_type)
1612 return deref().eval(env);
1613
1614 if (get_type() != type::function_type)
1615 BOOST_THROW_EXCEPTION(
1616 bad_type_exception(
1617 "eval() called on non-function utree type", get_type()));
1618 return (*pf)(env);
1619 }
1620
1621 inline utree utree::operator() (utree const& env) const
1622 {
1623 return eval(env);
1624 }
1625
1626 inline utree utree::operator() (utree& env) const
1627 {
1628 return eval(env);
1629 }
1630}}
1631
1632#if defined(BOOST_MSVC)
1633# pragma warning(pop)
1634#endif
1635#endif