X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2Ftags%2F0.04.12%2FETL%2F_value.h;fp=ETL%2Ftags%2F0.04.12%2FETL%2F_value.h;h=a52567e1ac52d4f74f9b72911b3d4685ab31ff53;hb=d953ebc0f88bcc2533ed89a2800283f529a57620;hp=0000000000000000000000000000000000000000;hpb=aadb96df9b7cc6aaad86946cb009f2ee76398349;p=synfig.git diff --git a/ETL/tags/0.04.12/ETL/_value.h b/ETL/tags/0.04.12/ETL/_value.h new file mode 100644 index 0000000..a52567e --- /dev/null +++ b/ETL/tags/0.04.12/ETL/_value.h @@ -0,0 +1,237 @@ +/* ======================================================================== +** Extended Template and Library +** Abstraction for a Generic Value Type +** $Id$ +** +** Copyright (c) 2002 Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** === N O T E S =========================================================== +** +** This is an internal header file, included by other ETL headers. +** You should not attempt to use it directly. +** +** ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __ETL_VALUE_H +#define __ETL_VALUE_H + +/* === H E A D E R S ======================================================= */ +#include +#include +#include + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +/*! \note This class may be specialized to support binary compatibility + for desired objects (e.g. point3,vector3,float[3]). + However it MUST be declared within scope that you are using the + values.... + + \warning If you specialize this class for something that isn't binary + compatible, then your values could easily report belonging to + the wrong types. +*/ +template < typename T > +class value_store_type +{ +public: + typedef T value_type; +}; + +_ETL_BEGIN_NAMESPACE + +/*! \class value _value.h ETL/value + \brief Abstraction of the concept of a generic value + + Modified from ideas for the boost::any type. Added binary compatibility + structure +*/ +class value +{ + struct contentholder + { + virtual ~contentholder() {} + virtual contentholder *clone() const = 0; + virtual const std::type_info &type() const = 0; + }; + + contentholder *content; + +public: //constructor interface + value() + :content(0) + { + } + + value(const value &v) + :content( v.content ? v.content->clone() : 0 ) + { + } + + /* Copies the object passed to it + */ + template < typename T > + value(const T &v) + :content( new holder< typename value_store_type::value_type > + (reinterpret_cast::value_type &>(v)) ) + { + } + +public: //modifier interface + + value & swap(value & rhs) + { + std::swap(content, rhs.content); + return *this; + } + + template + value & operator=(const ValueType & rhs) + { + value(rhs).swap(*this); + return *this; + } + + value & operator=(const value & rhs) + { + value(rhs).swap(*this); + return *this; + } + +public: //query interface + + bool empty() const + { + return content == 0; + } + + const std::type_info & type() const + { + return content ? content->type() : typeid(void); + } + +private: //implementation interface + + template < typename T > + class holder : public contentholder + { + public: //representation + T obj; + + public: //constructor interface + + holder(const T &o) + :obj(o) + { + } + + holder(const holder &h) + :obj(h.obj) + { + } + + public: //accessor interface + virtual contentholder *clone() const + { + return new holder(*this); + } + + virtual const std::type_info &type() const + { + return typeid(T); + } + + public: //allocation interface + void *operator new(unsigned int size) + { + assert(size == sizeof(holder)); + + //use pool allocation at some point + return malloc(size); + } + + void operator delete(void *p) + { + assert(p); + //use pool allocation at some point + return free(p); + } + }; + + template < typename ValueType > + friend ValueType *value_cast(value *v); +}; + +/*! Is thrown for bad value_casts (when using a reference...) +*/ +class bad_value_cast : public std::bad_cast +{ +public: + virtual const char * what() const throw() + { + return "etl::bad_value_cast: " "failed conversion using boost::value_cast"; + } +}; + +/*! Returns a pointer to the desired value type if the value_type and the internal + binary format agree (mediated by using the value_store_type class), otherwise + it returns 0. + + \see value_store_type +*/ +template < typename ValueType > +ValueType *value_cast(value *v) +{ + assert(v); + + return ( typeid(typename value_store_type::value_type) == v->type() ) + ? &static_cast *>(v->content)->obj + : 0; +} + +/*! Same as above except tweaked to allow const cast (possibly for purposes involving + type agreement... if const impacts a typeid call I do not know...) +*/ +template < typename ValueType > +const ValueType * value_cast(const value *v) +{ + return value_cast(const_cast(v)); +} + +/*! Extract a copy of the internal object and will throw a bad_value_cast exception + if the types do not agree. + + \note I'm not sure why boost::any didn't use a reference here... there must be a reason... + + \see bad_value_cast +*/ +template < typename ValueType > +ValueType value_cast(const value &v) +{ + const ValueType * result = value_cast(&v); + if(!result) + throw bad_value_cast(); + return *result; +} + +_ETL_END_NAMESPACE + +/* === E N D =============================================================== */ + +#endif