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 "TMethodCall.h"
155#include "TRealData.h"
156#include "TROOT.h"
157#include "TVirtualMutex.h"
158
159#include <cassert>
160#include <cctype>
161#include <cstdlib>
162#include <cstring>
163
164
165////////////////////////////////////////////////////////////////////////////////
166/// Default TDataMember ctor. TDataMembers are constructed in TClass
167/// via a call to TCling::CreateListOfDataMembers(). It parses the comment
168/// string, initializes optionlist and getter/setter methods.
169
171{
172 fInfo = info;
173 fClass = cl;
174 fDataType = nullptr;
175 fOptions = nullptr;
176 fValueSetter = nullptr;
177 fValueGetter = nullptr;
178 fOffset = -1;
179 fProperty = -1;
180 fSTLCont = -1;
181 fArrayDim = -1;
182 fArrayMaxIndex=nullptr;
183 if (!fInfo && !fClass) return; // default ctor is called
184
185 Init(false);
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Routines called by the constructor and Update to reset the member's
190/// information.
191/// afterReading is set when initializing after reading through Streamer().
192
194{
195 if (!afterReading) {
196 // Initialize from fInfo
197 if (!fInfo || !gInterpreter->DataMemberInfo_IsValid(fInfo))
198 return;
199 // Also sets names.
200 Property();
201 }
202 const char *t = GetTitle();
203 if (t && t[0] != '!')
205 fDataType = nullptr;
206 if (IsBasic() || IsEnum()) {
207 if (IsBasic()) {
208 const char *name = GetFullTypeName();
209 if (strcmp(name, "unsigned char") != 0 &&
210 strncmp(name, "unsigned short", sizeof ("unsigned short")) != 0 &&
211 strcmp(name, "unsigned int") != 0 &&
212 strncmp(name, "unsigned long", sizeof ("unsigned long")) != 0)
213 // strncmp() also covers "unsigned long long"
214 name = GetTypeName();
216
217 if (fDataType==nullptr) {
218 // humm we did not find it ... maybe it's a typedef that has not been loaded yet.
219 // (this can happen if the executable does not have a TApplication object).
221 }
222 } else {
224 if (enumdesc)
225 fDataType = TDataType::GetDataType(enumdesc->GetUnderlyingType());
226 else
227 fDataType = gROOT->GetType("Int_t", kTRUE); // In rare instance we are called before Int_t has been added to
228 // the list of types in TROOT, the kTRUE insures it is there.
229 }
230 // if (!fDataType)
231 // Error("TDataMember", "basic data type %s not found in list of basic types",
232 // GetTypeName());
233 }
234
235
236 if (afterReading) {
237 // Options are streamed; can't build TMethodCall for getters and setters
238 // because we deserialize a TDataMember when we do not have interpreter
239 // data. Thus do an early return.
240 return;
241 }
242
243 if (strstr(GetTitle(), "*OPTION={")) {
244 // Delay setting fOptions until it's used: the enum constants might
245 // not have been added as members yet.
246
247 // if option string does not exist but it's an Enum - parse it!!!!
248 } else if (IsEnum()) {
249 fOptions = new TList();
251 TIter iEnumConst(enumDict->GetConstants());
254 = new TOptionListItem(this, enumConst->GetValue(),0,0,
255 enumConst->GetName(),enumConst->GetName());
256 fOptions->Add(it);
257 }
258 }
259
260 // and the case od Bool_t : we add items "ON" and "Off"
261 } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
262
263 fOptions = new TList();
264 TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",nullptr);
265 fOptions->Add(it);
266 it = new TOptionListItem(this,0,0,0,"Off",nullptr);
267 fOptions->Add(it);
268
269 } else fOptions = nullptr;
270
271}
272
273////////////////////////////////////////////////////////////////////////////////
274/// copy constructor
275
277 TDictionary(dm),
278 fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
279 fClass(dm.fClass),
280 fDataType(dm.fDataType),
281 fOffset(dm.fOffset),
282 fSTLCont(dm.fSTLCont),
283 fProperty(dm.fProperty),
284 fArrayDim(dm.fArrayDim),
285 fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr),
286 fArrayIndex(dm.fArrayIndex),
287 fTypeName(dm.fTypeName),
288 fFullTypeName(dm.fFullTypeName),
289 fTrueTypeName(dm.fTrueTypeName),
290 fValueGetter(nullptr),
291 fValueSetter(nullptr),
292 fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr)
293{
294 for(Int_t d = 0; d < fArrayDim; ++d)
296}
297
298////////////////////////////////////////////////////////////////////////////////
299/// assignment operator
300
302{
303 if(this!=&dm) {
305 delete fValueSetter; fValueSetter = nullptr;
306 delete fValueGetter; fValueGetter = nullptr;
307 if (fOptions) {
308 fOptions->Delete();
309 delete fOptions;
310 fOptions = nullptr;
311 }
312
315 fClass=dm.fClass;
317 fOffset=dm.fOffset;
320 fArrayDim = dm.fArrayDim;
321 delete [] fArrayMaxIndex;
322 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr;
323 for(Int_t d = 0; d < fArrayDim; ++d)
329 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr;
330 }
331 return *this;
332}
333
334////////////////////////////////////////////////////////////////////////////////
335/// TDataMember dtor deletes adopted CINT DataMemberInfo object.
336
338{
339 delete [] fArrayMaxIndex;
341 delete fValueSetter;
342 delete fValueGetter;
343 if (fOptions) {
344 fOptions->Delete();
345 delete fOptions;
346 }
347}
348
349////////////////////////////////////////////////////////////////////////////////
350/// Return number of array dimensions.
351
353{
354 if (fArrayDim<0 && fInfo) {
356 TDataMember *dm = const_cast<TDataMember*>(this);
358 // fArrayMaxIndex should be zero
359 if (dm->fArrayDim) {
360 dm->fArrayMaxIndex = new Int_t[fArrayDim];
361 for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
363 }
364 }
365 }
366 return fArrayDim;
367}
368
369////////////////////////////////////////////////////////////////////////////////
370/// If the data member is pointer and has a valid array size in its comments
371/// GetArrayIndex returns a string pointing to it;
372/// otherwise it returns an empty string.
373
374const char *TDataMember::GetArrayIndex() const
375{
376 if (!IsaPointer()) return "";
377 if (fArrayIndex.Length()==0 && fInfo) {
379 TDataMember *dm = const_cast<TDataMember*>(this);
380 const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
381 if (val) dm->fArrayIndex = val;
382 else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
383 }
384 return fArrayIndex;
385}
386
387////////////////////////////////////////////////////////////////////////////////
388
390{
391 if (fInfo) return gInterpreter->GetDeclId(fInfo);
392 else return nullptr;
393}
394
395////////////////////////////////////////////////////////////////////////////////
396/// Return maximum index for array dimension "dim".
397
399{
400 if (fArrayDim<0 && fInfo) {
402 } else {
403 if (dim < 0 || dim >= fArrayDim) return -1;
404 return fArrayMaxIndex[dim];
405 }
406}
407
408////////////////////////////////////////////////////////////////////////////////
409/// Get the decayed type name of this data member, removing `const` and `volatile` qualifiers, and pointers `*` and
410/// references `&`. This function resolves typedefs in the type name. E.g., let `Foo_t` be a typedef to `class
411/// TDirectory`; assuming `this` is a member of type `const Foo_t*`, this function will return `TDirectory`.
412
413const char *TDataMember::GetTypeName() const
414{
415 if (fProperty==(-1)) Property();
416 return fTypeName.Data();
417}
418
419////////////////////////////////////////////////////////////////////////////////
420/// Get the concrete type name of this data member, including `const` and `volatile` qualifiers. This function does not
421/// resolve any typedef in the type name. E.g., let `Foo_t` be a typedef to `class TDirectory`; assuming `this` is a
422/// member of type `const Foo_t*`, this function will return `const Foo_t*`.
423///
424/// For the desugared type name, see TDataMember::GetTrueTypeName().
425
427{
428 if (fProperty==(-1)) Property();
429
430 return fFullTypeName.Data();
431}
432
433////////////////////////////////////////////////////////////////////////////////
434/// Get the desugared type name of this data member, including `const` and `volatile` qualifiers. This function
435/// resolves typedefs in the type name. E.g., let `Foo_t` be a typedef to `class TDirectory`; assuming `this` is a
436/// member of type `const Foo_t*`, this function will return `const TDirectory*`.
437
439{
440 return fTrueTypeName.Data();
441}
442
443////////////////////////////////////////////////////////////////////////////////
444/// Get offset from "this".
445
447{
448 if (fOffset>=0) return fOffset;
449
451 //case of an interpreted or emulated class
452 if (fClass->GetDeclFileLine() < 0) {
453 ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
454 return fOffset;
455 }
456 //case of a compiled class
457 //Note that the offset cannot be computed in case of an abstract class
458 //for which the list of real data has not yet been computed via
459 //a real daughter class.
461 dmbracket.Form("%s[",GetName());
464 TRealData *rdm;
465 Int_t offset = 0;
466 while ((rdm = (TRealData*)next())) {
467 char *rdmc = (char*)rdm->GetName();
468 //next statement required in case a class and one of its parent class
469 //have data members with the same name
470 if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
471
472 if (rdm->GetDataMember() != this) continue;
473 if (strcmp(rdmc,GetName()) == 0) {
474 offset = rdm->GetThisOffset();
475 break;
476 }
477 if (strcmp(rdm->GetName(),GetName()) == 0) {
478 if (rdm->IsObject()) {
479 offset = rdm->GetThisOffset();
480 break;
481 }
482 }
483 if (strstr(rdm->GetName(),dmbracket.Data())) {
484 offset = rdm->GetThisOffset();
485 break;
486 }
487 }
488 ((TDataMember*)this)->fOffset = offset;
489 return fOffset;
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Get offset from "this" using the information in CINT only.
494
496{
497 if (fOffset>=0) return fOffset;
498
500 TDataMember *dm = const_cast<TDataMember*>(this);
501
502 if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
503 else return -1;
504}
505
506////////////////////////////////////////////////////////////////////////////////
507/// Get the sizeof the underlying type of the data member
508/// (i.e. if the member is an array sizeof(member)/length)
509
511{
512 if (IsaPointer()) return sizeof(void*);
513 if (IsEnum()) {
514 auto e = TEnum::GetEnum(GetTypeName());
515 if (e)
516 return TDataType::GetDataType(e->GetUnderlyingType())->Size();
517 else
518 return sizeof(Int_t);
519 }
520 if (IsBasic())
521 return GetDataType()->Size();
522
524 if (!cl) cl = TClass::GetClass(GetTrueTypeName());
525 if ( cl) return cl->Size();
526
527 Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
528 return 0;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Return true if data member is a basic type, e.g. char, int, long...
533
535{
536 if (fProperty == -1) Property();
537 return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Return true if data member is an enum.
542
544{
545 if (fProperty == -1) Property();
546 return (fProperty & kIsEnum) ? kTRUE : kFALSE;
547}
548
549////////////////////////////////////////////////////////////////////////////////
550/// Return true if data member is a pointer.
551
553{
554 if (fProperty == -1) Property();
555 return (fProperty & kIsPointer) ? kTRUE : kFALSE;
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// The return type is defined in TDictionary (kVector, kList, etc.)
560
568
569////////////////////////////////////////////////////////////////////////////////
570/// Return true if this data member object is pointing to a currently
571/// loaded data member. If a function is unloaded after the TDataMember
572/// is created, the TDataMember will be set to be invalid.
573
575{
576 if (fOffset >= 0) return kTRUE;
577
578 // Register the transaction when checking the validity of the object.
580 DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
581 if (newId) {
583 = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
584 Update(info);
585 // We need to make sure that the list of data member is properly
586 // informed and updated.
588 lst->Update(this);
589 }
590 return newId != nullptr;
591 }
592 return fInfo != nullptr;
593}
594
595////////////////////////////////////////////////////////////////////////////////
596/// Get property description word. For meaning of bits see EProperty.
597
626
627
628////////////////////////////////////////////////////////////////////////////////
629/// Build TOptionListItems from the member comment `*OPTION={`
630
632{
633 if (fOptions)
634 return;
635
636 const char *optTitle = strstr(GetTitle(), "*OPTION={");
637 if (!optTitle)
638 return;
639
640 // If option string exist in comment - we'll parse it and create
641 // list of options
642
643 // Option-list string has a form:
644 // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
645 // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
646 //
647 // As one can see it is possible to specify value as either numerical
648 // value , string or enum.
649 // One can also specify implicitly names of Getter/Setter methods.
650
651 char cmt[2048];
652 char opt[2048];
653 const char *ptr1 = nullptr;
654 char *ptr2 = nullptr;
655 char *ptr3 = nullptr;
656 Int_t cnt = 0;
658 Int_t i;
659
660 strlcpy(cmt,GetTitle(),2048);
661
662 char *opt_ptr = strstr(cmt, "*OPTION={");
663
664 // If we found it - parsing...
665
666 //let's cut the part lying between {}
667 char *rest;
668 ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
669 if (ptr1 == nullptr) {
670 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
671 return;
672 }
673 ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
674 if (ptr1 == nullptr) {
675 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
676 return;
677 }
678
679 //and save it:
680 strlcpy(opt,ptr1,2048);
681
682 // Let's extract sub-tokens extracted by ';' sign.
683 // We'll put'em in an array for convenience;
684 // You have to do it in this manner because you cannot use nested tokenizing
685
686 std::vector<std::string> tokens; // a storage for these sub-tokens.
687 token_cnt = 0;
688 cnt = 0;
689
690 do { //tokenizing loop
691 ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
692 if (ptr1) {
693 tokens.emplace_back(ptr1);
694 token_cnt++;
695 }
696 } while (ptr1);
697
698 // OK! Now let's check whether we have Get/Set methods encode in any string
699 for (i=0;i<token_cnt;i++) {
700 if (strstr(tokens[i].c_str(),"GetMethod")) {
701 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest); // tokenizing-strip text "GetMethod"
702 if (ptr1 == nullptr) {
703 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
704 return;
705 }
706 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
707 if (ptr1 == nullptr) {
708 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
709 return;
710 }
711
712 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
713 // FIXME: wrong in case called derives via multiple inheritance from this class
715
716 continue; //next item!
717 }
718
719 if (strstr(tokens[i].c_str(),"SetMethod")) {
720 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest);
721 if (ptr1 == nullptr) {
722 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
723 return;
724 }
725 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
726 if (ptr1 == nullptr) {
727 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
728 return;
729 }
730 if (GetClass()->GetMethod(ptr1,"1"))
731 // FIXME: wrong in case called derives via multiple inheritance from this class
733 }
734 }
735
736 //Now let's parse option strings...
737
738 Int_t opt_cnt = 0;
739 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
740
741 for (i=0;i<token_cnt;i++) {
742 if (strstr(tokens[i].c_str(),"Items")) {
743 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "()", &rest);
744 if (ptr1 == nullptr) {
745 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
746 return;
747 }
748 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
749 if (ptr1 == nullptr) {
750 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
751 return;
752 }
753
754 char opts[2048]; //and save it!
755 strlcpy(opts,ptr1,2048);
756
757 //now parse it...
758 //firstly we just store strings like: xxx="Label Name"
759 //We'll store it in TOptionListItem objects, because they're derived
760 //from TObject and thus can be stored in TList.
761 //It's not elegant but works.
762 do {
763 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
764 if (ptr1) {
765 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
766 optionlist->Add(it);
767 }
768 } while(ptr1);
769
770 }
771 }
772
773 //having all options extracted and put into list, we finally can parse
774 //them to create a list of options...
775
776 fOptions = new TList(); //create the list
777
778 TIter next(optionlist.get()); //we'll iterate through all
779 //strings containing options
780 TOptionListItem *it = nullptr;
781 TOptionListItem *it1 = nullptr;
782 while ((it=(TOptionListItem*)next())) {
783
784 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.
785 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
786 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
787 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
788
789 if (islabel) {
790 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
791 fOptions->Add(it1);
792 } else {
793
794 char *strtolResult;
795 Long_t l = std::strtol(ptr1, &strtolResult, 10);
796 bool isnumber = (strtolResult != ptr1);
797
798 if (!isnumber) {
799 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
800 if (enumval) {
801 Int_t *value = (Int_t *)(enumval->GetAddress());
802 // We'll try to find global enum existing in ROOT...
803 l = (Long_t)(*value);
804 } else if (IsEnum()) {
806 if (obj)
807 l = ((TEnumConstant *)obj)->GetValue();
808 else
809 l = gInterpreter->Calc(Form("%s;", ptr1));
810 } else {
811 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
812 }
813 }
814
815 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
816 fOptions->Add(it1);
817 }
818
819 optionlist->Remove(it); //delete this option string from list
820 delete it; // and dispose of it.
821
822 }
823
824}
825
826
827////////////////////////////////////////////////////////////////////////////////
828/// Returns list of options - list of TOptionListItems
829
836
837////////////////////////////////////////////////////////////////////////////////
838/// Return a TMethodCall method responsible for getting the value
839/// of data member. The cl argument specifies the class of the object
840/// which will be used to call this method (in case of multiple
841/// inheritance TMethodCall needs to know this to calculate the proper
842/// offset).
843
845{
846 if (!fValueGetter || cl) {
847
849
850 if (!cl) cl = fClass;
851
852 if (fValueGetter) {
854 delete fValueGetter;
855 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
856
857 } else {
858 // try to guess Getter function:
859 // we strip the fist character of name of data field ('f') and then
860 // try to find the name of Getter by applying "Get", "Is" or "Has"
861 // as a prefix
862
863 const char *dataname = GetName();
864
866 gettername.Form( "Get%s", dataname+1);
867 if (GetClass()->GetMethod(gettername, ""))
868 return fValueGetter = new TMethodCall(cl, gettername, "");
869 gettername.Form( "Is%s", dataname+1);
870 if (GetClass()->GetMethod(gettername, ""))
871 return fValueGetter = new TMethodCall(cl, gettername, "");
872 gettername.Form( "Has%s", dataname+1);
873 if (GetClass()->GetMethod(gettername, ""))
874 return fValueGetter = new TMethodCall(cl, gettername, "");
875 }
876 }
877
878 return fValueGetter;
879}
880
881////////////////////////////////////////////////////////////////////////////////
882/// Return a TMethodCall method responsible for setting the value
883/// of data member. The cl argument specifies the class of the object
884/// which will be used to call this method (in case of multiple
885/// inheritance TMethodCall needs to know this to calculate the proper
886/// offset).
887
889{
890 if (!fValueSetter || cl) {
891
893
894 if (!cl) cl = fClass;
895
896 if (fValueSetter) {
897
899 TString params = fValueSetter->GetParams();
900 delete fValueSetter;
901 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
902
903 } else {
904
905 // try to guess Setter function:
906 // we strip the fist character of name of data field ('f') and then
907 // try to find the name of Setter by applying "Set" as a prefix
908
909 const char *dataname = GetName();
910
912 settername.Form( "Set%s", dataname+1);
913 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
914 if (GetClass()->GetMethod(settername, "0"))
915 fValueSetter = new TMethodCall(cl, settername, "0");
916 if (!fValueSetter)
917 if (GetClass()->GetMethod(settername, "true"))
918 fValueSetter = new TMethodCall(cl, settername, "true");
919 }
920 }
921
922 return fValueSetter;
923}
924
925////////////////////////////////////////////////////////////////////////////////
926/// Update the TFunction to reflect the new info.
927///
928/// This can be used to implement unloading (info == 0) and then reloading
929/// (info being the 'new' decl address).
930
932{
934
938 if (fOptions) {
939 fOptions->Delete();
941 }
942
943 if (info == nullptr) {
944 fOffset = -1;
945 fProperty = -1;
946 fSTLCont = -1;
947 fArrayDim = -1;
948 delete [] fArrayMaxIndex;
949 fArrayMaxIndex=nullptr;
951
952 fInfo = nullptr;
953 return kTRUE;
954 } else {
955 fInfo = info;
956 Init(false);
957 return kTRUE;
958 }
959}
960
961
962////////////////////////////////////////////////////////////////////////////////
963/// Stream an object of TDataMember. Forces calculation of all cached
964/// (and persistent) values.
965
967 if (b.IsReading()) {
968 b.ReadClassBuffer(Class(), this);
969 Init(true /*reading*/);
970 } else {
971 // Writing.
972 if (fProperty & kIsStatic) {
973 // We have a static member and in this case fOffset contains the
974 // actual address in memory of the data, it will be different everytime,
975 // let's not record it.
976 fOffset = -1;
977 } else {
978 GetOffset();
979 }
981 GetArrayDim();
983 Property(); // also calculates fTypeName and friends
984 b.WriteClassBuffer(Class(), this);
985 }
986}
987
988////////////////////////////////////////////////////////////////////////////////
989/// Constructor.
990
992 Long_t tglmask,const char *name, const char *label)
993{
994 fDataMember = d;
995 fValue = val;
998 if (name) {
999 fOptName = name;
1000 }
1001
1002 if (label) {
1003 fOptLabel = label;
1004 }
1005}
Cppyy::TCppType_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
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
@ 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
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2571
#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:5869
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 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...
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
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
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
Mother of all ROOT objects.
Definition TObject.h:42
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 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
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
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