Logo ROOT   6.16/01
Reference Guide
TDataMember.cxx
Go to the documentation of this file.
1// @(#)root/meta:$Id$
2// Author: Fons Rademakers 04/02/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TDataMember
13
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 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); //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 // dispose of temporary option list...
436 delete optionlist;
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()) {
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;
511 fOffset=dm.fOffset;
514 fArrayDim = dm.fArrayDim;
515 fArrayMaxIndex = dm.fArrayDim ? new Int_t[dm.fArrayDim] : 0;
516 for(Int_t d = 0; d < fArrayDim; ++d)
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 < 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
567const 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) {
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
604const 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
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
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());
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;
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
900Bool_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;
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
935void 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 }
950 GetArrayDim();
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}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:529
#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:363
char * R__STRTOK_R(char *str, const char *delim, char **saveptr)
Definition: Rtypes.h:484
@ kIsPointer
Definition: TDictionary.h:77
@ kIsEnum
Definition: TDictionary.h:68
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsStatic
Definition: TDictionary.h:79
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
#define gInterpreter
Definition: TInterpreter.h:538
#define gROOT
Definition: TROOT.h:410
char * Form(const char *fmt,...)
#define R__LOCKGUARD(mutex)
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3615
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:5466
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:2885
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:159
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:206
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:438
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:448
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:446
virtual const char * DataMemberInfo_ValidArrayIndex(DataMemberInfo_t *) const
Definition: TInterpreter.h:450
virtual Long_t DataMemberInfo_Offset(DataMemberInfo_t *) const
Definition: TInterpreter.h:442
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t *) const
Definition: TInterpreter.h:439
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:444
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:443
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:434
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:435
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:440
virtual const char * DataMemberInfo_Title(DataMemberInfo_t *) const
Definition: TInterpreter.h:449
virtual const char * DataMemberInfo_TypeTrueName(DataMemberInfo_t *) const
Definition: TInterpreter.h:447
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 * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
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:1151
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:2264
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: Cppyy.cxx:744
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
Definition: TClassEdit.cxx:827
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