diff options
author | Kevin Smith <git@kismith.co.uk> | 2013-01-12 18:41:34 (GMT) |
---|---|---|
committer | Swift Review <review@swift.im> | 2013-01-13 10:36:26 (GMT) |
commit | f3bc816af1b0d61452de973963e453bf3b3f95a2 (patch) | |
tree | e895f8afa3580e6cff6f5ad2017d45bf147a17c2 /3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp | |
parent | 188fc285c6555eadd3c9d50ab8a94adcade78d89 (diff) | |
download | swift-f3bc816af1b0d61452de973963e453bf3b3f95a2.zip swift-f3bc816af1b0d61452de973963e453bf3b3f95a2.tar.bz2 |
Adding in the spirit Boost stuff
Change-Id: I4f127ce61667243b64081b0aa309028d5077045f
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp b/3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp new file mode 100644 index 0000000..4332fa2 --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/support/detail/hold_any.hpp @@ -0,0 +1,459 @@ +/*============================================================================= + Copyright (c) 2007-2011 Hartmut Kaiser + Copyright (c) Christopher Diggins 2005 + Copyright (c) Pablo Aguilar 2005 + Copyright (c) Kevlin Henney 2001 + + 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) + + The class boost::spirit::hold_any is built based on the any class + published here: http://www.codeproject.com/cpp/dynamic_typing.asp. It adds + support for std streaming operator<<() and operator>>(). +==============================================================================*/ +#if !defined(BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM) +#define BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/is_reference.hpp> +#include <boost/throw_exception.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/assert.hpp> +#include <boost/detail/sp_typeinfo.hpp> + +#include <stdexcept> +#include <typeinfo> +#include <algorithm> +#include <iosfwd> + +/////////////////////////////////////////////////////////////////////////////// +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4100) // 'x': unreferenced formal parameter +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit +{ + struct bad_any_cast + : std::bad_cast + { + bad_any_cast(boost::detail::sp_typeinfo const& src, boost::detail::sp_typeinfo const& dest) + : from(src.name()), to(dest.name()) + {} + + virtual const char* what() const throw() { return "bad any cast"; } + + const char* from; + const char* to; + }; + + namespace detail + { + // function pointer table + template <typename Char> + struct fxn_ptr_table + { + boost::detail::sp_typeinfo const& (*get_type)(); + void (*static_delete)(void**); + void (*destruct)(void**); + void (*clone)(void* const*, void**); + void (*move)(void* const*, void**); + std::basic_istream<Char>& (*stream_in)(std::basic_istream<Char>&, void**); + std::basic_ostream<Char>& (*stream_out)(std::basic_ostream<Char>&, void* const*); + }; + + // static functions for small value-types + template <typename Small> + struct fxns; + + template <> + struct fxns<mpl::true_> + { + template<typename T, typename Char> + struct type + { + static boost::detail::sp_typeinfo const& get_type() + { + return BOOST_SP_TYPEID(T); + } + static void static_delete(void** x) + { + reinterpret_cast<T*>(x)->~T(); + } + static void destruct(void** x) + { + reinterpret_cast<T*>(x)->~T(); + } + static void clone(void* const* src, void** dest) + { + new (dest) T(*reinterpret_cast<T const*>(src)); + } + static void move(void* const* src, void** dest) + { + reinterpret_cast<T*>(dest)->~T(); + *reinterpret_cast<T*>(dest) = + *reinterpret_cast<T const*>(src); + } + static std::basic_istream<Char>& + stream_in (std::basic_istream<Char>& i, void** obj) + { + i >> *reinterpret_cast<T*>(obj); + return i; + } + static std::basic_ostream<Char>& + stream_out(std::basic_ostream<Char>& o, void* const* obj) + { + o << *reinterpret_cast<T const*>(obj); + return o; + } + }; + }; + + // static functions for big value-types (bigger than a void*) + template <> + struct fxns<mpl::false_> + { + template<typename T, typename Char> + struct type + { + static boost::detail::sp_typeinfo const& get_type() + { + return BOOST_SP_TYPEID(T); + } + static void static_delete(void** x) + { + // destruct and free memory + delete (*reinterpret_cast<T**>(x)); + } + static void destruct(void** x) + { + // destruct only, we'll reuse memory + (*reinterpret_cast<T**>(x))->~T(); + } + static void clone(void* const* src, void** dest) + { + *dest = new T(**reinterpret_cast<T* const*>(src)); + } + static void move(void* const* src, void** dest) + { + (*reinterpret_cast<T**>(dest))->~T(); + **reinterpret_cast<T**>(dest) = + **reinterpret_cast<T* const*>(src); + } + static std::basic_istream<Char>& + stream_in(std::basic_istream<Char>& i, void** obj) + { + i >> **reinterpret_cast<T**>(obj); + return i; + } + static std::basic_ostream<Char>& + stream_out(std::basic_ostream<Char>& o, void* const* obj) + { + o << **reinterpret_cast<T* const*>(obj); + return o; + } + }; + }; + + template <typename T> + struct get_table + { + typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small; + + template <typename Char> + static fxn_ptr_table<Char>* get() + { + static fxn_ptr_table<Char> static_table = + { + fxns<is_small>::template type<T, Char>::get_type, + fxns<is_small>::template type<T, Char>::static_delete, + fxns<is_small>::template type<T, Char>::destruct, + fxns<is_small>::template type<T, Char>::clone, + fxns<is_small>::template type<T, Char>::move, + fxns<is_small>::template type<T, Char>::stream_in, + fxns<is_small>::template type<T, Char>::stream_out + }; + return &static_table; + } + }; + + /////////////////////////////////////////////////////////////////////// + struct empty {}; + + template <typename Char> + inline std::basic_istream<Char>& + operator>> (std::basic_istream<Char>& i, empty&) + { + // If this assertion fires you tried to insert from a std istream + // into an empty hold_any instance. This simply can't work, because + // there is no way to figure out what type to extract from the + // stream. + // The only way to make this work is to assign an arbitrary + // value of the required type to the hold_any instance you want to + // stream to. This assignment has to be executed before the actual + // call to the operator>>(). + BOOST_ASSERT(false && + "Tried to insert from a std istream into an empty " + "hold_any instance"); + return i; + } + + template <typename Char> + inline std::basic_ostream<Char>& + operator<< (std::basic_ostream<Char>& o, empty const&) + { + return o; + } + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char> + class basic_hold_any + { + public: + // constructors + template <typename T> + explicit basic_hold_any(T const& x) + : table(spirit::detail::get_table<T>::template get<Char>()), object(0) + { + if (spirit::detail::get_table<T>::is_small::value) + new (&object) T(x); + else + object = new T(x); + } + + basic_hold_any() + : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()), + object(0) + { + } + + basic_hold_any(basic_hold_any const& x) + : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()), + object(0) + { + assign(x); + } + + ~basic_hold_any() + { + table->static_delete(&object); + } + + // assignment + basic_hold_any& assign(basic_hold_any const& x) + { + if (&x != this) { + // are we copying between the same type? + if (table == x.table) { + // if so, we can avoid reallocation + table->move(&x.object, &object); + } + else { + reset(); + x.table->clone(&x.object, &object); + table = x.table; + } + } + return *this; + } + + template <typename T> + basic_hold_any& assign(T const& x) + { + // are we copying between the same type? + spirit::detail::fxn_ptr_table<Char>* x_table = + spirit::detail::get_table<T>::template get<Char>(); + if (table == x_table) { + // if so, we can avoid deallocating and re-use memory + table->destruct(&object); // first destruct the old content + if (spirit::detail::get_table<T>::is_small::value) { + // create copy on-top of object pointer itself + new (&object) T(x); + } + else { + // create copy on-top of old version + new (object) T(x); + } + } + else { + if (spirit::detail::get_table<T>::is_small::value) { + // create copy on-top of object pointer itself + table->destruct(&object); // first destruct the old content + new (&object) T(x); + } + else { + reset(); // first delete the old content + object = new T(x); + } + table = x_table; // update table pointer + } + return *this; + } + + // assignment operator + template <typename T> + basic_hold_any& operator=(T const& x) + { + return assign(x); + } + + // utility functions + basic_hold_any& swap(basic_hold_any& x) + { + std::swap(table, x.table); + std::swap(object, x.object); + return *this; + } + + boost::detail::sp_typeinfo const& type() const + { + return table->get_type(); + } + + template <typename T> + T const& cast() const + { + if (type() != BOOST_SP_TYPEID(T)) + throw bad_any_cast(type(), BOOST_SP_TYPEID(T)); + + return spirit::detail::get_table<T>::is_small::value ? + *reinterpret_cast<T const*>(&object) : + *reinterpret_cast<T const*>(object); + } + +// implicit casting is disabled by default for compatibility with boost::any +#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING + // automatic casting operator + template <typename T> + operator T const& () const { return cast<T>(); } +#endif // implicit casting + + bool empty() const + { + return table == spirit::detail::get_table<spirit::detail::empty>::template get<Char>(); + } + + void reset() + { + if (!empty()) + { + table->static_delete(&object); + table = spirit::detail::get_table<spirit::detail::empty>::template get<Char>(); + object = 0; + } + } + + // these functions have been added in the assumption that the embedded + // type has a corresponding operator defined, which is completely safe + // because spirit::hold_any is used only in contexts where these operators + // do exist + template <typename Char_> + friend inline std::basic_istream<Char_>& + operator>> (std::basic_istream<Char_>& i, basic_hold_any<Char_>& obj) + { + return obj.table->stream_in(i, &obj.object); + } + + template <typename Char_> + friend inline std::basic_ostream<Char_>& + operator<< (std::basic_ostream<Char_>& o, basic_hold_any<Char_> const& obj) + { + return obj.table->stream_out(o, &obj.object); + } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + private: // types + template <typename T, typename Char_> + friend T* any_cast(basic_hold_any<Char_> *); +#else + public: // types (public so any_cast can be non-friend) +#endif + // fields + spirit::detail::fxn_ptr_table<Char>* table; + void* object; + }; + + // boost::any-like casting + template <typename T, typename Char> + inline T* any_cast (basic_hold_any<Char>* operand) + { + if (operand && operand->type() == BOOST_SP_TYPEID(T)) { + return spirit::detail::get_table<T>::is_small::value ? + reinterpret_cast<T*>(&operand->object) : + reinterpret_cast<T*>(operand->object); + } + return 0; + } + + template <typename T, typename Char> + inline T const* any_cast(basic_hold_any<Char> const* operand) + { + return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand)); + } + + template <typename T, typename Char> + T any_cast(basic_hold_any<Char>& operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // If 'nonref' is still reference type, it means the user has not + // specialized 'remove_reference'. + + // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro + // to generate specialization of remove_reference for your class + // See type traits library documentation for details + BOOST_STATIC_ASSERT(!is_reference<nonref>::value); +#endif + + nonref* result = any_cast<nonref>(&operand); + if(!result) + boost::throw_exception(bad_any_cast(operand.type(), BOOST_SP_TYPEID(T))); + return *result; + } + + template <typename T, typename Char> + T const& any_cast(basic_hold_any<Char> const& operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // The comment in the above version of 'any_cast' explains when this + // assert is fired and what to do. + BOOST_STATIC_ASSERT(!is_reference<nonref>::value); +#endif + + return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand)); + } + + /////////////////////////////////////////////////////////////////////////////// + // backwards compatibility + typedef basic_hold_any<char> hold_any; + typedef basic_hold_any<wchar_t> whold_any; + + namespace traits + { + template <typename T> + struct is_hold_any : mpl::false_ {}; + + template <typename Char> + struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {}; + } + +}} // namespace boost::spirit + +/////////////////////////////////////////////////////////////////////////////// +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +#endif |