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
13The 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
38TEnum::TEnum(const char *name, DeclId_t declid, TClass *cls)
39 : fInfo(nullptr), fClass(cls)
40{
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
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
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
143TEnum *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
177TEnum *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}
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:95
EDataType
Definition: TDataType.h:28
@ kNumDataTypes
Definition: TDataType.h:40
@ kIsScopedEnum
Definition: TDictionary.h:89
@ kIsEnum
Definition: TDictionary.h:68
@ kIsNamespace
Definition: TDictionary.h:92
char name[80]
Definition: TGX11.cxx:109
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
#define gInterpreter
Definition: TInterpreter.h:555
#define gROOT
Definition: TROOT.h:415
#define R__LOCKGUARD(mutex)
#define free
Definition: civetweb.c:1539
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
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:2906
Collection abstract base class.
Definition: TCollection.h:63
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
const void * DeclId_t
Definition: TDictionary.h:209
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:29
The TEnum class implements the enum type.
Definition: TEnum.h:33
EDataType GetUnderlyingType() const
Get the unterlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Definition: TEnum.cxx:107
@ kBitIsScopedEnum
The enum is an enum class.
Definition: TEnum.h:42
THashList fConstantList
Definition: TEnum.h:36
TClass * GetClass() const
Definition: TEnum.h:58
void AddConstant(TEnumConstant *constant)
Add a EnumConstant to the list of constants of the Enum Type.
Definition: TEnum.cxx:71
ClassInfo_t * fInfo
Definition: TEnum.h:37
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TEnum.cxx:96
TClass * fClass
interpreter information, owned by TEnum
Definition: TEnum.h:38
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:143
void Update(DeclId_t id)
Definition: TEnum.cxx:126
Bool_t IsValid()
Return true if this enum object is pointing to a currently loaded enum.
Definition: TEnum.cxx:81
DeclId_t GetDeclId() const
Definition: TEnum.cxx:116
std::string fQualName
owning class
Definition: TEnum.h:39
ESearchAction
Definition: TEnum.h:47
@ kALoadAndInterpLookup
Definition: TEnum.h:50
@ kNone
Definition: TEnum.h:47
@ kAutoload
Definition: TEnum.h:48
@ kInterpLookup
Definition: TEnum.h:49
TEnum()
Definition: TEnum.h:53
virtual ~TEnum()
Destructor.
Definition: TEnum.cxx:63
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
Definition: TListOfEnums.h:33
virtual void Add(TObject *obj)
Definition: TList.h:87
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
Persistent version of a TClass.
Definition: TProtoClass.h:35
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.
Definition: TClassEdit.cxx:908
char * DemangleName(const char *mangled_name, int &errorCode)
Definition: TClassEdit.h:205
auto * l
Definition: textangle.C:4