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