Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 std::string normalizedName;
281 {
284 TClassEdit::GetNormalizedName(normalizedName, enumName);
285 }
286
287 if (normalizedName != enumName) {
288 enumName = normalizedName.c_str();
289 lastPos = TClassEdit::GetUnqualifiedName(enumName);
290 }
291
292 // Keep the state consistent. In particular prevent change in the state of
293 // AutoLoading and AutoParsing allowance and gROOT->GetListOfClasses()
294 // and the later update/modification to the autoparsing state.
296
297 if (lastPos != enumName) {
298 // We have a scope
299 const auto enName = lastPos;
300 const auto scopeNameSize = (lastPos - enumName) / sizeof(decltype(*lastPos)) - 2;
301 std::string scopeName{enumName, scopeNameSize};
302 // Three levels of search
303 theEnum = searchEnum(scopeName.c_str(), enName, kNone);
304 if (!theEnum && (sa & kAutoload)) {
305 const auto libsLoaded = gInterpreter->AutoLoad(scopeName.c_str());
306 // It could be an enum in a scope which is not selected
307 if (libsLoaded == 0){
308 gInterpreter->AutoLoad(enumName);
309 }
310 theEnum = searchEnum(scopeName.c_str(), enName, kAutoload);
311 }
312 if (!theEnum && (sa & kALoadAndInterpLookup)) {
313 if (gDebug > 0) {
314 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);
315 }
316 theEnum = searchEnum(scopeName.c_str(), enName, kALoadAndInterpLookup);
317 }
318 } else {
319 // We don't have any scope: this is a global enum
320 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
321 if (!theEnum && (sa & kAutoload)) {
322 gInterpreter->AutoLoad(enumName);
323 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
324 }
325 if (!theEnum && (sa & kALoadAndInterpLookup)) {
326 if (gDebug > 0) {
327 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);
328 }
329 theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
330 }
331 }
332
333 return theEnum;
334}
Cppyy::TCppType_t fClass
#define c(i)
Definition RSha256.hxx:101
long Long_t
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
R__EXTERN TClassTable * gClassTable
@ 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
Int_t gDebug
Definition TROOT.cxx:597
#define gROOT
Definition TROOT.h:406
#define R__WRITE_LOCKGUARD(mutex)
#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:3037
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...
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
TDictionary & operator=(const TDictionary &other)
const void * DeclId_t
The TEnumConstant class implements the constants of the enum type.
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.
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
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:199
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:420
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
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'.
char * DemangleName(const char *mangled_name, int &errorCode)
Definition TClassEdit.h:208
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
TLine l
Definition textangle.C:4