cppvariant

cppvariant Mercurial Source Tree


Root/variant.h

#ifndef VARIANT_H
#define VARIANT_H
 
#include <iostream>
#include <exception>
#include <map>
#include <sstream>
#include <typeinfo>
#include <string>
 
using namespace std;
 
enum VAR_TYPES { INT, CHAR, DOUBLE, STRING, OBJECT, NONE };
 
//
// portable 64-bit integers
//
 
#if defined(_MSC_VER) || defined(__BORLANDC__)
   typedef __int64             large;
   typedef unsigned __int64    ularge;
#  define LLCONST(a) (a##i64)
#else
   typedef long long           large;
   typedef unsigned long long  ularge;
#  define LLCONST(a) (a##ll)
#endif
 
template<typename T>
T StrToType(std::string& str)
{
    std::istringstream ss(str);
    T ret;
    ss >> ret;
    return ret;
}
 
template <typename T>
std::string TypeToStr (const T & obj )
{
    std::ostringstream ss;
    ss << obj;
    return ss.str();
}
 
template <class T = void>
class variant
{
protected:
    VAR_TYPES _type;
    union {
        large i;
        char c;
        double d;
        string * s;
        T * v;
    } _container;
 
    void releaseObject()
    {
        if (this->_type == STRING)
            delete this->_container.s;
        if (this->_type == OBJECT && typeid(this->_container.v) != typeid(void*))
            delete this->_container.v;
 
        this->_type = NONE;
    }
    void setString(const string& s)
    {
        this->_container.s = new string(s);
        this->_type = STRING;
    }
 
    void setObject(const T* o)
    {
        this->_container.v = o;
        this->_type = OBJECT;
    }
     
public:
    ~variant() { releaseObject(); }
    variant() { type = NONE; };
 
    variant(int i)
    {
        this->_container.i = i;
        this->_type = INT;
    }
     
    variant(const string& s)
    {
        setString(s); 
    }
     
    variant(const char* s)
    {
        setString(s); 
    }
 
    variant(char c)
    {
        this->_container.c = c;
        this->_type = CHAR;
    }
 
    variant(double d)
    {
        this->_container.d = d;
        this->_type = DOUBLE;
    }
 
    variant(T * o)
    {
        this->_container.v = o;
        this->_type = OBJECT;
    }
     
    variant operator=(const string& s)
    {
        releaseObject();
        setString(s);
        return *this;
    }
     
    variant operator=(const char * s)
    {
        releaseObject();
        setString(s);
        return *this;
    }
     
    variant operator=(large i)
    {
        releaseObject();
        this->_type = INT;
        this->_container.i = i;
        return *this;
    }
 
    variant operator=(char c)
    {
        releaseObject();
        this->_type = CHAR;
        this->_container.c = c;
        return *this;
    }
 
    variant operator=(int i)
    {
        releaseObject();
        this->_type = INT;
        this->_container.i = i;
        return *this;
    }
 
    variant operator=(double d)
    {
        releaseObject();
        this->_type = DOUBLE;
        this->_container.d = d;
        return *this;
    }
 
    variant operator=(T * o)
    {
        releaseObject();
        this->_type = OBJECT;
        this->_container.v = o;
        return *this;
    }
 
    variant operator=(variant<> & v)
    {
        if (this != &v)
        {
            switch (v._type)
            {
                case STRING:
                    this->_container.s = v._container.s;
                    v._type = NONE;
                    return *this;
                    break;
                case INT:
                    this->_container.i = v._container.i;
                    return *this;
                    break;
                case DOUBLE:
                    this->_container.d = v._container.d;
                    return *this;
                    break;
                case CHAR:
                    this->_container.c = v._container.c;
                    return *this;
                    break;
                case OBJECT:
                    v._type = NONE;
                    this->_container.v = v._container.v;
                    return *this;
                    break;
            }
        }
        return *this;
    }
 
    bool operator>(const variant& v)
    {
        if (this->type == NONE || v.type == NONE)
            return true;
 
        if (this->type == STRING && v.type == STRING)
        {
            return *this->_container.s > *v._container.s;
        } else if (this->_type == INT && v._type == INT)
        {
            return this->_container.i > this->_container.i;
        } else {
            return true;
        }
    }
 
    bool operator<(const variant & v)
    {
        return !(*this > v);
    }
 
 
    operator large() const
    {
        switch (this->_type)
        {
            case INT:
                return this->_container.i;
                break;
            case STRING:
                return StrToType<int>(this->_container.s);
                break;
            case DOUBLE:
                return (large)this->_container.d;
                break;
            case CHAR:
                return (large)this->_container.c;
            case OBJECT:
                return (large)this->_container.v;
 
        }
        return NULL;
    }
 
