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