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();
311 void operator>>(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();
338 void ParseString(std::string str);
340 void Assembly();
342 void Destroy();
344 void PrintMemory(int bytepreline = 16);
346 TRestReflector GetDataMember(std::string name);
350 std::vector<std::string> GetListOfDataMembers();
352 std::string GetDataMemberValueString(std::string name);
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(std::string typeName);
407
411TRestReflector WrapType(std::string typeName);
412
418void CloneAny(TRestReflector from, 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.
TRestReflector(T *obj)
Constructor to wrap an object pointer.
void ParseString(std::string str)
Set the value of the wrapped object from std::string.
void Assembly()
Assembly a new object, and save its address. The old object will be destroied if not null.
std::string ToString()
Convert the wrapped object to std::string.
TRestReflector()
Default constructor.
std::string GetDataMemberValueString(std::string name)
Get the value of datamember as std::string.
std::string type
Type of the wrapped object.
int size
Size of the object.
std::vector< std::string > GetListOfDataMembers()
Get a list of the class's datamembers as a std::vector of std::string, including those from base clas...
char * address
Address of the wrapped object.
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.
void operator>>(TRestReflector to)
Deep copy the content of the wrapped object to to.
int GetNumberOfDataMembers()
Get the number of data members of a class.
TRestReflector GetDataMember(std::string name)
Find the class's datamember as TRestReflector object, including those from base class.
std::string name
Name field.
void PrintMemory(int bytepreline=16)
Print the Hex memory std::map of the wrappered object.
void Destroy()
Destroy the current object. It will make the class to be zombie.
const std::type_info * typeinfo
value of typeid(T).name() of the wrapped object
bool IsZombie()
If this object type wrapper is invalid.
bool onheap
If on heap, we can call Destroy() to TRestReflector. True only when initialized from Assembly()
friend std::ostream & operator<<(std::ostream &cin, TRestReflector ptr)
Output overload by calling ToString();.
int InitDictionary()
Prepare the ROOT dictionary for this type.
A base class for any REST event process.
This namespace serves for the reflection functionality.
TRestReflector WrapType(std::string typeName)
Wrap information an object of type: typeName, memory is not allocated.
std::string GetTypeName()
Get the type name of an object.
TClass * GetClassQuick(std::string type)
void CloneAny(TRestReflector from, TRestReflector to)
Deep copy the content of object from to to
TRestReflector Assembly(std::string typeName)
Assembly an object of type: typeName, returning the allocated memory address and size.