    operator double() const
    {
        switch (this->_type)
        {
            case INT:
                return (double)this->_container.i;
                break;
            case STRING:
                return StrToType<double>(this->_container.s);
                break;
            case DOUBLE:
                return (double)this->_container.d;
                break;
            case CHAR:
                return (double)this->_container.c;
            case OBJECT:
                return (double)this->_container.v;
        }
        return NULL;
    }
 
    operator int() const
    {
        switch (this->_type)
        {
            case INT:
                return (int)this->_container.i;
                break;
            case STRING:
                return StrToType<int>(*this->_container.s);
                break;
            case DOUBLE:
                return (int)this->_container.d;
                break;
            case CHAR:
                return (int)this->_container.c;
            case OBJECT:
                return (int)this->_container.v;
 
        }
        return NULL;
    }
 
    operator char() const
    {
        switch (this->_type)
        {
            case INT:
                return (char)this->_container.i;
                break;
            case STRING:
                return StrToType<char>(*this->_container.s);
                break;
            case DOUBLE:
                return (char)this->_container.d;
                break;
            case CHAR:
                return this->_container.c;
            case OBJECT:
                return (char)this->_container.v;
 
        }
        return NULL;
    }
 
    operator string() const
    {
        switch (this->_type)
        {
            case INT:
                return TypeToStr<large>(this->_container.i);
                break;
            case STRING:
                return *this->_container.s;
                break;
            case DOUBLE:
                return TypeToStr<double>(this->_container.d);
                break;
            case CHAR:
                return TypeToStr<char>(this->_container.c);
                break;
            case OBJECT:
                return TypeToStr<T*>(this->_container.v);
                break;
 
        }
        return "";
    }
 
    variant & operator+(const variant & v)
    {
        *this += v;
        /*if (this->_type == v._type)
        {
            switch (this->_type)
            {
                case INT:
                    this->_container.i += v._container.i;
                    break;
                case DOUBLE:
                    this->_container.d += v._container.d;
                    break;
                case STRING:
                    *this->_container.s += *v._container.s;
                    break;
                case CHAR:
                    this->_container.c += v._container.c;
                    break;
                case OBJECT:
                    //*this->_container.v += *v._container.v;
                    //if (typeid(this->_container.v) != typeid(void*) && typeid(v._container.v) != typeid(void*))
                    //{
                    //  T a = *this->_container.v;
                    //}
                         
                    break;
            }
        }*/
        return *this;
    }
 
    variant & operator+(large i)
    {
        if (this->_type == INT)
        {
            this->_container.i += i;
        }
        else if (this->_type == STRING)
        {
            large i = StrToType(*this->_container.s) + i;
            releaseObject();
            this->_container.s = new string(TypeToStr<large>(i));
        }
        return *this;
    }
 
    variant & operator+(int i)
    {
        if (this->_type == INT)
        {
            this->_container.i += i;
        } else if (this->_type == STRING)
        {
            large i2 = StrToType<large>(*this->_container.s) + i;
            releaseObject();
            this->_type = STRING;
            this->_container.s = new string(TypeToStr<large>(i2));
        }
        return *this;
    }
 
    variant & operator+(const string & s)
    {
        if (this->_type == STRING)
            (*this->_container.s) += s;
        return *this;
    }
 
    variant & operator+(char c)
    {
        if (this->_type == CHAR)
        {
            this->_container.c += c;
        } else if (this->_type == STRING)
        {
            (*this->_container.s) += c;
        }
        return *this;
    }
 
    variant & operator+(double d)
    {
        if (this->_type == DOUBLE)
            this->_container.d += d;
        return *this;
    }
 
    variant & operator+(T * obj)
    {
        if (this->_type == OBJECT)
            (*this->_container.o) += *obj;
        return *this;
    }
 
    /*variant & operator+=(void * o)
    {
        return *this;
    }*/
 
