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
30
32namespace REST_Reflection {
33
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
231EXTERN_DEF std::map<void*, TClass*> RESTListOfClasses_typeid;
232EXTERN_DEF std::map<std::string, TClass*> RESTListOfClasses_typename;
233
239inline 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
257template <typename T>
258TClass* 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
272template <typename T>
273std::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}
281template <class T>
282std::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>
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>
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
400 }
401};
402
406TRestReflector Assembly(const std::string& typeName);
407
411TRestReflector WrapType(const std::string& typeName);
412
418void 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}
431EXTERN_DEF std::map<size_t, RESTVirtualConverter*> RESTConverterMethodBase;
432
433template <class T>
434class 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.
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.
friend std::ostream & operator<<(std::ostream &cin, TRestReflector ptr)
Output overload by calling ToString();.
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.