Itasca C++ Interface
variant.h
Go to the documentation of this file.
1 #pragma once
9 #include "avect.h"
10 #include "basestring.h"
11 #include "type_selector.h"
12 #include "vect.h"
13 #include <cassert>
14 
15 class QDataStream;
16 
25 #ifndef __GNUC__
26 #pragma warning(push)
27 #pragma warning(disable:26450) // Clang overflow warning
28 #pragma warning(disable:26495) // Clang initialize in union
29 #pragma warning(disable:26812) // Non-class enum
30 #pragma warning(disable:26495) // Unitiailized value in a union
31 #endif
32 class Variant {
33  template <class T> friend class VUserType; // need this so that VUserType can access dataSize_
34 private:
35  class UserTypeBase {
36  public:
40  virtual ~UserTypeBase() {}
42  virtual UserTypeBase *clone(char *data) const = 0;
44  virtual void copy(const UserTypeBase *base) = 0;
45  };
46 
47 #ifdef _WIN64
48 # ifdef _DEBUG
49  static const int dataSize_ = 80;
50 # else
51  static const int dataSize_ = 72;
52 # endif
53 #else
54 # ifdef _DEBUG
55  static const int dataSize_ = 40;
56 # else
57  static const int dataSize_ = 36;
58 # endif
59 #endif
60 public:
68  template <typename T> class VUserType;
69 
71  friend BASE_EXPORT QDataStream &operator<<(QDataStream &, const Variant &);
72 
74  enum class Type {
75  Byte = 1,
76  UByte,
77  Short,
78  UShort,
79  Int,
80  UInt,
81  Long,
82  ULong,
83  Float,
84  Double,
85  Void,
86  Bool,
87  IVect2,
88  DVect2,
89  IVect3,
90  DVect3,
91  RawData,
92  String = 100,
93  User
94  };
96  BASE_EXPORT Variant(const Variant &mv) : type_(Type::Int) { operator=(mv); }
99  BASE_EXPORT Variant(const int32 &v = 0) : type_(Type::Int), int_(v) {}
102  BASE_EXPORT Variant(const bool &v) : type_(Type::Bool), bool_(v) {}
103  BASE_EXPORT Variant(const int8 &v) : type_(Type::Byte), byte_(v) {}
104  BASE_EXPORT Variant(const uint8 &v) : type_(Type::UByte), ubyte_(v) {}
105  BASE_EXPORT Variant(const int16 &v) : type_(Type::Short), short_(v) {}
106  BASE_EXPORT Variant(const uint16 &v) : type_(Type::UShort), ushort_(v) {}
107  BASE_EXPORT Variant(const uint32 &v) : type_(Type::UInt), uint_(v) {}
108  BASE_EXPORT Variant(const int64 &v) : type_(Type::Long), long_(v) {}
109  BASE_EXPORT Variant(const uint64 &v) : type_(Type::ULong), ulong_(v) {}
110  BASE_EXPORT Variant(const float &v) : type_(Type::Float), float_(v) {}
111  BASE_EXPORT Variant(const double &v) : type_(Type::Double), double_(v) {}
112  BASE_EXPORT Variant(void *v) : type_(Type::Void), void_(v) {}
113  BASE_EXPORT Variant(const void *v) : type_(Type::Void), void_(const_cast<void *>(v)) {}
114  BASE_EXPORT Variant(const IVect2 &v) : type_(Type::IVect2) { conv<IVect2>() = v; }
115  BASE_EXPORT Variant(const DVect2 &v) : type_(Type::DVect2) { conv<DVect2>() = v; }
116  BASE_EXPORT Variant(const IVect3 &v) : type_(Type::IVect3) { conv<IVect3>() = v; }
117  BASE_EXPORT Variant(const DVect3 &v) : type_(Type::DVect3) { conv<DVect3>() = v; }
118  BASE_EXPORT Variant(const string &v);
119  BASE_EXPORT Variant(const char *v);
121  BASE_EXPORT ~Variant() { del(); }
123  BASE_EXPORT const Variant &operator=(const Variant &mv);
124 
126  BASE_EXPORT Type getType() const { return type_; }
128  BASE_EXPORT string getTypeName() const { return getTypeName(getType()); }
129 
133  BASE_EXPORT bool toBool(bool *success = 0) const;
134  BASE_EXPORT int8 toByte(bool *success = 0) const;
135  BASE_EXPORT uint8 toUByte(bool *success = 0) const;
136  BASE_EXPORT int16 toShort(bool *success = 0) const;
137  BASE_EXPORT uint16 toUShort(bool *success = 0) const;
138  BASE_EXPORT int32 toInt(bool *success = 0) const;
139  BASE_EXPORT uint32 toUInt(bool *success = 0) const;
140  BASE_EXPORT int64 toLong(bool *success = 0) const;
141  BASE_EXPORT uint64 toULong(bool *success = 0) const;
142  BASE_EXPORT float toFloat(bool *success = 0) const;
143  BASE_EXPORT double toDouble(bool *success = 0) const;
144  BASE_EXPORT string toString(bool *success = 0) const;
145  BASE_EXPORT void *toVoid(bool *success = 0) const;
146  BASE_EXPORT IVect2 toIVect2(bool *success = 0) const;
147  BASE_EXPORT DVect2 toDVect2(bool *success = 0) const;
148  BASE_EXPORT IVect3 toIVect3(bool *success = 0) const;
149  BASE_EXPORT DVect3 toDVect3(bool *success = 0) const;
150 
154  BASE_EXPORT const int32 &fastToInt() const { return int_; }
155  BASE_EXPORT const bool &fastToBool() const { return bool_; }
156  BASE_EXPORT const int64 &fastToLong() const { return long_; }
157  BASE_EXPORT const double &fastToDouble() const { return double_; }
158  BASE_EXPORT const DVect2 &fastToDVect2() const { return conv<DVect2>(); }
159  BASE_EXPORT const DVect3 &fastToDVect3() const { return conv<DVect3>(); }
160  BASE_EXPORT const string &fastToString() const;
161 
163  const Variant &operator=(const bool &v) { del(); type_ = Type::Bool; bool_ = v; return *this; }
164  const Variant &operator=(const int8 &v) { del(); type_ = Type::Byte; byte_ = v; return *this; }
165  const Variant &operator=(const uint8 &v) { del(); type_ = Type::UByte; ubyte_ = v; return *this; }
166  const Variant &operator=(const int16 &v) { del(); type_ = Type::Short; short_ = v; return *this; }
167  const Variant &operator=(const uint16 &v) { del(); type_ = Type::UShort; ushort_ = v; return *this; }
168  const Variant &operator=(const int32 &v) { del(); type_ = Type::Int; int_ = v; return *this; }
169  const Variant &operator=(const uint32 &v) { del(); type_ = Type::UInt; uint_ = v; return *this; }
170  const Variant &operator=(const int64 &v) { del(); type_ = Type::Long; long_ = v; return *this; }
171  const Variant &operator=(const uint64 &v) { del(); type_ = Type::ULong; ulong_ = v; return *this; }
172  const Variant &operator=(const float &v) { del(); type_ = Type::Float; float_ = v; return *this; }
173  const Variant &operator=(const double &v) { del(); type_ = Type::Double; double_ = v; return *this; }
174  const Variant &operator=(void *v) { del(); type_ = Type::Void; void_ = v; return *this; }
175  const Variant &operator=(const void *v) { del(); type_ = Type::Void; void_ = const_cast<void *>(v); return *this; }
176  const Variant &operator=(const IVect2 &v) { del(); type_ = Type::IVect2; conv<IVect2>() = v; return *this; }
177  const Variant &operator=(const DVect2 &v) { del(); type_ = Type::DVect2; conv<DVect2>() = v; return *this; }
178  const Variant &operator=(const DAVect2 &v) { del(); type_ = Type::Double; double_ = v.z(); return *this; }
179  const Variant &operator=(const IVect3 &v) { del(); type_ = Type::IVect3; conv<IVect3>() = v; return *this; }
180  const Variant &operator=(const DVect3 &v) { del(); type_ = Type::DVect3; conv<DVect3>() = v; return *this; }
181  BASE_EXPORT const Variant &operator=(const string &v);
182  const Variant &operator=(const char *v) { return operator=(string(v)); }
183 
188  BASE_EXPORT void setToRawData();
193  char *getRawData() { return data_; }
194  const char *getRawData() const { return data_; }
195 
199  template <class T> void setToUserType(const T &t);
200 
204  template <class T> void moveToUserType(T &&t);
205 
208  template <class T> T &convertToUserType();
209 
215  template <class T> T toUserType() const;
220  template <class T> T &fastToUserType() { return conv<VUserType<T> >().value(); }
221  template <class T> const T &fastToUserType() const { return conv<VUserType<T> >().value(); }
226  template <class T> bool isUserType() const { return getType() == VUserType<T>::typeNumber_; }
228  static BASE_EXPORT string getTypeName(Type type);
231  static BASE_EXPORT int getRawDataSize() { return dataSize_; }
234  static BASE_EXPORT bool getUserTypeClaimed(int type);
250  template <class T> static bool registerType(int type, const string &name);
251 
252 private:
253  static const int version_;
254  bool isSpecialType() const { return type_ >= Type::String; }
255 
256  static BASE_EXPORT bool claimUserType(int type, const string &name);
257 
258  template <class T> T &conv() { return *reinterpret_cast<T *>(data_); }
259  template <class T> const T &conv() const { return *reinterpret_cast<const T *>(data_); }
260  void del() { if (isSpecialType()) conv<UserTypeBase>().~UserTypeBase(); }
261 
262  Type type_=Type::Int;
263  union {
264  int8 byte_;
265  uint8 ubyte_;
266  int16 short_;
267  uint16 ushort_;
268  int32 int_;
269  uint32 uint_;
270  int64 long_;
271  uint64 ulong_;
272  float float_;
273  double double_;
274  void * void_;
275  bool bool_;
276  char data_[dataSize_];
277  };
278 };
279 #ifndef __GNUC__
280 #pragma warning(pop)
281 #endif
282 
284 template <> class Variant::VUserType<void *> : public Variant::UserTypeBase {
285 public:
287  VUserType() : t_(nullptr) {}
288  VUserType(void *const t) : t_(t) {}
290  ~VUserType() override {}
292  VUserType<void *> *clone(char *data) const override { return new(data) VUserType<void *>(t_); }
294  void copy(const UserTypeBase *base) override {
295  const VUserType<void *> *p = reinterpret_cast<const VUserType<void *> *>(base);
296  if (!p) return;
297  t_ = p->t_;
298  }
299 
300  static bool isValue() { return true; }
301  void *t_;
302  static int typeNumber_;
303 };
304 
305 template <typename T> class Variant::VUserType : public Variant::UserTypeBase, public itasca::conditional_container<sizeof(T) + sizeof(Variant::VUserType<void *>) - sizeof(void *) <= Variant::dataSize_, T> {
306 public:
308  VUserType(const T &t = T()) : itasca::conditional_container<sizeof(T) + sizeof(VUserType<void *>) - sizeof(void *) <= Variant::dataSize_, T>(t) {};
310  VUserType(T &&t) : itasca::conditional_container<sizeof(T) + sizeof(VUserType<void *>) - sizeof(void *) <= Variant::dataSize_, T>(std::move(t)) {};
312  ~VUserType() override {}
314  VUserType<T> *clone(char *data) const override { return new(data) VUserType<T>(this->value()); }
316  void copy(const UserTypeBase *base) override {
317  const VUserType<T> *p = reinterpret_cast<const VUserType<T> *>(base);
318  if (!p) return;
319  operator=(*p);
320  }
321 
322  static int typeNumber_;
323 };
324 
325 
326 template <class T> inline void Variant::setToUserType(const T &t) {
327  if (getType() != VUserType<T>::typeNumber_) {
328  del();
329  new(data_) VUserType<T>(t);
330  type_ = static_cast<Type>(VUserType<T>::typeNumber_);
331  return;
332  }
333  conv<VUserType<T>>() = t;
334 }
335 
336 template <class T> inline void Variant::moveToUserType(T &&t) {
337  if (getType() != VUserType<T>::typeNumber_) {
338  del();
339  new(data_) VUserType<T>(std::move(t));
340  type_ = static_cast<Type>(VUserType<T>::typeNumber_);
341  return;
342  }
343  conv<VUserType<T>>() = std::move(t);
344 }
345 
346 template <class T> inline T Variant::toUserType() const {
347  if (getType() != VUserType<T>::typeNumber_)
348  return T();
349  return conv<VUserType<T>>().VUserType<T>::value();
350 }
351 
352 template <class T> T &Variant::convertToUserType() {
353  if (getType() != VUserType<T>::typeNumber_) {
354  del();
355  new(data_) VUserType<T>();
356  type_ = static_cast<Type>(VUserType<T>::typeNumber_);
357  }
358  VUserType<T> &v = conv<VUserType<T>>();
359  return v.value();
360 }
361 
362 template <class T> bool Variant::registerType(int typeNumber, const string &name) {
363  //if ( sizeof(VUserType<T>) > dataSize_ ) { throw std::exception("ERROR: Type too large for variant."); }
364  static_assert(sizeof(VUserType<T>) <= dataSize_, "ERROR: Type too large for variant.");
365  if (!claimUserType(typeNumber, name)) return false;
366  VUserType<T>::typeNumber_ = typeNumber;
367  return true;
368 }
370 
371 // EOF
Angular Vectors.
QString helper functions, plus some additions.
Template specialization for void pointers; this should probably never be used, except to determine th...
Definition: variant.h:284
This is a helper class, designed to make it possible to allow user-defined types to be encoded in a V...
Definition: variant.h:68
A simpler (and slightly faster) version of a QVariant, added for interfaces that do not use Qt.
Definition: variant.h:32
A container, which either stores its value as a value or a pointer depending on the condition.
Definition: type_selector.h:59
static bool registerType(int type, const string &name)
This method allows user-defined types to be encoded in a variant.
BASE_EXPORT Variant(const IVect3 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:116
BASE_EXPORT void * toVoid(bool *success=0) const
Definition: variant.cpp:372
BASE_EXPORT Variant(const int16 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:105
BASE_EXPORT Variant(const IVect2 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:114
BASE_EXPORT int32 toInt(bool *success=0) const
Definition: variant.cpp:219
BASE_EXPORT string getTypeName() const
A string indicating the Variant type.
Definition: variant.h:128
BASE_EXPORT const bool & fastToBool() const
Definition: variant.h:155
BASE_EXPORT int16 toShort(bool *success=0) const
Definition: variant.cpp:177
const Variant & operator=(const uint16 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:167
BASE_EXPORT Variant(const DVect2 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:115
BASE_EXPORT double toDouble(bool *success=0) const
Definition: variant.cpp:324
BASE_EXPORT ~Variant()
Destructor.
Definition: variant.h:121
const Variant & operator=(const bool &v)
Assignment operator for a specific type, converts the Variant to the same type and value.
Definition: variant.h:163
BASE_EXPORT const int32 & fastToInt() const
Definition: variant.h:154
static bool isValue()
Checks if the user type holds the literal value of T, or a pointer to it.
Definition: variant.h:300
const Variant & operator=(const DAVect2 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:178
const char * getRawData() const
Definition: variant.h:194
BASE_EXPORT const Variant & operator=(const Variant &mv)
Equality operator.
Definition: variant.cpp:73
~VUserType() override
Destructor.
Definition: variant.h:290
BASE_EXPORT uint8 toUByte(bool *success=0) const
Definition: variant.cpp:155
BASE_EXPORT Variant(const uint16 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:106
BASE_EXPORT IVect3 toIVect3(bool *success=0) const
Definition: variant.cpp:408
const Variant & operator=(const int32 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:168
BASE_EXPORT float toFloat(bool *success=0) const
Definition: variant.cpp:303
const Variant & operator=(const DVect2 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:177
const Variant & operator=(const double &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:173
BASE_EXPORT Variant(const Variant &mv)
Copy constructor.
Definition: variant.h:96
const Variant & operator=(const IVect3 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:179
const Variant & operator=(const float &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:172
BASE_EXPORT Variant(const bool &v)
Definition: variant.h:102
const Variant & operator=(void *v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:174
BASE_EXPORT Variant(const uint8 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:104
void setToUserType(const T &t)
BASE_EXPORT Variant(const int32 &v=0)
Definition: variant.h:99
bool isUserType() const
Definition: variant.h:226
UserTypeBase()
Default constructor, no data initialization.
Definition: variant.h:38
BASE_EXPORT uint64 toULong(bool *success=0) const
Definition: variant.cpp:282
VUserType< void * > * clone(char *data) const override
in-place clone
Definition: variant.h:292
virtual UserTypeBase * clone(char *data) const =0
Clone function.
BASE_EXPORT Variant(const uint64 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:109
virtual void copy(const UserTypeBase *base)=0
Copy from base pointer.
const Variant & operator=(const IVect2 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:176
T & convertToUserType()
static int typeNumber_
The typeNumber_ used to uniquely identify the type.
Definition: variant.h:302
BASE_EXPORT int8 toByte(bool *success=0) const
Definition: variant.cpp:134
BASE_EXPORT const double & fastToDouble() const
Definition: variant.h:157
const Variant & operator=(const int16 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:166
T toUserType() const
BASE_EXPORT Variant(const int64 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:108
void copy(const UserTypeBase *base) override
copy from base pointer, uses reinterpret_cast to upcast (careful!).
Definition: variant.h:294
BASE_EXPORT Variant(const int8 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:103
#define BASE_EXPORT
Definition: basedef.h:24
void moveToUserType(T &&t)
const Variant & operator=(const int64 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:170
BASE_EXPORT uint16 toUShort(bool *success=0) const
Definition: variant.cpp:198
BASE_EXPORT bool toBool(bool *success=0) const
Definition: variant.cpp:105
BASE_EXPORT Variant(void *v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:112
BASE_EXPORT string toString(bool *success=0) const
Definition: variant.cpp:345
BASE_EXPORT void setToRawData()
Definition: variant.cpp:444
const Variant & operator=(const uint8 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:165
friend BASE_EXPORT QDataStream & operator<<(QDataStream &, const Variant &)
Allows writing a Variant to a QDataStream.
Definition: basetoqt.cpp:195
void * t_
The actual value being stored.
Definition: variant.h:301
BASE_EXPORT const int64 & fastToLong() const
Definition: variant.h:156
const T & fastToUserType() const
Definition: variant.h:221
const Variant & operator=(const uint32 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:169
BASE_EXPORT Type getType() const
The type of the Variant. Note that this may be a user-defined value.
Definition: variant.h:126
T & fastToUserType()
Definition: variant.h:220
const Variant & operator=(const DVect3 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:180
const Variant & operator=(const int8 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:164
BASE_EXPORT int64 toLong(bool *success=0) const
Definition: variant.cpp:261
static BASE_EXPORT bool getUserTypeClaimed(int type)
Definition: variant.cpp:480
BASE_EXPORT DVect3 toDVect3(bool *success=0) const
Definition: variant.cpp:421
BASE_EXPORT const DVect3 & fastToDVect3() const
Definition: variant.h:159
BASE_EXPORT Variant(const float &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:110
BASE_EXPORT Variant(const DVect3 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:117
const Variant & operator=(const uint64 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:171
BASE_EXPORT const string & fastToString() const
Definition: variant.cpp:69
static BASE_EXPORT int getRawDataSize()
Definition: variant.h:231
BASE_EXPORT IVect2 toIVect2(bool *success=0) const
Definition: variant.cpp:382
BASE_EXPORT Variant(const uint32 &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:107
VUserType()
Default constructor.
Definition: variant.h:287
BASE_EXPORT DVect2 toDVect2(bool *success=0) const
Definition: variant.cpp:395
const Variant & operator=(const char *v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:182
BASE_EXPORT Variant(const double &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:111
char * getRawData()
Definition: variant.h:193
BASE_EXPORT Variant(const void *v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:113
virtual ~UserTypeBase()
Deconstructor.
Definition: variant.h:40
BASE_EXPORT const DVect2 & fastToDVect2() const
Definition: variant.h:158
BASE_EXPORT uint32 toUInt(bool *success=0) const
Definition: variant.cpp:240
Type
Indicates the type of the variant. 18 types are predefined.
Definition: variant.h:74
const Variant & operator=(const void *v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: variant.h:175
@ UInt
unsigned 32 bit integer.
@ Int
signed 32 bit integer.
@ Float
32 bit floating point value.
@ String
A String() class.
@ Short
signed 16 bit integer.
@ ULong
unsigned 64 bit integer.
@ UByte
unsigned 8 bit integer.
@ DVect2
A 2D vector of 64 bit floating point values.
@ Void
A void pointer.
@ Long
signed 64 bit integer.
@ User
A user-defined type. See the Variant::registerType() method.
@ Byte
signed 8 bit integer.
@ IVect3
A 3D vector of 32 bit signed integers.
@ DVect3
A 3D vector of 64 bit floating point values.
@ IVect2
A 2D vector of 32 bit signed integers.
@ Bool
A value of type bool.
@ RawData
Raw binary data – see the Variant::setToRawData() and Variant::getRawData() methods.
@ Double
64 bit floating point value.
@ UShort
unsigned 16 bit integer.
2D and 3D vector utility classes.