    variant & operator+=(const variant & v)
    {
        //if (this->_type == v._type)
        //{
        switch (this->_type)
        {
            case INT:
                switch (v._type)
                {
                    case INT:
                        this->_container.i += v._container.i;
                        break;
                    case CHAR:
                        this->_container.i += (large)v._container.c;
                        break;
                    case DOUBLE:
                        this->_container.i += (large)v._container.d;
                        break;
                    case STRING:
                        this->_container.i += StrToType<large>(*v._container.s);
                        break;
                    case OBJECT:
                        break;
                     
                }
                break;
            case DOUBLE:
                switch (v._type)
                {
                    case INT:
                        this->_container.d += (double)v._container.i;
                        break;
                    case CHAR:
                        this->_container.d += (double)v._container.c;
                        break;
                    case DOUBLE:
                        this->_container.d += v._container.d;
                        break;
                    case STRING:
                        this->_container.d += StrToType<double>(*v._container.s);
                        break;
                    case OBJECT:
                        break;
                     
                }
                break;
            case STRING:
                switch (v._type)
                {
                    case INT:
                        *this->_container.s += TypeToStr<large>(v._container.i);
                        break;
                    case CHAR:
                        *this->_container.s += v._container.c;
                        break;
                    case DOUBLE:
                        *this->_container.s += TypeToStr<double>(v._container.d);
                        break;
                    case STRING:
                        *this->_container.s += *v._container.s;
                        break;
                    case OBJECT:
                        break;
                     
                }
                break;
            case CHAR:
                switch (v._type)
                {
                    case INT:
                        this->_container.c += TypeToStr<large>(v._container.i)[0];
                        break;
                    case CHAR:
                        this->_container.c += v._container.c;
                        break;
                    case DOUBLE:
                        this->_container.c += TypeToStr<double>(v._container.d)[0];
                        break;
                    case STRING:
                        this->_container.c += (*v._container.s)[0];
                        break;
                    case OBJECT:
                        break;
                     
                }
                break;
            case OBJECT:
                //this->_container.v += v._container.v;
                break;
        }
        //}
        return *this;
    }
 
    variant & operator+=(large i)
    {
        if (this->_type == INT)
        {
            this->_container.i += i;
        }
        else if (this->_type == STRING)
        {
            large i = StrToType(*this->_container.s) + i;
            releaseObject();
            this->_container.s = new string(TypeToStr<large>(i));
        }
        return *this;
    }
 
    variant & operator+=(int i)
    {
        if (this->_type == INT)
        {
            this->_container.i += i;
        } else if (this->_type == STRING)
        {
            large i2 = StrToType<large>(*this->_container.s) + i;
            releaseObject();
            this->_type = STRING;
            this->_container.s = new string(TypeToStr<large>(i2));
        }
        return *this;
    }
 
    variant & operator+=(const string & s)
    {
        if (this->_type == STRING)
        {
            (*this->_container.s) += s;
        } else if (this->_type == INT) {
            large i = StrToType<large>(const_cast<string>(s));
            this->_container.i += i;
        }
        return *this;
    }
 
    variant & operator+=(const char * s)
    {
        if (this->_type == STRING)
        {
            (*this->_container.s) += s;
        } else if (this->_type == INT)
        {
            string tmp = string(s);
            large i = StrToType<large>(tmp);
            this->_container.i += i;
        }
        return *this;
    }
 
    variant & operator+=(char c)
    {
        if (this->_type == CHAR)
        {
            this->_container.c += c;
        } else if (this->_type == STRING)
        {
            (*this->_container.s) += c;
        }
        return *this;
    }
 
    variant & operator+=(double d)
    {
        if (this->_type == DOUBLE)
            this->_container.d += d;
        return *this;
    }
 
    variant & operator+=(T * obj)
    {
        if (this->_type == OBJECT)
            (*this->_container.o) += *obj;
        return *this;
    }
 
    friend ostream & operator<<(const ostream & o, variant<T> & v);
    friend istream & operator>>(istream & i, variant<T> & v);
 
    friend ostream & operator<<(const ostream & o, variant<> & v);
    friend istream & operator>>(istream & i, variant<> & v);
 
    operator T*() const
    {
        return this->_container.v;
    }
 
    operator T() const
    {
        return *this->_container.v;
    }
 
    VAR_TYPES type() { return this->_type; }
};
 
ostream & operator<<(ostream& o, variant<> & v)
{
    o << (string)v;
    return o;
}
 
istream & operator>>(istream & i, variant<> & v)
{
    string * x = new string();
    i >> *x;
    v._type = STRING;
    v._container.s = x;
    return i;
}
 
template <class T>
ostream & operator<<(ostream& o, variant<T> & v)
{
    o << (string)v;
    return o;
}
 
template <class T>
istream & operator>>(istream & i, variant<T> & v)
{
    string * x = new string();
    i >> *x;
    v._type = STRING;
    v._container.s = x;
    return i;
}
 
#endif
Source at commit 39ba50dd77ee created 11 years 9 months ago.
By Nathan Adams, Adding source and sample

Archive Download this file

Branches

Tags

Page rendered in 0.76883s using 11 queries.