TDataMember.cxx

Go to the documentation of this file.
00001 // @(#)root/meta:$Id: TDataMember.cxx 36925 2010-11-25 06:22:59Z pcanal $
00002 // Author: Fons Rademakers   04/02/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //
00014 //  TDataMember.
00015 //
00016 // All ROOT classes may have RTTI (run time type identification) support
00017 // added. The data is stored in so called DICTIONARY (look at TDictionary).
00018 // Information about a class is stored in TClass.
00019 // This information may be obtained via the CINT api - see class TCint.
00020 // TClass has a list of TDataMember objects providing information about all
00021 // data members of described class.
00022 //Begin_Html
00023 /*
00024 <img align=center src="gif/classinfo.gif">
00025 */
00026 //End_Html
00027 // TDataMember provides information about name of data member, its type,
00028 // and comment field string. It also tries to find the TMethodCall objects
00029 // responsible for getting/setting a value of it, and gives you pointers
00030 // to these methods. This gives you a unique possibility to access
00031 // protected and private (!) data members if only methods for doing that
00032 // are defined.
00033 // These methods could either be specified in a comment field, or found
00034 // out automatically by ROOT: here's an example:
00035 // suppose you have a class definition:
00036 //Begin_Html <pre>
00037 /*
00038 
00039         class MyClass{
00040             private:
00041                 Float_t fX1;
00042                     ...
00043             public:
00044                 void    SetX1(Float_t x) {fX1 = x;};
00045                 Float_t GetX1()          {return fX1;};
00046                     ...
00047         }
00048 
00049 */
00050 //</pre>
00051 //End_Html
00052 // Look at the data member name and method names: a data member name has
00053 // a prefix letter (f) and has a base name X1 . The methods for getting and
00054 // setting this value have names which consist of string Get/Set and the
00055 // same base name. This convention of naming data fields and methods which
00056 // access them allows TDataMember find this methods by itself completely
00057 // automatically. To make this description complete, one should know,
00058 // that names that are automatically recognized may be also:
00059 // for data fields: either fXXX or fIsXXX; and for getter function
00060 // GetXXX() or IsXXX() [where XXX is base name].
00061 //
00062 // As an example of using it let's analyse a few lines which get and set
00063 // a fEditable field in TCanvas:
00064 //Begin_Html <pre>
00065 /*
00066 
00067     TCanvas     *c  = new TCanvas("c");   // create a canvas
00068     TClass      *cl = c-&gt;IsA();            // get its class description object.
00069 
00070     TDataMember *dm = cl-&gt;GetDataMember("fEditable"); //This is our data member
00071 
00072     TMethodCall *getter = dm-&gt;GetterMethod(c); //find a method that gets value!
00073     Long_t l;   // declare a storage for this value;
00074 
00075     getter-&gt;Execute(c,"",l);  // Get this Value !!!! It will appear in l !!!
00076 
00077 
00078     TMethodCall *setter = dm-&gt;SetterMethod(c);
00079     setter-&gt;Execute(c,"0",);   // Set Value 0 !!!
00080 
00081 */
00082 //</pre>
00083 //End_Html
00084 //
00085 // This trick is widely used in ROOT TContextMenu and dialogs for obtaining
00086 // current values and put them as initial values in dialog fields.
00087 //
00088 // If you don't want to follow the convention of naming used by ROOT
00089 // you still could benefit from Getter/Setter method support: the solution
00090 // is to instruct ROOT what the names of these routines are.
00091 // The way to do it is putting this information in a comment string to a data
00092 // field in your class declaration:
00093 //
00094 //Begin_Html <pre>
00095 /*
00096 
00097     class MyClass{
00098         Int_t mydata;  // <em> *OPTIONS={GetMethod="Get";SetMethod="Set"} </em>
00099          ...
00100         Int_t Get() const { return mydata;};
00101         void  Set(Int_t i) {mydata=i;};
00102         }
00103 */
00104 //</pre>
00105 //End_Html
00106 //
00107 // However, this getting/setting functions are not the only feature of
00108 // this class. The next point is providing lists of possible settings
00109 // for the concerned data member. The idea is to have a list of possible
00110 // options for this data member, with strings identifying them. This
00111 // is used in dialogs with parameters to set - for details see
00112 // TMethodArg, TRootContextMenu, TContextMenu. This list not only specifies
00113 // the allowed value, but also provides strings naming the options.
00114 // Options are managed via TList of TOptionListItem objects. This list
00115 // is also  created automatically: if a data type is an enum tynpe,
00116 // the list will have items describing every enum value, and named
00117 // according to enum name. If type is Bool_t, two options "On" and "Off"
00118 // with values 0 and 1 are created. For other types you need to instruct
00119 // ROOT about possible options. The way to do it is the same as in case of
00120 // specifying getter/setter method: a comment string to a data field in
00121 // Your header file with class definition.
00122 // The most general format of this string is:
00123 //Begin_Html <pre>
00124 /*
00125 
00126 <em>*OPTIONS={GetMethod="</em>getter<em>";SetMethod="</em>setter<em>";Items=(</em>it1<em>="</em>title1<em>",</em>it2<em>="</em>title2<em>", ... ) } </em>
00127 
00128 */
00129 //</pre>
00130 //End_Html
00131 //
00132 // While parsing this string ROOT firstly looks for command-tokens:
00133 // GetMethod, SetMethod, Items; They must be preceded by string
00134 // *OPTIONS= , enclosed by {} and separated by semicolons ";".
00135 // All command token should have a form TOKEN=VALUE.
00136 // All tokens are optional.
00137 // The names of getter and setter method must be enclosed by double-quote
00138 // marks (") .
00139 // Specifications of Items is slightly more complicated: you need to
00140 // put token ITEMS= and then enclose all options in curly brackets "()".
00141 // You separate options by comas ",".
00142 // Each option item may have one of the following forms:
00143 //Begin_Html <pre>
00144 /*
00145          IntegerValue<em>  = "</em>Text Label<em>"</em>
00146 
00147          EnumValue   <em>  = "</em>Text Label<em>"</em>
00148 
00149         <em>"</em>TextValue<em>" = </em>Text Label<em>"</em>
00150 
00151 */
00152 //</pre>
00153 //End_Html
00154 //
00155 // One can sepcify values as Integers or Enums - when data field is an
00156 // Integer, Float or Enum type; as texts - for char (more precisely:
00157 // Option_t).
00158 //
00159 // As mentioned above - this information are mainly used by contextmenu,
00160 // but also in Dump() and Inspect() methods and by the THtml class.
00161 //
00162 //////////////////////////////////////////////////////////////////////////
00163 
00164 #include "TDataMember.h"
00165 #include "TDataType.h"
00166 #include "TROOT.h"
00167 #include "TGlobal.h"
00168 #include "TInterpreter.h"
00169 #include "Strlen.h"
00170 #include "TMethodCall.h"
00171 #include "TClass.h"
00172 #include "TClassEdit.h"
00173 #include "TMethod.h"
00174 #include "TIterator.h"
00175 #include "TList.h"
00176 #include "TGlobal.h"
00177 #include "TRealData.h"
00178  
00179 #include <stdlib.h>
00180 
00181 
00182 ClassImp(TDataMember)
00183 
00184 //______________________________________________________________________________
00185 TDataMember::TDataMember(DataMemberInfo_t *info, TClass *cl) : TDictionary()
00186 {
00187    // Default TDataMember ctor. TDataMembers are constructed in TClass
00188    // via a call to TCint::CreateListOfDataMembers(). It parses the comment
00189    // string, initializes optionlist and getter/setter methods.
00190 
00191    fInfo        = info;
00192    fClass       = cl;
00193    fDataType    = 0;
00194    fOptions     = 0;
00195    fValueSetter = 0;
00196    fValueGetter = 0;
00197    fOffset      = -1;
00198    fProperty    = -1;
00199    fSTLCont     = -1;
00200    if (!fInfo && !fClass) return; // default ctor is called
00201 
00202    if (fInfo) {
00203       fFullTypeName = TClassEdit::GetLong64_Name(gCint->DataMemberInfo_TypeName(fInfo));
00204       fTrueTypeName = TClassEdit::GetLong64_Name(gCint->DataMemberInfo_TypeTrueName(fInfo));
00205       fTypeName     = TClassEdit::GetLong64_Name(gCint->TypeName(fFullTypeName));
00206       SetName(gCint->DataMemberInfo_Name(fInfo));
00207       const char *t = gCint->DataMemberInfo_Title(fInfo);
00208       SetTitle(t);
00209       if (t && t[0] != '!') SetBit(kObjIsPersistent);
00210       fDataType = 0;
00211       if (IsBasic() || IsEnum()) {
00212          if (IsBasic()) {
00213             const char *name = GetFullTypeName();
00214             if (strcmp(name, "unsigned char") != 0 &&
00215                 strncmp(name, "unsigned short", sizeof ("unsigned short")) != 0 &&
00216                 strcmp(name, "unsigned int") != 0 &&
00217                 strncmp(name, "unsigned long", sizeof ("unsigned long")) != 0)
00218                 // strncmp() also covers "unsigned long long"
00219                name = GetTypeName();
00220             fDataType = gROOT->GetType(name);
00221 
00222             if (fDataType==0) {
00223                // humm we did not find it ... maybe it's a typedef that has not been loaded yet.
00224                // (this can happen if the executable does not have a TApplication object).
00225                fDataType = gROOT->GetType(name,kTRUE);
00226             }
00227          } else {
00228             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.
00229          }
00230 //         if (!fDataType)
00231 //            Error("TDataMember", "basic data type %s not found in list of basic types",
00232 //                  GetTypeName());
00233       }
00234    }
00235 
00236    // If option string exist in comment - we'll parse it and create
00237    // list of options
00238 
00239    // Option-list string has a form:
00240    // *OPTION={GetMethod="GetXXX";SetMethod="SetXXX";
00241    //          Items=(0="NULL ITEM","one"="First Item",kRed="Red Item")}
00242    //
00243    // As one can see it is possible to specify value as either numerical
00244    // value , string  or enum.
00245    // One can also specify implicitly names of Getter/Setter methods.
00246 
00247    char cmt[2048];
00248    char opt[2048];
00249    char *opt_ptr = 0;
00250    char *ptr1    = 0;
00251    char *ptr2    = 0;
00252    char *ptr3    = 0;
00253    char *tok     = 0;
00254    Int_t cnt     = 0;
00255    Int_t token_cnt;
00256    Int_t i;
00257 
00258    strlcpy(cmt,gCint->DataMemberInfo_Title(fInfo),2048);
00259 
00260    if ((opt_ptr=strstr(cmt,"*OPTION={"))) {
00261 
00262       // If we found it - parsing...
00263 
00264       //let's cut the part lying between {}
00265       ptr1 = strtok(opt_ptr  ,"{}");  //starts tokenizing:extracts "*OPTION={"
00266       if (ptr1 == 0) {
00267          Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00268          return;
00269       }
00270       ptr1 = strtok((char*)0,"{}");   //And now we have what we need in ptr1!!!
00271       if (ptr1 == 0) {
00272          Fatal("TDataMember","Internal error, found \"*OPTION={\" but not \"{}\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00273          return;
00274       }
00275       
00276       //and save it:
00277       strlcpy(opt,ptr1,2048);
00278 
00279       // Let's extract sub-tokens extracted by ';' sign.
00280       // We'll put'em in an array for convenience;
00281       // You have to do it in this manner because you cannot use nested 'strtok'
00282 
00283       char *tokens[256];           // a storage for these sub-tokens.
00284       token_cnt = 0;
00285       cnt       = 0;
00286 
00287       do {                          //tokenizing loop
00288          ptr1=strtok((char*) (cnt++ ? 0:opt),";");
00289          if (ptr1){
00290             Int_t nch = strlen(ptr1)+1;
00291             tok=new char[nch];
00292             strlcpy(tok,ptr1,nch);
00293             tokens[token_cnt]=tok;
00294             token_cnt++;
00295          }
00296       } while (ptr1);
00297 
00298       // OK! Now let's check whether we have Get/Set methods encode in any string
00299       for (i=0;i<token_cnt;i++) {
00300 
00301          if (strstr(tokens[i],"GetMethod")) {
00302             ptr1 = strtok(tokens[i],"\"");    //tokenizing-strip text "GetMethod"
00303             if (ptr1 == 0) {
00304                Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00305                return;
00306             }
00307             ptr1 = strtok(0,"\"");         //tokenizing - name is in ptr1!
00308             if (ptr1 == 0) {
00309                Fatal("TDataMember","Internal error, found \"GetMethod\" but not \"\\\"\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00310                return;
00311             }
00312             
00313             if (GetClass()->GetMethod(ptr1,"")) // check whether such method exists
00314                // FIXME: wrong in case called derives via multiple inheritance from this class
00315                fValueGetter = new TMethodCall(GetClass(),ptr1,"");
00316 
00317             continue; //next item!
00318          }
00319 
00320          if (strstr(tokens[i],"SetMethod")) {
00321             ptr1 = strtok(tokens[i],"\"");
00322             if (ptr1 == 0) {
00323                Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00324                return;
00325             }
00326             ptr1 = strtok((char*)0,"\"");    //name of Setter in ptr1
00327             if (ptr1 == 0) {
00328                Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00329                return;
00330             }
00331             if (GetClass()->GetMethod(ptr1,"1"))
00332                // FIXME: wrong in case called derives via multiple inheritance from this class
00333                fValueSetter = new TMethodCall(GetClass(),ptr1,"1");
00334          }
00335       }
00336 
00337       //Now let's parse option strings...
00338 
00339       Int_t  opt_cnt    = 0;
00340       TList *optionlist = new TList();       //storage for options strings
00341 
00342       for (i=0;i<token_cnt;i++) {
00343          if (strstr(tokens[i],"Items")) {
00344             ptr1 = strtok(tokens[i],"()");
00345             if (ptr1 == 0) {
00346                Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00347                return;
00348             }
00349             ptr1 = strtok((char*)0,"()");
00350             if (ptr1 == 0) {
00351                Fatal("TDataMember","Internal error, found \"Items\" but not \"()\" in %s.",gCint->DataMemberInfo_Title(fInfo));
00352                return;
00353             }
00354             
00355             char opts[2048];  //and save it!
00356             strlcpy(opts,ptr1,2048);
00357 
00358             //now parse it...
00359             //fistly we just store strings like: xxx="Label Name"
00360             //We'll store it in TOptionListItem objects, because they're derived
00361             //from TObject and thus can be stored in TList.
00362             //It's not elegant but works.
00363 
00364             do {
00365                ptr1 = strtok(opt_cnt++ ? (char*)0:opts,","); //options extraction
00366                if (ptr1) {
00367                   TOptionListItem *it = new TOptionListItem(this,1,0,0,ptr1,"");
00368                   optionlist->Add(it);
00369                }
00370             } while(ptr1);
00371 
00372          }
00373       }
00374 
00375       //having all options extracted and put into list, we finally can parse
00376       //them to create a list of options...
00377 
00378       fOptions = new TList();                //create the list
00379 
00380       TIter next(optionlist);                //we'll iterate through all
00381                                              //strings containing options
00382       TOptionListItem *it  = 0;
00383       TOptionListItem *it1 = 0;
00384       while ((it=(TOptionListItem*)next())) {
00385 
00386          ptr1 = it->fOptName;
00387          Bool_t islabel = (ptr1[0]=='\"');   // value is label or numerical?
00388          ptr2 = strtok(ptr1,"=\"");          //extract LeftHandeSide
00389          ptr3 = strtok(0,"=\"");             //extract RightHandedSize
00390 
00391          if (islabel) {
00392             it1=new TOptionListItem(this,-9999,0,0,ptr3,ptr2);
00393             fOptions->Add(it1);
00394          }  else {
00395             //We'll try to find global enum existing in ROOT...
00396             Long_t l=0;
00397             Int_t  *value;
00398             TGlobal *enumval = gROOT->GetGlobal(ptr1,kTRUE);
00399             if (enumval){
00400                value = (Int_t*)(enumval->GetAddress());
00401                l     = (Long_t)(*value);
00402             } else if (IsEnum()) {
00403                TObject *obj = fClass->GetListOfDataMembers()->FindObject(ptr1);
00404                if (obj)
00405                   l = gROOT->ProcessLineFast(Form("%s::%s;",fClass->GetName(),ptr1));
00406                else
00407                   l = gROOT->ProcessLineFast(Form("%s;",ptr1));
00408             } else
00409                l = atol(ptr1);
00410             
00411             it1 = new TOptionListItem(this,l,0,0,ptr3,ptr1);
00412             fOptions->Add(it1);
00413          }
00414 
00415          optionlist->Remove(it);         //delete this option string from list
00416          delete it;                      // and dispose of it.
00417 
00418       }
00419 
00420       // Garbage colletion
00421 
00422       // dispose of temporary option list...
00423       delete optionlist;
00424 
00425       //And dispose tokens string...
00426       for (i=0;i<token_cnt;i++) if(tokens[i]) delete [] tokens[i];
00427 
00428    // if option string does not exist but it's an Enum - parse it!!!!
00429    //} else if (!strncmp(GetFullTypeName(),"enum",4)) {
00430    } else if (IsEnum()) {
00431 
00432       TGlobal *global = 0;
00433       TDataMember::fOptions = new TList();
00434       char etypename[65];
00435       strlcpy(etypename,this->GetTypeName(),65); //save the typename!!! must do it!
00436       const char *gtypename = 0;
00437       TList *globals = (TList*)(gROOT->GetListOfGlobals(kTRUE)); //get all globals
00438       if (!globals) return;
00439 
00440       TIter nextglobal(globals);                //iterate through all global to find
00441       while ((global=(TGlobal*)nextglobal())) { // values belonging to this enum type
00442          gtypename = global->GetTypeName();
00443          if (strcmp(gtypename,etypename)==0) {
00444             Int_t *value = (Int_t*)(global->GetAddress());
00445             Long_t l     = (Long_t)(*value);
00446             TOptionListItem *it = new TOptionListItem(this,l,0,0,global->GetName(),global->GetName());
00447             fOptions->Add(it);
00448          }
00449       }
00450 
00451    // and the case od Bool_t : we add items "ON" and "Off"
00452    } else if (!strncmp(GetFullTypeName(),"Bool_t",6)){
00453 
00454       fOptions = new TList();
00455       TOptionListItem *it = new TOptionListItem(this,1,0,0,"ON",0);
00456       fOptions->Add(it);
00457       it = new TOptionListItem(this,0,0,0,"Off",0);
00458       fOptions->Add(it);
00459 
00460    } else fOptions = 0;
00461 
00462 }
00463 
00464 //______________________________________________________________________________
00465 TDataMember::TDataMember(const TDataMember& dm) :
00466   TDictionary(dm),
00467   fInfo(gCint->DataMemberInfo_FactoryCopy(dm.fInfo)),
00468   fClass(dm.fClass),
00469   fDataType(dm.fDataType),
00470   fOffset(dm.fOffset),
00471   fSTLCont(dm.fSTLCont),
00472   fProperty(dm.fProperty),
00473   fTypeName(dm.fTypeName),
00474   fFullTypeName(dm.fFullTypeName),
00475   fTrueTypeName(dm.fTrueTypeName),
00476   fValueGetter(0),
00477   fValueSetter(0),
00478   fOptions(dm.fOptions ? (TList*)dm.fOptions->Clone() : 0)
00479 { 
00480    //copy constructor
00481 }
00482 
00483 //______________________________________________________________________________
00484 TDataMember& TDataMember::operator=(const TDataMember& dm) 
00485 {
00486    //assignement operator
00487    if(this!=&dm) {
00488       gCint->DataMemberInfo_Delete(fInfo);
00489       delete fValueSetter;
00490       delete fValueGetter;
00491       if (fOptions) {
00492          fOptions->Delete();
00493          delete fOptions;
00494          fOptions = 0;
00495       }
00496 
00497       TDictionary::operator=(dm);
00498       fInfo= gCint->DataMemberInfo_FactoryCopy(dm.fInfo);
00499       fClass=dm.fClass;
00500       fDataType=dm.fDataType;
00501       fOffset=dm.fOffset;
00502       fSTLCont=dm.fSTLCont;
00503       fProperty=dm.fProperty;
00504       fTypeName=dm.fTypeName;
00505       fFullTypeName=dm.fFullTypeName;
00506       fTrueTypeName=dm.fTrueTypeName;
00507       fOptions = dm.fOptions ? (TList*)dm.fOptions->Clone() : 0;
00508    } 
00509    return *this;
00510 }
00511 
00512 //______________________________________________________________________________
00513 TDataMember::~TDataMember()
00514 {
00515    // TDataMember dtor deletes adopted CINT DataMemberInfo object.
00516 
00517    gCint->DataMemberInfo_Delete(fInfo);
00518    delete fValueSetter;
00519    delete fValueGetter;
00520    if (fOptions) {
00521       fOptions->Delete();
00522       delete fOptions;
00523    }
00524 }
00525 
00526 //______________________________________________________________________________
00527 Int_t TDataMember::GetArrayDim() const
00528 {
00529    // Return number of array dimensions.
00530 
00531    return gCint->DataMemberInfo_ArrayDim(fInfo);
00532 }
00533 
00534 //______________________________________________________________________________
00535 const char *TDataMember::GetArrayIndex() const
00536 {
00537    // If the data member is pointer and has a valid array size in its comments
00538    // GetArrayIndex returns a string pointing to it;
00539    // otherwise it returns an empty string.
00540 
00541    const char* val = gCint->DataMemberInfo_ValidArrayIndex(fInfo);
00542    return (val && IsaPointer() ) ? val : "";
00543 }
00544 
00545 //______________________________________________________________________________
00546 Int_t TDataMember::GetMaxIndex(Int_t dim) const
00547 {
00548    // Return maximum index for array dimension "dim".
00549 
00550    return gCint->DataMemberInfo_MaxIndex(fInfo,dim);
00551 }
00552 
00553 //______________________________________________________________________________
00554 const char *TDataMember::GetTypeName() const
00555 {
00556    // Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
00557 
00558    if (fProperty==(-1)) Property();
00559    return fTypeName.Data();
00560 }
00561 
00562 //______________________________________________________________________________
00563 const char *TDataMember::GetFullTypeName() const
00564 {
00565    // Get full type description of data member, e,g.: "class TDirectory*".
00566    if (fProperty==(-1)) Property();
00567 
00568    return fFullTypeName.Data();
00569 }
00570 
00571 //______________________________________________________________________________
00572 const char *TDataMember::GetTrueTypeName() const
00573 {
00574    // Get full type description of data member, e,g.: "class TDirectory*".
00575 
00576    return fTrueTypeName.Data();
00577 }
00578 
00579 //______________________________________________________________________________
00580 Long_t TDataMember::GetOffset() const
00581 {
00582    // Get offset from "this".
00583 
00584    if (fOffset>=0) return fOffset;
00585 
00586    //case of an interpreted or emulated class
00587    if (fClass->GetDeclFileLine() < 0) {
00588       ((TDataMember*)this)->fOffset = gCint->DataMemberInfo_Offset(fInfo);
00589       return fOffset;
00590    }
00591    //case of a compiled class
00592    //Note that the offset cannot be computed in case of an abstract class
00593    //for which the list of real data has not yet been computed via
00594    //a real daughter class.
00595    TString dmbracket;
00596    dmbracket.Form("%s[",GetName());
00597    fClass->BuildRealData();
00598    TIter next(fClass->GetListOfRealData());
00599    TRealData *rdm;
00600    Int_t offset = 0;
00601    while ((rdm = (TRealData*)next())) {
00602       char *rdmc = (char*)rdm->GetName();
00603       //next statement required in case a class and one of its parent class
00604       //have data members with the same name
00605       if (this->IsaPointer() && rdmc[0] == '*') rdmc++;
00606 
00607       if (rdm->GetDataMember() != this) continue;
00608       if (strcmp(rdmc,GetName()) == 0) {
00609          offset = rdm->GetThisOffset();
00610          break;
00611       }
00612       if (strcmp(rdm->GetName(),GetName()) == 0) {
00613          if (rdm->IsObject()) {
00614             offset = rdm->GetThisOffset();
00615             break;
00616          }
00617       }
00618       if (strstr(rdm->GetName(),dmbracket.Data())) {
00619          offset = rdm->GetThisOffset();
00620          break;
00621       }
00622    }
00623    ((TDataMember*)this)->fOffset = offset;
00624    return fOffset;
00625 }
00626 
00627 //______________________________________________________________________________
00628 Long_t TDataMember::GetOffsetCint() const
00629 {
00630    // Get offset from "this" using the information in CINT only.
00631 
00632    return gCint->DataMemberInfo_Offset(fInfo);
00633 }
00634 
00635 //______________________________________________________________________________
00636 Int_t TDataMember::GetUnitSize() const
00637 {
00638    // Get the sizeof the underlying type of the data member
00639    // (i.e. if the member is an array sizeof(member)/length)
00640 
00641    if (IsaPointer()) return sizeof(void*);
00642    if (IsEnum()    ) return sizeof(Int_t);
00643    if (IsBasic()   ) return GetDataType()->Size();
00644 
00645    TClass *cl = TClass::GetClass(GetTypeName());
00646    if (!cl) cl = TClass::GetClass(GetTrueTypeName());
00647    if ( cl) return cl->Size();
00648 
00649    Warning("GetUnitSize","Can not determine sizeof(%s)",GetTypeName());
00650    return 0;
00651 }
00652 
00653 //______________________________________________________________________________
00654 Bool_t TDataMember::IsBasic() const
00655 {
00656    // Return true if data member is a basic type, e.g. char, int, long...
00657 
00658    if (fProperty == -1) Property();
00659    return (fProperty & kIsFundamental) ? kTRUE : kFALSE;
00660 }
00661 
00662 //______________________________________________________________________________
00663 Bool_t TDataMember::IsEnum() const
00664 {
00665    // Return true if data member is an enum.
00666 
00667    if (fProperty == -1) Property();
00668    return (fProperty & kIsEnum) ? kTRUE : kFALSE;
00669 }
00670 
00671 //______________________________________________________________________________
00672 Bool_t TDataMember::IsaPointer() const
00673 {
00674    // Return true if data member is a pointer.
00675 
00676    if (fProperty == -1) Property();
00677    return (fProperty & kIsPointer) ? kTRUE : kFALSE;
00678 }
00679 
00680 //______________________________________________________________________________
00681 int TDataMember::IsSTLContainer()
00682 {
00683    // The return type is defined in TDictionary (kVector, kList, etc.)
00684 
00685    if (fSTLCont != -1) return fSTLCont;
00686    fSTLCont = abs(TClassEdit::IsSTLCont(GetTrueTypeName()));
00687    return fSTLCont;
00688 }
00689 
00690 //______________________________________________________________________________
00691 Long_t TDataMember::Property() const
00692 {
00693    // Get property description word. For meaning of bits see EProperty.
00694 
00695    if (fProperty!=(-1)) return fProperty;
00696 
00697    TDataMember *t = (TDataMember*)this;
00698    if (!fInfo) return 0;
00699    int prop  = gCint->DataMemberInfo_Property(fInfo);
00700    int propt = gCint->DataMemberInfo_TypeProperty(fInfo);
00701    t->fProperty = prop|propt;
00702    const char *tname = gCint->DataMemberInfo_TypeName(fInfo);
00703    t->fTypeName = gCint->TypeName(tname);
00704    t->fFullTypeName = tname;
00705    t->fName  = gCint->DataMemberInfo_Name(fInfo);
00706    t->fTitle = gCint->DataMemberInfo_Title(fInfo);
00707 
00708    return fProperty;
00709 }
00710 
00711 //______________________________________________________________________________
00712 TList *TDataMember::GetOptions() const
00713 {
00714    // Returns list of options - list of TOptionListItems
00715 
00716    return fOptions;
00717 }
00718 
00719 //______________________________________________________________________________
00720 TMethodCall *TDataMember::GetterMethod(TClass *cl)
00721 {
00722    // Return a TMethodCall method responsible for getting the value
00723    // of data member. The cl argument specifies the class of the object
00724    // which will be used to call this method (in case of multiple
00725    // inheritance TMethodCall needs to know this to calculate the proper
00726    // offset).
00727 
00728    if (!fValueGetter || cl) {
00729 
00730       if (!cl) cl = fClass;
00731 
00732       if (fValueGetter) {
00733          TString methodname = fValueGetter->GetMethodName();
00734          delete fValueGetter;
00735          fValueGetter = new TMethodCall(cl, methodname.Data(), "");
00736 
00737       } else {
00738          // try to guess Getter function:
00739          // we strip the fist character of name of data field ('f') and then
00740          // try to find the name of Getter by applying "Get", "Is" or "Has"
00741          // as a prefix
00742 
00743          const char *dataname = GetName();
00744 
00745          TString gettername;
00746          gettername.Form( "Get%s", dataname+1);
00747          if (GetClass()->GetMethod(gettername, ""))
00748             return fValueGetter = new TMethodCall(cl, gettername, "");
00749          gettername.Form( "Is%s", dataname+1);
00750          if (GetClass()->GetMethod(gettername, ""))
00751             return fValueGetter = new TMethodCall(cl, gettername, "");
00752          gettername.Form( "Has%s", dataname+1);
00753          if (GetClass()->GetMethod(gettername, ""))
00754             return fValueGetter = new TMethodCall(cl, gettername, "");
00755       }
00756    }
00757 
00758    return fValueGetter;
00759 }
00760 
00761 //______________________________________________________________________________
00762 TMethodCall *TDataMember::SetterMethod(TClass *cl)
00763 {
00764    // Return a TMethodCall method responsible for setting the value
00765    // of data member. The cl argument specifies the class of the object
00766    // which will be used to call this method (in case of multiple
00767    // inheritance TMethodCall needs to know this to calculate the proper
00768    // offset).
00769 
00770    if (!fValueSetter || cl) {
00771 
00772       if (!cl) cl = fClass;
00773 
00774       if (fValueSetter) {
00775 
00776          TString methodname = fValueSetter->GetMethodName();
00777          TString params = fValueSetter->GetParams();
00778          delete fValueSetter;
00779          fValueSetter = new TMethodCall(cl, methodname.Data(), params.Data());
00780 
00781       } else {
00782 
00783          // try to guess Setter function:
00784          // we strip the fist character of name of data field ('f') and then
00785          // try to find the name of Setter by applying "Set" as a prefix
00786 
00787          const char *dataname = GetName();
00788 
00789          TString settername;
00790          settername.Form( "Set%s", dataname+1);
00791          if (strstr(settername, "Is")) settername.Form( "Set%s", dataname+3);
00792          if (GetClass()->GetMethod(settername, "1"))
00793             fValueSetter = new TMethodCall(cl, settername, "1");
00794          if (!fValueSetter)
00795             if (GetClass()->GetMethod(settername, "true"))
00796                fValueSetter = new TMethodCall(cl, settername, "true");
00797       }
00798    }
00799 
00800    return fValueSetter;
00801 }
00802 
00803 //______________________________________________________________________________
00804 TOptionListItem::TOptionListItem(TDataMember *d, Long_t val, Long_t valmask,
00805                  Long_t tglmask,const char *name, const char *label)
00806 {
00807    // Constuctor.
00808 
00809    fDataMember    = d;
00810    fValue         = val;
00811    fValueMaskBit  = valmask;
00812    fToggleMaskBit = tglmask;
00813    if (name){
00814 
00815       Int_t nch1 = strlen(name)+1;
00816       fOptName = new char[nch1];
00817       strlcpy(fOptName,name,nch1);
00818 
00819    } else fOptName = 0;
00820 
00821    if(label){
00822 
00823       Int_t nch2 = strlen(label)+1;
00824       fOptLabel = new char[nch2];
00825       strlcpy(fOptLabel,label,nch2);
00826 
00827    } else fOptLabel = 0;
00828 }
00829 
00830 //______________________________________________________________________________
00831 TOptionListItem::TOptionListItem(const TOptionListItem& oli) :
00832   TObject(oli),
00833   fDataMember(oli.fDataMember),
00834   fValue(oli.fValue),
00835   fValueMaskBit(oli.fValueMaskBit),
00836   fToggleMaskBit(oli.fToggleMaskBit),
00837   fOptName(oli.fOptName),
00838   fOptLabel(oli.fOptLabel)
00839 { 
00840    //copy constructor
00841 }
00842 
00843 //______________________________________________________________________________
00844 TOptionListItem& TOptionListItem::operator=(const TOptionListItem& oli)
00845 {
00846    //assignment operator
00847    if(this!=&oli) {
00848       TObject::operator=(oli);
00849       fDataMember=oli.fDataMember;
00850       fValue=oli.fValue;
00851       fValueMaskBit=oli.fValueMaskBit;
00852       fToggleMaskBit=oli.fToggleMaskBit;
00853       fOptName=oli.fOptName;
00854       fOptLabel=oli.fOptLabel;
00855    } 
00856    return *this;
00857 }
00858 
00859 //______________________________________________________________________________
00860 TOptionListItem::~TOptionListItem()
00861 {
00862    // Destructor.
00863 
00864    if (fOptName)  delete [] fOptName;
00865    if (fOptLabel) delete [] fOptLabel;
00866 }

Generated on Tue Jul 5 14:11:55 2011 for ROOT_528-00b_version by  doxygen 1.5.1