Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDataMember.cxx
Go to the documentation of this file.
1// @(#)root/meta:$Id$
2// Author: Fons Rademakers 04/02/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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 TDataMember
13
14All ROOT classes may have RTTI (run time type identification) support
15added. The data is stored in so called DICTIONARY (look at TDictionary).
16Information about a class is stored in TClass.
17This information may be obtained via the cling api - see class TCling.
18TClass has a list of TDataMember objects providing information about all
19data members of described class.
20
21\image html base_classinfo.png
22
23TDataMember provides information about name of data member, its type,
24and comment field string. It also tries to find the TMethodCall objects
25responsible for getting/setting a value of it, and gives you pointers
26to these methods. This gives you a unique possibility to access
27protected and private (!) data members if only methods for doing that
28are defined.
29
30These methods could either be specified in a comment field, or found
31out automatically by ROOT: here's an example:
32suppose you have a class definition:
33~~~ {.cpp}
34 class MyClass{
35 private:
36 Float_t fX1;
37 ...
38 public:
39 void SetX1(Float_t x) {fX1 = x;};
40 Float_t GetX1() {return fX1;};
41 ...
42 }
43~~~
44Look at the data member name and method names: a data member name has
45a prefix letter (f) and has a base name X1 . The methods for getting and
46setting this value have names which consist of string Get/Set and the
47same base name. This convention of naming data fields and methods which
48access them allows TDataMember find this methods by itself completely
49automatically. To make this description complete, one should know,
50that names that are automatically recognized may be also:
51for data fields: either fXXX or fIsXXX; and for getter function
52GetXXX() or IsXXX() [where XXX is base name].
53
54As an example of using it let's analyse a few lines which get and set
55a fEditable field in TCanvas:
56~~~ {.cpp}
57 TCanvas *c = new TCanvas("c"); // create a canvas
58 TClass *cl = c->IsA(); // get its class description object.
59
60 TDataMember *dm = cl->GetDataMember("fEditable"); //This is our data member
61
62 TMethodCall *getter = dm->GetterMethod(c); //find a method that gets value!
63 Long_t l; // declare a storage for this value;
64
65 getter->Execute(c,"",l); // Get this Value !!!! It will appear in l !!!
66
67
68 TMethodCall *setter = dm->SetterMethod(c);
69 setter->Execute(c,"0",); // Set Value 0 !!!
70~~~
71
72This trick is widely used in ROOT TContextMenu and dialogs for obtaining
73current values and put them as initial values in dialog fields.
74
75If you don't want to follow the convention of naming used by ROOT
76you still could benefit from Getter/Setter method support: the solution
77is to instruct ROOT what the names of these routines are.
78The way to do it is putting this information in a comment string to a data
79field in your class declaration:
80
81~~~ {.cpp}
82 class MyClass{
83 Int_t mydata; // *OPTIONS={GetMethod="Get";SetMethod="Set"}
84 ...
85 Int_t Get() const { return mydata;};
86 void Set(Int_t i) {mydata=i;};
87 }
88~~~
89
90However, this getting/setting functions are not the only feature of
91this class. The next point is providing lists of possible settings
92for the concerned data member. The idea is to have a list of possible
93options for this data member, with strings identifying them. This
94is used in dialogs with parameters to set - for details see
95TMethodArg, TRootContextMenu, TContextMenu. This list not only specifies
96the allowed value, but also provides strings naming the options.
97Options are managed via TList of TOptionListItem objects. This list
98is also created automatically: if a data type is an enum type,
99the list will have items describing every enum value, and named
100according to enum name. If type is Bool_t, two options "On" and "Off"
101with values 0 and 1 are created. For other types you need to instruct
102ROOT about possible options. The way to do it is the same as in case of
103specifying getter/setter method: a comment string to a data field in
104Your header file with class definition.
105The most general format of this string is:
106~~~ {.cpp}
107*OPTIONS={GetMethod="getter";SetMethod="setter";Items=(it1="title1",it2="title2", ... ) }
108~~~
109
110While parsing this string ROOT firstly looks for command-tokens:
111GetMethod, SetMethod, Items; They must be preceded by string
112*OPTIONS= , enclosed by {} and separated by semicolons ";".
113All command token should have a form TOKEN=VALUE.
114All tokens are optional.
115The names of getter and setter method must be enclosed by double-quote
116marks (") .
117Specifications of Items is slightly more complicated: you need to
118put token ITEMS= and then enclose all options in curly brackets "()".
119You separate options by comas ",".
120Each option item may have one of the following forms:
121~~~ {.cpp}
122 IntegerValue = "Text Label"
123
124 EnumValue = "Text Label"
125
126 "TextValue" = Text Label"
127
128~~~ {.cpp}
129
130One can specify values as Integers or Enums - when data field is an
131Integer, Float or Enum type; as texts - for char (more precisely:
132Option_t).
133
134As mentioned above - this information are mainly used by contextmenu,
135but also in Dump() and Inspect() methods and by the THtml class.
136*/
137
138#include "TDataMember.h"
139
140#include "strtok.h"
141#include "strlcpy.h"
142#include "TBuffer.h"
143#include "TClass.h"
144#include "TClassEdit.h"
145#include "TDataType.h"
146#include "TEnum.h"
147#include "TEnumConstant.h"
148#include "TGlobal.h"
149#include "TInterpreter.h"
150#include "TIterator.h"
151#include "TList.h"
152#include "TListOfDataMembers.h"
153#include "TMethod.h"
154#include "TMethodArg.h"
155#include "TMethodCall.h"
156#include "TRealData.h"
157#include "TROOT.h"
158#include "TVirtualMutex.h"
159
160#include <cassert>
161#include <cctype>
162#include <cstdlib>
163#include <cstring>
164
165
166////////////////////////////////////////////////////////////////////////////////
167/// Default TDataMember ctor. TDataMembers are constructed in TClass
168/// via a call to TCling::CreateListOfDataMembers(). It parses the comment
169/// string, initializes optionlist and getter/setter methods.
170
171TDataMember::TDataMember(DataMemberInfo_t *info, TClass *cl) : TDictionary()
172{
173 fInfo = info;
174 fClass = cl;
175 fDataType = nullptr;
176 fOptions = nullptr;
177 fValueSetter = nullptr;
178 fValueGetter = nullptr;
179 fOffset = -1;
180 fProperty = -1;
181 fSTLCont = -1;
182 fArrayDim = -1;
183 fArrayMaxIndex=nullptr;
184 if (!fInfo && !fClass) return; // default ctor is called
185
186 Init(false);
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Routines called by the constructor and Update to reset the member's
191/// information.
192/// afterReading is set when initializing after reading through Streamer().
193
194void TDataMember::Init(bool afterReading)
195{
196 if (!afterReading) {
197 // Initialize from fInfo
198 if (!fInfo || !gInterpreter->DataMemberInfo_IsValid(fInfo))
199 return;
200 // Also sets names.
201 Property();
202 }
203 const char *t = GetTitle();
204 if (t && t[0] != '!')
206 fDataType = nullptr;
207 if (IsBasic() || IsEnum()) {
208 if (IsBasic()) {
209 const char *name = GetFullTypeName();
210 if (strcmp(name, "unsigned char") != 0 &&
211 strncmp(name, "unsigned short", sizeof ("unsigned short")) != 0 &&
212 strcmp(name, "unsigned int") != 0 &&
213 strncmp(name, "unsigned long", sizeof ("unsigned long")) != 0)
214 // strncmp() also covers "unsigned long long"
215 name = GetTypeName();
217
218 if (fDataType==nullptr) {
219 // humm we did not find it ... maybe it's a typedef that has not been loaded yet.
220 // (this can happen if the executable does not have a TApplication object).
222 }
223 } else {
224 auto enumdesc = TEnum::GetEnum(GetFullTypeName(), TEnum::kNone);
225 if (enumdesc)
226 fDataType = TDataType::GetDataType(enumdesc->GetUnderlyingType());
227 else
228 fDataType = gROOT->GetType("Int_t", kTRUE); // In rare instance we are called before Int_t has been added to
229 // the list of types in TROOT, the kTRUE insures it is there.
230 }
231 // if (!fDataType)
232 // Error("TDataMember", "basic data type %s not found in list of basic types",
233 // GetTypeName());
234 }
235
236
237 if (afterReading) {
238 // Options are streamed; can't build TMethodCall for getters and setters
239 // because we deserialize a TDataMember when we do not have interpreter
240 // data. Thus do an early return.
241 return;
242 }
243
244 if (strstr(GetTitle(), "*OPTION={")) {
245 // Delay setting fOptions until it's used: the enum constants might
246 // not have been added as members yet.
247
248 // if option string does not exist but it's an Enum - parse it!!!!
249 } else if (IsEnum()) {
250 fOptions = new TList();
251 if (TEnum* enumDict = TEnum::GetEnum(GetTypeName()) ){
252 TIter iEnumConst(enumDict->GetConstants());
253 while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
255 = new TOptionListItem(this, enumConst->GetValue(),0,0,
256 enumConst->GetName(),enumConst->GetName());
257 fOptions->Add(it);
258 }
259 }
260
261 // and the case od Bool_t : we add items "ON" and "Off"
262 } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
263
264 fOptions = new TList();
265 TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",nullptr);
266 fOptions->Add(it);
267 it = new TOptionListItem(this,0,0,0,"Off",nullptr);
268 fOptions->Add(it);
269
270 } else fOptions = nullptr;
271
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// copy constructor
276
278 TDictionary(dm),
279 fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
280 fClass(dm.fClass),
281 fDataType(dm.fDataType),
282 fOffset(dm.fOffset),
283 fSTLCont(dm.fSTLCont),
284 fProperty(dm.fProperty),
285 fArrayDim(dm.fArrayDim),
286 fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr),
287 fArrayIndex(dm.fArrayIndex),
288 fTypeName(dm.fTypeName),
289 fFullTypeName(dm.fFullTypeName),
290 fTrueTypeName(dm.fTrueTypeName),
291 fValueGetter(nullptr),
292 fValueSetter(nullptr),
293 fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr)
294{
295 for(Int_t d = 0; d < fArrayDim; ++d)
297}
298
299////////////////////////////////////////////////////////////////////////////////
300/// assignment operator
301
303{
304 if(this!=&dm) {
306 delete fValueSetter; fValueSetter = nullptr;
307 delete fValueGetter; fValueGetter = nullptr;
308 if (fOptions) {
309 fOptions->Delete();
310 delete fOptions;
311 fOptions = nullptr;
312 }
313
316 fClass=dm.fClass;
318 fOffset=dm.fOffset;
321 fArrayDim = dm.fArrayDim;
322 delete [] fArrayMaxIndex;
323 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr;
324 for(Int_t d = 0; d < fArrayDim; ++d)
330 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr;
331 }
332 return *this;
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// TDataMember dtor deletes adopted CINT DataMemberInfo object.
337
339{
340 delete [] fArrayMaxIndex;
342 delete fValueSetter;
343 delete fValueGetter;
344 if (fOptions) {
345 fOptions->Delete();
346 delete fOptions;
347 }
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Return number of array dimensions.
352
354{
355 if (fArrayDim<0 && fInfo) {
357 TDataMember *dm = const_cast<TDataMember*>(this);
359 // fArrayMaxIndex should be zero
360 if (dm->fArrayDim) {
361 dm->fArrayMaxIndex = new Int_t[fArrayDim];
362 for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
364 }
365 }
366 }
367 return fArrayDim;
368}
369
370////////////////////////////////////////////////////////////////////////////////
371/// If the data member is pointer and has a valid array size in its comments
372/// GetArrayIndex returns a string pointing to it;
373/// otherwise it returns an empty string.
374
375const char *TDataMember::GetArrayIndex() const
376{
377 if (!IsaPointer()) return "";
378 if (fArrayIndex.Length()==0 && fInfo) {
380 TDataMember *dm = const_cast<TDataMember*>(this);
381 const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
382 if (val) dm->fArrayIndex = val;
383 else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
384 }
385 return fArrayIndex;
386}
387
388////////////////////////////////////////////////////////////////////////////////
389
391{
392 if (fInfo) return gInterpreter->GetDeclId(fInfo);
393 else return nullptr;
394}
395
396////////////////////////////////////////////////////////////////////////////////
397/// Return maximum index for array dimension "dim".
398
400{
401 if (fArrayDim<0 && fInfo) {
403 } else {
404 if (dim < 0 || dim >= fArrayDim) return -1;
405 return fArrayMaxIndex[dim];
406 }
407}
408
409////////////////////////////////////////////////////////////////////////////////
410/// Get the decayed type name of this data member, removing `const` and `volatile` qualifiers, and pointers `*` and
411/// references `&`. This function resolves typedefs in the type name. E.g., let `Foo_t` be a typedef to `class
412/// TDirectory`; assuming `this` is a member of type `const Foo_t*`, this function will return `TDirectory`.
413
414const char *TDataMember::GetTypeName() const
415{
416 if (fProperty==(-1)) Property();
417 return fTypeName.Data();
418}
419
420////////////////////////////////////////////////////////////////////////////////
421/// Get the concrete type name of this data member, including `const` and `volatile` qualifiers. This function does not
422/// resolve any typedef in the type name. E.g., let `Foo_t` be a typedef to `class TDirectory`; assuming `this` is a
423/// member of type `const Foo_t*`, this function will return `const Foo_t*`.
424///
425/// For the desugared type name, see TDataMember::GetTrueTypeName().
426
428{
429 if (fProperty==(-1)) Property();
430
431 return fFullTypeName.Data();
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// Get the desugared type name of this data member, including `const` and `volatile` qualifiers. This function
436/// resolves typedefs in the type name. E.g., let `Foo_t` be a typedef to `class TDirectory`; assuming `this` is a
437/// member of type `const Foo_t*`, this function will return `const TDirectory*`.
438
440{
441 return fTrueTypeName.Data();
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// Get offset from "this".
446
448{
449 if (Property() & kIsStatic) {
450 Error("GetOffset", "Cannot get offset of static data member %s", GetName());
451 return -1;
452 }
453
454 if (fOffset >= 0)
455 return fOffset;
456
458 //case of an interpreted or emulated class
459 if (fClass->GetDeclFileLine() < 0) {
460 ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
461 return fOffset;
462 }
463 //case of a compiled class
464 //Note that the offset cannot be computed in case of an abstract class
465 //for which the list of real data has not yet been computed via
466 //a real daughter class.
467 TString dmbracket;
468 dmbracket.Form("%s[",GetName());
471 TRealData *rdm;
472 Int_t offset = 0;
473 while ((rdm = (TRealData*)next())) {
474 char *rdmc = (char*)rdm->GetName();
475 //next statement required in case a class and one of its parent class
476 //have data members with the same name
477 if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
478
479 if (rdm->GetDataMember() != this) continue;
480 if (strcmp(rdmc,GetName()) == 0) {
481 offset = rdm->GetThisOffset();
482 break;
483 }
484 if (strcmp(rdm->GetName(),GetName()) == 0) {
485 if (rdm->IsObject()) {
486 offset = rdm->GetThisOffset();
487 break;
488 }
489 }
490 if (strstr(rdm->GetName(),dmbracket.Data())) {
491 offset = rdm->GetThisOffset();
492 break;
493 }
494 }
495 ((TDataMember*)this)->fOffset = offset;
496 return fOffset;
497}
498
499////////////////////////////////////////////////////////////////////////////////
500/// Get offset from "this" using the information in CINT only.
501
503{
504 if (fOffset >= 0)
505 return fOffset;
506
508 TDataMember *dm = const_cast<TDataMember *>(this);
509
510 if (dm->IsValid()) {
512 dm->fOffset = offset;
513 return offset;
514 }
515 return -1;
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Get the sizeof the underlying type of the data member
520/// (i.e. if the member is an array sizeof(member)/length)
521
523{
524 if (IsaPointer()) return sizeof(void*);
525 if (IsEnum()) {
526 auto e = TEnum::GetEnum(GetTypeName());
527 if (e)
528 return TDataType::GetDataType(e->GetUnderlyingType())->Size();
529 else
530 return sizeof(Int_t);
531 }
532 if (IsBasic())
533 return GetDataType()->Size();
534
536 if (!cl) cl = TClass::GetClass(GetTrueTypeName());
537 if ( cl) return cl->Size();
538
539 Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
540 return 0;
541}
542
543////////////////////////////////////////////////////////////////////////////////
544/// Return true if data member is a basic type, e.g. char, int, long...
545
547{
548 if (fProperty == -1) Property();
549 return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
550}
551
552////////////////////////////////////////////////////////////////////////////////
553/// Return true if data member is an enum.
554
556{
557 if (fProperty == -1) Property();
558 return (fProperty & kIsEnum) ? kTRUE : kFALSE;
559}
560
561////////////////////////////////////////////////////////////////////////////////
562/// Return true if data member is a pointer.
563
565{
566 if (fProperty == -1) Property();
567 return (fProperty & kIsPointer) ? kTRUE : kFALSE;
568}
569
570////////////////////////////////////////////////////////////////////////////////
571/// The return type is defined in TDictionary (kVector, kList, etc.)
572
580
581////////////////////////////////////////////////////////////////////////////////
582/// Return true if this data member object is pointing to a currently
583/// loaded data member. If a function is unloaded after the TDataMember
584/// is created, the TDataMember will be set to be invalid.
585
587{
588 if (fOffset >= 0) return kTRUE;
589
590 // Register the transaction when checking the validity of the object.
592 DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
593 if (newId) {
594 DataMemberInfo_t *info
595 = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
596 Update(info);
597 // We need to make sure that the list of data member is properly
598 // informed and updated.
600 lst->Update(this);
601 }
602 return newId != nullptr;
603 }
604 return fInfo != nullptr;
605}
606
607////////////////////////////////////////////////////////////////////////////////
608/// Get property description word. For meaning of bits see EProperty.
609
611{
612 if (fProperty!=(-1)) return fProperty;
613
615 TDataMember *t = (TDataMember*)this;
616
617 if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
620 t->fProperty = (prop | propt) & ~(kIsPublic | kIsProtected | kIsPrivate);
621 // Set to the strictest access of the member and the type
622 if ((prop | propt) & kIsPrivate)
623 t->fProperty |= kIsPrivate;
624 else if ((prop | propt) & kIsProtected)
626 else
627 t->fProperty |= kIsPublic;
628
632
635
636 return fProperty;
637}
638
639
640////////////////////////////////////////////////////////////////////////////////
641/// Build TOptionListItems from the member comment `*OPTION={`
642
644{
645 if (fOptions)
646 return;
647
648 const char *optTitle = strstr(GetTitle(), "*OPTION={");
649 if (!optTitle)
650 return;
651
652 // If option string exist in comment - we'll parse it and create
653 // list of options
654
655 // Option-list string has a form:
656 // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
657 // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
658 //
659 // As one can see it is possible to specify value as either numerical
660 // value , string or enum.
661 // One can also specify implicitly names of Getter/Setter methods.
662
663 char cmt[2048];
664 char opt[2048];
665 const char *ptr1 = nullptr;
666 char *ptr2 = nullptr;
667 char *ptr3 = nullptr;
668 Int_t cnt = 0;
669 Int_t token_cnt;
670 Int_t i;
671
672 strlcpy(cmt,GetTitle(),2048);
673
674 char *opt_ptr = strstr(cmt, "*OPTION={");
675
676 // If we found it - parsing...
677
678 //let's cut the part lying between {}
679 char *rest;
680 ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
681 if (ptr1 == nullptr) {
682 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
683 return;
684 }
685 ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
686 if (ptr1 == nullptr) {
687 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
688 return;
689 }
690
691 //and save it:
692 strlcpy(opt,ptr1,2048);
693
694 // Let's extract sub-tokens extracted by ';' sign.
695 // We'll put'em in an array for convenience;
696 // You have to do it in this manner because you cannot use nested tokenizing
697
698 std::vector<std::string> tokens; // a storage for these sub-tokens.
699 token_cnt = 0;
700 cnt = 0;
701
702 do { //tokenizing loop
703 ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
704 if (ptr1) {
705 tokens.emplace_back(ptr1);
706 token_cnt++;
707 }
708 } while (ptr1);
709
710 // OK! Now let's check whether we have Get/Set methods encode in any string
711 for (i=0;i<token_cnt;i++) {
712 if (strstr(tokens[i].c_str(),"GetMethod")) {
713 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest); // tokenizing-strip text "GetMethod"
714 if (ptr1 == nullptr) {
715 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
716 return;
717 }
718 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
719 if (ptr1 == nullptr) {
720 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
721 return;
722 }
723
724 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
725 // FIXME: wrong in case called derives via multiple inheritance from this class
726 fValueGetter = new TMethodCall(GetClass(),ptr1,"");
727
728 continue; //next item!
729 }
730
731 if (strstr(tokens[i].c_str(),"SetMethod")) {
732 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest);
733 if (ptr1 == nullptr) {
734 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
735 return;
736 }
737 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
738 if (ptr1 == nullptr) {
739 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
740 return;
741 }
742 // setter method may accept enum data type - therefore check if it exists at all
743 if (GetClass()->GetMethod(ptr1,"1"))
744 // FIXME: wrong in case called derives via multiple inheritance from this class
745 fValueSetter = new TMethodCall(GetClass(), ptr1, "1");
746 else if (auto method = IsEnum() ? GetClass()->GetMethodAny(ptr1) : nullptr) {
747 // if data member is enum, take setter and cast 1 to argument data type
748 auto arg = dynamic_cast<TMethodArg *>(method->GetListOfMethodArgs()->First());
749 auto sarg = TString::Format("(%s) 1", arg ? arg->GetFullTypeName() : "int");
750 fValueSetter = new TMethodCall(GetClass(), ptr1, sarg.Data());
751 }
752 }
753 }
754
755 //Now let's parse option strings...
756
757 Int_t opt_cnt = 0;
758 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
759
760 for (i=0;i<token_cnt;i++) {
761 if (strstr(tokens[i].c_str(),"Items")) {
762 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "()", &rest);
763 if (ptr1 == nullptr) {
764 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
765 return;
766 }
767 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
768 if (ptr1 == nullptr) {
769 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
770 return;
771 }
772
773 char opts[2048]; //and save it!
774 strlcpy(opts,ptr1,2048);
775
776 //now parse it...
777 //firstly we just store strings like: xxx="Label Name"
778 //We'll store it in TOptionListItem objects, because they're derived
779 //from TObject and thus can be stored in TList.
780 //It's not elegant but works.
781 do {
782 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
783 if (ptr1) {
784 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
785 optionlist->Add(it);
786 }
787 } while(ptr1);
788
789 }
790 }
791
792 //having all options extracted and put into list, we finally can parse
793 //them to create a list of options...
794
795 auto enumDict = IsEnum() ? TEnum::GetEnum(GetTypeName()) : nullptr;
796
797 fOptions = new TList(); //create the list
798
799 TIter next(optionlist.get()); //we'll iterate through all
800 //strings containing options
801 TOptionListItem *it = nullptr;
802 TOptionListItem *it1 = nullptr;
803 while ((it=(TOptionListItem*)next())) {
804
805 ptr1 = it->fOptName; // We will change the value of OptName ... but it is fine since we delete the object at the end of the loop.
806 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
807 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
808 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
809
810 if (islabel) {
811 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
812 fOptions->Add(it1);
813 } else {
814
815 char *strtolResult;
816 Long_t l = std::strtol(ptr1, &strtolResult, 10);
817 bool isnumber = (strtolResult != ptr1);
818
819 if (!isnumber) {
820 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
821 if (enumval) {
822 Int_t *value = (Int_t *)(enumval->GetAddress());
823 // We'll try to find global enum existing in ROOT...
824 l = (Long_t)(*value);
825 } else if (IsEnum()) {
826 if (auto enumConst = enumDict ? (TEnumConstant*) enumDict->GetConstants()->FindObject(ptr1) : nullptr)
827 l = enumConst->GetValue();
828 else
829 l = gInterpreter->Calc(TString::Format("%s;", ptr1));
830 } else {
831 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
832 }
833 }
834
835 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
836 fOptions->Add(it1);
837 }
838
839 optionlist->Remove(it); //delete this option string from list
840 delete it; // and dispose of it.
841
842 }
843
844}
845
846
847////////////////////////////////////////////////////////////////////////////////
848/// Returns list of options - list of TOptionListItems
849
856
857////////////////////////////////////////////////////////////////////////////////
858/// Return a TMethodCall method responsible for getting the value
859/// of data member. The cl argument specifies the class of the object
860/// which will be used to call this method (in case of multiple
861/// inheritance TMethodCall needs to know this to calculate the proper
862/// offset).
863
865{
866 if (!fValueGetter || cl) {
867
869
870 if (!cl) cl = fClass;
871
872 if (fValueGetter) {
873 TString methodname = fValueGetter->GetMethodName();
874 delete fValueGetter;
875 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
876
877 } else {
878 // try to guess Getter function:
879 // we strip the fist character of name of data field ('f') and then
880 // try to find the name of Getter by applying "Get", "Is" or "Has"
881 // as a prefix
882
883 const char *dataname = GetName();
884
885 TString gettername;
886 gettername.Form( "Get%s", dataname+1);
887 if (GetClass()->GetMethod(gettername, ""))
888 return fValueGetter = new TMethodCall(cl, gettername, "");
889 gettername.Form( "Is%s", dataname+1);
890 if (GetClass()->GetMethod(gettername, ""))
891 return fValueGetter = new TMethodCall(cl, gettername, "");
892 gettername.Form( "Has%s", dataname+1);
893 if (GetClass()->GetMethod(gettername, ""))
894 return fValueGetter = new TMethodCall(cl, gettername, "");
895 }
896 }
897
898 return fValueGetter;
899}
900
901////////////////////////////////////////////////////////////////////////////////
902/// Return a TMethodCall method responsible for setting the value
903/// of data member. The cl argument specifies the class of the object
904/// which will be used to call this method (in case of multiple
905/// inheritance TMethodCall needs to know this to calculate the proper
906/// offset).
907
909{
910 if (!fValueSetter || cl) {
911
913
914 if (!cl) cl = fClass;
915
916 if (fValueSetter) {
917
918 TString methodname = fValueSetter->GetMethodName();
919 TString params = fValueSetter->GetParams();
920 delete fValueSetter;
921 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
922
923 } else {
924
925 // try to guess Setter function:
926 // we strip the fist character of name of data field ('f') and then
927 // try to find the name of Setter by applying "Set" as a prefix
928
929 const char *dataname = GetName();
930
931 TString settername;
932 settername.Form( "Set%s", dataname+1);
933 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
934 if (GetClass()->GetMethod(settername, "0"))
935 fValueSetter = new TMethodCall(cl, settername, "0");
936 if (!fValueSetter)
937 if (GetClass()->GetMethod(settername, "true"))
938 fValueSetter = new TMethodCall(cl, settername, "true");
939 }
940 }
941
942 return fValueSetter;
943}
944
945////////////////////////////////////////////////////////////////////////////////
946/// Update the TFunction to reflect the new info.
947///
948/// This can be used to implement unloading (info == 0) and then reloading
949/// (info being the 'new' decl address).
950
951Bool_t TDataMember::Update(DataMemberInfo_t *info)
952{
954
958 if (fOptions) {
959 fOptions->Delete();
961 }
962
963 if (info == nullptr) {
964 fOffset = -1;
965 fProperty = -1;
966 fSTLCont = -1;
967 fArrayDim = -1;
968 delete [] fArrayMaxIndex;
969 fArrayMaxIndex=nullptr;
971
972 fInfo = nullptr;
973 return kTRUE;
974 } else {
975 fInfo = info;
976 Init(false);
977 return kTRUE;
978 }
979}
980
981
982////////////////////////////////////////////////////////////////////////////////
983/// Stream an object of TDataMember. Forces calculation of all cached
984/// (and persistent) values.
985
987 if (b.IsReading()) {
988 b.ReadClassBuffer(Class(), this);
989 Init(true /*reading*/);
990 } else {
991 // Writing.
992 if (fProperty & kIsStatic) {
993 // We have a static member and in this case fOffset contains the
994 // actual address in memory of the data, it will be different everytime,
995 // let's not record it.
996 fOffset = -1;
997 } else {
998 GetOffset();
999 }
1001 GetArrayDim();
1002 GetArrayIndex();
1003 Property(); // also calculates fTypeName and friends
1004 b.WriteClassBuffer(Class(), this);
1005 }
1006}
1007
1008////////////////////////////////////////////////////////////////////////////////
1009/// Constructor.
1010
1012 Long_t tglmask,const char *name, const char *label)
1013{
1014 fDataMember = d;
1015 fValue = val;
1016 fValueMaskBit = valmask;
1017 fToggleMaskBit = tglmask;
1018 if (name) {
1019 fOptName = name;
1020 }
1021
1022 if (label) {
1023 fOptLabel = label;
1024 }
1025}
interop::TCppScope_t fClass
#define SafeDelete(p)
Definition RConfig.hxx:507
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:90
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:52
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
@ kIsPublic
Definition TDictionary.h:75
@ kIsPointer
Definition TDictionary.h:78
@ kIsEnum
Definition TDictionary.h:68
@ kIsPrivate
Definition TDictionary.h:77
@ kIsFundamental
Definition TDictionary.h:70
@ kIsStatic
Definition TDictionary.h:80
@ kIsProtected
Definition TDictionary.h:76
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h prop
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:142
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
#define gInterpreter
#define gROOT
Definition TROOT.h:417
#define R__LOCKGUARD(mutex)
Buffer base class used for serializing objects.
Definition TBuffer.h:43
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2043
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3833
Short_t GetDeclFileLine() const
Definition TClass.h:444
TList * GetListOfRealData() const
Definition TClass.h:468
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5875
ClassInfo_t * GetClassInfo() const
Definition TClass.h:448
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:2999
TObject * Clone(const char *newname="") const override
Make a clone of an collection using the Streamer facility.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
virtual ~TDataMember()
TDataMember dtor deletes adopted CINT DataMemberInfo object.
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
TDataMember(const TDataMember &)
copy constructor
Long_t fProperty
Definition TDataMember.h:44
TString fFullTypeName
Definition TDataMember.h:50
TString fTypeName
Definition TDataMember.h:49
void Streamer(TBuffer &) override
Stream an object of TDataMember.
TMethodCall * SetterMethod(TClass *cl)
Return a TMethodCall method responsible for setting the value of data member.
virtual bool Update(DataMemberInfo_t *info)
Update the TFunction to reflect the new info.
TDataMember & operator=(const TDataMember &)
assignment operator
const char * GetTrueTypeName() const
Get the desugared type name of this data member, including const and volatile qualifiers.
Longptr_t GetOffsetCint() const
Get offset from "this" using the information in CINT only.
DataMemberInfo_t * fInfo
!pointer to CINT data member info
Definition TDataMember.h:38
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
Int_t * fArrayMaxIndex
Definition TDataMember.h:46
TString fTrueTypeName
Definition TDataMember.h:51
TMethodCall * fValueGetter
!method that returns a value;
Definition TDataMember.h:56
Int_t GetArrayDim() const
Return number of array dimensions.
Longptr_t fOffset
Definition TDataMember.h:42
Bool_t IsEnum() const
Return true if data member is an enum.
TList * GetOptions()
Returns list of options - list of TOptionListItems.
void Init(bool afterReading)
Routines called by the constructor and Update to reset the member's information.
Int_t GetUnitSize() const
Get the sizeof the underlying type of the data member (i.e.
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
Bool_t IsaPointer() const
Return true if data member is a pointer.
Bool_t IsValid()
Return true if this data member object is pointing to a currently loaded data member.
TMethodCall * GetterMethod(TClass *cl=nullptr)
Return a TMethodCall method responsible for getting the value of data member.
TClass * fClass
!pointer to the class
Definition TDataMember.h:39
void ExtractOptionsFromComment()
Build TOptionListItems from the member comment *OPTION={
TDataType * GetDataType() const
Definition TDataMember.h:76
Longptr_t GetOffset() const
Get offset from "this".
const char * GetTypeName() const
Get the decayed type name of this data member, removing const and volatile qualifiers,...
DeclId_t GetDeclId() const
TMethodCall * fValueSetter
!method which sets value;
Definition TDataMember.h:57
TList * fOptions
Definition TDataMember.h:58
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
Int_t fSTLCont
Definition TDataMember.h:43
TDataType * fDataType
!pointer to data basic type descriptor
Definition TDataMember.h:40
const char * GetFullTypeName() const
Get the concrete type name of this data member, including const and volatile qualifiers.
TString fArrayIndex
Definition TDataMember.h:47
TClass * GetClass() const
Definition TDataMember.h:75
Int_t fArrayDim
Definition TDataMember.h:45
static TClass * Class()
Int_t GetType() const
Definition TDataType.h:71
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Int_t Size() const
Get size of basic typedef'ed type.
This class defines an abstract interface that must be implemented by all classes that contain diction...
Bool_t UpdateInterpreterStateMarker()
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
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:181
@ kNone
Definition TEnum.h:55
Global variables class (global variables are obtained from CINT).
Definition TGlobal.h:28
virtual void * GetAddress() const
Return address of global.
Definition TGlobal.cxx:80
virtual DataMemberInfo_t * DataMemberInfo_FactoryCopy(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
virtual Longptr_t DataMemberInfo_Offset(DataMemberInfo_t *) const
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
virtual const char * TypeName(const char *s)=0
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
void Update(TDictionary *member)
Move the member or data member to the expect set of list.
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition TMethodArg.h:36
Method or function calling interface.
Definition TMethodCall.h:37
const char * GetMethodName() const
Definition TMethodCall.h:90
const char * GetParams() const
Definition TMethodCall.h:91
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
Long_t fToggleMaskBit
TDataMember * fDataMember
!Data member to which this option belongs
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
const char * GetName() const override
Returns name of object.
Definition TRealData.h:52
TDataMember * GetDataMember() const
Definition TRealData.h:53
Bool_t IsObject() const
Definition TRealData.h:56
Long_t GetThisOffset() const
Definition TRealData.h:55
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1242
const char * Data() const
Definition TString.h:385
TString & Append(const char *cs)
Definition TString.h:582
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
ROOT::ESTLType UnderlyingIsSTLCont(std::string_view type)
Return the type of STL collection, if any, that is the underlying type of the given type.
TLine l
Definition textangle.C:4