Logo ROOT  
Reference Guide
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~~~
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 "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
164
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
172TDataMember::TDataMember(DataMemberInfo_t *info, TClass *cl) : TDictionary()
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
195void TDataMember::Init(bool afterReading)
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();
217 fDataType = gROOT->GetType(name);
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).
222 fDataType = gROOT->GetType(name,kTRUE);
223 }
224 } else {
225 fDataType = gROOT->GetType("Int_t", kTRUE); // In rare instance we are called before Int_t has been added to the list of types in TROOT, the kTRUE insures it is there.
226 }
227 // if (!fDataType)
228 // Error("TDataMember", "basic data type %s not found in list of basic types",
229 // GetTypeName());
230 }
231
232
233 if (afterReading) {
234 // Options are streamed; can't build TMethodCall for getters and setters
235 // because we deserialize a TDataMember when we do not have interpreter
236 // data. Thus do an early return.
237 return;
238 }
239
240 if (strstr(GetTitle(), "*OPTION={")) {
241 // Delay setting fOptions until it's used: the enum constants might
242 // not have been added as members yet.
243
244 // if option string does not exist but it's an Enum - parse it!!!!
245 } else if (IsEnum()) {
246 fOptions = new TList();
247 if (TEnum* enumDict = TEnum::GetEnum(GetTypeName()) ){
248 TIter iEnumConst(enumDict->GetConstants());
249 while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
251 = new TOptionListItem(this, enumConst->GetValue(),0,0,
252 enumConst->GetName(),enumConst->GetName());
253 fOptions->Add(it);
254 }
255 }
256
257 // and the case od Bool_t : we add items "ON" and "Off"
258 } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
259
260 fOptions = new TList();
261 TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",nullptr);
262 fOptions->Add(it);
263 it = new TOptionListItem(this,0,0,0,"Off",nullptr);
264 fOptions->Add(it);
265
266 } else fOptions = nullptr;
267
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// copy constructor
272
274 TDictionary(dm),
275 fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
276 fClass(dm.fClass),
277 fDataType(dm.fDataType),
278 fOffset(dm.fOffset),
279 fSTLCont(dm.fSTLCont),
280 fProperty(dm.fProperty),
281 fArrayDim(dm.fArrayDim),
282 fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr),
283 fArrayIndex(dm.fArrayIndex),
285 fFullTypeName(dm.fFullTypeName),
286 fTrueTypeName(dm.fTrueTypeName),
287 fValueGetter(nullptr),
288 fValueSetter(nullptr),
289 fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr)
290{
291 for(Int_t d = 0; d < fArrayDim; ++d)
293}
294
295////////////////////////////////////////////////////////////////////////////////
296/// assignment operator
297
299{
300 if(this!=&dm) {
302 delete fValueSetter; fValueSetter = nullptr;
303 delete fValueGetter; fValueGetter = nullptr;
304 if (fOptions) {
305 fOptions->Delete();
306 delete fOptions;
307 fOptions = nullptr;
308 }
309
312 fClass=dm.fClass;
314 fOffset=dm.fOffset;
317 fArrayDim = dm.fArrayDim;
318 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr;
319 for(Int_t d = 0; d < fArrayDim; ++d)
325 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr;
326 }
327 return *this;
328}
329
330////////////////////////////////////////////////////////////////////////////////
331/// TDataMember dtor deletes adopted CINT DataMemberInfo object.
332
334{
335 delete [] fArrayMaxIndex;
337 delete fValueSetter;
338 delete fValueGetter;
339 if (fOptions) {
340 fOptions->Delete();
341 delete fOptions;
342 }
343}
344
345////////////////////////////////////////////////////////////////////////////////
346/// Return number of array dimensions.
347
349{
350 if (fArrayDim<0 && fInfo) {
352 TDataMember *dm = const_cast<TDataMember*>(this);
354 // fArrayMaxIndex should be zero
355 if (dm->fArrayDim) {
356 dm->fArrayMaxIndex = new Int_t[fArrayDim];
357 for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
359 }
360 }
361 }
362 return fArrayDim;
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// If the data member is pointer and has a valid array size in its comments
367/// GetArrayIndex returns a string pointing to it;
368/// otherwise it returns an empty string.
369
370const char *TDataMember::GetArrayIndex() const
371{
372 if (!IsaPointer()) return "";
373 if (fArrayIndex.Length()==0 && fInfo) {
375 TDataMember *dm = const_cast<TDataMember*>(this);
376 const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
377 if (val) dm->fArrayIndex = val;
378 else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
379 }
380 return fArrayIndex;
381}
382
383////////////////////////////////////////////////////////////////////////////////
384
386{
387 if (fInfo) return gInterpreter->GetDeclId(fInfo);
388 else return nullptr;
389}
390
391////////////////////////////////////////////////////////////////////////////////
392/// Return maximum index for array dimension "dim".
393
395{
396 if (fArrayDim<0 && fInfo) {
398 } else {
399 if (dim < 0 || dim >= fArrayDim) return -1;
400 return fArrayMaxIndex[dim];
401 }
402}
403
404////////////////////////////////////////////////////////////////////////////////
405/// Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
406
407const char *TDataMember::GetTypeName() const
408{
409 if (fProperty==(-1)) Property();
410 return fTypeName.Data();
411}
412
413////////////////////////////////////////////////////////////////////////////////
414/// Get full type description of data member, e,g.: "class TDirectory*".
415
417{
418 if (fProperty==(-1)) Property();
419
420 return fFullTypeName.Data();
421}
422
423////////////////////////////////////////////////////////////////////////////////
424/// Get full type description of data member, e,g.: "class TDirectory*".
425
427{
428 return fTrueTypeName.Data();
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Get offset from "this".
433
435{
436 if (fOffset>=0) return fOffset;
437
439 //case of an interpreted or emulated class
440 if (fClass->GetDeclFileLine() < 0) {
441 ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
442 return fOffset;
443 }
444 //case of a compiled class
445 //Note that the offset cannot be computed in case of an abstract class
446 //for which the list of real data has not yet been computed via
447 //a real daughter class.
448 TString dmbracket;
449 dmbracket.Form("%s[",GetName());
452 TRealData *rdm;
453 Int_t offset = 0;
454 while ((rdm = (TRealData*)next())) {
455 char *rdmc = (char*)rdm->GetName();
456 //next statement required in case a class and one of its parent class
457 //have data members with the same name
458 if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
459
460 if (rdm->GetDataMember() != this) continue;
461 if (strcmp(rdmc,GetName()) == 0) {
462 offset = rdm->GetThisOffset();
463 break;
464 }
465 if (strcmp(rdm->GetName(),GetName()) == 0) {
466 if (rdm->IsObject()) {
467 offset = rdm->GetThisOffset();
468 break;
469 }
470 }
471 if (strstr(rdm->GetName(),dmbracket.Data())) {
472 offset = rdm->GetThisOffset();
473 break;
474 }
475 }
476 ((TDataMember*)this)->fOffset = offset;
477 return fOffset;
478}
479
480////////////////////////////////////////////////////////////////////////////////
481/// Get offset from "this" using the information in CINT only.
482
484{
485 if (fOffset>=0) return fOffset;
486
488 TDataMember *dm = const_cast<TDataMember*>(this);
489
490 if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
491 else return -1;
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// Get the sizeof the underlying type of the data member
496/// (i.e. if the member is an array sizeof(member)/length)
497
499{
500 if (IsaPointer()) return sizeof(void*);
501 if (IsEnum() ) return sizeof(Int_t);
502 if (IsBasic() ) return GetDataType()->Size();
503
505 if (!cl) cl = TClass::GetClass(GetTrueTypeName());
506 if ( cl) return cl->Size();
507
508 Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
509 return 0;
510}
511
512////////////////////////////////////////////////////////////////////////////////
513/// Return true if data member is a basic type, e.g. char, int, long...
514
516{
517 if (fProperty == -1) Property();
518 return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
519}
520
521////////////////////////////////////////////////////////////////////////////////
522/// Return true if data member is an enum.
523
525{
526 if (fProperty == -1) Property();
527 return (fProperty & kIsEnum) ? kTRUE : kFALSE;
528}
529
530////////////////////////////////////////////////////////////////////////////////
531/// Return true if data member is a pointer.
532
534{
535 if (fProperty == -1) Property();
536 return (fProperty & kIsPointer) ? kTRUE : kFALSE;
537}
538
539////////////////////////////////////////////////////////////////////////////////
540/// The return type is defined in TDictionary (kVector, kList, etc.)
541
543{
544 if (fSTLCont != -1) return fSTLCont;
547 return fSTLCont;
548}
549
550////////////////////////////////////////////////////////////////////////////////
551/// Return true if this data member object is pointing to a currently
552/// loaded data member. If a function is unloaded after the TDataMember
553/// is created, the TDataMember will be set to be invalid.
554
556{
557 if (fOffset >= 0) return kTRUE;
558
559 // Register the transaction when checking the validity of the object.
561 DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
562 if (newId) {
563 DataMemberInfo_t *info
564 = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
565 Update(info);
566 // We need to make sure that the list of data member is properly
567 // informed and updated.
569 lst->Update(this);
570 }
571 return newId != nullptr;
572 }
573 return fInfo != nullptr;
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Get property description word. For meaning of bits see EProperty.
578
580{
581 if (fProperty!=(-1)) return fProperty;
582
584 TDataMember *t = (TDataMember*)this;
585
586 if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
589 t->fProperty = prop|propt;
590
594
597
598 return fProperty;
599}
600
601
602////////////////////////////////////////////////////////////////////////////////
603/// Build TOptionListItems from the member comment `*OPTION={`
604
606{
607 if (fOptions)
608 return;
609
610 const char *optTitle = strstr(GetTitle(), "*OPTION={");
611 if (!optTitle)
612 return;
613
614 // If option string exist in comment - we'll parse it and create
615 // list of options
616
617 // Option-list string has a form:
618 // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
619 // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
620 //
621 // As one can see it is possible to specify value as either numerical
622 // value , string or enum.
623 // One can also specify implicitly names of Getter/Setter methods.
624
625 char cmt[2048];
626 char opt[2048];
627 const char *ptr1 = nullptr;
628 char *ptr2 = nullptr;
629 char *ptr3 = nullptr;
630 Int_t cnt = 0;
631 Int_t token_cnt;
632 Int_t i;
633
634 strlcpy(cmt,GetTitle(),2048);
635
636 char *opt_ptr = strstr(cmt, "*OPTION={");
637
638 // If we found it - parsing...
639
640 //let's cut the part lying between {}
641 char *rest;
642 ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
643 if (ptr1 == nullptr) {
644 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
645 return;
646 }
647 ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
648 if (ptr1 == nullptr) {
649 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
650 return;
651 }
652
653 //and save it:
654 strlcpy(opt,ptr1,2048);
655
656 // Let's extract sub-tokens extracted by ';' sign.
657 // We'll put'em in an array for convenience;
658 // You have to do it in this manner because you cannot use nested tokenizing
659
660 std::vector<std::string> tokens; // a storage for these sub-tokens.
661 token_cnt = 0;
662 cnt = 0;
663
664 do { //tokenizing loop
665 ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
666 if (ptr1) {
667 tokens.emplace_back(ptr1);
668 token_cnt++;
669 }
670 } while (ptr1);
671
672 // OK! Now let's check whether we have Get/Set methods encode in any string
673 for (i=0;i<token_cnt;i++) {
674 if (strstr(tokens[i].c_str(),"GetMethod")) {
675 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest); // tokenizing-strip text "GetMethod"
676 if (ptr1 == nullptr) {
677 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
678 return;
679 }
680 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
681 if (ptr1 == nullptr) {
682 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
683 return;
684 }
685
686 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
687 // FIXME: wrong in case called derives via multiple inheritance from this class
689
690 continue; //next item!
691 }
692
693 if (strstr(tokens[i].c_str(),"SetMethod")) {
694 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest);
695 if (ptr1 == nullptr) {
696 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
697 return;
698 }
699 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
700 if (ptr1 == nullptr) {
701 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
702 return;
703 }
704 if (GetClass()->GetMethod(ptr1,"1"))
705 // FIXME: wrong in case called derives via multiple inheritance from this class
707 }
708 }
709
710 //Now let's parse option strings...
711
712 Int_t opt_cnt = 0;
713 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
714
715 for (i=0;i<token_cnt;i++) {
716 if (strstr(tokens[i].c_str(),"Items")) {
717 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "()", &rest);
718 if (ptr1 == nullptr) {
719 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
720 return;
721 }
722 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
723 if (ptr1 == nullptr) {
724 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
725 return;
726 }
727
728 char opts[2048]; //and save it!
729 strlcpy(opts,ptr1,2048);
730
731 //now parse it...
732 //firstly we just store strings like: xxx="Label Name"
733 //We'll store it in TOptionListItem objects, because they're derived
734 //from TObject and thus can be stored in TList.
735 //It's not elegant but works.
736 do {
737 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
738 if (ptr1) {
739 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
740 optionlist->Add(it);
741 }
742 } while(ptr1);
743
744 }
745 }
746
747 //having all options extracted and put into list, we finally can parse
748 //them to create a list of options...
749
750 fOptions = new TList(); //create the list
751
752 TIter next(optionlist.get()); //we'll iterate through all
753 //strings containing options
754 TOptionListItem *it = nullptr;
755 TOptionListItem *it1 = nullptr;
756 while ((it=(TOptionListItem*)next())) {
757
758 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.
759 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
760 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
761 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
762
763 if (islabel) {
764 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
765 fOptions->Add(it1);
766 } else {
767
768 char *strtolResult;
769 Long_t l = std::strtol(ptr1, &strtolResult, 10);
770 bool isnumber = (strtolResult != ptr1);
771
772 if (!isnumber) {
773 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
774 if (enumval) {
775 Int_t *value = (Int_t *)(enumval->GetAddress());
776 // We'll try to find global enum existing in ROOT...
777 l = (Long_t)(*value);
778 } else if (IsEnum()) {
780 if (obj)
781 l = ((TEnumConstant *)obj)->GetValue();
782 else
783 l = gInterpreter->Calc(Form("%s;", ptr1));
784 } else {
785 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
786 }
787 }
788
789 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
790 fOptions->Add(it1);
791 }
792
793 optionlist->Remove(it); //delete this option string from list
794 delete it; // and dispose of it.
795
796 }
797
798}
799
800
801////////////////////////////////////////////////////////////////////////////////
802/// Returns list of options - list of TOptionListItems
803
805{
806 if (!fOptions)
808 return fOptions;
809}
810
811////////////////////////////////////////////////////////////////////////////////
812/// Return a TMethodCall method responsible for getting the value
813/// of data member. The cl argument specifies the class of the object
814/// which will be used to call this method (in case of multiple
815/// inheritance TMethodCall needs to know this to calculate the proper
816/// offset).
817
819{
820 if (!fValueGetter || cl) {
821
823
824 if (!cl) cl = fClass;
825
826 if (fValueGetter) {
827 TString methodname = fValueGetter->GetMethodName();
828 delete fValueGetter;
829 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
830
831 } else {
832 // try to guess Getter function:
833 // we strip the fist character of name of data field ('f') and then
834 // try to find the name of Getter by applying "Get", "Is" or "Has"
835 // as a prefix
836
837 const char *dataname = GetName();
838
839 TString gettername;
840 gettername.Form( "Get%s", dataname+1);
841 if (GetClass()->GetMethod(gettername, ""))
842 return fValueGetter = new TMethodCall(cl, gettername, "");
843 gettername.Form( "Is%s", dataname+1);
844 if (GetClass()->GetMethod(gettername, ""))
845 return fValueGetter = new TMethodCall(cl, gettername, "");
846 gettername.Form( "Has%s", dataname+1);
847 if (GetClass()->GetMethod(gettername, ""))
848 return fValueGetter = new TMethodCall(cl, gettername, "");
849 }
850 }
851
852 return fValueGetter;
853}
854
855////////////////////////////////////////////////////////////////////////////////
856/// Return a TMethodCall method responsible for setting the value
857/// of data member. The cl argument specifies the class of the object
858/// which will be used to call this method (in case of multiple
859/// inheritance TMethodCall needs to know this to calculate the proper
860/// offset).
861
863{
864 if (!fValueSetter || cl) {
865
867
868 if (!cl) cl = fClass;
869
870 if (fValueSetter) {
871
872 TString methodname = fValueSetter->GetMethodName();
873 TString params = fValueSetter->GetParams();
874 delete fValueSetter;
875 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
876
877 } else {
878
879 // try to guess Setter function:
880 // we strip the fist character of name of data field ('f') and then
881 // try to find the name of Setter by applying "Set" as a prefix
882
883 const char *dataname = GetName();
884
885 TString settername;
886 settername.Form( "Set%s", dataname+1);
887 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
888 if (GetClass()->GetMethod(settername, "1"))
889 fValueSetter = new TMethodCall(cl, settername, "1");
890 if (!fValueSetter)
891 if (GetClass()->GetMethod(settername, "true"))
892 fValueSetter = new TMethodCall(cl, settername, "true");
893 }
894 }
895
896 return fValueSetter;
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Update the TFunction to reflect the new info.
901///
902/// This can be used to implement unloading (info == 0) and then reloading
903/// (info being the 'new' decl address).
904
905Bool_t TDataMember::Update(DataMemberInfo_t *info)
906{
908
912 if (fOptions) {
913 fOptions->Delete();
915 }
916
917 if (info == nullptr) {
918 fOffset = -1;
919 fProperty = -1;
920 fSTLCont = -1;
921 fArrayDim = -1;
922 delete [] fArrayMaxIndex;
923 fArrayMaxIndex=nullptr;
925
926 fInfo = nullptr;
927 return kTRUE;
928 } else {
929 fInfo = info;
930 Init(false);
931 return kTRUE;
932 }
933}
934
935
936////////////////////////////////////////////////////////////////////////////////
937/// Stream an object of TDataMember. Forces calculation of all cached
938/// (and persistent) values.
939
940void TDataMember::Streamer(TBuffer& b) {
941 if (b.IsReading()) {
942 b.ReadClassBuffer(Class(), this);
943 Init(true /*reading*/);
944 } else {
945 // Writing.
946 if (fProperty & kIsStatic) {
947 // We have a static member and in this case fOffset contains the
948 // actual address in memory of the data, it will be different everytime,
949 // let's not record it.
950 fOffset = -1;
951 } else {
952 GetOffset();
953 }
955 GetArrayDim();
957 Property(); // also calculates fTypeName and friends
958 b.WriteClassBuffer(Class(), this);
959 }
960}
961
962////////////////////////////////////////////////////////////////////////////////
963/// Constructor.
964
966 Long_t tglmask,const char *name, const char *label)
967{
968 fDataMember = d;
969 fValue = val;
970 fValueMaskBit = valmask;
971 fToggleMaskBit = tglmask;
972 if (name) {
973 fOptName = name;
974 }
975
976 if (label) {
977 fOptLabel = label;
978 }
979}
void Class()
Definition: Class.C:29
Cppyy::TCppType_t fClass
#define SafeDelete(p)
Definition: RConfig.hxx:536
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
int Int_t
Definition: RtypesCore.h:45
long Longptr_t
Definition: RtypesCore.h:82
char Char_t
Definition: RtypesCore.h:33
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
bool Bool_t
Definition: RtypesCore.h:63
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
@ kIsPointer
Definition: TDictionary.h:78
@ kIsEnum
Definition: TDictionary.h:68
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsStatic
Definition: TDictionary.h:80
char name[80]
Definition: TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:44
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:563
#define gInterpreter
Definition: TInterpreter.h:562
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
#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:80
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:2018
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3763
Short_t GetDeclFileLine() const
Definition: TClass.h:426
TList * GetListOfRealData() const
Definition: TClass.h:450
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5697
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:430
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:2955
virtual TObject * Clone(const char *newname="") const
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
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 full type description of data member, e,g.: "class TDirectory*".
Longptr_t GetOffsetCint() const
Get offset from "this" using the information in CINT only.
DataMemberInfo_t * fInfo
Definition: TDataMember.h:38
Int_t * fArrayMaxIndex
Definition: TDataMember.h:46
TString fTrueTypeName
Definition: TDataMember.h:51
TMethodCall * fValueGetter
Definition: TDataMember.h:56
Int_t GetArrayDim() const
Return number of array dimensions.
Longptr_t fOffset
pointer to data basic type descriptor
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.
TClass * fClass
pointer to CINT data member info
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 type of data member, e,g.: "class TDirectory*" -> "TDirectory".
DeclId_t GetDeclId() const
TMethodCall * fValueSetter
method that returns a value;
Definition: TDataMember.h:57
TMethodCall * GetterMethod(TClass *cl=0)
Return a TMethodCall method responsible for getting the value of data member.
TList * fOptions
method which sets value;
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 the class
Definition: TDataMember.h:40
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TString fArrayIndex
Definition: TDataMember.h:47
@ kObjIsPersistent
Definition: TDataMember.h:35
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
TClass * GetClass() const
Definition: TDataMember.h:75
Int_t fArrayDim
Definition: TDataMember.h:45
Int_t Size() const
Get size of basic typedef'ed type.
Definition: TDataType.cxx:369
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:167
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
TDictionary & operator=(const TDictionary &other)
Definition: TDictionary.cxx:62
const void * DeclId_t
Definition: TDictionary.h:223
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:29
The TEnum class implements the enum type.
Definition: TEnum.h:33
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:132
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:28
virtual void * GetAddress() const
Return address of global.
Definition: TGlobal.cxx:77
virtual DataMemberInfo_t * DataMemberInfo_FactoryCopy(DataMemberInfo_t *) const
Definition: TInterpreter.h:461
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:471
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:469
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
Definition: TInterpreter.h:473
virtual Longptr_t DataMemberInfo_Offset(DataMemberInfo_t *) const
Definition: TInterpreter.h:465
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
Definition: TInterpreter.h:462
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:467
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:466
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:457
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:458
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:463
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
Definition: TInterpreter.h:472
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
Definition: TInterpreter.h:470
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:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:578
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:470
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
TString fTitle
Definition: TNamed.h:33
TString fName
Definition: TNamed.h:32
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:879
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:921
Long_t fToggleMaskBit
Definition: TDataMember.h:111
TString fOptName
Definition: TDataMember.h:112
Long_t fValueMaskBit
Definition: TDataMember.h:110
TDataMember * fDataMember
Definition: TDataMember.h:108
Long_t fValue
Data member to which this option belongs.
Definition: TDataMember.h:109
TString fOptLabel
Definition: TDataMember.h:113
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
TDataMember * GetDataMember() const
Definition: TRealData.h:53
Bool_t IsObject() const
Definition: TRealData.h:56
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
Long_t GetThisOffset() const
Definition: TRealData.h:55
Basic string class.
Definition: TString.h:136
Ssiz_t Length() const
Definition: TString.h:410
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1201
const char * Data() const
Definition: TString.h:369
TString & Append(const char *cs)
Definition: TString.h:564
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2314
struct void * fTypeName
Definition: cppyy.h:9
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
Definition: TClassEdit.cxx:891
ROOT::ESTLType UnderlyingIsSTLCont(std::string_view type)
Return the type of STL collection, if any, that is the underlying type of the given type.
const char * cnt
Definition: TXMLSetup.cxx:75
auto * l
Definition: textangle.C:4
static byte * ptr1
Definition: gifdecode.c:16
static byte * ptr2
Definition: gifdecode.c:17