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