//Variant data type class header //Updated 6 Aug 2012 //WARNING: Untested code! Use at your own risk. //Found a bug? Awesome! Let us know via: http://generaldevelopment.net/contact /*============================================================================== Copyright (c) 2011 General Development Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ==============================================================================*/ #pragma once #define VARIANT_NUL 0 //no value set. Empty. Equates to boolean false #define VARIANT_UND 1 //no value set. Undefined. Attempts to check value throw exception. #define VARIANT_STR 2 //string. Zero length strings equate to boolean false #define VARIANT_BOO 3 //boolean #define VARIANT_INT 4 //integer. 0 equates to boolean false #define VARIANT_FLO 5 //double precision floating point. 0. equates to boolean false. #include class Variant { private: char type; //1 byte tag field with type value defined by macros above. union { //each different type uses a different storage mechanism. //Heap allocation is used for data types larger than sizeof(void*), //to avoid enlarging the union for other types. bool b; //for type==T_BOO std::string* s; //for type==T_STR int i; //for type==T_INT (store int directly, it's only 4 bytes!) double* d; //for type==T_FLO } data; //TODO: on 64 bit systems pointers are 8 bytes, so T_FLO could be stored directly in the stack without enlarging //the union, conditional on 64 bit compilation. public: class Undefined {}; //exception class thrown on invalid operation //(e.g. division by a string) or invalid cast Variant(); Variant(const Variant&); //copy constructor Variant(const std::string&); Variant(const char&); Variant(const bool&); Variant(const int&); Variant(const double&); ~Variant(); inline char getType() const {return type;} //Casting is used to extract values from the variant. //A cast to a different type to that stored will perform limited //type conversion. //Casting a string to a numeric value returns string length. operator std::string() const throw(Undefined); operator bool() const throw(Undefined); operator int() const throw(Undefined); operator float() const throw(Undefined); operator double() const throw(Undefined); //to change type would be a matter of e.g. idt = (int)idt; size_t size(); //return string length or number of elements (0 if null, 1 otherwise) void clear(); //clear current value and assign null void setUnd(); //assign an 'undefined' state rather than a value. Variant& operator=(const Variant&); Variant& operator=(const std::string&); Variant& operator=(const char&); Variant& operator=(const bool&); Variant& operator=(const int&); Variant& operator=(const double&); Variant& operator+=(const Variant&); Variant& operator+=(const std::string&); Variant& operator+=(const char&); Variant& operator+=(const int&); Variant& operator+=(const double&); Variant& operator-=(const Variant&); Variant& operator-=(const int&); Variant& operator-=(const double&); Variant& operator*=(const Variant&); Variant& operator*=(const int&); Variant& operator*=(const double&); Variant& operator/=(const Variant&); Variant& operator/=(const int&); Variant& operator/=(const double&); Variant operator+(const Variant&) const; Variant operator+(const std::string&) const; Variant operator+(const char&) const; Variant operator+(const int&) const; Variant operator+(const double&) const; Variant operator-() const throw(Undefined); //unary (-) Variant operator-(const Variant&) const; Variant operator-(const int&) const; Variant operator-(const double&) const; Variant operator*(const Variant&) const; Variant operator*(const int&) const; Variant operator*(const double&) const; Variant operator/(const Variant&) const; Variant operator/(const int&) const; Variant operator/(const double&) const; int compare(const Variant&) const throw(Undefined); bool operator==(const Variant&) const throw(Undefined); bool operator!=(const Variant&) const throw(Undefined); bool operator>(const Variant&) const throw(Undefined); bool operator>=(const Variant&) const throw(Undefined); bool operator<(const Variant&) const throw(Undefined); bool operator<=(const Variant&) const throw(Undefined); };