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 "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();
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 {
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 delete [] fArrayMaxIndex;
319 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : nullptr;
320 for(Int_t d = 0; d < fArrayDim; ++d)
326 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : nullptr;
327 }
328 return *this;
329}
330
331////////////////////////////////////////////////////////////////////////////////
332/// TDataMember dtor deletes adopted CINT DataMemberInfo object.
333
335{
336 delete [] fArrayMaxIndex;
338 delete fValueSetter;
339 delete fValueGetter;
340 if (fOptions) {
341 fOptions->Delete();
342 delete fOptions;
343 }
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Return number of array dimensions.
348
350{
351 if (fArrayDim<0 && fInfo) {
353 TDataMember *dm = const_cast<TDataMember*>(this);
355 // fArrayMaxIndex should be zero
356 if (dm->fArrayDim) {
357 dm->fArrayMaxIndex = new Int_t[fArrayDim];
358 for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
360 }
361 }
362 }
363 return fArrayDim;
364}
365
366////////////////////////////////////////////////////////////////////////////////
367/// If the data member is pointer and has a valid array size in its comments
368/// GetArrayIndex returns a string pointing to it;
369/// otherwise it returns an empty string.
370
371const char *TDataMember::GetArrayIndex() const
372{
373 if (!IsaPointer()) return "";
374 if (fArrayIndex.Length()==0 && fInfo) {
376 TDataMember *dm = const_cast<TDataMember*>(this);
377 const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
378 if (val) dm->fArrayIndex = val;
379 else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
380 }
381 return fArrayIndex;
382}
383
384////////////////////////////////////////////////////////////////////////////////
385
387{
388 if (fInfo) return gInterpreter->GetDeclId(fInfo);
389 else return nullptr;
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// Return maximum index for array dimension "dim".
394
396{
397 if (fArrayDim<0 && fInfo) {
399 } else {
400 if (dim < 0 || dim >= fArrayDim) return -1;
401 return fArrayMaxIndex[dim];
402 }
403}
404
405////////////////////////////////////////////////////////////////////////////////
406/// Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
407
408const char *TDataMember::GetTypeName() const
409{
410 if (fProperty==(-1)) Property();
411 return fTypeName.Data();
412}
413
414////////////////////////////////////////////////////////////////////////////////
415/// Get full type description of data member, e,g.: "class TDirectory*".
416
418{
419 if (fProperty==(-1)) Property();
420
421 return fFullTypeName.Data();
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Get full type description of data member, e,g.: "class TDirectory*".
426
428{
429 return fTrueTypeName.Data();
430}
431
432////////////////////////////////////////////////////////////////////////////////
433/// Get offset from "this".
434
436{
437 if (fOffset>=0) return fOffset;
438
440 //case of an interpreted or emulated class
441 if (fClass->GetDeclFileLine() < 0) {
442 ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
443 return fOffset;
444 }
445 //case of a compiled class
446 //Note that the offset cannot be computed in case of an abstract class
447 //for which the list of real data has not yet been computed via
448 //a real daughter class.
449 TString dmbracket;
450 dmbracket.Form("%s[",GetName());
453 TRealData *rdm;
454 Int_t offset = 0;
455 while ((rdm = (TRealData*)next())) {
456 char *rdmc = (char*)rdm->GetName();
457 //next statement required in case a class and one of its parent class
458 //have data members with the same name
459 if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
460
461 if (rdm->GetDataMember() != this) continue;
462 if (strcmp(rdmc,GetName()) == 0) {
463 offset = rdm->GetThisOffset();
464 break;
465 }
466 if (strcmp(rdm->GetName(),GetName()) == 0) {
467 if (rdm->IsObject()) {
468 offset = rdm->GetThisOffset();
469 break;
470 }
471 }
472 if (strstr(rdm->GetName(),dmbracket.Data())) {
473 offset = rdm->GetThisOffset();
474 break;
475 }
476 }
477 ((TDataMember*)this)->fOffset = offset;
478 return fOffset;
479}
480
481////////////////////////////////////////////////////////////////////////////////
482/// Get offset from "this" using the information in CINT only.
483
485{
486 if (fOffset>=0) return fOffset;
487
489 TDataMember *dm = const_cast<TDataMember*>(this);
490
491 if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
492 else return -1;
493}
494
495////////////////////////////////////////////////////////////////////////////////
496/// Get the sizeof the underlying type of the data member
497/// (i.e. if the member is an array sizeof(member)/length)
498
500{
501 if (IsaPointer()) return sizeof(void*);
502 if (IsEnum() ) return sizeof(Int_t);
503 if (IsBasic() ) return GetDataType()->Size();
504
506 if (!cl) cl = TClass::GetClass(GetTrueTypeName());
507 if ( cl) return cl->Size();
508
509 Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
510 return 0;
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Return true if data member is a basic type, e.g. char, int, long...
515
517{
518 if (fProperty == -1) Property();
519 return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
520}
521
522////////////////////////////////////////////////////////////////////////////////
523/// Return true if data member is an enum.
524
526{
527 if (fProperty == -1) Property();
528 return (fProperty & kIsEnum) ? kTRUE : kFALSE;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Return true if data member is a pointer.
533
535{
536 if (fProperty == -1) Property();
537 return (fProperty & kIsPointer) ? kTRUE : kFALSE;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// The return type is defined in TDictionary (kVector, kList, etc.)
542
544{
545 if (fSTLCont != -1) return fSTLCont;
548 return fSTLCont;
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// Return true if this data member object is pointing to a currently
553/// loaded data member. If a function is unloaded after the TDataMember
554/// is created, the TDataMember will be set to be invalid.
555
557{
558 if (fOffset >= 0) return kTRUE;
559
560 // Register the transaction when checking the validity of the object.
562 DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
563 if (newId) {
564 DataMemberInfo_t *info
565 = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
566 Update(info);
567 // We need to make sure that the list of data member is properly
568 // informed and updated.
570 lst->Update(this);
571 }
572 return newId != nullptr;
573 }
574 return fInfo != nullptr;
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Get property description word. For meaning of bits see EProperty.
579
581{
582 if (fProperty!=(-1)) return fProperty;
583
585 TDataMember *t = (TDataMember*)this;
586
587 if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
590 t->fProperty = prop|propt;
591
595
598
599 return fProperty;
600}
601
602
603////////////////////////////////////////////////////////////////////////////////
604/// Build TOptionListItems from the member comment `*OPTION={`
605
607{
608 if (fOptions)
609 return;
610
611 const char *optTitle = strstr(GetTitle(), "*OPTION={");
612 if (!optTitle)
613 return;
614
615 // If option string exist in comment - we'll parse it and create
616 // list of options
617
618 // Option-list string has a form:
619 // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
620 // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
621 //
622 // As one can see it is possible to specify value as either numerical
623 // value , string or enum.
624 // One can also specify implicitly names of Getter/Setter methods.
625
626 char cmt[2048];
627 char opt[2048];
628 const char *ptr1 = nullptr;
629 char *ptr2 = nullptr;
630 char *ptr3 = nullptr;
631 Int_t cnt = 0;
632 Int_t token_cnt;
633 Int_t i;
634
635 strlcpy(cmt,GetTitle(),2048);
636
637 char *opt_ptr = strstr(cmt, "*OPTION={");
638
639 // If we found it - parsing...
640
641 //let's cut the part lying between {}
642 char *rest;
643 ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
644 if (ptr1 == nullptr) {
645 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
646 return;
647 }
648 ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
649 if (ptr1 == nullptr) {
650 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
651 return;
652 }
653
654 //and save it:
655 strlcpy(opt,ptr1,2048);
656
657 // Let's extract sub-tokens extracted by ';' sign.
658 // We'll put'em in an array for convenience;
659 // You have to do it in this manner because you cannot use nested tokenizing
660
661 std::vector<std::string> tokens; // a storage for these sub-tokens.
662 token_cnt = 0;
663 cnt = 0;
664
665 do { //tokenizing loop
666 ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
667 if (ptr1) {
668 tokens.emplace_back(ptr1);
669 token_cnt++;
670 }
671 } while (ptr1);
672
673 // OK! Now let's check whether we have Get/Set methods encode in any string
674 for (i=0;i<token_cnt;i++) {
675 if (strstr(tokens[i].c_str(),"GetMethod")) {
676 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest); // tokenizing-strip text "GetMethod"
677 if (ptr1 == nullptr) {
678 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
679 return;
680 }
681 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
682 if (ptr1 == nullptr) {
683 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
684 return;
685 }
686
687 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
688 // FIXME: wrong in case called derives via multiple inheritance from this class
690
691 continue; //next item!
692 }
693
694 if (strstr(tokens[i].c_str(),"SetMethod")) {
695 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "\"", &rest);
696 if (ptr1 == nullptr) {
697 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
698 return;
699 }
700 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
701 if (ptr1 == nullptr) {
702 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
703 return;
704 }
705 if (GetClass()->GetMethod(ptr1,"1"))
706 // FIXME: wrong in case called derives via multiple inheritance from this class
708 }
709 }
710
711 //Now let's parse option strings...
712
713 Int_t opt_cnt = 0;
714 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
715
716 for (i=0;i<token_cnt;i++) {
717 if (strstr(tokens[i].c_str(),"Items")) {
718 ptr1 = R__STRTOK_R(const_cast<char *>(tokens[i].c_str()), "()", &rest);
719 if (ptr1 == nullptr) {
720 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
721 return;
722 }
723 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
724 if (ptr1 == nullptr) {
725 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
726 return;
727 }
728
729 char opts[2048]; //and save it!
730 strlcpy(opts,ptr1,2048);
731
732 //now parse it...
733 //firstly we just store strings like: xxx="Label Name"
734 //We'll store it in TOptionListItem objects, because they're derived
735 //from TObject and thus can be stored in TList.
736 //It's not elegant but works.
737 do {
738 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
739 if (ptr1) {
740 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
741 optionlist->Add(it);
742 }
743 } while(ptr1);
744
745 }
746 }
747
748 //having all options extracted and put into list, we finally can parse
749 //them to create a list of options...
750
751 fOptions = new TList(); //create the list
752
753 TIter next(optionlist.get()); //we'll iterate through all
754 //strings containing options
755 TOptionListItem *it = nullptr;
756 TOptionListItem *it1 = nullptr;
757 while ((it=(TOptionListItem*)next())) {
758
759 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.
760 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
761 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
762 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
763
764 if (islabel) {
765 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
766 fOptions->Add(it1);
767 } else {
768
769 char *strtolResult;
770 Long_t l = std::strtol(ptr1, &strtolResult, 10);
771 bool isnumber = (strtolResult != ptr1);
772
773 if (!isnumber) {
774 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
775 if (enumval) {
776 Int_t *value = (Int_t *)(enumval->GetAddress());
777 // We'll try to find global enum existing in ROOT...
778 l = (Long_t)(*value);
779 } else if (IsEnum()) {
781 if (obj)
782 l = ((TEnumConstant *)obj)->GetValue();
783 else
784 l = gInterpreter->Calc(Form("%s;", ptr1));
785 } else {
786 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
787 }
788 }
789
790 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
791 fOptions->Add(it1);
792 }
793
794 optionlist->Remove(it); //delete this option string from list
795 delete it; // and dispose of it.
796
797 }
798
799}
800
801
802////////////////////////////////////////////////////////////////////////////////
803/// Returns list of options - list of TOptionListItems
804
806{
807 if (!fOptions)
809 return fOptions;
810}
811
812////////////////////////////////////////////////////////////////////////////////
813/// Return a TMethodCall method responsible for getting the value
814/// of data member. The cl argument specifies the class of the object
815/// which will be used to call this method (in case of multiple
816/// inheritance TMethodCall needs to know this to calculate the proper
817/// offset).
818
820{
821 if (!fValueGetter || cl) {
822
824
825 if (!cl) cl = fClass;
826
827 if (fValueGetter) {
828 TString methodname = fValueGetter->GetMethodName();
829 delete fValueGetter;
830 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
831
832 } else {
833 // try to guess Getter function:
834 // we strip the fist character of name of data field ('f') and then
835 // try to find the name of Getter by applying "Get", "Is" or "Has"
836 // as a prefix
837
838 const char *dataname = GetName();
839
840 TString gettername;
841 gettername.Form( "Get%s", dataname+1);
842 if (GetClass()->GetMethod(gettername, ""))
843 return fValueGetter = new TMethodCall(cl, gettername, "");
844 gettername.Form( "Is%s", dataname+1);
845 if (GetClass()->GetMethod(gettername, ""))
846 return fValueGetter = new TMethodCall(cl, gettername, "");
847 gettername.Form( "Has%s", dataname+1);
848 if (GetClass()->GetMethod(gettername, ""))
849 return fValueGetter = new TMethodCall(cl, gettername, "");
850 }
851 }
852
853 return fValueGetter;
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// Return a TMethodCall method responsible for setting the value
858/// of data member. The cl argument specifies the class of the object
859/// which will be used to call this method (in case of multiple
860/// inheritance TMethodCall needs to know this to calculate the proper
861/// offset).
862
864{
865 if (!fValueSetter || cl) {
866
868
869 if (!cl) cl = fClass;
870
871 if (fValueSetter) {
872
873 TString methodname = fValueSetter->GetMethodName();
874 TString params = fValueSetter->GetParams();
875 delete fValueSetter;
876 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
877
878 } else {
879
880 // try to guess Setter function:
881 // we strip the fist character of name of data field ('f') and then
882 // try to find the name of Setter by applying "Set" as a prefix
883
884 const char *dataname = GetName();
885
886 TString settername;
887 settername.Form( "Set%s", dataname+1);
888 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
889 if (GetClass()->GetMethod(settername, "1"))
890 fValueSetter = new TMethodCall(cl, settername, "1");
891 if (!fValueSetter)
892 if (GetClass()->GetMethod(settername, "true"))
893 fValueSetter = new TMethodCall(cl, settername, "true");
894 }
895 }
896
897 return fValueSetter;
898}
899
900////////////////////////////////////////////////////////////////////////////////
901/// Update the TFunction to reflect the new info.
902///
903/// This can be used to implement unloading (info == 0) and then reloading
904/// (info being the 'new' decl address).
905
906Bool_t TDataMember::Update(DataMemberInfo_t *info)
907{
909
913 if (fOptions) {
914 fOptions->Delete();
916 }
917
918 if (info == nullptr) {
919 fOffset = -1;
920 fProperty = -1;
921 fSTLCont = -1;
922 fArrayDim = -1;
923 delete [] fArrayMaxIndex;
924 fArrayMaxIndex=nullptr;
926
927 fInfo = nullptr;
928 return kTRUE;
929 } else {
930 fInfo = info;
931 Init(false);
932 return kTRUE;
933 }
934}
935
936
937////////////////////////////////////////////////////////////////////////////////
938/// Stream an object of TDataMember. Forces calculation of all cached
939/// (and persistent) values.
940
942 if (b.IsReading()) {
943 b.ReadClassBuffer(Class(), this);
944 Init(true /*reading*/);
945 } else {
946 // Writing.
947 if (fProperty & kIsStatic) {
948 // We have a static member and in this case fOffset contains the
949 // actual address in memory of the data, it will be different everytime,
950 // let's not record it.
951 fOffset = -1;
952 } else {
953 GetOffset();
954 }
956 GetArrayDim();
958 Property(); // also calculates fTypeName and friends
959 b.WriteClassBuffer(Class(), this);
960 }
961}
962
963////////////////////////////////////////////////////////////////////////////////
964/// Constructor.
965
967 Long_t tglmask,const char *name, const char *label)
968{
969 fDataMember = d;
970 fValue = val;
971 fValueMaskBit = valmask;
972 fToggleMaskBit = tglmask;
973 if (name) {
974 fOptName = name;
975 }
976
977 if (label) {
978 fOptLabel = label;
979 }
980}
Cppyy::TCppType_t fClass
#define SafeDelete(p)
Definition RConfig.hxx:540
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
long Longptr_t
Definition RtypesCore.h:82
char Char_t
Definition RtypesCore.h:37
long Long_t
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
@ kIsPointer
Definition TDictionary.h:78
@ kIsEnum
Definition TDictionary.h:68
@ kIsFundamental
Definition TDictionary.h:70
@ kIsStatic
Definition TDictionary.h:80
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:110
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
#define gInterpreter
#define gROOT
Definition TROOT.h:405
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2467
#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:81
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2031
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3770
Short_t GetDeclFileLine() const
Definition TClass.h:427
TList * GetListOfRealData() const
Definition TClass.h:451
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5704
ClassInfo_t * GetClassInfo() const
Definition TClass.h:431
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:2968
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 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
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
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.
TMethodCall * GetterMethod(TClass *cl=nullptr)
Return a TMethodCall method responsible for getting the value of 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
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
TClass * GetClass() const
Definition TDataMember.h:75
Int_t fArrayDim
Definition TDataMember.h:45
static TClass * Class()
Int_t GetType() const
Definition TDataType.h:68
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()
the Cling ID of the transaction that last updated the object
TDictionary & operator=(const TDictionary &other)
const void * DeclId_t
The TEnumConstant class implements the constants of the enum type.
The TEnum class implements the enum type.
Definition TEnum.h:33
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:175
Global variables class (global variables are obtained from CINT).
Definition TGlobal.h:28
virtual void * GetAddress() const
Return address of global.
Definition TGlobal.cxx:81
virtual DataMemberInfo_t * DataMemberInfo_FactoryCopy(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
virtual Longptr_t DataMemberInfo_Offset(DataMemberInfo_t *) const
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
virtual const char * TypeName(const char *s)=0
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
void Update(TDictionary *member)
Move the member or data member to the expect set of list.
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
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: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
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:956
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:774
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:998
Long_t fToggleMaskBit
TDataMember * fDataMember
Long_t fValue
Data member to which this option belongs.
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
const char * GetName() const override
Returns name of object.
Definition TRealData.h:52
TDataMember * GetDataMember() const
Definition TRealData.h:53
Bool_t IsObject() const
Definition TRealData.h:56
Long_t GetThisOffset() const
Definition TRealData.h:55
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1221
const char * Data() const
Definition TString.h:380
TString & Append(const char *cs)
Definition TString.h:576
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
struct void * fTypeName
Definition cppyy.h:9
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