Jpp  19.1.0-rc.1
the software that should make you happy
JRootClass.hh
Go to the documentation of this file.
1 #ifndef __JROOT__JROOTCLASS__
2 #define __JROOT__JROOTCLASS__
3 
4 #include <string>
5 #include <ostream>
6 #include <cstring>
7 #include <typeinfo>
8 #include <vector>
9 #include <memory>
10 
11 #include <TDictionary.h>
12 #include <TClass.h>
13 #include <TDataMember.h>
14 #include <TBaseClass.h>
15 #include <TIterator.h>
16 #include <TList.h>
17 
18 #include "JLang/JType.hh"
19 #include "JLang/JException.hh"
20 #include "JLang/JEquals.hh"
21 
22 
23 /**
24  * \author mdejong
25  */
26 
27 namespace JROOT {}
28 namespace JPP { using namespace JROOT; }
29 
30 namespace JROOT {
31 
32  using JLANG::JEquals;
33  using JLANG::JType;
34  using JLANG::getType;
36 
37 
38  /**
39  * Auxiliary class to manage access to base classes and data members of ROOT class.
40  */
41  struct JRootClass :
42  public JEquals<JRootClass>
43  {
44  /**
45  * Check name of class against ROOT classes.
46  *
47  * \param name name of class
48  * \return true if name of class corresponds to genuine class; else false
49  */
50  static inline bool is_class(const char* const name)
51  {
52  return (name != NULL &&
53  strcmp(name, TClass ::Class()->GetName()) != 0 &&
54  strcmp(name, TObject::Class()->GetName()) != 0 &&
55  strcmp(name, "_Rb_tree_node_base") != 0 &&
56  strcmp(name, "fgIsA") != 0 &&
57  strcmp(name, "atomic<TClass*>") != 0);
58  }
59 
60 
61  /**
62  * Check base class against ROOT class names.
63  *
64  * \param base_class base class
65  * \return true if valid class name; else false
66  */
67  static inline bool is_class(const TBaseClass& base_class)
68  {
69  return is_class(base_class.GetName());
70  }
71 
72 
73  /**
74  * Check data member against ROOT class names.
75  *
76  * \param data_member data member
77  * \return true if valid class name; else false
78  */
79  static inline bool is_class(const TDataMember& data_member)
80  {
81  return is_class(data_member.GetTypeName());
82  }
83 
84 
85  /**
86  * Check if base class is STL container.
87  *
88  * \param base_class base class
89  * \return true if STL congtainer; else false
90  */
91  static inline bool is_STLcontainer(const TBaseClass& base_class)
92  {
93  return (const_cast<TBaseClass&>(base_class).IsSTLContainer() != ROOT::kNotSTL);
94  }
95 
96 
97  /**
98  * Check if data member is STL container.
99  *
100  * \param data_member data member
101  * \return true if STL congtainer; else false
102  */
103  static inline bool is_STLcontainer(const TDataMember& data_member)
104  {
105  return (const_cast<TDataMember&>(data_member).IsSTLContainer() != ROOT::kNotSTL);
106  }
107 
108 
109  /**
110  * Check if data member is STL string.
111  *
112  * \param data_member data member
113  * \return true if STL string; else false
114  */
115  static inline bool is_STLstring(const TDataMember& data_member)
116  {
117  return (strcmp(data_member.GetFullTypeName(), "string") == 0 ||
118  strcmp(data_member.GetFullTypeName(), "const string") == 0);
119  }
120 
121 
122  /**
123  * Check if data member is static.
124  *
125  * \param data_member data member
126  * \return true if static; else false
127  */
128  static inline bool is_static(const TDataMember& data_member)
129  {
130  return (data_member.Property() & kIsStatic);
131  }
132 
133 
134  /**
135  * Check if name is one of TObject own data members
136  * (fBits or fUniqueID, for Root <= 6.30.04 at least)
137  */
138  static inline bool is_tobject_member(const char* name)
139  {
140  TClass* o_class = TClass::GetClass<TObject>();
141  return o_class->GetListOfRealData()->FindObject(name) != nullptr;
142  }
143  /**
144  * Constructor.
145  *
146  * \param type data type
147  */
148  template<class JType_t>
149  JRootClass(const JType<JType_t>& type) :
150  dictionary(TDictionary::GetDictionary(typeid(JType_t))),
151  offset(0)
152  {}
153 
154 
155  /**
156  * Constructor.
157  *
158  * \param pd pointer to C++ data member
159  */
160  template<class JType_t, class JClass_t>
161  JRootClass(JType_t JClass_t::*pd) :
162  dictionary(TDictionary::GetDictionary(typeid(JType_t))),
163  offset((char*) &(((JClass_t*) NULL)->*pd) - (char*) NULL)
164  {}
165 
166 
167  /**
168  * Get dictionary.
169  *
170  * \return pointer to dictionary
171  */
172  TDictionary* getDictionary() const
173  {
174  return dictionary;
175  }
176 
177 
178  /**
179  * Get offset of this class with respect to parent class.
180  *
181  * \return offset
182  */
183  int getOffset() const
184  {
185  return offset;
186  }
187 
188 
189  /**
190  * Get class.
191  *
192  * \return pointer to class
193  */
194  TClass* getClass() const
195  {
196  return dynamic_cast<TClass*>(dictionary);
197  }
198 
199 
200  /**
201  * Get type name.
202  *
203  * \return type name
204  */
205  const char* getTypename() const
206  {
207  if (dictionary != NULL)
208  return dictionary->GetName();
209  else
210  return NULL;
211  }
212 
213 
214  /**
215  * Check validity of this class.
216  *
217  * \return true if valid class; else false
218  */
219  bool is_valid() const
220  {
221  return (this->getDictionary() != NULL && is_class(this->getTypename()));
222  }
223 
224 
225  /**
226  * Test equality of ROOT classes.
227  *
228  * \param object ROOT class
229  * \return true if both ROOT classes are same type; else false
230  */
231  bool equals(const JRootClass& object) const
232  {
233  return (this-> getTypename() != NULL &&
234  object.getTypename() != NULL &&
235  strcmp(this->getTypename(), object.getTypename()) == 0);
236  }
237 
238 
239  /**
240  * Find base class or data member with given name within current class.
241  *
242  * \param name name of base class or data member
243  * \param option case sensitivity
244  * \return ROOT class
245  */
246  JRootClass find(const char* const name, const bool option = true) const
247  {
248  if (name != NULL && strlen(name) != 0) {
249 
250  if (strcmp(getTypename(), name) == 0) {
251  return *this;
252  }
253 
254  if (this->getClass() != NULL) {
255 
256  // check for data member
257 
258  for (std::unique_ptr<TIterator> i(this->getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) {
259  if (( option && strcmp (p->GetName(), name) == 0) ||
260  (!option && strcasecmp(p->GetName(), name) == 0)) {
261  return this->get(*p);
262  }
263  }
264 
265  // check for base classes
266 
267  for (std::unique_ptr<TIterator> i(this->getClass()->GetListOfBases()->MakeIterator()); TBaseClass* p = (TBaseClass*) i->Next(); ) {
268 
269  if (is_class(*p) && !is_STLcontainer(*p)) {
270 
271  JRootClass rcs = this->get(*p);
272 
273  rcs = rcs.find(name);
274 
275  if (rcs.is_valid()) {
276  return rcs;
277  }
278  }
279  }
280  }
281  }
282 
283  return JRootClass(); // invalid value
284  }
285 
286 
287  /**
288  * Get ROOT class of given data member.
289  *
290  * \param data_member data member
291  * \return ROOT class
292  */
293  JRootClass get(const TDataMember& data_member) const
294  {
295  return JRootClass(TDictionary::GetDictionary(data_member.GetTypeName()),
296  this->getOffset() + data_member.GetOffset());
297  }
298 
299 
300  /**
301  * Get ROOT class of given base class
302  *
303  * \param base_class base class
304  * \return ROOT class
305  */
306  JRootClass get(const TBaseClass& base_class) const
307  {
308  return JRootClass(TDictionary::GetDictionary(base_class.GetName()),
309  this->getOffset() + const_cast<TBaseClass&>(base_class).GetDelta());
310  }
311 
312 
313  /**
314  * Print ROOT class information.
315  *
316  * \param out output stream
317  */
318  inline void print(std::ostream& out) const
319  {
320  print(out, getTypename());
321  }
322 
323 
324  protected:
325 
326  TDictionary* dictionary; //!< pointer to ROOT dictionary
327  int offset; //!< offset with respect to data structure [B]
328 
329 
330  /**
331  * Default constructor.
332  */
334  dictionary(NULL),
335  offset(0)
336  {}
337 
338 
339  /**
340  * Constructor.
341  *
342  * \param dictionary pointer to dictionary
343  * \param offset offset
344  */
345  JRootClass(TDictionary* dictionary,
346  int offset) :
348  offset (offset)
349  {}
350 
351 
352  /**
353  * Print ROOT class information.
354  *
355  * \param out output stream
356  * \param prefix prefix
357  */
358  inline void print(std::ostream& out, const std::string& prefix) const
359  {
360  if (this->is_valid()) {
361 
362  print(out, prefix, this->getTypename());
363 
364  if (this->getClass() != NULL) {
365 
366  if (this->getClass()->GetListOfBases() != NULL) {
367 
368  for (std::unique_ptr<TIterator> i(this->getClass()->GetListOfBases()->MakeIterator()); const TBaseClass* p = (const TBaseClass*) i->Next(); ) {
369  if (!is_STLcontainer(*p))
370  this->get(*p).print(out, prefix + "::" + p->GetName());
371  else
372  print(out, prefix + "::" + p->GetName(), this->get(*p).getTypename());
373  }
374  }
375 
376  if (this->getClass()->GetListOfDataMembers(kFALSE) != NULL) {
377 
378  for (std::unique_ptr<TIterator> i(this->getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) {
379  if (!is_STLstring(*p) && !is_STLcontainer(*p))
380  this->get(*p).print(out, prefix + (is_static(*p) ? "::" : ".") + p->GetName());
381  else
382  print(out, prefix + (is_static(*p) ? "::" : ".") + p->GetName(), this->get(*p).getTypename());
383  }
384  }
385  }
386  }
387  }
388 
389 
390  /**
391  * Print ROOT class information.
392  *
393  * \param out output stream
394  * \param name name
395  * \param type type
396  */
397  inline static void print(std::ostream& out, const std::string& name, const std::string& type)
398  {
399  using namespace std;
400 
401  out << name << " " << '(' << type << ')' << endl;
402  }
403  };
404 
405 
406  /**
407  * Simple address wrapper.
408  */
409  template<class JPointer_t>
410  struct JAddress
411  {
412  /**
413  * Type definition of address.
414  */
415  typedef JPointer_t pointer_type;
416 
417  /**
418  * Constructor.
419  *
420  * \param p pointer to object
421  */
423  address(p)
424  {}
425 
427  };
428 
429 
430  /**
431  * Auxiliary class to manage access to base classes and data members of ROOT class objects.
432  *
433  * This class augments the class JRootClass with addressing capabilities.
434  */
435  template<class JPointer_t>
437  public JRootClass,
438  public JAddress<JPointer_t>
439  {
442 
443  /**
444  * Constructor.
445  *
446  * \param object template object
447  */
448  template<class T>
450  JRootClass(JType<T>()),
451  JAddress_t((pointer_type) &object)
452  {}
453 
454 
455  /**
456  * Get address.
457  *
458  * \return pointer to object
459  */
461  {
462  return this->address + getOffset();
463  }
464 
465 
466  /**
467  * Check validity of this addressable class.
468  *
469  * \return true if valid addressable class; else false
470  */
471  bool is_valid() const
472  {
473  return (JRootClass::is_valid() && this->address != NULL);
474  }
475 
476 
477  /**
478  * Find addressable base class or data member with given name within current class.
479  *
480  * \param name name of base class or data member
481  * \return ROOT addressable class
482  */
483  JRootAddressableClass find(const char* const name) const
484  {
485  return JRootAddressableClass(JRootClass::find(name), this->address);
486  }
487 
488 
489  /**
490  * Get addressable class of given data member.
491  *
492  * \param data_member data member
493  * \return ROOT addressable class
494  */
495  JRootAddressableClass get(const TDataMember& data_member) const
496  {
497  return JRootAddressableClass(JRootClass::get(data_member), this->address);
498  }
499 
500 
501  /**
502  * Get addressable class of given base class
503  *
504  * \param base_class base class
505  * \return ROOT addressable class
506  */
507  JRootAddressableClass get(const TBaseClass& base_class) const
508  {
509  return JRootAddressableClass(JRootClass::get(base_class), this->address);
510  }
511 
512 
513  /**
514  * Find addressable base class or data member with given name within current class.
515  *
516  * \param name name of base class or data member
517  * \return ROOT addressable class
518  */
519  JRootAddressableClass operator[](const char* const name) const
520  {
521  return this->find(name);
522  }
523 
524 
525  protected:
526  /**
527  * Constructor.
528  *
529  * \param rc ROOT class
530  * \param address address
531  */
533  JRootClass(rc),
534  JAddress_t(address)
535  {}
536  };
537 
538 
539  /**
540  * ROOT class for reading object.
541  */
543  public JRootAddressableClass<char *>
544  {
545  /**
546  * Constructor.
547  *
548  * \param object template object
549  */
550  template<class T>
551  JRootReadableClass(T& object) :
552  JRootAddressableClass<char *>(object)
553  {}
554 
555 
556  /**
557  * Copy constructor.
558  *
559  * \param rc ROOT addressable class
560  */
562  JRootAddressableClass<char *>(rc)
563  {}
564 
565 
566  /**
567  * Type conversion operator.
568  *
569  * \return value
570  */
571  template<class T>
572  operator const T&() const
573  {
574  if (static_cast<const JRootClass&>(*this) == JRootClass(JType<T>())) {
575  return * (const T*) this->getAddress();
576  } else {
577  THROW(JCastException, "JRootReadableClass::operator const T&");
578  }
579  }
580 
581 
582  /**
583  * Type conversion operator.
584  *
585  * \return value
586  */
587  template<class T>
588  operator T&()
589  {
590  if (static_cast<const JRootClass&>(*this) == JRootClass(JType<T>())) {
591  return * (T*) this->getAddress();
592  } else {
593  THROW(JCastException, "JRootReadableClass::operator T&");
594  }
595  }
596  };
597 
598 
599  /**
600  * ROOT class for writing object.
601  */
603  public JRootAddressableClass<const char*>
604  {
605  /**
606  * Constructor.
607  *
608  * \param object template object
609  */
610  template<class T>
611  JRootWritableClass(const T& object) :
612  JRootAddressableClass<const char *>(object)
613  {}
614 
615 
616  /**
617  * Copy constructor.
618  *
619  * \param rc ROOT addressable class
620  */
622  JRootAddressableClass<const char *>(rc)
623  {}
624 
625 
626  /**
627  * Type conversion operator.
628  *
629  * \return value
630  */
631  template<class T>
632  operator const T&() const
633  {
634  if (static_cast<const JRootClass&>(*this) == JRootClass(JType<T>())) {
635  return * (const T*) this->getAddress();
636  } else {
637  THROW(JCastException, "JRootWritableClass::operator const T&");
638  }
639  }
640  };
641 
642 
643  /**
644  * Get ROOT data member for given parent and member class.
645  *
646  * \param parent ROOT class
647  * \param member ROOT class
648  * \return pointer to ROOT data member
649  */
650  inline const TDataMember* getDataMember(const JRootClass& parent,
651  const JRootClass& member)
652  {
653  if (parent.getClass() != NULL) {
654 
655  for (std::unique_ptr<TIterator> i(parent.getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) {
656 
657  const JRootClass abc = parent.get(*p);
658 
659  if (abc == member && abc.getOffset() == member.getOffset()) {
660  return p;
661  }
662  }
663 
664  for (std::unique_ptr<TIterator> i(parent.getClass()->GetListOfBases()->MakeIterator()); const TBaseClass* p = (const TBaseClass*) i->Next(); ) {
665 
667 
668  const TDataMember* q = getDataMember(parent.get(*p), member);
669 
670  if (q != NULL) {
671  return q;
672  }
673  }
674  }
675  }
676 
677  return NULL;
678  }
679 
680 
681  /**
682  * Get ROOT data member for given C++ data member.
683  *
684  * \param pd pointer to C++ data member
685  * \return pointer to ROOT data member
686  */
687  template<class JType_t, class JClass_t>
688  inline const TDataMember* getDataMember(JType_t JClass_t::*pd)
689  {
690  return getDataMember(JRootClass(getType<JClass_t>()), JRootClass(pd));
691  }
692 
693 
694  /**
695  * Get list of ROOT data members for given class.
696  */
697  template<class T>
699  {
701 
702  TClass* rc = (TClass*) TDictionary::GetDictionary(typeid(T));
703 
704  for (std::unique_ptr<TIterator> i(rc->GetListOfDataMembers(kFALSE)->MakeIterator()); TDataMember* p = (TDataMember*) i->Next(); ) {
705  if (JRootClass::is_class(p->GetName())) {
706  buffer.push_back(p);
707  }
708  }
709 
710  return buffer;
711  }
712 }
713 
714 #endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
Exception for cast operation.
Definition: JException.hh:252
JType< T > getType()
Get type.
Definition: JType.hh:31
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary classes and methods for ROOT I/O.
const TDataMember * getDataMember(JType_t JClass_t::*pd)
Get ROOT data member for given C++ data member.
Definition: JRootClass.hh:688
std::vector< TDataMember * > getListOfDataMembers()
Get list of ROOT data members for given class.
Definition: JRootClass.hh:698
Definition: JSTDTypes.hh:14
Template definition of auxiliary base class for comparison of data structures.
Definition: JEquals.hh:84
Auxiliary class for a type holder.
Definition: JType.hh:19
Simple address wrapper.
Definition: JRootClass.hh:411
JPointer_t pointer_type
Type definition of address.
Definition: JRootClass.hh:415
pointer_type address
Definition: JRootClass.hh:426
JAddress(pointer_type p)
Constructor.
Definition: JRootClass.hh:422
Auxiliary class to manage access to base classes and data members of ROOT class objects.
Definition: JRootClass.hh:439
bool is_valid() const
Check validity of this addressable class.
Definition: JRootClass.hh:471
JRootAddressableClass get(const TBaseClass &base_class) const
Get addressable class of given base class.
Definition: JRootClass.hh:507
pointer_type getAddress() const
Get address.
Definition: JRootClass.hh:460
JAddress_t::pointer_type pointer_type
Definition: JRootClass.hh:441
JAddress< JPointer_t > JAddress_t
Definition: JRootClass.hh:440
JRootAddressableClass get(const TDataMember &data_member) const
Get addressable class of given data member.
Definition: JRootClass.hh:495
JRootAddressableClass find(const char *const name) const
Find addressable base class or data member with given name within current class.
Definition: JRootClass.hh:483
JRootAddressableClass operator[](const char *const name) const
Find addressable base class or data member with given name within current class.
Definition: JRootClass.hh:519
JRootAddressableClass(const JRootClass &rc, pointer_type address)
Constructor.
Definition: JRootClass.hh:532
JRootAddressableClass(T &object)
Constructor.
Definition: JRootClass.hh:449
Auxiliary class to manage access to base classes and data members of ROOT class.
Definition: JRootClass.hh:43
static bool is_tobject_member(const char *name)
Check if name is one of TObject own data members (fBits or fUniqueID, for Root <= 6....
Definition: JRootClass.hh:138
JRootClass(const JType< JType_t > &type)
Constructor.
Definition: JRootClass.hh:149
void print(std::ostream &out) const
Print ROOT class information.
Definition: JRootClass.hh:318
TDictionary * dictionary
pointer to ROOT dictionary
Definition: JRootClass.hh:326
JRootClass get(const TBaseClass &base_class) const
Get ROOT class of given base class.
Definition: JRootClass.hh:306
bool is_valid() const
Check validity of this class.
Definition: JRootClass.hh:219
static bool is_STLcontainer(const TDataMember &data_member)
Check if data member is STL container.
Definition: JRootClass.hh:103
JRootClass get(const TDataMember &data_member) const
Get ROOT class of given data member.
Definition: JRootClass.hh:293
static bool is_STLcontainer(const TBaseClass &base_class)
Check if base class is STL container.
Definition: JRootClass.hh:91
JRootClass(JType_t JClass_t::*pd)
Constructor.
Definition: JRootClass.hh:161
JRootClass()
Default constructor.
Definition: JRootClass.hh:333
static bool is_static(const TDataMember &data_member)
Check if data member is static.
Definition: JRootClass.hh:128
void print(std::ostream &out, const std::string &prefix) const
Print ROOT class information.
Definition: JRootClass.hh:358
int getOffset() const
Get offset of this class with respect to parent class.
Definition: JRootClass.hh:183
TClass * getClass() const
Get class.
Definition: JRootClass.hh:194
int offset
offset with respect to data structure [B]
Definition: JRootClass.hh:327
TDictionary * getDictionary() const
Get dictionary.
Definition: JRootClass.hh:172
JRootClass find(const char *const name, const bool option=true) const
Find base class or data member with given name within current class.
Definition: JRootClass.hh:246
static bool is_STLstring(const TDataMember &data_member)
Check if data member is STL string.
Definition: JRootClass.hh:115
static bool is_class(const TDataMember &data_member)
Check data member against ROOT class names.
Definition: JRootClass.hh:79
static void print(std::ostream &out, const std::string &name, const std::string &type)
Print ROOT class information.
Definition: JRootClass.hh:397
static bool is_class(const TBaseClass &base_class)
Check base class against ROOT class names.
Definition: JRootClass.hh:67
const char * getTypename() const
Get type name.
Definition: JRootClass.hh:205
JRootClass(TDictionary *dictionary, int offset)
Constructor.
Definition: JRootClass.hh:345
static bool is_class(const char *const name)
Check name of class against ROOT classes.
Definition: JRootClass.hh:50
bool equals(const JRootClass &object) const
Test equality of ROOT classes.
Definition: JRootClass.hh:231
ROOT class for reading object.
Definition: JRootClass.hh:544
JRootReadableClass(const JRootAddressableClass< char * > &rc)
Copy constructor.
Definition: JRootClass.hh:561
JRootReadableClass(T &object)
Constructor.
Definition: JRootClass.hh:551
ROOT class for writing object.
Definition: JRootClass.hh:604
JRootWritableClass(const JRootAddressableClass< const char * > &rc)
Copy constructor.
Definition: JRootClass.hh:621
JRootWritableClass(const T &object)
Constructor.
Definition: JRootClass.hh:611