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 #include <boost/type_traits/remove_pointer.hpp>
13 #include <boost/type_traits/is_pointer.hpp>
14 #include <boost/utility/enable_if.hpp>
15 #include <boost/throw_exception.hpp>
16 #include <boost/iterator/iterator_traits.hpp>
17 #include <cstring> // for std::memcpy
20 # pragma warning(push)
21 # pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
23 # pragma warning(disable: 4702) // unreachable code
27 namespace boost { namespace spirit { namespace detail
29 inline char& fast_string::info()
31 return buff[small_string_size];
34 inline char fast_string::info() const
36 return buff[small_string_size];
39 inline int fast_string::get_type() const
44 inline void fast_string::set_type(int t)
46 info() = (t << 1) | (info() & 1);
49 inline short fast_string::tag() const
52 std::memcpy(&tmp, &buff[small_string_size-2], sizeof(tmp));
56 inline void fast_string::tag(short tag)
58 boost::int16_t tmp = tag;
59 std::memcpy(&buff[small_string_size-2], &tmp, sizeof(tmp));
62 inline bool fast_string::is_heap_allocated() const
67 inline std::size_t fast_string::size() const
69 if (is_heap_allocated())
72 return max_string_len - buff[max_string_len];
75 inline char const* fast_string::str() const
77 if (is_heap_allocated())
83 template <typename Iterator>
84 inline void fast_string::construct(Iterator f, Iterator l)
86 std::size_t const size = static_cast<std::size_t>(l-f);
88 if (size < max_string_len)
90 // if it fits, store it in-situ; small_string_size minus the length
91 // of the string is placed in buff[small_string_size - 1]
93 buff[max_string_len] = static_cast<char>(max_string_len - size);
98 // else, store it in the heap
99 str = new char[size + 1]; // add one for the null char
104 for (std::size_t i = 0; i != size; ++i)
108 *str = '\0'; // add the null char
111 inline void fast_string::swap(fast_string& other)
113 std::swap(*this, other);
116 inline void fast_string::free()
118 if (is_heap_allocated())
124 inline void fast_string::copy(fast_string const& other)
126 construct(other.str(), other.str() + other.size());
129 inline void fast_string::initialize()
131 for (std::size_t i = 0; i != buff_size / (sizeof(long)/sizeof(char)); ++i)
135 struct list::node : boost::noncopyable
137 template <typename T>
138 node(T const& val, node* next, node* prev)
139 : val(val), next(next), prev(prev) {}
152 template <typename Value>
153 class list::node_iterator
154 : public boost::iterator_facade<
157 , boost::bidirectional_traversal_tag>
162 : node(0), prev(0) {}
164 node_iterator(list::node* node, list::node* prev)
165 : node(node), prev(prev) {}
169 friend class boost::iterator_core_access;
170 friend class boost::spirit::utree;
171 friend struct boost::spirit::detail::list;
175 if (node != 0) // not at end
184 if (prev != 0) // not at begin
191 bool equal(node_iterator const& other) const
193 return node == other.node;
196 typename node_iterator::reference dereference() const
205 template <typename Value>
206 class list::node_iterator<boost::reference_wrapper<Value> >
207 : public boost::iterator_facade<
208 node_iterator<boost::reference_wrapper<Value> >
209 , boost::reference_wrapper<Value>
210 , boost::bidirectional_traversal_tag>
215 : node(0), prev(0), curr(nil_node) {}
217 node_iterator(list::node* node, list::node* prev)
218 : node(node), prev(prev), curr(node ? node->val : nil_node) {}
222 friend class boost::iterator_core_access;
223 friend class boost::spirit::utree;
224 friend struct boost::spirit::detail::list;
228 if (node != 0) // not at end
232 curr = boost::ref(node ? node->val : nil_node);
238 if (prev != 0) // not at begin
242 curr = boost::ref(node ? node->val : nil_node);
246 bool equal(node_iterator const& other) const
248 return node == other.node;
251 typename node_iterator::reference dereference() const
259 static Value nil_node;
260 mutable boost::reference_wrapper<Value> curr;
263 template <typename Value>
264 Value list::node_iterator<boost::reference_wrapper<Value> >::nil_node = Value();
266 inline void list::free()
271 node* next = p->next;
277 inline void list::copy(list const& other)
279 node* p = other.first;
287 inline void list::default_construct()
293 template <typename T, typename Iterator>
294 inline void list::insert(T const& val, Iterator pos)
302 detail::list::node* new_node =
303 new detail::list::node(val, pos.node, pos.node->prev);
306 pos.node->prev->next = new_node;
310 pos.node->prev = new_node;
314 template <typename T>
315 inline void list::push_front(T const& val)
317 detail::list::node* new_node;
320 new_node = new detail::list::node(val, 0, 0);
321 first = last = new_node;
326 new_node = new detail::list::node(val, first, first->prev);
327 first->prev = new_node;
333 template <typename T>
334 inline void list::push_back(T const& val)
339 detail::list::node* new_node =
340 new detail::list::node(val, last->next, last);
341 last->next = new_node;
347 inline void list::pop_front()
349 BOOST_ASSERT(size != 0);
350 if (first == last) // there's only one item
366 inline void list::pop_back()
368 BOOST_ASSERT(size != 0);
369 if (first == last) // there's only one item
385 inline list::node* list::erase(node* pos)
387 BOOST_ASSERT(pos != 0);
393 else if (pos == last)
400 node* next(pos->next);
408 ///////////////////////////////////////////////////////////////////////////
409 // simple binder for binary visitation (we don't want to bring in the big guns)
410 template <typename F, typename X>
413 typedef typename F::result_type result_type;
414 X& x; // always by reference
416 bind_impl(F f, X& x) : x(x), f(f) {}
418 template <typename Y>
419 typename F::result_type operator()(Y& y) const
424 template <typename Y>
425 typename F::result_type operator()(Y const& y) const
431 template <typename F, typename X>
432 bind_impl<F, X const> bind(F f, X const& x)
434 return bind_impl<F, X const>(f, x);
437 template <typename F, typename X>
438 bind_impl<F, X> bind(F f, X& x)
440 return bind_impl<F, X>(f, x);
443 template <typename UTreeX, typename UTreeY = UTreeX>
446 template <typename F>
447 typename F::result_type
448 static apply(UTreeX& x, F f) // single dispatch
451 boost::mpl::if_<boost::is_const<UTreeX>,
452 typename UTreeX::const_iterator,
453 typename UTreeX::iterator>::type
456 typedef boost::iterator_range<iterator> list_range;
457 typedef utree_type type;
459 switch (x.get_type())
462 BOOST_THROW_EXCEPTION(
463 bad_type_exception("corrupt utree type", x.get_type()));
466 case type::invalid_type:
472 case type::bool_type:
478 case type::double_type:
481 case type::list_type:
482 return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
484 case type::range_type:
485 return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
487 case type::string_type:
488 return f(utf8_string_range_type(x.s.str(), x.s.size()));
490 case type::string_range_type:
491 return f(utf8_string_range_type(x.sr.first, x.sr.last));
493 case type::symbol_type:
494 return f(utf8_symbol_range_type(x.s.str(), x.s.size()));
496 case type::binary_type:
497 return f(binary_range_type(x.s.str(), x.s.size()));
499 case type::reference_type:
500 return apply(*x.p, f);
503 return f(any_ptr(x.v.p, x.v.i));
505 case type::function_type:
510 template <typename F>
511 typename F::result_type
512 static apply(UTreeX& x, UTreeY& y, F f) // double dispatch
515 boost::mpl::if_<boost::is_const<UTreeX>,
516 typename UTreeX::const_iterator,
517 typename UTreeX::iterator>::type
520 typedef boost::iterator_range<iterator> list_range;
521 typedef utree_type type;
523 switch (x.get_type())
526 BOOST_THROW_EXCEPTION(
527 bad_type_exception("corrupt utree type", x.get_type()));
530 case type::invalid_type:
531 return visit_impl::apply(y, detail::bind(f, invalid));
534 return visit_impl::apply(y, detail::bind(f, nil));
536 case type::bool_type:
537 return visit_impl::apply(y, detail::bind(f, x.b));
540 return visit_impl::apply(y, detail::bind(f, x.i));
542 case type::double_type:
543 return visit_impl::apply(y, detail::bind(f, x.d));
545 case type::list_type:
546 return visit_impl::apply(
547 y, detail::bind<F, list_range>(f,
548 list_range(iterator(x.l.first, 0), iterator(0, x.l.last))));
550 case type::range_type:
551 return visit_impl::apply(
552 y, detail::bind<F, list_range>(f,
553 list_range(iterator(x.r.first, 0), iterator(0, x.r.last))));
555 case type::string_type:
556 return visit_impl::apply(y, detail::bind(
557 f, utf8_string_range_type(x.s.str(), x.s.size())));
559 case type::string_range_type:
560 return visit_impl::apply(y, detail::bind(
561 f, utf8_string_range_type(x.sr.first, x.sr.last)));
563 case type::symbol_type:
564 return visit_impl::apply(y, detail::bind(
565 f, utf8_symbol_range_type(x.s.str(), x.s.size())));
567 case type::binary_type:
568 return visit_impl::apply(y, detail::bind(
569 f, binary_range_type(x.s.str(), x.s.size())));
571 case type::reference_type:
572 return apply(*x.p, y, f);
575 return visit_impl::apply(
576 y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
578 case type::function_type:
579 return visit_impl::apply(y, detail::bind(f, *x.pf));
586 static utree& apply(utree& ut, std::size_t i)
588 switch (ut.get_type())
590 case utree_type::reference_type:
591 return apply(ut.deref(), i);
592 case utree_type::range_type:
593 return apply(ut.r.first, i);
594 case utree_type::list_type:
595 return apply(ut.l.first, i);
597 BOOST_THROW_EXCEPTION(
599 ("index operation performed on non-list utree type",
604 static utree const& apply(utree const& ut, std::size_t i)
606 switch (ut.get_type())
608 case utree_type::reference_type:
609 return apply(ut.deref(), i);
610 case utree_type::range_type:
611 return apply(ut.r.first, i);
612 case utree_type::list_type:
613 return apply(ut.l.first, i);
615 BOOST_THROW_EXCEPTION(
617 ("index operation performed on non-list utree type",
622 static utree& apply(list::node* node, std::size_t i)
629 static utree const& apply(list::node const* node, std::size_t i)
638 namespace boost { namespace spirit
640 template <typename F>
641 stored_function<F>::stored_function(F f)
646 template <typename F>
647 stored_function<F>::~stored_function()
651 template <typename F>
652 utree stored_function<F>::operator()(utree const& env) const
657 template <typename F>
658 utree stored_function<F>::operator()(utree& env) const
663 template <typename F>
665 stored_function<F>::clone() const
667 return new stored_function<F>(f);
670 template <typename F>
671 referenced_function<F>::referenced_function(F& f)
676 template <typename F>
677 referenced_function<F>::~referenced_function()
681 template <typename F>
682 utree referenced_function<F>::operator()(utree const& env) const
687 template <typename F>
688 utree referenced_function<F>::operator()(utree& env) const
693 template <typename F>
695 referenced_function<F>::clone() const
697 return new referenced_function<F>(f);
700 inline utree::utree(utree::invalid_type)
703 set_type(type::invalid_type);
706 inline utree::utree(utree::nil_type)
709 set_type(type::nil_type);
712 inline utree::utree(bool b_)
716 set_type(type::bool_type);
719 inline utree::utree(char c)
722 // char constructs a single element string
723 s.construct(&c, &c+1);
724 set_type(type::string_type);
727 inline utree::utree(unsigned int i_)
731 set_type(type::int_type);
734 inline utree::utree(int i_)
738 set_type(type::int_type);
741 inline utree::utree(double d_)
745 set_type(type::double_type);
748 inline utree::utree(char const* str)
751 s.construct(str, str + strlen(str));
752 set_type(type::string_type);
755 inline utree::utree(char const* str, std::size_t len)
758 s.construct(str, str + len);
759 set_type(type::string_type);
762 inline utree::utree(std::string const& str)
765 s.construct(str.begin(), str.end());
766 set_type(type::string_type);
769 template <typename Base, utree_type::info type_>
770 inline utree::utree(basic_string<Base, type_> const& bin)
773 s.construct(bin.begin(), bin.end());
777 inline utree::utree(boost::reference_wrapper<utree> ref)
780 p = ref.get_pointer();
781 set_type(type::reference_type);
784 inline utree::utree(any_ptr const& p)
789 set_type(type::any_type);
792 inline utree::utree(function_base const& pf_)
796 set_type(type::function_type);
799 inline utree::utree(function_base* pf_)
803 set_type(type::function_type);
806 template <typename Iter>
807 inline utree::utree(boost::iterator_range<Iter> r)
811 assign(r.begin(), r.end());
814 inline utree::utree(range r, shallow_tag)
817 this->r.first = r.begin().node;
818 this->r.last = r.end().prev;
819 set_type(type::range_type);
822 inline utree::utree(const_range r, shallow_tag)
825 this->r.first = r.begin().node;
826 this->r.last = r.end().prev;
827 set_type(type::range_type);
830 inline utree::utree(utf8_string_range_type const& str, shallow_tag)
833 this->sr.first = str.begin();
834 this->sr.last = str.end();
835 set_type(type::string_range_type);
838 inline utree::utree(utree const& other)
844 inline utree::~utree()
849 inline utree& utree::operator=(utree const& other)
859 inline utree& utree::operator=(nil_type)
862 set_type(type::nil_type);
866 inline utree& utree::operator=(bool b_)
870 set_type(type::bool_type);
874 inline utree& utree::operator=(char c)
876 // char constructs a single element string
878 s.construct(&c, &c+1);
879 set_type(type::string_type);
883 inline utree& utree::operator=(unsigned int i_)
887 set_type(type::int_type);
891 inline utree& utree::operator=(int i_)
895 set_type(type::int_type);
899 inline utree& utree::operator=(double d_)
903 set_type(type::double_type);
907 inline utree& utree::operator=(char const* s_)
910 s.construct(s_, s_ + strlen(s_));
911 set_type(type::string_type);
915 inline utree& utree::operator=(std::string const& s_)
918 s.construct(s_.begin(), s_.end());
919 set_type(type::string_type);
923 template <typename Base, utree_type::info type_>
924 inline utree& utree::operator=(basic_string<Base, type_> const& bin)
927 s.construct(bin.begin(), bin.end());
932 inline utree& utree::operator=(boost::reference_wrapper<utree> ref)
935 p = ref.get_pointer();
936 set_type(type::reference_type);
940 inline utree& utree::operator=(any_ptr const& p_)
945 set_type(type::any_type);
949 inline utree& utree::operator=(function_base const& pf_)
953 set_type(type::function_type);
957 inline utree& utree::operator=(function_base* pf_)
961 set_type(type::function_type);
965 template <typename Iter>
966 inline utree& utree::operator=(boost::iterator_range<Iter> r)
969 assign(r.begin(), r.end());
973 template <typename F>
974 typename boost::result_of<F(utree const&)>::type
975 inline utree::visit(utree const& x, F f)
977 return detail::visit_impl<utree const>::apply(x, f);
980 template <typename F>
981 typename boost::result_of<F(utree&)>::type
982 inline utree::visit(utree& x, F f)
984 return detail::visit_impl<utree>::apply(x, f);
987 template <typename F>
988 typename boost::result_of<F(utree const&, utree const&)>::type
989 inline utree::visit(utree const& x, utree const& y, F f)
991 return detail::visit_impl<utree const, utree const>::apply(x, y, f);
994 template <typename F>
995 typename boost::result_of<F(utree const&, utree&)>::type
996 inline utree::visit(utree const& x, utree& y, F f)
998 return detail::visit_impl<utree const, utree>::apply(x, y, f);
1001 template <typename F>
1002 typename boost::result_of<F(utree&, utree const&)>::type
1003 inline utree::visit(utree& x, utree const& y, F f)
1005 return detail::visit_impl<utree, utree const>::apply(x, y, f);
1008 template <typename F>
1009 typename boost::result_of<F(utree&, utree&)>::type
1010 inline utree::visit(utree& x, utree& y, F f)
1012 return detail::visit_impl<utree, utree>::apply(x, y, f);
1015 inline utree::reference get(utree::reference ut, utree::size_type i)
1016 { return detail::index_impl::apply(ut, i); }
1018 inline utree::const_reference
1019 get(utree::const_reference ut, utree::size_type i)
1020 { return detail::index_impl::apply(ut, i); }
1022 template <typename T>
1023 inline void utree::push_front(T const& val)
1025 if (get_type() == type::reference_type)
1026 return p->push_front(val);
1028 ensure_list_type("push_front()");
1032 template <typename T>
1033 inline void utree::push_back(T const& val)
1035 if (get_type() == type::reference_type)
1036 return p->push_back(val);
1038 ensure_list_type("push_back()");
1042 template <typename T>
1043 inline utree::iterator utree::insert(iterator pos, T const& val)
1045 if (get_type() == type::reference_type)
1046 return p->insert(pos, val);
1048 ensure_list_type("insert()");
1052 return utree::iterator(l.last, l.last->prev);
1055 return utree::iterator(pos.node->prev, pos.node->prev->prev);
1058 template <typename T>
1059 inline void utree::insert(iterator pos, std::size_t n, T const& val)
1061 if (get_type() == type::reference_type)
1062 return p->insert(pos, n, val);
1064 ensure_list_type("insert()");
1065 for (std::size_t i = 0; i != n; ++i)
1069 template <typename Iterator>
1070 inline void utree::insert(iterator pos, Iterator first, Iterator last)
1072 if (get_type() == type::reference_type)
1073 return p->insert(pos, first, last);
1075 ensure_list_type("insert()");
1076 while (first != last)
1077 insert(pos, *first++);
1080 template <typename Iterator>
1081 inline void utree::assign(Iterator first, Iterator last)
1083 if (get_type() == type::reference_type)
1084 return p->assign(first, last);
1087 set_type(type::list_type);
1089 while (first != last)
1096 inline void utree::clear()
1098 if (get_type() == type::reference_type)
1101 // clear will always make this an invalid type
1103 set_type(type::invalid_type);
1106 inline void utree::pop_front()
1108 if (get_type() == type::reference_type)
1109 return p->pop_front();
1110 if (get_type() != type::list_type)
1111 BOOST_THROW_EXCEPTION(
1113 ("pop_front() called on non-list utree type",
1119 inline void utree::pop_back()
1121 if (get_type() == type::reference_type)
1122 return p->pop_back();
1123 if (get_type() != type::list_type)
1124 BOOST_THROW_EXCEPTION(
1126 ("pop_back() called on non-list utree type",
1132 inline utree::iterator utree::erase(iterator pos)
1134 if (get_type() == type::reference_type)
1135 return p->erase(pos);
1136 if (get_type() != type::list_type)
1137 BOOST_THROW_EXCEPTION(
1139 ("erase() called on non-list utree type",
1142 detail::list::node* np = l.erase(pos.node);
1143 return iterator(np, np?np->prev:l.last);
1146 inline utree::iterator utree::erase(iterator first, iterator last)
1148 if (get_type() == type::reference_type)
1149 return p->erase(first, last);
1151 if (get_type() != type::list_type)
1152 BOOST_THROW_EXCEPTION(
1154 ("erase() called on non-list utree type",
1156 while (first != last)
1161 inline utree::iterator utree::begin()
1163 if (get_type() == type::reference_type)
1165 else if (get_type() == type::range_type)
1166 return iterator(r.first, 0);
1169 ensure_list_type("begin()");
1170 return iterator(l.first, 0);
1173 inline utree::iterator utree::end()
1175 if (get_type() == type::reference_type)
1177 else if (get_type() == type::range_type)
1178 return iterator(0, r.first);
1181 ensure_list_type("end()");
1182 return iterator(0, l.last);
1185 inline utree::ref_iterator utree::ref_begin()
1187 if (get_type() == type::reference_type)
1188 return p->ref_begin();
1189 else if (get_type() == type::range_type)
1190 return ref_iterator(r.first, 0);
1193 ensure_list_type("ref_begin()");
1194 return ref_iterator(l.first, 0);
1197 inline utree::ref_iterator utree::ref_end()
1199 if (get_type() == type::reference_type)
1200 return p->ref_end();
1201 else if (get_type() == type::range_type)
1202 return ref_iterator(0, r.first);
1205 ensure_list_type("ref_end()");
1206 return ref_iterator(0, l.last);
1209 inline utree::const_iterator utree::begin() const
1211 if (get_type() == type::reference_type)
1212 return ((utree const*)p)->begin();
1213 if (get_type() == type::range_type)
1214 return const_iterator(r.first, 0);
1217 if (get_type() != type::list_type)
1218 BOOST_THROW_EXCEPTION(
1220 ("begin() called on non-list utree type",
1223 return const_iterator(l.first, 0);
1226 inline utree::const_iterator utree::end() const
1228 if (get_type() == type::reference_type)
1229 return ((utree const*)p)->end();
1230 if (get_type() == type::range_type)
1231 return const_iterator(0, r.first);
1234 if (get_type() != type::list_type)
1235 BOOST_THROW_EXCEPTION(
1237 ("end() called on non-list utree type",
1240 return const_iterator(0, l.last);
1243 inline bool utree::empty() const
1245 type::info t = get_type();
1246 if (t == type::reference_type)
1247 return ((utree const*)p)->empty();
1249 if (t == type::range_type)
1250 return r.first == 0;
1251 if (t == type::list_type)
1254 return t == type::nil_type || t == type::invalid_type;
1257 inline std::size_t utree::size() const
1259 type::info t = get_type();
1260 if (t == type::reference_type)
1261 return ((utree const*)p)->size();
1263 if (t == type::range_type)
1265 // FIXME: O(n), and we have the room to store the size of a range
1266 // in the union if we compute it when assigned/constructed.
1267 std::size_t size = 0;
1268 detail::list::node* n = r.first;
1276 if (t == type::list_type)
1279 if (t == type::string_type)
1282 if (t == type::symbol_type)
1285 if (t == type::binary_type)
1288 if (t == type::string_range_type)
1289 return sr.last - sr.first;
1291 if (t != type::nil_type)
1292 BOOST_THROW_EXCEPTION(
1294 ("size() called on non-list and non-string utree type",
1300 inline utree_type::info utree::which() const
1305 inline utree& utree::front()
1307 if (get_type() == type::reference_type)
1309 if (get_type() == type::range_type)
1312 BOOST_THROW_EXCEPTION(
1313 empty_exception("front() called on empty utree range"));
1314 return r.first->val;
1318 if (get_type() != type::list_type)
1319 BOOST_THROW_EXCEPTION(
1321 ("front() called on non-list utree type", get_type()));
1323 BOOST_THROW_EXCEPTION(
1324 empty_exception("front() called on empty utree list"));
1326 return l.first->val;
1329 inline utree& utree::back()
1331 if (get_type() == type::reference_type)
1333 if (get_type() == type::range_type)
1336 BOOST_THROW_EXCEPTION(
1337 empty_exception("back() called on empty utree range"));
1342 if (get_type() != type::list_type)
1343 BOOST_THROW_EXCEPTION(
1345 ("back() called on non-list utree type", get_type()));
1347 BOOST_THROW_EXCEPTION(
1348 empty_exception("back() called on empty utree list"));
1353 inline utree const& utree::front() const
1355 if (get_type() == type::reference_type)
1356 return ((utree const*)p)->front();
1357 if (get_type() == type::range_type)
1360 BOOST_THROW_EXCEPTION(
1361 empty_exception("front() called on empty utree range"));
1362 return r.first->val;
1366 if (get_type() != type::list_type)
1367 BOOST_THROW_EXCEPTION(
1369 ("front() called on non-list utree type", get_type()));
1371 BOOST_THROW_EXCEPTION(
1372 empty_exception("front() called on empty utree list"));
1374 return l.first->val;
1377 inline utree const& utree::back() const
1379 if (get_type() == type::reference_type)
1380 return ((utree const*)p)->back();
1381 if (get_type() == type::range_type)
1384 BOOST_THROW_EXCEPTION(
1385 empty_exception("back() called on empty utree range"));
1390 if (get_type() != type::list_type)
1391 BOOST_THROW_EXCEPTION(
1393 ("back() called on non-list utree type", get_type()));
1395 BOOST_THROW_EXCEPTION(
1396 empty_exception("back() called on empty utree list"));
1401 inline void utree::swap(utree& other)
1406 inline utree::type::info utree::get_type() const
1408 // the fast string holds the type info
1409 return static_cast<utree::type::info>(s.get_type());
1412 inline void utree::set_type(type::info t)
1414 // the fast string holds the type info
1418 inline void utree::ensure_list_type(char const* failed_in)
1420 type::info t = get_type();
1421 if (t == type::invalid_type)
1423 set_type(type::list_type);
1424 l.default_construct();
1426 else if (get_type() != type::list_type)
1428 std::string msg = failed_in;
1429 msg += "called on non-list and non-invalid utree type";
1430 BOOST_THROW_EXCEPTION(bad_type_exception(msg.c_str(), get_type()));
1434 inline void utree::free()
1438 case type::binary_type:
1439 case type::symbol_type:
1440 case type::string_type:
1443 case type::list_type:
1446 case type::function_type:
1455 inline void utree::copy(utree const& other)
1457 set_type(other.get_type());
1458 switch (other.get_type())
1461 BOOST_THROW_EXCEPTION(
1462 bad_type_exception("corrupt utree type", other.get_type()));
1464 case type::invalid_type:
1465 case type::nil_type:
1466 s.tag(other.s.tag());
1468 case type::bool_type:
1470 s.tag(other.s.tag());
1472 case type::int_type:
1474 s.tag(other.s.tag());
1476 case type::double_type:
1478 s.tag(other.s.tag());
1480 case type::reference_type:
1482 s.tag(other.s.tag());
1484 case type::any_type:
1486 s.tag(other.s.tag());
1488 case type::range_type:
1490 s.tag(other.s.tag());
1492 case type::string_range_type:
1494 s.tag(other.s.tag());
1496 case type::function_type:
1497 pf = other.pf->clone();
1498 s.tag(other.s.tag());
1500 case type::string_type:
1501 case type::symbol_type:
1502 case type::binary_type:
1504 s.tag(other.s.tag());
1506 case type::list_type:
1508 s.tag(other.s.tag());
1513 template <typename T>
1514 struct is_iterator_range
1515 : boost::mpl::false_
1518 template <typename Iterator>
1519 struct is_iterator_range<boost::iterator_range<Iterator> >
1523 template <typename To>
1526 typedef To result_type;
1528 template <typename From>
1529 To dispatch(From const& val, boost::mpl::true_) const
1531 return To(val); // From is convertible to To
1534 template <typename From>
1535 BOOST_NORETURN To dispatch(From const&, boost::mpl::false_) const
1537 // From is NOT convertible to To !!!
1538 throw std::bad_cast();
1539 BOOST_UNREACHABLE_RETURN(To())
1542 template <typename From>
1543 To operator()(From const& val) const
1545 // boost::iterator_range has a templated constructor, accepting
1546 // any argument and hence any type is 'convertible' to it.
1547 typedef typename boost::mpl::eval_if<
1548 is_iterator_range<To>
1549 , boost::is_same<From, To>, boost::is_convertible<From, To>
1550 >::type is_convertible;
1551 return dispatch(val, is_convertible());
1555 template <typename T>
1556 struct utree_cast<T*>
1558 typedef T* result_type;
1560 template <typename From>
1561 BOOST_NORETURN T* operator()(From const&) const
1563 // From is NOT convertible to T !!!
1564 throw std::bad_cast();
1565 BOOST_UNREACHABLE_RETURN(NULL)
1568 T* operator()(any_ptr const& p) const
1574 template <typename T>
1575 inline T utree::get() const
1577 return utree::visit(*this, utree_cast<T>());
1580 inline utree& utree::deref()
1582 return (get_type() == type::reference_type) ? *p : *this;
1585 inline utree const& utree::deref() const
1587 return (get_type() == type::reference_type) ? *p : *this;
1590 inline short utree::tag() const
1595 inline void utree::tag(short tag)
1600 inline utree utree::eval(utree const& env) const
1602 if (get_type() == type::reference_type)
1603 return deref().eval(env);
1605 if (get_type() != type::function_type)
1606 BOOST_THROW_EXCEPTION(
1608 "eval() called on non-function utree type", get_type()));
1612 inline utree utree::eval(utree& env) const
1614 if (get_type() == type::reference_type)
1615 return deref().eval(env);
1617 if (get_type() != type::function_type)
1618 BOOST_THROW_EXCEPTION(
1620 "eval() called on non-function utree type", get_type()));
1624 inline utree utree::operator() (utree const& env) const
1629 inline utree utree::operator() (utree& env) const
1636 # pragma warning(pop)