REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestReflector.h
1 #ifndef RestTools_REST_Reflection
2 #define RestTools_REST_Reflection
3 
4 #include <TFormula.h>
5 #include <TVector2.h>
6 #include <TVector3.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #include <algorithm>
11 #include <cstdio>
12 #include <cstring>
13 #include <fstream>
14 #include <iomanip>
15 #include <iostream>
16 #include <sstream>
17 
18 #include "Strlen.h"
19 #include "TBuffer.h"
20 #include "TBufferFile.h"
21 #include "TClass.h"
22 #include "TClassEdit.h"
23 #include "TDataMember.h"
24 #include "TDataType.h"
25 #include "TRestStringHelper.h"
26 #include "TStreamerElement.h"
27 #include "TVirtualStreamerInfo.h"
28 
29 class TRestEventProcess;
30 
32 namespace REST_Reflection {
33 
34 struct DataType_Info {
35  char name[20]{'u', 'n', 'k', 'n', 'o', 'w', 'n', 0};
36  Int_t size = 0;
37  const std::type_info* typeinfo = 0;
38 
39  DataType_Info() {}
40 
41  DataType_Info(std::string name) {
42  switch (ToHash(name)) {
43  case ToHash("char"):
44  typeinfo = &typeid(char);
45  size = sizeof(char);
46  break;
47  case ToHash("short"):
48  typeinfo = &typeid(short);
49  size = sizeof(short);
50  break;
51  case ToHash("int"):
52  typeinfo = &typeid(int);
53  size = sizeof(int);
54  break;
55  case ToHash("long"):
56  typeinfo = &typeid(long);
57  size = sizeof(long);
58  break;
59  case ToHash("long int"):
60  typeinfo = &typeid(long int);
61  size = sizeof(long int);
62  break;
63  case ToHash("long long"):
64  typeinfo = &typeid(long long);
65  size = sizeof(long long);
66  break;
67  case ToHash("bool"):
68  typeinfo = &typeid(bool);
69  size = sizeof(bool);
70  break;
71  case ToHash("float"):
72  typeinfo = &typeid(float);
73  size = sizeof(float);
74  break;
75  case ToHash("double"):
76  typeinfo = &typeid(double);
77  size = sizeof(double);
78  break;
79  case ToHash("long double"):
80  typeinfo = &typeid(long double);
81  size = sizeof(long double);
82  break;
83  case ToHash("unsigned char"):
84  typeinfo = &typeid(unsigned char);
85  size = sizeof(unsigned char);
86  break;
87  case ToHash("unsigned short"):
88  typeinfo = &typeid(unsigned short);
89  size = sizeof(unsigned short);
90  break;
91  case ToHash("unsigned int"):
92  typeinfo = &typeid(unsigned int);
93  size = sizeof(unsigned int);
94  break;
95  case ToHash("unsigned long"):
96  typeinfo = &typeid(unsigned long);
97  size = sizeof(unsigned long);
98  break;
99  case ToHash("unsigned long long"):
100  typeinfo = &typeid(unsigned long long);
101  size = sizeof(unsigned long long);
102  break;
103  case ToHash("unsigned long int"):
104  typeinfo = &typeid(unsigned long int);
105  size = sizeof(unsigned long int);
106  break;
107  case ToHash("char*"):
108  typeinfo = &typeid(char*);
109  size = sizeof(char*);
110  break;
111  case ToHash("size_t"):
112  typeinfo = &typeid(size_t);
113  size = sizeof(char*);
114  break;
115  // we also add some name of ROOT data types
116  case ToHash("Char_t"):
117  typeinfo = &typeid(Char_t);
118  size = sizeof(Char_t);
119  break;
120  case ToHash("UChar_t"):
121  typeinfo = &typeid(UChar_t);
122  size = sizeof(UChar_t);
123  break;
124  case ToHash("Short_t"):
125  typeinfo = &typeid(Short_t);
126  size = sizeof(Short_t);
127  break;
128  case ToHash("Int_t"):
129  typeinfo = &typeid(Int_t);
130  size = sizeof(Int_t);
131  break;
132  case ToHash("UInt_t"):
133  typeinfo = &typeid(UInt_t);
134  size = sizeof(UInt_t);
135  break;
136  case ToHash("Long_t"):
137  typeinfo = &typeid(Long_t);
138  size = sizeof(Long_t);
139  break;
140  case ToHash("ULong_t"):
141  typeinfo = &typeid(ULong_t);
142  size = sizeof(ULong_t);
143  break;
144  case ToHash("Long64_t"):
145  typeinfo = &typeid(Long64_t);
146  size = sizeof(Long64_t);
147  break;
148  case ToHash("ULong64_t"):
149  typeinfo = &typeid(ULong64_t);
150  size = sizeof(ULong64_t);
151  break;
152  case ToHash("Float_t"):
153  typeinfo = &typeid(Float_t);
154  size = sizeof(Float_t);
155  break;
156  case ToHash("Float16_t"):
157  typeinfo = &typeid(Float16_t);
158  size = sizeof(Float16_t);
159  break;
160  case ToHash("Double_t"):
161  typeinfo = &typeid(Double_t);
162  size = sizeof(Double_t);
163  break;
164  case ToHash("Double32_t"):
165  typeinfo = &typeid(Double32_t);
166  size = sizeof(Double32_t);
167  break;
168  case ToHash("LongDouble_t"):
169  typeinfo = &typeid(LongDouble_t);
170  size = sizeof(LongDouble_t);
171  break;
172  case ToHash("Bool_t"):
173  typeinfo = &typeid(Bool_t);
174  size = sizeof(Bool_t);
175  break;
176  default:
177  break;
178  }
179  if (typeinfo != 0) {
180  strcpy(this->name, name.c_str());
181  }
182  }
183 
184  template <typename T>
185  DataType_Info(T* obj) {
186  std::string name = "";
187  if (typeid(T) == typeid(char)) {
188  name = "char";
189  } else if (typeid(T) == typeid(short)) {
190  name = "short";
191  } else if (typeid(T) == typeid(int)) {
192  name = "int";
193  } else if (typeid(T) == typeid(long)) {
194  name = "long";
195  } else if (typeid(T) == typeid(long int)) {
196  name = "long int";
197  } else if (typeid(T) == typeid(long long)) {
198  name = "long long";
199  } else if (typeid(T) == typeid(bool)) {
200  name = "bool";
201  } else if (typeid(T) == typeid(float)) {
202  name = "float";
203  } else if (typeid(T) == typeid(double)) {
204  name = "double";
205  } else if (typeid(T) == typeid(long double)) {
206  name = "long double";
207  } else if (typeid(T) == typeid(unsigned char)) {
208  name = "unsigned char";
209  } else if (typeid(T) == typeid(unsigned short)) {
210  name = "unsigned short";
211  } else if (typeid(T) == typeid(unsigned int)) {
212  name = "unsigned int";
213  } else if (typeid(T) == typeid(unsigned long)) {
214  name = "unsigned long";
215  } else if (typeid(T) == typeid(unsigned long long)) {
216  name = "unsigned long long";
217  } else if (typeid(T) == typeid(unsigned long int)) {
218  name = "unsigned long int";
219  } else if (typeid(T) == typeid(char*)) {
220  name = "char*";
221  }
222 
223  if (name != "") {
224  strcpy(this->name, name.c_str());
225  size = sizeof(T);
226  typeinfo = &typeid(T);
227  }
228  }
229 };
230 
231 EXTERN_DEF std::map<void*, TClass*> RESTListOfClasses_typeid;
232 EXTERN_DEF std::map<std::string, TClass*> RESTListOfClasses_typename;
233 
239 inline TClass* GetClassQuick(std::string type) {
240  auto iter = RESTListOfClasses_typename.find(type);
241  if (iter != RESTListOfClasses_typename.end()) {
242  return iter->second;
243  } else {
244  TClass* cl = TClass::GetClass(type.c_str());
245  RESTListOfClasses_typename[type] = cl;
246  return cl;
247  }
248  return nullptr;
249 }
250 
257 template <typename T>
258 TClass* GetClassQuick() {
259  void* typeidaddr = (void*)&typeid(T);
260  auto iter = RESTListOfClasses_typeid.find(typeidaddr);
261  if (iter != RESTListOfClasses_typeid.end()) {
262  return iter->second;
263  } else {
264  TClass* cl = TClass::GetClass(typeid(T));
265  RESTListOfClasses_typeid[typeidaddr] = cl;
266  return cl;
267  }
268  return nullptr;
269 }
270 
272 template <typename T>
273 std::string GetTypeName() {
274  TClass* cl = TClass::GetClass(typeid(T));
275  if (cl != nullptr) {
276  return cl->GetName();
277  }
278  return std::string(DataType_Info((T*)0).name);
279 }
281 template <class T>
282 std::string GetTypeName(T obj) {
283  return GetTypeName<T>();
284 }
285 
287  private:
289  int InitDictionary();
291  bool onheap = false;
292 
293  public:
295  std::string name = "";
297  std::string type = "";
299  const std::type_info* typeinfo = 0;
301  char* address = 0;
303  int size = 0;
305  TClass* cl = 0;
307  bool is_data_type = false;
309  bool IsZombie() const;
311  void operator>>(const TRestReflector& to);
313  friend std::ostream& operator<<(std::ostream& cin, TRestReflector ptr) { return cin << ptr.ToString(); }
315  template <typename T>
316  T GetValue() {
317  if (typeid(T) != *this->typeinfo) {
318  std::cout << "In TRestReflector::GetValue() : type unmatch! " << std::endl;
319  std::cout << "Input: " << GetTypeName<T>() << ", this: " << this->type << std::endl;
320  return T();
321  }
322  if (address != nullptr) return *(T*)(address);
323  return T();
324  }
326  template <class T>
327  void SetValue(const T& val) {
328  if (typeid(T) != *this->typeinfo) {
329  std::cout << "In TRestReflector::SetValue() : type unmatch! " << std::endl;
330  std::cout << "Input: " << GetTypeName<T>() << ", this: " << std::string(this->type) << std::endl;
331  return;
332  }
333  if (address != nullptr) *((T*)(address)) = val;
334  }
336  std::string ToString() const;
338  void ParseString(const std::string& str) const;
340  void Assembly();
342  void Destroy() const;
344  void PrintMemory(int bytepreline = 16);
346  TRestReflector GetDataMember(const std::string& name);
350  std::vector<std::string> GetListOfDataMembers() const;
352  std::string GetDataMemberValueString(const std::string& name);
354  int GetNumberOfDataMembers() const;
355 
359  template <class T>
360  operator T*() {
361  return (T*)address;
362  }
366  TRestReflector(void* address, const std::string& type);
368  template <class T>
369  TRestReflector(const T& obj) {
370  address = (char*)&obj;
371  InitFromTemplate<T>();
372  }
374  template <class T>
375  TRestReflector(T* obj) {
376  address = (char*)obj;
377  InitFromTemplate<T>();
378  }
379 
380  template <class T>
381  void InitFromTemplate() {
382  onheap = false;
383  cl = REST_Reflection::GetClassQuick<T>();
384  DataType_Info dt = DataType_Info((T*)0);
385  if (cl == nullptr && dt.size == 0) {
386  std::cout << "In TRestReflector::TRestReflector() : unrecognized type! " << std::endl;
387  return;
388  }
389 
390  typeinfo = &typeid(T);
391  is_data_type = dt.size > 0;
392  size = sizeof(T);
393  if (cl == nullptr) {
394  type = dt.name;
395  } else {
396  type = cl->GetName();
397  }
398 
399  InitDictionary();
400  }
401 };
402 
406 TRestReflector Assembly(const std::string& typeName);
407 
411 TRestReflector WrapType(const std::string& typeName);
412 
418 void CloneAny(const TRestReflector& from, const TRestReflector& to);
419 }; // namespace REST_Reflection
420 
422 
424  public:
425  virtual std::string ToString(void* obj) = 0;
426  virtual void ParseString(void* obj, std::string str) = 0;
427  virtual void CloneObj(void* from, void* to) = 0;
428 };
429 
430 // type name, {toString method, parseString method}
431 EXTERN_DEF std::map<size_t, RESTVirtualConverter*> RESTConverterMethodBase;
432 
433 template <class T>
434 class Converter : RESTVirtualConverter {
435  public:
436  std::string (*ToStringFunc)(T);
437  T (*ParseStringFunc)(std::string);
438  static Converter<T>* thisptr;
439 
440  std::string ToString(void* obj) override { return ToStringFunc(*(T*)obj); }
441  void ParseString(void* obj, std::string str) override {
442  T newobj = ParseStringFunc(str);
443  *((T*)(obj)) = newobj;
444  }
445  void CloneObj(void* from, void* to) override { *((T*)(to)) = *((T*)(from)); }
446 
447  Converter(std::string (*_ToStringFunc)(T), T (*_ParseStringFunc)(std::string)) {
448  ToStringFunc = _ToStringFunc;
449  ParseStringFunc = _ParseStringFunc;
450  if (RESTConverterMethodBase.count(typeid(T).hash_code()) > 0) {
451  std::cout << "Warning! converter for type: " << typeid(T).name() << " already added!"
452  << std::endl;
453  } else {
454  RESTConverterMethodBase[typeid(T).hash_code()] = this;
455  }
456 
457  // std::string type_name_actual = REST_Reflection::GetTypeName<T>(); // in case ROOT redefines type
458  // name if (RESTConverterMethodBase.count(type_name_actual) == 0) {
459  // RESTConverterMethodBase[type_name_actual] = this;
460  //}
461  }
462 };
463 
464 #define AddConverter(ToStringFunc, ParseStringFunc, type) \
465  template <> \
466  Converter<type>* Converter<type>::thisptr = new Converter<type>(&ToStringFunc, &ParseStringFunc);
467 
468 #endif
TRestReflector(const T &obj)
Constructor to wrap an object. Any typed object can be revieved as argument.
friend std::ostream & operator<<(std::ostream &cin, TRestReflector ptr)
Output overload by calling ToString();.
void SetValue(const T &val)
Set the value of the wrapped type.
std::string GetDataMemberValueString(const std::string &name)
Get the value of datamember as std::string.
TRestReflector(T *obj)
Constructor to wrap an object pointer.
void Assembly()
Assembly a new object, and save its address. The old object will be destroied if not null.
TRestReflector()
Default constructor.
std::string type
Type of the wrapped object.
int size
Size of the object.
void Destroy() const
Destroy the current object. It will make the class to be zombie.
char * address
Address of the wrapped object.
int GetNumberOfDataMembers() const
Get the number of data members of a class.
void operator>>(const TRestReflector &to)
Deep copy the content of the wrapped object to to.
TClass * cl
Pointer to the corresponding TClass helper, if the wrapped object is in class type.
bool is_data_type
Pointer to the corresponding TDataType helper, if the wrapped object is in data type.
T GetValue()
Get the value of the wrapped type, not recommended to use.
std::vector< std::string > GetListOfDataMembers() const
Get a list of the class's datamembers as a std::vector of std::string, including those from base clas...
bool IsZombie() const
If this object type wrapper is invalid.
std::string ToString() const
Convert the wrapped object to std::string.
std::string name
Name field.
void PrintMemory(int bytepreline=16)
Print the Hex memory std::map of the wrappered object.
const std::type_info * typeinfo
value of typeid(T).name() of the wrapped object
bool onheap
If on heap, we can call Destroy() to TRestReflector. True only when initialized from Assembly()
TRestReflector GetDataMember(const std::string &name)
Find the class's datamember as TRestReflector object, including those from base class.
void ParseString(const std::string &str) const
Set the value of the wrapped object from std::string.
int InitDictionary()
Prepare the ROOT dictionary for this type.
A base class for any REST event process.
This namespace serves for the reflection functionality.
std::string GetTypeName()
Get the type name of an object.
TClass * GetClassQuick(std::string type)
TRestReflector WrapType(const std::string &typeName)
Wrap information an object of type: typeName, memory is not allocated.
void CloneAny(const TRestReflector &from, const TRestReflector &to)
Deep copy the content of object from to to
TRestReflector Assembly(const std::string &typeName)
Assembly an object of type: typeName, returning the allocated memory address and size.