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