Program Listing for File Variant.cpp
↰ Return to documentation for file (src/Variant.cpp
)
//-------------------------------------------------------------
// Based on Variant.cc in the Physics eXtension Library (PXL) -
// http://vispa.physik.rwth-aachen.de/ -
// Licensed under a LGPL-2 or later license -
//-------------------------------------------------------------
#include "crpropa/Variant.h"
#include <algorithm>
namespace crpropa
{
Variant::Variant() :
type(TYPE_NONE)
{
}
Variant::~Variant()
{
clear();
}
Variant::Variant(const Variant& a) :
type(TYPE_NONE)
{
copy(a);
}
Variant::Variant(const char *s)
{
data._String = new std::string(s);
type = TYPE_STRING;
}
void Variant::clear()
{
if (type == TYPE_STRING)
{
if(data._String)
{
delete data._String;
data._String = NULL;
}
}
type = TYPE_NONE;
}
void Variant::check(const Type t) const
{
if (type != t)
throw bad_conversion(type, t);
}
void Variant::check(const Type t)
{
if (type == TYPE_NONE)
{
std::memset(&data, 0, sizeof(data));
switch (t)
{
case TYPE_STRING:
data._String = new std::string;
break;
default:
break;
}
type = t;
}
else if (type != t)
{
throw bad_conversion(type, t);
}
}
const std::type_info& Variant::getTypeInfo() const
{
if (type == TYPE_BOOL)
{
const std::type_info &ti = typeid(data._Bool);
return ti;
}
else if (type == TYPE_CHAR)
{
const std::type_info &ti = typeid(data._Char);
return ti;
}
else if (type == TYPE_UCHAR)
{
const std::type_info &ti = typeid(data._UChar);
return ti;
}
else if (type == TYPE_INT16)
{
const std::type_info &ti = typeid(data._Int16);
return ti;
}
else if (type == TYPE_UINT16)
{
const std::type_info &ti = typeid(data._UInt16);
return ti;
}
else if (type == TYPE_INT32)
{
const std::type_info &ti = typeid(data._Int32);
return ti;
}
else if (type == TYPE_UINT32)
{
const std::type_info &ti = typeid(data._UInt32);
return ti;
}
else if (type == TYPE_INT64)
{
const std::type_info &ti = typeid(data._Int64);
return ti;
}
else if (type == TYPE_UINT64)
{
const std::type_info &ti = typeid(data._UInt64);
return ti;
}
else if (type == TYPE_FLOAT)
{
const std::type_info &ti = typeid(data._Float);
return ti;
}
else if (type == TYPE_DOUBLE)
{
const std::type_info &ti = typeid(data._Double);
return ti;
}
else if (type == TYPE_STRING)
{
const std::type_info &ti = typeid(*data._String);
return ti;
}
else
{
const std::type_info &ti = typeid(0);
return ti;
}
}
const char *Variant::getTypeName(Type type)
{
if (type == TYPE_NONE)
{
return "none";
}
else if (type == TYPE_BOOL)
{
return "bool";
}
else if (type == TYPE_CHAR)
{
return "char";
}
else if (type == TYPE_UCHAR)
{
return "uchar";
}
else if (type == TYPE_INT16)
{
return "int16";
}
else if (type == TYPE_UINT16)
{
return "uint16";
}
else if (type == TYPE_INT32)
{
return "int32";
}
else if (type == TYPE_UINT32)
{
return "uint32";
}
else if (type == TYPE_INT64)
{
return "int64";
}
else if (type == TYPE_UINT64)
{
return "uint64";
}
else if (type == TYPE_FLOAT)
{
return "float";
}
else if (type == TYPE_DOUBLE)
{
return "double";
}
else if (type == TYPE_STRING)
{
return "string";
}
else
{
return "unknown";
}
}
Variant::Type Variant::toType(const std::string &name)
{
if (name == "none")
{
return TYPE_NONE;
}
else if (name == "bool")
{
return TYPE_BOOL;
}
else if (name == "char")
{
return TYPE_CHAR;
}
else if (name == "uchar")
{
return TYPE_UCHAR;
}
else if (name == "int16")
{
return TYPE_INT16;
}
else if (name == "uint16")
{
return TYPE_UINT16;
}
else if (name == "int32")
{
return TYPE_INT32;
}
else if (name == "uint32")
{
return TYPE_UINT32;
}
else if (name == "int64")
{
return TYPE_INT64;
}
else if (name == "uint64")
{
return TYPE_UINT64;
}
else if (name == "float")
{
return TYPE_FLOAT;
}
else if (name == "double")
{
return TYPE_DOUBLE;
}
else if (name == "string")
{
return TYPE_STRING;
}
else
{
return TYPE_NONE;
}
}
bool Variant::operator ==(const Variant &a) const
{
if (type != a.type)
return false;
if (type == TYPE_BOOL)
{
return (data._Bool == a.data._Bool);
}
else if (type == TYPE_CHAR)
{
return (data._Char == a.data._Char);
}
else if (type == TYPE_UCHAR)
{
return (data._UChar == a.data._UChar);
}
else if (type == TYPE_INT16)
{
return (data._Int16 == a.data._Int16);
}
else if (type == TYPE_UINT16)
{
return (data._UInt16 == a.data._UInt16);
}
else if (type == TYPE_INT32)
{
return (data._Int32 == a.data._Int32);
}
else if (type == TYPE_UINT32)
{
return (data._UInt32 == a.data._UInt32);
}
else if (type == TYPE_INT64)
{
return (data._Int64 == a.data._Int64);
}
else if (type == TYPE_UINT64)
{
return (data._UInt64 == a.data._UInt64);
}
else if (type == TYPE_FLOAT)
{
return (data._Float == a.data._Float);
}
else if (type == TYPE_DOUBLE)
{
return (data._Double == a.data._Double);
}
else if (type == TYPE_STRING)
{
return (*data._String == *a.data._String);
}
else
{
throw std::runtime_error("compare operator not implemented");
}
}
std::string Variant::toString() const
{
if (type == TYPE_STRING)
return *data._String;
std::stringstream sstr;
if (type == TYPE_BOOL)
{
sstr << data._Bool;
}
else if (type == TYPE_CHAR)
{
sstr << data._Char;
}
else if (type == TYPE_UCHAR)
{
sstr << data._UChar;
}
else if (type == TYPE_INT16)
{
sstr << data._Int16;
}
else if (type == TYPE_UINT16)
{
sstr << data._UInt16;
}
else if (type == TYPE_INT32)
{
sstr << data._Int32;
}
else if (type == TYPE_UINT32)
{
sstr << data._UInt32;
}
else if (type == TYPE_INT64)
{
sstr << data._Int64;
}
else if (type == TYPE_UINT64)
{
sstr << data._UInt64;
}
else if (type == TYPE_FLOAT)
{
sstr << std::scientific << data._Float;
}
else if (type == TYPE_DOUBLE)
{
sstr << std::scientific << data._Double;
}
return sstr.str();
}
Variant Variant::fromString(const std::string &str, Type type)
{
std::stringstream sstr(str);
switch (type)
{
case TYPE_BOOL:
{
std::string upperstr(str);
std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(),
(int(*)(int))toupper);if
( upperstr == "YES")
return Variant(true);
else if (upperstr == "NO")
return Variant(false);
if (upperstr == "TRUE")
return Variant(true);
else if (upperstr == "FALSE")
return Variant(false);
if (upperstr == "1")
return Variant(true);
else if (upperstr == "0")
return Variant(false);
throw bad_conversion(type, TYPE_BOOL);
}
case TYPE_CHAR:
{
char c;
sstr >> c;
return Variant(c);
}
case TYPE_UCHAR:
{
unsigned char c;
sstr >> c;
return Variant(c);
}
case TYPE_INT16:
{
int16_t c;
sstr >> c;
return Variant(c);
}
case TYPE_UINT16:
{
uint16_t c;
sstr >> c;
return Variant(c);
}
case TYPE_INT32:
{
int32_t c;
sstr >> c;
return Variant(c);
}
case TYPE_UINT32:
{
uint32_t c;
sstr >> c;
return Variant(c);
}
case TYPE_INT64:
{
int64_t c;
sstr >> c;
return Variant(c);
}
case TYPE_UINT64:
{
uint64_t c;
sstr >> c;
return Variant(c);
}
case TYPE_FLOAT:
{
float c;
sstr >> c;
return Variant(c);
}
case TYPE_DOUBLE:
{
double c;
sstr >> c;
return Variant(c);
}
case TYPE_STRING:
{
return Variant(str);
}
default:
throw std::runtime_error("pxl::Variant::fromString: unknown type");
}
}
bool Variant::operator !=(const Variant &a) const
{
if (type != a.type)
return true;
switch (type)
{
case TYPE_BOOL:
return (data._Bool != a.data._Bool);
case TYPE_CHAR:
return (data._Char != a.data._Char);
case TYPE_UCHAR:
return (data._UChar != a.data._UChar);
case TYPE_INT16:
return (data._Int16 != a.data._Int16);
case TYPE_UINT16:
return (data._UInt16 == a.data._UInt16);
case TYPE_INT32:
return (data._Int32 == a.data._Int32);
case TYPE_UINT32:
return (data._UInt32 == a.data._UInt32);
case TYPE_INT64:
return (data._Int64 == a.data._Int64);
case TYPE_UINT64:
return (data._UInt64 == a.data._UInt64);
case TYPE_FLOAT:
return (data._Float == a.data._Float);
case TYPE_DOUBLE:
return (data._Double == a.data._Double);
case TYPE_STRING:
return (*data._String == *a.data._String);
default:
throw std::runtime_error("compare operator not implemented");
}
}
void Variant::copy(const Variant &a)
{
Type t = a.type;
if (t == TYPE_BOOL)
{
operator =(a.data._Bool);
}
else if (t == TYPE_CHAR)
{
operator =(a.data._Char);
}
else if (t == TYPE_UCHAR)
{
operator =(a.data._UChar);
}
else if (t == TYPE_INT16)
{
operator =(a.data._Int16);
}
else if (t == TYPE_UINT16)
{
operator =(a.data._UInt16);
}
else if (t == TYPE_INT32)
{
operator =(a.data._Int32);
}
else if (t == TYPE_UINT32)
{
operator =(a.data._UInt32);
}
else if (t == TYPE_INT64)
{
operator =(a.data._Int64);
}
else if (t == TYPE_UINT64)
{
operator =(a.data._UInt64);
}
else if (t == TYPE_FLOAT)
{
operator =(a.data._Float);
}
else if (t == TYPE_DOUBLE)
{
operator =(a.data._Double);
}
else if (t == TYPE_STRING)
{
operator =(*a.data._String);
}
else
{
type = TYPE_NONE;
}
}
bool Variant::toBool() const
{
switch (type)
{
case TYPE_BOOL:
return data._Bool;
break;
case TYPE_CHAR:
return data._Char != 0;
break;
case TYPE_UCHAR:
return data._UChar != 0;
break;
case TYPE_INT16:
return data._Int16 != 0;
break;
case TYPE_UINT16:
return data._UInt16 != 0;
break;
case TYPE_INT32:
return data._Int32 != 0;
break;
case TYPE_UINT32:
return data._UInt32 != 0;
break;
case TYPE_INT64:
return data._Int64 != 0;
break;
case TYPE_UINT64:
return data._UInt64 != 0;
break;
case TYPE_STRING:
{
std::string upperstr(*data._String);
std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(),
(int(*)(int))toupper);if
( upperstr == "YES")
return true;
else if (upperstr == "NO")
return false;
if (upperstr == "TRUE")
return true;
else if (upperstr == "FALSE")
return false;
if (upperstr == "1")
return true;
else if (upperstr == "0")
return false;
else
throw bad_conversion(type, TYPE_BOOL);
}
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
case TYPE_NONE:
throw bad_conversion(type, TYPE_BOOL);
break;
}
return false;
}
#define INT_CASE(from_var, from_type, to_type, to) \
case Variant::from_type:\
if (data._##from_var < std::numeric_limits<to>::min() || data._##from_var > std::numeric_limits<to>::max())\
throw bad_conversion(type, to_type);\
else\
return static_cast<to>(data._##from_var);\
break;\
#define INT_FUNCTION(to_type, fun, to) \
to Variant::fun() const { \
switch (type) { \
case Variant::TYPE_BOOL: \
return data._Bool ? 1 : 0; \
break; \
INT_CASE(Char, TYPE_CHAR, to_type, to) \
INT_CASE(UChar, TYPE_UCHAR, to_type, to) \
INT_CASE(Int16, TYPE_INT16, to_type, to) \
INT_CASE(UInt16, TYPE_UINT16, to_type, to) \
INT_CASE(Int32, TYPE_INT32, to_type, to) \
INT_CASE(UInt32, TYPE_UINT32, to_type, to) \
INT_CASE(Int64, TYPE_INT64, to_type, to) \
INT_CASE(UInt64, TYPE_UINT64, to_type, to) \
INT_CASE(Float, TYPE_FLOAT, to_type, to) \
INT_CASE(Double, TYPE_DOUBLE, to_type, to) \
case Variant::TYPE_STRING: \
{ \
long l = atol(data._String->c_str()); \
if (l < std::numeric_limits<to>::min() || l > std::numeric_limits<to>::max()) \
throw bad_conversion(type, to_type); \
else \
return l; \
} \
break; \
case Variant::TYPE_NONE: \
throw bad_conversion(type, TYPE_INT16); \
break;\
}\
return 0;\
}
INT_FUNCTION( TYPE_CHAR, toChar, char)
INT_FUNCTION( TYPE_UCHAR, toUChar, unsigned char)
INT_FUNCTION( TYPE_INT16, toInt16, int16_t)
INT_FUNCTION( TYPE_UINT16, toUInt16, uint16_t)
INT_FUNCTION( TYPE_INT32, toInt32, int32_t)
INT_FUNCTION( TYPE_UINT32, toUInt32, uint32_t)
INT_FUNCTION( TYPE_INT64, toInt64, int64_t)
INT_FUNCTION( TYPE_UINT64, toUInt64, uint64_t)
std::ostream& operator <<(std::ostream& os, const Variant &v)
{
switch (v.getType())
{
case Variant::TYPE_BOOL:
os << v.asBool();
break;
case Variant::TYPE_CHAR:
os << v.asChar();
break;
case Variant::TYPE_UCHAR:
os << v.asUChar();
break;
case Variant::TYPE_INT16:
os << v.asInt16();
break;
case Variant::TYPE_UINT16:
os << v.asUInt16();
break;
case Variant::TYPE_INT32:
os << v.asInt32();
break;
case Variant::TYPE_UINT32:
os << v.asUInt32();
break;
case Variant::TYPE_INT64:
os << v.asInt64();
break;
case Variant::TYPE_UINT64:
os << v.asUInt64();
break;
case Variant::TYPE_FLOAT:
os << v.asFloat();
break;
case Variant::TYPE_DOUBLE:
os << v.asDouble();
break;
case Variant::TYPE_STRING:
os << v.asString();
break;
default:
break;
}
return os;
}
float Variant::toFloat() const
{
if (type == TYPE_CHAR)
{
return static_cast<float>(data._Char);
}
else if (type == TYPE_UCHAR)
{
return static_cast<float>(data._UChar);
}
else if (type == TYPE_INT16)
{
return static_cast<float>(data._Int16);
}
else if (type == TYPE_UINT16)
{
return static_cast<float>(data._UInt16);
}
else if (type == TYPE_INT32)
{
return static_cast<float>(data._Int32);
}
else if (type == TYPE_UINT32)
{
return static_cast<float>(data._UInt32);
}
else if (type == TYPE_INT64)
{
return static_cast<float>(data._Int64);
}
else if (type == TYPE_UINT64)
{
return static_cast<float>(data._UInt64);
}
else if (type == TYPE_FLOAT)
{
return static_cast<float>(data._Float);
}
else if (type == TYPE_DOUBLE)
{
return static_cast<float>(data._Double);
}
else if (type == TYPE_STRING)
{
return static_cast<float>(std::atof(data._String->c_str()));
}
else if (type == TYPE_BOOL)
{
return data._Bool ? 1.0f : 0.0f;
}
else
{
return 0.0;
}
}
double Variant::toDouble() const
{
if (type == TYPE_CHAR)
{
return static_cast<double>(data._Char);
}
else if (type == TYPE_UCHAR)
{
return static_cast<double>(data._UChar);
}
else if (type == TYPE_INT16)
{
return static_cast<double>(data._Int16);
}
else if (type == TYPE_UINT16)
{
return static_cast<double>(data._UInt16);
}
else if (type == TYPE_INT32)
{
return static_cast<double>(data._Int32);
}
else if (type == TYPE_UINT32)
{
return static_cast<double>(data._UInt32);
}
else if (type == TYPE_INT64)
{
return static_cast<double>(data._Int64);
}
else if (type == TYPE_UINT64)
{
return static_cast<double>(data._UInt64);
}
else if (type == TYPE_FLOAT)
{
return static_cast<double>(data._Float);
}
else if (type == TYPE_DOUBLE)
{
return static_cast<double>(data._Double);
}
else if (type == TYPE_STRING)
{
return std::atof(data._String->c_str());
}
else if (type == TYPE_BOOL)
{
return data._Bool ? 1.0 : 0.0;
}
else
{
return 0.0;
}
}
#define MEMCPYRET(VAR) \
memcpy(buffer, &VAR, sizeof( VAR) );\
return sizeof( VAR );
size_t Variant::copyToBuffer(void* buffer)
{
if (type == TYPE_CHAR)
{
MEMCPYRET( data._Char )
}
else if (type == TYPE_UCHAR)
{
MEMCPYRET( data._UChar )
}
else if (type == TYPE_INT16)
{
MEMCPYRET(data._Int16);
}
else if (type == TYPE_UINT16)
{
MEMCPYRET(data._UInt16);
}
else if (type == TYPE_INT32)
{
MEMCPYRET(data._Int32);
}
else if (type == TYPE_UINT32)
{
MEMCPYRET(data._UInt32);
}
else if (type == TYPE_INT64)
{
MEMCPYRET(data._Int64);
}
else if (type == TYPE_UINT64)
{
MEMCPYRET(data._UInt64);
}
else if (type == TYPE_FLOAT)
{
MEMCPYRET(data._Float);
}
else if (type == TYPE_DOUBLE)
{
MEMCPYRET(data._Double);
}
else if (type == TYPE_STRING)
{
size_t len = data._String->size();
memcpy(buffer, data._String->c_str(), len);
return len;
}
else if (type == TYPE_BOOL)
{
MEMCPYRET(data._Bool);
}
else if (type == TYPE_NONE)
{
return 0;
}
throw std::runtime_error("This is serious: Type not handled in copyToBuffer()!");
};
size_t Variant::getSize() const
{
if (type == TYPE_CHAR)
{
return sizeof(data._Char);
}
else if (type == TYPE_UCHAR)
{
return sizeof(data._UChar);
}
else if (type == TYPE_INT16)
{
return sizeof(data._Int16);
}
else if (type == TYPE_UINT16)
{
return sizeof(data._UInt16);
}
else if (type == TYPE_INT32)
{
return sizeof(data._Int32);
}
else if (type == TYPE_UINT32)
{
return sizeof(data._UInt32);
}
else if (type == TYPE_INT64)
{
return sizeof(data._Int64);
}
else if (type == TYPE_UINT64)
{
return sizeof(data._UInt64);
}
else if (type == TYPE_FLOAT)
{
return sizeof(data._Float);
}
else if (type == TYPE_DOUBLE)
{
return sizeof(data._Double);
}
else if (type == TYPE_STRING)
{
size_t len = strlen(data._String->c_str()+1);
return len;
}
else if (type == TYPE_BOOL)
{
return sizeof(data._Bool);
}
else if (type == TYPE_NONE)
{
return 0;
}
throw std::runtime_error("This is serious: Type not handled in getSize()!");
};
} // namespace pxl