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