Program Listing for File Variant.h
↰ Return to documentation for file (include/crpropa/Variant.h
)
//-------------------------------------------------------------
// Based on Variant.hh of the Physics eXtension Library (PXL) -
// http://vispa.physik.rwth-aachen.de/ -
// Licensed under a LGPL-2 or later license -
//-------------------------------------------------------------
#ifndef CRPROPA_VARIANT_H
#define CRPROPA_VARIANT_H
#include <complex>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>
#include <sstream>
#include <stdexcept>
#include <typeinfo>
#include "crpropa/Vector3.h"
// defines copy constructor X(const X&), isX(), asX(), fromX(), toX(), op(), op=, op==, op!=
#define VARIANT_ADD_TYPE_DECL_POD(NAME, TYPE, VALUE, FIELD) \
Variant(const VALUE& v) { \
data._t_##FIELD = v; \
type = TYPE; \
} \
bool is##NAME() const { \
return type == TYPE; \
} \
VALUE& as##NAME() { \
check(TYPE); \
return data._t_##FIELD; \
} \
const VALUE& as##NAME() const { \
check(TYPE); \
return data._t_##FIELD; \
} \
static Variant from##NAME(const VALUE& v) { \
return Variant(v); \
} \
VALUE to##NAME() const; \
operator VALUE() const { \
return to##NAME(); \
} \
Variant& operator=(const VALUE& v) { \
clear(); \
type = TYPE; \
data._t_##FIELD = v; \
return *this; \
} \
bool operator==(const VALUE& v) const { \
check(TYPE); \
return data._t_##FIELD == v; \
} \
bool operator!=(const VALUE& v) const { \
check(TYPE); \
return data._t_##FIELD != v; \
} \
// defines isX(), asX(), fromX()
#define VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \
bool is##NAME() const { \
return type == TYPE; \
} \
VALUE& as##NAME() { \
check(TYPE); \
return *data._t_##FIELD; \
} \
const VALUE& as##NAME() const { \
check(TYPE); \
return *data._t_##FIELD; \
} \
static Variant from##NAME(const VALUE& v) { \
return Variant(v); \
} \
// defines isX(), asX(), fromX(), and copy constructor X(const X&), op=, op==, op!=
#define VARIANT_ADD_TYPE_DECL_PTR(NAME, TYPE, VALUE, FIELD) \
VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \
Variant(const VALUE& v) { \
data._t_##FIELD = new VALUE(v); \
type = TYPE; \
} \
Variant& operator=(const VALUE& v) { \
if (type != TYPE) { \
clear(); \
data._t_##FIELD = new VALUE();\
} \
type = TYPE; \
(*data._t_##FIELD) = v; \
return *this; \
} \
bool operator==(const VALUE& v) const { \
check(TYPE); \
return *data._t_##FIELD == v; \
} \
bool operator!=(const VALUE& v) const { \
return !(*this == v); \
} \
#define VARIANT_ADD_ITER_DECL_PTR(NAME, TYPE, FIELD) \
typedef FIELD##_t::iterator FIELD##_iterator; \
typedef FIELD##_t::const_iterator FIELD##_const_iterator; \
inline FIELD##_iterator begin##NAME() { \
check(TYPE); \
return data._t_##FIELD->begin(); \
} \
inline FIELD##_iterator end##NAME() { \
check(TYPE); \
return data._t_##FIELD->end(); \
} \
inline FIELD##_const_iterator begin##NAME() const { \
check(TYPE); \
return data._t_##FIELD->begin(); \
} \
inline FIELD##_const_iterator end##NAME() const { \
check(TYPE); \
return data._t_##FIELD->end(); \
}
namespace crpropa {
class Variant {
public:
enum Type {
TYPE_NONE = 0,
TYPE_BOOL,
TYPE_CHAR,
TYPE_UCHAR,
TYPE_INT16,
TYPE_UINT16,
TYPE_INT32,
TYPE_UINT32,
TYPE_INT64,
TYPE_UINT64,
TYPE_FLOAT,
TYPE_DOUBLE,
TYPE_LONGDOUBLE,
TYPE_COMPLEXF,
TYPE_COMPLEXD,
TYPE_STRING,
TYPE_VECTOR3F,
TYPE_VECTOR3D,
TYPE_VECTOR3C,
TYPE_VECTOR
};
class bad_conversion: public std::exception {
protected:
std::string msg;
public:
const char* what() const throw () {
return msg.c_str();
}
bad_conversion(Type f, Type t) {
msg = "Variant: bad conversion from '";
msg += Variant::getTypeName(f);
msg += "' to '";
msg += Variant::getTypeName(t);
msg += "'";
}
~bad_conversion() throw () {
}
};
typedef std::complex<float> complex_f;
typedef std::complex<double> complex_d;
typedef Vector3<std::complex<double>> Vector3c;
typedef std::vector<Variant> vector_t;
protected:
Type type;
union {
bool _t_bool;
char _t_char;
unsigned char _t_uchar;
int16_t _t_int16;
uint16_t _t_uint16;
int32_t _t_int32;
uint32_t _t_uint32;
int64_t _t_int64;
uint64_t _t_uint64;
float _t_float;
double _t_double;
long double _t_ldouble;
complex_f* _t_complex_f;
complex_d* _t_complex_d;
std::string* _t_string;
Vector3f* _t_vector3f;
Vector3d* _t_vector3d;
Vector3c* _t_vector3c;
vector_t* _t_vector;
} data;
public:
Variant();
Variant(Type t);
Variant(const Variant& v);
Variant(const char* s);
~Variant();
inline Type getType() const {
return type;
}
const char* getTypeName() const;
static const char* getTypeName(Type t);
const std::type_info& getTypeInfo() const;
static Type toType(const std::string& name);
std::string toString(const std::string& delimiter = "\t") const;
std::complex<float> toComplexFloat() const;
std::complex<double> toComplexDouble() const;
Vector3f toVector3f() const;
Vector3d toVector3d() const;
Vector3c toVector3c() const;
vector_t toVector() const;
static Variant fromString(const std::string& str, Type type);
void clear(Type t = TYPE_NONE);
bool isValid() const;
size_t size() const;
size_t getSizeOf() const;
size_t getSize() const;
void resize(size_t i);
size_t copyToBuffer(void* buffer);
operator std::string() const {
return toString();
}
Variant& operator=(const Variant& v);
bool operator==(const Variant& v) const;
bool operator!=(const Variant& v) const;
bool operator!=(const char* a) const;
Variant& operator[](size_t i);
inline Variant& operator[](int i) {
return operator[]((size_t) i);
}
const Variant& operator[](size_t i) const;
const Variant& operator[](int i) const {
return operator[]((size_t) i);
}
operator vector_t&();
operator const vector_t&() const;
template<class T>
T to() const {
throw bad_conversion(type, TYPE_NONE);
}
// automatically-generated functions
VARIANT_ADD_TYPE_DECL_POD(Bool, TYPE_BOOL, bool, bool)
VARIANT_ADD_TYPE_DECL_POD(Char, TYPE_CHAR, char, char)
VARIANT_ADD_TYPE_DECL_POD(UChar, TYPE_UCHAR, unsigned char, uchar)
VARIANT_ADD_TYPE_DECL_POD(Int16, TYPE_INT16, int16_t, int16)
VARIANT_ADD_TYPE_DECL_POD(UInt16, TYPE_UINT16, uint16_t, uint16)
VARIANT_ADD_TYPE_DECL_POD(Int32, TYPE_INT32, int32_t, int32)
VARIANT_ADD_TYPE_DECL_POD(UInt32, TYPE_UINT32, uint32_t, uint32)
VARIANT_ADD_TYPE_DECL_POD(Int64, TYPE_INT64, int64_t, int64)
VARIANT_ADD_TYPE_DECL_POD(UInt64, TYPE_UINT64, uint64_t, uint64)
VARIANT_ADD_TYPE_DECL_POD(Float, TYPE_FLOAT, float, float)
VARIANT_ADD_TYPE_DECL_POD(Double, TYPE_DOUBLE, double, double)
VARIANT_ADD_TYPE_DECL_POD(LongDouble, TYPE_LONGDOUBLE, long double, ldouble)
VARIANT_ADD_TYPE_DECL_PTR(ComplexFloat, TYPE_COMPLEXF, std::complex<float>, complex_f)
VARIANT_ADD_TYPE_DECL_PTR(ComplexDouble, TYPE_COMPLEXD, std::complex<double>, complex_d)
VARIANT_ADD_TYPE_DECL_PTR(String, TYPE_STRING, std::string, string)
VARIANT_ADD_TYPE_DECL_PTR(Vector3f, TYPE_VECTOR3F, Vector3f, vector3f)
VARIANT_ADD_TYPE_DECL_PTR(Vector3d, TYPE_VECTOR3D, Vector3d, vector3d)
VARIANT_ADD_TYPE_DECL_PTR(Vector3c, TYPE_VECTOR3C, Vector3c, vector3c)
VARIANT_ADD_TYPE_DECL_PTR(Vector, TYPE_VECTOR, vector_t, vector)
VARIANT_ADD_ITER_DECL_PTR(Vector, TYPE_VECTOR, vector)
private:
void copy(const Variant& v);
void check(const Type t) const;
void check(const Type t);
};
#define VARIANT_TO_DECL(NAME, VALUE) \
template<> inline VALUE Variant::to<VALUE>() const { \
return to##NAME(); \
} \
// declare type conversion functions
// not implemented for Vector3 and complex_*
VARIANT_TO_DECL(Bool, bool)
VARIANT_TO_DECL(Char, char)
VARIANT_TO_DECL(UChar, unsigned char)
VARIANT_TO_DECL(Int16, int16_t)
VARIANT_TO_DECL(UInt16, uint16_t)
VARIANT_TO_DECL(Int32, int32_t)
VARIANT_TO_DECL(UInt32, uint32_t)
VARIANT_TO_DECL(Int64, int64_t)
VARIANT_TO_DECL(UInt64, uint64_t)
VARIANT_TO_DECL(Float, float)
VARIANT_TO_DECL(Double, double)
VARIANT_TO_DECL(LongDouble, long double)
VARIANT_TO_DECL(String, std::string)
VARIANT_TO_DECL(Vector, Variant::vector_t)
std::ostream& operator <<(std::ostream& os, const Variant &v);
template <class T>
inline void safeDelete(T*& p) {
if (p) {
delete p;
p = 0;
}
}
} // namespace crpropa
#endif // CRPROPA_VARIANT