From e99509abde688315ac7a82d764b352e2e3312e61 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 25 Sep 2009 22:14:26 +0000 Subject: New Bu::Variant class. Store anything in it, get it out again, find out it's type. It's really just that easy. More info, docs, and tweaks to come. --- src/variant.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/variant.h (limited to 'src/variant.h') diff --git a/src/variant.h b/src/variant.h new file mode 100644 index 0000000..889df88 --- /dev/null +++ b/src/variant.h @@ -0,0 +1,184 @@ +#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; + } + + 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(); + 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 + void set( const t &val ) + { + if( pCore && pCore->getType() != typeid(t) ) + { + delete pCore; + pCore = NULL; + } + pCore = new VariantType(); + (*dynamic_cast *>(pCore)) = val; + } + + 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 -- cgit v1.2.3