From 469bbcf0701e1eb8a6670c23145b0da87357e178 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 25 Mar 2012 20:00:08 +0000 Subject: Code is all reorganized. We're about ready to release. I should write up a little explenation of the arrangement. --- src/stable/variant.h | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 src/stable/variant.h (limited to 'src/stable/variant.h') diff --git a/src/stable/variant.h b/src/stable/variant.h new file mode 100644 index 0000000..45e3339 --- /dev/null +++ b/src/stable/variant.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2007-2011 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 + +#ifndef NULL +#define NULL (0L) +#endif + +#include "bu/exceptionbase.h" + +namespace Bu +{ + class String; + class Formatter; + class Variant; + /** @cond DEVEL */ + template class VariantType; + + class VariantTypeRoot + { + public: + VariantTypeRoot(); + virtual ~VariantTypeRoot(); + + virtual const std::type_info &getType() const=0; + virtual VariantTypeRoot *clone() const=0; + virtual void format( Bu::Formatter &f ) 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 void format( Formatter &f ) const + { + f << data; + } + + 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; + }; + /** @endcond */ + + /** + * Store any data type and access it safely. Variant gives you a way to + * pass arbitrary data types around without having to worry about what + * type a variable is. It allows code to be easily extended and to manage + * data without having to know what type it is ahead of time. + * + * Because of the generic method that this class was implemented it may seem + * to have some drawbacks compared to other Variant classes you may have + * seen, however it is fairly easy to get it to do just about anything you + * may need. It is also very low overhead. On most compilers the class + * itself has only 3 words of overhead + the size of the variable you store + * in it. And, since many parts of it are templatized they can often be + * optimized quite a bit. + */ + class Variant + { + friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); + public: + Variant(); + Variant( const Variant &v ); + Variant( const char *t ); + template + Variant( const t &v ) : + pCore( new VariantType() ) + { + (*dynamic_cast *>(pCore)) = v; + } + virtual ~Variant(); + + Bu::String toString() const; + bool isSet() 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.getData; + }*/ + + Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); +}; + +#endif -- cgit v1.2.3