|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r66912 - in trunk/boost/spirit/home: karma/string support support/utree support/utree/detail
From: hartmut.kaiser_at_[hidden]
Date: 2010-11-30 14:48:29
Author: hkaiser
Date: 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
New Revision: 66912
URL: http://svn.boost.org/trac/boost/changeset/66912
Log:
Spirit: adding utree as a first class citizen
Added:
trunk/boost/spirit/home/support/utree/
trunk/boost/spirit/home/support/utree.hpp (contents, props changed)
trunk/boost/spirit/home/support/utree/detail/
trunk/boost/spirit/home/support/utree/detail/utree_detail1.hpp (contents, props changed)
trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp (contents, props changed)
trunk/boost/spirit/home/support/utree/operators.hpp (contents, props changed)
trunk/boost/spirit/home/support/utree/utree.hpp (contents, props changed)
trunk/boost/spirit/home/support/utree/utree_traits.hpp (contents, props changed)
Text files modified:
trunk/boost/spirit/home/karma/string/symbols.hpp | 5 +++--
trunk/boost/spirit/home/support/attributes_fwd.hpp | 9 +++++++++
2 files changed, 12 insertions(+), 2 deletions(-)
Modified: trunk/boost/spirit/home/karma/string/symbols.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/symbols.hpp (original)
+++ trunk/boost/spirit/home/karma/string/symbols.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -9,6 +9,7 @@
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
@@ -31,7 +32,7 @@
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
- template <typename T, typename Attribute, typename Enable = void>
+ template <typename T, typename Attribute, typename Enable>
struct symbols_lookup
{
typedef
@@ -84,7 +85,7 @@
}
};
- template <typename Attribute, typename T, typename Enable = void>
+ template <typename Attribute, typename T, typename Enable>
struct symbols_value
{
typedef
Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -193,6 +193,15 @@
template<typename Out, typename T>
void print_token(Out&, T const&);
+ ///////////////////////////////////////////////////////////////////////////
+ // Access attributes from a karma symbol table
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, typename Attribute, typename Enable = void>
+ struct symbols_lookup;
+
+ template <typename Attribute, typename T, typename Enable = void>
+ struct symbols_value;
+
}}}
#endif
Added: trunk/boost/spirit/home/support/utree.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,19 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE_NOV_30_2010_1246PM)
+#define BOOST_SPIRIT_UTREE_NOV_30_2010_1246PM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/utree/utree.hpp>
+#include <boost/spirit/home/support/utree/operators.hpp>
+#include <boost/spirit/home/support/utree/utree_traits.hpp>
+#include <boost/spirit/home/support/utree/detail/utree_detail2.hpp>
+
+#endif
Added: trunk/boost/spirit/home/support/utree/detail/utree_detail1.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree/detail/utree_detail1.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,149 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE_DETAIL1)
+#define BOOST_SPIRIT_UTREE_DETAIL1
+
+#include <boost/type_traits/alignment_of.hpp>
+
+namespace boost { namespace spirit { namespace detail
+{
+ template <typename UTreeX, typename UTreeY>
+ struct visit_impl;
+
+ struct index_impl;
+
+ template <typename T>
+ struct get_impl;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our POD double linked list. Straightforward implementation.
+ // This implementation is very primitive and is not meant to be
+ // used stand-alone. This is the internal data representation
+ // of lists in our utree.
+ ///////////////////////////////////////////////////////////////////////////
+ struct list // keep this a POD!
+ {
+ struct node;
+
+ template <typename Value>
+ class node_iterator;
+
+ void free();
+ void copy(list const& other);
+ void default_construct();
+
+ template <typename T>
+ void insert_before(T const& val, node* node);
+
+ template <typename T>
+ void insert_after(T const& val, node* node);
+
+ template <typename T>
+ void push_front(T const& val);
+
+ template <typename T>
+ void push_back(T const& val);
+
+ void pop_front();
+ void pop_back();
+ node* erase(node* pos);
+
+ node* first;
+ node* last;
+ std::size_t size;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A range of utree(s) using an iterator range (begin/end) of node(s)
+ ///////////////////////////////////////////////////////////////////////////
+ struct range
+ {
+ list::node* first;
+ list::node* last;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A range of char*s
+ ///////////////////////////////////////////////////////////////////////////
+ struct string_range
+ {
+ char const* first;
+ char const* last;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A void* plus type_info
+ ///////////////////////////////////////////////////////////////////////////
+ struct void_ptr
+ {
+ void* p;
+ std::type_info const* i;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our POD fast string. This implementation is very primitive and is not
+ // meant to be used stand-alone. This is the internal data representation
+ // of strings in our utree. This is deliberately a POD to allow it to be
+ // placed in a union. This POD fast string specifically utilizes
+ // (sizeof(list) * alignment_of(list)) - (2 * sizeof(char)). In a 32 bit
+ // system, this is 14 bytes. The two extra bytes are used by utree to store
+ // management info.
+ //
+ // It is a const string (i.e. immutable). It stores the characters directly
+ // if possible and only uses the heap if the string does not fit. Null
+ // characters are allowed, making it suitable to encode raw binary. The
+ // string length is encoded in the first byte if the string is placed in-situ,
+ // else, the length plus a pointer to the string in the heap are stored.
+ ///////////////////////////////////////////////////////////////////////////
+ struct fast_string // Keep this a POD!
+ {
+ static std::size_t const
+ buff_size = (sizeof(list) + boost::alignment_of<list>::value)
+ / sizeof(char);
+
+ static std::size_t const
+ small_string_size = buff_size-sizeof(char);
+
+ static std::size_t const
+ max_string_len = small_string_size - 1;
+
+ struct heap_store
+ {
+ char* str;
+ std::size_t size;
+ };
+
+ union
+ {
+ char buff[buff_size];
+ heap_store heap;
+ };
+
+ int get_type() const;
+ void set_type(int t);
+ bool is_heap_allocated() const;
+
+ std::size_t size() const;
+ char const* str() const;
+
+ template <typename Iterator>
+ void construct(Iterator f, Iterator l);
+
+ void swap(fast_string& other);
+ void free();
+ void copy(fast_string const& other);
+
+ char& info();
+ char info() const;
+
+ short tag() const;
+ void tag(short tag);
+ };
+}}}
+
+#endif
Added: trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,1390 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE_DETAIL2)
+#define BOOST_SPIRIT_UTREE_DETAIL2
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4800)
+#endif
+
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost { namespace spirit { namespace detail
+{
+ inline char& fast_string::info()
+ {
+ return buff[small_string_size];
+ }
+
+ inline char fast_string::info() const
+ {
+ return buff[small_string_size];
+ }
+
+ inline int fast_string::get_type() const
+ {
+ return info() >> 1;
+ }
+
+ inline void fast_string::set_type(int t)
+ {
+ info() = (t << 1) | (info() & 1);
+ }
+
+ inline short fast_string::tag() const
+ {
+ // warning the tag is not allowed for fast_string!!! it's only
+ // placed here to avoid excess padding.
+ return (int(buff[small_string_size-2]) << 8) + buff[small_string_size-1];
+ }
+
+ inline void fast_string::tag(short tag)
+ {
+ // warning the tag is not allowed for fast_string!!! it's only
+ // placed here to avoid excess padding.
+ buff[small_string_size-2] = tag >> 8;
+ buff[small_string_size-1] = tag & 0xff;
+ }
+
+ inline bool fast_string::is_heap_allocated() const
+ {
+ return info() & 1;
+ }
+
+ inline std::size_t fast_string::size() const
+ {
+ if (is_heap_allocated())
+ return heap.size;
+ else
+ return max_string_len - buff[small_string_size - 1];
+ }
+
+ inline char const* fast_string::str() const
+ {
+ if (is_heap_allocated())
+ return heap.str;
+ else
+ return buff;
+ }
+
+ template <typename Iterator>
+ inline void fast_string::construct(Iterator f, Iterator l)
+ {
+ unsigned const size = l-f;
+ char* str;
+ if (size < small_string_size)
+ {
+ // if it fits, store it in-situ; small_string_size minus the length
+ // of the string is placed in buff[small_string_size - 1]
+ str = buff;
+ buff[small_string_size - 1] = static_cast<char>(max_string_len - size);
+ info() &= ~0x1;
+ }
+ else
+ {
+ // else, store it in the heap
+ str = new char[size + 1]; // add one for the null char
+ heap.str = str;
+ heap.size = size;
+ info() |= 0x1;
+ }
+ for (std::size_t i = 0; i != size; ++i)
+ {
+ *str++ = *f++;
+ }
+ *str = '\0'; // add the null char
+ }
+
+ inline void fast_string::swap(fast_string& other)
+ {
+ std::swap(*this, other);
+ }
+
+ inline void fast_string::free()
+ {
+ if (is_heap_allocated())
+ {
+ delete [] heap.str;
+ heap.str = 0;
+ }
+ }
+
+ inline void fast_string::copy(fast_string const& other)
+ {
+ construct(other.str(), other.str() + other.size());
+ }
+
+ struct list::node : boost::noncopyable
+ {
+ template <typename T>
+ node(T const& val, node* next, node* prev)
+ : val(val), next(next), prev(prev) {}
+
+ void unlink()
+ {
+ prev->next = next;
+ next->prev = prev;
+ }
+
+ utree val;
+ node* next;
+ node* prev;
+ };
+
+ template <typename Value>
+ class list::node_iterator
+ : public boost::iterator_facade<
+ node_iterator<Value>
+ , Value
+ , boost::random_access_traversal_tag
+ >
+ {
+ public:
+
+ node_iterator()
+ : node(0) {}
+
+ node_iterator(list::node* node, list::node* prev)
+ : node(node), prev(prev) {}
+
+ private:
+
+ friend class boost::iterator_core_access;
+ friend class boost::spirit::utree;
+
+ void increment()
+ {
+ if (node != 0) // not at end
+ {
+ prev = node;
+ node = node->next;
+ }
+ }
+
+ void decrement()
+ {
+ if (prev != 0) // not at begin
+ {
+ node = prev;
+ prev = prev->prev;
+ }
+ }
+
+ bool equal(node_iterator const& other) const
+ {
+ return node == other.node;
+ }
+
+ typename node_iterator::reference dereference() const
+ {
+ return node->val;
+ }
+
+ void advance (typename node_iterator::difference_type n)
+ {
+ std::advance(*this, n);
+ }
+
+ template<typename Iterator>
+ typename node_iterator::difference_type distance_to(Iterator const& other)
+ const {
+ return std::distance(*this, node_iterator(other));
+ }
+
+ list::node* node;
+ list::node* prev;
+ };
+
+ template <typename Value>
+ class list::node_iterator<boost::reference_wrapper<Value> >
+ : public boost::iterator_facade<
+ node_iterator<boost::reference_wrapper<Value> >
+ , boost::reference_wrapper<Value>
+ , boost::random_access_traversal_tag
+ >
+ {
+ public:
+
+ node_iterator()
+ : node(0), prev(0), curr(nil_node) {}
+
+ node_iterator(list::node* node, list::node* prev)
+ : node(node), prev(prev), curr(node ? node->val : nil_node) {}
+
+ private:
+
+ friend class boost::iterator_core_access;
+ friend class boost::spirit::utree;
+
+ void increment()
+ {
+ if (node != 0) // not at end
+ {
+ prev = node;
+ node = node->next;
+ curr = boost::ref(node ? node->val : nil_node);
+ }
+ }
+
+ void decrement()
+ {
+ if (prev != 0) // not at begin
+ {
+ node = prev;
+ prev = prev->prev;
+ curr = boost::ref(node ? node->val : nil_node);
+ }
+ }
+
+ bool equal(node_iterator const& other) const
+ {
+ return node == other.node;
+ }
+
+ typename node_iterator::reference dereference() const
+ {
+ return curr;
+ }
+
+ void advance (typename node_iterator::difference_type n)
+ {
+ std::advance(*this, n);
+ }
+
+ template<typename Iterator>
+ typename node_iterator::difference_type distance_to(Iterator const& other)
+ const {
+ return std::distance(*this, node_iterator(other));
+ }
+
+ list::node* node;
+ list::node* prev;
+
+ static Value nil_node;
+ mutable boost::reference_wrapper<Value> curr;
+ };
+
+ template <typename Value>
+ Value list::node_iterator<boost::reference_wrapper<Value> >::nil_node = Value();
+
+ inline void list::free()
+ {
+ node* p = first;
+ while (p != last)
+ {
+ node* next = p->next;
+ delete p;
+ p = next;
+ }
+ first = last = 0;
+ size = 0;
+ }
+
+ inline void list::copy(list const& other)
+ {
+ first = last = 0;
+ size = 0;
+ node* p = other.first;
+ while (p != 0)
+ {
+ push_back(p->val);
+ p = p->next;
+ }
+ }
+
+ inline void list::default_construct()
+ {
+ first = last = 0;
+ size = 0;
+ }
+
+ template <typename T>
+ inline void list::insert_before(T const& val, node* np)
+ {
+ BOOST_ASSERT(np != 0);
+ node* new_node = new node(val, np, np->prev);
+ if (np->prev)
+ np->prev->next = new_node;
+ else
+ first = new_node;
+ np->prev = new_node;
+ ++size;
+ }
+
+ template <typename T>
+ inline void list::insert_after(T const& val, node* np)
+ {
+ BOOST_ASSERT(np != 0);
+ node* new_node = new node(val, np->next, np);
+ if (np->next)
+ np->next->prev = new_node;
+ else
+ last = new_node;
+ np->next = new_node;
+ ++size;
+ }
+
+ template <typename T>
+ inline void list::push_front(T const& val)
+ {
+ detail::list::node* new_node;
+ if (first == 0)
+ {
+ new_node = new detail::list::node(val, 0, 0);
+ first = last = new_node;
+ ++size;
+ }
+ else
+ {
+ insert_before(val, first);
+ }
+ }
+
+ template <typename T>
+ inline void list::push_back(T const& val)
+ {
+ if (last == 0)
+ push_front(val);
+ else
+ insert_after(val, last);
+ }
+
+ inline void list::pop_front()
+ {
+ BOOST_ASSERT(size != 0);
+ if (first == last) // there's only one item
+ {
+ delete first;
+ size = 0;
+ first = last = 0;
+ }
+ else
+ {
+ node* np = first;
+ first = first->next;
+ first->prev = 0;
+ delete np;
+ --size;
+ }
+ }
+
+ inline void list::pop_back()
+ {
+ BOOST_ASSERT(size != 0);
+ if (first == last) // there's only one item
+ {
+ delete first;
+ size = 0;
+ first = last = 0;
+ }
+ else
+ {
+ node* np = last;
+ last = last->prev;
+ last->next = 0;
+ delete np;
+ --size;
+ }
+ }
+
+ inline list::node* list::erase(node* pos)
+ {
+ BOOST_ASSERT(pos != 0);
+ if (pos == first)
+ {
+ pop_front();
+ return first;
+ }
+ else if (pos == last)
+ {
+ pop_back();
+ return 0;
+ }
+ else
+ {
+ node* next(pos->next);
+ pos->unlink();
+ delete pos;
+ --size;
+ return next;
+ }
+ }
+
+ template <typename F, typename X>
+ struct bind_impl // simple binder for binary visitation (we don't want to bring in the big guns)
+ {
+ typedef typename F::result_type result_type;
+ X& x; // always by reference
+ F f;
+ bind_impl(F f, X& x) : x(x), f(f) {}
+
+ template <typename Y>
+ typename F::result_type operator()(Y& y) const
+ {
+ return f(x, y);
+ }
+
+ template <typename Y>
+ typename F::result_type operator()(Y const& y) const
+ {
+ return f(x, y);
+ }
+ };
+
+ template <typename F, typename X>
+ bind_impl<F, X const> bind(F f, X const& x)
+ {
+ return bind_impl<F, X const>(f, x);
+ }
+
+ template <typename F, typename X>
+ bind_impl<F, X> bind(F f, X& x)
+ {
+ return bind_impl<F, X>(f, x);
+ }
+
+ template <typename UTreeX, typename UTreeY = UTreeX>
+ struct visit_impl
+ {
+ template <typename F>
+ typename F::result_type
+ static apply(UTreeX& x, F f) // single dispatch
+ {
+ typedef typename
+ boost::mpl::if_<boost::is_const<UTreeX>,
+ typename UTreeX::const_iterator,
+ typename UTreeX::iterator>::type
+ iterator;
+
+ typedef boost::iterator_range<iterator> list_range;
+ typedef utree_type type;
+
+ switch (x.get_type())
+ {
+ default:
+ BOOST_ASSERT(false); // can't happen
+
+ case type::nil_type:
+ nil arg;
+ return f(arg);
+
+ case type::bool_type:
+ return f(x.b);
+
+ case type::int_type:
+ return f(x.i);
+
+ case type::double_type:
+ return f(x.d);
+
+ case type::list_type:
+ return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
+
+ case type::range_type:
+ return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
+
+ case type::string_type:
+ return f(utf8_string_range(x.s.str(), x.s.size()));
+
+ case type::string_range_type:
+ return f(utf8_string_range(x.sr.first, x.sr.last));
+
+ case type::symbol_type:
+ return f(utf8_symbol_range(x.s.str(), x.s.size()));
+
+ case type::binary_type:
+ return f(binary_range(x.s.str(), x.s.size()));
+
+ case type::reference_type:
+ return apply(*x.p, f);
+
+ case type::any_type:
+ return f(any_ptr(x.v.p, x.v.i));
+
+ case type::function_type:
+ return f(*x.pf);
+ }
+ }
+
+ template <typename F>
+ typename F::result_type
+ static apply(UTreeX& x, UTreeY& y, F f) // double dispatch
+ {
+ typedef typename
+ boost::mpl::if_<boost::is_const<UTreeX>,
+ typename UTreeX::const_iterator,
+ typename UTreeX::iterator>::type
+ iterator;
+
+ typedef boost::iterator_range<iterator> list_range;
+ typedef utree_type type;
+
+ switch (x.get_type())
+ {
+ default:
+ BOOST_ASSERT(false); // can't happen
+
+ case type::nil_type:
+ nil x_;
+ return visit_impl::apply(y, detail::bind(f, x_));
+
+ case type::bool_type:
+ return visit_impl::apply(y, detail::bind(f, x.b));
+
+ case type::int_type:
+ return visit_impl::apply(y, detail::bind(f, x.i));
+
+ case type::double_type:
+ return visit_impl::apply(y, detail::bind(f, x.d));
+
+ case type::list_type:
+ return visit_impl::apply(
+ y, detail::bind<F, list_range>(f,
+ list_range(iterator(x.l.first, 0), iterator(0, x.l.last))));
+
+ case type::range_type:
+ return visit_impl::apply(
+ y, detail::bind<F, list_range>(f,
+ list_range(iterator(x.r.first, 0), iterator(0, x.r.last))));
+
+ case type::string_type:
+ return visit_impl::apply(y, detail::bind(
+ f, utf8_string_range(x.s.str(), x.s.size())));
+
+ case type::string_range_type:
+ return visit_impl::apply(y, detail::bind(
+ f, utf8_string_range(x.sr.first, x.sr.last)));
+
+ case type::symbol_type:
+ return visit_impl::apply(y, detail::bind(
+ f, utf8_symbol_range(x.s.str(), x.s.size())));
+
+ case type::binary_type:
+ return visit_impl::apply(y, detail::bind(
+ f, binary_range(x.s.str(), x.s.size())));
+
+ case type::reference_type:
+ return apply(*x.p, y, f);
+
+ case type::any_type:
+ return visit_impl::apply(
+ y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
+
+ case type::function_type:
+ return visit_impl::apply(y, detail::bind(f, *x.pf));
+
+ }
+ }
+ };
+
+ struct index_impl
+ {
+ static utree& apply(list::node* node, std::size_t i)
+ {
+ for (; i > 0; --i)
+ node = node->next;
+ return node->val;
+ }
+
+ static utree const& apply(list::node const* node, std::size_t i)
+ {
+ for (; i > 0; --i)
+ node = node->next;
+ return node->val;
+ }
+ };
+}}}
+
+namespace boost { namespace spirit
+{
+ template <typename F>
+ stored_function<F>::stored_function(F f)
+ : f(f)
+ {
+ }
+
+ template <typename F>
+ stored_function<F>::~stored_function()
+ {
+ };
+
+ template <typename F>
+ utree stored_function<F>::operator()(scope const& env) const
+ {
+ return f(env);
+ }
+
+ template <typename F>
+ function_base*
+ stored_function<F>::clone() const
+ {
+ return new stored_function<F>(*this);
+ }
+
+ inline utree::utree()
+ {
+ set_type(type::nil_type);
+ }
+
+ inline utree::utree(bool b) : b(b)
+ {
+ set_type(type::bool_type);
+ }
+
+ inline utree::utree(char c)
+ {
+ // char constructs a single element string
+ s.construct(&c, &c+1);
+ set_type(type::string_type);
+ }
+
+ inline utree::utree(unsigned int i) : i(i)
+ {
+ set_type(type::int_type);
+ }
+
+ inline utree::utree(int i) : i(i)
+ {
+ set_type(type::int_type);
+ }
+
+ inline utree::utree(double d) : d(d)
+ {
+ set_type(type::double_type);
+ }
+
+ inline utree::utree(char const* str)
+ {
+ s.construct(str, str + strlen(str));
+ set_type(type::string_type);
+ }
+
+ inline utree::utree(char const* str, std::size_t len)
+ {
+ s.construct(str, str + len);
+ set_type(type::string_type);
+ }
+
+ inline utree::utree(std::string const& str)
+ {
+ s.construct(str.begin(), str.end());
+ set_type(type::string_type);
+ }
+
+ template <typename Base, utree_type::info type_>
+ inline utree::utree(basic_string<Base, type_> const& bin)
+ {
+ s.construct(bin.begin(), bin.end());
+ set_type(type_);
+ }
+
+ inline utree::utree(boost::reference_wrapper<utree> ref)
+ : p(ref.get_pointer())
+ {
+ set_type(type::reference_type);
+ }
+
+ inline utree::utree(any_ptr const& p)
+ {
+ v.p = p.p;
+ v.i = p.i;
+ set_type(type::any_type);
+ }
+
+ template <typename F>
+ inline utree::utree(stored_function<F> const& pf)
+ : pf(new stored_function<F>(pf))
+ {
+ set_type(type::function_type);
+ }
+
+ template <typename Iter>
+ inline utree::utree(boost::iterator_range<Iter> r)
+ {
+ set_type(type::nil_type);
+ assign(r.begin(), r.end());
+ }
+
+ inline utree::utree(range r, shallow_tag)
+ {
+ this->r.first = r.begin().node;
+ this->r.last = r.end().prev;
+ set_type(type::range_type);
+ }
+
+ inline utree::utree(const_range r, shallow_tag)
+ {
+ this->r.first = r.begin().node;
+ this->r.last = r.end().prev;
+ set_type(type::range_type);
+ }
+
+ inline utree::utree(utf8_string_range const& str, shallow_tag)
+ {
+ this->sr.first = str.begin();
+ this->sr.last = str.end();
+ set_type(type::string_range_type);
+ }
+
+ inline utree::utree(utree const& other)
+ {
+ copy(other);
+ }
+
+ inline utree::~utree()
+ {
+ free();
+ }
+
+ inline utree& utree::operator=(utree const& other)
+ {
+ if (this != &other)
+ {
+ free();
+ copy(other);
+ }
+ return *this;
+ }
+
+ inline utree& utree::operator=(bool b_)
+ {
+ free();
+ b = b_;
+ set_type(type::bool_type);
+ return *this;
+ }
+
+ inline utree& utree::operator=(unsigned int i_)
+ {
+ free();
+ i = i_;
+ set_type(type::int_type);
+ return *this;
+ }
+
+ inline utree& utree::operator=(int i_)
+ {
+ free();
+ i = i_;
+ set_type(type::int_type);
+ return *this;
+ }
+
+ inline utree& utree::operator=(double d_)
+ {
+ free();
+ d = d_;
+ set_type(type::double_type);
+ return *this;
+ }
+
+ inline utree& utree::operator=(char const* s_)
+ {
+ free();
+ s.construct(s_, s_ + strlen(s_));
+ set_type(type::string_type);
+ return *this;
+ }
+
+ inline utree& utree::operator=(std::string const& s_)
+ {
+ free();
+ s.construct(s_.begin(), s_.end());
+ set_type(type::string_type);
+ return *this;
+ }
+
+ template <typename Base, utree_type::info type_>
+ inline utree& utree::operator=(basic_string<Base, type_> const& bin)
+ {
+ free();
+ s.construct(bin.begin(), bin.end());
+ set_type(type_);
+ return *this;
+ }
+
+ inline utree& utree::operator=(boost::reference_wrapper<utree> ref)
+ {
+ free();
+ p = ref.get_pointer();
+ set_type(type::reference_type);
+ return *this;
+ }
+
+ template <typename F>
+ utree& utree::operator=(stored_function<F> const& pf)
+ {
+ free();
+ pf = new stored_function<F>(pf);
+ set_type(type::function_type);
+ return *this;
+ }
+
+ template <typename Iter>
+ inline utree& utree::operator=(boost::iterator_range<Iter> r)
+ {
+ free();
+ assign(r.begin(), r.end());
+ return *this;
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree const& x, F f)
+ {
+ return detail::visit_impl<utree const>::apply(x, f);
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree& x, F f)
+ {
+ return detail::visit_impl<utree>::apply(x, f);
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree const& x, utree const& y, F f)
+ {
+ return detail::visit_impl<utree const, utree const>::apply(x, y, f);
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree const& x, utree& y, F f)
+ {
+ return detail::visit_impl<utree const, utree>::apply(x, y, f);
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree& x, utree const& y, F f)
+ {
+ return detail::visit_impl<utree, utree const>::apply(x, y, f);
+ }
+
+ template <typename F>
+ typename F::result_type
+ inline utree::visit(utree& x, utree& y, F f)
+ {
+ return detail::visit_impl<utree, utree>::apply(x, y, f);
+ }
+
+ inline utree& utree::operator[](std::size_t i)
+ {
+ if (get_type() == type::reference_type)
+ return (*p)[i];
+ else if (get_type() == type::range_type)
+ return detail::index_impl::apply(r.first, i);
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && size() > i);
+ return detail::index_impl::apply(l.first, i);
+ }
+
+ inline utree const& utree::operator[](std::size_t i) const
+ {
+ if (get_type() == type::reference_type)
+ return (*(utree const*)p)[i];
+ else if (get_type() == type::range_type)
+ return detail::index_impl::apply(r.first, i);
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && size() > i);
+ return detail::index_impl::apply(l.first, i);
+ }
+
+ template <typename T>
+ inline void utree::push_front(T const& val)
+ {
+ if (get_type() == type::reference_type)
+ return p->push_front(val);
+ ensure_list_type();
+ l.push_front(val);
+ }
+
+ template <typename T>
+ inline void utree::push_back(T const& val)
+ {
+ if (get_type() == type::reference_type)
+ return p->push_back(val);
+ ensure_list_type();
+ l.push_back(val);
+ }
+
+ template <typename T>
+ inline utree::iterator utree::insert(iterator pos, T const& val)
+ {
+ if (get_type() == type::reference_type)
+ return p->insert(pos, val);
+ ensure_list_type();
+ if (pos == end())
+ {
+ push_back(val);
+ return begin();
+ }
+ else
+ {
+ l.insert_before(val, pos.node);
+ return utree::iterator(pos.node->prev, pos.node->prev->prev);
+ }
+ }
+
+ template <typename T>
+ inline void utree::insert(iterator pos, std::size_t n, T const& val)
+ {
+ if (get_type() == type::reference_type)
+ return p->insert(pos, n, val);
+ for (std::size_t i = 0; i != n; ++i)
+ insert(pos, val);
+ }
+
+ template <typename Iter>
+ inline void utree::insert(iterator pos, Iter first, Iter last)
+ {
+ if (get_type() == type::reference_type)
+ return p->insert(pos, first, last);
+ ensure_list_type();
+ while (first != last)
+ insert(pos, *first++);
+ }
+
+ template <typename Iter>
+ inline void utree::assign(Iter first, Iter last)
+ {
+ if (get_type() == type::reference_type)
+ return p->assign(first, last);
+ ensure_list_type();
+ clear();
+ while (first != last)
+ {
+ push_back(*first);
+ ++first;
+ }
+ }
+
+ inline void utree::clear()
+ {
+ if (get_type() == type::reference_type)
+ return p->clear();
+ // clear will always make this a nil type
+ free();
+ set_type(type::nil_type);
+ }
+
+ inline void utree::pop_front()
+ {
+ if (get_type() == type::reference_type)
+ return p->pop_front();
+ BOOST_ASSERT(get_type() == type::list_type);
+ l.pop_front();
+ }
+
+ inline void utree::pop_back()
+ {
+ if (get_type() == type::reference_type)
+ return p->pop_back();
+ BOOST_ASSERT(get_type() == type::list_type);
+ l.pop_back();
+ }
+
+ inline utree::iterator utree::erase(iterator pos)
+ {
+ if (get_type() == type::reference_type)
+ return p->erase(pos);
+ BOOST_ASSERT(get_type() == type::list_type);
+ detail::list::node* np = l.erase(pos.node);
+ return iterator(np, np?np->prev:l.last);
+ }
+
+ inline utree::iterator utree::erase(iterator first, iterator last)
+ {
+ if (get_type() == type::reference_type)
+ return p->erase(first, last);
+ while (first != last)
+ erase(first++);
+ return last;
+ }
+
+ inline utree::iterator utree::begin()
+ {
+ if (get_type() == type::reference_type)
+ return p->begin();
+ else if (get_type() == type::range_type)
+ return iterator(r.first, 0);
+
+ // otherwise...
+ ensure_list_type();
+ return iterator(l.first, 0);
+ }
+
+ inline utree::iterator utree::end()
+ {
+ if (get_type() == type::reference_type)
+ return p->end();
+ else if (get_type() == type::range_type)
+ return iterator(0, r.first);
+
+ // otherwise...
+ ensure_list_type();
+ return iterator(0, l.last);
+ }
+
+ inline utree::ref_iterator utree::ref_begin()
+ {
+ if (get_type() == type::reference_type)
+ return p->ref_begin();
+ else if (get_type() == type::range_type)
+ return ref_iterator(r.first, 0);
+
+ // otherwise...
+ ensure_list_type();
+ return ref_iterator(l.first, 0);
+ }
+
+ inline utree::ref_iterator utree::ref_end()
+ {
+ if (get_type() == type::reference_type)
+ return p->ref_end();
+ else if (get_type() == type::range_type)
+ return ref_iterator(0, r.first);
+
+ // otherwise...
+ ensure_list_type();
+ return ref_iterator(0, l.last);
+ }
+
+ inline utree::const_iterator utree::begin() const
+ {
+ if (get_type() == type::reference_type)
+ return ((utree const*)p)->begin();
+ else if (get_type() == type::range_type)
+ return const_iterator(r.first, 0);
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type);
+ return const_iterator(l.first, 0);
+ }
+
+ inline utree::const_iterator utree::end() const
+ {
+ if (get_type() == type::reference_type)
+ return ((utree const*)p)->end();
+ else if (get_type() == type::range_type)
+ return const_iterator(0, r.first);
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type);
+ return const_iterator(0, l.last);
+ }
+
+ inline bool utree::empty() const
+ {
+ if (get_type() == type::reference_type)
+ return ((utree const*)p)->empty();
+ else if (get_type() == type::range_type)
+ return r.first == 0;
+ else if (get_type() == type::list_type)
+ return l.size == 0;
+ return get_type() == type::nil_type;
+ }
+
+ inline std::size_t utree::size() const
+ {
+ if (get_type() == type::reference_type)
+ {
+ return ((utree const*)p)->size();
+ }
+ else if (get_type() == type::range_type)
+ {
+ std::size_t size = 0;
+ detail::list::node* n = r.first;
+ while (n)
+ {
+ n = n->next;
+ ++size;
+ }
+ return size;
+ }
+ else if (get_type() == type::list_type)
+ {
+ return l.size;
+ }
+ BOOST_ASSERT(get_type() == type::nil_type);
+ return 0;
+ }
+
+ inline utree_type::info utree::which() const
+ {
+ return get_type();
+ }
+
+ inline utree& utree::front()
+ {
+ if (get_type() == type::reference_type)
+ {
+ return p->front();
+ }
+ else if (get_type() == type::range_type)
+ {
+ BOOST_ASSERT(r.first != 0);
+ return r.first->val;
+ }
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && l.first != 0);
+ return l.first->val;
+ }
+
+ inline utree& utree::back()
+ {
+ if (get_type() == type::reference_type)
+ {
+ return p->back();
+ }
+ else if (get_type() == type::range_type)
+ {
+ BOOST_ASSERT(r.last != 0);
+ return r.last->val;
+ }
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && l.last != 0);
+ return l.last->val;
+ }
+
+ inline utree const& utree::front() const
+ {
+ if (get_type() == type::reference_type)
+ {
+ return ((utree const*)p)->front();
+ }
+ else if (get_type() == type::range_type)
+ {
+ BOOST_ASSERT(r.first != 0);
+ return r.first->val;
+ }
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && l.first != 0);
+ return l.first->val;
+ }
+
+ inline utree const& utree::back() const
+ {
+ if (get_type() == type::reference_type)
+ {
+ return ((utree const*)p)->back();
+ }
+ else if (get_type() == type::range_type)
+ {
+ BOOST_ASSERT(r.last != 0);
+ return r.last->val;
+ }
+
+ // otherwise...
+ BOOST_ASSERT(get_type() == type::list_type && l.last != 0);
+ return l.last->val;
+ }
+
+ inline void utree::swap(utree& other)
+ {
+ s.swap(other.s);
+ }
+
+ inline utree::type::info utree::get_type() const
+ {
+ // the fast string holds the type info
+ return static_cast<utree::type::info>(s.get_type());
+ }
+
+ inline void utree::set_type(type::info t)
+ {
+ // the fast string holds the type info
+ s.set_type(t);
+ }
+
+ inline void utree::ensure_list_type()
+ {
+ if (get_type() == type::nil_type)
+ {
+ set_type(type::list_type);
+ l.default_construct();
+ }
+ else
+ {
+ BOOST_ASSERT(get_type() == type::list_type);
+ }
+ }
+
+ inline void utree::free()
+ {
+ switch (get_type())
+ {
+ case type::binary_type:
+ case type::symbol_type:
+ case type::string_type:
+ s.free();
+ break;
+ case type::list_type:
+ l.free();
+ break;
+ case type::function_type:
+ delete pf;
+ break;
+ default:
+ break;
+ };
+ }
+
+ inline void utree::copy(utree const& other)
+ {
+ set_type(other.get_type());
+ switch (other.get_type())
+ {
+ case type::nil_type:
+ break;
+ case type::bool_type:
+ b = other.b;
+ break;
+ case type::int_type:
+ i = other.i;
+ break;
+ case type::double_type:
+ d = other.d;
+ break;
+ case type::reference_type:
+ p = other.p;
+ break;
+ case type::any_type:
+ v = other.v;
+ break;
+ case type::range_type:
+ r = other.r;
+ break;
+ case type::string_range_type:
+ sr = other.sr;
+ break;
+ case type::function_type:
+ pf = other.pf->clone();
+ break;
+ case type::string_type:
+ case type::symbol_type:
+ case type::binary_type:
+ s.copy(other.s);
+ break;
+ case type::list_type:
+ l.copy(other.l);
+ s.tag(other.s.tag());
+ break;
+ }
+ }
+
+ template <typename T>
+ struct is_iterator_range
+ : boost::mpl::false_
+ {};
+
+ template <typename Iterator>
+ struct is_iterator_range<boost::iterator_range<Iterator> >
+ : boost::mpl::true_
+ {};
+
+ template <typename To>
+ struct utree_cast
+ {
+ typedef To result_type;
+
+ template <typename From>
+ To dispatch(From const& val, boost::mpl::true_) const
+ {
+ return To(val); // From is convertible to To
+ }
+
+ template <typename From>
+ To dispatch(From const& val, boost::mpl::false_) const
+ {
+ // From is NOT convertible to To !!!
+ throw std::bad_cast();
+ return To();
+ }
+
+ template <typename From>
+ To operator()(From const& val) const
+ {
+ // boost::iterator_range has a templated constructor, accepting
+ // any argument and hence any type is 'convertible' to it.
+ typedef typename boost::mpl::eval_if<
+ is_iterator_range<To>
+ , boost::is_same<From, To>, boost::is_convertible<From, To>
+ >::type is_convertible;
+ return dispatch(val, is_convertible());
+ }
+ };
+
+ template <typename T>
+ struct utree_cast<T*>
+ {
+ typedef T* result_type;
+
+ template <typename From>
+ T* operator()(From const& val) const
+ {
+ // From is NOT convertible to T !!!
+ throw std::bad_cast();
+ return 0;
+ }
+
+ T* operator()(any_ptr const& p) const
+ {
+ return p.get<T*>();
+ }
+ };
+
+ template <typename T>
+ inline T utree::get() const
+ {
+ return utree::visit(*this, utree_cast<T>());
+ }
+
+ inline utree& utree::deref()
+ {
+ return (get_type() == type::reference_type) ? *p : *this;
+ }
+
+ inline utree const& utree::deref() const
+ {
+ return (get_type() == type::reference_type) ? *p : *this;
+ }
+
+ inline short utree::tag() const
+ {
+ BOOST_ASSERT(get_type() == type::list_type);
+ return s.tag();
+ }
+
+ inline void utree::tag(short tag)
+ {
+ ensure_list_type();
+ s.tag(tag);
+ }
+
+ inline utree utree::eval(scope const& env) const
+ {
+ BOOST_ASSERT(get_type() == type::function_type);
+ return (*pf)(env);
+ }
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+#endif
Added: trunk/boost/spirit/home/support/utree/operators.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree/operators.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,582 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
+#define BOOST_SPIRIT_UTREE_OPERATORS
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4804)
+# pragma warning(disable: 4805)
+#endif
+
+#include <exception>
+#include <boost/spirit/home/support/utree/utree.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_integral.hpp>
+
+namespace boost { namespace spirit
+{
+ struct utree_exception : std::exception {};
+
+ struct illegal_arithmetic_operation : utree_exception
+ {
+ virtual const char* what() const throw()
+ {
+ return "utree: Illegal arithmetic operation.";
+ }
+ };
+
+ struct illegal_integral_operation : utree_exception
+ {
+ virtual const char* what() const throw()
+ {
+ return "utree: Illegal integral operation.";
+ }
+ };
+
+ // Relational operators
+ bool operator==(utree const& a, utree const& b);
+ bool operator<(utree const& a, utree const& b);
+ bool operator!=(utree const& a, utree const& b);
+ bool operator>(utree const& a, utree const& b);
+ bool operator<=(utree const& a, utree const& b);
+ bool operator>=(utree const& a, utree const& b);
+
+ // Input and output
+ std::ostream& operator<<(std::ostream& out, utree const& x);
+ std::istream& operator>>(std::istream& in, utree& x);
+
+ std::ostream& operator<<(std::ostream& out, nil const& x);
+
+ // Logical operators
+ utree operator&&(utree const& a, utree const& b);
+ utree operator||(utree const& a, utree const& b);
+ utree operator!(utree const& a);
+
+ // Arithmetic operators
+ utree operator+(utree const& a, utree const& b);
+ utree operator-(utree const& a, utree const& b);
+ utree operator*(utree const& a, utree const& b);
+ utree operator/(utree const& a, utree const& b);
+ utree operator%(utree const& a, utree const& b);
+ utree operator-(utree const& a);
+
+ // Bitwise operators
+ utree operator&(utree const& a, utree const& b);
+ utree operator|(utree const& a, utree const& b);
+ utree operator^(utree const& a, utree const& b);
+ utree operator<<(utree const& a, utree const& b);
+ utree operator>>(utree const& a, utree const& b);
+ utree operator~(utree const& a);
+
+ // Implementation
+ struct utree_is_equal
+ {
+ typedef bool result_type;
+
+ template <typename A, typename B>
+ bool dispatch(const A&, const B&, boost::mpl::false_) const
+ {
+ return false; // cannot compare different types by default
+ }
+
+ template <typename A, typename B>
+ bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+ {
+ return a == b; // for arithmetic types
+ }
+
+ template <typename A, typename B>
+ bool operator()(const A& a, const B& b) const
+ {
+ return dispatch(a, b,
+ boost::mpl::and_<
+ boost::is_arithmetic<A>,
+ boost::is_arithmetic<B> >());
+ }
+
+ template <typename T>
+ bool operator()(const T& a, const T& b) const
+ {
+ // This code works for lists
+ return a == b;
+ }
+
+ template <typename Base, utree_type::info type_>
+ bool operator()(
+ basic_string<Base, type_> const& a,
+ basic_string<Base, type_> const& b) const
+ {
+ return static_cast<Base const&>(a) == static_cast<Base const&>(b);
+ }
+
+ bool operator()(nil, nil) const
+ {
+ return true;
+ }
+
+ bool operator()(function_base const& a, function_base const& b) const
+ {
+ return false; // just don't allow comparison of functions
+ }
+ };
+
+ struct utree_is_less_than
+ {
+ typedef bool result_type;
+
+ template <typename A, typename B>
+ bool dispatch(const A&, const B&, boost::mpl::false_) const
+ {
+ return false; // cannot compare different types by default
+ }
+
+ template <typename A, typename B>
+ bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+ {
+ return a < b; // for arithmetic types
+ }
+
+ template <typename A, typename B>
+ bool operator()(const A& a, const B& b) const
+ {
+ return dispatch(a, b,
+ boost::mpl::and_<
+ boost::is_arithmetic<A>,
+ boost::is_arithmetic<B> >());
+ }
+
+ template <typename T>
+ bool operator()(const T& a, const T& b) const
+ {
+ // This code works for lists
+ return a < b;
+ }
+
+ template <typename Base, utree_type::info type_>
+ bool operator()(
+ basic_string<Base, type_> const& a,
+ basic_string<Base, type_> const& b) const
+ {
+ return static_cast<Base const&>(a) < static_cast<Base const&>(b);
+ }
+
+ bool operator()(nil, nil) const
+ {
+ BOOST_ASSERT(false);
+ return false; // no less than comparison for nil
+ }
+
+ bool operator()(any_ptr const& a, any_ptr const& b) const
+ {
+ BOOST_ASSERT(false);
+ return false; // no less than comparison for any_ptr
+ }
+
+ bool operator()(function_base const& a, function_base const& b) const
+ {
+ BOOST_ASSERT(false);
+ return false; // no less than comparison of functions
+ }
+ };
+
+ struct utree_print
+ {
+ typedef void result_type;
+
+ std::ostream& out;
+ utree_print(std::ostream& out) : out(out) {}
+
+ void operator()(boost::spirit::nil) const
+ {
+ out << "<nil> ";
+ }
+
+ template <typename T>
+ void operator()(T val) const
+ {
+ out << val << ' ';
+ }
+
+ void operator()(bool b) const
+ {
+ out << (b ? "true" : "false") << ' ';
+ }
+
+ void operator()(binary_range const& b) const
+ {
+ out << "#";
+ out.width(2);
+ out.fill('0');
+
+ typedef binary_range::const_iterator iterator;
+ for (iterator i = b.begin(); i != b.end(); ++i)
+ out << std::hex << int((unsigned char)*i);
+ out << std::dec << "# ";
+ }
+
+ void operator()(utf8_string_range const& str) const
+ {
+ typedef utf8_string_range::const_iterator iterator;
+ iterator i = str.begin();
+ out << '"';
+ for (; i != str.end(); ++i)
+ out << *i;
+ out << "\" ";
+ }
+
+ void operator()(utf8_symbol_range const& str) const
+ {
+ typedef utf8_symbol_range::const_iterator iterator;
+ iterator i = str.begin();
+ for (; i != str.end(); ++i)
+ out << *i;
+ }
+
+ template <typename Iterator>
+ void operator()(boost::iterator_range<Iterator> const& range) const
+ {
+ typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
+ (*this)('(');
+ for (iterator i = range.begin(); i != range.end(); ++i)
+ {
+ boost::spirit::utree::visit(*i, *this);
+ }
+ (*this)(')');
+ }
+
+ void operator()(any_ptr const& p) const
+ {
+ return (*this)("<pointer>");
+ }
+
+ void operator()(function_base const& pf) const
+ {
+ return (*this)("<function>");
+ }
+ };
+
+ template <typename Base>
+ struct logical_function
+ {
+ typedef utree result_type;
+
+ // We assume anything except false is true
+
+ // binary
+ utree operator()(bool a, bool b) const
+ {
+ return Base::eval(a, b); // for boolean types
+ }
+
+ // binary
+ template <typename A>
+ utree operator()(A const& a, bool b) const
+ {
+ return Base::eval(true, b);
+ }
+
+ // binary
+ template <typename B>
+ utree operator()(bool a, B const& b) const
+ {
+ return Base::eval(a, true);
+ }
+
+ // binary
+ template <typename A, typename B>
+ utree operator()(A const& a, B const& b) const
+ {
+ return Base::eval(true, true);
+ }
+
+ // unary
+ utree operator()(bool a) const
+ {
+ return Base::eval(a);
+ }
+
+ // unary
+ template <typename A>
+ utree operator()(A const& a) const
+ {
+ return Base::eval(true);
+ }
+ };
+
+ template <typename Base>
+ struct arithmetic_function
+ {
+ typedef utree result_type;
+
+ template <typename A, typename B>
+ utree dispatch(A const&, B const&, boost::mpl::false_) const
+ {
+ throw illegal_arithmetic_operation();
+ return utree(); // cannot apply to non-arithmetic types
+ }
+
+ template <typename A, typename B>
+ utree dispatch(A const& a, B const& b, boost::mpl::true_) const
+ {
+ return Base::eval(a, b); // for arithmetic types
+ }
+
+ // binary
+ template <typename A, typename B>
+ utree operator()(A const& a, B const& b) const
+ {
+ return dispatch(a, b,
+ boost::mpl::and_<
+ boost::is_arithmetic<A>,
+ boost::is_arithmetic<B> >());
+ }
+
+ template <typename A>
+ utree dispatch(A const&, boost::mpl::false_) const
+ {
+ throw illegal_arithmetic_operation();
+ return utree(); // cannot apply to non-arithmetic types
+ }
+
+ template <typename A>
+ utree dispatch(A const& a, boost::mpl::true_) const
+ {
+ return Base::eval(a); // for arithmetic types
+ }
+
+ // unary
+ template <typename A>
+ utree operator()(A const& a) const
+ {
+ return dispatch(a, boost::is_arithmetic<A>());
+ }
+ };
+
+ template <typename Base>
+ struct integral_function
+ {
+ typedef utree result_type;
+
+ template <typename A, typename B>
+ utree dispatch(A const&, B const&, boost::mpl::false_) const
+ {
+ throw illegal_integral_operation();
+ return utree(); // cannot apply to non-integral types
+ }
+
+ template <typename A, typename B>
+ utree dispatch(A const& a, B const& b, boost::mpl::true_) const
+ {
+ return Base::eval(a, b); // for integral types
+ }
+
+ // binary
+ template <typename A, typename B>
+ utree operator()(A const& a, B const& b) const
+ {
+ return dispatch(a, b,
+ boost::mpl::and_<
+ boost::is_integral<A>,
+ boost::is_integral<B> >());
+ }
+
+ template <typename A>
+ utree dispatch(A const&, boost::mpl::false_) const
+ {
+ throw illegal_integral_operation();
+ return utree(); // cannot apply to non-integral types
+ }
+
+ template <typename A>
+ utree dispatch(A const& a, boost::mpl::true_) const
+ {
+ return Base::eval(a); // for integral types
+ }
+
+ // unary
+ template <typename A>
+ utree operator()(A const& a) const
+ {
+ return dispatch(a, boost::is_integral<A>());
+ }
+ };
+
+#define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, base) \
+ struct BOOST_PP_CAT(function_impl_, name) \
+ { \
+ template <typename A, typename B> \
+ static utree eval(A const& a, B const& b) \
+ { \
+ return utree(expr); \
+ } \
+ template <typename A> \
+ static utree eval(A const& a) \
+ { \
+ static int b; \
+ (void) b; \
+ return utree(expr); \
+ } \
+ }; \
+ base<BOOST_PP_CAT(function_impl_, name)> const \
+ BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \
+ /***/
+
+#define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(name, expr) \
+ BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, arithmetic_function) \
+ /***/
+
+#define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(name, expr) \
+ BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, integral_function) \
+ /***/
+
+#define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(name, expr) \
+ BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, logical_function) \
+ /***/
+
+ inline bool operator==(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, utree_is_equal());
+ }
+
+ inline bool operator<(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, utree_is_less_than());
+ }
+
+ inline bool operator!=(utree const& a, utree const& b)
+ {
+ return !(a == b);
+ }
+
+ inline bool operator>(utree const& a, utree const& b)
+ {
+ return b < a;
+ }
+
+ inline bool operator<=(utree const& a, utree const& b)
+ {
+ return !(b < a);
+ }
+
+ inline bool operator>=(utree const& a, utree const& b)
+ {
+ return !(a < b);
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, utree const& x)
+ {
+ utree::visit(x, utree_print(out));
+ return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, nil const& x)
+ {
+ return out;
+ }
+
+ BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b);
+ BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b);
+ BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(not_, !a);
+
+ BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(plus, a+b);
+ BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(minus, a-b);
+ BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(times, a*b);
+ BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(divides, a/b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(modulus, a%b);
+ BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(negate, -a);
+
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitand_, a&b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitor_, a|b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_left, a<<b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_right, a>>b);
+ BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a);
+
+ inline utree operator&&(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, logical_function_and_);
+ }
+
+ inline utree operator||(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, logical_function_or_);
+ }
+
+ inline utree operator!(utree const& a)
+ {
+ return utree::visit(a, logical_function_not_);
+ }
+
+ inline utree operator+(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, arithmetic_function_plus);
+ }
+
+ inline utree operator-(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, arithmetic_function_minus);
+ }
+
+ inline utree operator*(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, arithmetic_function_times);
+ }
+
+ inline utree operator/(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, arithmetic_function_divides);
+ }
+
+ inline utree operator%(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_modulus);
+ }
+
+ inline utree operator-(utree const& a)
+ {
+ return utree::visit(a, arithmetic_function_negate);
+ }
+
+ inline utree operator&(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_bitand_);
+ }
+
+ inline utree operator|(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_bitor_);
+ }
+
+ inline utree operator^(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_bitxor_);
+ }
+
+ inline utree operator<<(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_shift_left);
+ }
+
+ inline utree operator>>(utree const& a, utree const& b)
+ {
+ return utree::visit(a, b, integral_function_shift_right);
+ }
+
+ inline utree operator~(utree const& a)
+ {
+ return utree::visit(a, integral_function_invert);
+ }
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif
Added: trunk/boost/spirit/home/support/utree/utree.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree/utree.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,443 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE)
+#define BOOST_SPIRIT_UTREE
+
+#include <cstddef>
+#include <algorithm>
+#include <string>
+#include <ostream>
+#include <typeinfo>
+
+#include <boost/assert.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/ref.hpp>
+
+#include <boost/spirit/home/support/utree/detail/utree_detail1.hpp>
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4804)
+# pragma warning(disable: 4805)
+# pragma warning(disable: 4244)
+#endif
+
+namespace boost { namespace spirit
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our utree can store these types. This enum tells us what type
+ // of data is stored in utree's discriminated union.
+ ///////////////////////////////////////////////////////////////////////////
+ struct utree_type
+ {
+ enum info
+ {
+ nil_type,
+ bool_type,
+ int_type,
+ double_type,
+ string_type,
+ string_range_type,
+ symbol_type,
+ binary_type,
+ list_type,
+ range_type,
+ reference_type,
+ any_type,
+ function_type
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The nil type
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A typed string with parametric Base storage. The storage can be any
+ // range or (stl container) of chars.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Base, utree_type::info type_>
+ struct basic_string : Base
+ {
+ static utree_type::info const type = type_;
+
+ basic_string()
+ : Base() {}
+
+ basic_string(Base const& base)
+ : Base(base) {}
+
+ template <typename Iterator>
+ basic_string(Iterator bits, std::size_t len)
+ : Base(bits, bits + len) {}
+
+ template <typename Iterator>
+ basic_string(Iterator first, Iterator last)
+ : Base(first, last) {}
+
+ basic_string& operator=(basic_string const& other)
+ {
+ Base::operator=(other);
+ return *this;
+ }
+
+ basic_string& operator=(Base const& other)
+ {
+ Base::operator=(other);
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Binary string
+ ///////////////////////////////////////////////////////////////////////////
+ typedef basic_string<
+ boost::iterator_range<char const*>,
+ utree_type::binary_type>
+ binary_range;
+
+ typedef basic_string<
+ std::string,
+ utree_type::binary_type>
+ binary_string;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our UTF-8 string
+ ///////////////////////////////////////////////////////////////////////////
+ typedef basic_string<
+ boost::iterator_range<char const*>,
+ utree_type::string_type>
+ utf8_string_range;
+
+ typedef basic_string<
+ std::string,
+ utree_type::string_type>
+ utf8_string_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our UTF-8 symbol (for identifiers)
+ ///////////////////////////////////////////////////////////////////////////
+ typedef basic_string<
+ boost::iterator_range<char const*>,
+ utree_type::symbol_type>
+ utf8_symbol_range;
+
+ typedef basic_string<
+ std::string,
+ utree_type::symbol_type>
+ utf8_symbol;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our function type
+ ///////////////////////////////////////////////////////////////////////////
+ class utree;
+ class scope;
+
+ struct function_base
+ {
+ virtual ~function_base() {};
+ virtual utree operator()(scope const& env) const = 0;
+ virtual function_base* clone() const = 0;
+ };
+
+ template <typename F>
+ struct stored_function : function_base
+ {
+ F f;
+ stored_function(F f = F());
+ virtual ~stored_function();
+ virtual utree operator()(scope const& env) const;
+ virtual function_base* clone() const;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Shallow tag. Instructs utree to hold an iterator_range
+ // as-is without deep copying the range.
+ ///////////////////////////////////////////////////////////////////////////
+ struct shallow_tag {};
+ shallow_tag const shallow = {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A void* plus type_info
+ ///////////////////////////////////////////////////////////////////////////
+ class any_ptr
+ {
+ public:
+
+ template <typename Ptr>
+ typename boost::disable_if<
+ boost::is_polymorphic<
+ typename boost::remove_pointer<Ptr>::type>,
+ Ptr>::type
+ get() const
+ {
+ if (*i == typeid(Ptr))
+ {
+ return static_cast<Ptr>(p);
+ }
+ throw std::bad_cast();
+ }
+
+ template <typename T>
+ any_ptr(T* p)
+ : p(p), i(&typeid(T*))
+ {}
+
+ friend bool operator==(any_ptr const& a, any_ptr const& b)
+ {
+ return (a.p == b.p) && (*a.i == *b.i);
+ }
+
+ private:
+
+ // constructor is private
+ any_ptr(void* p, std::type_info const* i)
+ : p(p), i(i) {}
+
+ template <typename UTreeX, typename UTreeY>
+ friend struct detail::visit_impl;
+
+ friend class utree;
+
+ void* p;
+ std::type_info const* i;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The main utree (Universal Tree) class
+ // The utree is a hierarchical, dynamic type that can store:
+ // - a nil
+ // - a bool
+ // - an integer
+ // - a double
+ // - a string
+ // - a string range
+ // - a symbol (identifier)
+ // - binary data
+ // - a (doubly linked) list of utree
+ // - an iterator_range of list::iterator
+ // - a reference to a utree
+ // - a pointer or reference to any type
+ // - a function
+ //
+ // The utree has minimal memory footprint. The data structure size is
+ // 16 bytes on a 32-bit platform. Being a container of itself, it can
+ // represent tree structures.
+ ///////////////////////////////////////////////////////////////////////////
+ class utree
+ {
+ public:
+
+ typedef utree value_type;
+ typedef detail::list::node_iterator<utree> iterator;
+ typedef detail::list::node_iterator<utree const> const_iterator;
+ typedef detail::list::node_iterator<boost::reference_wrapper<utree> >
+ ref_iterator;
+ typedef utree& reference;
+ typedef utree const& const_reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+
+ typedef boost::iterator_range<iterator> range;
+ typedef boost::iterator_range<const_iterator> const_range;
+
+ utree();
+ utree(bool b);
+ utree(char c);
+ utree(unsigned int i);
+ utree(int i);
+ utree(double d);
+ utree(char const* str);
+ utree(char const* str, std::size_t len);
+ utree(std::string const& str);
+ utree(boost::reference_wrapper<utree> ref);
+ utree(any_ptr const& p);
+
+ template <typename Iter>
+ utree(boost::iterator_range<Iter> r);
+ utree(range r, shallow_tag);
+ utree(const_range r, shallow_tag);
+ utree(utf8_string_range const& str, shallow_tag);
+
+ template <typename F>
+ utree(stored_function<F> const& pf);
+
+ template <typename Base, utree_type::info type_>
+ utree(basic_string<Base, type_> const& str);
+
+ utree(utree const& other);
+ ~utree();
+
+ utree& operator=(utree const& other);
+ utree& operator=(bool b);
+ utree& operator=(unsigned int i);
+ utree& operator=(int i);
+ utree& operator=(double d);
+ utree& operator=(char const* s);
+ utree& operator=(std::string const& s);
+ utree& operator=(boost::reference_wrapper<utree> ref);
+
+ template <typename F>
+ utree& operator=(stored_function<F> const& pf);
+
+ template <typename Iter>
+ utree& operator=(boost::iterator_range<Iter> r);
+
+ template <typename Base, utree_type::info type_>
+ utree& operator=(basic_string<Base, type_> const& bin);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree const& x, F f);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree& x, F f);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree const& x, utree const& y, F f);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree& x, utree const& y, F f);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree const& x, utree& y, F f);
+
+ template <typename F>
+ typename F::result_type
+ static visit(utree& x, utree& y, F f);
+
+ template <typename T>
+ void push_back(T const& val);
+
+ template <typename T>
+ void push_front(T const& val);
+
+ template <typename T>
+ iterator insert(iterator pos, T const& x);
+
+ template <typename T>
+ void insert(iterator pos, std::size_t, T const& x);
+
+ template <typename Iter>
+ void insert(iterator pos, Iter first, Iter last);
+
+ template <typename Iter>
+ void assign(Iter first, Iter last);
+
+ void clear();
+ void pop_front();
+ void pop_back();
+ iterator erase(iterator pos);
+ iterator erase(iterator first, iterator last);
+
+ utree& front();
+ utree& back();
+ utree const& front() const;
+ utree const& back() const;
+
+ utree& operator[](std::size_t i);
+ utree const& operator[](std::size_t i) const;
+
+ void swap(utree& other);
+
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ ref_iterator ref_begin();
+ ref_iterator ref_end();
+
+ bool empty() const;
+ std::size_t size() const;
+
+ utree_type::info which() const;
+
+ template <typename T>
+ T get() const;
+
+ utree& deref();
+ utree const& deref() const;
+
+ short tag() const;
+ void tag(short tag);
+
+ utree eval(scope const& env) const;
+
+ private:
+
+ typedef utree_type type;
+
+ template <typename UTreeX, typename UTreeY>
+ friend struct detail::visit_impl;
+ friend struct detail::index_impl;
+
+ template <typename T>
+ friend struct detail::get_impl;
+
+ type::info get_type() const;
+ void set_type(type::info t);
+ void ensure_list_type();
+ void free();
+ void copy(utree const& other);
+
+ union
+ {
+ detail::fast_string s;
+ detail::list l;
+ detail::range r;
+ detail::string_range sr;
+ detail::void_ptr v;
+ bool b;
+ int i;
+ double d;
+ utree* p;
+ function_base* pf;
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The scope
+ ///////////////////////////////////////////////////////////////////////////
+ class scope : public boost::iterator_range<utree*>
+ {
+ public:
+
+ scope(utree* first = 0,
+ utree* last = 0,
+ scope const* parent = 0)
+ : boost::iterator_range<utree*>(first, last),
+ parent(parent),
+ depth(parent? parent->depth + 1 : 0)
+ {}
+
+ scope const* outer() const { return parent; }
+ int level() const { return depth; }
+
+ private:
+
+ scope const* parent;
+ int depth;
+ };
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif
Added: trunk/boost/spirit/home/support/utree/utree_traits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/spirit/home/support/utree/utree_traits.hpp 2010-11-30 14:48:27 EST (Tue, 30 Nov 2010)
@@ -0,0 +1,367 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM)
+#define BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM
+
+#include <boost/spirit/home/support/attributes.hpp>
+#include <boost/spirit/home/support/container.hpp>
+#include <boost/spirit/home/support/utree.hpp>
+#include <boost/spirit/home/karma/domain.hpp>
+
+#include <string>
+
+#include <boost/cstdint.hpp>
+#include <boost/variant.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/utility/enable_if.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost
+{
+ template <typename T>
+ inline T get(boost::spirit::utree const& x)
+ {
+ return x.get<T>();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace traits
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // this specialization tells Spirit.Qi to allow assignment to an utree from
+ // a variant
+ namespace detail
+ {
+ struct assign_to_utree_visitor : static_visitor<>
+ {
+ assign_to_utree_visitor(utree& ut) : ut_(ut) {}
+
+ template <typename T>
+ void operator()(T& val) const
+ {
+ ut_ = val;
+ }
+
+ utree& ut_;
+ };
+ }
+
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+ struct assign_to_attribute_from_value<utree, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+ {
+ static void
+ call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val, utree& attr)
+ {
+ apply_visitor(detail::assign_to_utree_visitor(attr), val);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // this specialization tells Spirit.Qi to allow assignment to an utree from
+ // a STL container
+ template <typename Container>
+ struct assign_to_attribute_from_value<utree, Container
+ , typename enable_if<is_container<Container> >::type>
+ {
+ static void
+ call(Container const& val, utree& attr)
+ {
+ attr = make_iterator_range(traits::begin(val), traits::end(val));
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // the specialization below tells Spirit to handle utree as if it
+ // where a 'real' variant (in the context of karma)
+ template <>
+ struct not_is_variant<utree, karma::domain>
+ : mpl::false_ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // this specialization tells Spirit how to extract the type of the value
+ // stored in the given utree node
+ template <>
+ struct variant_which<utree>
+ {
+ static int call(utree const& u) { return u.which(); }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The specializations below tell Spirit to verify whether an attribute
+ // type is compatible with a given variant type
+ template <>
+ struct compute_compatible_component_variant<
+ utree, iterator_range<utree::iterator> >
+ : mpl::true_
+ {
+ typedef iterator_range<utree::iterator> compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::list_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, iterator_range<utree::const_iterator> >
+ : mpl::true_
+ {
+ typedef iterator_range<utree::const_iterator> compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::list_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<utree, nil>
+ : mpl::true_
+ {
+ typedef nil compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::nil_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<utree, bool>
+ : mpl::true_
+ {
+ typedef bool compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::bool_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<utree, int>
+ : mpl::true_
+ {
+ typedef int compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::int_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<utree, double>
+ : mpl::true_
+ {
+ typedef double compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::double_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, utf8_string_range>
+ : mpl::true_
+ {
+ typedef utf8_string_range compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::string_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, utf8_string_type>
+ : mpl::true_
+ {
+ typedef utf8_string_type compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::string_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, utf8_symbol_range>
+ : mpl::true_
+ {
+ typedef utf8_symbol_range compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::symbol_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, utf8_symbol>
+ : mpl::true_
+ {
+ typedef utf8_symbol compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::symbol_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, binary_range>
+ : mpl::true_
+ {
+ typedef binary_range compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::binary_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, binary_string>
+ : mpl::true_
+ {
+ typedef binary_string compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::binary_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<utree, utree>
+ : mpl::true_
+ {
+ typedef utree compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d >= utree_type::nil_type &&
+ d <= utree_type::reference_type;
+ }
+ };
+
+ template <>
+ struct compute_compatible_component_variant<
+ utree, std::vector<utree> >
+ : mpl::true_
+ {
+ typedef utree compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d >= utree_type::nil_type &&
+ d <= utree_type::reference_type;
+ }
+ };
+
+ template <typename Sequence>
+ struct compute_compatible_component_variant<utree, Sequence
+ , mpl::false_
+ , typename enable_if<fusion::traits::is_sequence<Sequence> >::type>
+ : mpl::true_
+ {
+ typedef iterator_range<utree::const_iterator> compatible_type;
+
+ static bool is_compatible(int d)
+ {
+ return d == utree_type::list_type;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct symbols_lookup<utree, utf8_symbol>
+ {
+ typedef std::string type;
+
+ static type call(utree const& t)
+ {
+ utf8_symbol_range r = boost::get<utf8_symbol_range>(t);
+ return std::string(r.begin(), r.end());
+ }
+ };
+
+ template <>
+ struct symbols_lookup<utf8_symbol, utf8_symbol>
+ {
+ typedef std::string type;
+
+ static type call(utf8_symbol const& t)
+ {
+ return t;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct extract_from_attribute<utree, utf8_symbol>
+ {
+ typedef std::string type;
+
+ template <typename Context>
+ static type call(utree const& t, Context&)
+ {
+ utf8_symbol_range r = boost::get<utf8_symbol_range>(t);
+ return std::string(r.begin(), r.end());
+ }
+ };
+
+ template <>
+ struct extract_from_attribute<utree, utf8_string>
+ {
+ typedef std::string type;
+
+ template <typename Context>
+ static type call(utree const& t, Context&)
+ {
+ utf8_string_range r = boost::get<utf8_string_range>(t);
+ return std::string(r.begin(), r.end());
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_attribute<utree const, utf8_string, karma::domain>
+ {
+ typedef std::string type;
+
+ static type pre(utree const& t)
+ {
+ utf8_string_range r = boost::get<utf8_string_range>(t);
+ return std::string(r.begin(), r.end());
+ }
+ };
+
+ template <>
+ struct transform_attribute<utree const, utf8_symbol, karma::domain>
+ {
+ typedef std::string type;
+
+ static type pre(utree const& t)
+ {
+ utf8_symbol_range r = boost::get<utf8_symbol_range>(t);
+ return std::string(r.begin(), r.end());
+ }
+ };
+}}}
+
+#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk