Logo ROOT   6.12/07
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  ptr1 = strtok(opt_ptr ,"{}"); //starts tokenizing:extracts "*OPTION={"
274  if (ptr1 == 0) {
275  Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
276  return;
277  }
278  ptr1 = strtok((char*)0,"{}"); //And now we have what we need in ptr1!!!
279  if (ptr1 == 0) {
280  Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",GetTitle());
281  return;
282  }
283 
284  //and save it:
285  strlcpy(opt,ptr1,2048);
286 
287  // Let's extract sub-tokens extracted by ';' sign.
288  // We'll put'em in an array for convenience;
289  // You have to do it in this manner because you cannot use nested 'strtok'
290 
291  char *tokens[256]; // a storage for these sub-tokens.
292  token_cnt = 0;
293  cnt = 0;
294 
295  do { //tokenizing loop
296  ptr1=strtok((char*) (cnt++ ? 0:opt),";");
297  if (ptr1){
298  Int_t nch = strlen(ptr1)+1;
299  tok=new char[nch];
300  strlcpy(tok,ptr1,nch);
301  tokens[token_cnt]=tok;
302  token_cnt++;
303  }
304  } while (ptr1);
305 
306  // OK! Now let's check whether we have Get/Set methods encode in any string
307  for (i=0;i<token_cnt;i++) {
308 
309  if (strstr(tokens[i],"GetMethod")) {
310  ptr1 = strtok(tokens[i],"\""); //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 = strtok(0,"\""); //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
323  fValueGetter = new TMethodCall(GetClass(),ptr1,"");
324 
325  continue; //next item!
326  }
327 
328  if (strstr(tokens[i],"SetMethod")) {
329  ptr1 = strtok(tokens[i],"\"");
330  if (ptr1 == 0) {
331  Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle());
332  return;
333  }
334  ptr1 = strtok((char*)0,"\""); //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  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 = strtok(tokens[i],"()");
353  if (ptr1 == 0) {
354  Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",GetTitle());
355  return;
356  }
357  ptr1 = strtok((char*)0,"()");
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 
372  do {
373  ptr1 = strtok(opt_cnt++ ? (char*)0:opts,","); //options extraction
374  if (ptr1) {
375  TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
376  optionlist->Add(it);
377  }
378  } while(ptr1);
379 
380  }
381  }
382 
383  //having all options extracted and put into list, we finally can parse
384  //them to create a list of options...
385 
386  fOptions = new TList(); //create the list
387 
388  TIter next(optionlist); //we'll iterate through all
389  //strings containing options
390  TOptionListItem *it = 0;
391  TOptionListItem *it1 = 0;
392  while ((it=(TOptionListItem*)next())) {
393 
394  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.
395  Bool_t islabel = (ptr1[0]=='\"'); // value is label or numerical?
396  ptr2 = strtok((char*)ptr1,"=\""); //extract LeftHandeSide
397  ptr3 = strtok(0,"=\""); //extract RightHandedSize
398 
399  if (islabel) {
400  it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
401  fOptions->Add(it1);
402  } else {
403 
404  char *strtolResult;
405  Long_t l = std::strtol(ptr1, &strtolResult, 10);
406  bool isnumber = (strtolResult != ptr1);
407 
408  if (!isnumber) {
409  TGlobal *enumval = gROOT->GetGlobal(ptr1, kTRUE);
410  if (enumval) {
411  Int_t *value = (Int_t *)(enumval->GetAddress());
412  // We'll try to find global enum existing in ROOT...
413  l = (Long_t)(*value);
414  } else if (IsEnum()) {
415  TObject *obj = fClass->GetListOfDataMembers(false)->FindObject(ptr1);
416  if (obj)
417  l = ((TEnumConstant *)obj)->GetValue();
418  else
419  l = gInterpreter->Calc(Form("%s;", ptr1));
420  } else {
421  Fatal("TDataMember", "Internal error, couldn't recognize enum/global value %s.", ptr1);
422  }
423  }
424 
425  it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
426  fOptions->Add(it1);
427  }
428 
429  optionlist->Remove(it); //delete this option string from list
430  delete it; // and dispose of it.
431 
432  }
433 
434  // Garbage collection
435 
436  // dispose of temporary option list...
437  delete optionlist;
438 
439  //And dispose tokens string...
440  for (i=0;i<token_cnt;i++) if(tokens[i]) delete [] tokens[i];
441 
442  // if option string does not exist but it's an Enum - parse it!!!!
443  } else if (IsEnum()) {
444  fOptions = new TList();
445  if (TEnum* enumDict = TEnum::GetEnum(GetTypeName()) ){
446  TIter iEnumConst(enumDict->GetConstants());
447  while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
448  TOptionListItem *it
449  = new TOptionListItem(this, enumConst->GetValue(),0,0,
450  enumConst->GetName(),enumConst->GetName());
451  fOptions->Add(it);
452  }
453  }
454 
455  // and the case od Bool_t : we add items "ON" and "Off"
456  } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
457 
458  fOptions = new TList();
459  TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",0);
460  fOptions->Add(it);
461  it = new TOptionListItem(this,0,0,0,"Off",0);
462  fOptions->Add(it);
463 
464  } else fOptions = 0;
465 
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// copy constructor
470 
472  TDictionary(dm),
473  fInfo(gCling->DataMemberInfo_FactoryCopy(dm.fInfo)),
474  fClass(dm.fClass),
475  fDataType(dm.fDataType),
476  fOffset(dm.fOffset),
477  fSTLCont(dm.fSTLCont),
478  fProperty(dm.fProperty),
479  fArrayDim(dm.fArrayDim),
480  fArrayMaxIndex( dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0),
482  fTypeName(dm.fTypeName),
485  fValueGetter(0),
486  fValueSetter(0),
487  fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : 0)
488 {
489  for(Int_t d = 0; d < fArrayDim; ++d)
490  fArrayMaxIndex[d] = dm.fArrayMaxIndex[d];
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// assignment operator
495 
497 {
498  if(this!=&dm) {
500  delete fValueSetter;
501  delete fValueGetter;
502  if (fOptions) {
503  fOptions->Delete();
504  delete fOptions;
505  fOptions = 0;
506  }
507 
510  fClass=dm.fClass;
511  fDataType=dm.fDataType;
512  fOffset=dm.fOffset;
513  fSTLCont=dm.fSTLCont;
514  fProperty=dm.fProperty;
515  fArrayDim = dm.fArrayDim;
516  fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0;
517  for(Int_t d = 0; d < fArrayDim; ++d)
518  fArrayMaxIndex[d] = dm.fArrayMaxIndex[d];
520  fTypeName=dm.fTypeName;
523  fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : 0;
524  }
525  return *this;
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// TDataMember dtor deletes adopted CINT DataMemberInfo object.
530 
532 {
533  delete [] fArrayMaxIndex;
535  delete fValueSetter;
536  delete fValueGetter;
537  if (fOptions) {
538  fOptions->Delete();
539  delete fOptions;
540  }
541 }
542 
543 ////////////////////////////////////////////////////////////////////////////////
544 /// Return number of array dimensions.
545 
547 {
548  if (fArrayDim<0 && fInfo) {
550  TDataMember *dm = const_cast<TDataMember*>(this);
552  // fArrayMaxIndex should be zero
553  if (dm->fArrayDim) {
554  dm->fArrayMaxIndex = new Int_t[fArrayDim];
555  for(Int_t dim = 0; dim < fArrayDim; ++dim) {
557  }
558  }
559  }
560  return fArrayDim;
561 }
562 
563 ////////////////////////////////////////////////////////////////////////////////
564 /// If the data member is pointer and has a valid array size in its comments
565 /// GetArrayIndex returns a string pointing to it;
566 /// otherwise it returns an empty string.
567 
568 const char *TDataMember::GetArrayIndex() const
569 {
570  if (!IsaPointer()) return "";
571  if (fArrayIndex.Length()==0 && fInfo) {
573  TDataMember *dm = const_cast<TDataMember*>(this);
574  const char* val = gCling->DataMemberInfo_ValidArrayIndex(fInfo);
575  if (val) dm->fArrayIndex = val;
576  else dm->fArrayIndex.Append((Char_t)0); // Make length non-zero but string still empty.
577  }
578  return fArrayIndex;
579 }
580 
581 ////////////////////////////////////////////////////////////////////////////////
582 
584 {
585  if (fInfo) return gInterpreter->GetDeclId(fInfo);
586  else return 0;
587 }
588 
589 ////////////////////////////////////////////////////////////////////////////////
590 /// Return maximum index for array dimension "dim".
591 
593 {
594  if (fArrayDim<0 && fInfo) {
595  return gCling->DataMemberInfo_MaxIndex(fInfo,dim);
596  } else {
597  if (dim < 0 || dim >= fArrayDim) return -1;
598  return fArrayMaxIndex[dim];
599  }
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
604 
605 const char *TDataMember::GetTypeName() const
606 {
607  if (fProperty==(-1)) Property();
608  return fTypeName.Data();
609 }
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// Get full type description of data member, e,g.: "class TDirectory*".
613 
614 const char *TDataMember::GetFullTypeName() const
615 {
616  if (fProperty==(-1)) Property();
617 
618  return fFullTypeName.Data();
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Get full type description of data member, e,g.: "class TDirectory*".
623 
624 const char *TDataMember::GetTrueTypeName() const
625 {
626  return fTrueTypeName.Data();
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 /// Get offset from "this".
631 
633 {
634  if (fOffset>=0) return fOffset;
635 
637  //case of an interpreted or emulated class
638  if (fClass->GetDeclFileLine() < 0) {
639  ((TDataMember*)this)->fOffset = gCling->DataMemberInfo_Offset(fInfo);
640  return fOffset;
641  }
642  //case of a compiled class
643  //Note that the offset cannot be computed in case of an abstract class
644  //for which the list of real data has not yet been computed via
645  //a real daughter class.
646  TString dmbracket;
647  dmbracket.Form("%s[",GetName());
649  TIter next(fClass->GetListOfRealData());
650  TRealData *rdm;
651  Int_t offset = 0;
652  while ((rdm = (TRealData*)next())) {
653  char *rdmc = (char*)rdm->GetName();
654  //next statement required in case a class and one of its parent class
655  //have data members with the same name
656  if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
657 
658  if (rdm->GetDataMember() != this) continue;
659  if (strcmp(rdmc,GetName()) == 0) {
660  offset = rdm->GetThisOffset();
661  break;
662  }
663  if (strcmp(rdm->GetName(),GetName()) == 0) {
664  if (rdm->IsObject()) {
665  offset = rdm->GetThisOffset();
666  break;
667  }
668  }
669  if (strstr(rdm->GetName(),dmbracket.Data())) {
670  offset = rdm->GetThisOffset();
671  break;
672  }
673  }
674  ((TDataMember*)this)->fOffset = offset;
675  return fOffset;
676 }
677 
678 ////////////////////////////////////////////////////////////////////////////////
679 /// Get offset from "this" using the information in CINT only.
680 
682 {
683  if (fOffset>=0) return fOffset;
684 
686  TDataMember *dm = const_cast<TDataMember*>(this);
687 
688  if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo);
689  else return -1;
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 /// Get the sizeof the underlying type of the data member
694 /// (i.e. if the member is an array sizeof(member)/length)
695 
697 {
698  if (IsaPointer()) return sizeof(void*);
699  if (IsEnum() ) return sizeof(Int_t);
700  if (IsBasic() ) return GetDataType()->Size();
701 
703  if (!cl) cl = TClass::GetClass(GetTrueTypeName());
704  if ( cl) return cl->Size();
705 
706  Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
707  return 0;
708 }
709 
710 ////////////////////////////////////////////////////////////////////////////////
711 /// Return true if data member is a basic type, e.g. char, int, long...
712 
714 {
715  if (fProperty == -1) Property();
716  return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
717 }
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// Return true if data member is an enum.
721 
723 {
724  if (fProperty == -1) Property();
725  return (fProperty & kIsEnum) ? kTRUE : kFALSE;
726 }
727 
728 ////////////////////////////////////////////////////////////////////////////////
729 /// Return true if data member is a pointer.
730 
732 {
733  if (fProperty == -1) Property();
734  return (fProperty & kIsPointer) ? kTRUE : kFALSE;
735 }
736 
737 ////////////////////////////////////////////////////////////////////////////////
738 /// The return type is defined in TDictionary (kVector, kList, etc.)
739 
741 {
742  if (fSTLCont != -1) return fSTLCont;
745  return fSTLCont;
746 }
747 
748 ////////////////////////////////////////////////////////////////////////////////
749 /// Return true if this data member object is pointing to a currently
750 /// loaded data member. If a function is unloaded after the TDataMember
751 /// is created, the TDataMember will be set to be invalid.
752 
754 {
755  if (fOffset >= 0) return kTRUE;
756 
757  // Register the transaction when checking the validity of the object.
759  DeclId_t newId = gInterpreter->GetDataMember(fClass->GetClassInfo(), fName);
760  if (newId) {
761  DataMemberInfo_t *info
762  = gInterpreter->DataMemberInfo_Factory(newId, fClass->GetClassInfo());
763  Update(info);
764  // We need to make sure that the list of data member is properly
765  // informed and updated.
767  lst->Update(this);
768  }
769  return newId != 0;
770  }
771  return fInfo != 0;
772 }
773 
774 ////////////////////////////////////////////////////////////////////////////////
775 /// Get property description word. For meaning of bits see EProperty.
776 
778 {
779  if (fProperty!=(-1)) return fProperty;
780 
782  TDataMember *t = (TDataMember*)this;
783 
784  if (!fInfo || !gCling->DataMemberInfo_IsValid(fInfo)) return 0;
785  int prop = gCling->DataMemberInfo_Property(fInfo);
787  t->fProperty = prop|propt;
788 
792 
795 
796  return fProperty;
797 }
798 
799 ////////////////////////////////////////////////////////////////////////////////
800 /// Returns list of options - list of TOptionListItems
801 
803 {
804  return fOptions;
805 }
806 
807 ////////////////////////////////////////////////////////////////////////////////
808 /// Return a TMethodCall method responsible for getting the value
809 /// of data member. The cl argument specifies the class of the object
810 /// which will be used to call this method (in case of multiple
811 /// inheritance TMethodCall needs to know this to calculate the proper
812 /// offset).
813 
815 {
816  if (!fValueGetter || cl) {
817 
819 
820  if (!cl) cl = fClass;
821 
822  if (fValueGetter) {
823  TString methodname = fValueGetter->GetMethodName();
824  delete fValueGetter;
825  fValueGetter = new TMethodCall(cl, methodname.Data(), "");
826 
827  } else {
828  // try to guess Getter function:
829  // we strip the fist character of name of data field ('f') and then
830  // try to find the name of Getter by applying "Get", "Is" or "Has"
831  // as a prefix
832 
833  const char *dataname = GetName();
834 
835  TString gettername;
836  gettername.Form( "Get%s", dataname+1);
837  if (GetClass()->GetMethod(gettername, ""))
838  return fValueGetter = new TMethodCall(cl, gettername, "");
839  gettername.Form( "Is%s", dataname+1);
840  if (GetClass()->GetMethod(gettername, ""))
841  return fValueGetter = new TMethodCall(cl, gettername, "");
842  gettername.Form( "Has%s", dataname+1);
843  if (GetClass()->GetMethod(gettername, ""))
844  return fValueGetter = new TMethodCall(cl, gettername, "");
845  }
846  }
847 
848  return fValueGetter;
849 }
850 
851 ////////////////////////////////////////////////////////////////////////////////
852 /// Return a TMethodCall method responsible for setting the value
853 /// of data member. The cl argument specifies the class of the object
854 /// which will be used to call this method (in case of multiple
855 /// inheritance TMethodCall needs to know this to calculate the proper
856 /// offset).
857 
859 {
860  if (!fValueSetter || cl) {
861 
863 
864  if (!cl) cl = fClass;
865 
866  if (fValueSetter) {
867 
868  TString methodname = fValueSetter->GetMethodName();
869  TString params = fValueSetter->GetParams();
870  delete fValueSetter;
871  fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
872 
873  } else {
874 
875  // try to guess Setter function:
876  // we strip the fist character of name of data field ('f') and then
877  // try to find the name of Setter by applying "Set" as a prefix
878 
879  const char *dataname = GetName();
880 
881  TString settername;
882  settername.Form( "Set%s", dataname+1);
883  if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
884  if (GetClass()->GetMethod(settername, "1"))
885  fValueSetter = new TMethodCall(cl, settername, "1");
886  if (!fValueSetter)
887  if (GetClass()->GetMethod(settername, "true"))
888  fValueSetter = new TMethodCall(cl, settername, "true");
889  }
890  }
891 
892  return fValueSetter;
893 }
894 
895 ////////////////////////////////////////////////////////////////////////////////
896 /// Update the TFunction to reflect the new info.
897 ///
898 /// This can be used to implement unloading (info == 0) and then reloading
899 /// (info being the 'new' decl address).
900 
901 Bool_t TDataMember::Update(DataMemberInfo_t *info)
902 {
904 
908  if (fOptions) {
909  fOptions->Delete();
911  }
912 
913  if (info == 0) {
914  fOffset = -1;
915  fProperty = -1;
916  fSTLCont = -1;
917  fArrayDim = -1;
918  delete [] fArrayMaxIndex;
919  fArrayMaxIndex=0;
920  fArrayIndex.Clear();
921 
922  fInfo = 0;
923  return kTRUE;
924  } else {
925  fInfo = info;
926  Init(false);
927  return kTRUE;
928  }
929 }
930 
931 
932 ////////////////////////////////////////////////////////////////////////////////
933 /// Stream an object of TDataMember. Forces calculation of all cached
934 /// (and persistent) values.
935 
936 void TDataMember::Streamer(TBuffer& b) {
937  if (b.IsReading()) {
938  b.ReadClassBuffer(Class(), this);
939  Init(true /*reading*/);
940  } else {
941  // Writing.
942  if (fProperty & kIsStatic) {
943  // We have a static member and in this case fOffset contains the
944  // actual address in memory of the data, it will be different everytime,
945  // let's not record it.
946  fOffset = -1;
947  } else {
948  GetOffset();
949  }
950  IsSTLContainer();
951  GetArrayDim();
952  GetArrayIndex();
953  Property(); // also calculates fTypeName and friends
954  b.WriteClassBuffer(Class(), this);
955  }
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////////
959 /// Constructor.
960 
962  Long_t tglmask,const char *name, const char *label)
963 {
964  fDataMember = d;
965  fValue = val;
966  fValueMaskBit = valmask;
967  fToggleMaskBit = tglmask;
968  if (name) {
969  fOptName = name;
970  }
971 
972  if (label) {
973  fOptLabel = label;
974  }
975 }
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.
Bool_t IsReading() const
Definition: TBuffer.h:83
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:31
TMethodCall * GetterMethod(TClass *cl=0)
Return a TMethodCall method responsible for getting the value of data member.
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
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:438
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:427
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:426
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
TMethodCall * fValueSetter
method that returns a value;
Definition: TDataMember.h:57
#define gROOT
Definition: TROOT.h:402
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:3617
Basic string class.
Definition: TString.h:125
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:526
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:205
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
Delete a TObjLink object.
Definition: TList.cxx:574
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:437
#define SafeDelete(p)
Definition: RConfig.h:509
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 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:1150
DataMemberInfo_t * fInfo
Definition: TDataMember.h:38
TString & Append(const char *cs)
Definition: TString.h:495
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:431
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
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:817
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:727
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:428
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1942
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:434
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:423
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:158
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:432
PyObject * fValue
Long_t fProperty
Definition: TDataMember.h:44
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
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:2343
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:386
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5434
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.
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:27
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:430
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*".
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
#define ClassImp(name)
Definition: Rtypes.h:359
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:2887
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
Int_t fArrayDim
Definition: TDataMember.h:45
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:436
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:108
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:435
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
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:422
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:528
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:345