From 15b30fe20b401d079c2b3c6a8e77eee827813de3 Mon Sep 17 00:00:00 2001 From: Travis CI Date: Tue, 17 Mar 2015 22:54:19 +0000 Subject: Gem 096ed6ef786b7a9d6e11a437ff8526619c89a1fd osx/x86_64 built 'master:096ed6ef786b7a9d6e11a437ff8526619c89a1fd' for osx/x86_64 --- Gem/develop/include/Gem/Utils/any.h | 318 ++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 Gem/develop/include/Gem/Utils/any.h (limited to 'Gem/develop/include/Gem/Utils/any.h') diff --git a/Gem/develop/include/Gem/Utils/any.h b/Gem/develop/include/Gem/Utils/any.h new file mode 100644 index 0000000..fc66b46 --- /dev/null +++ b/Gem/develop/include/Gem/Utils/any.h @@ -0,0 +1,318 @@ +/* + * (C) Copyright Christopher Diggins 2005 + * (C) Copyright Pablo Aguilar 2005 + * (C) Copyright Kevlin Henney 2001 + * + * Copyright (C) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at + * downloaded this code from http://www.codeproject.com/KB/cpp/dynamic_typing.aspx + * changed namespace/defines "cdiggins" to something "gem" + * + * 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) + */ + +#ifndef GEM_ANY_HPP +#define GEM_ANY_HPP + +#include "Gem/ExportDef.h" + +#ifdef _MSC_VER +# pragma warning( push ) +# pragma warning( disable: 4275 ) +#endif + +#include +#include +#include +#include + + +namespace gem +{ + struct GEM_EXTERN bad_any_cast : std::bad_cast { + bad_any_cast(const std::type_info& src, const std::type_info& dest) + : result(std::string("bad cast (")+src.name() + "->" + dest.name()+")") + { } + virtual ~bad_any_cast(void) throw() + { } + virtual const char* what(void) const throw() { + return result.c_str(); + } + const std::string result; + }; + + namespace any_detail { + // function pointer table + + struct fxn_ptr_table { + const std::type_info& (*get_type)(void); + void (*static_delete)(void**); + void (*clone)(void* const*, void**); + void (*move)(void* const*,void**); + }; + + // static functions for small value-types + + template + struct fxns + { + template + struct type { + static const std::type_info& get_type(void) { + const std::type_info&res=typeid(T); + // the following is a dummy use of the type_info struct + // to make the template engine work properly on OSX/10.9 + static std::string _ = res.name(); + return res; + } + static void static_delete(void** x) { + reinterpret_cast(x)->~T(); + } + static void clone(void* const* src, void** dest) { + new(dest) T(*reinterpret_cast(src)); + } + static void move(void* const* src, void** dest) { + reinterpret_cast(dest)->~T(); + *reinterpret_cast(dest) = *reinterpret_cast(src); + } + }; + }; + + // static functions for big value-types (bigger than a void*) + + template<> + struct fxns + { + template + struct type { + static const std::type_info& get_type(void) { + const std::type_info&res=typeid(T); + return res; + } + static void static_delete(void** x) { + delete(*reinterpret_cast(x)); + } + static void clone(void* const* src, void** dest) { + *dest = new T(**reinterpret_cast(src)); + } + static void move(void* const* src, void** dest) { + (*reinterpret_cast(dest))->~T(); + **reinterpret_cast(dest) = **reinterpret_cast(src); + } + }; + }; + + template + struct get_table + { + static const bool is_small = sizeof(T) <= sizeof(void*); + + static fxn_ptr_table* get(void) + { + static fxn_ptr_table static_table = { + fxns::template type::get_type + , fxns::template type::static_delete + , fxns::template type::clone + , fxns::template type::move + }; + return &static_table; + } + }; + + struct empty { + }; + } // namespace any_detail + + + struct GEM_EXTERN any + { + // structors + + template + any(const T& x) : table(NULL), object(NULL) { + table = any_detail::get_table::get(); + if (sizeof(T) <= sizeof(void*)) { + new(&object) T(x); + } + else { + object = new T(x); + } + } + + any(void) : table(NULL), object(NULL) { + table = any_detail::get_table::get(); + object = NULL; + } + + any(const any& x) : table(NULL), object(NULL) { + table = any_detail::get_table::get(); + assign(x); + } + + virtual ~any(void) { + table->static_delete(&object); + } + + // assignment + + any& assign(const any& x) { + // 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 + any& assign(const T& x) + { + // are we copying between the same type? + + any_detail::fxn_ptr_table* x_table = any_detail::get_table::get(); + if (table == x_table) { + // if so, we can avoid deallocating and resuse memory + + if (sizeof(T) <= sizeof(void*)) { + // 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 { + reset(); + if (sizeof(T) <= sizeof(void*)) { + // create copy on-top of object pointer itself + + new(&object) T(x); + // update table pointer + + table = x_table; + } + else { + object = new T(x); + table = x_table; + } + } + return *this; + } + + // assignment operator + + template + any& operator=(T const& x) { + return assign(x); + } + any& operator=(const any& x) { + return assign(x); + } + + // utility functions + + any& swap(any& x) { + std::swap(table, x.table); + std::swap(object, x.object); + return *this; + } + + const std::type_info& get_type(void) const { + return table->get_type(); + } + + template + const T& cast(void) const { + if (!compatible()) { + throw bad_any_cast(get_type(), typeid(T)); + } + if (sizeof(T) <= sizeof(void*)) { + return *reinterpret_cast(&object); + } + else { + return *reinterpret_cast(object); + } + } + + /// Returns true if the two types are the same. + bool compatible(const any& x) const { + return get_type() == x.get_type(); + } + /// Returns true if the two types are the same. + template + bool compatible() const { + return (get_type() == typeid(T)); + } + + // implicit casting is disabled by default + + #ifdef ANY_IMPLICIT_CASTING + // automatic casting operator + + template + operator T(void) const { + return cast(); + } + #endif // implicit casting + + + bool empty(void) const { + return table == any_detail::get_table::get(); + } + + void reset(void) + { + if (empty()) return; + table->static_delete(&object); + table = any_detail::get_table::get(); + object = NULL; + } + + // fields + + any_detail::fxn_ptr_table* table; + void* object; + }; + + // boost::any-like casting + + template + T* any_cast(any* this_) { + if (this_->get_type() != typeid(T)) { + throw bad_any_cast(this_->get_type(), typeid(T)); + } + if (sizeof(T) <= sizeof(void*)) { + return reinterpret_cast(&this_->object); + } + else { + return reinterpret_cast(this_->object); + } + } + + template + T const* any_cast(any const* this_) { + return any_cast(const_cast(this_)); + } + + template + T const& any_cast(any const& this_){ + return *any_cast(const_cast(&this_)); + } +} + +#ifdef _MSC_VER +# pragma warning( pop ) +#endif + +#endif // GEM_ANY_HPP -- cgit v1.2.1