Variant var("-18.99");//Here a variant is created and assigned to the char array value "-18.99"
std::cout << var.toStdString()<< std::endl;//Here the char array value will be converted to a std string
std::cout << var.toInt64()<< std::endl;//Here the char array value will be converted to a int64/long long
//since a long long can't hold decimals the .99 will be lost during the conversion
std::cout << var.toDouble() << std::endl;//The char array will here be converted to a double, no data will be
//lost during this conversion since a double can hold decimal values.
std::cout << var.toULong() << std::endl;//When converted to a unsigned long alla data will be lost
//and zero will be returned since unsigned values does not hold negative values
std::cout << var.canFullyConvertTo(Variant::Int64) << std::endl;//Here it checks
//if no data will be lost during a conversion to a Int64(long long) it will return false since the decimals
//in the char array will be lost
#ifndef VARIANT_H
#define VARIANT_H
#include <sstream>
#include <string.h>
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <list>
typedef long long int64;//A long long is the same as a int64
class Variant
{
//A class meant to make it easier to convert between basic types
//and classes and various functions that fits in that category
public:
Variant();//The user don't assign the variable in the creation of the class
Variant(const int Val);//The user assigns the class to a integer
Variant(const float Val);//The user assigns the class to a float
Variant(const double Val);//The user assigns the class to a double
Variant(const bool Val);//The user assings the class to a boolean
Variant(const char Val);//The user assigns the class to a char
Variant(const char * Val);//The user assigns the class to a char array/char pointer
Variant(const std::string Val);//The user assigns the class to a std::string
Variant(const unsigned long Val);//The user assigns the class to a unsigned long by default
Variant(const int64);//The user assigns the class to a long long/int64
Variant(const std::vector<Variant> val);//The user assigns the class to a vector
Variant(const std::list<Variant> val);//The user assigns the class to list
Variant(const std::map<const char*,Variant> val);//Assigns the variant to a map
void operator = (const Variant Val);//Set the variant to another variant
bool operator == (const Variant val);//Check if the current variant equals to another
//Variant by the value and the type
bool operator != (const Variant val);//If the Variants don't have the same value and or type return true
//else false
enum Types
{
//A enum to keep track of all the types and classes
//the variant class supports convertion between
Undefined = -1,
Int,
Float,
Double,
Int64,
ULong,
Bool,
Char,
CharArray,
stdString,
Vector,
List,
Map
};
int type();//Return the current type of the current Variant class
//The conversion functions
int toInt();//Try to return the Variant as a integer
float toFloat();//Try to return the Variant as a float
double toDouble();//Try to return the Variant as a double
bool toBool();//Try to return the Variant as a bool
char toChar();//Try to return the Variant as a char
char * toCharArray();//Try to return the Variant as a char array
unsigned long toULong();//Try to return the variant as a unsigned long
std::string toStdString();//Try to return the variant as a std::string
int64 toInt64();//Try to return the variant as a int64
long long toLongLong();//Try to return the variant as a long,long / 64 bit integer
std::vector<Variant> toVector();//Try to return the variant as vector
std::list<Variant> toList();//Try to return the current variant as a list
std::map<const char*, Variant> toMap();//Return the current variant as a map if the current type is map
static int toInt(Variant val);
static float toFloat(Variant val);
static double toDouble(Variant val);
static unsigned long toULong( Variant val);
static int64 toInt64( Variant val);
long long toLongLong(Variant val);
static bool toBool(Variant val);
static char toChar(Variant val);
static char * toCharArray( Variant val);
static std::string toStdString(Variant val);
static std::vector<Variant> toVector(Variant val);
static std::list<Variant> toList(Variant val);
std::map<const char*,Variant> toMap(Variant val);
static bool isTrue(Variant Var);//Check if a variant is true
bool canCastTo(const Types type);//Wheater the variant can be cast/always be converted to a specefied type
bool cast(int & val);//Cast the current variant to the integer the user passed
bool cast(float & val);//Cast the current variant to the float the user passed
bool cast(double &val);//Cast the current variant to the double the user passed
bool cast(bool &val);//Cast the current variant to the bool the user passed
bool cast(char &val);//Cast the current variant to the char the user passed
bool cast(unsigned long & val);//Cast the current variant to the unsigned long the user passed
bool cast(int64 & val);//Cast the current variant to the int64 the user passed
bool canFullyConvertTo(const Types type);//Wheater the Variant can be converted to a type without losing any data
//if it cans it returns true else it returns false
int indexOf(Variant value,const unsigned int begin);//Find the first index of a certain value inside the variant
int lastIndexOf(Variant value,const unsigned int begin);//Find the last reference of a certain value inside the variant
bool contains(const Variant val);//Check if the Variant contains another value or not
bool matchingValues(const Variant val);//If the type matches and
//the value of the both Variants matches return true
//else false
bool matchingTypes(const Variant val);//If the current Variant and the variant passed
//has the same type it will return true
//else it will return false
bool isUndefined();//If the current variant is undefined
//return true else false
bool isContainer();//Wheater the current variant is a container or not
enum Error
{
Error_NoError = 0,
Error_UndefinedType,
Error_UnknownError
};
void clear();//Clear the current variant
void setProperty(const char * keyName,const Variant value);//Set or add a new property to the current variant
Variant property(const char * key);//Return the variant at the key, if it exist
bool setValue(const Variant val, const Types type);//Set the value of the current variant and set type of the current variant
private:
Types currentType;//To keep track of the current type
void setCurrentType(const Types type);//Update the current type
struct Value
{
//A struct/containter to keep track to store
//the current value
int iVal;//To hold integer values
float fVal;//To hold floating point values
double dVal;//To hold double values
unsigned long ulVal;//To hold unsigned long values
int64 i64Val;//To hold the int64 values
bool bVal;//To hold boolean values
char cVal;//To hold char values
char * strVal;//To hold char array values/ cstring values
std::string stdStrVal;//Hold the stdstirng
std::vector<Variant> vecVal;//To hold vectors
std::list<Variant> listVal;//To hold lists
std::map<const char *,Variant> mapVal;//To hold maps
};
Value currentValue;//To keep track of the current value
std::map<const char *,const Variant> properties;//The map that will store all the properties of the current Variant
bool isIntegerData();//Check if the current variant only contains data that can be converted to a integer
bool isDecimalData();//Check if the current variant onlu contains data that can be converted to a decimal type such as float or double
//can fully be converted to a number
bool vecCompare(std::vector<Variant>,std::vector<Variant>);//Check if two vectors are the same
bool listCompare(std::list<Variant>, std::list<Variant>);//Check if two lists are the same
bool mapCompare(std::map<const char*,Variant>,std::map<const char*,Variant>);
std::list<Variant> vecToList(std::vector<Variant> Vec);//Return a vector as list
std::vector<Variant> listToVec(std::list<Variant> list);//Return the list as a vector
};
#endif // VARIANT_H
#include "variant.h"
Variant::Variant()
{
setCurrentType(Undefined);//The current type is undefined
//since the user did not pass a type as the parameters
}
void Variant::setCurrentType(const Variant::Types type)
{
currentType = type;//Set the current type to keep track of the current type
}
Variant::Variant(const int Val)
{
//The user assigns the class to a integer
setCurrentType(Int);//Set the current type to int
currentValue.iVal = Val;//Set the integer value to the integer the user passed
}
Variant::Variant(const float Val)
{
//The user assigns the class to a float
setCurrentType(Float);//Set the current type to float
currentValue.fVal = Val;//Set the floating point value to the float value the user passed
}
Variant::Variant(const double Val)
{
//The user assigns the class to a double
setCurrentType(Double);//Set the current type to a double
currentValue.dVal = Val;//Set the double to the double the user passed
}
Variant::Variant(const bool Val)
{
//The user assings the class to a boolean
setCurrentType(Bool);//Set the current type to bool
currentValue.bVal = Val;//Set the boolean value to boolean the user passed
}
Variant::Variant(const char Val)
{
//The user assigns the class to a char
setCurrentType(Char);//Set the current type to char
currentValue.cVal = Val;//Set the char value to the value the user passed
}
Variant::Variant(const char * Val)
{
//The user assigns the class to a char array/char pointer
setCurrentType(CharArray);//Set the current type to a char array
currentValue.strVal = (char*)Val;//Set the string value to the string value the user passed
}
Variant::Variant(const std::string Val)
{
//The user assigns the current variant to a std::string
setCurrentType(stdString);//Set the current type to std::string to keep track of the current type
currentValue.stdStrVal = Val;//Set the current value to the value passed by the user
}
Variant::Variant(const unsigned long Val)
{
//The user assigns the current Variant to a unsigned long
setCurrentType(ULong);//To keep track of the current type
currentValue.ulVal = Val;//Set the current value to the value of the ULong passed by the user
}
Variant::Variant(const int64 Val)
{
//The user assigns the Variant to a int64/long long
setCurrentType(Int64);
currentValue.i64Val = Val;//Set the int 64
}
Variant::Variant(const std::vector<Variant> val)
{
setCurrentType(Vector);//Set the current type to vector
currentValue.vecVal = val;//Set the vector
}
Variant::Variant(const std::list<Variant> val)
{
setCurrentType(List);
currentValue.listVal = val;
}
Variant::Variant(const std::map<const char *, Variant> val)
{
setCurrentType(Map);
currentValue.mapVal = val;
}
void Variant::operator =(const Variant Var)
{
this->currentType = Var.currentType;//Set the currentType to the type of the variant the user passed
this->currentValue = Var.currentValue;//Set the currentValue to the value of the variant the user passed
//Since the Variant can handle all the basic types
//there is no need to create a new = operator for each type, when they all can be passed
//via the variant in this function
}
int Variant::type()
{
//Return the current type of the current value
//so the user can check for different types
return (int)currentType;
}
int Variant::toInt()
{
//Try to return the Variant as a integer
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
return this->currentValue.iVal;//If the Variant is a integer just return it
break;
case Float:
return (int)this->currentValue.fVal;//If the variant is a float type it to a integer and return it
break;
case Double:
return (int)this->currentValue.dVal;//If the variant is a double type it to a integer and return
break;
case ULong:
return (int)this->currentValue.ulVal;//Return the integer version of the unsigned long
break;
case Int64:
return (int)this->currentValue.i64Val;//Return the integer version of the int64
case Bool:
return (int)this->currentValue.bVal;//Type the boolean to a intger and return
break;
case Char:
{
std::stringstream stream;//Create a stringstream to hold the char value
stream << this->currentValue.cVal;//Set the stringstream to the char value
int Re = 0;//Create the return integer and set it to 0 to avoid undefined behaviour
stream >> Re;//Input the stored char to the integer
return Re;//Return the integer
}
break;
case CharArray:
{
std::stringstream stream;//Create a stringstream to hold the char array
stream << this->currentValue.strVal;//Set the stringstream to the char array
int Re = 0;//Create the return integer and assign it to 0 to avoid undefiend behaviours
stream >> Re;//Input the char array tp the integer
return Re;//Return the integer
}
case stdString:
{
std::stringstream stream;
stream << this->currentValue.stdStrVal;
int Re = 0;//Create the return integer
stream >> Re;//Input the string value to the integer
return Re;//Return the integer
}
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
break;
case Undefined:
{
return 0;//Return -1 for failed
}
}
}
return 0;//Return -1 for failed
}
float Variant::toFloat()
{
//Try to return the Variant as a float
if(isDecimalData() || isIntegerData())
{
switch(this->currentType)
{
case Int:
return (float)this->currentValue.iVal;//Type the integer to a float and return it
break;
case Float:
return (float)this->currentValue.fVal;//Return the float value
break;
case Double:
return (float)this->currentValue.dVal;//Type the double to a float and return it
break;
case ULong:
return (float)this->currentValue.ulVal;
break;
case Int64:
return (float)this->currentValue.i64Val;
break;
case Bool:
return (float)this->currentValue.bVal;//Type the boolean to a float ad return it
break;
case Char:
{
std::stringstream stream;//Create a stringstream for the char
stream << this->currentValue.cVal;//Set the stringstream to the char
float Re = 0.0;//Create the return float
stream >> Re;//Assign the float to the value of the stream
return Re;//Return the float
}
break;
case CharArray:
{
std::stringstream stream;//Create a stringstream for the char array
stream << this->currentValue.strVal;//Assisgn the stream to the char array
float Re = 0.0;//Create the return float
stream >> Re;//Assign the float the value of the stream
return Re;//Return the float value
}
break;
case stdString:
{
std::stringstream stream;//Create a stringstream for the char array
stream << this->currentValue.stdStrVal;//Assisgn the stream to the std::string
float Re = 0.0;//Create the return float
stream >> Re;//Assign the float the value of the stream
return Re;//Return the float value
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
{
return (float)0;//Return -1 for error
}
break;
}
}
return (float)0;
}
bool Variant::toBool()
{
return isTrue(this->toCharArray());//If the variant is true it will return true else false
}
double Variant::toDouble()
{
if(isDecimalData() || isIntegerData())
{
switch(this->currentType)
{
case Int:
return (double)this->currentValue.iVal;//Type the integer to a double and return it
break;
case Float:
return (double)this->currentValue.fVal;//Type the float to a double and return it
break;
case Double:
return this->currentValue.dVal;//Return the double vba
break;
case ULong:
return (double)this->currentValue.ulVal;
break;
case Int64:
return (double)this->currentValue.i64Val;
case Bool:
return (double)this->currentValue.bVal;//Type the boolean to a double and return it
break;
case Char:
{
std::stringstream stream;//Create the stream that will store the char
stream << this->currentValue.cVal;//Assign the stream to the char
double Re = 0.0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the double value
}
break;
case CharArray:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.strVal;//Assign the stream to the char array
double Re = 0.0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the double value
}
break;
case stdString:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.stdStrVal;//Assign the stream to the std::string
double Re = 0.0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the double value
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
{
return 0;//Return 0 failed
}
break;
}
}
return 0;//Return 0 for failed
}
unsigned long Variant::toULong()
{
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
return (unsigned long)this->currentValue.iVal;
break;
case Float:
return (unsigned long)this->currentValue.fVal;
break;
case Double:
return (unsigned long)this->currentValue.dVal;
break;
case ULong:
return this->currentValue.ulVal;
break;
case Int64:
return (unsigned long)this->currentValue.i64Val;
case Bool:
return (unsigned long)this->currentValue.bVal;
break;
case Char:
{
std::stringstream stream;//Create the stream that will store the char
stream << this->currentValue.cVal;//Assign the stream to the char
unsigned long Re = 0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the ULong value
}
break;
case CharArray:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.strVal;//Assign the stream to the char array
unsigned long Re = 0;//Create the return ulong
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the ulong
}
break;
case stdString:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.stdStrVal;//Assign the stream to the std::string
unsigned long Re = 0;//Create the return ulong
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the ulong
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
return 0;//Failed
break;
}
}
return 0;//Failed
}
int64 Variant::toInt64()
{
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
{
return (int64)this->currentValue.iVal;
}
break;
case Float:
{
return (int64)this->currentValue.fVal;
}
break;
case Double:
{
return (int64)this->currentValue.dVal;
}
break;
case ULong:
{
return (int64)this->currentValue.ulVal;
}
break;
case Int64:
{
return this->currentValue.i64Val;
}
break;
case Bool:
{
return (int64)this->currentValue.bVal;
}
break;
case Char:
{
std::stringstream stream;
stream << this->currentValue.cVal;
int64 re = 0;
stream >> re;
return re;
}
break;
case CharArray:
{
std::stringstream stream;
stream << this->currentValue.strVal;
int64 re = 0;
stream >> re;
return re;
}
break;
case stdString:
{
std::stringstream stream;
stream << this->currentValue.stdStrVal;
int64 re = 0;
stream >> re;
return re;
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
return 0;
break;
}
}
return 0;
}
long long Variant::toLongLong()
{
return this->toInt64();
}
char * Variant::toCharArray()
{
//Try to return the variant as a char array
switch(this->currentType)
{
case Int:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.iVal;//Assign the stream to the integer value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Float:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.fVal;//Assign the stream to the floating point value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Double:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.dVal;//Assign the stream to the double value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case ULong:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.ulVal;//Assign the stream to the unsigned long value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Int64:
{
std::stringstream stream;
stream << this->currentValue.i64Val;
const char * re;
re = stream.str().c_str();
return (char*)re;
}
case Bool:
{
if(this->currentValue.bVal == true)
return (char*)"1";//Return one for true
return (char*)"0";//Return zero for false
}
break;
case Char:
{
std::stringstream stream;//Create the stream to hold the char
stream << this->currentValue.cVal;//Set the stream to the char
return (char*)stream.str().c_str();//Return the stream as a char array
}
break;
case CharArray:
return (char*)this->currentValue.strVal;//Just return the char array
break;
case stdString:
return (char*)this->currentValue.stdStrVal.c_str();//Return the char array version of the std::string
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
return (char*)"";//Return nothing as for failed
}
return (char*)"";//Return nothing as for failed
}
bool Variant::isTrue(Variant Var)
{
//Check if the passed variant is true or false
const char * str = (const char*)Var.toCharArray();//Convert the variant to a cstring
int strsize = strlen((const char*)str);//Get the lenght of the string
int TCount = 0;//Too keep track of the number of true chars in the string
int FCount = 0;//Too keep track of the number of false chars in the string
for(int i = 0; i < strsize;++i)
{
//Loop through the entire string
//And check each char if it is true or not
if(str[i] == '0')
++FCount;//A new false char was found,increase the number of false chars
else
++TCount;//Else it is a true char increase the number of true chars in the string
}
if(TCount > FCount)
return true;//The string contained more true chars than false chars
else if(FCount > TCount)
return false;//The string contained more false chars than true chars
//If it has gotten to this point TCount and FCount is the same value
//then base boolean of the first char in the string
if(str[0] == '0')
return false;//The first char is false so then return false
return true;//Else the first char is true so return true
}
char Variant::toChar()
{
//Try to convert the current Variant to a char
switch(this->currentType)
{
case Int:
{
std::stringstream stream;//Create the stringstream that will hold tje integer value
stream << this->currentValue.iVal;//Assign the stream to the integer value
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Float:
{
std::stringstream stream;//Create the stringstream that will hold the float valie
stream << this->currentValue.fVal;//Assign the stream to the float value
char Re = '0';//Create the return char
stream >> Re;///Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Double:
{
std::stringstream stream;//Create the stringstream that will hold the double
stream << this->currentValue.dVal;//Assign the stream to the double
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case ULong:
{
std::stringstream stream;//Create the stringstream that will hold the double
stream << this->currentValue.ulVal;//Assign the stream to the unsigned long value
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Int64:
{
std::stringstream stream;
stream << this->currentValue.i64Val;
char Re = '0';
stream >> Re;
return Re;
}
break;
case Bool:
{
if(this->currentValue.bVal == true)
return (char)'1';//Return true
return (char)'0';//Return false
}
break;
case Char:
return this->currentValue.cVal;//Just return the char value
break;
case CharArray:
{
if(strlen((const char*)this->currentValue.strVal) > 0)
return (char)this->currentValue.strVal[0];//Return the first char of the string
else
{
return (char)'0';
}
}
break;
case stdString:
{
if(this->currentValue.stdStrVal.size() > 0)
return this->currentValue.stdStrVal.at(0);//Return the first char
else
return (char)'0';
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
{
return '0';//Return 0 for failed
}
}
return (char)'0';//Return 0 for failed
}
std::string Variant::toStdString()
{
switch(this->currentType)
{
case Int:
{
std::stringstream stream;
stream << this->currentValue.iVal;
return stream.str();
}
break;
case Float:
{
std::stringstream stream;
stream << this->currentValue.fVal;
return stream.str();
}
break;
case Double:
{
std::stringstream stream;
stream << this->currentValue.dVal;
return stream.str();
}
break;
case ULong:
{
std::stringstream stream;
stream << this->currentValue.ulVal;
return stream.str();
}
break;
case Int64:
{
std::stringstream stream;
stream << this->currentValue.i64Val;
return stream.str();
}
break;
case Bool:
{
if(this->currentValue.bVal == true)
return "1";
return "0";
}
break;
case Char:
{
std::stringstream stream;
stream << this->currentValue.cVal;
return stream.str();
}
break;
case CharArray:
{
return (std::string)this->currentValue.strVal;
}
break;
case stdString:
{
return this->currentValue.stdStrVal;
}
break;
case Vector:
return 0;
break;
case List:
return 0;
break;
case Map:
return 0;
break;
case Undefined:
{
return (std::string)"0";
}
break;
default:
return (std::string)"0";
break;
}
return "0";
}
std::vector<Variant> Variant::toVector()
{
if(this->currentType == Vector)
return this->currentValue.vecVal;
else if(this->currentType == List)
{
return listToVec(currentValue.listVal);
}
return std::vector<Variant>();//Return a undefined vector
}
std::list<Variant> Variant::toList()
{
if(currentType == List)
return currentValue.listVal;
else if(currentType == Vector)
{
return vecToList(currentValue.vecVal);//Return the vector as list
}
return std::list<Variant>();//Return a undefined list
}
std::map<const char*,Variant> Variant::toMap()
{
//Maps can only be converted to maps
if(currentType == Map)
return currentValue.mapVal;//Return the map if the current type is map
return std::map<const char*, Variant>();//Return a empty map
}
int Variant::toInt(Variant val)
{
return val.toInt();
}
float Variant::toFloat(Variant val)
{
return val.toFloat();
}
double Variant::toDouble(Variant val)
{
return val.toDouble();
}
unsigned long Variant::toULong(Variant val)
{
return val.toULong();
}
int64 Variant::toInt64(Variant val)
{
return val.toInt64();
}
long long Variant::toLongLong(Variant val)
{
return val.toInt64();
}
bool Variant::toBool(Variant val)
{
return val.toBool();
}
char Variant::toChar(Variant val)
{
return val.toChar();
}
char * Variant::toCharArray(Variant val)
{
return val.toCharArray();
}
std::string Variant::toStdString(Variant val)
{
return val.toStdString();
}
std::vector<Variant> Variant::toVector(Variant val)
{
return val.toVector();
}
std::list<Variant> Variant::toList(Variant val)
{
return val.toList();
}
std::map<const char*, Variant> Variant::toMap(Variant val)
{
return val.toMap();
}
void Variant::clear()
{
//Clear all the Variants values
currentValue.iVal = 0;//Set the integer value to zero
currentValue.fVal = 0;//Set the float value to zero
currentValue.dVal = 0;//Set the double value to zero
currentValue.cVal = (char)(int)0;//Set the char value to null
currentValue.ulVal = 0;
currentValue.i64Val = 0;
currentValue.stdStrVal = "";
currentValue.strVal = (char*)"";//Set the string value to empty
currentValue.bVal = false;//Set the boolean value to false
currentValue.vecVal = std::vector<Variant>();
currentValue.listVal = std::list<Variant>();
currentValue.mapVal = std::map<const char *, Variant>();
setCurrentType(Undefined);//Set the current type to undefined
//no type has been set by the user yet
}
bool Variant::canCastTo(const Variant::Types type)
{
//Check if the current variant can be casted
//to another type
if(this->currentType == Char || this->currentType == Int
|| this->currentType == Float || this->currentType == Double || this->currentType == Bool || this->currentType == ULong || this->currentType == Int64)
{
//If the current Variant is any of these types
return (type == Char || type == Int || type == Float || type == Double || type == Bool || type == ULong || type == Int64);
}
//The remaning type is the char array which can't be casted with anything
return false;//therefore return false for not can be casted with the type the user passed
}
bool Variant::cast(int & val)
{
switch(this->currentType)
{
case Int:
val = (int)this->currentValue.iVal;
return true;
break;
case Float:
val = (int)this->currentValue.fVal;
return true;
break;
case Double:
val = (int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (int)this->currentValue.bVal;
return true;
break;
case Char:
val = (int)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(int64 & val)
{
//Cast the current variant to a 64 bit integer
switch(this->currentType)
{
case Int:
val = (int64)this->currentValue.iVal;
return true;
break;
case Float:
val = (int64)this->currentValue.fVal;
return true;
break;
case Double:
val = (int64)this->currentValue.dVal;
return true;
break;
case ULong:
val = (int64)this->currentValue.ulVal;
return true;
break;
case Int64:
val = this->currentValue.i64Val;
return true;
break;
case Char:
val = (int64)this->currentValue.cVal;
return true;
break;
case Bool:
val = (int64)this->currentValue.bVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(unsigned long & val)
{
switch(this->currentType)
{
case Int:
val = (unsigned long)this->currentValue.iVal;
return true;
break;
case Float:
val = (unsigned long)this->currentValue.fVal;
return true;
break;
case Double:
val = (unsigned long)this->currentValue.dVal;
return true;
break;
case ULong:
val = (unsigned long)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (unsigned long)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (unsigned long)this->currentValue.bVal;
return true;
break;
case Char:
val = (unsigned long)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(float & val)
{
switch(this->currentType)
{
case Int:
val = (float)this->currentValue.iVal;
return true;
break;
case Float:
val = (float)this->currentValue.fVal;
return true;
break;
case Double:
val = (float)this->currentValue.dVal;
return true;
break;
case ULong:
val = (float)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (float)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (float)this->currentValue.bVal;
return true;
break;
case Char:
val = (float)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(double & val)
{
switch(this->currentType)
{
case Int:
val = (double)this->currentValue.iVal;
return true;
break;
case Float:
val = (double)this->currentValue.fVal;
return true;
break;
case Double:
val = (double)this->currentValue.dVal;
return true;
break;
case ULong:
val = (double)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (double)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (double)this->currentValue.bVal;
return true;
break;
case Char:
val = (double)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(char & val)
{
switch(this->currentType)
{
case Int:
val = (char)this->currentValue.iVal;
return true;
break;
case Float:
val = (char)(int)this->currentValue.fVal;
return true;
break;
case Double:
val = (char)(int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (char)(int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (char)(int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (char)(int)this->currentValue.bVal;
return true;
break;
case Char:
val = (char)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(bool &val)
{
switch(this->currentType)
{
case Int:
val = (bool)this->currentValue.iVal;
return true;
break;
case Float:
val = (bool)(int)this->currentValue.fVal;
return true;
break;
case Double:
val = (bool)(int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (bool)(int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (bool)(int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (bool)this->currentValue.bVal;
return true;
break;
case Char:
val = (bool)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case stdString:
return false;
break;
case Vector:
return false;
break;
case List:
return false;
break;
case Map:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::canFullyConvertTo(const Types T)
{
// //A function meant for checking if the Variant can
// //be converted to a type without losing any data
//Since no data should ever be lost during a to std::string conversion
//it can be used to check if the value somehow changed
Variant check;//Create a variant to keep track of the value
if(check.setValue(this->toStdString(),T))
{//Set the value to the current to std::string since no data should be lost
//and convert the string to whatever type the user entered
return (check.toStdString() == this->toStdString());
//If the two strings is the same no data was lost during the conversion and
//true will be returned for can fully convert to
//If the string are not the same data was lost and false will be returned
}
return false;//Return false for the value could not be set
}
int Variant::indexOf(Variant value, const unsigned int begin)
{
//Find the first index of a ceratin value inside
//this current variant from the begin posistion
//if no one is found or it failed is someway return -1
if(!isContainer())
{
const std::string str = toStdString();//The current Variant as a std::string
const std::string refstr = value.toStdString();//The reference value as a std::string
if(begin < str.size() && begin >= 0)//Just a basic overflow and underflow check
{
for(int i = 0; i + begin + refstr.size() <= str.size();++i)
{
//Loop through all the different possible substrings, that matches the lenght of the reference string
if(str.substr(begin + i,refstr.size()) == refstr)
return i;//The start posistion of the reference string was found from the begin point
}
}
}
return -1;//Return -1 for not found
}
int Variant::lastIndexOf(Variant value, const unsigned int begin)
{
//Find the flst index of a certain value inside the Variant
//begining from the begin posistion
//To avoid overflows and underflows
if(!isContainer())
{
const std::string str = toStdString();//The string representatiob of the Variant
const std::string refstr = value.toStdString();//The string representation of the value to find
if(begin < str.size() && begin >= 0)//Just basic overflow and underflow check
{
unsigned int lastIndex = -1;//The integer that will keep track of the last found index
//if non is found the value will stay at -1 and will return false
for(int i = 0; i + begin + refstr.size() <= str.size();++i)
{
//Loop through all the different possible substrings, that matches the lenght of the reference string
if(str.substr(begin + i,refstr.size()) == refstr)
lastIndex = i;//The start posistion of the reference string was found from the begin point
}
return lastIndex;//If the value was found somewhere inside the Variant a value bigger than -1 will be returned
//else -1 will be returned for failed
}
}
return -1;//The user entered a value to either to small or to big, and -1 is returned for failed
}
bool Variant::contains(const Variant val)
{
//If the current variant contains the value
//of val true will be returned, otherwise false
if(this->indexOf(val,0) > -1)
return true;//The value was found inside the variant
return false;//It was not found inside the variant
}
bool Variant::setValue(Variant val, const Types T)
{
//Set the Variant value without changing the T
setCurrentType(T);
if(currentType == T)
{//If the current type actually was set
switch(T)
{
case Int:
this->currentValue.iVal = val.toInt();
return true;
break;
case Float:
this->currentValue.fVal = val.toFloat();
return true;
break;
case Double:
this->currentValue.dVal = val.toDouble();
return true;
break;
case ULong:
this->currentValue.ulVal = val.toULong();
return true;
break;
case Int64:
this->currentValue.i64Val = val.toInt64();
return true;
break;
case Bool:
this->currentValue.bVal = val.toBool();
return true;
break;
case Char:
this->currentValue.cVal = val.toChar();
return true;
break;
case CharArray:
this->currentValue.strVal = val.toCharArray();
return true;
break;
case stdString:
this->currentValue.stdStrVal = val.toStdString();
return true;
break;
case Vector:
this->currentValue.vecVal = val.toVector();
return true;
break;
case List:
this->currentValue.listVal = val.toList();
return true;
break;
case Map:
this->currentValue.mapVal = val.toMap();
return true;
break;
case Undefined:
this->clear();//Clear the current variant/undefine it
return true;
break;
default:
return false;
break;
}
}
return false;//Return false for failed
}
bool Variant::operator ==(const Variant val)
{
return matchingValues(val);//Check if the values and the types are the same
}
bool Variant::matchingTypes(const Variant val)
{
return (this->currentType == val.currentType);
}
bool Variant::matchingValues(Variant val)
{
if(matchingTypes(val))
{
//The types must be the same for the value to match
switch(this->currentType)
{
case Int:
{
return (this->currentValue.iVal == val.currentValue.iVal);
}
break;
case Float:
{
return (this->currentValue.fVal == val.currentValue.fVal);
}
break;
case Double:
{
return (this->currentValue.dVal == val.currentValue.dVal);
}
break;
case ULong:
{
return (this->currentValue.ulVal == val.currentValue.ulVal);
}
break;
case Int64:
{
return (this->currentValue.i64Val == val.currentValue.i64Val);
}
break;
case Bool:
{
return (this->currentValue.bVal == val.currentValue.bVal);
}
break;
case Char:
{
return (this->currentValue.cVal == val.currentValue.cVal);
}
break;
case CharArray:
{
return (this->currentValue.strVal == val.currentValue.strVal);
}
break;
case stdString:
{
return (this->currentValue.stdStrVal == val.currentValue.stdStrVal);
}
break;
case Vector:
{
return vecCompare(this->currentValue.vecVal,val.currentValue.vecVal);
}
break;
case List:
{
return listCompare(this->currentValue.listVal,val.currentValue.listVal);
}
break;
case Map:
{
return mapCompare(this->currentValue.mapVal,val.currentValue.mapVal);
}
break;
case Undefined:
return true;//Both the variants are undefined
break;
}
}
return false;
}
bool Variant::operator !=(const Variant val)
{
//Check if the current variant and the passed variant
//don't have the same value and or type
return (!matchingValues(val));
}
bool Variant::isUndefined()
{
return (currentType == Undefined);
}
void Variant::setProperty(const char * keyName,const Variant value)
{
//Add a new property with the keyName as the key and the Variant as the value
properties.insert(std::pair<const char*,const Variant>(keyName,value));
}
Variant Variant::property(const char *key)
{
//Return the value of the key from key of it
Variant re;//Create a undefined variant
std::map<const char*,const Variant>::const_iterator iter = properties.find(key);
if(iter != properties.end())
{
//If the key was found
//the matching value can be returned
re = iter->second;//Set the variant to the value of the key
}
return re;//If the key and value was not found a undefined variant will be returned
}
bool Variant::isContainer()
{
return (currentType == Vector || currentType == List || currentType == Map);
}
bool Variant::vecCompare(std::vector<Variant> v1, std::vector<Variant> v2)
{
return (v1.size() == v2.size()) && std::equal(v1.begin(),v1.end(),v2.begin());
}
bool Variant::listCompare(std::list<Variant> L1, std::list<Variant> L2)
{
return (L1.size() == L2.size()) && std::equal(L1.begin(),L1.end(),L2.begin());
}
bool Variant::mapCompare(std::map<const char *, Variant> m1, std::map<const char *, Variant> m2)
{
if(m1.size() != m2.size())
return false;
std::map<const char*, Variant>::iterator iter1 = m1.begin(), iter2 = m2.begin();
while(iter1 != m1.end() && iter2 != m2.end())
{
if(iter1->first != iter2->first)return false;
if(iter1->second != iter2->second)return false;
++iter1;
++iter2;
}
return true;//The both maps are the same
}
std::list<Variant> Variant::vecToList(std::vector<Variant> Vec)
{
//Convert a vector to a list
return std::list<Variant>(Vec.begin(),Vec.end());//Fill the list with the data fof the vector
}
std::vector<Variant> Variant::listToVec(std::list<Variant> List)
{
//Convert a List to vector
return std::vector<Variant>(List.begin(),List.end());//Fill the vector with the data of the list
}
bool Variant::isIntegerData()
{
//Check if the current Variant only contains data that can be converted to a integer type
//Only for private usage since it might
if(isContainer())
return false;//If the Variant has the type of a container it can't be converted to any integer type
if(currentType == Int || currentType == ULong || currentType == Int64)
return true;
const std::string check = toStdString();//Convert the current variant to a std::string since
//no data should be lost during that conversion
for(unsigned int i = 0; i < check.size();++i)
if((int)(char)check.at(i) < 48 || (int)(char)check.at(i) > 57)
{
if(i > 0 && (int)(char)check.at(i) != 45)
return false;
}
return true;//The integer only contains data that can be converted to a integer
}
bool Variant::isDecimalData()
{
//Check if the current variant only contains data that can be converted to float or double data
if(isContainer())
return false;
else if(currentType == Float || currentType == Double)
return true;
const std::string check = toStdString();
for(unsigned int i = 0; i < check.size();++i)
if((int)(char)check.at(i) < 48 || (int)(char)check.at(i) > 57)
{
if(i == 0 && (int)(char)check.at(i) == 45);//Check if it is negative mark
else if(i == 0 || i == check.size() - 1 || (int)(char)check.at(i) != 46)//Check if it is not a decimal value
return false;
}
return true;
}
Variant var((std::string)"189.89"); double dVal = var.toDouble();//Will convert the std::string to a double var = (int64)189888; const char * cVal = var.toCharArray();//Wil convert the variant that now contains the long long value 189888 to a char array/ cstring.
void printStuff(Variant val)
{
std::cout << val.toStdString();
}
//You can now call that print function with the most common types.
printStuff((double)189.89);
printStuff((bool)false);
It is a very simple class the code is just very repetitive since i didn't use templates. Look up the boost libraries Variant class if you are confused.#ifndef VARIANT_H
#define VARIANT_H
#include <sstream>
#include <string.h>
#include <iostream>
typedef long long int64;//A long long is the same as a int64
class Variant
{
//A class meant to make it easier to convert between basic types
//and classes and various functions that fits in that category
public:
Variant();//The user don't assign the variable in the creation of the class
Variant(const Variant& val);
Variant(const int Val);//The user assigns the class to a integer
Variant(const float Val);//The user assigns the class to a float
Variant(const double Val);//The user assigns the class to a double
Variant(const bool Val);//The user assings the class to a boolean
Variant(const char Val);//The user assigns the class to a char
Variant(const char * Val);//The user assigns the class to a char array/char pointer
Variant(const unsigned long Val);//The user assigns the class to a unsigned long by default
Variant(const int64);//The user assigns the class to a long long/int64
~Variant();
void operator = (const Variant& Val);//Set the variant to another variant
bool operator == (const Variant& val) const;//Check if the current variant equals to another
//Variant by the value and the type
bool operator != (const Variant& val) const;//If the Variants don't have the same value and or type return true
//else false
enum Types
{
//A enum to keep track of all the types and classes
//the variant class supports convertion between
Undefined = -1,
Int,
Float,
Double,
Int64,
ULong,
Bool,
Char,
CharArray
};
int type() const;//Return the current type of the current Variant class
//The conversion functions
int toInt() const;//Try to return the Variant as a integer
float toFloat() const;//Try to return the Variant as a float
double toDouble() const;//Try to return the Variant as a double
bool toBool() const;//Try to return the Variant as a bool
char toChar() const;//Try to return the Variant as a char
const char * toCharArray() const;//Try to return the Variant as a char array
unsigned long toULong() const;//Try to return the variant as a unsigned long
int64 toInt64() const;//Try to return the variant as a int64
long long toLongLong() const;//Try to return the variant as a long,long / 64 bit integer
static int toInt(const Variant& val);
static float toFloat(const Variant& val);
static double toDouble(const Variant& val);
static unsigned long toULong(const Variant& val);
static int64 toInt64(const Variant& val);
long long toLongLong(const Variant& val);
static bool toBool(const Variant& val);
static char toChar(const Variant& val);
static const char * toCharArray( const Variant& val);
static bool isTrue(const Variant& Var);//Check if a variant is true
bool canCastTo(const Types type) const;//Wheater the variant can be cast/always be converted to a specefied type
bool cast(int val);//Cast the current variant to the integer the user passed
bool cast(float val);//Cast the current variant to the float the user passed
bool cast(double val);//Cast the current variant to the double the user passed
bool cast(bool val);//Cast the current variant to the bool the user passed
bool cast(char val);//Cast the current variant to the char the user passed
bool cast(unsigned long val);//Cast the current variant to the unsigned long the user passed
bool cast(int64 val);//Cast the current variant to the int64 the user passed
bool matchingValues(const Variant &val) const; //If the type matches and
//the value of the both Variants matches return true
//else false
bool matchingTypes(const Variant &val) const;//If the current Variant and the variant passed
//has the same type it will return true
//else it will return false
bool isUndefined() const;//If the current variant is undefined
//return true else false
enum Error
{
Error_NoError = 0,
Error_UndefinedType,
Error_UnknownError
};
void clear();//Clear the current variant
bool setValue(const Variant &val, const Types type);//Set the value of the current variant and set type of the current variant
private:
Types currentType;//To keep track of the current type
void setCurrentType(const Types type);//Update the current type
union Value
{
//A struct/containter to keep track to store
//the current value
int iVal;//To hold integer values
float fVal;//To hold floating point values
double dVal;//To hold double values
unsigned long ulVal;//To hold unsigned long values
int64 i64Val;//To hold the int64 values
bool bVal;//To hold boolean values
char cVal;//To hold char values
char * strVal;//To hold char array values/ cstring values
};
Value currentValue;//To keep track of the current value
bool isIntegerData() const;//Check if the current variant only contains data that can be converted to a integer
bool isDecimalData() const;//Check if the current variant onlu contains data that can be converted to a decimal type such as float or double
//can fully be converted to a number
};
#endif // VARIANT_H
#include "variant.h"
Variant::Variant()
{
currentValue.strVal = NULL;
setCurrentType(Undefined);//The current type is undefined
//since the user did not pass a type as the parameters
}
Variant::Variant(const Variant &val)
{
setValue(val, val.currentType);
}
Variant::~Variant()
{
setCurrentType(Undefined);
}
void Variant::setCurrentType(const Variant::Types type)
{
if ( currentType != CharArray )
currentValue.strVal = NULL;
if ( currentType == CharArray && currentValue.strVal)
{
free(currentValue.strVal);
currentValue.strVal = NULL;
}
currentType = type;//Set the current type to keep track of the current type
}
Variant::Variant(const int Val)
{
//The user assigns the class to a integer
setCurrentType(Int);//Set the current type to int
currentValue.iVal = Val;//Set the integer value to the integer the user passed
}
Variant::Variant(const float Val)
{
//The user assigns the class to a float
setCurrentType(Float);//Set the current type to float
currentValue.fVal = Val;//Set the floating point value to the float value the user passed
}
Variant::Variant(const double Val)
{
//The user assigns the class to a double
setCurrentType(Double);//Set the current type to a double
currentValue.dVal = Val;//Set the double to the double the user passed
}
Variant::Variant(const bool Val)
{
//The user assings the class to a boolean
setCurrentType(Bool);//Set the current type to bool
currentValue.bVal = Val;//Set the boolean value to boolean the user passed
}
Variant::Variant(const char Val)
{
//The user assigns the class to a char
setCurrentType(Char);//Set the current type to char
currentValue.cVal = Val;//Set the char value to the value the user passed
}
Variant::Variant(const char * Val)
{
//The user assigns the class to a char array/char pointer
setCurrentType(CharArray);//Set the current type to a char array
currentValue.strVal = _strdup(Val);//Set the string value to the string value the user passed
}
Variant::Variant(const unsigned long Val)
{
//The user assigns the current Variant to a unsigned long
setCurrentType(ULong);//To keep track of the current type
currentValue.ulVal = Val;//Set the current value to the value of the ULong passed by the user
}
Variant::Variant(const int64 Val)
{
//The user assigns the Variant to a int64/long long
setCurrentType(Int64);
currentValue.i64Val = Val;//Set the int 64
}
void Variant::operator =(const Variant &Var)
{
setValue(Var, Var.currentType);
// this->currentType = Var.currentType;//Set the currentType to the type of the variant the user passed
// this->currentValue = Var.currentValue;//Set the currentValue to the value of the variant the user passed
//Since the Variant can handle all the basic types
//there is no need to create a new = operator for each type, when they all can be passed
//via the variant in this function
}
int Variant::type() const
{
//Return the current type of the current value
//so the user can check for different types
return (int)currentType;
}
int Variant::toInt() const
{
//Try to return the Variant as a integer
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
return this->currentValue.iVal;//If the Variant is a integer just return it
break;
case Float:
return (int)this->currentValue.fVal;//If the variant is a float type it to a integer and return it
break;
case Double:
return (int)this->currentValue.dVal;//If the variant is a double type it to a integer and return
break;
case ULong:
return (int)this->currentValue.ulVal;//Return the integer version of the unsigned long
break;
case Int64:
return (int)this->currentValue.i64Val;//Return the integer version of the int64
case Bool:
return (int)this->currentValue.bVal;//Type the boolean to a intger and return
break;
case Char:
{
std::stringstream stream;//Create a stringstream to hold the char value
stream << this->currentValue.cVal;//Set the stringstream to the char value
int Re = 0;//Create the return integer and set it to 0 to avoid undefined behaviour
stream >> Re;//Input the stored char to the integer
return Re;//Return the integer
}
break;
case CharArray:
{
std::stringstream stream;//Create a stringstream to hold the char array
stream << this->currentValue.strVal;//Set the stringstream to the char array
int Re = 0;//Create the return integer and assign it to 0 to avoid undefiend behaviours
stream >> Re;//Input the char array tp the integer
return Re;//Return the integer
}
case Undefined:
{
return 0;//Return -1 for failed
}
}
}
return 0;//Return -1 for failed
}
float Variant::toFloat() const
{
//Try to return the Variant as a float
if(isDecimalData() || isIntegerData())
{
switch(this->currentType)
{
case Int:
return (float)this->currentValue.iVal;//Type the integer to a float and return it
break;
case Float:
return (float)this->currentValue.fVal;//Return the float value
break;
case Double:
return (float)this->currentValue.dVal;//Type the double to a float and return it
break;
case ULong:
return (float)this->currentValue.ulVal;
break;
case Int64:
return (float)this->currentValue.i64Val;
break;
case Bool:
return (float)this->currentValue.bVal;//Type the boolean to a float ad return it
break;
case Char:
{
std::stringstream stream;//Create a stringstream for the char
stream << this->currentValue.cVal;//Set the stringstream to the char
float Re = 0.0;//Create the return float
stream >> Re;//Assign the float to the value of the stream
return Re;//Return the float
}
break;
case CharArray:
{
std::stringstream stream;//Create a stringstream for the char array
stream << this->currentValue.strVal;//Assisgn the stream to the char array
float Re = 0.0;//Create the return float
stream >> Re;//Assign the float the value of the stream
return Re;//Return the float value
}
break;
case Undefined:
{
return (float)0;//Return -1 for error
}
break;
}
}
return (float)0;
}
bool Variant::toBool() const
{
return isTrue(this->toCharArray());//If the variant is true it will return true else false
}
double Variant::toDouble() const
{
if(isDecimalData() || isIntegerData())
{
switch(this->currentType)
{
case Int:
return (double)this->currentValue.iVal;//Type the integer to a double and return it
break;
case Float:
return (double)this->currentValue.fVal;//Type the float to a double and return it
break;
case Double:
return this->currentValue.dVal;//Return the double vba
break;
case ULong:
return (double)this->currentValue.ulVal;
break;
case Int64:
return (double)this->currentValue.i64Val;
case Bool:
return (double)this->currentValue.bVal;//Type the boolean to a double and return it
break;
case Char:
{
std::stringstream stream;//Create the stream that will store the char
stream << this->currentValue.cVal;//Assign the stream to the char
double Re = 0.0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the double value
}
break;
case CharArray:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.strVal;//Assign the stream to the char array
double Re = 0.0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the double value
}
break;
case Undefined:
{
return 0;//Return 0 failed
}
break;
}
}
return 0;//Return 0 for failed
}
unsigned long Variant::toULong() const
{
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
return (unsigned long)this->currentValue.iVal;
break;
case Float:
return (unsigned long)this->currentValue.fVal;
break;
case Double:
return (unsigned long)this->currentValue.dVal;
break;
case ULong:
return this->currentValue.ulVal;
break;
case Int64:
return (unsigned long)this->currentValue.i64Val;
case Bool:
return (unsigned long)this->currentValue.bVal;
break;
case Char:
{
std::stringstream stream;//Create the stream that will store the char
stream << this->currentValue.cVal;//Assign the stream to the char
unsigned long Re = 0;//Create the return double
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the ULong value
}
break;
case CharArray:
{
std::stringstream stream;//Create the stream that will store the char array
stream << this->currentValue.strVal;//Assign the stream to the char array
unsigned long Re = 0;//Create the return ulong
stream >> Re;//Assign the double to the value of the stream
return Re;//Return the ulong
}
break;
case Undefined:
return 0;//Failed
break;
}
}
return 0;//Failed
}
int64 Variant::toInt64() const
{
if(isIntegerData() || isDecimalData())
{
switch(this->currentType)
{
case Int:
{
return (int64)this->currentValue.iVal;
}
break;
case Float:
{
return (int64)this->currentValue.fVal;
}
break;
case Double:
{
return (int64)this->currentValue.dVal;
}
break;
case ULong:
{
return (int64)this->currentValue.ulVal;
}
break;
case Int64:
{
return this->currentValue.i64Val;
}
break;
case Bool:
{
return (int64)this->currentValue.bVal;
}
break;
case Char:
{
std::stringstream stream;
stream << this->currentValue.cVal;
int64 re = 0;
stream >> re;
return re;
}
break;
case CharArray:
{
std::stringstream stream;
stream << this->currentValue.strVal;
int64 re = 0;
stream >> re;
return re;
}
break;
case Undefined:
return 0;
break;
}
}
return 0;
}
long long Variant::toLongLong() const
{
return this->toInt64();
}
const char * Variant::toCharArray() const
{
//Try to return the variant as a char array
switch(this->currentType)
{
case Int:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.iVal;//Assign the stream to the integer value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Float:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.fVal;//Assign the stream to the floating point value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Double:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.dVal;//Assign the stream to the double value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case ULong:
{
std::stringstream stream;//Create the stream where the ineger will be stored
stream << this->currentValue.ulVal;//Assign the stream to the unsigned long value
const char * re;//Create the return char array
re = stream.str().c_str();//Assign the char array with the value of the stream
return (char*) re;//Return the char array
}
break;
case Int64:
{
std::stringstream stream;
stream << this->currentValue.i64Val;
const char * re;
re = stream.str().c_str();
return (char*)re;
}
case Bool:
{
if(this->currentValue.bVal == true)
return (char*)"1";//Return one for true
return (char*)"0";//Return zero for false
}
break;
case Char:
{
std::stringstream stream;//Create the stream to hold the char
stream << this->currentValue.cVal;//Set the stream to the char
return (char*)stream.str().c_str();//Return the stream as a char array
}
break;
case CharArray:
return (char*)this->currentValue.strVal;//Just return the char array
break;
case Undefined:
return (char*)NULL;//Return nothing as for failed
}
return (char*)NULL;//Return nothing as for failed
}
bool Variant::isTrue(const Variant &Var)
{
//Check if the passed variant is true or false
const char * str = (const char*)Var.toCharArray();//Convert the variant to a cstring
int strsize = strlen((const char*)str);//Get the lenght of the string
int TCount = 0;//Too keep track of the number of true chars in the string
int FCount = 0;//Too keep track of the number of false chars in the string
for(int i = 0; i < strsize;++i)
{
//Loop through the entire string
//And check each char if it is true or not
if(str[i] == '0')
++FCount;//A new false char was found,increase the number of false chars
else
++TCount;//Else it is a true char increase the number of true chars in the string
}
if(TCount > FCount)
return true;//The string contained more true chars than false chars
else if(FCount > TCount)
return false;//The string contained more false chars than true chars
//If it has gotten to this point TCount and FCount is the same value
//then base boolean of the first char in the string
if(str[0] == '0')
return false;//The first char is false so then return false
return true;//Else the first char is true so return true
}
char Variant::toChar() const
{
//Try to convert the current Variant to a char
switch(this->currentType)
{
case Int:
{
std::stringstream stream;//Create the stringstream that will hold tje integer value
stream << this->currentValue.iVal;//Assign the stream to the integer value
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Float:
{
std::stringstream stream;//Create the stringstream that will hold the float valie
stream << this->currentValue.fVal;//Assign the stream to the float value
char Re = '0';//Create the return char
stream >> Re;///Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Double:
{
std::stringstream stream;//Create the stringstream that will hold the double
stream << this->currentValue.dVal;//Assign the stream to the double
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case ULong:
{
std::stringstream stream;//Create the stringstream that will hold the double
stream << this->currentValue.ulVal;//Assign the stream to the unsigned long value
char Re = '0';//Create the return char
stream >> Re;//Assign the char to the value of the stream
return Re;//Return the char
}
break;
case Int64:
{
std::stringstream stream;
stream << this->currentValue.i64Val;
char Re = '0';
stream >> Re;
return Re;
}
break;
case Bool:
{
if(this->currentValue.bVal == true)
return (char)'1';//Return true
return (char)'0';//Return false
}
break;
case Char:
return this->currentValue.cVal;//Just return the char value
break;
case CharArray:
{
if(strlen((const char*)this->currentValue.strVal) > 0)
return (char)this->currentValue.strVal[0];//Return the first char of the string
else
{
return (char)'0';
}
}
break;
case Undefined:
{
return '0';//Return 0 for failed
}
}
return (char)'0';//Return 0 for failed
}
int Variant::toInt(const Variant &val)
{
return val.toInt();
}
float Variant::toFloat(const Variant &val)
{
return val.toFloat();
}
double Variant::toDouble(const Variant &val)
{
return val.toDouble();
}
unsigned long Variant::toULong(const Variant &val)
{
return val.toULong();
}
int64 Variant::toInt64(const Variant &val)
{
return val.toInt64();
}
long long Variant::toLongLong(const Variant &val)
{
return val.toInt64();
}
bool Variant::toBool(const Variant &val)
{
return val.toBool();
}
char Variant::toChar(const Variant &val)
{
return val.toChar();
}
const char * Variant::toCharArray(const Variant &val)
{
return val.toCharArray();
}
void Variant::clear()
{
//Clear all the Variants values
currentValue.iVal = 0;//Set the integer value to zero
currentValue.fVal = 0;//Set the float value to zero
currentValue.dVal = 0;//Set the double value to zero
currentValue.cVal = (char)(int)0;//Set the char value to null
currentValue.ulVal = 0;
currentValue.i64Val = 0;
currentValue.strVal = (char*)NULL;//Set the string value to empty
currentValue.bVal = false;//Set the boolean value to false
setCurrentType(Undefined);//Set the current type to undefined
//no type has been set by the user yet
}
bool Variant::canCastTo(const Variant::Types type) const
{
//Check if the current variant can be casted
//to another type
if(this->currentType == Char || this->currentType == Int
|| this->currentType == Float || this->currentType == Double || this->currentType == Bool || this->currentType == ULong || this->currentType == Int64)
{
//If the current Variant is any of these types
return (type == Char || type == Int || type == Float || type == Double || type == Bool || type == ULong || type == Int64);
}
//The remaning type is the char array which can't be casted with anything
return false;//therefore return false for not can be casted with the type the user passed
}
bool Variant::cast(int val)
{
switch(this->currentType)
{
case Int:
val = (int)this->currentValue.iVal;
return true;
break;
case Float:
val = (int)this->currentValue.fVal;
return true;
break;
case Double:
val = (int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (int)this->currentValue.bVal;
return true;
break;
case Char:
val = (int)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(int64 val)
{
//Cast the current variant to a 64 bit integer
switch(this->currentType)
{
case Int:
val = (int64)this->currentValue.iVal;
return true;
break;
case Float:
val = (int64)this->currentValue.fVal;
return true;
break;
case Double:
val = (int64)this->currentValue.dVal;
return true;
break;
case ULong:
val = (int64)this->currentValue.ulVal;
return true;
break;
case Int64:
val = this->currentValue.i64Val;
return true;
break;
case Char:
val = (int64)this->currentValue.cVal;
return true;
break;
case Bool:
val = (int64)this->currentValue.bVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(unsigned long val)
{
switch(this->currentType)
{
case Int:
val = (unsigned long)this->currentValue.iVal;
return true;
break;
case Float:
val = (unsigned long)this->currentValue.fVal;
return true;
break;
case Double:
val = (unsigned long)this->currentValue.dVal;
return true;
break;
case ULong:
val = (unsigned long)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (unsigned long)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (unsigned long)this->currentValue.bVal;
return true;
break;
case Char:
val = (unsigned long)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(float val)
{
switch(this->currentType)
{
case Int:
val = (float)this->currentValue.iVal;
return true;
break;
case Float:
val = (float)this->currentValue.fVal;
return true;
break;
case Double:
val = (float)this->currentValue.dVal;
return true;
break;
case ULong:
val = (float)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (float)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (float)this->currentValue.bVal;
return true;
break;
case Char:
val = (float)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(double val)
{
switch(this->currentType)
{
case Int:
val = (double)this->currentValue.iVal;
return true;
break;
case Float:
val = (double)this->currentValue.fVal;
return true;
break;
case Double:
val = (double)this->currentValue.dVal;
return true;
break;
case ULong:
val = (double)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (double)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (double)this->currentValue.bVal;
return true;
break;
case Char:
val = (double)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(char val)
{
switch(this->currentType)
{
case Int:
val = (char)this->currentValue.iVal;
return true;
break;
case Float:
val = (char)(int)this->currentValue.fVal;
return true;
break;
case Double:
val = (char)(int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (char)(int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (char)(int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (char)(int)this->currentValue.bVal;
return true;
break;
case Char:
val = (char)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::cast(bool val)
{
switch(this->currentType)
{
case Int:
val = (bool)this->currentValue.iVal;
return true;
break;
case Float:
val = (bool)(int)this->currentValue.fVal;
return true;
break;
case Double:
val = (bool)(int)this->currentValue.dVal;
return true;
break;
case ULong:
val = (bool)(int)this->currentValue.ulVal;
return true;
break;
case Int64:
val = (bool)(int)this->currentValue.i64Val;
return true;
break;
case Bool:
val = (bool)this->currentValue.bVal;
return true;
break;
case Char:
val = (bool)this->currentValue.cVal;
return true;
break;
case CharArray:
return false;
break;
case Undefined:
return false;
break;
}
return false;
}
bool Variant::setValue(const Variant &val, const Types T)
{
//Set the Variant value without changing the T
setCurrentType(T);
if(currentType == T)
{//If the current type actually was set
switch(T)
{
case Int:
this->currentValue.iVal = val.toInt();
return true;
break;
case Float:
this->currentValue.fVal = val.toFloat();
return true;
break;
case Double:
this->currentValue.dVal = val.toDouble();
return true;
break;
case ULong:
this->currentValue.ulVal = val.toULong();
return true;
break;
case Int64:
this->currentValue.i64Val = val.toInt64();
return true;
break;
case Bool:
this->currentValue.bVal = val.toBool();
return true;
break;
case Char:
this->currentValue.cVal = val.toChar();
return true;
break;
case CharArray:
this->currentValue.strVal = _strdup(val.toCharArray());
return true;
break;
default:
return false;
break;
}
}
return false;//Return false for failed
}
bool Variant::operator ==(const Variant &val) const
{
return matchingValues(val);//Check if the values and the types are the same
}
bool Variant::matchingTypes(const Variant &val) const
{
return (this->currentType == val.currentType);
}
bool Variant::matchingValues(const Variant &val) const
{
if(matchingTypes(val))
{
//The types must be the same for the value to match
switch(this->currentType)
{
case Int:
{
return (this->currentValue.iVal == val.currentValue.iVal);
}
break;
case Float:
{
return (this->currentValue.fVal == val.currentValue.fVal);
}
break;
case Double:
{
return (this->currentValue.dVal == val.currentValue.dVal);
}
break;
case ULong:
{
return (this->currentValue.ulVal == val.currentValue.ulVal);
}
break;
case Int64:
{
return (this->currentValue.i64Val == val.currentValue.i64Val);
}
break;
case Bool:
{
return (this->currentValue.bVal == val.currentValue.bVal);
}
break;
case Char:
{
return (this->currentValue.cVal == val.currentValue.cVal);
}
break;
case CharArray:
{
return strcmp(this->currentValue.strVal,val.currentValue.strVal) == 0;
}
break;
case Undefined:
return true;//Both the variants are undefined
break;
}
}
return false;
}
bool Variant::operator !=(const Variant &val) const
{
//Check if the current variant and the passed variant
//don't have the same value and or type
return (!matchingValues(val));
}
bool Variant::isUndefined() const
{
return (currentType == Undefined);
}
bool Variant::isIntegerData() const
{
if(currentType == Int || currentType == ULong || currentType == Int64)
return true;
return false;//The integer only contains data that can be converted to a integer
}
bool Variant::isDecimalData() const
{
if(currentType == Float || currentType == Double)
return true;
return false;
}