ROOT  6.06/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  if (!demangledEnumName) {
115  free(demangledEnumName);
116  }
117  std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
118  return nullptr;
119  }
120 
121  const char *constDemangledEnumName = demangledEnumName;
122  TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
123  free(demangledEnumName);
124  return en;
125 
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Static function to retrieve enumerator from the ROOT's typesystem.
130 /// It has no side effect, except when the load flag is true. In this case,
131 /// the load of the library containing the scope of the enumerator is attempted.
132 /// There are two top level code paths: the enumerator is scoped or isn't.
133 /// If it is not, a lookup in the list of global enums is performed.
134 /// If it is, two lookups are carried out for its scope: one in the list of
135 /// classes and one in the list of protoclasses. If a scope with the desired name
136 /// is found, the enum is searched. If the scope is not found, and the load flag is
137 /// true, the aforementioned two steps are performed again after an autoload attempt
138 /// with the name of the scope as key is tried out.
139 /// If the interpreter lookup flag is false, the ListOfEnums objects are not treated
140 /// as such, but rather as THashList objects. This prevents any flow of information
141 /// from the interpreter into the ROOT's typesystem: a snapshot of the typesystem
142 /// status is taken.
143 
144 TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
145 {
146  // Potential optimisation: reduce number of branches using partial specialisation of
147  // helper functions.
148 
149  TEnum *theEnum = nullptr;
150 
151  // Wrap some gymnastic around the enum finding. The special treatment of the
152  // ListOfEnums objects is located in this routine.
153  auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
154  TObject *obj;
155  if (sa_local & kInterpLookup) {
156  obj = l->FindObject(enName);
157  } else {
158  auto enumTable = dynamic_cast<const TListOfEnums *>(l);
159  obj = enumTable->GetObject(enName);
160  }
161  return static_cast<TEnum *>(obj);
162  };
163 
164  // Helper routine to look fo the scope::enum in the typesystem.
165  // If autoload and interpreter lookup is allowed, TClass::GetClass is called.
166  // If not, the list of classes and the list of protoclasses is inspected.
167  auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
168  // Check if the scope is a class
169  if (sa_local == (kALoadAndInterpLookup)) {
170  auto scope = TClass::GetClass(scopeName, true);
171  TEnum *en = nullptr;
172  if (scope) en = findEnumInList(scope->GetListOfEnums(), enName, sa_local);
173  return en;
174  }
175 
176  // Lock need for gROOT->GetListOfClasses() and the later update/modification to
177  // the autoparsing state.
179  if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
180  // If this is a class, load only if the user allowed interpreter lookup
181  // If this is a namespace and the user did not allow for interpreter lookup, load but before disable
182  // autoparsing if enabled.
183  bool canLoadEnums (sa_local & kInterpLookup);
184  const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
185 
186  const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
187  const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
188 
189  TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
190 
191  if (scopeIsNamespace && !autoParseSuspended){
192  canLoadEnums=true;
193  }
194 
195  auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
196 
197  // Previous incarnation of the code re-enabled the auto parsing,
198  // before executing findEnumInList
199  theEnum = findEnumInList(listOfEnums, enName, sa_local);
200  }
201  // Check if the scope is still a protoclass
202  else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
203  auto listOfEnums = tProtoClassscope->GetListOfEnums();
204  if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
205  }
206  return theEnum;
207  };
208 
209  const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
210 
211  if (strchr(lastPos,'<')) {
212  // The unqualified name has template syntax, it can't possibly be an
213  // enum.
214  return nullptr;
215  }
216 
217  if (lastPos != enumName) {
218  // We have a scope
219  // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
220  const auto enName = lastPos;
221  const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
222 #ifdef R__WIN32
223  char *scopeName = new char[scopeNameSize + 1];
224 #else
225  char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
226 #endif
227  strncpy(scopeName, enumName, scopeNameSize);
228  scopeName[scopeNameSize] = '\0';
229  // Three levels of search
230  theEnum = searchEnum(scopeName, enName, kNone);
231  if (!theEnum && (sa & kAutoload)) {
232  const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
233  // It could be an enum in a scope which is not selected
234  if (libsLoaded == 0){
235  gInterpreter->AutoLoad(enumName);
236  }
237  theEnum = searchEnum(scopeName, enName, kAutoload);
238  }
239  if (!theEnum && (sa & kALoadAndInterpLookup)) {
240  if (gDebug > 0) {
241  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);
242  }
243  theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
244  }
245 #ifdef R__WIN32
246  delete [] scopeName;
247 #endif
248  } else {
249  // We don't have any scope: this is a global enum
250  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
251  if (!theEnum && (sa & kAutoload)) {
252  gInterpreter->AutoLoad(enumName);
253  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
254  }
255  if (!theEnum && (sa & kALoadAndInterpLookup)) {
256  if (gDebug > 0) {
257  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);
258  }
259  theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
260  }
261  }
262 
263  return theEnum;
264 }
The TEnum class implements the enum type.
Definition: TEnum.h:42
long long Long64_t
Definition: RtypesCore.h:69
void Update(DeclId_t id)
Definition: TEnum.cxx:101
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:97
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:46
#define gROOT
Definition: TROOT.h:340
bool Bool_t
Definition: RtypesCore.h:59
TClass * fClass
interpreter implementation provided declaration
Definition: TEnum.h:47
#define gInterpreter
Definition: TInterpreter.h:502
const void * DeclId_t
Definition: TDictionary.h:209
virtual ~TEnum()
Destructor.
Definition: TEnum.cxx:61
TClass * GetClass(T *)
Definition: TClass.h:555
Vc_ALWAYS_INLINE void free(T *p)
Frees memory that was allocated with Vc::malloc.
Definition: memory.h:94
char * DemangleName(const char *mangled_name, int &errorCode)
Definition: TClassEdit.h:178
TClass * fClass
pointer to the foreign object
Collection abstract base class.
Definition: TCollection.h:48
TLine * l
Definition: textangle.C:4
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:33
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
ClassImp(TEnum) TEnum
Constructor for TEnum class.
Definition: TEnum.cxx:29
TString fName
Definition: TNamed.h:36
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
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
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:2881
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:108
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.
Definition: TClassEdit.cxx:850
void * fInfo
Definition: TEnum.h:46
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
Definition: TListOfEnums.h:36
virtual void Add(TObject *obj)
Definition: TList.h:81
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TEnum.cxx:94
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
ESearchAction
Definition: TEnum.h:52
THashList fConstantList
Definition: TEnum.h:45
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
gr SetName("gr")