1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 Bryce Lelbach
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
12 #if defined(BOOST_MSVC)
13 # pragma warning(push)
14 # pragma warning(disable: 4800)
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 #include <cstring> // for std::memcpy
24 namespace boost { namespace spirit { namespace detail
26 inline char& fast_string::info()
28 return buff[small_string_size];
31 inline char fast_string::info() const
33 return buff[small_string_size];
36 inline int fast_string::get_type() const
41 inline void fast_string::set_type(int t)
43 info() = (t << 1) | (info() & 1);
46 inline short fast_string::tag() const
49 std::memcpy(&tmp, &buff[small_string_size-2], sizeof(tmp));
53 inline void fast_string::tag(short tag)
55 boost::int16_t tmp = tag;
56 std::memcpy(&buff[small_string_size-2], &tmp, sizeof(tmp));
59 inline bool fast_string::is_heap_allocated() const
64 inline std::size_t fast_string::size() const
66 if (is_heap_allocated())
69 return max_string_len - buff[max_string_len];
72 inline char const* fast_string::str() const
74 if (is_heap_allocated())
80 template <typename Iterator>
81 inline void fast_string::construct(Iterator f, Iterator l)
83 std::size_t const size = static_cast<std::size_t>(l-f);
85 if (size < max_string_len)
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]
90 buff[max_string_len] = static_cast<char>(max_string_len - size);
95 // else, store it in the heap
96 str = new char[size + 1]; // add one for the null char
101 for (std::size_t i = 0; i != size; ++i)
105 *str = '\0'; // add the null char
108 inline void fast_string::swap(fast_string& other)
110 std::swap(*this, other);
113 inline void fast_string::free()
115 if (is_heap_allocated())
121 inline void fast_string::copy(fast_string const& other)
123 construct(other.str(), other.str() + other.size());
126 inline void fast_string::initialize()
128 for (std::size_t i = 0; i != buff_size / (sizeof(long)/sizeof(char)); ++i)
132 struct list::node : boost::noncopyable
134 template <typename T>
135 node(T const& val, node* next, node* prev)
136 : val(val), next(next), prev(prev) {}
149 template <typename Value>
150 class list::node_iterator
151 : public boost::iterator_facade<
154 , boost::bidirectional_traversal_tag>
159 : node(0), prev(0) {}
161 node_iterator(list::node* node, list::node* prev)
162 : node(node), prev(prev) {}
166 friend class boost::iterator_core_access;
167 friend class boost::spirit::utree;
168 friend struct boost::spirit::detail::list;
172 if (node != 0) // not at end
181 if (prev != 0) // not at begin
188 bool equal(node_iterator const& other) const
190 return node == other.node;
193 typename node_iterator::reference dereference() const
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>
212 : node(0), prev(0), curr(nil_node) {}
214 node_iterator(list::node* node, list::node* prev)
215 : node(node), prev(prev), curr(node ? node->val : nil_node) {}
219 friend class boost::iterator_core_access;
220 friend class boost::spirit::utree;
221 friend struct boost::spirit::detail::list;
225 if (node != 0) // not at end
229 curr = boost::ref(node ? node->val : nil_node);
235 if (prev != 0) // not at begin
239 curr = boost::ref(node ? node->val : nil_node);
243 bool equal(node_iterator const& other) const
245 return node == other.node;
248 typename node_iterator::reference dereference() const
256 static Value nil_node;
257 mutable boost::reference_wrapper<Value> curr;
260 template <typename Value>
261 Value list::node_iterator<boost::reference_wrapper<Value> >::nil_node = Value();
263 inline void list::free()
268 node* next = p->next;
274 inline void list::copy(list const& other)
276 node* p = other.first;
284 inline void list::default_construct()
290 template <typename T, typename Iterator>
291 inline void list::insert(T const& val, Iterator pos)
299 detail::list::node* new_node =
300 new detail::list::node(val, pos.node, pos.node->prev);
303 pos.node->prev->next = new_node;
307 pos.node->prev = new_node;
311 template <typename T>
312 inline void list::push_front(T const& val)
314 detail::list::node* new_node;
317 new_node = new detail::list::node(val, 0, 0);
318 first = last = new_node;
323 new_node = new detail::list::node(val, first, first->prev);
324 first->prev = new_node;
330 template <typename T>
331 inline void list::push_back(T const& val)
336 detail::list::node* new_node =
337 new detail::list::node(val, last->next, last);
338 last->next = new_node;
344 inline void list::pop_front()
346 BOOST_ASSERT(size != 0);
347 if (first == last) // there's only one item
363 inline void list::pop_back()
365 BOOST_ASSERT(size != 0);
366 if (first == last) // there's only one item
382 inline list::node* list::erase(node* pos)
384 BOOST_ASSERT(pos != 0);
390 else if (pos == last)
397 node* next(pos->next);
405 ///////////////////////////////////////////////////////////////////////////
406 // simple binder for binary visitation (we don't want to bring in the big guns)
407 template <typename F, typename X>
410 typedef typename F::result_type result_type;
411 X& x; // always by reference
413 bind_impl(F f, X& x) : x(x), f(f) {}
415 template <typename Y>
416 typename F::result_type operator()(Y& y) const
421 template <typename Y>
422 typename F::result_type operator()(Y const& y) const
428 template <typename F, typename X>
429 bind_impl<F, X const> bind(F f, X const& x)
431 return bind_impl<F, X const>(f, x);
434 template <typename F, typename X>
435 bind_impl<F, X> bind(F f, X& x)
437 return bind_impl<F, X>(f, x);
440 template <typename UTreeX, typename UTreeY = UTreeX>
443 template <typename F>
444 typename F::result_type
445 static apply(UTreeX& x, F f) // single dispatch
448 boost::mpl::if_<boost::is_const<UTreeX>,
449 typename UTreeX::const_iterator,
450 typename UTreeX::iterator>::type
453 typedef boost::iterator_range<iterator> list_range;
454 typedef utree_type type;
456 switch (x.get_type())
459 BOOST_THROW_EXCEPTION(
460 bad_type_exception("corrupt utree type", x.get_type()));
463 case type::invalid_type:
469 case type::bool_type:
475 case type::double_type:
478 case type::list_type:
479 return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
481 case type::range_type:
482 return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
484 case type::string_type:
485 return f(utf8_string_range_type(x.s.str(), x.s.size()));
487 case type::string_range_type:
488 return f(utf8_string_range_type(x.sr.first, x.sr.last));
490 case type::symbol_type:
491 return f(utf8_symbol_range_type(x.s.str(), x.s.size()));
493 case type::binary_type:
494 return f(binary_range_type(x.s.str(), x.s.size()));
496 case type::reference_type:
497 return apply(*x.p, f);
500 return f(any_ptr(x.v.p, x.v.i));
502 case type::function_type:
507 template <typename F>
508 typename F::result_type
509 static apply(UTreeX& x, UTreeY& y, F f) // double dispatch
512 boost::mpl::if_<boost::is_const<UTreeX>,
513 typename UTreeX::const_iterator,
514 typename UTreeX::iterator>::type
517 typedef boost::iterator_range<iterator> list_range;
518 typedef utree_type type;
520 switch (x.get_type())
523 BOOST_THROW_EXCEPTION(
524 bad_type_exception("corrupt utree type", x.get_type()));
527 case type::invalid_type:
528 return visit_impl::apply(y, detail::bind(f, invalid));
531 return visit_impl::apply(y, detail::bind(f, nil));
533 case type::bool_type:
534 return visit_impl::apply(y, detail::bind(f, x.b));
537 return visit_impl::apply(y, detail::bind(f, x.i));
539 case type::double_type:
540 return visit_impl::apply(y, detail::bind(f, x.d));
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))));
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))));
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())));
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)));
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())));
564 case type::binary_type:
565 return visit_impl::apply(y, detail::bind(
566 f, binary_range_type(x.s.str(), x.s.size())));
568 case type::reference_type:
569 return apply(*x.p, y, f);
572 return visit_impl::apply(
573 y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
575 case type::function_type:
576 return visit_impl::apply(y, detail::bind(f, *x.pf));
583 static utree& apply(utree& ut, std::size_t i)
585 switch (ut.get_type())
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);
594 BOOST_THROW_EXCEPTION(
596 ("index operation performed on non-list utree type",
601 static utree const& apply(utree const& ut, std::size_t i)
603 switch (ut.get_type())
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);
612 BOOST_THROW_EXCEPTION(
614 ("index operation performed on non-list utree type",
619 static utree& apply(list::node* node, std::size_t i)
626 static utree const& apply(list::node const* node, std::size_t i)
635 namespace boost { namespace spirit
637 template <typename F>
638 stored_function<F>::stored_function(F f)
643 template <typename F>
644 stored_function<F>::~stored_function()
648 template <typename F>
649 utree stored_function<F>::operator()(utree const& env) const
654 template <typename F>
655 utree stored_function<F>::operator()(utree& env) const
660 template <typename F>
662 stored_function<F>::clone() const
664 return new stored_function<F>(f);
667 template <typename F>
668 referenced_function<F>::referenced_function(F& f)
673 template <typename F>
674 referenced_function<F>::~referenced_function()
678 template <typename F>
679 utree referenced_function<F>::operator()(utree const& env) const
684 template <typename F>
685 utree referenced_function<F>::operator()(utree& env) const
690 template <typename F>
692 referenced_function<F>::clone() const
694 return new referenced_function<F>(f);
697 inline utree::utree(utree::invalid_type)
700 set_type(type::invalid_type);
703 inline utree::utree(utree::nil_type)
706 set_type(type::nil_type);
709 inline utree::utree(bool b_)
713 set_type(type::bool_type);
716 inline utree::utree(char c)
719 // char constructs a single element string
720 s.construct(&c, &c+1);
721 set_type(type::string_type);
724 inline utree::utree(unsigned int i_)
728 set_type(type::int_type);
731 inline utree::utree(int i_)
735 set_type(type::int_type);
738 inline utree::utree(double d_)
742 set_type(type::double_type);
745 inline utree::utree(char const* str)
748 s.construct(str, str + strlen(str));
749 set_type(type::string_type);
752 inline utree::utree(char const* str, std::size_t len)
755 s.construct(str, str + len);
756 set_type(type::string_type);
759 inline utree::utree(std::string const& str)
762 s.construct(str.begin(), str.end());
763 set_type(type::string_type);
766 template <typename Base, utree_type::info type_>
767 inline utree::utree(basic_string<Base, type_> const& bin)
770 s.construct(bin.begin(), bin.end());
774 inline utree::utree(boost::reference_wrapper<utree> ref)
777 p = ref.get_pointer();
778 set_type(type::reference_type);
781 inline utree::utree(any_ptr const& p)
786 set_type(type::any_type);
789 inline utree::utree(function_base const& pf_)
793 set_type(type::function_type);
796 inline utree::utree(function_base* pf_)
800 set_type(type::function_type);
803 template <typename Iter>
804 inline utree::utree(boost::iterator_range<Iter> r)
808 assign(r.begin(), r.end());
811 inline utree::utree(range r, shallow_tag)
814 this->r.first = r.begin().node;
815 this->r.last = r.end().prev;
816 set_type(type::range_type);
819 inline utree::utree(const_range r, shallow_tag)
822 this->r.first = r.begin().node;
823 this->r.last = r.end().prev;
824 set_type(type::range_type);
827 inline utree::utree(utf8_string_range_type const& str, shallow_tag)
830 this->sr.first = str.begin();
831 this->sr.last = str.end();
832 set_type(type::string_range_type);
835 inline utree::utree(utree const& other)
841 inline utree::~utree()
846 inline utree& utree::operator=(utree const& other)
856 inline utree& utree::operator=(nil_type)
859 set_type(type::nil_type);
863 inline utree& utree::operator=(bool b_)
867 set_type(type::bool_type);
871 inline utree& utree::operator=(char c)
873 // char constructs a single element string
875 s.construct(&c, &c+1);
876 set_type(type::string_type);
880 inline utree& utree::operator=(unsigned int i_)
884 set_type(type::int_type);
888 inline utree& utree::operator=(int i_)
892 set_type(type::int_type);
896 inline utree& utree::operator=(double d_)
900 set_type(type::double_type);
904 inline utree& utree::operator=(char const* s_)
907 s.construct(s_, s_ + strlen(s_));
908 set_type(type::string_type);
912 inline utree& utree::operator=(std::string const& s_)
915 s.construct(s_.begin(), s_.end());
916 set_type(type::string_type);
920 template <typename Base, utree_type::info type_>
921 inline utree& utree::operator=(basic_string<Base, type_> const& bin)
924 s.construct(bin.begin(), bin.end());
929 inline utree& utree::operator=(boost::reference_wrapper<utree> ref)
932 p = ref.get_pointer();
933 set_type(type::reference_type);
937 inline utree& utree::operator=(any_ptr const& p_)
942 set_type(type::any_type);
946 inline utree& utree::operator=(function_base const& pf_)
950 set_type(type::function_type);
954 inline utree& utree::operator=(function_base* pf_)
958 set_type(type::function_type);
962 template <typename Iter>
963 inline utree& utree::operator=(boost::iterator_range<Iter> r)
966 assign(r.begin(), r.end());
970 template <typename F>
971 typename boost::result_of<F(utree const&)>::type
972 inline utree::visit(utree const& x, F f)
974 return detail::visit_impl<utree const>::apply(x, f);
977 template <typename F>
978 typename boost::result_of<F(utree&)>::type
979 inline utree::visit(utree& x, F f)
981 return detail::visit_impl<utree>::apply(x, f);
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)
988 return detail::visit_impl<utree const, utree const>::apply(x, y, f);
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)
995 return detail::visit_impl<utree const, utree>::apply(x, y, f);
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)
1002 return detail::visit_impl<utree, utree const>::apply(x, y, f);
1005 template <typename F>
1006 typename boost::result_of<F(utree&, utree&)>::type
1007 inline utree::visit(utree& x, utree& y, F f)
1009 return detail::visit_impl<utree, utree>::apply(x, y, f);
1012 inline utree::reference get(utree::reference ut, utree::size_type i)
1013 { return detail::index_impl::apply(ut, i); }
1015 inline utree::const_reference
1016 get(utree::const_reference ut, utree::size_type i)
1017 { return detail::index_impl::apply(ut, i); }
1019 template <typename T>
1020 inline void utree::push_front(T const& val)
1022 if (get_type() == type::reference_type)
1023 return p->push_front(val);
1025 ensure_list_type("push_front()");
1029 template <typename T>
1030 inline void utree::push_back(T const& val)
1032 if (get_type() == type::reference_type)
1033 return p->push_back(val);
1035 ensure_list_type("push_back()");
1039 template <typename T>
1040 inline utree::iterator utree::insert(iterator pos, T const& val)
1042 if (get_type() == type::reference_type)
1043 return p->insert(pos, val);
1045 ensure_list_type("insert()");
1049 return utree::iterator(l.last, l.last->prev);
1052 return utree::iterator(pos.node->prev, pos.node->prev->prev);
1055 template <typename T>
1056 inline void utree::insert(iterator pos, std::size_t n, T const& val)
1058 if (get_type() == type::reference_type)
1059 return p->insert(pos, n, val);
1061 ensure_list_type("insert()");
1062 for (std::size_t i = 0; i != n; ++i)
1066 template <typename Iterator>
1067 inline void utree::insert(iterator pos, Iterator first, Iterator last)
1069 if (get_type() == type::reference_type)
1070 return p->insert(pos, first, last);
1072 ensure_list_type("insert()");
1073 while (first != last)
1074 insert(pos, *first++);
1077 template <typename Iterator>
1078 inline void utree::assign(Iterator first, Iterator last)
1080 if (get_type() == type::reference_type)
1081 return p->assign(first, last);
1084 set_type(type::list_type);
1086 while (first != last)
1093 inline void utree::clear()
1095 if (get_type() == type::reference_type)
1098 // clear will always make this an invalid type
1100 set_type(type::invalid_type);
1103 inline void utree::pop_front()
1105 if (get_type() == type::reference_type)
1106 return p->pop_front();
1107 if (get_type() != type::list_type)
1108 BOOST_THROW_EXCEPTION(
1110 ("pop_front() called on non-list utree type",
1116 inline void utree::pop_back()
1118 if (get_type() == type::reference_type)
1119 return p->pop_back();
1120 if (get_type() != type::list_type)
1121 BOOST_THROW_EXCEPTION(
1123 ("pop_back() called on non-list utree type",
1129 inline utree::iterator utree::erase(iterator pos)
1131 if (get_type() == type::reference_type)
1132 return p->erase(pos);
1133 if (get_type() != type::list_type)
1134 BOOST_THROW_EXCEPTION(
1136 ("erase() called on non-list utree type",
1139 detail::list::node* np = l.erase(pos.node);
1140 return iterator(np, np?np->prev:l.last);
1143 inline utree::iterator utree::erase(iterator first, iterator last)
1145 if (get_type() == type::reference_type)
1146 return p->erase(first, last);
1148 if (get_type() != type::list_type)
1149 BOOST_THROW_EXCEPTION(
1151 ("erase() called on non-list utree type",
1153 while (first != last)
1158 inline utree::iterator utree::begin()
1160 if (get_type() == type::reference_type)
1162 else if (get_type() == type::range_type)
1163 return iterator(r.first, 0);
1166 ensure_list_type("begin()");
1167 return iterator(l.first, 0);
1170 inline utree::iterator utree::end()
1172 if (get_type() == type::reference_type)
1174 else if (get_type() == type::range_type)
1175 return iterator(0, r.first);
1178 ensure_list_type("end()");
1179 return iterator(0, l.last);
1182 inline utree::ref_iterator utree::ref_begin()
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);
1190 ensure_list_type("ref_begin()");
1191 return ref_iterator(l.first, 0);
1194 inline utree::ref_iterator utree::ref_end()
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);
1202 ensure_list_type("ref_end()");
1203 return ref_iterator(0, l.last);
1206 inline utree::const_iterator utree::begin() const
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);
1214 if (get_type() != type::list_type)
1215 BOOST_THROW_EXCEPTION(
1217 ("begin() called on non-list utree type",
1220 return const_iterator(l.first, 0);
1223 inline utree::const_iterator utree::end() const
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);
1231 if (get_type() != type::list_type)
1232 BOOST_THROW_EXCEPTION(
1234 ("end() called on non-list utree type",
1237 return const_iterator(0, l.last);
1240 inline bool utree::empty() const
1242 type::info t = get_type();
1243 if (t == type::reference_type)
1244 return ((utree const*)p)->empty();
1246 if (t == type::range_type)
1247 return r.first == 0;
1248 if (t == type::list_type)
1251 return t == type::nil_type || t == type::invalid_type;
1254 inline std::size_t utree::size() const
1256 type::info t = get_type();
1257 if (t == type::reference_type)
1258 return ((utree const*)p)->size();
1260 if (t == type::range_type)
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;
1273 if (t == type::list_type)
1276 if (t == type::string_type)
1279 if (t == type::symbol_type)
1282 if (t == type::binary_type)
1285 if (t == type::string_range_type)
1286 return sr.last - sr.first;
1288 if (t != type::nil_type)
1289 BOOST_THROW_EXCEPTION(
1291 ("size() called on non-list and non-string utree type",
1297 inline utree_type::info utree::which() const
1302 inline utree& utree::front()
1304 if (get_type() == type::reference_type)
1306 if (get_type() == type::range_type)
1309 BOOST_THROW_EXCEPTION(
1310 empty_exception("front() called on empty utree range"));
1311 return r.first->val;
1315 if (get_type() != type::list_type)
1316 BOOST_THROW_EXCEPTION(
1318 ("front() called on non-list utree type", get_type()));
1320 BOOST_THROW_EXCEPTION(
1321 empty_exception("front() called on empty utree list"));
1323 return l.first->val;
1326 inline utree& utree::back()
1328 if (get_type() == type::reference_type)
1330 if (get_type() == type::range_type)
1333 BOOST_THROW_EXCEPTION(
1334 empty_exception("back() called on empty utree range"));
1339 if (get_type() != type::list_type)
1340 BOOST_THROW_EXCEPTION(
1342 ("back() called on non-list utree type", get_type()));
1344 BOOST_THROW_EXCEPTION(
1345 empty_exception("back() called on empty utree list"));
1350 inline utree const& utree::front() const
1352 if (get_type() == type::reference_type)
1353 return ((utree const*)p)->front();
1354 if (get_type() == type::range_type)
1357 BOOST_THROW_EXCEPTION(
1358 empty_exception("front() called on empty utree range"));
1359 return r.first->val;
1363 if (get_type() != type::list_type)
1364 BOOST_THROW_EXCEPTION(
1366 ("front() called on non-list utree type", get_type()));
1368 BOOST_THROW_EXCEPTION(
1369 empty_exception("front() called on empty utree list"));
1371 return l.first->val;
1374 inline utree const& utree::back() const
1376 if (get_type() == type::reference_type)
1377 return ((utree const*)p)->back();
1378 if (get_type() == type::range_type)
1381 BOOST_THROW_EXCEPTION(
1382 empty_exception("back() called on empty utree range"));
1387 if (get_type() != type::list_type)
1388 BOOST_THROW_EXCEPTION(
1390 ("back() called on non-list utree type", get_type()));
1392 BOOST_THROW_EXCEPTION(
1393 empty_exception("back() called on empty utree list"));
1398 inline void utree::swap(utree& other)
1403 inline utree::type::info utree::get_type() const
1405 // the fast string holds the type info
1406 return static_cast<utree::type::info>(s.get_type());
1409 inline void utree::set_type(type::info t)
1411 // the fast string holds the type info
1415 inline void utree::ensure_list_type(char const* failed_in)
1417 type::info t = get_type();
1418 if (t == type::invalid_type)
1420 set_type(type::list_type);
1421 l.default_construct();
1423 else if (get_type() != type::list_type)
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()));
1431 inline void utree::free()
1435 case type::binary_type:
1436 case type::symbol_type:
1437 case type::string_type:
1440 case type::list_type:
1443 case type::function_type:
1452 inline void utree::copy(utree const& other)
1454 set_type(other.get_type());
1455 switch (other.get_type())
1458 BOOST_THROW_EXCEPTION(
1459 bad_type_exception("corrupt utree type", other.get_type()));
1461 case type::invalid_type:
1462 case type::nil_type:
1463 s.tag(other.s.tag());
1465 case type::bool_type:
1467 s.tag(other.s.tag());
1469 case type::int_type:
1471 s.tag(other.s.tag());
1473 case type::double_type:
1475 s.tag(other.s.tag());
1477 case type::reference_type:
1479 s.tag(other.s.tag());
1481 case type::any_type:
1483 s.tag(other.s.tag());
1485 case type::range_type:
1487 s.tag(other.s.tag());
1489 case type::string_range_type:
1491 s.tag(other.s.tag());
1493 case type::function_type:
1494 pf = other.pf->clone();
1495 s.tag(other.s.tag());
1497 case type::string_type:
1498 case type::symbol_type:
1499 case type::binary_type:
1501 s.tag(other.s.tag());
1503 case type::list_type:
1505 s.tag(other.s.tag());
1510 template <typename T>
1511 struct is_iterator_range
1512 : boost::mpl::false_
1515 template <typename Iterator>
1516 struct is_iterator_range<boost::iterator_range<Iterator> >
1520 template <typename To>
1523 typedef To result_type;
1525 template <typename From>
1526 To dispatch(From const& val, boost::mpl::true_) const
1528 return To(val); // From is convertible to To
1531 template <typename From>
1532 To dispatch(From const&, boost::mpl::false_) const
1534 // From is NOT convertible to To !!!
1535 throw std::bad_cast();
1539 template <typename From>
1540 To operator()(From const& val) const
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());
1552 template <typename T>
1553 struct utree_cast<T*>
1555 typedef T* result_type;
1557 template <typename From>
1558 T* operator()(From const&) const
1560 // From is NOT convertible to T !!!
1561 throw std::bad_cast();
1565 T* operator()(any_ptr const& p) const
1571 template <typename T>
1572 inline T utree::get() const
1574 return utree::visit(*this, utree_cast<T>());
1577 inline utree& utree::deref()
1579 return (get_type() == type::reference_type) ? *p : *this;
1582 inline utree const& utree::deref() const
1584 return (get_type() == type::reference_type) ? *p : *this;
1587 inline short utree::tag() const
1592 inline void utree::tag(short tag)
1597 inline utree utree::eval(utree const& env) const
1599 if (get_type() == type::reference_type)
1600 return deref().eval(env);
1602 if (get_type() != type::function_type)
1603 BOOST_THROW_EXCEPTION(
1605 "eval() called on non-function utree type", get_type()));
1609 inline utree utree::eval(utree& env) const
1611 if (get_type() == type::reference_type)
1612 return deref().eval(env);
1614 if (get_type() != type::function_type)
1615 BOOST_THROW_EXCEPTION(
1617 "eval() called on non-function utree type", get_type()));
1621 inline utree utree::operator() (utree const& env) const
1626 inline utree utree::operator() (utree& env) const
1632 #if defined(BOOST_MSVC)
1633 # pragma warning(pop)