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~~~
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 = 0;
177 fOptions = 0;
178 fValueSetter = 0;
179 fValueGetter = 0;
180 fOffset = -1;
181 fProperty = -1;
182 fSTLCont = -1;
183 fArrayDim = -1;
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 = 0;
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==0) {
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",0);
262 fOptions->Add(it);
263 it = new TOptionListItem(this,0,0,0,"Off",0);
264 fOptions->Add(it);
265
266 } else fOptions = 0;
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] : 0),
283 fArrayIndex(dm.fArrayIndex),
285 fFullTypeName(dm.fFullTypeName),
286 fTrueTypeName(dm.fTrueTypeName),
287 fValueGetter(0),
288 fValueSetter(0),
289 fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : 0)
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;
303 delete fValueGetter;
304 if (fOptions) {
305 fOptions->Delete();
306 delete fOptions;
307 fOptions = 0;
308 }
309
312 fClass=dm.fClass;
314 fOffset=dm.fOffset;
317 fArrayDim = dm.fArrayDim;
318 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0;
319 for(Int_t d = 0; d < fArrayDim; ++d)
325 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : 0;
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 0;
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 != 0;
572 }
573 return fInfo != 0;
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 = 0;
628 char *ptr2 = 0;
629 char *ptr3 = 0;
630 char *tok = 0;
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 == 0) {
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 == 0) {
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 char *tokens[256]; // 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 Int_t nch = strlen(ptr1)+1;
669 tok=new char[nch];
670 strlcpy(tok,ptr1,nch);
671 tokens[token_cnt]=tok;
672 token_cnt++;
673 }
674 } while (ptr1);
675
676 // OK! Now let's check whether we have Get/Set methods encode in any string
677 for (i=0;i<token_cnt;i++) {
678 if (strstr(tokens[i],"GetMethod")) {
679 ptr1 = R__STRTOK_R(tokens[i], "\"", &rest); // tokenizing-strip text "GetMethod"
680 if (ptr1 == 0) {
681 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
682 return;
683 }
684 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
685 if (ptr1 == 0) {
686 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
687 return;
688 }
689
690 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
691 // FIXME: wrong in case called derives via multiple inheritance from this class
693
694 continue; //next item!
695 }
696
697 if (strstr(tokens[i],"SetMethod")) {
698 ptr1 = R__STRTOK_R(tokens[i], "\"", &rest);
699 if (ptr1 == 0) {
700 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
701 return;
702 }
703 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
704 if (ptr1 == 0) {
705 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
706 return;
707 }
708 if (GetClass()->GetMethod(ptr1,"1"))
709 // FIXME: wrong in case called derives via multiple inheritance from this class
711 }
712 }
713
714 //Now let's parse option strings...
715
716 Int_t opt_cnt = 0;
717 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
718
719 for (i=0;i<token_cnt;i++) {
720 if (strstr(tokens[i],"Items")) {
721 ptr1 = R__STRTOK_R(tokens[i], "()", &rest);
722 if (ptr1 == 0) {
723 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
724 return;
725 }
726 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
727 if (ptr1 == 0) {
728 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
729 return;
730 }
731
732 char opts[2048]; //and save it!
733 strlcpy(opts,ptr1,2048);
734
735 //now parse it...
736 //firstly we just store strings like: xxx="Label Name"
737 //We'll store it in TOptionListItem objects, because they're derived
738 //from TObject and thus can be stored in TList.
739 //It's not elegant but works.
740 do {
741 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
742 if (ptr1) {
743 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
744 optionlist->Add(it);
745 }
746 } while(ptr1);
747
748 }
749 }
750
751 //having all options extracted and put into list, we finally can parse
752 //them to create a list of options...
753
754 fOptions = new TList(); //create the list
755
756 TIter next(optionlist.get()); //we'll iterate through all
757 //strings containing options
758 TOptionListItem *it = 0;
759 TOptionListItem *it1 = 0;
760 while ((it=(TOptionListItem*)next())) {
761
762 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.
763 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
764 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
765 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
766
767 if (islabel) {
768 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
769 fOptions->Add(it1);
770 } else {
771
772 char *strtolResult;
773 Long_t l = std::strtol(ptr1, &strtolResult, 10);
774 bool isnumber = (strtolResult != ptr1);
775
776 if (!isnumber) {
777 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
778 if (enumval) {
779 Int_t *value = (Int_t *)(enumval->GetAddress());
780 // We'll try to find global enum existing in ROOT...
781 l = (Long_t)(*value);
782 } else if (IsEnum()) {
784 if (obj)
785 l = ((TEnumConstant *)obj)->GetValue();
786 else
787 l = gInterpreter->Calc(Form("%s;", ptr1));
788 } else {
789 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
790 }
791 }
792
793 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
794 fOptions->Add(it1);
795 }
796
797 optionlist->Remove(it); //delete this option string from list
798 delete it; // and dispose of it.
799
800 }
801
802 // Garbage collection
803
804 //And dispose tokens string...
805 for (i=0;i<token_cnt;i++)
806 if(tokens[i])
807 delete [] tokens[i];
808}
809
810
811////////////////////////////////////////////////////////////////////////////////
812/// Returns list of options - list of TOptionListItems
813
815{
816 if (!fOptions)
818 return fOptions;
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// Return a TMethodCall method responsible for getting the value
823/// of data member. The cl argument specifies the class of the object
824/// which will be used to call this method (in case of multiple
825/// inheritance TMethodCall needs to know this to calculate the proper
826/// offset).
827
829{
830 if (!fValueGetter || cl) {
831
833
834 if (!cl) cl = fClass;
835
836 if (fValueGetter) {
837 TString methodname = fValueGetter->GetMethodName();
838 delete fValueGetter;
839 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
840
841 } else {
842 // try to guess Getter function:
843 // we strip the fist character of name of data field ('f') and then
844 // try to find the name of Getter by applying "Get", "Is" or "Has"
845 // as a prefix
846
847 const char *dataname = GetName();
848
849 TString gettername;
850 gettername.Form( "Get%s", dataname+1);
851 if (GetClass()->GetMethod(gettername, ""))
852 return fValueGetter = new TMethodCall(cl, gettername, "");
853 gettername.Form( "Is%s", dataname+1);
854 if (GetClass()->GetMethod(gettername, ""))
855 return fValueGetter = new TMethodCall(cl, gettername, "");
856 gettername.Form( "Has%s", dataname+1);
857 if (GetClass()->GetMethod(gettername, ""))
858 return fValueGetter = new TMethodCall(cl, gettername, "");
859 }
860 }
861
862 return fValueGetter;
863}
864
865////////////////////////////////////////////////////////////////////////////////
866/// Return a TMethodCall method responsible for setting the value
867/// of data member. The cl argument specifies the class of the object
868/// which will be used to call this method (in case of multiple
869/// inheritance TMethodCall needs to know this to calculate the proper
870/// offset).
871
873{
874 if (!fValueSetter || cl) {
875
877
878 if (!cl) cl = fClass;
879
880 if (fValueSetter) {
881
882 TString methodname = fValueSetter->GetMethodName();
883 TString params = fValueSetter->GetParams();
884 delete fValueSetter;
885 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
886
887 } else {
888
889 // try to guess Setter function:
890 // we strip the fist character of name of data field ('f') and then
891 // try to find the name of Setter by applying "Set" as a prefix
892
893 const char *dataname = GetName();
894
895 TString settername;
896 settername.Form( "Set%s", dataname+1);
897 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
898 if (GetClass()->GetMethod(settername, "1"))
899 fValueSetter = new TMethodCall(cl, settername, "1");
900 if (!fValueSetter)
901 if (GetClass()->GetMethod(settername, "true"))
902 fValueSetter = new TMethodCall(cl, settername, "true");
903 }
904 }
905
906 return fValueSetter;
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Update the TFunction to reflect the new info.
911///
912/// This can be used to implement unloading (info == 0) and then reloading
913/// (info being the 'new' decl address).
914
915Bool_t TDataMember::Update(DataMemberInfo_t *info)
916{
918
922 if (fOptions) {
923 fOptions->Delete();
925 }
926
927 if (info == 0) {
928 fOffset = -1;
929 fProperty = -1;
930 fSTLCont = -1;
931 fArrayDim = -1;
932 delete [] fArrayMaxIndex;
935
936 fInfo = 0;
937 return kTRUE;
938 } else {
939 fInfo = info;
940 Init(false);
941 return kTRUE;
942 }
943}
944
945
946////////////////////////////////////////////////////////////////////////////////
947/// Stream an object of TDataMember. Forces calculation of all cached
948/// (and persistent) values.
949
950void TDataMember::Streamer(TBuffer& b) {
951 if (b.IsReading()) {
952 b.ReadClassBuffer(Class(), this);
953 Init(true /*reading*/);
954 } else {
955 // Writing.
956 if (fProperty & kIsStatic) {
957 // We have a static member and in this case fOffset contains the
958 // actual address in memory of the data, it will be different everytime,
959 // let's not record it.
960 fOffset = -1;
961 } else {
962 GetOffset();
963 }
965 GetArrayDim();
967 Property(); // also calculates fTypeName and friends
968 b.WriteClassBuffer(Class(), this);
969 }
970}
971
972////////////////////////////////////////////////////////////////////////////////
973/// Constructor.
974
976 Long_t tglmask,const char *name, const char *label)
977{
978 fDataMember = d;
979 fValue = val;
980 fValueMaskBit = valmask;
981 fToggleMaskBit = tglmask;
982 if (name) {
983 fOptName = name;
984 }
985
986 if (label) {
987 fOptLabel = label;
988 }
989}
void Class()
Definition Class.C:29
Cppyy::TCppType_t fClass
#define SafeDelete(p)
Definition RConfig.hxx:547
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
char Char_t
Definition RtypesCore.h:37
const Bool_t kFALSE
Definition RtypesCore.h:92
long Long_t
Definition RtypesCore.h:54
const Bool_t kTRUE
Definition RtypesCore.h:91
#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
R__EXTERN TInterpreter * gCling
#define gInterpreter
#define gROOT
Definition TROOT.h:406
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:2020
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3747
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:5681
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:2957
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*".
DataMemberInfo_t * fInfo
Definition TDataMember.h:38
Int_t * fArrayMaxIndex
Definition TDataMember.h:46
Long_t GetOffset() const
Get offset from "this".
TString fTrueTypeName
Definition TDataMember.h:51
TMethodCall * fValueGetter
Definition TDataMember.h:56
Int_t GetArrayDim() const
Return number of array dimensions.
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
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
Long_t GetOffsetCint() const
Get offset from "this" using the information in CINT only.
Long_t fOffset
pointer to data basic type descriptor
Definition TDataMember.h:42
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 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: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
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 Long_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: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
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
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:1196
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:2309
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.
auto * l
Definition textangle.C:4
static byte * ptr1
Definition gifdecode.c:16
static byte * ptr2
Definition gifdecode.c:17