void inspectDicts() { // Supercluster energy TClass* sc = TClass::GetClass("SuperCluster"); TDataMember* dm = sc->GetDataMember("energy2"); if (dm) std::cout << "SuperCluster::energy2 type is " << dm->GetTypeName() << std::endl; dm = sc->GetDataMember("energy"); // should not if (dm) std::cout << "SuperCluster::energy type is " << dm->GetTypeName() << std::endl; // Particle vertex TClass* par = TClass::GetClass("Particle"); dm = par->GetDataMember("vertex"); if (dm) std::cout << "Particle::vertex type is " << dm->GetTypeName() << std::endl; dm = par->GetDataMember("vertex2"); // should not print if (dm) std::cout << "Particle::vertex2 type is " << dm->GetTypeName() << std::endl; }
//_____________________________________________________________________________ Int_t THaRTTI::Find( TClass* cl, TString& var, const void* const prototype ) { // Get RTTI info for member variable 'var' of ROOT class 'cl' // 'prototype' is a pointer to an object of class 'cl' and must // be specified if the class does not have a default constructor. if( !cl ) return -1; // Get the object's list TRealData. Unlike the list of TDataMembers, // this list handles inheritance (i.e. it includes base class data // members), and TRealData allows us to get any variable's offset. // The main limitation is that data members have to be persistent. TList* lrd = cl->GetListOfRealData(); if( !lrd ) { // FIXME: Check if const_cast is appropriate here // - prototype must not be modified cl->BuildRealData( const_cast<void*>(prototype) ); lrd = cl->GetListOfRealData(); if( !lrd ) return -1; } // Variable names in TRealData are stored along with pointer prefixes (*) // and array subscripts, so we have to use a customized search function: TRealData* rd = static_cast<TRealData*>( FindRealDataVar( lrd, var ) ); if( !rd ) return -1; // Get the TDataMember, which holds the really useful information TDataMember* m = rd->GetDataMember(); if( !m ) return -1; VarType type; if( m->IsBasic() || m->IsEnum() ) { TString typnam( m->GetTypeName() ); if( typnam == "Double_t" ) type = kDouble; else if( typnam == "Float_t" || typnam == "Real_t" ) type = kFloat; else if( typnam == "Int_t" ) type = kInt; else if( typnam == "UInt_t" ) type = kUInt; else if( typnam == "Short_t" ) type = kShort; else if( typnam == "UShort_t" ) type = kUShort; else if( typnam == "Long_t" ) type = kLong; else if( typnam == "ULong_t" ) type = kULong; else if( typnam == "Char_t" || typnam == "Text_t" ) type = kChar; else if( typnam == "Byte_t" || typnam == "UChar_t" || typnam == "Bool_t" ) type = kByte; else if( m->IsEnum() ) // Enumeration types are all treated as integers type = kInt; else return -1; // Pointers are flagged as pointer types. The way THaVar works, this means: // - Simple pointers will be dereferenced when reading the variable. // This avoids dangling pointers. // - For pointers to pointers, the value of the base pointer will be // memorized. Therefore, if the base pointer changes, the variable // will become invalid. if( m->IsaPointer() ) // Simple, but depends on the definition order in VarType.h type = (VarType)(type + kDoubleP); } else { type = (m->IsaPointer()) ? kObjectP : kObject; } // Check for arrays Int_t array_dim = m->GetArrayDim(); const char* array_index = m->GetArrayIndex(); Int_t count_offset = -1; TString subscript( rd->GetName() ); EArrayType atype = kScalar; // If variable is explicitly dimensioned, ignore any "array index" // in the comment. if( array_dim > 0 ) { // Explicitly dimensioned arrays must not be pointers if( m->IsaPointer() ) return -1; Ssiz_t i = subscript.Index( '[' ); if( i == kNPOS ) return -1; subscript = subscript(i,subscript.Length()-i); atype = kFixed; } else if( array_index && *array_index && m->IsaPointer() ) { // If no explicit dimensions given, but the variable is a pointer // and there is an array subscript given in the comment ( // [fN] ), // then we have a variable-size array. The subscript variable in the // comment MUST be an Int_t. I guess that is a standard ROOT // convention anyway. // See if the subscript variable exists and is an Int_t TString index(array_index); THaRTTI rtti; rtti.Find( cl, index, prototype ); if( rtti.IsValid() && rtti.GetType() == kInt ) { // Looking good. Let's get the offset count_offset = rtti.GetOffset(); } atype = kVariable; } // Build the RTTI object fOffset = rd->GetThisOffset(); fType = type; fArrayType = atype; fDataMember = m; fRealData = rd; switch( atype ) { case kFixed: fSubscript = subscript; break; case kVariable: fCountOffset = count_offset; break; default: break; } return 0; }