Logo ROOT   6.10/09
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 take the name of the TEnum type, specification if it is global
34 /// and interpreter info.
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, void *info, TClass *cls)
39  : fInfo(info), fClass(cls)
40 {
41  SetName(name);
42  if (cls) {
43  fConstantList.SetOwner(kTRUE);
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 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Destructor
60 
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Add a EnumConstant to the list of constants of the Enum Type.
67 
69 {
70  fConstantList.Add(constant);
71 }
72 
73 ////////////////////////////////////////////////////////////////////////////////
74 /// Return true if this enum object is pointing to a currently
75 /// loaded enum. If a enum is unloaded after the TEnum
76 /// is created, the TEnum will be set to be invalid.
77 
79 {
80  // Register the transaction when checking the validity of the object.
82  DeclId_t newId = gInterpreter->GetEnum(fClass, fName);
83  if (newId) {
84  Update(newId);
85  }
86  return newId != 0;
87  }
88  return fInfo != 0;
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 /// Get property description word. For meaning of bits see EProperty.
93 
95 {
96  return kIsEnum;
97 }
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 
102 {
103  fInfo = (void *)id;
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 
108 TEnum *TEnum::GetEnum(const std::type_info &ti, ESearchAction sa)
109 {
110  int errorCode = 0;
111  char *demangledEnumName = TClassEdit::DemangleName(ti.name(), errorCode);
112 
113  if (errorCode != 0) {
114  free(demangledEnumName);
115  std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
116  return nullptr;
117  }
118 
119  const char *constDemangledEnumName = demangledEnumName;
120  TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
121  free(demangledEnumName);
122  return en;
123 
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Static function to retrieve enumerator from the ROOT's typesystem.
128 /// It has no side effect, except when the load flag is true. In this case,
129 /// the load of the library containing the scope of the enumerator is attempted.
130 /// There are two top level code paths: the enumerator is scoped or isn't.
131 /// If it is not, a lookup in the list of global enums is performed.
132 /// If it is, two lookups are carried out for its scope: one in the list of
133 /// classes and one in the list of protoclasses. If a scope with the desired name
134 /// is found, the enum is searched. If the scope is not found, and the load flag is
135 /// true, the aforementioned two steps are performed again after an autoload attempt
136 /// with the name of the scope as key is tried out.
137 /// If the interpreter lookup flag is false, the ListOfEnums objects are not treated
138 /// as such, but rather as THashList objects. This prevents any flow of information
139 /// from the interpreter into the ROOT's typesystem: a snapshot of the typesystem
140 /// status is taken.
141 
142 TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
143 {
144  // Potential optimisation: reduce number of branches using partial specialisation of
145  // helper functions.
146 
147  TEnum *theEnum = nullptr;
148 
149  // Wrap some gymnastic around the enum finding. The special treatment of the
150  // ListOfEnums objects is located in this routine.
151  auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
152  TObject *obj;
153  if (sa_local & kInterpLookup) {
154  obj = l->FindObject(enName);
155  } else {
156  auto enumTable = dynamic_cast<const TListOfEnums *>(l);
157  obj = enumTable->GetObject(enName);
158  }
159  return static_cast<TEnum *>(obj);
160  };
161 
162  // Helper routine to look fo the scope::enum in the typesystem.
163  // If autoload and interpreter lookup is allowed, TClass::GetClass is called.
164  // If not, the list of classes and the list of protoclasses is inspected.
165  auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
166  // Check if the scope is a class
167  if (sa_local == (kALoadAndInterpLookup)) {
168  auto scope = TClass::GetClass(scopeName, true);
169  TEnum *en = nullptr;
170  if (scope) en = findEnumInList(scope->GetListOfEnums(), enName, sa_local);
171  return en;
172  }
173 
174  // Lock need for gROOT->GetListOfClasses() and the later update/modification to
175  // the autoparsing state.
177  if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
178  // If this is a class, load only if the user allowed interpreter lookup
179  // If this is a namespace and the user did not allow for interpreter lookup, load but before disable
180  // autoparsing if enabled.
181  bool canLoadEnums (sa_local & kInterpLookup);
182  const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
183 
184  const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
185  const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
186 
187  TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
188 
189  if (scopeIsNamespace && !autoParseSuspended){
190  canLoadEnums=true;
191  }
192 
193  auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
194 
195  // Previous incarnation of the code re-enabled the auto parsing,
196  // before executing findEnumInList
197  theEnum = findEnumInList(listOfEnums, enName, sa_local);
198  }
199  // Check if the scope is still a protoclass
200  else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
201  auto listOfEnums = tProtoClassscope->GetListOfEnums();
202  if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
203  }
204  return theEnum;
205  };
206 
207  const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
208 
209  if (strchr(lastPos,'<')) {
210  // The unqualified name has template syntax, it can't possibly be an
211  // enum.
212  return nullptr;
213  }
214 
215  if (lastPos != enumName) {
216  // We have a scope
217  // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
218  const auto enName = lastPos;
219  const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
220 #ifdef R__WIN32
221  char *scopeName = new char[scopeNameSize + 1];
222 #else
223  char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
224 #endif
225  strncpy(scopeName, enumName, scopeNameSize);
226  scopeName[scopeNameSize] = '\0';
227  // Three levels of search
228  theEnum = searchEnum(scopeName, enName, kNone);
229  if (!theEnum && (sa & kAutoload)) {
230  const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
231  // It could be an enum in a scope which is not selected
232  if (libsLoaded == 0){
233  gInterpreter->AutoLoad(enumName);
234  }
235  theEnum = searchEnum(scopeName, enName, kAutoload);
236  }
237  if (!theEnum && (sa & kALoadAndInterpLookup)) {
238  if (gDebug > 0) {
239  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);
240  }
241  theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
242  }
243 #ifdef R__WIN32
244  delete [] scopeName;
245 #endif
246  } else {
247  // We don't have any scope: this is a global enum
248  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
249  if (!theEnum && (sa & kAutoload)) {
250  gInterpreter->AutoLoad(enumName);
251  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
252  }
253  if (!theEnum && (sa & kALoadAndInterpLookup)) {
254  if (gDebug > 0) {
255  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);
256  }
257  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
258  }
259  }
260 
261  return theEnum;
262 }
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
The TEnum class implements the enum type.
Definition: TEnum.h:31
long long Long64_t
Definition: RtypesCore.h:69
void Update(DeclId_t id)
Definition: TEnum.cxx:101
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:93
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
#define gROOT
Definition: TROOT.h:375
bool Bool_t
Definition: RtypesCore.h:59
TClass * fClass
interpreter implementation provided declaration
Definition: TEnum.h:36
#define gInterpreter
Definition: TInterpreter.h:499
const void * DeclId_t
Definition: TDictionary.h:205
virtual ~TEnum()
Destructor.
Definition: TEnum.cxx:61
TClass * GetClass(T *)
Definition: TClass.h:545
Collection abstract base class.
Definition: TCollection.h:42
TLine * l
Definition: textangle.C:4
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:29
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
TString fName
Definition: TNamed.h:32
void AddConstant(TEnumConstant *constant)
Add a EnumConstant to the list of constants of the Enum Type.
Definition: TEnum.cxx:68
long Long_t
Definition: RtypesCore.h:50
#define ClassImp(name)
Definition: Rtypes.h:336
#define free
Definition: civetweb.c:821
Bool_t IsValid()
Return true if this enum object is pointing to a currently loaded enum.
Definition: TEnum.cxx:78
#define R__LOCKGUARD(mutex)
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:2885
Mother of all ROOT objects.
Definition: TObject.h:37
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:108
void * fInfo
Definition: TEnum.h:35
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
Definition: TListOfEnums.h:32
virtual void Add(TObject *obj)
Definition: TList.h:77
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:83
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TEnum.cxx:94
ESearchAction
Definition: TEnum.h:41
THashList fConstantList
Definition: TEnum.h:34
const Bool_t kTRUE
Definition: RtypesCore.h:91
gr SetName("gr")