Gorgon Game Engine
Any.h
Go to the documentation of this file.
1 
5 
6 #pragma once
7 
8 #include <cstring>
9 #include <cstdlib>
10 #include <stdexcept>
11 #include <typeinfo>
12 #include <algorithm>
13 #include <typeinfo>
14 #include "Utils/Assert.h"
15 #include "TMP.h"
16 
17 
18 
19 namespace Gorgon {
20 
32  class Any {
33  public:
36  Any() : content(nullptr),type(nullptr) { }
37 
40  Any(const TMP::RTTS &typeinterface, void *data) {
41  type=typeinterface.Duplicate();
42  content=type->Clone(data);
43  }
44 
48  Any(void *data, const TMP::RTTS &typeinterface) {
49  type=typeinterface.Duplicate();
50  content=type->Clone(data);
51  }
52 
56  template <class T_>
57  Any(const T_ &data) {
58  using Type = typename std::decay<T_>::type;
59  static_assert(!std::is_same<typename std::decay<typename std::remove_reference<T_>::type>::type, Any>::value,
60  "Something is wrong in here");
61 
62  type=new TMP::RTT<Type>;
63  content=type->Clone(&data);
64  }
65 
68  Any(const Any &any) {
69  if(any.content) {
70  type=any.type->Duplicate();
71  content=type->Clone(any.content);
72  }
73  else {
74  content=nullptr;
75  type=nullptr;
76  }
77  }
78 
79 
82  Any(Any &&any) : content(nullptr), type(nullptr) {
83  Swap(any);
84  }
85 
87  TMP::RTTI &TypeInfo() const {
88  ASSERT(type, "Any is not set");
89 
90  return *type;
91  }
92 
95  return type;
96  }
97 
98 
101  Any &operator =(const Any &any) {
102  Clear();
103 
104  if(any.type) {
105  type=any.type->Duplicate();
106  content=type->Clone(any.content);
107  }
108  else {
109  type=nullptr;
110  content=nullptr;
111  }
112 
113  return *this;
114  }
115 
119  Any &operator =(Any &&any) {
120  Clear();
121 
122  Swap(any);
123 
124  return *this;
125  }
126 
129  template<class T_>
130  Any &operator =(const T_ &value) {
131  static_assert(!std::is_same<typename std::decay<typename std::remove_reference<T_>::type>::type, Any>::value,
132  "Something is wrong in here");
133  Set(value);
134 
135  return *this;
136  }
137 
138 
141  void Swap(Any &other) {
142  using std::swap;
143 
144  swap(type, other.type);
145  swap(content, other.content);
146  }
147 
150  template <class T_>
151  void Set(const T_ &data) {
152  Clear();
153 
154  using Type = typename std::decay<T_>::type;
155 
156  type=new TMP::RTT<Type>;
157  content=type->Clone(&data);
158  }
159 
162  template <class T_>
163  void Set(T_ &&data) {
164  Clear();
165 
166 
167  using Type = typename std::decay<T_>::type;
168 
169  type=new TMP::RTT<Type>;
170  Type *n=new Type(std::move(data));
171  content=n;
172  }
173 
174 
176  void Clear() {
177  if(content) {
178  type->Delete(content);
179  delete type;
180  type=nullptr;
181  content=nullptr;
182  }
183  }
184 
187  void *GetRaw() const {
188  return content;
189  }
190 
194  void SetRaw(void *data) {
195  if(content) type->Delete(content);
196 
197  content=type->Clone(data);
198  }
199 
203  void SetRaw(TMP::RTTS *type, void *data) {
204  Clear();
205 
206  this->type=type->Duplicate();
207  content=type->Clone(data);
208  }
209 
214  template<class T_>
215  void Set(const T_ &data, TMP::RTTS *type) {
216  Clear();
217 
218  this->type=type->Duplicate();
219  content=type->Clone(&data);
220  }
221 
225  void AssumeRaw(TMP::RTTS &type, void *data) {
226  Clear();
227 
228  this->type=type.Duplicate();
229  content=data;
230  }
231 
234  void *Disown() {
235  auto ret=content;
236 
237  delete type;
238  type=nullptr;
239  content=nullptr;
240 
241  return ret;
242  }
243 
246  void SetType(const TMP::RTTS &type) {
247  if(this->type) delete this->type;
248  this->type=type.Duplicate();
249  }
250 
257  template <class T_>
258  T_ &Get() {
259 #ifndef GORGON_FAST_ANY
260  if(!type || !content) {
261  throw std::runtime_error("Any storage is empty");
262  }
263 
264  ASSERT(type->IsSameType(typeid(T_)),
265  "Type mismatch, orginal: "+type->Name()+", target: "+Utils::GetTypeName<T_>()
266  );
267 #endif
268 
269  return *static_cast<T_*>(content);
270  }
271 
272  std::string GetTypeName() const {
273  if(!type) return "";
274 
275  return Utils::demangle(type->TypeInfo().name());
276  }
277 
284  template <class T_>
285  const T_ &Get() const {
286 #ifndef GORGON_FAST_ANY
287  if(!type || !content) {
288  throw std::runtime_error("Any storage is empty");
289  }
290 
291  ASSERT(type->IsSameType(typeid(T_)),
292  "Type mismatch, orginal: "+type->Name()+", target: "+Utils::GetTypeName<T_>()
293  );
294 #endif
295 
296  return *static_cast<T_*>(content);
297  }
298 
299 
304  template <class T_>
305  T_ UnsafeGet() const {
306 #ifndef GORGON_FAST_ANY
307  if(!type || !content) {
308  throw std::runtime_error("Any storage is empty");
309  }
310 #endif
311 
312  return *static_cast<T_*>(content);
313  }
314 
316  template <class T_>
317  bool TypeCheck() const {
318  return type->IsSameType(typeid(T_));
319  }
320 
322  bool IsSameType(const Any &other) const {
323  return type->IsSameType(other.type->TypeInfo());
324  }
325 
327  bool IsPointer() const {
328  return type->IsPointer();
329  }
330 
332  void *Pointer() const {
333  return *reinterpret_cast<void**>(content);
334  }
335 
336 
343  template <class T_>
344  bool operator ==(const T_ &content) const {
345 #ifndef GORGON_FAST_ANY
346  if(!type || !this->content) {
347  throw std::runtime_error("Any storage is empty");
348  }
349 
350  ASSERT(type->IsSameType(typeid(T_)),
351  "Type mismatch, orginal: "+type->Name()+", target: "+Utils::GetTypeName<T_>()
352  );
353 #endif
354 
355  return *static_cast<T_*>(this->content)==content;
356  }
357 
361  bool operator ==(const Any &content) const {
362  if(!content.content && !this->content) {
363  return true;
364  }
365  else if(!content.content || !this->content) {
366  return false;
367  }
368 
369 #ifndef GORGON_FAST_ANY
370  ASSERT(type->TypeInfo() != content.type->TypeInfo(),
371  "Type mismatch, left: "+type->Name()+", right: "+content.type->Name()
372  );
373 #endif
374 
375  return memcmp(this->content, content.content, type->GetSize())==0;
376  }
377 
384  template <class T_>
385  bool operator !=(const T_ &content) const {
386  return !operator==(content);
387  }
388 
392  bool operator !=(const Any &content) const {
393  return !operator==(content);
394  }
395 
398  bool IsSet() const {
399  return content!=nullptr;
400  }
401 
404  ~Any() {
405  Clear();
406  }
407 
408  protected:
411  void *content;
415  };
416 
417 
419  struct CopyFreeAny {
420  virtual ~CopyFreeAny() {}
421 
422  template<class T_>
423  T_ &GetData() const {
424  return *reinterpret_cast<T_*>(data);
425  }
426 
427  void *data;
428  };
429 
430  template<class T_>
431  struct CopyFreeAny_impl : public CopyFreeAny {
432  CopyFreeAny_impl(T_ data) : mydata(std::move(data)) {
433  this->data = &mydata;
434  }
435 
436  CopyFreeAny_impl(const CopyFreeAny_impl &) = delete;
437 
438  CopyFreeAny_impl(CopyFreeAny_impl &&other) {
439  mydata = std::move(other.data);
440  }
441 
442  CopyFreeAny_impl &operator =(CopyFreeAny_impl &&other) {
443  mydata = std::move(other.data);
444 
445  return *this;
446  }
447 
448  CopyFreeAny_impl &operator =(const CopyFreeAny_impl &other) = delete;
449 
450  virtual ~CopyFreeAny_impl() {}
451 
452  T_ mydata;
453  };
454 
456  template<class T_>
457  CopyFreeAny &MakeCopyFreeAny(T_ data) {
458  return *new CopyFreeAny_impl<T_>(std::move(data));
459  }
461 
462 
463 }
Gorgon::swap
void swap(Event< Source_, Args_... > &l, Event< Source_, Args_... > &r)
Swaps two events.
Definition: Event.h:351
Gorgon::Any::Swap
void Swap(Any &other)
Swaps the contents of the current any with another.
Definition: Any.h:141
Gorgon::Any::Any
Any(const TMP::RTTS &typeinterface, void *data)
Unsafe! Constructs any from give raw data.
Definition: Any.h:40
Gorgon::Any::content
void * content
Data stored in this any.
Definition: Any.h:411
Gorgon::Any::operator!=
bool operator!=(const T_ &content) const
Compares the contents of this Any to the given value.
Definition: Any.h:385
Gorgon::TMP::RTT
Runtime Type. This class implements both RTTS and RTTI.
Definition: TMP.h:210
Gorgon::Any::GetRaw
void * GetRaw() const
Unsafe! This function returns raw data contained within any.
Definition: Any.h:187
Gorgon::Any
This class can hold any other information providing type erasure.
Definition: Any.h:32
Gorgon::Any::Any
Any()
Default constructor.
Definition: Any.h:36
Gorgon::Any::Any
Any(Any &&any)
Move constructor.
Definition: Any.h:82
Gorgon::Any::Any
Any(const T_ &data)
Creates a new Any from the given data.
Definition: Any.h:57
Gorgon::Any::UnsafeGet
T_ UnsafeGet() const
Unsafe version of Get.
Definition: Any.h:305
Gorgon::Any::SetRaw
void SetRaw(void *data)
Unsafe! This function sets the raw data contained within any, without modifying its type data.
Definition: Any.h:194
TMP.h
This file contains template metaprogramming methods and classes used throughout Gorgon Library.
Gorgon::Any::Disown
void * Disown()
Unsafe! Disowns the data contained in this any.
Definition: Any.h:234
Gorgon::TMP::RTTI::GetSize
virtual long GetSize() const =0
Returns the size of the object.
Gorgon::TMP::RTTI::TypeInfo
virtual const std::type_info & TypeInfo() const =0
Gorgon::TMP::RTTI::IsPointer
virtual bool IsPointer() const =0
Returns if this type is pointer.
Gorgon::Any::SetType
void SetType(const TMP::RTTS &type)
Unsafe! This function modifies type information of the data content.
Definition: Any.h:246
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Any::~Any
~Any()
Destructor.
Definition: Any.h:404
Gorgon::Any::operator==
bool operator==(const T_ &content) const
Compares the contents of this Any to the given value.
Definition: Any.h:344
Gorgon::Any::type
TMP::RTTS * type
Type of the data stored.
Definition: Any.h:414
Gorgon::Any::Clear
void Clear()
Clears the content of the any.
Definition: Any.h:176
Gorgon::Any::IsSameType
bool IsSameType(const Any &other) const
Checks whether the Any is the same type with the given type.
Definition: Any.h:322
ASSERT
#define ASSERT(expression, message,...)
Replaces regular assert to allow messages and backtrace.
Definition: Assert.h:161
Gorgon::Any::TypeInfo
TMP::RTTI & TypeInfo() const
Returns TypeInfo used by current data.
Definition: Any.h:87
Gorgon::TMP::RTTS::Delete
virtual void Delete(void *obj) const =0
Deletes the given object.
Gorgon::Any::IsPointer
bool IsPointer() const
Checks if any contains a pointer.
Definition: Any.h:327
Gorgon::Any::Set
void Set(T_ &&data)
Set the content of the Any to the given value.
Definition: Any.h:163
Gorgon::TMP::RTTS
This class contains runtime type services that allows dealing with unknown type.
Definition: TMP.h:190
Gorgon::Any::Get
const T_ & Get() const
Returns the value contained with this any.
Definition: Any.h:285
Gorgon::Any::Set
void Set(const T_ &data)
Set the content of the Any to the given value.
Definition: Any.h:151
Gorgon::TMP::RTTI
This class contains information about a runtime type.
Definition: TMP.h:143
Gorgon::TMP::RTTS::Duplicate
virtual RTTS * Duplicate() const =0
Duplicates this service.
Gorgon::Any::Set
void Set(const T_ &data, TMP::RTTS *type)
Unsafe! This function sets the data contained within any with regular means.
Definition: Any.h:215
Gorgon::TMP::RTTS::Clone
virtual void * Clone(const void *const obj) const =0
Clones the given object.
Gorgon::TMP::RTTI::Name
std::string Name() const
Returns human readable name of the type.
Definition: TMP.h:184
Gorgon::GL::UBOBindingPoint::Type
Type
Definition: Shader.h:14
Gorgon::Any::Pointer
void * Pointer() const
Returns the pointer without type information.
Definition: Any.h:332
Gorgon::TMP::RTTI::IsSameType
virtual bool IsSameType(const std::type_info &) const =0
Compares the type stored with this service to the given type info.
Gorgon::Any::AssumeRaw
void AssumeRaw(TMP::RTTS &type, void *data)
Unsafe! This function sets the raw data contained within any, while modifying its type data.
Definition: Any.h:225
Gorgon::Any::SetRaw
void SetRaw(TMP::RTTS *type, void *data)
Unsafe! This function sets the raw data contained within any, while modifying its type data.
Definition: Any.h:203
Gorgon::Any::Any
Any(const Any &any)
Copy constructor.
Definition: Any.h:68
Gorgon::Any::TypeCheck
bool TypeCheck() const
Checks whether the Any is the same type with the given type.
Definition: Any.h:317
Gorgon::Any::Get
T_ & Get()
Returns the value contained with this any.
Definition: Any.h:258
Gorgon::Any::operator=
Any & operator=(const Any &any)
Copies the information in the given Any.
Definition: Any.h:101
Gorgon::Any::IsSet
bool IsSet() const
Checks whether the Any is set.
Definition: Any.h:398
Gorgon::Any::GetTypeName
std::string GetTypeName() const
Definition: Any.h:272
Gorgon::Any::Any
Any(void *data, const TMP::RTTS &typeinterface)
Unsafe! Constructs any from give raw data.
Definition: Any.h:48
Gorgon::Utils::demangle
std::string demangle(const std::string &name)
Definition: Compiler_GCC.cpp:8
Gorgon::Any::TypeServices
TMP::RTTS * TypeServices() const
Returns TypeInterface used by this any.
Definition: Any.h:94
Assert.h