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/// Copy constructor
62
64{
65 fClass = src.fClass;
66 fInfo = src.fInfo ? gInterpreter->ClassInfo_Factory(src.fInfo) : nullptr;
67 fQualName = src.fQualName;
68 fUnderlyingType = src.fUnderlyingType;
69
70 Bool_t isowner = src.fConstantList.IsOwner();
71 fConstantList.SetOwner(isowner);
72 TIter next(&src.fConstantList);
73 while (auto c = (TEnumConstant *) next())
74 fConstantList.Add(isowner ? new TEnumConstant(*c) : c);
75
76}
77
78////////////////////////////////////////////////////////////////////////////////
79/// Assign operator
80
82{
83 if (this != &src) {
84 if (fInfo)
85 gInterpreter->ClassInfo_Delete(fInfo);
87
89
90 fInfo = src.fInfo ? gInterpreter->ClassInfo_Factory(src.fInfo) : nullptr;
91 fQualName = src.fQualName;
92 fUnderlyingType = src.fUnderlyingType;
93
94 Bool_t isowner = src.fConstantList.IsOwner();
95 fConstantList.SetOwner(isowner);
96 TIter next(&src.fConstantList);
97 while (auto c = (TEnumConstant *) next())
98 fConstantList.Add(isowner ? new TEnumConstant(*c) : c);
99 }
100 return *this;
101}
102
103////////////////////////////////////////////////////////////////////////////////
104/// Destructor
105
107{
108 gInterpreter->ClassInfo_Delete(fInfo);
109}
110
111////////////////////////////////////////////////////////////////////////////////
112/// Add a EnumConstant to the list of constants of the Enum Type.
113
115{
116 fConstantList.Add(constant);
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Return true if this enum object is pointing to a currently
121/// loaded enum. If a enum is unloaded after the TEnum
122/// is created, the TEnum will be set to be invalid.
123
125{
126 // Register the transaction when checking the validity of the object.
128 DeclId_t newId = gInterpreter->GetEnum(fClass, fName);
129 if (newId)
130 Update(newId);
131 return newId != nullptr;
132 }
133 return fInfo != nullptr;
134}
135
136////////////////////////////////////////////////////////////////////////////////
137/// Get property description word. For meaning of bits see EProperty.
138
140{
142}
143
144////////////////////////////////////////////////////////////////////////////////
145
147{
148 if (fInfo)
149 return gInterpreter->GetDeclId(fInfo);
150
151 return nullptr;
152}
153
154////////////////////////////////////////////////////////////////////////////////
155
157{
158 if (fInfo)
159 gInterpreter->ClassInfo_Delete(fInfo);
160 if (!id) {
161 fInfo = nullptr;
162 return;
163 }
164
165 fInfo = gInterpreter->ClassInfo_Factory(id);
166
167 if (fInfo) {
168 SetBit(kBitIsScopedEnum, gInterpreter->ClassInfo_IsScopedEnum(fInfo));
169 fUnderlyingType = gInterpreter->ClassInfo_GetUnderlyingType(fInfo);
170 }
171}
172
173////////////////////////////////////////////////////////////////////////////////
174
175TEnum *TEnum::GetEnum(const std::type_info &ti, ESearchAction sa)
176{
177 int errorCode = 0;
178 char *demangledEnumName = TClassEdit::DemangleName(ti.name(), errorCode);
179
180 if (errorCode != 0) {
181 free(demangledEnumName);
182 std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
183 return nullptr;
184 }
185
186 const char *constDemangledEnumName = demangledEnumName;
187 TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
188 free(demangledEnumName);
189 return en;
190
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Static function to retrieve enumerator from the ROOT's typesystem.
195/// It has no side effect, except when the load flag is true. In this case,
196/// the load of the library containing the scope of the enumerator is attempted.
197/// There are two top level code paths: the enumerator is scoped or isn't.
198/// If it is not, a lookup in the list of global enums is performed.
199/// If it is, two lookups are carried out for its scope: one in the list of
200/// classes and one in the list of protoclasses. If a scope with the desired name
201/// is found, the enum is searched. If the scope is not found, and the load flag is
202/// true, the aforementioned two steps are performed again after an autoload attempt
203/// with the name of the scope as key is tried out.
204/// If the interpreter lookup flag is false, the ListOfEnums objects are not treated
205/// as such, but rather as THashList objects. This prevents any flow of information
206/// from the interpreter into the ROOT's typesystem: a snapshot of the typesystem
207/// status is taken.
208
209TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
210{
211 // Potential optimisation: reduce number of branches using partial specialisation of
212 // helper functions.
213
214 TEnum *theEnum = nullptr;
215
216 // Wrap some gymnastic around the enum finding. The special treatment of the
217 // ListOfEnums objects is located in this routine.
218 auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
219 TObject *obj;
220 if (sa_local & kInterpLookup) {
221 obj = l->FindObject(enName);
222 } else {
223 auto enumTable = dynamic_cast<const TListOfEnums *>(l);
224 obj = enumTable->GetObject(enName);
225 }
226 return static_cast<TEnum *>(obj);
227 };
228
229 // Helper routine to look fo the scope::enum in the typesystem.
230 // If autoload and interpreter lookup is allowed, TClass::GetClass is called.
231 // If not, the list of classes and the list of protoclasses is inspected.
232 auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
233 // Check if the scope is a class
234 if (sa_local == (kALoadAndInterpLookup)) {
235 auto scope = TClass::GetClass(scopeName, true);
236 TEnum *en = nullptr;
237 if (scope) en = findEnumInList(scope->GetListOfEnums(kFALSE), enName, sa_local);
238 return en;
239 }
240
241
242 if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
243 // If this is a class, load only if the user allowed interpreter lookup
244 // If this is a namespace and the user did not allow for interpreter lookup, load but before disable
245 // autoparsing if enabled.
246 bool canLoadEnums (sa_local & kInterpLookup);
247 const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
248
249 const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
250 const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
251
252 TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
253
254 if (scopeIsNamespace && !autoParseSuspended){
255 canLoadEnums=true;
256 }
257
258 auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
259
260 // Previous incarnation of the code re-enabled the auto parsing,
261 // before executing findEnumInList
262 theEnum = findEnumInList(listOfEnums, enName, sa_local);
263 }
264 // Check if the scope is still a protoclass
265 else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
266 auto listOfEnums = tProtoClassscope->GetListOfEnums();
267 if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
268 }
269 return theEnum;
270 };
271
272 const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
273
274 if (strchr(lastPos,'<')) {
275 // The unqualified name has template syntax, it can't possibly be an
276 // enum.
277 return nullptr;
278 }
279
280 // Keep the state consistent. I particular prevent change in the state of AutoLoading and AutoParsing allowance
281 // and gROOT->GetListOfClasses() and the later update/modification to the autoparsing state.
283
284 if (lastPos != enumName) {
285 // We have a scope
286 // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
287 const auto enName = lastPos;
288 const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
289#ifdef R__WIN32
290 char *scopeName = new char[scopeNameSize + 1];
291#else
292 char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
293#endif
294 strncpy(scopeName, enumName, scopeNameSize);
295 scopeName[scopeNameSize] = '\0';
296 // Three levels of search
297 theEnum = searchEnum(scopeName, enName, kNone);
298 if (!theEnum && (sa & kAutoload)) {
299 const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
300 // It could be an enum in a scope which is not selected
301 if (libsLoaded == 0){
302 gInterpreter->AutoLoad(enumName);
303 }
304 theEnum = searchEnum(scopeName, enName, kAutoload);
305 }
306 if (!theEnum && (sa & kALoadAndInterpLookup)) {
307 if (gDebug > 0) {
308 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);
309 }
310 theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
311 }
312#ifdef R__WIN32
313 delete [] scopeName;
314#endif
315 } else {
316 // We don't have any scope: this is a global enum
317 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
318 if (!theEnum && (sa & kAutoload)) {
319 gInterpreter->AutoLoad(enumName);
320 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
321 }
322 if (!theEnum && (sa & kALoadAndInterpLookup)) {
323 if (gDebug > 0) {
324 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);
325 }
326 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
327 }
328 }
329
330 return theEnum;
331}
Cppyy::TCppType_t fClass
#define c(i)
Definition: RSha256.hxx:101
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:375
R__EXTERN TClassTable * gClassTable
Definition: TClassTable.h:95
@ kIsScopedEnum
Definition: TDictionary.h:91
@ kIsEnum
Definition: TDictionary.h:68
@ kIsNamespace
Definition: TDictionary.h:95
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
char name[80]
Definition: TGX11.cxx:110
#define gInterpreter
Definition: TInterpreter.h:564
Int_t gDebug
Definition: TROOT.cxx:585
#define gROOT
Definition: TROOT.h:404
#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:81
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:2969
Collection abstract base class.
Definition: TCollection.h:65
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:167
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
TDictionary & operator=(const TDictionary &other)
Definition: TDictionary.cxx:62
const void * DeclId_t
Definition: TDictionary.h:223
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
TEnum & operator=(const TEnum &)
Assign operator.
Definition: TEnum.cxx:81
@ kBitIsScopedEnum
The enum is an enum class.
Definition: TEnum.h:43
THashList fConstantList
Definition: TEnum.h:36
TClass * GetClass() const
Definition: TEnum.h:62
void AddConstant(TEnumConstant *constant)
Add a EnumConstant to the list of constants of the Enum Type.
Definition: TEnum.cxx:114
ClassInfo_t * fInfo
Definition: TEnum.h:37
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
Definition: TEnum.cxx:139
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:175
void Update(DeclId_t id)
Definition: TEnum.cxx:156
Bool_t IsValid()
Return true if this enum object is pointing to a currently loaded enum.
Definition: TEnum.cxx:124
EDataType fUnderlyingType
Definition: TEnum.h:40
DeclId_t GetDeclId() const
Definition: TEnum.cxx:146
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
TEnum()
Definition: TEnum.h:54
virtual ~TEnum()
Destructor.
Definition: TEnum.cxx:106
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition: THashList.cxx:189
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
Definition: TListOfEnums.h:33
void Add(TObject *obj) override
Definition: TList.h:81
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition: TNamed.h:48
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
Mother of all ROOT objects.
Definition: TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:201
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:404
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:775
Persistent version of a TClass.
Definition: TProtoClass.h:38
R__EXTERN TVirtualRWMutex * gCoreMutex
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.
Definition: TClassEdit.cxx:942
char * DemangleName(const char *mangled_name, int &errorCode)
Definition: TClassEdit.h:218
TLine l
Definition: textangle.C:4