Logo ROOT   6.19/01
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 
14 All ROOT classes may have RTTI (run time type identification) support
15 added. The data is stored in so called DICTIONARY (look at TDictionary).
16 Information about a class is stored in TClass.
17 This information may be obtained via the cling api - see class TCling.
18 TClass has a list of TDataMember objects providing information about all
19 data members of described class.
20 
21 \image html base_classinfo.png
22 
23 TDataMember provides information about name of data member, its type,
24 and comment field string. It also tries to find the TMethodCall objects
25 responsible for getting/setting a value of it, and gives you pointers
26 to these methods. This gives you a unique possibility to access
27 protected and private (!) data members if only methods for doing that
28 are defined.
29 
30 These methods could either be specified in a comment field, or found
31 out automatically by ROOT: here's an example:
32 suppose 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 ~~~
44 Look at the data member name and method names: a data member name has
45 a prefix letter (f) and has a base name X1 . The methods for getting and
46 setting this value have names which consist of string Get/Set and the
47 same base name. This convention of naming data fields and methods which
48 access them allows TDataMember find this methods by itself completely
49 automatically. To make this description complete, one should know,
50 that names that are automatically recognized may be also:
51 for data fields: either fXXX or fIsXXX; and for getter function
52 GetXXX() or IsXXX() [where XXX is base name].
53 
54 As an example of using it let's analyse a few lines which get and set
55 a 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 
72 This trick is widely used in ROOT TContextMenu and dialogs for obtaining
73 current values and put them as initial values in dialog fields.
74 
75 If you don't want to follow the convention of naming used by ROOT
76 you still could benefit from Getter/Setter method support: the solution
77 is to instruct ROOT what the names of these routines are.
78 The way to do it is putting this information in a comment string to a data
79 field 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 
90 However, this getting/setting functions are not the only feature of
91 this class. The next point is providing lists of possible settings
92 for the concerned data member. The idea is to have a list of possible
93 options for this data member, with strings identifying them. This
94 is used in dialogs with parameters to set - for details see
95 TMethodArg, TRootContextMenu, TContextMenu. This list not only specifies
96 the allowed value, but also provides strings naming the options.
97 Options are managed via TList of TOptionListItem objects. This list
98 is also created automatically: if a data type is an enum type,
99 the list will have items describing every enum value, and named
100 according to enum name. If type is Bool_t, two options "On" and "Off"
101 with values 0 and 1 are created. For other types you need to instruct
102 ROOT about possible options. The way to do it is the same as in case of
103 specifying getter/setter method: a comment string to a data field in
104 Your header file with class definition.
105 The most general format of this string is:
106 ~~~ {.cpp}
107 *OPTIONS={GetMethod="getter";SetMethod="setter";Items=(it1="title1",it2="title2", ... ) }
108 ~~~
109 
110 While parsing this string ROOT firstly looks for command-tokens:
111 GetMethod, SetMethod, Items; They must be preceded by string
112 *OPTIONS= , enclosed by {} and separated by semicolons ";".
113 All command token should have a form TOKEN=VALUE.
114 All tokens are optional.
115 The names of getter and setter method must be enclosed by double-quote
116 marks (") .
117 Specifications of Items is slightly more complicated: you need to
118 put token ITEMS= and then enclose all options in curly brackets "()".
119 You separate options by comas ",".
120 Each 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 
130 One can specify values as Integers or Enums - when data field is an
131 Integer, Float or Enum type; as texts - for char (more precisely:
132 Option_t).
133 
134 As mentioned above - this information are mainly used by contextmenu,
135 but also in Dump() and Inspect() methods and by the THtml class.
136 */
137 
138 #include "TDataMember.h"
139 
140 #include "Strlen.h"
141 #include "TClass.h"
142 #include "TClassEdit.h"
143 #include "TDataType.h"
144 #include "TEnum.h"
145 #include "TEnumConstant.h"
146 #include "TGlobal.h"
147 #include "TInterpreter.h"
148 #include "TIterator.h"
149 #include "TList.h"
150 #include "TListOfDataMembers.h"
151 #include "TMethod.h"
152 #include "TMethodCall.h"
153 #include "TRealData.h"
154 #include "TROOT.h"
155 #include "TVirtualMutex.h"
156 
157 #include <cassert>
158 #include <cctype>
159 #include <stdlib.h>
160 
161 
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Default TDataMember ctor. TDataMembers are constructed in TClass
166 /// via a call to TCling::CreateListOfDataMembers(). It parses the comment
167 /// string, initializes optionlist and getter/setter methods.
168 
169 TDataMember::TDataMember(DataMemberInfo_t *info, TClass *cl) : TDictionary()
170 {
171  fInfo = info;
172  fClass = cl;
173  fDataType = 0;
174  fOptions = 0;
175  fValueSetter = 0;
176  fValueGetter = 0;
177  fOffset = -1;
178  fProperty = -1;
179  fSTLCont = -1;
180  fArrayDim = -1;
181  fArrayMaxIndex=0;
182  if (!fInfo && !fClass) return; // default ctor is called
183 
184  Init(false);
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Routines called by the constructor and Update to reset the member's
189 /// information.
190 /// afterReading is set when initializing after reading through Streamer().
191 
192 void TDataMember::Init(bool afterReading)
193 {
194  const char *t = 0;
195  if (!afterReading) {
196  // Initialize from fInfo
197  if (!fInfo || !gInterpreter->DataMemberInfo_IsValid(fInfo)) return;
198 
204  SetTitle(t);
205  } else {
206  // We have read the persistent data members.
207  t = GetTitle();
208  }
209  if (t && t[0] != '!') SetBit(kObjIsPersistent);
210  fDataType = 0;
211  if (IsBasic() || IsEnum()) {
212  if (IsBasic()) {
213  const char *name = GetFullTypeName();
214  if (strcmp(name, "unsigned char") != 0 &&
215  strncmp(name, "unsigned short", sizeof ("unsigned short")) != 0 &&
216  strcmp(name, "unsigned int") != 0 &&
217  strncmp(name, "unsigned long", sizeof ("unsigned long")) != 0)
218  // strncmp() also covers "unsigned long long"
219  name = GetTypeName();
220  fDataType = gROOT->GetType(name);
221 
222  if (fDataType==0) {
223  // humm we did not find it ... maybe it's a typedef that has not been loaded yet.
224  // (this can happen if the executable does not have a TApplication object).
225  fDataType = gROOT->GetType(name,kTRUE);
226  }
227  } else {
228  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.
229  }
230  // if (!fDataType)
231  // Error("TDataMember", "basic data type %s not found in list of basic types",
232  // GetTypeName());
233  }
234 
235 
236  if (afterReading) {
237  // Options are streamed; can't build TMethodCall for getters and setters
238  // because we deserialize a TDataMember when we do not have interpreter
239  // data. Thus do an early return.
240  return;
241  }
242 
243 
244  // If option string exist in comment - we'll parse it and create
245  // list of options
246 
247  // Option-list string has a form:
248  // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
249  // Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
250  //
251  // As one can see it is possible to specify value as either numerical
252  // value , string or enum.
253  // One can also specify implicitly names of Getter/Setter methods.
254 
255  char cmt[2048];
256  char opt[2048];
257  char *opt_ptr = 0;
258  const char *ptr1 = 0;
259  char *ptr2 = 0;
260  char *ptr3 = 0;
261  char *tok = 0;
262  Int_t cnt = 0;
263  Int_t token_cnt;
264  Int_t i;
265 
266  strlcpy(cmt,GetTitle(),2048);
267 
268  if ((opt_ptr=strstr(cmt,"*OPTION={"))) {
269 
270  // If we found it - parsing...
271 
272  //let's cut the part lying between {}
273  char *rest;
274  ptr1 = R__STRTOK_R(opt_ptr, "{}", &rest); // starts tokenizing:extracts "*OPTION={"
275  if (ptr1 == 0) {
276  Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
277  return;
278  }
279  ptr1 = R__STRTOK_R(nullptr, "{}", &rest); // And now we have what we need in ptr1!!!
280  if (ptr1 == 0) {
281  Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
282  return;
283  }
284 
285  //and save it:
286  strlcpy(opt,ptr1,2048);
287 
288  // Let's extract sub-tokens extracted by ';' sign.
289  // We'll put'em in an array for convenience;
290  // You have to do it in this manner because you cannot use nested tokenizing
291 
292  char *tokens[256]; // a storage for these sub-tokens.
293  token_cnt = 0;
294  cnt = 0;
295 
296  do { //tokenizing loop
297  ptr1 = R__STRTOK_R((char *)(cnt++ ? nullptr : opt), ";", &rest);
298  if (ptr1){
299  Int_t nch = strlen(ptr1)+1;
300  tok=new char[nch];
301  strlcpy(tok,ptr1,nch);
302  tokens[token_cnt]=tok;
303  token_cnt++;
304  }
305  } while (ptr1);
306 
307  // OK! Now let's check whether we have Get/Set methods encode in any string
308  for (i=0;i<token_cnt;i++) {
309  if (strstr(tokens[i],"GetMethod")) {
310  ptr1 = R__STRTOK_R(tokens[i], "\"", &rest); // tokenizing-strip text "GetMethod"
311  if (ptr1 == 0) {
312  Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
313  return;
314  }
315  ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // tokenizing - name is in ptr1!
316  if (ptr1 == 0) {
317  Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",GetTitle());
318  return;
319  }
320 
321  if (!afterReading && GetClass()->GetMethod(ptr1,"")) // check whether such method exists
322  // FIXME: wrong in case called derives via multiple inheritance from this class
324 
325  continue; //next item!
326  }
327 
328  if (strstr(tokens[i],"SetMethod")) {
329  ptr1 = R__STRTOK_R(tokens[i], "\"", &rest);
330  if (ptr1 == 0) {
331  Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
332  return;
333  }
334  ptr1 = R__STRTOK_R(nullptr, "\"", &rest); // name of Setter in ptr1
335  if (ptr1 == 0) {
336  Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
337  return;
338  }
339  if (GetClass()->GetMethod(ptr1,"1"))
340  // FIXME: wrong in case called derives via multiple inheritance from this class
341  fValueSetter = new TMethodCall(GetClass(),ptr1,"1");
342  }
343  }
344 
345  //Now let's parse option strings...
346 
347  Int_t opt_cnt = 0;
348  std::unique_ptr<TList> optionlist{new TList()}; //storage for options strings
349 
350  for (i=0;i<token_cnt;i++) {
351  if (strstr(tokens[i],"Items")) {
352  ptr1 = R__STRTOK_R(tokens[i], "()", &rest);
353  if (ptr1 == 0) {
354  Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
355  return;
356  }
357  ptr1 = R__STRTOK_R(nullptr, "()", &rest);
358  if (ptr1 == 0) {
359  Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
360  return;
361  }
362 
363  char opts[2048]; //and save it!
364  strlcpy(opts,ptr1,2048);
365 
366  //now parse it...
367  //firstly we just store strings like: xxx="Label Name"
368  //We'll store it in TOptionListItem objects, because they're derived
369  //from TObject and thus can be stored in TList.
370  //It's not elegant but works.
371  do {
372  ptr1 = R__STRTOK_R(opt_cnt++ ? nullptr : opts, ",", &rest); // options extraction
373  if (ptr1) {
374  TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
375  optionlist->Add(it);
376  }
377  } while(ptr1);
378 
379  }
380  }
381 
382  //having all options extracted and put into list, we finally can parse
383  //them to create a list of options...
384 
385  fOptions = new TList(); //create the list
386 
387  TIter next(optionlist.get()); //we'll iterate through all
388  //strings containing options
389  TOptionListItem *it = 0;
390  TOptionListItem *it1 = 0;
391  while ((it=(TOptionListItem*)next())) {
392 
393  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.
394  Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
395  ptr2 = R__STRTOK_R((char *)ptr1, "=\"", &rest); // extract LeftHandeSide
396  ptr3 = R__STRTOK_R(nullptr, "=\"", &rest); // extract RightHandedSize
397 
398  if (islabel) {
399  it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
400  fOptions->Add(it1);
401  } else {
402 
403  char *strtolResult;
404  Long_t l = std::strtol(ptr1, &strtolResult, 10);
405  bool isnumber = (strtolResult != ptr1);
406 
407  if (!isnumber) {
408  TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
409  if (enumval) {
410  Int_t *value = (Int_t *)(enumval->GetAddress());
411  // We'll try to find global enum existing in ROOT...
412  l = (Long_t)(*value);
413  } else if (IsEnum()) {
415  if (obj)
416  l = ((TEnumConstant *)obj)->GetValue();
417  else
418  l = gInterpreter->Calc(Form("%s;", ptr1));
419  } else {
420  Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
421  }
422  }
423 
424  it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
425  fOptions->Add(it1);
426  }
427 
428  optionlist->Remove(it); //delete this option string from list
429  delete it; // and dispose of it.
430 
431  }
432 
433  // Garbage collection
434 
435  //And dispose tokens string...
436  for (i=0;i<token_cnt;i++) if(tokens[i]) delete [] tokens[i];
437 
438  // if option string does not exist but it's an Enum - parse it!!!!
439  } else if (IsEnum()) {
440  fOptions = new TList();
441  if (TEnum* enumDict = TEnum::GetEnum(GetTypeName()) ){
442  TIter iEnumConst(enumDict->GetConstants());
443  while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
444  TOptionListItem *it
445  = new TOptionListItem(this, enumConst->GetValue(),0,0,
446  enumConst->GetName(),enumConst->GetName());
447  fOptions->Add(it);
448  }
449  }
450 
451  // and the case od Bool_t : we add items "ON" and "Off"
452  } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
453 
454  fOptions = new TList();
455  TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",0);
456  fOptions->Add(it);
457  it = new TOptionListItem(this,0,0,0,"Off",0);
458  fOptions->Add(it);
459 
460  } else fOptions = 0;
461 
462 }
463 
464 ////////////////////////////////////////////////////////////////////////////////
465 /// copy constructor
466 
468  TDictionary(dm),
469  fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
470  fClass(dm.fClass),
471  fDataType(dm.fDataType),
472  fOffset(dm.fOffset),
473  fSTLCont(dm.fSTLCont),
474  fProperty(dm.fProperty),
475  fArrayDim(dm.fArrayDim),
476  fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0),
477  fArrayIndex(dm.fArrayIndex),
478  fTypeName(dm.fTypeName),
479  fFullTypeName(dm.fFullTypeName),
480  fTrueTypeName(dm.fTrueTypeName),
481  fValueGetter(0),
482  fValueSetter(0),
483  fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : 0)
484 {
485  for(Int_t d = 0; d < fArrayDim; ++d)
487 }
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 /// assignment operator
491 
493 {
494  if(this!=&dm) {
496  delete fValueSetter;
497  delete fValueGetter;
498  if (fOptions) {
499  fOptions->Delete();
500  delete fOptions;
501  fOptions = 0;
502  }
503 
506  fClass=dm.fClass;
507  fDataType=dm.fDataType;
508  fOffset=dm.fOffset;
509  fSTLCont=dm.fSTLCont;
510  fProperty=dm.fProperty;
511  fArrayDim = dm.fArrayDim;
512  fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0;
513  for(Int_t d = 0; d < fArrayDim; ++d)
516  fTypeName=dm.fTypeName;
519  fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : 0;
520  }
521  return *this;
522 }
523 
524 ////////////////////////////////////////////////////////////////////////////////
525 /// TDataMember dtor deletes adopted CINT DataMemberInfo object.
526 
528 {
529  delete [] fArrayMaxIndex;
531  delete fValueSetter;
532  delete fValueGetter;
533  if (fOptions) {
534  fOptions->Delete();
535  delete fOptions;
536  }
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 /// Return number of array dimensions.
541 
543 {
544  if (fArrayDim<0 && fInfo) {
546  TDataMember *dm = const_cast<TDataMember*>(this);
548  // fArrayMaxIndex should be zero
549  if (dm->fArrayDim) {
550  dm->fArrayMaxIndex = new Int_t[fArrayDim];
551  for(Int_t dim = 0; dim < dm->fArrayDim; ++dim) {
553  }
554  }
555  }
556  return fArrayDim;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// If the data member is pointer and has a valid array size in its comments
561 /// GetArrayIndex returns a string pointing to it;
562 /// otherwise it returns an empty string.
563 
564 const char *TDataMember::GetArrayIndex() const
565 {
566  if (!IsaPointer()) return "";
567  if (fArrayIndex.Length()==0 && fInfo) {
569  TDataMember *dm = const_cast<TDataMember*>(this);
570  const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
571  if (val) dm->fArrayIndex = val;
572  else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
573  }
574  return fArrayIndex;
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 
580 {
581  if (fInfo) return gInterpreter->GetDeclId(fInfo);
582  else return 0;
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Return maximum index for array dimension "dim".
587 
589 {
590  if (fArrayDim<0 && fInfo) {
591  return gCling->DataMemberInfo_MaxIndex(fInfo,dim);
592  } else {
593  if (dim < 0 || dim >= fArrayDim) return -1;
594  return fArrayMaxIndex[dim];
595  }
596 }
597 
598 ////////////////////////////////////////////////////////////////////////////////
599 /// Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
600 
601 const char *TDataMember::GetTypeName() const
602 {
603  if (fProperty==(-1)) Property();
604  return fTypeName.Data();
605 }
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 /// Get full type description of data member, e,g.: "class TDirectory*".
609 
610 const char *TDataMember::GetFullTypeName() const
611 {
612  if (fProperty==(-1)) Property();
613 
614  return fFullTypeName.Data();
615 }
616 
617 ////////////////////////////////////////////////////////////////////////////////
618 /// Get full type description of data member, e,g.: "class TDirectory*".
619 
620 const char *TDataMember::GetTrueTypeName() const
621 {
622  return fTrueTypeName.Data();
623 }
624 
625 ////////////////////////////////////////////////////////////////////////////////
626 /// Get offset from "this".
627 
629 {
630  if (fOffset>=0) return fOffset;
631 
633  //case of an interpreted or emulated class
634  if (fClass->GetDeclFileLine() < 0) {
635  ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
636  return fOffset;
637  }
638  //case of a compiled class
639  //Note that the offset cannot be computed in case of an abstract class
640  //for which the list of real data has not yet been computed via
641  //a real daughter class.
642  TString dmbracket;
643  dmbracket.Form("%s[",GetName());
645  TIter next(fClass->GetListOfRealData());
646  TRealData *rdm;
647  Int_t offset = 0;
648  while ((rdm = (TRealData*)next())) {
649  char *rdmc = (char*)rdm->GetName();
650  //next statement required in case a class and one of its parent class
651  //have data members with the same name
652  if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
653 
654  if (rdm->GetDataMember() != this) continue;
655  if (strcmp(rdmc,GetName()) == 0) {
656  offset = rdm->GetThisOffset();
657  break;
658  }
659  if (strcmp(rdm->GetName(),GetName()) == 0) {
660  if (rdm->IsObject()) {
661  offset = rdm->GetThisOffset();
662  break;
663  }
664  }
665  if (strstr(rdm->GetName(),dmbracket.Data())) {
666  offset = rdm->GetThisOffset();
667  break;
668  }
669  }
670  ((TDataMember*)this)->fOffset = offset;
671  return fOffset;
672 }
673 
674 ////////////////////////////////////////////////////////////////////////////////
675 /// Get offset from "this" using the information in CINT only.
676 
678 {
679  if (fOffset>=0) return fOffset;
680 
682  TDataMember *dm = const_cast<TDataMember*>(this);
683 
684  if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
685  else return -1;
686 }
687 
688 ////////////////////////////////////////////////////////////////////////////////
689 /// Get the sizeof the underlying type of the data member
690 /// (i.e. if the member is an array sizeof(member)/length)
691 
693 {
694  if (IsaPointer()) return sizeof(void*);
695  if (IsEnum() ) return sizeof(Int_t);
696  if (IsBasic() ) return GetDataType()->Size();
697 
699  if (!cl) cl = TClass::GetClass(GetTrueTypeName());
700  if ( cl) return cl->Size();
701 
702  Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
703  return 0;
704 }
705 
706 ////////////////////////////////////////////////////////////////////////////////
707 /// Return true if data member is a basic type, e.g. char, int, long...
708 
710 {
711  if (fProperty == -1) Property();
712  return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
713 }
714 
715 ////////////////////////////////////////////////////////////////////////////////
716 /// Return true if data member is an enum.
717 
719 {
720  if (fProperty == -1) Property();
721  return (fProperty & kIsEnum) ? kTRUE : kFALSE;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 /// Return true if data member is a pointer.
726 
728 {
729  if (fProperty == -1) Property();
730  return (fProperty & kIsPointer) ? kTRUE : kFALSE;
731 }
732 
733 ////////////////////////////////////////////////////////////////////////////////
734 /// The return type is defined in TDictionary (kVector, kList, etc.)
735 
737 {
738  if (fSTLCont != -1) return fSTLCont;
741  return fSTLCont;
742 }
743 
744 ////////////////////////////////////////////////////////////////////////////////
745 /// Return true if this data member object is pointing to a currently
746 /// loaded data member. If a function is unloaded after the TDataMember
747 /// is created, the TDataMember will be set to be invalid.
748 
750 {
751  if (fOffset >= 0) return kTRUE;
752 
753  // Register the transaction when checking the validity of the object.
755  DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
756  if (newId) {
757  DataMemberInfo_t *info
758  = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
759  Update(info);
760  // We need to make sure that the list of data member is properly
761  // informed and updated.
763  lst->Update(this);
764  }
765  return newId != 0;
766  }
767  return fInfo != 0;
768 }
769 
770 ////////////////////////////////////////////////////////////////////////////////
771 /// Get property description word. For meaning of bits see EProperty.
772 
774 {
775  if (fProperty!=(-1)) return fProperty;
776 
778  TDataMember *t = (TDataMember*)this;
779 
780  if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
781  int prop = gCling->DataMemberInfo_Property(fInfo);
783  t->fProperty = prop|propt;
784 
788 
791 
792  return fProperty;
793 }
794 
795 ////////////////////////////////////////////////////////////////////////////////
796 /// Returns list of options - list of TOptionListItems
797 
799 {
800  return fOptions;
801 }
802 
803 ////////////////////////////////////////////////////////////////////////////////
804 /// Return a TMethodCall method responsible for getting the value
805 /// of data member. The cl argument specifies the class of the object
806 /// which will be used to call this method (in case of multiple
807 /// inheritance TMethodCall needs to know this to calculate the proper
808 /// offset).
809 
811 {
812  if (!fValueGetter || cl) {
813 
815 
816  if (!cl) cl = fClass;
817 
818  if (fValueGetter) {
819  TString methodname = fValueGetter->GetMethodName();
820  delete fValueGetter;
821  fValueGetter = new TMethodCall(cl, methodname.Data(), "");
822 
823  } else {
824  // try to guess Getter function:
825  // we strip the fist character of name of data field ('f') and then
826  // try to find the name of Getter by applying "Get", "Is" or "Has"
827  // as a prefix
828 
829  const char *dataname = GetName();
830 
831  TString gettername;
832  gettername.Form( "Get%s", dataname+1);
833  if (GetClass()->GetMethod(gettername, ""))
834  return fValueGetter = new TMethodCall(cl, gettername, "");
835  gettername.Form( "Is%s", dataname+1);
836  if (GetClass()->GetMethod(gettername, ""))
837  return fValueGetter = new TMethodCall(cl, gettername, "");
838  gettername.Form( "Has%s", dataname+1);
839  if (GetClass()->GetMethod(gettername, ""))
840  return fValueGetter = new TMethodCall(cl, gettername, "");
841  }
842  }
843 
844  return fValueGetter;
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// Return a TMethodCall method responsible for setting the value
849 /// of data member. The cl argument specifies the class of the object
850 /// which will be used to call this method (in case of multiple
851 /// inheritance TMethodCall needs to know this to calculate the proper
852 /// offset).
853 
855 {
856  if (!fValueSetter || cl) {
857 
859 
860  if (!cl) cl = fClass;
861 
862  if (fValueSetter) {
863 
864  TString methodname = fValueSetter->GetMethodName();
865  TString params = fValueSetter->GetParams();
866  delete fValueSetter;
867  fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
868 
869  } else {
870 
871  // try to guess Setter function:
872  // we strip the fist character of name of data field ('f') and then
873  // try to find the name of Setter by applying "Set" as a prefix
874 
875  const char *dataname = GetName();
876 
877  TString settername;
878  settername.Form( "Set%s", dataname+1);
879  if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
880  if (GetClass()->GetMethod(settername, "1"))
881  fValueSetter = new TMethodCall(cl, settername, "1");
882  if (!fValueSetter)
883  if (GetClass()->GetMethod(settername, "true"))
884  fValueSetter = new TMethodCall(cl, settername, "true");
885  }
886  }
887 
888  return fValueSetter;
889 }
890 
891 ////////////////////////////////////////////////////////////////////////////////
892 /// Update the TFunction to reflect the new info.
893 ///
894 /// This can be used to implement unloading (info == 0) and then reloading
895 /// (info being the 'new' decl address).
896 
897 Bool_t TDataMember::Update(DataMemberInfo_t *info)
898 {
900 
904  if (fOptions) {
905  fOptions->Delete();
907  }
908 
909  if (info == 0) {
910  fOffset = -1;
911  fProperty = -1;
912  fSTLCont = -1;
913  fArrayDim = -1;
914  delete [] fArrayMaxIndex;
915  fArrayMaxIndex=0;
916  fArrayIndex.Clear();
917 
918  fInfo = 0;
919  return kTRUE;
920  } else {
921  fInfo = info;
922  Init(false);
923  return kTRUE;
924  }
925 }
926 
927 
928 ////////////////////////////////////////////////////////////////////////////////
929 /// Stream an object of TDataMember. Forces calculation of all cached
930 /// (and persistent) values.
931 
932 void TDataMember::Streamer(TBuffer& b) {
933  if (b.IsReading()) {
934  b.ReadClassBuffer(Class(), this);
935  Init(true /*reading*/);
936  } else {
937  // Writing.
938  if (fProperty & kIsStatic) {
939  // We have a static member and in this case fOffset contains the
940  // actual address in memory of the data, it will be different everytime,
941  // let's not record it.
942  fOffset = -1;
943  } else {
944  GetOffset();
945  }
946  IsSTLContainer();
947  GetArrayDim();
948  GetArrayIndex();
949  Property(); // also calculates fTypeName and friends
950  b.WriteClassBuffer(Class(), this);
951  }
952 }
953 
954 ////////////////////////////////////////////////////////////////////////////////
955 /// Constructor.
956 
958  Long_t tglmask,const char *name, const char *label)
959 {
960  fDataMember = d;
961  fValue = val;
962  fValueMaskBit = valmask;
963  fToggleMaskBit = tglmask;
964  if (name) {
965  fOptName = name;
966  }
967 
968  if (label) {
969  fOptLabel = label;
970  }
971 }
TString fTitle
Definition: TNamed.h:33
void Init(bool afterReading)
Routines called by the constructor and Update to reset the member&#39;s information.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TMethodCall * SetterMethod(TClass *cl)
Return a TMethodCall method responsible for setting the value of data member.
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
The TEnum class implements the enum type.
Definition: TEnum.h:33
TMethodCall * GetterMethod(TClass *cl=0)
Return a TMethodCall method responsible for getting the value of data member.
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
Definition: TInterpreter.h:466
Long_t fValueMaskBit
Definition: TDataMember.h:108
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Long_t GetOffsetCint() const
Get offset from "this" using the information in CINT only.
Bool_t UpdateInterpreterStateMarker()
the Cling ID of the transaction that last updated the object
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
Int_t * fArrayMaxIndex
Definition: TDataMember.h:46
Short_t GetDeclFileLine() const
Definition: TClass.h:396
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
Bool_t IsEnum() const
Return true if data member is an enum.
static byte * ptr1
Definition: gifdecode.c:16
TDictionary & operator=(const TDictionary &other)
Definition: TDictionary.cxx:62
Int_t GetUnitSize() const
Get the sizeof the underlying type of the data member (i.e.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
Definition: TInterpreter.h:455
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual DataMemberInfo_t * DataMemberInfo_FactoryCopy(DataMemberInfo_t *) const
Definition: TInterpreter.h:454
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
TMethodCall * fValueSetter
method that returns a value;
Definition: TDataMember.h:57
#define gROOT
Definition: TROOT.h:414
TList * GetOptions() const
Returns list of options - list of TOptionListItems.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3646
Basic string class.
Definition: TString.h:131
virtual void * GetAddress() const
Return address of global.
Definition: TGlobal.cxx:77
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
#define gInterpreter
Definition: TInterpreter.h:555
TDataMember * fDataMember
Definition: TDataMember.h:106
TString fFullTypeName
Definition: TDataMember.h:50
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
const void * DeclId_t
Definition: TDictionary.h:209
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:575
TMethodCall * fValueGetter
Definition: TDataMember.h:56
Bool_t IsValid()
Return true if this data member object is pointing to a currently loaded data member.
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
Definition: TInterpreter.h:465
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
void Class()
Definition: Class.C:29
TString fOptLabel
Definition: TDataMember.h:111
TString fArrayIndex
Definition: TDataMember.h:47
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1176
DataMemberInfo_t * fInfo
Definition: TDataMember.h:38
TString & Append(const char *cs)
Definition: TString.h:559
TClass * fClass
pointer to CINT data member info
Definition: TDataMember.h:39
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:400
TDataType * GetDataType() const
Definition: TDataMember.h:74
virtual bool Update(DataMemberInfo_t *info)
Update the TFunction to reflect the new info.
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:459
virtual ~TDataMember()
TDataMember dtor deletes adopted CINT DataMemberInfo object.
Method or function calling interface.
Definition: TMethodCall.h:37
virtual const char * TypeName(const char *s)=0
char * R__STRTOK_R(char *str, const char *delim, char **saveptr)
Definition: Rtypes.h:486
std::string GetLong64_Name(const char *original)
Replace &#39;long long&#39; and &#39;unsigned long long&#39; by &#39;Long64_t&#39; and &#39;ULong64_t&#39;.
Definition: TClassEdit.cxx:861
ROOT::ESTLType UnderlyingIsSTLCont(std::string_view type)
Return the type of STL collection, if any, that is the underlying type of the given type...
TDataMember & operator=(const TDataMember &)
assignment operator
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: Cppyy.cxx:747
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
A doubly linked list.
Definition: TList.h:44
const char * GetMethodName() const
Definition: TMethodCall.h:90
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:456
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1961
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:462
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:451
TList * fOptions
method which sets value;
Definition: TDataMember.h:58
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:162
void Update(TDictionary *member)
Move the member or data member to the expect set of list.
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:460
Long_t fProperty
Definition: TDataMember.h:44
static byte * ptr2
Definition: gifdecode.c:16
TString fOptName
Definition: TDataMember.h:110
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:405
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5499
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:29
Int_t GetArrayDim() const
Return number of array dimensions.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:28
Long_t GetOffset() const
Get offset from "this".
TString fName
Definition: TNamed.h:32
virtual Long_t DataMemberInfo_Offset(DataMemberInfo_t *) const
Definition: TInterpreter.h:458
const char * GetParams() const
Definition: TMethodCall.h:91
const Bool_t kFALSE
Definition: RtypesCore.h:88
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
#define SafeDelete(p)
Definition: RConfig.hxx:550
long Long_t
Definition: RtypesCore.h:50
#define d(i)
Definition: RSha256.hxx:102
Long_t fValue
Data member to which this option belongs.
Definition: TDataMember.h:107
#define ClassImp(name)
Definition: Rtypes.h:365
TList * GetListOfRealData() const
Definition: TClass.h:418
TString fTrueTypeName
Definition: TDataMember.h:51
TDataType * fDataType
pointer to the class
Definition: TDataMember.h:40
#define R__LOCKGUARD(mutex)
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:2906
Int_t fArrayDim
Definition: TDataMember.h:45
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:464
Mother of all ROOT objects.
Definition: TObject.h:37
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
char Char_t
Definition: RtypesCore.h:29
Long_t fOffset
pointer to data basic type descriptor
Definition: TDataMember.h:42
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition: TEnum.cxx:143
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
Definition: TInterpreter.h:463
Int_t Size() const
Get size of basic typedef&#39;ed type.
Definition: TDataType.cxx:366
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Int_t fSTLCont
Definition: TDataMember.h:43
Long_t fToggleMaskBit
Definition: TDataMember.h:109
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:450
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
TDataMember(const TDataMember &)
copy constructor
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:556
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
TClass * GetClass() const
Definition: TDataMember.h:73
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
Bool_t IsaPointer() const
Return true if data member is a pointer.
const Bool_t kTRUE
Definition: RtypesCore.h:87
TString fTypeName
Definition: TDataMember.h:49
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:74
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
DeclId_t GetDeclId() const
const char * Data() const
Definition: TString.h:364