#ifndef __JROOT__JROOTCLASS__ #define __JROOT__JROOTCLASS__ #include #include #include #include #include #include #include #include #include #include #include #include #include "JLang/JType.hh" #include "JLang/JException.hh" #include "JLang/JEquals.hh" /** * \author mdejong */ namespace JROOT {} namespace JPP { using namespace JROOT; } namespace JROOT { using JLANG::JEquals; using JLANG::JType; using JLANG::getType; using JLANG::JCastException; /** * Auxiliary class to manage access to base classes and data members of ROOT class. */ struct JRootClass : public JEquals { /** * Check name of class against ROOT classes. * * \param name name of class * \return true if name of class corresponds to genuine class; else false */ static inline bool is_class(const char* const name) { return (name != NULL && strcmp(name, TClass ::Class()->GetName()) != 0 && strcmp(name, TObject::Class()->GetName()) != 0 && strcmp(name, "_Rb_tree_node_base") != 0 && strcmp(name, "fgIsA") != 0 && strcmp(name, "atomic") != 0); } /** * Check base class against ROOT class names. * * \param base_class base class * \return true if valid class name; else false */ static inline bool is_class(const TBaseClass& base_class) { return is_class(base_class.GetName()); } /** * Check data member against ROOT class names. * * \param data_member data member * \return true if valid class name; else false */ static inline bool is_class(const TDataMember& data_member) { return is_class(data_member.GetTypeName()); } /** * Check if base class is STL container. * * \param base_class base class * \return true if STL congtainer; else false */ static inline bool is_STLcontainer(const TBaseClass& base_class) { return (const_cast(base_class).IsSTLContainer() != ROOT::kNotSTL); } /** * Check if data member is STL container. * * \param data_member data member * \return true if STL congtainer; else false */ static inline bool is_STLcontainer(const TDataMember& data_member) { return (const_cast(data_member).IsSTLContainer() != ROOT::kNotSTL); } /** * Check if data member is STL string. * * \param data_member data member * \return true if STL string; else false */ static inline bool is_STLstring(const TDataMember& data_member) { return (strcmp(data_member.GetFullTypeName(), "string") == 0 || strcmp(data_member.GetFullTypeName(), "const string") == 0); } /** * Check if data member is static. * * \param data_member data member * \return true if static; else false */ static inline bool is_static(const TDataMember& data_member) { return (data_member.Property() & kIsStatic); } /** * Constructor. * * \param type data type */ template JRootClass(const JType& type) : dictionary(TDictionary::GetDictionary(typeid(JType_t))), offset(0) {} /** * Constructor. * * \param pd pointer to C++ data member */ template JRootClass(JType_t JClass_t::*pd) : dictionary(TDictionary::GetDictionary(typeid(JType_t))), offset((char*) &(((JClass_t*) NULL)->*pd) - (char*) NULL) {} /** * Get dictionary. * * \return pointer to dictionary */ TDictionary* getDictionary() const { return dictionary; } /** * Get offset of this class with respect to parent class. * * \return offset */ int getOffset() const { return offset; } /** * Get class. * * \return pointer to class */ TClass* getClass() const { return dynamic_cast(dictionary); } /** * Get type name. * * \return type name */ const char* getTypename() const { if (dictionary != NULL) return dictionary->GetName(); else return NULL; } /** * Check validity of this class. * * \return true if valid class; else false */ bool is_valid() const { return (this->getDictionary() != NULL && is_class(this->getTypename())); } /** * Test equality of ROOT classes. * * \param object ROOT class * \return true if both ROOT classes are same type; else false */ bool equals(const JRootClass& object) const { return (this-> getTypename() != NULL && object.getTypename() != NULL && strcmp(this->getTypename(), object.getTypename()) == 0); } /** * Find base class or data member with given name within current class. * * \param name name of base class or data member * \param option case sensitivity * \return ROOT class */ JRootClass find(const char* const name, const bool option = true) const { if (name != NULL && strlen(name) != 0) { if (strcmp(getTypename(), name) == 0) { return *this; } if (this->getClass() != NULL) { // check for data member for (std::unique_ptr i(this->getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) { if (( option && strcmp (p->GetName(), name) == 0) || (!option && strcasecmp(p->GetName(), name) == 0)) { return this->get(*p); } } // check for base classes for (std::unique_ptr i(this->getClass()->GetListOfBases()->MakeIterator()); TBaseClass* p = (TBaseClass*) i->Next(); ) { if (is_class(*p) && !is_STLcontainer(*p)) { JRootClass rcs = this->get(*p); rcs = rcs.find(name); if (rcs.is_valid()) { return rcs; } } } } } return JRootClass(); // invalid value } /** * Get ROOT class of given data member. * * \param data_member data member * \return ROOT class */ JRootClass get(const TDataMember& data_member) const { return JRootClass(TDictionary::GetDictionary(data_member.GetTypeName()), this->getOffset() + data_member.GetOffset()); } /** * Get ROOT class of given base class * * \param base_class base class * \return ROOT class */ JRootClass get(const TBaseClass& base_class) const { return JRootClass(TDictionary::GetDictionary(base_class.GetName()), this->getOffset() + const_cast(base_class).GetDelta()); } /** * Print ROOT class information. * * \param out output stream */ inline void print(std::ostream& out) const { print(out, getTypename()); } protected: TDictionary* dictionary; //!< pointer to ROOT dictionary int offset; //!< offset with respect to data structure [B] /** * Default constructor. */ JRootClass() : dictionary(NULL), offset(0) {} /** * Constructor. * * \param dictionary pointer to dictionary * \param offset offset */ JRootClass(TDictionary* dictionary, int offset) : dictionary(dictionary), offset (offset) {} /** * Print ROOT class information. * * \param out output stream * \param prefix prefix */ inline void print(std::ostream& out, const std::string& prefix) const { if (this->is_valid()) { print(out, prefix, this->getTypename()); if (this->getClass() != NULL) { if (this->getClass()->GetListOfBases() != NULL) { for (std::unique_ptr i(this->getClass()->GetListOfBases()->MakeIterator()); const TBaseClass* p = (const TBaseClass*) i->Next(); ) { if (!is_STLcontainer(*p)) this->get(*p).print(out, prefix + "::" + p->GetName()); else print(out, prefix + "::" + p->GetName(), this->get(*p).getTypename()); } } if (this->getClass()->GetListOfDataMembers(kFALSE) != NULL) { for (std::unique_ptr i(this->getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) { if (!is_STLstring(*p) && !is_STLcontainer(*p)) this->get(*p).print(out, prefix + (is_static(*p) ? "::" : ".") + p->GetName()); else print(out, prefix + (is_static(*p) ? "::" : ".") + p->GetName(), this->get(*p).getTypename()); } } } } } /** * Print ROOT class information. * * \param out output stream * \param name name * \param type type */ inline static void print(std::ostream& out, const std::string& name, const std::string& type) { using namespace std; out << name << " " << '(' << type << ')' << endl; } }; /** * Simple address wrapper. */ template struct JAddress { /** * Type definition of address. */ typedef JPointer_t pointer_type; /** * Constructor. * * \param p pointer to object */ JAddress(pointer_type p) : address(p) {} pointer_type address; }; /** * Auxiliary class to manage access to base classes and data members of ROOT class objects. * * This class augments the class JRootClass with addressing capabilities. */ template struct JRootAddressableClass : public JRootClass, public JAddress { typedef JAddress JAddress_t; typedef typename JAddress_t::pointer_type pointer_type; /** * Constructor. * * \param object template object */ template JRootAddressableClass(T& object) : JRootClass(JType()), JAddress_t((pointer_type) &object) {} /** * Get address. * * \return pointer to object */ pointer_type getAddress() const { return this->address + getOffset(); } /** * Check validity of this addressable class. * * \return true if valid addressable class; else false */ bool is_valid() const { return (JRootClass::is_valid() && this->address != NULL); } /** * Find addressable base class or data member with given name within current class. * * \param name name of base class or data member * \return ROOT addressable class */ JRootAddressableClass find(const char* const name) const { return JRootAddressableClass(JRootClass::find(name), this->address); } /** * Get addressable class of given data member. * * \param data_member data member * \return ROOT addressable class */ JRootAddressableClass get(const TDataMember& data_member) const { return JRootAddressableClass(JRootClass::get(data_member), this->address); } /** * Get addressable class of given base class * * \param base_class base class * \return ROOT addressable class */ JRootAddressableClass get(const TBaseClass& base_class) const { return JRootAddressableClass(JRootClass::get(base_class), this->address); } /** * Find addressable base class or data member with given name within current class. * * \param name name of base class or data member * \return ROOT addressable class */ JRootAddressableClass operator[](const char* const name) const { return this->find(name); } protected: /** * Constructor. * * \param rc ROOT class * \param address address */ JRootAddressableClass(const JRootClass& rc, pointer_type address) : JRootClass(rc), JAddress_t(address) {} }; /** * ROOT class for reading object. */ struct JRootReadableClass : public JRootAddressableClass { /** * Constructor. * * \param object template object */ template JRootReadableClass(T& object) : JRootAddressableClass(object) {} /** * Copy constructor. * * \param rc ROOT addressable class */ JRootReadableClass(const JRootAddressableClass& rc) : JRootAddressableClass(rc) {} /** * Type conversion operator. * * \return value */ template operator const T&() const { if (static_cast(*this) == JRootClass(JType())) { return * (const T*) this->getAddress(); } else { THROW(JCastException, "JRootReadableClass::operator const T&"); } } /** * Type conversion operator. * * \return value */ template operator T&() { if (static_cast(*this) == JRootClass(JType())) { return * (T*) this->getAddress(); } else { THROW(JCastException, "JRootReadableClass::operator T&"); } } }; /** * ROOT class for writing object. */ struct JRootWritableClass : public JRootAddressableClass { /** * Constructor. * * \param object template object */ template JRootWritableClass(const T& object) : JRootAddressableClass(object) {} /** * Copy constructor. * * \param rc ROOT addressable class */ JRootWritableClass(const JRootAddressableClass& rc) : JRootAddressableClass(rc) {} /** * Type conversion operator. * * \return value */ template operator const T&() const { if (static_cast(*this) == JRootClass(JType())) { return * (const T*) this->getAddress(); } else { THROW(JCastException, "JRootWritableClass::operator const T&"); } } }; /** * Get ROOT data member for given parent and member class. * * \param parent ROOT class * \param member ROOT class * \return pointer to ROOT data member */ inline const TDataMember* getDataMember(const JRootClass& parent, const JRootClass& member) { if (parent.getClass() != NULL) { for (std::unique_ptr i(parent.getClass()->GetListOfDataMembers(kFALSE)->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) { const JRootClass abc = parent.get(*p); if (abc == member && abc.getOffset() == member.getOffset()) { return p; } } for (std::unique_ptr i(parent.getClass()->GetListOfBases()->MakeIterator()); const TBaseClass* p = (const TBaseClass*) i->Next(); ) { if (JRootClass::is_class(*p) && !JRootClass::is_STLcontainer(*p)) { const TDataMember* q = getDataMember(parent.get(*p), member); if (q != NULL) { return q; } } } } return NULL; } /** * Get ROOT data member for given C++ data member. * * \param pd pointer to C++ data member * \return pointer to ROOT data member */ template inline const TDataMember* getDataMember(JType_t JClass_t::*pd) { return getDataMember(JRootClass(getType()), JRootClass(pd)); } /** * Get list of ROOT data members for given class. */ template std::vector getListOfDataMembers() { std::vector buffer; TClass* rc = (TClass*) TDictionary::GetDictionary(typeid(T)); for (std::unique_ptr i(rc->GetListOfDataMembers(kFALSE)->MakeIterator()); TDataMember* p = (TDataMember*) i->Next(); ) { if (JRootClass::is_class(p->GetName())) { buffer.push_back(p); } } return buffer; } } #endif