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 : 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
104{
105 if (fInfo)
106 return gInterpreter->GetDeclId(fInfo);
107
108 return nullptr;
109}
110
111////////////////////////////////////////////////////////////////////////////////
112
114{
115 if (fInfo)
116 gInterpreter->ClassInfo_Delete(fInfo);
117 if (!id) {
118 fInfo = nullptr;
119 return;
120 }
121
122 fInfo = gInterpreter->ClassInfo_Factory(id);
123
124 if (fInfo) {
125 SetBit(kBitIsScopedEnum, gInterpreter->ClassInfo_IsScopedEnum(fInfo));
126 fUnderlyingType = gInterpreter->ClassInfo_GetUnderlyingType(fInfo);
127 }
128}
129
130////////////////////////////////////////////////////////////////////////////////
131
132TEnum *TEnum::GetEnum(const std::type_info &ti, ESearchAction sa)
133{
134 int errorCode = 0;
135 char *demangledEnumName = TClassEdit::DemangleName(ti.name(), errorCode);
136
137 if (errorCode != 0) {
138 free(demangledEnumName);
139 std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
140 return nullptr;
141 }
142
143 const char *constDemangledEnumName = demangledEnumName;
144 TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
145 free(demangledEnumName);
146 return en;
147
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Static function to retrieve enumerator from the ROOT's typesystem.
152/// It has no side effect, except when the load flag is true. In this case,
153/// the load of the library containing the scope of the enumerator is attempted.
154/// There are two top level code paths: the enumerator is scoped or isn't.
155/// If it is not, a lookup in the list of global enums is performed.
156/// If it is, two lookups are carried out for its scope: one in the list of
157/// classes and one in the list of protoclasses. If a scope with the desired name
158/// is found, the enum is searched. If the scope is not found, and the load flag is
159/// true, the aforementioned two steps are performed again after an autoload attempt
160/// with the name of the scope as key is tried out.
161/// If the interpreter lookup flag is false, the ListOfEnums objects are not treated
162/// as such, but rather as THashList objects. This prevents any flow of information
163/// from the interpreter into the ROOT's typesystem: a snapshot of the typesystem
164/// status is taken.
165
166TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
167{
168 // Potential optimisation: reduce number of branches using partial specialisation of
169 // helper functions.
170
171 TEnum *theEnum = nullptr;
172
173 // Wrap some gymnastic around the enum finding. The special treatment of the
174 // ListOfEnums objects is located in this routine.
175 auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
176 TObject *obj;
177 if (sa_local & kInterpLookup) {
178 obj = l->FindObject(enName);
179 } else {
180 auto enumTable = dynamic_cast<const TListOfEnums *>(l);
181 obj = enumTable->GetObject(enName);
182 }
183 return static_cast<TEnum *>(obj);
184 };
185
186 // Helper routine to look fo the scope::enum in the typesystem.
187 // If autoload and interpreter lookup is allowed, TClass::GetClass is called.
188 // If not, the list of classes and the list of protoclasses is inspected.
189 auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
190 // Check if the scope is a class
191 if (sa_local == (kALoadAndInterpLookup)) {
192 auto scope = TClass::GetClass(scopeName, true);
193 TEnum *en = nullptr;
194 if (scope) en = findEnumInList(scope->GetListOfEnums(kFALSE), enName, sa_local);
195 return en;
196 }
197
198
199 if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
200 // If this is a class, load only if the user allowed interpreter lookup
201 // If this is a namespace and the user did not allow for interpreter lookup, load but before disable
202 // autoparsing if enabled.
203 bool canLoadEnums (sa_local & kInterpLookup);
204 const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
205
206 const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
207 const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
208
209 TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
210
211 if (scopeIsNamespace && !autoParseSuspended){
212 canLoadEnums=true;
213 }
214
215 auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
216
217 // Previous incarnation of the code re-enabled the auto parsing,
218 // before executing findEnumInList
219 theEnum = findEnumInList(listOfEnums, enName, sa_local);
220 }
221 // Check if the scope is still a protoclass
222 else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
223 auto listOfEnums = tProtoClassscope->GetListOfEnums();
224 if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
225 }
226 return theEnum;
227 };
228
229 const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
230
231 if (strchr(lastPos,'<')) {
232 // The unqualified name has template syntax, it can't possibly be an
233 // enum.
234 return nullptr;
235 }
236
237 // Keep the state consistent. I particular prevent change in the state of AutoLoading and AutoParsing allowance
238 // and gROOT->GetListOfClasses() and the later update/modification to the autoparsing state.
240
241 if (lastPos != enumName) {
242 // We have a scope
243 // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
244 const auto enName = lastPos;
245 const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
246#ifdef R__WIN32
247 char *scopeName = new char[scopeNameSize + 1];
248#else
249 char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
250#endif
251 strncpy(scopeName, enumName, scopeNameSize);
252 scopeName[scopeNameSize] = '\0';
253 // Three levels of search
254 theEnum = searchEnum(scopeName, enName, kNone);
255 if (!theEnum && (sa & kAutoload)) {
256 const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
257 // It could be an enum in a scope which is not selected
258 if (libsLoaded == 0){
259 gInterpreter->AutoLoad(enumName);
260 }
261 theEnum = searchEnum(scopeName, enName, kAutoload);
262 }
263 if (!theEnum && (sa & kALoadAndInterpLookup)) {
264 if (gDebug > 0) {
265 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);
266 }
267 theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
268 }
269#ifdef R__WIN32
270 delete [] scopeName;
271#endif
272 } else {
273 // We don't have any scope: this is a global enum
274 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
275 if (!theEnum && (sa & kAutoload)) {
276 gInterpreter->AutoLoad(enumName);
277 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
278 }
279 if (!theEnum && (sa & kALoadAndInterpLookup)) {
280 if (gDebug > 0) {
281 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);
282 }
283 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
284 }
285 }
286
287 return theEnum;
288}
Cppyy::TCppType_t fClass
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
long long Long64_t
Definition: RtypesCore.h:71
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:94
@ kIsScopedEnum
Definition: TDictionary.h:91
@ kIsEnum
Definition: TDictionary.h:68
@ kIsNamespace
Definition: TDictionary.h:95
char name[80]
Definition: TGX11.cxx:109
#define gInterpreter
Definition: TInterpreter.h:556
#define gROOT
Definition: TROOT.h:406
#define R__READ_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:80
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:2948
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:222
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
@ kBitIsScopedEnum
The enum is an enum class.
Definition: TEnum.h:43
THashList fConstantList
Definition: TEnum.h:36
TClass * GetClass() const
Definition: TEnum.h:59
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
TEnum()=default
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:132
void Update(DeclId_t id)
Definition: TEnum.cxx:113
Bool_t IsValid()
Return true if this enum object is pointing to a currently loaded enum.
Definition: TEnum.cxx:81
EDataType fUnderlyingType
Definition: TEnum.h:40
DeclId_t GetDeclId() const
Definition: TEnum.cxx:103
std::string fQualName
Owning class.
Definition: TEnum.h:39
ESearchAction
Definition: TEnum.h:48
@ kALoadAndInterpLookup
Definition: TEnum.h:51
@ kNone
Definition: TEnum.h:48
@ kAutoload
Definition: TEnum.h:49
@ kInterpLookup
Definition: TEnum.h:50
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:187
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
R__EXTERN TVirtualRWMutex * gCoreMutex
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.
Definition: TClassEdit.cxx:921
char * DemangleName(const char *mangled_name, int &errorCode)
Definition: TClassEdit.h:217
auto * l
Definition: textangle.C:4