Line data Source code
1 : //-------------------------------------------------------------
2 : // Based on Variant.hh of the Physics eXtension Library (PXL) -
3 : // http://vispa.physik.rwth-aachen.de/ -
4 : // Licensed under a LGPL-2 or later license -
5 : //-------------------------------------------------------------
6 :
7 : #ifndef CRPROPA_VARIANT_H
8 : #define CRPROPA_VARIANT_H
9 :
10 : #include <complex>
11 : #include <cstdint>
12 : #include <cstdlib>
13 : #include <cstring>
14 : #include <iostream>
15 : #include <limits>
16 : #include <string>
17 : #include <sstream>
18 : #include <stdexcept>
19 : #include <typeinfo>
20 :
21 : #include "crpropa/Vector3.h"
22 :
23 :
24 :
25 : // defines copy constructor X(const X&), isX(), asX(), fromX(), toX(), op(), op=, op==, op!=
26 : #define VARIANT_ADD_TYPE_DECL_POD(NAME, TYPE, VALUE, FIELD) \
27 : Variant(const VALUE& v) { \
28 : data._t_##FIELD = v; \
29 : type = TYPE; \
30 : } \
31 : bool is##NAME() const { \
32 : return type == TYPE; \
33 : } \
34 : VALUE& as##NAME() { \
35 : check(TYPE); \
36 : return data._t_##FIELD; \
37 : } \
38 : const VALUE& as##NAME() const { \
39 : check(TYPE); \
40 : return data._t_##FIELD; \
41 : } \
42 : static Variant from##NAME(const VALUE& v) { \
43 : return Variant(v); \
44 : } \
45 : VALUE to##NAME() const; \
46 : operator VALUE() const { \
47 : return to##NAME(); \
48 : } \
49 : Variant& operator=(const VALUE& v) { \
50 : clear(); \
51 : type = TYPE; \
52 : data._t_##FIELD = v; \
53 : return *this; \
54 : } \
55 : bool operator==(const VALUE& v) const { \
56 : check(TYPE); \
57 : return data._t_##FIELD == v; \
58 : } \
59 : bool operator!=(const VALUE& v) const { \
60 : check(TYPE); \
61 : return data._t_##FIELD != v; \
62 : } \
63 :
64 : // defines isX(), asX(), fromX()
65 : #define VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \
66 : bool is##NAME() const { \
67 : return type == TYPE; \
68 : } \
69 : VALUE& as##NAME() { \
70 : check(TYPE); \
71 : return *data._t_##FIELD; \
72 : } \
73 : const VALUE& as##NAME() const { \
74 : check(TYPE); \
75 : return *data._t_##FIELD; \
76 : } \
77 : static Variant from##NAME(const VALUE& v) { \
78 : return Variant(v); \
79 : } \
80 :
81 : // defines isX(), asX(), fromX(), and copy constructor X(const X&), op=, op==, op!=
82 : #define VARIANT_ADD_TYPE_DECL_PTR(NAME, TYPE, VALUE, FIELD) \
83 : VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \
84 : Variant(const VALUE& v) { \
85 : data._t_##FIELD = new VALUE(v); \
86 : type = TYPE; \
87 : } \
88 : Variant& operator=(const VALUE& v) { \
89 : if (type != TYPE) { \
90 : clear(); \
91 : data._t_##FIELD = new VALUE();\
92 : } \
93 : type = TYPE; \
94 : (*data._t_##FIELD) = v; \
95 : return *this; \
96 : } \
97 : bool operator==(const VALUE& v) const { \
98 : check(TYPE); \
99 : return *data._t_##FIELD == v; \
100 : } \
101 : bool operator!=(const VALUE& v) const { \
102 : return !(*this == v); \
103 : } \
104 :
105 : #define VARIANT_ADD_ITER_DECL_PTR(NAME, TYPE, FIELD) \
106 : typedef FIELD##_t::iterator FIELD##_iterator; \
107 : typedef FIELD##_t::const_iterator FIELD##_const_iterator; \
108 : inline FIELD##_iterator begin##NAME() { \
109 : check(TYPE); \
110 : return data._t_##FIELD->begin(); \
111 : } \
112 : inline FIELD##_iterator end##NAME() { \
113 : check(TYPE); \
114 : return data._t_##FIELD->end(); \
115 : } \
116 : inline FIELD##_const_iterator begin##NAME() const { \
117 : check(TYPE); \
118 : return data._t_##FIELD->begin(); \
119 : } \
120 : inline FIELD##_const_iterator end##NAME() const { \
121 : check(TYPE); \
122 : return data._t_##FIELD->end(); \
123 : }
124 :
125 :
126 :
127 : namespace crpropa {
128 :
129 : /**
130 : @class Variant
131 : @brief storage container for data types as e.g. int, float, string, etc.
132 :
133 : Allows storage of multiple data types in one base class. Used to construct a map of `arbitrary' data types.
134 : Note that most default C++ types allow default conversions from `Variant` to the corresponding type.
135 : Types that require an explicit call via `toTargetType()` are: complex (float and double), Vector3, and vector<Variant>.
136 : */
137 : class Variant {
138 : public:
139 : enum Type {
140 : TYPE_NONE = 0,
141 : TYPE_BOOL,
142 : TYPE_CHAR,
143 : TYPE_UCHAR,
144 : TYPE_INT16,
145 : TYPE_UINT16,
146 : TYPE_INT32,
147 : TYPE_UINT32,
148 : TYPE_INT64,
149 : TYPE_UINT64,
150 : TYPE_FLOAT,
151 : TYPE_DOUBLE,
152 : TYPE_LONGDOUBLE,
153 : TYPE_COMPLEXF,
154 : TYPE_COMPLEXD,
155 : TYPE_STRING,
156 : TYPE_VECTOR3F,
157 : TYPE_VECTOR3D,
158 : TYPE_VECTOR3C,
159 : TYPE_VECTOR
160 : };
161 :
162 : class bad_conversion: public std::exception {
163 : protected:
164 : std::string msg;
165 : public:
166 0 : const char* what() const throw () {
167 0 : return msg.c_str();
168 : }
169 :
170 0 : bad_conversion(Type f, Type t) {
171 : msg = "Variant: bad conversion from '";
172 0 : msg += Variant::getTypeName(f);
173 : msg += "' to '";
174 0 : msg += Variant::getTypeName(t);
175 : msg += "'";
176 0 : }
177 :
178 0 : ~bad_conversion() throw () {
179 0 : }
180 : };
181 :
182 : typedef std::complex<float> complex_f;
183 : typedef std::complex<double> complex_d;
184 : typedef Vector3<std::complex<double>> Vector3c;
185 : typedef std::vector<Variant> vector_t;
186 :
187 : protected:
188 : Type type;
189 :
190 : union {
191 : bool _t_bool;
192 : char _t_char;
193 : unsigned char _t_uchar;
194 : int16_t _t_int16;
195 : uint16_t _t_uint16;
196 : int32_t _t_int32;
197 : uint32_t _t_uint32;
198 : int64_t _t_int64;
199 : uint64_t _t_uint64;
200 : float _t_float;
201 : double _t_double;
202 : long double _t_ldouble;
203 : complex_f* _t_complex_f;
204 : complex_d* _t_complex_d;
205 : std::string* _t_string;
206 : Vector3f* _t_vector3f;
207 : Vector3d* _t_vector3d;
208 : Vector3c* _t_vector3c;
209 : vector_t* _t_vector;
210 : } data;
211 :
212 :
213 : public:
214 : Variant();
215 : Variant(Type t);
216 : Variant(const Variant& v);
217 : Variant(const char* s);
218 : ~Variant();
219 : inline Type getType() const {
220 2 : return type;
221 : }
222 : const char* getTypeName() const;
223 : static const char* getTypeName(Type t);
224 : const std::type_info& getTypeInfo() const;
225 : static Type toType(const std::string& name);
226 : std::string toString(const std::string& delimiter = "\t") const;
227 : std::complex<float> toComplexFloat() const;
228 : std::complex<double> toComplexDouble() const;
229 : Vector3f toVector3f() const;
230 : Vector3d toVector3d() const;
231 : Vector3c toVector3c() const;
232 : vector_t toVector() const;
233 : static Variant fromString(const std::string& str, Type type);
234 : void clear(Type t = TYPE_NONE);
235 : bool isValid() const;
236 : size_t size() const;
237 : size_t getSizeOf() const;
238 : size_t getSize() const;
239 : void resize(size_t i);
240 : size_t copyToBuffer(void* buffer);
241 1 : operator std::string() const {
242 2 : return toString();
243 : }
244 : Variant& operator=(const Variant& v);
245 : bool operator==(const Variant& v) const;
246 : bool operator!=(const Variant& v) const;
247 : bool operator!=(const char* a) const;
248 : Variant& operator[](size_t i);
249 : inline Variant& operator[](int i) {
250 : return operator[]((size_t) i);
251 : }
252 : const Variant& operator[](size_t i) const;
253 : const Variant& operator[](int i) const {
254 : return operator[]((size_t) i);
255 : }
256 : operator vector_t&();
257 : operator const vector_t&() const;
258 :
259 :
260 : template<class T>
261 : T to() const {
262 : throw bad_conversion(type, TYPE_NONE);
263 : }
264 :
265 : // automatically-generated functions
266 6 : VARIANT_ADD_TYPE_DECL_POD(Bool, TYPE_BOOL, bool, bool)
267 0 : VARIANT_ADD_TYPE_DECL_POD(Char, TYPE_CHAR, char, char)
268 0 : VARIANT_ADD_TYPE_DECL_POD(UChar, TYPE_UCHAR, unsigned char, uchar)
269 0 : VARIANT_ADD_TYPE_DECL_POD(Int16, TYPE_INT16, int16_t, int16)
270 0 : VARIANT_ADD_TYPE_DECL_POD(UInt16, TYPE_UINT16, uint16_t, uint16)
271 12 : VARIANT_ADD_TYPE_DECL_POD(Int32, TYPE_INT32, int32_t, int32)
272 0 : VARIANT_ADD_TYPE_DECL_POD(UInt32, TYPE_UINT32, uint32_t, uint32)
273 6 : VARIANT_ADD_TYPE_DECL_POD(Int64, TYPE_INT64, int64_t, int64)
274 16 : VARIANT_ADD_TYPE_DECL_POD(UInt64, TYPE_UINT64, uint64_t, uint64)
275 0 : VARIANT_ADD_TYPE_DECL_POD(Float, TYPE_FLOAT, float, float)
276 34 : VARIANT_ADD_TYPE_DECL_POD(Double, TYPE_DOUBLE, double, double)
277 0 : VARIANT_ADD_TYPE_DECL_POD(LongDouble, TYPE_LONGDOUBLE, long double, ldouble)
278 0 : VARIANT_ADD_TYPE_DECL_PTR(ComplexFloat, TYPE_COMPLEXF, std::complex<float>, complex_f)
279 1 : VARIANT_ADD_TYPE_DECL_PTR(ComplexDouble, TYPE_COMPLEXD, std::complex<double>, complex_d)
280 3396 : VARIANT_ADD_TYPE_DECL_PTR(String, TYPE_STRING, std::string, string)
281 0 : VARIANT_ADD_TYPE_DECL_PTR(Vector3f, TYPE_VECTOR3F, Vector3f, vector3f)
282 1 : VARIANT_ADD_TYPE_DECL_PTR(Vector3d, TYPE_VECTOR3D, Vector3d, vector3d)
283 1 : VARIANT_ADD_TYPE_DECL_PTR(Vector3c, TYPE_VECTOR3C, Vector3c, vector3c)
284 2 : VARIANT_ADD_TYPE_DECL_PTR(Vector, TYPE_VECTOR, vector_t, vector)
285 : VARIANT_ADD_ITER_DECL_PTR(Vector, TYPE_VECTOR, vector)
286 :
287 : private:
288 : void copy(const Variant& v);
289 : void check(const Type t) const;
290 : void check(const Type t);
291 : };
292 :
293 : #define VARIANT_TO_DECL(NAME, VALUE) \
294 : template<> inline VALUE Variant::to<VALUE>() const { \
295 : return to##NAME(); \
296 : } \
297 :
298 : // declare type conversion functions
299 : // not implemented for Vector3 and complex_*
300 : VARIANT_TO_DECL(Bool, bool)
301 : VARIANT_TO_DECL(Char, char)
302 : VARIANT_TO_DECL(UChar, unsigned char)
303 : VARIANT_TO_DECL(Int16, int16_t)
304 : VARIANT_TO_DECL(UInt16, uint16_t)
305 : VARIANT_TO_DECL(Int32, int32_t)
306 : VARIANT_TO_DECL(UInt32, uint32_t)
307 : VARIANT_TO_DECL(Int64, int64_t)
308 : VARIANT_TO_DECL(UInt64, uint64_t)
309 : VARIANT_TO_DECL(Float, float)
310 : VARIANT_TO_DECL(Double, double)
311 : VARIANT_TO_DECL(LongDouble, long double)
312 : VARIANT_TO_DECL(String, std::string)
313 : VARIANT_TO_DECL(Vector, Variant::vector_t)
314 :
315 : std::ostream& operator <<(std::ostream& os, const Variant &v);
316 :
317 :
318 : /**
319 : Taken from PXL
320 : https://git.rwth-aachen.de/3pia/pxl/pxl/-/blob/master/core/include/pxl/core/Functions.hh
321 : */
322 : template <class T>
323 0 : inline void safeDelete(T*& p) {
324 0 : if (p) {
325 0 : delete p;
326 0 : p = 0;
327 : }
328 0 : }
329 :
330 :
331 :
332 : } // namespace crpropa
333 :
334 : #endif // CRPROPA_VARIANT
|