Logo ROOT  
Reference Guide
TEnum.cxx
Go to the documentation of this file.
1 // @(#)root/meta:$Id$
2 // Author: Bianca-Cristina Cristescu 10/07/13
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TEnum
13 The TEnum class implements the enum type.
14 */
15 
16 #include <iostream>
17 
18 #include "TEnum.h"
19 #include "TEnumConstant.h"
20 #include "TInterpreter.h"
21 #include "TClass.h"
22 #include "TClassEdit.h"
23 #include "TClassTable.h"
24 #include "TProtoClass.h"
25 #include "TROOT.h"
26 
27 #include "TListOfEnums.h"
28 
30 
31 ////////////////////////////////////////////////////////////////////////////////
32 /// Constructor for TEnum class.
33 /// It takes the name of the TEnum type, interpreter info and surrounding class
34 /// the enum it is not globalat namespace scope.
35 /// Constant List is owner if enum not on global scope (thus constants not
36 /// in TROOT::GetListOfGlobals).
37 
38 TEnum::TEnum(const char *name, DeclId_t declid, TClass *cls)
39  : fInfo(nullptr), fClass(cls)
40 {
41  SetName(name);
42  if (cls) {
44  }
45 
46  // Determine fQualName
47  if (0 != strcmp("",GetTitle())){ // It comes from a protoclass
48  fQualName = std::string(GetTitle()) + "::" + GetName();
49  }
50  else if (GetClass()){ // It comes from a class/ns
51  fQualName = std::string(GetClass()->GetName()) + "::" + GetName();
52  }
53  else { // it is in the global scope
54  fQualName = GetName();
55  }
56 
57  Update(declid);
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// Destructor
62 
64 {
65  gInterpreter->ClassInfo_Delete(fInfo);
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Add a EnumConstant to the list of constants of the Enum Type.
70 
72 {
73  fConstantList.Add(constant);
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Return true if this enum object is pointing to a currently
78 /// loaded enum. If a enum is unloaded after the TEnum
79 /// is created, the TEnum will be set to be invalid.
80 
82 {
83  // Register the transaction when checking the validity of the object.
85  DeclId_t newId = gInterpreter->GetEnum(fClass, fName);
86  if (newId)
87  Update(newId);
88  return newId != 0;
89  }
90  return fInfo != 0;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Get property description word. For meaning of bits see EProperty.
95 
97 {
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Get the unterlying integer type of the enum:
103 /// enum E { kOne }; // ==> int
104 /// enum F: long; // ==> long
105 /// Returns kNumDataTypes if the enum is unknown / invalid.
106 
108 {
109  if (fInfo)
110  return gInterpreter->ClassInfo_GetUnderlyingType(fInfo);
111  return kNumDataTypes;
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 
117 {
118  if (fInfo)
119  return gInterpreter->GetDeclId(fInfo);
120 
121  return nullptr;
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 
126 void TEnum::Update(DeclId_t id)
127 {
128  if (fInfo)
129  gInterpreter->ClassInfo_Delete(fInfo);
130  if (!id) {
131  fInfo = nullptr;
132  return;
133  }
134 
135  fInfo = gInterpreter->ClassInfo_Factory(id);
136 
137  if (fInfo)
138  SetBit(kBitIsScopedEnum, gInterpreter->ClassInfo_IsScopedEnum(fInfo));
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 
143 TEnum *TEnum::GetEnum(const std::type_info &ti, ESearchAction sa)
144 {
145  int errorCode = 0;
146  char *demangledEnumName = TClassEdit::DemangleName(ti.name(), errorCode);
147 
148  if (errorCode != 0) {
149  free(demangledEnumName);
150  std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
151  return nullptr;
152  }
153 
154  const char *constDemangledEnumName = demangledEnumName;
155  TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
156  free(demangledEnumName);
157  return en;
158 
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// Static function to retrieve enumerator from the ROOT's typesystem.
163 /// It has no side effect, except when the load flag is true. In this case,
164 /// the load of the library containing the scope of the enumerator is attempted.
165 /// There are two top level code paths: the enumerator is scoped or isn't.
166 /// If it is not, a lookup in the list of global enums is performed.
167 /// If it is, two lookups are carried out for its scope: one in the list of
168 /// classes and one in the list of protoclasses. If a scope with the desired name
169 /// is found, the enum is searched. If the scope is not found, and the load flag is
170 /// true, the aforementioned two steps are performed again after an autoload attempt
171 /// with the name of the scope as key is tried out.
172 /// If the interpreter lookup flag is false, the ListOfEnums objects are not treated
173 /// as such, but rather as THashList objects. This prevents any flow of information
174 /// from the interpreter into the ROOT's typesystem: a snapshot of the typesystem
175 /// status is taken.
176 
177 TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
178 {
179  // Potential optimisation: reduce number of branches using partial specialisation of
180  // helper functions.
181 
182  TEnum *theEnum = nullptr;
183 
184  // Wrap some gymnastic around the enum finding. The special treatment of the
185  // ListOfEnums objects is located in this routine.
186  auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
187  TObject *obj;
188  if (sa_local & kInterpLookup) {
189  obj = l->FindObject(enName);
190  } else {
191  auto enumTable = dynamic_cast<const TListOfEnums *>(l);
192  obj = enumTable->GetObject(enName);
193  }
194  return static_cast<TEnum *>(obj);
195  };
196 
197  // Helper routine to look fo the scope::enum in the typesystem.
198  // If autoload and interpreter lookup is allowed, TClass::GetClass is called.
199  // If not, the list of classes and the list of protoclasses is inspected.
200  auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
201  // Check if the scope is a class
202  if (sa_local == (kALoadAndInterpLookup)) {
203  auto scope = TClass::GetClass(scopeName, true);
204  TEnum *en = nullptr;
205  if (scope) en = findEnumInList(scope->GetListOfEnums(kFALSE), enName, sa_local);
206  return en;
207  }
208 
209  // Lock need for gROOT->GetListOfClasses() and the later update/modification to
210  // the autoparsing state.
212  if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
213  // If this is a class, load only if the user allowed interpreter lookup
214  // If this is a namespace and the user did not allow for interpreter lookup, load but before disable
215  // autoparsing if enabled.
216  bool canLoadEnums (sa_local & kInterpLookup);
217  const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
218 
219  const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
220  const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
221 
222  TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
223 
224  if (scopeIsNamespace && !autoParseSuspended){
225  canLoadEnums=true;
226  }
227 
228  auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
229 
230  // Previous incarnation of the code re-enabled the auto parsing,
231  // before executing findEnumInList
232  theEnum = findEnumInList(listOfEnums, enName, sa_local);
233  }
234  // Check if the scope is still a protoclass
235  else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
236  auto listOfEnums = tProtoClassscope->GetListOfEnums();
237  if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
238  }
239  return theEnum;
240  };
241 
242  const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
243 
244  if (strchr(lastPos,'<')) {
245  // The unqualified name has template syntax, it can't possibly be an
246  // enum.
247  return nullptr;
248  }
249 
250  if (lastPos != enumName) {
251  // We have a scope
252  // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
253  const auto enName = lastPos;
254  const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
255 #ifdef R__WIN32
256  char *scopeName = new char[scopeNameSize + 1];
257 #else
258  char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
259 #endif
260  strncpy(scopeName, enumName, scopeNameSize);
261  scopeName[scopeNameSize] = '\0';
262  // Three levels of search
263  theEnum = searchEnum(scopeName, enName, kNone);
264  if (!theEnum && (sa & kAutoload)) {
265  const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
266  // It could be an enum in a scope which is not selected
267  if (libsLoaded == 0){
268  gInterpreter->AutoLoad(enumName);
269  }
270  theEnum = searchEnum(scopeName, enName, kAutoload);
271  }
272  if (!theEnum && (sa & kALoadAndInterpLookup)) {
273  if (gDebug > 0) {
274  printf("TEnum::GetEnum: Header Parsing - The enumerator %s is not known to the typesystem: an interpreter lookup will be performed. This can imply parsing of headers. This can be avoided selecting the numerator in the linkdef/selection file.\n", enumName);
275  }
276  theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
277  }
278 #ifdef R__WIN32
279  delete [] scopeName;
280 #endif
281  } else {
282  // We don't have any scope: this is a global enum
283  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
284  if (!theEnum && (sa & kAutoload)) {
285  gInterpreter->AutoLoad(enumName);
286  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
287  }
288  if (!theEnum && (sa & kALoadAndInterpLookup)) {
289  if (gDebug > 0) {
290  printf("TEnum::GetEnum: Header Parsing - The enumerator %s is not known to the typesystem: an interpreter lookup will be performed. This can imply parsing of headers. This can be avoided selecting the numerator in the linkdef/selection file.\n", enumName);
291  }
292  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
293  }
294  }
295 
296  return theEnum;
297 }
l
auto * l
Definition: textangle.C:4
gClassTable
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:95
TEnum::Update
void Update(DeclId_t id)
Definition: TEnum.cxx:126
TProtoClass.h
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TEnum::TEnum
TEnum()
Definition: TEnum.h:53
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
TNamed::SetName
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
TEnumConstant.h
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:54
TEnum::kInterpLookup
@ kInterpLookup
Definition: TEnum.h:49
kNumDataTypes
@ kNumDataTypes
Definition: TDataType.h:46
TEnum::fClass
TClass * fClass
interpreter information, owned by TEnum
Definition: TEnum.h:38
kIsNamespace
@ kIsNamespace
Definition: TDictionary.h:92
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TEnum::kALoadAndInterpLookup
@ kALoadAndInterpLookup
Definition: TEnum.h:50
TCollection::SetOwner
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Definition: TCollection.cxx:746
gInterpreter
#define gInterpreter
Definition: TInterpreter.h:558
TNamed::fName
TString fName
Definition: TNamed.h:38
TEnum::~TEnum
virtual ~TEnum()
Destructor.
Definition: TEnum.cxx:63
TEnum::GetUnderlyingType
EDataType GetUnderlyingType() const
Get the unterlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Definition: TEnum.cxx:107
TClass.h
TDictionary::DeclId_t
const typedef void * DeclId_t
Definition: TDictionary.h:209
TEnum::fInfo
ClassInfo_t * fInfo
Definition: TEnum.h:37
bool
TROOT.h
TProtoClass
Definition: TProtoClass.h:38
TClassEdit::DemangleName
char * DemangleName(const char *mangled_name, int &errorCode)
Definition: TClassEdit.h:205
TClassTable.h
gInterpreterMutex
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:43
TEnum.h
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TEnum::GetDeclId
DeclId_t GetDeclId() const
Definition: TEnum.cxx:116
TEnum
Definition: TEnum.h:33
TEnumConstant
Definition: TEnumConstant.h:29
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TListOfEnums.h
gDebug
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:119
Long_t
long Long_t
Definition: RtypesCore.h:54
TEnum::AddConstant
void AddConstant(TEnumConstant *constant)
Add a EnumConstant to the list of constants of the Enum Type.
Definition: TEnum.cxx:71
R__LOCKGUARD
#define R__LOCKGUARD(mutex)
Definition: TVirtualMutex.h:104
TClassEdit::GetUnqualifiedName
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.
Definition: TClassEdit.cxx:907
TClass::GetClass
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2925
fClass
Cppyy::TCppType_t fClass
Definition: DeclareConverters.h:259
TEnum::kAutoload
@ kAutoload
Definition: TEnum.h:48
TEnum::fQualName
std::string fQualName
owning class
Definition: TEnum.h:39
TListOfEnums
Definition: TListOfEnums.h:32
TEnum::kNone
@ kNone
Definition: TEnum.h:47
TEnum::Property
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TEnum.cxx:96
TEnum::kBitIsScopedEnum
@ kBitIsScopedEnum
The enum is an enum class.
Definition: TEnum.h:42
TClassEdit.h
TEnum::ESearchAction
ESearchAction
Definition: TEnum.h:47
kIsEnum
@ kIsEnum
Definition: TDictionary.h:68
TInterpreter.h
TClass
Definition: TClass.h:80
EDataType
EDataType
Definition: TDataType.h:28
TEnum::GetClass
TClass * GetClass() const
Definition: TEnum.h:58
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TObject
Definition: TObject.h:37
TEnum::IsValid
Bool_t IsValid()
Return true if this enum object is pointing to a currently loaded enum.
Definition: TEnum.cxx:81
name
char name[80]
Definition: TGX11.cxx:110
TInterpreter::SuspendAutoParsing
Definition: TInterpreter.h:114
TDictionary::UpdateInterpreterStateMarker
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
Definition: TDictionary.cxx:109
TEnum::GetEnum
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:143
TCollection
Definition: TCollection.h:63
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:53
kIsScopedEnum
@ kIsScopedEnum
Definition: TDictionary.h:89
free
#define free
Definition: civetweb.c:1539
TEnum::fConstantList
THashList fConstantList
Definition: TEnum.h:36
TClassTable::GetProtoNorm
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
Definition: TClassTable.cxx:645
gROOT
#define gROOT
Definition: TROOT.h:406