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 "TBuffer.h"
142#include "TClass.h"
143#include "TClassEdit.h"
144#include "TDataType.h"
145#include "TEnum.h"
146#include "TEnumConstant.h"
147#include "TGlobal.h"
148#include "TInterpreter.h"
149#include "TIterator.h"
150#include "TList.h"
151#include "TListOfDataMembers.h"
152#include "TMethod.h"
153#include "TMethodCall.h"
154#include "TRealData.h"
155#include "TROOT.h"
156#include "TVirtualMutex.h"
157
158#include <cassert>
159#include <cctype>
160#include <stdlib.h>
161
162
164
165////////////////////////////////////////////////////////////////////////////////
166/// Default TDataMember ctor. TDataMembers are constructed in TClass
167/// via a call to TCling::CreateListOfDataMembers(). It parses the comment
168/// string, initializes optionlist and getter/setter methods.
169
170TDataMember::TDataMember(DataMemberInfo_t *info, TClass *cl) : TDictionary()
171{
172 fInfo = info;
173 fClass = cl;
174 fDataType = 0;
175 fOptions = 0;
176 fValueSetter = 0;
177 fValueGetter = 0;
178 fOffset = -1;
179 fProperty = -1;
180 fSTLCont = -1;
181 fArrayDim = -1;
183 if (!fInfo && !fClass) return; // default ctor is called
184
185 Init(false);
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Routines called by the constructor and Update to reset the member's
190/// information.
191/// afterReading is set when initializing after reading through Streamer().
192
193void TDataMember::Init(bool afterReading)
194{
195 if (!afterReading) {
196 // Initialize from fInfo
197 if (!fInfo || !gInterpreter->DataMemberInfo_IsValid(fInfo))
198 return;
199 // Also sets names.
200 Property();
201 }
202 const char *t = GetTitle();
203 if (t && t[0] != '!')
205 fDataType = 0;
206 if (IsBasic() || IsEnum()) {
207 if (IsBasic()) {
208 const char *name = GetFullTypeName();
209 if (strcmp(name, "unsigned char") != 0 &&
210 strncmp(name, "unsigned short", sizeof ("unsigned short")) != 0 &&
211 strcmp(name, "unsigned int") != 0 &&
212 strncmp(name, "unsigned long", sizeof ("unsigned long")) != 0)
213 // strncmp() also covers "unsigned long long"
214 name = GetTypeName();
215 fDataType = gROOT->GetType(name);
216
217 if (fDataType==0) {
218 // humm we did not find it ... maybe it's a typedef that has not been loaded yet.
219 // (this can happen if the executable does not have a TApplication object).
220 fDataType = gROOT->GetType(name,kTRUE);
221 }
222 } else {
223 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.
224 }
225 // if (!fDataType)
226 // Error("TDataMember", "basic data type %s not found in list of basic types",
227 // GetTypeName());
228 }
229
230
231 if (afterReading) {
232 // Options are streamed; can't build TMethodCall for getters and setters
233 // because we deserialize a TDataMember when we do not have interpreter
234 // data. Thus do an early return.
235 return;
236 }
237
238 if (strstr(GetTitle(), "*OPTION={")) {
239 // Delay setting fOptions until it's used: the enum constants might
240 // not have been added as members yet.
241
242 // if option string does not exist but it's an Enum - parse it!!!!
243 } else if (IsEnum()) {
244 fOptions = new TList();
245 if (TEnum* enumDict = TEnum::GetEnum(GetTypeName()) ){
246 TIter iEnumConst(enumDict->GetConstants());
247 while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
249 = new TOptionListItem(this, enumConst->GetValue(),0,0,
250 enumConst->GetName(),enumConst->GetName());
251 fOptions->Add(it);
252 }
253 }
254
255 // and the case od Bool_t : we add items "ON" and "Off"
256 } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
257
258 fOptions = new TList();
259 TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",0);
260 fOptions->Add(it);
261 it = new TOptionListItem(this,0,0,0,"Off",0);
262 fOptions->Add(it);
263
264 } else fOptions = 0;
265
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// copy constructor
270
272 TDictionary(dm),
273 fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
274 fClass(dm.fClass),
275 fDataType(dm.fDataType),
276 fOffset(dm.fOffset),
277 fSTLCont(dm.fSTLCont),
278 fProperty(dm.fProperty),
279 fArrayDim(dm.fArrayDim),
280 fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0),
281 fArrayIndex(dm.fArrayIndex),
283 fFullTypeName(dm.fFullTypeName),
284 fTrueTypeName(dm.fTrueTypeName),
285 fValueGetter(0),
286 fValueSetter(0),
287 fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : 0)
288{
289 for(Int_t d = 0; d < fArrayDim; ++d)
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// assignment operator
295
297{
298 if(this!=&dm) {
300 delete fValueSetter;
301 delete fValueGetter;
302 if (fOptions) {
303 fOptions->Delete();
304 delete fOptions;
305 fOptions = 0;
306 }
307
310 fClass=dm.fClass;
312 fOffset=dm.fOffset;
315 fArrayDim = dm.fArrayDim;
316 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0;
317 for(Int_t d = 0; d < fArrayDim; ++d)
323 fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : 0;
324 }
325 return *this;
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// TDataMember dtor deletes adopted CINT DataMemberInfo object.
330
332{
333 delete [] fArrayMaxIndex;
335 delete fValueSetter;
336 delete fValueGetter;
337 if (fOptions) {
338 fOptions->Delete();
339 delete fOptions;
340 }
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Return number of array dimensions.
345
347{
348 if (fArrayDim<0 && fInfo) {
350 TDataMember *dm = const_cast<TDataMember*>(this);
352 // fArrayMaxIndex should be zero
353 if (dm->fArrayDim) {
354 dm->fArrayMaxIndex = new Int_t[fArrayDim];
355 for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
357 }
358 }
359 }
360 return fArrayDim;
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// If the data member is pointer and has a valid array size in its comments
365/// GetArrayIndex returns a string pointing to it;
366/// otherwise it returns an empty string.
367
368const char *TDataMember::GetArrayIndex() const
369{
370 if (!IsaPointer()) return "";
371 if (fArrayIndex.Length()==0 && fInfo) {
373 TDataMember *dm = const_cast<TDataMember*>(this);
374 const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
375 if (val) dm->fArrayIndex = val;
376 else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
377 }
378 return fArrayIndex;
379}
380
381////////////////////////////////////////////////////////////////////////////////
382
384{
385 if (fInfo) return gInterpreter->GetDeclId(fInfo);
386 else return 0;
387}
388
389////////////////////////////////////////////////////////////////////////////////
390/// Return maximum index for array dimension "dim".
391
393{
394 if (fArrayDim<0 && fInfo) {
396 } else {
397 if (dim < 0 || dim >= fArrayDim) return -1;
398 return fArrayMaxIndex[dim];
399 }
400}
401
402////////////////////////////////////////////////////////////////////////////////
403/// Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
404
405const char *TDataMember::GetTypeName() const
406{
407 if (fProperty==(-1)) Property();
408 return fTypeName.Data();
409}
410
411////////////////////////////////////////////////////////////////////////////////
412/// Get full type description of data member, e,g.: "class TDirectory*".
413
415{
416 if (fProperty==(-1)) Property();
417
418 return fFullTypeName.Data();
419}
420
421////////////////////////////////////////////////////////////////////////////////
422/// Get full type description of data member, e,g.: "class TDirectory*".
423
425{
426 return fTrueTypeName.Data();
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Get offset from "this".
431
433{
434 if (fOffset>=0) return fOffset;
435
437 //case of an interpreted or emulated class
438 if (fClass->GetDeclFileLine() < 0) {
439 ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
440 return fOffset;
441 }
442 //case of a compiled class
443 //Note that the offset cannot be computed in case of an abstract class
444 //for which the list of real data has not yet been computed via
445 //a real daughter class.
446 TString dmbracket;
447 dmbracket.Form("%s[",GetName());
450 TRealData *rdm;
451 Int_t offset = 0;
452 while ((rdm = (TRealData*)next())) {
453 char *rdmc = (char*)rdm->GetName();
454 //next statement required in case a class and one of its parent class
455 //have data members with the same name
456 if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
457
458 if (rdm->GetDataMember() != this) continue;
459 if (strcmp(rdmc,GetName()) == 0) {
460 offset = rdm->GetThisOffset();
461 break;
462 }
463 if (strcmp(rdm->GetName(),GetName()) == 0) {
464 if (rdm->IsObject()) {
465 offset = rdm->GetThisOffset();
466 break;
467 }
468 }
469 if (strstr(rdm->GetName(),dmbracket.Data())) {
470 offset = rdm->GetThisOffset();
471 break;
472 }
473 }
474 ((TDataMember*)this)->fOffset = offset;
475 return fOffset;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Get offset from "this" using the information in CINT only.
480
482{
483 if (fOffset>=0) return fOffset;
484
486 TDataMember *dm = const_cast<TDataMember*>(this);
487
488 if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
489 else return -1;
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Get the sizeof the underlying type of the data member
494/// (i.e. if the member is an array sizeof(member)/length)
495
497{
498 if (IsaPointer()) return sizeof(void*);
499 if (IsEnum() ) return sizeof(Int_t);
500 if (IsBasic() ) return GetDataType()->Size();
501
503 if (!cl) cl = TClass::GetClass(GetTrueTypeName());
504 if ( cl) return cl->Size();
505
506 Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
507 return 0;
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Return true if data member is a basic type, e.g. char, int, long...
512
514{
515 if (fProperty == -1) Property();
516 return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
517}
518
519////////////////////////////////////////////////////////////////////////////////
520/// Return true if data member is an enum.
521
523{
524 if (fProperty == -1) Property();
525 return (fProperty & kIsEnum) ? kTRUE : kFALSE;
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Return true if data member is a pointer.
530
532{
533 if (fProperty == -1) Property();
534 return (fProperty & kIsPointer) ? kTRUE : kFALSE;
535}
536
537////////////////////////////////////////////////////////////////////////////////
538/// The return type is defined in TDictionary (kVector, kList, etc.)
539
541{
542 if (fSTLCont != -1) return fSTLCont;
545 return fSTLCont;
546}
547
548////////////////////////////////////////////////////////////////////////////////
549/// Return true if this data member object is pointing to a currently
550/// loaded data member. If a function is unloaded after the TDataMember
551/// is created, the TDataMember will be set to be invalid.
552
554{
555 if (fOffset >= 0) return kTRUE;
556
557 // Register the transaction when checking the validity of the object.
559 DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
560 if (newId) {
561 DataMemberInfo_t *info
562 = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
563 Update(info);
564 // We need to make sure that the list of data member is properly
565 // informed and updated.
567 lst->Update(this);
568 }
569 return newId != 0;
570 }
571 return fInfo != 0;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Get property description word. For meaning of bits see EProperty.
576
578{
579 if (fProperty!=(-1)) return fProperty;
580
582 TDataMember *t = (TDataMember*)this;
583
584 if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
587 t->fProperty = prop|propt;
588
592
595
596 return fProperty;
597}
598
599
600////////////////////////////////////////////////////////////////////////////////
601/// Build TOptionListItems from the member comment `*OPTION={`
602
604{
605 if (fOptions)
606 return;
607
608 const char *optTitle = strstr(GetTitle(), "*OPTION={");
609 if (!optTitle)
610 return;
611
612 // If option string exist in comment - we'll parse it and create
613 // list of options
614
615 // Option-list string has a form:
616 // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
617 // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
618 //
619 // As one can see it is possible to specify value as either numerical
620 // value , string or enum.
621 // One can also specify implicitly names of Getter/Setter methods.
622
623 char cmt[2048];
624 char opt[2048];
625 const char *ptr1 = 0;
626 char *ptr2 = 0;
627 char *ptr3 = 0;
628 char *tok = 0;
629 Int_t cnt = 0;
630 Int_t token_cnt;
631 Int_t i;
632
633 strlcpy(cmt,GetTitle(),2048);
634
635 char *opt_ptr = strstr(cmt, "*OPTION={");
636
637 // If we found it - parsing...
638
639 //let's cut the part lying between {}
640 char *rest;
641 ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
642 if (ptr1 == 0) {
643 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
644 return;
645 }
646 ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
647 if (ptr1 == 0) {
648 Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
649 return;
650 }
651
652 //and save it:
653 strlcpy(opt,ptr1,2048);
654
655 // Let's extract sub-tokens extracted by ';' sign.
656 // We'll put'em in an array for convenience;
657 // You have to do it in this manner because you cannot use nested tokenizing
658
659 char *tokens[256]; // a storage for these sub-tokens.
660 token_cnt = 0;
661 cnt = 0;
662
663 do { //tokenizing loop
664 ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
665 if (ptr1){
666 Int_t nch = strlen(ptr1)+1;
667 tok=new char[nch];
668 strlcpy(tok,ptr1,nch);
669 tokens[token_cnt]=tok;
670 token_cnt++;
671 }
672 } while (ptr1);
673
674 // OK! Now let's check whether we have Get/Set methods encode in any string
675 for (i=0;i<token_cnt;i++) {
676 if (strstr(tokens[i],"GetMethod")) {
677 ptr1 = R__STRTOK_R(tokens[i], "\"", &rest); // tokenizing-strip text "GetMethod"
678 if (ptr1 == 0) {
679 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
680 return;
681 }
682 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
683 if (ptr1 == 0) {
684 Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
685 return;
686 }
687
688 if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
689 // FIXME: wrong in case called derives via multiple inheritance from this class
691
692 continue; //next item!
693 }
694
695 if (strstr(tokens[i],"SetMethod")) {
696 ptr1 = R__STRTOK_R(tokens[i], "\"", &rest);
697 if (ptr1 == 0) {
698 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
699 return;
700 }
701 ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
702 if (ptr1 == 0) {
703 Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
704 return;
705 }
706 if (GetClass()->GetMethod(ptr1,"1"))
707 // FIXME: wrong in case called derives via multiple inheritance from this class
709 }
710 }
711
712 //Now let's parse option strings...
713
714 Int_t opt_cnt = 0;
715 std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
716
717 for (i=0;i<token_cnt;i++) {
718 if (strstr(tokens[i],"Items")) {
719 ptr1 = R__STRTOK_R(tokens[i], "()", &rest);
720 if (ptr1 == 0) {
721 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
722 return;
723 }
724 ptr1 = R__STRTOK_R(nullptr, "()", &rest);
725 if (ptr1 == 0) {
726 Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
727 return;
728 }
729
730 char opts[2048]; //and save it!
731 strlcpy(opts,ptr1,2048);
732
733 //now parse it...
734 //firstly we just store strings like: xxx="Label Name"
735 //We'll store it in TOptionListItem objects, because they're derived
736 //from TObject and thus can be stored in TList.
737 //It's not elegant but works.
738 do {
739 ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
740 if (ptr1) {
741 TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
742 optionlist->Add(it);
743 }
744 } while(ptr1);
745
746 }
747 }
748
749 //having all options extracted and put into list, we finally can parse
750 //them to create a list of options...
751
752 fOptions = new TList(); //create the list
753
754 TIter next(optionlist.get()); //we'll iterate through all
755 //strings containing options
756 TOptionListItem *it = 0;
757 TOptionListItem *it1 = 0;
758 while ((it=(TOptionListItem*)next())) {
759
760 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.
761 Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
762 ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
763 ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
764
765 if (islabel) {
766 it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
767 fOptions->Add(it1);
768 } else {
769
770 char *strtolResult;
771 Long_t l = std::strtol(ptr1, &strtolResult, 10);
772 bool isnumber = (strtolResult != ptr1);
773
774 if (!isnumber) {
775 TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
776 if (enumval) {
777 Int_t *value = (Int_t *)(enumval->GetAddress());
778 // We'll try to find global enum existing in ROOT...
779 l = (Long_t)(*value);
780 } else if (IsEnum()) {
782 if (obj)
783 l = ((TEnumConstant *)obj)->GetValue();
784 else
785 l = gInterpreter->Calc(Form("%s;", ptr1));
786 } else {
787 Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
788 }
789 }
790
791 it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
792 fOptions->Add(it1);
793 }
794
795 optionlist->Remove(it); //delete this option string from list
796 delete it; // and dispose of it.
797
798 }
799
800 // Garbage collection
801
802 //And dispose tokens string...
803 for (i=0;i<token_cnt;i++)
804 if(tokens[i])
805 delete [] tokens[i];
806}
807
808
809////////////////////////////////////////////////////////////////////////////////
810/// Returns list of options - list of TOptionListItems
811
813{
814 if (!fOptions)
816 return fOptions;
817}
818
819////////////////////////////////////////////////////////////////////////////////
820/// Return a TMethodCall method responsible for getting the value
821/// of data member. The cl argument specifies the class of the object
822/// which will be used to call this method (in case of multiple
823/// inheritance TMethodCall needs to know this to calculate the proper
824/// offset).
825
827{
828 if (!fValueGetter || cl) {
829
831
832 if (!cl) cl = fClass;
833
834 if (fValueGetter) {
835 TString methodname = fValueGetter->GetMethodName();
836 delete fValueGetter;
837 fValueGetter = new TMethodCall(cl, methodname.Data(), "");
838
839 } else {
840 // try to guess Getter function:
841 // we strip the fist character of name of data field ('f') and then
842 // try to find the name of Getter by applying "Get", "Is" or "Has"
843 // as a prefix
844
845 const char *dataname = GetName();
846
847 TString gettername;
848 gettername.Form( "Get%s", dataname+1);
849 if (GetClass()->GetMethod(gettername, ""))
850 return fValueGetter = new TMethodCall(cl, gettername, "");
851 gettername.Form( "Is%s", dataname+1);
852 if (GetClass()->GetMethod(gettername, ""))
853 return fValueGetter = new TMethodCall(cl, gettername, "");
854 gettername.Form( "Has%s", dataname+1);
855 if (GetClass()->GetMethod(gettername, ""))
856 return fValueGetter = new TMethodCall(cl, gettername, "");
857 }
858 }
859
860 return fValueGetter;
861}
862
863////////////////////////////////////////////////////////////////////////////////
864/// Return a TMethodCall method responsible for setting the value
865/// of data member. The cl argument specifies the class of the object
866/// which will be used to call this method (in case of multiple
867/// inheritance TMethodCall needs to know this to calculate the proper
868/// offset).
869
871{
872 if (!fValueSetter || cl) {
873
875
876 if (!cl) cl = fClass;
877
878 if (fValueSetter) {
879
880 TString methodname = fValueSetter->GetMethodName();
881 TString params = fValueSetter->GetParams();
882 delete fValueSetter;
883 fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
884
885 } else {
886
887 // try to guess Setter function:
888 // we strip the fist character of name of data field ('f') and then
889 // try to find the name of Setter by applying "Set" as a prefix
890
891 const char *dataname = GetName();
892
893 TString settername;
894 settername.Form( "Set%s", dataname+1);
895 if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
896 if (GetClass()->GetMethod(settername, "1"))
897 fValueSetter = new TMethodCall(cl, settername, "1");
898 if (!fValueSetter)
899 if (GetClass()->GetMethod(settername, "true"))
900 fValueSetter = new TMethodCall(cl, settername, "true");
901 }
902 }
903
904 return fValueSetter;
905}
906
907////////////////////////////////////////////////////////////////////////////////
908/// Update the TFunction to reflect the new info.
909///
910/// This can be used to implement unloading (info == 0) and then reloading
911/// (info being the 'new' decl address).
912
913Bool_t TDataMember::Update(DataMemberInfo_t *info)
914{
916
920 if (fOptions) {
921 fOptions->Delete();
923 }
924
925 if (info == 0) {
926 fOffset = -1;
927 fProperty = -1;
928 fSTLCont = -1;
929 fArrayDim = -1;
930 delete [] fArrayMaxIndex;
933
934 fInfo = 0;
935 return kTRUE;
936 } else {
937 fInfo = info;
938 Init(false);
939 return kTRUE;
940 }
941}
942
943
944////////////////////////////////////////////////////////////////////////////////
945/// Stream an object of TDataMember. Forces calculation of all cached
946/// (and persistent) values.
947
948void TDataMember::Streamer(TBuffer& b) {
949 if (b.IsReading()) {
950 b.ReadClassBuffer(Class(), this);
951 Init(true /*reading*/);
952 } else {
953 // Writing.
954 if (fProperty & kIsStatic) {
955 // We have a static member and in this case fOffset contains the
956 // actual address in memory of the data, it will be different everytime,
957 // let's not record it.
958 fOffset = -1;
959 } else {
960 GetOffset();
961 }
963 GetArrayDim();
965 Property(); // also calculates fTypeName and friends
966 b.WriteClassBuffer(Class(), this);
967 }
968}
969
970////////////////////////////////////////////////////////////////////////////////
971/// Constructor.
972
974 Long_t tglmask,const char *name, const char *label)
975{
976 fDataMember = d;
977 fValue = val;
978 fValueMaskBit = valmask;
979 fToggleMaskBit = tglmask;
980 if (name) {
981 fOptName = name;
982 }
983
984 if (label) {
985 fOptLabel = label;
986 }
987}
void Class()
Definition: Class.C:29
Cppyy::TCppType_t fClass
#define SafeDelete(p)
Definition: RConfig.hxx:543
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
char Char_t
Definition: RtypesCore.h:31
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
char * R__STRTOK_R(char *str, const char *delim, char **saveptr)
Definition: Rtypes.h:482
@ 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:109
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:557
#define gInterpreter
Definition: TInterpreter.h:556
#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:42
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:2011
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3738
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:5667
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:2948
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.
@ kObjIsPersistent
Definition: TDataMember.h:35
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 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:166
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:222
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:455
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:465
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:463
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
Definition: TInterpreter.h:467
virtual Long_t DataMemberInfo_Offset(DataMemberInfo_t *) const
Definition: TInterpreter.h:459
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
Definition: TInterpreter.h:456
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:461
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:460
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:451
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:452
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:457
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
Definition: TInterpreter.h:466
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
Definition: TInterpreter.h:464
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:577
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
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:877
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:919
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:131
Ssiz_t Length() const
Definition: TString.h:405
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1176
const char * Data() const
Definition: TString.h:364
TString & Append(const char *cs)
Definition: TString.h:559
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
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:887
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:74
auto * l
Definition: textangle.C:4
static byte * ptr1
Definition: gifdecode.c:16
static byte * ptr2
Definition: gifdecode.c:17