/* * Copyright (C) 2007-2010 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #ifndef BU_VARIANT_H #define BU_VARIANT_H #include #include #include #include namespace Bu { class Formatter; class Variant; template class VariantType; class VariantTypeRoot { public: VariantTypeRoot(); virtual ~VariantTypeRoot(); virtual Bu::FString toString() const=0; virtual const std::type_info &getType() const=0; virtual VariantTypeRoot *clone() const=0; }; template class VariantType : public VariantTypeRoot { friend class Variant; private: VariantType() { } VariantType( const t &d ) : data( d ) { } VariantType( const VariantType &vt ) : data( vt.data ) { } virtual ~VariantType() { } public: t &getData() { return data; } const t &getData() const { return data; } virtual Bu::FString toString() const { MemBuf mb; Formatter f( mb ); f << data; return mb.getString(); } virtual const std::type_info &getType() const { return typeid( data ); } VariantType operator=( const t &rhs ) { data = rhs; return *this; } virtual VariantTypeRoot *clone() const { return new VariantType( *this ); } private: t data; }; class Variant { public: Variant(); Variant( const Variant &v ); virtual ~Variant(); bool isSet(); Bu::FString toString() const; const std::type_info &getType() const; Variant &operator=( const Variant &rhs ); template Variant &operator=( const t &rhs ) { if( pCore ) // && pCore->getType() != typeid(t) ) { delete pCore; pCore = NULL; } pCore = new VariantType(); (*dynamic_cast *>(pCore)) = rhs; return *this; } template t &get() { if( !pCore ) { throw Bu::ExceptionBase("No data!"); } if( pCore->getType() != typeid(t) ) { throw Bu::ExceptionBase("Invalid type conversion."); } return dynamic_cast *>(pCore)->getData(); } template t &get() const { if( !pCore ) { throw Bu::ExceptionBase("No data!"); } if( pCore->getType() != typeid(t) ) { throw Bu::ExceptionBase("Invalid type conversion."); } return dynamic_cast *>(pCore)->getData(); } template void set( const t &val ) { if( pCore && pCore->getType() != typeid(t) ) { delete pCore; pCore = NULL; } pCore = new VariantType(); (*dynamic_cast *>(pCore)) = val; } template bool isType() const { return pCore->getType() == typeid(t); } template operator t() { if( !pCore ) { throw Bu::ExceptionBase("No data!"); } if( pCore->getType() != typeid(t) ) { throw Bu::ExceptionBase("Invalid type conversion."); } return dynamic_cast *>(pCore)->getData(); } template operator t() const { if( !pCore ) { throw Bu::ExceptionBase("No data!"); } if( pCore->getType() != typeid(t) ) { throw Bu::ExceptionBase("Invalid type conversion."); } return dynamic_cast *>(pCore)->getData(); } private: VariantTypeRoot *pCore; }; template Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType &vt ) { return f << vt.toString(); } Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); template<> Bu::FString VariantType::toString() const; template<> Bu::FString VariantType::toString() const; }; #endif