TClass.cxx

Go to the documentation of this file.
00001 // @(#)root/meta:$Id: TClass.cxx 37531 2010-12-10 20:38:06Z pcanal $
00002 // Author: Rene Brun   07/01/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 //  The ROOT global object gROOT contains a list of all defined         //
00015 //  classes. This list is build when a reference to a class dictionary  //
00016 //  is made. When this happens, the static "class"::Dictionary()        //
00017 //  function is called to create a TClass object describing the         //
00018 //  class. The Dictionary() function is defined in the ClassDef         //
00019 //  macro and stored (at program startup or library load time) together //
00020 //  with the class name in the TClassTable singleton object.            //
00021 //  For a description of all dictionary classes see TDictionary.        //
00022 //                                                                      //
00023 //////////////////////////////////////////////////////////////////////////
00024 
00025 //*-*x7.5 macros/layout_class
00026 
00027 #include "TClass.h"
00028 
00029 #include "Riostream.h"
00030 #include "TBaseClass.h"
00031 #include "TBrowser.h"
00032 #include "TBuffer.h"
00033 #include "TClassGenerator.h"
00034 #include "TClassEdit.h"
00035 #include "TClassMenuItem.h"
00036 #include "TClassRef.h"
00037 #include "TClassTable.h"
00038 #include "TDataMember.h"
00039 #include "TDataType.h"
00040 #include "TError.h"
00041 #include "TExMap.h"
00042 #include "THashList.h"
00043 #include "TInterpreter.h"
00044 #include "TMemberInspector.h"
00045 #include "TMethod.h"
00046 #include "TMethodArg.h"
00047 #include "TMethodCall.h"
00048 #include "TObjArray.h"
00049 #include "TROOT.h"
00050 #include "TRealData.h"
00051 #include "TStreamer.h"
00052 #include "TStreamerElement.h"
00053 #include "TVirtualStreamerInfo.h"
00054 #include "TVirtualCollectionProxy.h"
00055 #include "TVirtualIsAProxy.h"
00056 #include "TVirtualRefProxy.h"
00057 #include "TVirtualMutex.h"
00058 #include "TVirtualPad.h"
00059 #include "THashTable.h"
00060 #include "TSchemaRuleSet.h"
00061 #include "TGenericClassInfo.h"
00062 #include "TIsAProxy.h"
00063 #include "TSchemaRule.h"
00064 #include "TSystem.h"
00065 
00066 #include <cstdio>
00067 #include <cctype>
00068 #include <set>
00069 #include <sstream>
00070 #include <string>
00071 #include <map>
00072 #include <typeinfo>
00073 #include <cmath>
00074 #include <assert.h>
00075 
00076 using namespace std;
00077 
00078 // Mutex to protect CINT and META operations
00079 // (exported to be used for similar cases in related classes)
00080 
00081 TVirtualMutex* gCINTMutex = 0;
00082 
00083 void *gMmallocDesc = 0; //is used and set in TMapFile
00084 namespace {
00085    class TMmallocDescTemp {
00086    private:
00087       void *fSave;
00088    public:
00089       TMmallocDescTemp(void *value = 0) : fSave(gMmallocDesc) { gMmallocDesc = value; }
00090       ~TMmallocDescTemp() { gMmallocDesc = fSave; }
00091    };
00092 }
00093 
00094 Int_t TClass::fgClassCount;
00095 TClass::ENewType TClass::fgCallingNew = kRealNew;
00096 
00097 static std::multimap<void*, Version_t> gObjectVersionRepository;
00098 
00099 static void RegisterAddressInRepository(const char * /*where*/, void *location, const TClass *what)
00100 {
00101    // Register the object for special handling in the destructor.
00102 
00103    Version_t version = what->GetClassVersion();
00104 //    if (!gObjectVersionRepository.count(location)) {
00105 //       Info(where, "Registering address %p of class '%s' version %d", location, what->GetName(), version);
00106 //    } else {
00107 //       Warning(where, "Registering address %p again of class '%s' version %d", location, what->GetName(), version);
00108 //    }
00109    gObjectVersionRepository.insert(std::pair<void* const,Version_t>(location, version));
00110 
00111 #if 0
00112    // This code could be used to prevent an address to be registered twice.
00113    std::pair<std::map<void*, Version_t>::iterator, Bool_t> tmp = gObjectVersionRepository.insert(std::pair<void*,Version_t>(location, version));
00114    if (!tmp.second) {
00115       Warning(where, "Reregistering an object of class '%s' version %d at address %p", what->GetName(), version, p);
00116       gObjectVersionRepository.erase(tmp.first);
00117       tmp = gObjectVersionRepository.insert(std::pair<void*,Version_t>(location, version));
00118       if (!tmp.second) {
00119          Warning(where, "Failed to reregister an object of class '%s' version %d at address %p", what->GetName(), version, location);
00120       }
00121    }
00122 #endif
00123 }
00124 
00125 static void UnregisterAddressInRepository(const char * /*where*/, void *location, const TClass *what)
00126 {
00127    std::multimap<void*, Version_t>::iterator cur = gObjectVersionRepository.find(location);
00128    for (; cur != gObjectVersionRepository.end();) {
00129       std::multimap<void*, Version_t>::iterator tmp = cur++;
00130       if ((tmp->first == location) && (tmp->second == what->GetClassVersion())) {
00131          // -- We still have an address, version match.
00132          // Info(where, "Unregistering address %p of class '%s' version %d", location, what->GetName(), what->GetClassVersion());
00133          gObjectVersionRepository.erase(tmp);
00134       } else {
00135          // -- No address, version match, we've reached the end.
00136          break;
00137       }
00138    }
00139 }
00140 
00141 static void MoveAddressInRepository(const char *where, void *oldadd, void *newadd, const TClass *what)
00142 {
00143    UnregisterAddressInRepository(where,oldadd,what);
00144    RegisterAddressInRepository(where,newadd,what);
00145 }
00146 
00147 //______________________________________________________________________________
00148 //______________________________________________________________________________
00149 namespace ROOT {
00150 #define R__USE_STD_MAP
00151    class TMapTypeToTClass {
00152 #if defined R__USE_STD_MAP
00153      // This wrapper class allow to avoid putting #include <map> in the
00154      // TROOT.h header file.
00155    public:
00156 #ifdef R__GLOBALSTL
00157       typedef map<string,TClass*>                 IdMap_t;
00158 #else
00159       typedef std::map<std::string,TClass*>       IdMap_t;
00160 #endif
00161       typedef IdMap_t::key_type                   key_type;
00162       typedef IdMap_t::const_iterator             const_iterator;
00163       typedef IdMap_t::size_type                  size_type;
00164 #ifdef R__WIN32
00165      // Window's std::map does NOT defined mapped_type
00166       typedef TClass*                             mapped_type;
00167 #else
00168       typedef IdMap_t::mapped_type                mapped_type;
00169 #endif
00170 
00171    private:
00172       IdMap_t fMap;
00173 
00174    public:
00175       void Add(const key_type &key, mapped_type &obj) {
00176          fMap[key] = obj;
00177       }
00178       mapped_type Find(const key_type &key) const {
00179          IdMap_t::const_iterator iter = fMap.find(key);
00180          mapped_type cl = 0;
00181          if (iter != fMap.end()) cl = iter->second;
00182          return cl;
00183       }
00184       void Remove(const key_type &key) { fMap.erase(key); }
00185 #else
00186    private:
00187       TMap fMap;
00188 
00189    public:
00190 #ifdef R__COMPLETE_MEM_TERMINATION
00191       TMapTypeToTClass() {
00192          TIter next(&fMap);
00193          TObjString *key;
00194          while((key = (TObjString*)next())) {
00195             delete key;
00196          }         
00197       }
00198 #endif
00199       void Add(const char *key, TClass *&obj) {
00200          TObjString *realkey = new TObjString(key);
00201          fMap.Add(realkey, obj);
00202       }
00203       TClass* Find(const char *key) const {
00204          const TPair *a = (const TPair *)fMap.FindObject(key);
00205          if (a) return (TClass*) a->Value();
00206          return 0;
00207       }
00208       void Remove(const char *key) {
00209          TObjString realkey(key);
00210          TObject *actual = fMap.Remove(&realkey);
00211          delete actual;
00212       }
00213 #endif
00214    };
00215 }
00216 #ifdef R__COMPLETE_MEM_TERMINATION
00217 static IdMap_t gIdMapObject;
00218 IdMap_t *TClass::fgIdMap = &gIdMapObject;
00219 #else
00220 IdMap_t *TClass::fgIdMap = new IdMap_t;
00221 #endif
00222 //______________________________________________________________________________
00223 void TClass::AddClass(TClass *cl)
00224 {
00225    // static: Add a class to the list and map of classes.
00226 
00227    if (!cl) return;
00228    gROOT->GetListOfClasses()->Add(cl);
00229    if (cl->GetTypeInfo()) {
00230       fgIdMap->Add(cl->GetTypeInfo()->name(),cl);
00231    }
00232 }
00233 
00234 
00235 //______________________________________________________________________________
00236 void TClass::RemoveClass(TClass *oldcl)
00237 {
00238    // static: Remove a class from the list and map of classes
00239 
00240    if (!oldcl) return;
00241    gROOT->GetListOfClasses()->Remove(oldcl);
00242    if (oldcl->GetTypeInfo()) {
00243       fgIdMap->Remove(oldcl->GetTypeInfo()->name());
00244    }
00245 }
00246 
00247 //______________________________________________________________________________
00248 //______________________________________________________________________________
00249 
00250 class TDumpMembers : public TMemberInspector {
00251 
00252 public:
00253    TDumpMembers() { }
00254    void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
00255 };
00256 
00257 //______________________________________________________________________________
00258 void TDumpMembers::Inspect(TClass *cl, const char *pname, const char *mname, const void *add)
00259 {
00260    // Print value of member mname.
00261    //
00262    // This method is called by the ShowMembers() method for each
00263    // data member when object.Dump() is invoked.
00264    //
00265    //    cl    is the pointer to the current class
00266    //    pname is the parent name (in case of composed objects)
00267    //    mname is the data member name
00268    //    add   is the data member address
00269 
00270    const Int_t kvalue = 30;
00271 #ifdef R__B64
00272    const Int_t ktitle = 50;
00273 #else
00274    const Int_t ktitle = 42;
00275 #endif
00276    const Int_t kline  = 1024;
00277    Int_t cdate = 0;
00278    Int_t ctime = 0;
00279    UInt_t *cdatime = 0;
00280    char line[kline];
00281 
00282    TDataType *membertype;
00283    TString memberTypeName;
00284    const char *memberName;
00285    const char *memberFullTypeName;
00286    const char *memberTitle;
00287    Bool_t isapointer;
00288    Bool_t isbasic;
00289 
00290    if (TDataMember *member = cl->GetDataMember(mname)) {
00291       memberTypeName = member->GetTypeName();
00292       memberName = member->GetName();
00293       memberFullTypeName = member->GetFullTypeName();
00294       memberTitle = member->GetTitle();
00295       isapointer = member->IsaPointer();
00296       isbasic = member->IsBasic();
00297       membertype = member->GetDataType();
00298    } else if (!cl->IsLoaded()) {
00299       // The class is not loaded, hence it is 'emulated' and the main source of
00300       // information is the StreamerInfo.
00301       TVirtualStreamerInfo *info = cl->GetStreamerInfo();
00302       if (!info) return;
00303       const char *cursor = mname;
00304       while ( (*cursor)=='*' ) ++cursor;
00305       TString elname( cursor );
00306       Ssiz_t pos = elname.Index("[");
00307       if ( pos != kNPOS ) {
00308          elname.Remove( pos );
00309       }
00310       TStreamerElement *element = (TStreamerElement*)info->GetElements()->FindObject(elname.Data());
00311       if (!element) return;
00312       memberFullTypeName = element->GetTypeName();
00313       
00314       memberTypeName = memberFullTypeName;
00315       memberTypeName = memberTypeName.Strip(TString::kTrailing, '*');
00316       if (memberTypeName.Index("const ")==0) memberTypeName.Remove(0,6);
00317 
00318       memberName = element->GetName();
00319       memberTitle = element->GetTitle();
00320       isapointer = element->IsaPointer() || element->GetType() == TVirtualStreamerInfo::kCharStar;
00321       membertype = gROOT->GetType(memberFullTypeName);
00322       
00323       isbasic = membertype !=0;
00324    } else {
00325       return;
00326    }
00327    
00328    
00329    Bool_t isdate = kFALSE;
00330    if (strcmp(memberName,"fDatime") == 0 && strcmp(memberTypeName,"UInt_t") == 0) {
00331       isdate = kTRUE;
00332    }
00333    Bool_t isbits = kFALSE;
00334    if (strcmp(memberName,"fBits") == 0 && strcmp(memberTypeName,"UInt_t") == 0) {
00335       isbits = kTRUE;
00336    }
00337 
00338    Int_t i;
00339    for (i = 0;i < kline; i++) line[i] = ' ';
00340    line[kline-1] = 0;
00341    snprintf(line,kline,"%s%s ",pname,mname);
00342    i = strlen(line); line[i] = ' ';
00343 
00344    // Encode data value or pointer value
00345    char *pointer = (char*)add;
00346    char **ppointer = (char**)(pointer);
00347 
00348    if (isapointer) {
00349       char **p3pointer = (char**)(*ppointer);
00350       if (!p3pointer)
00351          snprintf(&line[kvalue],kline-kvalue,"->0");
00352       else if (!isbasic)
00353          snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
00354       else if (membertype) {
00355          if (!strcmp(membertype->GetTypeName(), "char")) {
00356             i = strlen(*ppointer);
00357             if (kvalue+i > kline) i=kline-1-kvalue;
00358             Bool_t isPrintable = kTRUE;
00359             for (Int_t j = 0; j < i; j++) {
00360                if (!std::isprint((*ppointer)[j])) {
00361                   isPrintable = kFALSE;
00362                   break;
00363                }
00364             }
00365             if (isPrintable) {
00366                strncpy(line + kvalue, *ppointer, i);
00367                line[kvalue+i] = 0;
00368             } else {
00369                line[kvalue] = 0;
00370             }
00371          } else {
00372             strncpy(&line[kvalue], membertype->AsString(p3pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(p3pointer))));
00373          }
00374       } else if (!strcmp(memberFullTypeName, "char*") ||
00375                  !strcmp(memberFullTypeName, "const char*")) {
00376          i = strlen(*ppointer);
00377          if (kvalue+i >= kline) i=kline-1-kvalue;
00378          Bool_t isPrintable = kTRUE;
00379          for (Int_t j = 0; j < i; j++) {
00380             if (!std::isprint((*ppointer)[j])) {
00381                isPrintable = kFALSE;
00382                break;
00383             }
00384          }
00385          if (isPrintable) {
00386             strncpy(line + kvalue, *ppointer, i);
00387             line[kvalue+i] = 0;
00388          } else {
00389             line[kvalue] = 0;
00390          }
00391       } else {
00392          snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
00393       }
00394    } else if (membertype)
00395       if (isdate) {
00396          cdatime = (UInt_t*)pointer;
00397          TDatime::GetDateTime(cdatime[0],cdate,ctime);
00398          snprintf(&line[kvalue],kline-kvalue,"%d/%d",cdate,ctime);
00399       } else if (isbits) {
00400          snprintf(&line[kvalue],kline-kvalue,"0x%08x", *(UInt_t*)pointer);
00401       } else {
00402          strncpy(&line[kvalue], membertype->AsString(pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(pointer))));
00403       }
00404    else
00405       snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)pointer);
00406 
00407    // Encode data member title
00408    if (isdate == kFALSE && strcmp(memberFullTypeName, "char*") && strcmp(memberFullTypeName, "const char*")) {
00409       i = strlen(&line[0]); line[i] = ' ';
00410       Int_t lentit = strlen(memberTitle);
00411       if (lentit > 250-ktitle) lentit = 250-ktitle;
00412       strncpy(&line[ktitle],memberTitle,lentit);
00413       line[ktitle+lentit] = 0;
00414    }
00415    Printf("%s", line);
00416 }
00417 
00418 THashTable* TClass::fgClassTypedefHash = 0;
00419 THashTable* TClass::fgClassShortTypedefHash = 0;
00420 
00421 //______________________________________________________________________________
00422 //______________________________________________________________________________
00423 //______________________________________________________________________________
00424 TClass::TNameMapNode::TNameMapNode (const char* typedf, const char* orig)
00425   : TObjString (typedf),
00426     fOrigName (orig)
00427 {
00428 }
00429 
00430 //______________________________________________________________________________
00431 
00432 class TBuildRealData : public TMemberInspector {
00433 
00434 private:
00435    void    *fRealDataObject;
00436    TClass  *fRealDataClass;
00437    UInt_t   fBits;       //bit field status word
00438 
00439 public:
00440    TBuildRealData(void *obj, TClass *cl) : fBits(0) {
00441       fRealDataObject = obj;
00442       fRealDataClass = cl;
00443    }
00444    void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
00445 
00446    //----- bit manipulation
00447    void     SetBit(UInt_t f, Bool_t set);
00448    void     SetBit(UInt_t f) { fBits |= f & TObject::kBitMask; }
00449    void     ResetBit(UInt_t f) { fBits &= ~(f & TObject::kBitMask); }
00450    Bool_t   TestBit(UInt_t f) const { return (Bool_t) ((fBits & f) != 0); }
00451    Int_t    TestBits(UInt_t f) const { return (Int_t) (fBits & f); }
00452    void     InvertBit(UInt_t f) { fBits ^= f & TObject::kBitMask; }
00453 };
00454 
00455 //______________________________________________________________________________
00456 void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add)
00457 {
00458    // This method is called from ShowMembers() via BuildRealdata().
00459 
00460    TDataMember* dm = cl->GetDataMember(mname);
00461    if (!dm) {
00462       return;
00463    }
00464 
00465    Bool_t isTransient = kFALSE;
00466 
00467    if (!dm->IsPersistent()) {
00468       // For the DataModelEvolution we need access to the transient member.
00469       // so we now record them in the list of RealData.
00470       isTransient = kTRUE;
00471    }
00472 
00473    TString rname( pname );
00474    // Take into account cases like TPaveStats->TPaveText->TPave->TBox.
00475    // Check that member is in a derived class or an object in the class.
00476    if (cl != fRealDataClass) {
00477       if (!fRealDataClass->InheritsFrom(cl)) {
00478          Ssiz_t dot = rname.Index('.');
00479          if (dot == kNPOS) {
00480             return;
00481          }
00482          rname[dot] = '\0';
00483          if (!fRealDataClass->GetDataMember(rname)) {
00484             //could be a data member in a base class like in this example
00485             // class Event : public Data {
00486             //   class Data : public TObject {
00487             //     EventHeader fEvtHdr;
00488             //     class EventHeader {
00489             //       Int_t     fEvtNum;
00490             //       Int_t     fRun;
00491             //       Int_t     fDate;
00492             //       EventVertex fVertex;
00493             //       class EventVertex {
00494             //         EventTime  fTime;
00495             //         class EventTime {
00496             //           Int_t     fSec;
00497             //           Int_t     fNanoSec;
00498             if (!fRealDataClass->GetBaseDataMember(rname)) {
00499                return;
00500             }
00501          }
00502          rname[dot] = '.';
00503       }
00504    }
00505    rname += mname;
00506    Long_t offset = Long_t(((Long_t) add) - ((Long_t) fRealDataObject));
00507 
00508    if (dm->IsaPointer()) {
00509       // Data member is a pointer.
00510       if (!dm->IsBasic()) {
00511          // Pointer to class object.
00512          TRealData* rd = new TRealData(rname, offset, dm);
00513          if (isTransient) { rd->SetBit(TRealData::kTransient); };
00514          fRealDataClass->GetListOfRealData()->Add(rd);
00515       } else {
00516          // Pointer to basic data type.
00517          TRealData* rd = new TRealData(rname, offset, dm);
00518          if (isTransient) { rd->SetBit(TRealData::kTransient); };
00519          fRealDataClass->GetListOfRealData()->Add(rd);
00520       }
00521    } else {
00522       // Data Member is a basic data type.
00523       TRealData* rd = new TRealData(rname, offset, dm);
00524       if (isTransient) { rd->SetBit(TRealData::kTransient); };
00525       if (!dm->IsBasic()) {
00526          rd->SetIsObject(kTRUE);
00527 
00528          // Make sure that BuildReadData is called for any abstract
00529          // bases classes involved in this object, i.e for all the
00530          // classes composing this object (base classes, type of
00531          // embedded object and same for their data members).
00532          //
00533          TClass* dmclass = TClass::GetClass(dm->GetTypeName(), kTRUE, isTransient || TestBit(TRealData::kTransient));
00534          if (!dmclass) {
00535             dmclass = TClass::GetClass(dm->GetTrueTypeName(), kTRUE, isTransient || TestBit(TRealData::kTransient));
00536          }
00537          if (dmclass) {
00538             if (dmclass->Property()) {
00539                if (dmclass->Property() & kIsAbstract) {
00540                   fprintf(stderr, "TBuildRealDataRecursive::Inspect(): data member class: '%s'  is abstract.\n", dmclass->GetName());
00541                }
00542             }
00543             if ((dmclass != cl) && !dm->IsaPointer()) {
00544                if (dmclass->GetCollectionProxy()) {
00545                   TClass* valcl = dmclass->GetCollectionProxy()->GetValueClass();
00546                   if (valcl && !(valcl->Property() & kIsAbstract)) valcl->BuildRealData(0, isTransient || TestBit(TRealData::kTransient));
00547                } else {
00548                   dmclass->BuildRealData(const_cast<void*>(add), isTransient || TestBit(TRealData::kTransient));
00549                }
00550             }
00551          }
00552       }
00553       fRealDataClass->GetListOfRealData()->Add(rd);
00554    }
00555 }
00556 
00557 //______________________________________________________________________________
00558 //______________________________________________________________________________
00559 //______________________________________________________________________________
00560 
00561 //______________________________________________________________________________
00562 class TAutoInspector : public TMemberInspector {
00563 
00564 public:
00565    Int_t     fCount;
00566    TBrowser *fBrowser;
00567 
00568    TAutoInspector(TBrowser *b) { fBrowser = b; fCount = 0; }
00569    virtual ~TAutoInspector() { }
00570    virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
00571 };
00572 
00573 //______________________________________________________________________________
00574 void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
00575                              const void *addr)
00576 {
00577    // This method is called from ShowMembers() via AutoBrowse().
00578 
00579    if(tit && strchr(tit,'.'))    return ;
00580    if (fCount && !fBrowser) return;
00581 
00582    TString ts;
00583 
00584    if (!cl) return;
00585    //if (*(cl->GetName()) == 'T') return;
00586    if (*name == '*') name++;
00587    int ln = strcspn(name,"[ ");
00588    TString iname(name,ln);
00589 
00590    ClassInfo_t *classInfo = cl->GetClassInfo();
00591    if (!classInfo)               return;
00592 
00593    //              Browse data members
00594    DataMemberInfo_t *m = gCint->DataMemberInfo_Factory(classInfo);
00595    TString mname;
00596 
00597    int found=0;
00598    while (gCint->DataMemberInfo_Next(m)) {    // MemberLoop
00599       mname = gCint->DataMemberInfo_Name(m);
00600       mname.ReplaceAll("*","");
00601       if ((found = (iname==mname))) break;
00602    }
00603    assert(found);
00604 
00605    // we skip: non static members and non objects
00606    //  - the member G__virtualinfo inserted by the CINT RTTI system
00607 
00608    //Long_t prop = m.Property() | m.Type()->Property();
00609    Long_t prop = gCint->DataMemberInfo_Property(m) | gCint->DataMemberInfo_TypeProperty(m);
00610    if (prop & G__BIT_ISSTATIC)           return;
00611    if (prop & G__BIT_ISFUNDAMENTAL)      return;
00612    if (prop & G__BIT_ISENUM)             return;
00613    if (mname == "G__virtualinfo")        return;
00614 
00615    int  size = sizeof(void*);
00616 
00617    int nmax = 1;
00618    if (prop & G__BIT_ISARRAY) {
00619       for (int dim = 0; dim < gCint->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCint->DataMemberInfo_MaxIndex(m,dim);
00620    }
00621 
00622    std::string clmName(TClassEdit::ShortType(gCint->DataMemberInfo_TypeName(m),
00623                                              TClassEdit::kDropTrailStar) );
00624    TClass * clm = TClass::GetClass(clmName.c_str());
00625    R__ASSERT(clm);
00626    if (!(prop&G__BIT_ISPOINTER)) {
00627       size = clm->Size();
00628       if (size==0) size = gCint->DataMemberInfo_TypeSize(m);
00629    }
00630 
00631 
00632    gCint->DataMemberInfo_Delete(m);
00633    TVirtualCollectionProxy *proxy = clm->GetCollectionProxy();
00634 
00635    for(int i=0; i<nmax; i++) {
00636 
00637       char *ptr = (char*)addr + i*size;
00638 
00639       void *obj = (prop&G__BIT_ISPOINTER) ? *((void**)ptr) : (TObject*)ptr;
00640 
00641       if (!obj)           continue;
00642 
00643       fCount++;
00644       if (!fBrowser)      return;
00645 
00646       TString bwname;
00647       TClass *actualClass = clm->GetActualClass(obj);
00648       if (clm->IsTObject()) {
00649          TObject *tobj = (TObject*)clm->DynamicCast(TObject::Class(),obj);
00650          bwname = tobj->GetName();
00651       } else {
00652          bwname = actualClass->GetName();
00653          bwname += "::";
00654          bwname += mname;
00655       }
00656 
00657       if (!clm->IsTObject() ||
00658           bwname.Length()==0 ||
00659           strcmp(bwname.Data(),actualClass->GetName())==0) {
00660          bwname = name;
00661          int l = strcspn(bwname.Data(),"[ ");
00662          if (l<bwname.Length() && bwname[l]=='[') {
00663             char cbuf[12]; snprintf(cbuf,12,"[%02d]",i);
00664             ts.Replace(0,999,bwname,l);
00665             ts += cbuf;
00666             bwname = (const char*)ts;
00667          }
00668       }
00669 
00670       if (proxy==0) {
00671 
00672          fBrowser->Add(obj,clm,bwname);
00673 
00674       } else {
00675          TClass *valueCl = proxy->GetValueClass();
00676 
00677          if (valueCl==0) {
00678 
00679             fBrowser->Add( obj, clm, bwname );
00680 
00681          } else {
00682             TVirtualCollectionProxy::TPushPop env(proxy, obj);
00683             TClass *actualCl = 0;
00684 
00685             int sz = proxy->Size();
00686 
00687             char fmt[] = {"#%09d"};
00688             fmt[3]  = '0'+(int)log10(double(sz))+1;
00689             char buf[20];
00690             for (int ii=0;ii<sz;ii++) {
00691                void *p = proxy->At(ii);
00692 
00693                if (proxy->HasPointers()) {
00694                   p = *((void**)p);
00695                   if(!p) continue;
00696                   actualCl = valueCl->GetActualClass(p);
00697                   p = actualCl->DynamicCast(valueCl,p,0);
00698                }
00699                fCount++;
00700                snprintf(buf,20,fmt,ii);
00701                ts = bwname;
00702                ts += buf;
00703                fBrowser->Add( p, actualCl, ts );
00704             }
00705          }
00706       }
00707    }
00708 }
00709 
00710 //______________________________________________________________________________
00711 //______________________________________________________________________________
00712 //______________________________________________________________________________
00713 
00714 ClassImp(TClass)
00715 
00716 //______________________________________________________________________________
00717 TClass::TClass() :
00718    TDictionary(),
00719    fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
00720    fBase(0), fData(0), fMethod(0), fAllPubData(0), fAllPubMethod(0),
00721    fClassMenuList(0),
00722    fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
00723    fInstanceCount(0), fOnHeap(0),
00724    fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
00725    fTypeInfo(0), fShowMembers(0), fInterShowMembers(0),
00726    fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
00727    fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
00728    fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fSizeof(-1),
00729    fProperty(0),fVersionUsed(kFALSE), 
00730    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(kNone),
00731    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
00732    fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
00733 {
00734    // Default ctor.
00735 
00736    R__LOCKGUARD2(gCINTMutex);
00737    fDeclFileLine   = -2;    // -2 for standalone TClass (checked in dtor)
00738 }
00739 
00740 //______________________________________________________________________________
00741 TClass::TClass(const char *name, Bool_t silent) :
00742    TDictionary(name),
00743    fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
00744    fBase(0), fData(0), fMethod(0), fAllPubData(0), fAllPubMethod(0),
00745    fClassMenuList(0),
00746    fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
00747    fInstanceCount(0), fOnHeap(0),
00748    fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
00749    fTypeInfo(0), fShowMembers(0), fInterShowMembers(0),
00750    fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
00751    fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
00752    fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fSizeof(-1),
00753    fProperty(0),fVersionUsed(kFALSE), 
00754    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(kNone),
00755    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
00756    fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
00757 {
00758    // Create a TClass object. This object contains the full dictionary
00759    // of a class. It has list to baseclasses, datamembers and methods.
00760    // Use this ctor to create a standalone TClass object. Most useful
00761    // to get a TClass interface to an interpreted class. Used by TTabCom.
00762    // Normally you would use TClass::GetClass("class") to get access to a
00763    // TClass object for a certain class.
00764 
00765    R__LOCKGUARD2(gCINTMutex);
00766 
00767    if (!gROOT)
00768       ::Fatal("TClass::TClass", "ROOT system not initialized");
00769 
00770    fDeclFileLine   = -2;    // -2 for standalone TClass (checked in dtor)
00771 
00772    SetBit(kLoading);
00773    if (!gInterpreter)
00774       ::Fatal("TClass::TClass", "gInterpreter not initialized");
00775 
00776    gInterpreter->SetClassInfo(this);   // sets fClassInfo pointer
00777    if (!fClassInfo) {
00778       gInterpreter->InitializeDictionaries();
00779       gInterpreter->SetClassInfo(this);
00780    }
00781    if (!silent && !fClassInfo && fName.First('@')==kNPOS) 
00782       ::Warning("TClass::TClass", "no dictionary for class %s is available", name);
00783    ResetBit(kLoading);
00784 
00785    if (fClassInfo) SetTitle(gCint->ClassInfo_Title(fClassInfo));
00786    fConversionStreamerInfo = 0;
00787 }
00788 
00789 //______________________________________________________________________________
00790 TClass::TClass(const char *name, Version_t cversion,
00791                const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
00792    TDictionary(name),
00793    fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
00794    fBase(0), fData(0), fMethod(0), fAllPubData(0), fAllPubMethod(0),
00795    fClassMenuList(0),
00796    fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
00797    fInstanceCount(0), fOnHeap(0),
00798    fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
00799    fTypeInfo(0), fShowMembers(0), fInterShowMembers(0),
00800    fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
00801    fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
00802    fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fSizeof(-1),
00803    fProperty(0),fVersionUsed(kFALSE), 
00804    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(kNone),
00805    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
00806    fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
00807 {
00808    // Create a TClass object. This object contains the full dictionary
00809    // of a class. It has list to baseclasses, datamembers and methods.
00810    R__LOCKGUARD2(gCINTMutex);
00811    Init(name,cversion, 0, 0, 0, dfil, ifil, dl, il,silent);
00812    SetBit(kUnloaded);
00813 }
00814 
00815 //______________________________________________________________________________
00816 TClass::TClass(const char *name, Version_t cversion,
00817                const type_info &info, TVirtualIsAProxy *isa,
00818                ShowMembersFunc_t showmembers,
00819                const char *dfil, const char *ifil, Int_t dl, Int_t il,
00820                Bool_t silent) :
00821    TDictionary(name),
00822    fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
00823    fBase(0), fData(0), fMethod(0), fAllPubData(0), fAllPubMethod(0),
00824    fClassMenuList(0),
00825    fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
00826    fInstanceCount(0), fOnHeap(0),
00827    fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
00828    fTypeInfo(0), fShowMembers(0), fInterShowMembers(0),
00829    fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
00830    fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
00831    fDestructor(0), fDirAutoAdd(0), fSizeof(-1),
00832    fProperty(0),fVersionUsed(kFALSE), 
00833    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(kNone),
00834    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
00835    fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
00836 {
00837    // Create a TClass object. This object contains the full dictionary
00838    // of a class. It has list to baseclasses, datamembers and methods.
00839 
00840    R__LOCKGUARD2(gCINTMutex);
00841    // use info
00842    Init(name, cversion, &info, isa, showmembers, dfil, ifil, dl, il, silent);
00843 }
00844 
00845 //______________________________________________________________________________
00846 void TClass::ForceReload (TClass* oldcl)
00847 {
00848    // we found at least one equivalent.
00849    // let's force a reload
00850 
00851    TClass::RemoveClass(oldcl);
00852 
00853    if (oldcl->CanIgnoreTObjectStreamer()) {
00854       IgnoreTObjectStreamer();
00855    }
00856 
00857    TVirtualStreamerInfo *info;
00858    TIter next(oldcl->GetStreamerInfos());
00859    while ((info = (TVirtualStreamerInfo*)next())) {
00860       info->Clear("build");
00861       info->SetClass(this);
00862       fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
00863    }
00864    oldcl->GetStreamerInfos()->Clear();
00865 
00866    oldcl->ReplaceWith(this);
00867    delete oldcl;
00868 }
00869 
00870 //______________________________________________________________________________
00871 void TClass::Init(const char *name, Version_t cversion,
00872                   const type_info *typeinfo, TVirtualIsAProxy *isa,
00873                   ShowMembersFunc_t showmembers,
00874                   const char *dfil, const char *ifil, Int_t dl, Int_t il,
00875                   Bool_t silent)
00876 {
00877    // Initialize a TClass object. This object contains the full dictionary
00878    // of a class. It has list to baseclasses, datamembers and methods.
00879    if (!gROOT)
00880       ::Fatal("TClass::TClass", "ROOT system not initialized");
00881 
00882    // Always strip the default STL template arguments (from any template argument or the class name)
00883    SetName(TClassEdit::ShortType(name, TClassEdit::kDropStlDefault).c_str());
00884    fClassVersion   = cversion;
00885    fDeclFileName   = dfil ? dfil : "";
00886    fImplFileName   = ifil ? ifil : "";
00887    fDeclFileLine   = dl;
00888    fImplFileLine   = il;
00889    fTypeInfo       = typeinfo;
00890    fIsA            = isa;
00891    if ( fIsA ) fIsA->SetClass(this);
00892    fShowMembers    = showmembers;
00893    fStreamerInfo   = new TObjArray(fClassVersion+2+10,-1); // +10 to read new data by old
00894    fProperty       = -1;
00895 
00896    ResetInstanceCount();
00897 
00898    TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
00899 
00900    if (oldcl && oldcl->TestBit(kLoading)) {
00901       // Do not recreate a class while it is already being created!
00902       return;
00903    }
00904 
00905    if (oldcl) {
00906       gROOT->RemoveClass(oldcl);
00907       // move the StreamerInfo immediately so that there are
00908       // properly updated!
00909 
00910       if (oldcl->CanIgnoreTObjectStreamer()) {
00911          IgnoreTObjectStreamer();
00912       }
00913       TVirtualStreamerInfo *info;
00914 
00915       TIter next(oldcl->GetStreamerInfos());
00916       while ((info = (TVirtualStreamerInfo*)next())) {
00917          // We need to force a call to BuildOld
00918          info->Clear("build");
00919          info->SetClass(this);
00920          fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
00921       }
00922       oldcl->GetStreamerInfos()->Clear();
00923       
00924       // Move the Schema Rules too.
00925       fSchemaRules = oldcl->fSchemaRules;
00926       oldcl->fSchemaRules = 0;
00927 
00928    }
00929 
00930    SetBit(kLoading);
00931    // Advertise ourself as the loading class for this class name
00932    TClass::AddClass(this);
00933 
00934    Bool_t isStl = TClassEdit::IsSTLCont(fName);
00935 
00936    if (!fClassInfo) {
00937       Bool_t shouldLoad = kFALSE;
00938 
00939       if (gInterpreter->CheckClassInfo(fName)) shouldLoad = kTRUE;
00940       else if (fImplFileLine>=0) {
00941          // If the TClass is being generated from a ROOT dictionary,
00942          // eventhough we do not seem to have a CINT dictionary for
00943          // the class, we will will try to load it anyway UNLESS
00944          // the class is an STL container (or string).
00945          // This is because we do not expect the CINT dictionary
00946          // to be present for all STL classes (and we can handle
00947          // the lack of CINT dictionary in that cases).
00948 
00949          shouldLoad = ! isStl;
00950       }
00951 
00952       if (shouldLoad) {
00953          if (!gInterpreter)
00954             ::Fatal("TClass::TClass", "gInterpreter not initialized");
00955 
00956          gInterpreter->SetClassInfo(this);   // sets fClassInfo pointer
00957          if (!fClassInfo) {
00958             gInterpreter->InitializeDictionaries();
00959             gInterpreter->SetClassInfo(this);
00960             if (IsZombie()) {
00961                TClass::RemoveClass(this);
00962                return;
00963             }
00964          }
00965       }
00966    }
00967    if (!silent && !fClassInfo && !isStl && fName.First('@')==kNPOS)
00968       ::Warning("TClass::TClass", "no dictionary for class %s is available", fName.Data());
00969 
00970    fgClassCount++;
00971    SetUniqueID(fgClassCount);
00972 
00973    // Make the typedef-expanded -> original hash table entries.
00974    // There may be several entries for any given key.
00975    // We only make entries if the typedef-expanded name
00976    // is different from the original name.
00977    TString resolvedThis;
00978    if (strchr (name, '<')) {
00979       if ( fName != name) {
00980          if (!fgClassTypedefHash) {
00981             fgClassTypedefHash = new THashTable (100, 5);
00982             fgClassTypedefHash->SetOwner (kTRUE);
00983          }
00984          
00985          fgClassTypedefHash->Add (new TNameMapNode (name, fName));
00986          SetBit (kHasNameMapNode);         
00987 
00988          TString resolvedShort = TClassEdit::ResolveTypedef(fName, kTRUE);
00989          if (resolvedShort != fName) {
00990             fgClassShortTypedefHash->Add (new TNameMapNode (resolvedShort, fName));
00991          }         
00992       }
00993       resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
00994       if (resolvedThis != name) {
00995          if (!fgClassTypedefHash) {
00996             fgClassTypedefHash = new THashTable (100, 5);
00997             fgClassTypedefHash->SetOwner (kTRUE);
00998          }
00999 
01000          fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
01001          SetBit (kHasNameMapNode);
01002       }
01003 
01004    }
01005 
01006    //In case a class with the same name had been created by TVirtualStreamerInfo
01007    //we must delete the old class, importing only the StreamerInfo structure
01008    //from the old dummy class.
01009    if (oldcl) {
01010 
01011       oldcl->ReplaceWith(this);
01012       delete oldcl;
01013 
01014    } else if (resolvedThis.Length() > 0 && fgClassTypedefHash) {
01015 
01016       // Check for existing equivalent.
01017 
01018       if (resolvedThis != fName) {
01019          oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
01020          if (oldcl && oldcl != this)
01021             ForceReload (oldcl);
01022       }
01023       TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
01024       while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
01025          if (resolvedThis != htmp->String()) continue;
01026          oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName); // gROOT->GetClass (htmp->fOrigName, kFALSE);
01027          if (oldcl && oldcl != this) {
01028             ForceReload (oldcl);
01029          }
01030       }
01031    }
01032    if (fClassInfo) SetTitle(gCint->ClassInfo_Title(fClassInfo));
01033 
01034    ResetBit(kLoading);
01035 
01036    if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
01037       fCollectionProxy = TVirtualStreamerInfo::Factory()->GenEmulatedProxy( GetName() );
01038       if (fCollectionProxy) {
01039          fSizeof = fCollectionProxy->Sizeof();
01040       } else if (!silent) {
01041          Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
01042       }
01043       if (fStreamer==0) {
01044          fStreamer =  TVirtualStreamerInfo::Factory()->GenEmulatedClassStreamer( GetName() );
01045       }
01046    }
01047 
01048 }
01049 
01050 //______________________________________________________________________________
01051 TClass::TClass(const TClass& cl) :
01052   TDictionary(cl),
01053   fStreamerInfo(cl.fStreamerInfo),
01054   fConversionStreamerInfo(cl.fConversionStreamerInfo),
01055   fRealData(cl.fRealData),
01056   fBase(cl.fBase),
01057   fData(cl.fData),
01058   fMethod(cl.fMethod),
01059   fAllPubData(cl.fAllPubData),
01060   fAllPubMethod(cl.fAllPubMethod),
01061   fClassMenuList(0),
01062   fDeclFileName(cl.fDeclFileName),
01063   fImplFileName(cl.fImplFileName),
01064   fDeclFileLine(cl.fDeclFileLine),
01065   fImplFileLine(cl.fImplFileLine),
01066   fInstanceCount(cl.fInstanceCount),
01067   fOnHeap(cl.fOnHeap),
01068   fCheckSum(cl.fCheckSum),
01069   fCollectionProxy(cl.fCollectionProxy),
01070   fClassVersion(cl.fClassVersion),
01071   fClassInfo(cl.fClassInfo),
01072   fContextMenuTitle(cl.fContextMenuTitle),
01073   fTypeInfo(cl.fTypeInfo),
01074   fShowMembers(cl.fShowMembers),
01075   fInterShowMembers(cl.fInterShowMembers),
01076   fStreamer(cl.fStreamer),
01077   fSharedLibs(cl.fSharedLibs),
01078   fIsA(cl.fIsA),
01079   fGlobalIsA(cl.fGlobalIsA),
01080   fIsAMethod(cl.fIsAMethod),
01081   fNew(cl.fNew),
01082   fNewArray(cl.fNewArray),
01083   fDelete(cl.fDelete),
01084   fDeleteArray(cl.fDeleteArray),
01085   fDestructor(cl.fDestructor),
01086   fDirAutoAdd(cl.fDirAutoAdd),
01087   fStreamerFunc(cl.fStreamerFunc),
01088   fSizeof(cl.fSizeof),
01089   fProperty(cl.fProperty),
01090   fVersionUsed(cl.fVersionUsed),
01091   fIsOffsetStreamerSet(cl.fIsOffsetStreamerSet),
01092   fOffsetStreamer(cl.fOffsetStreamer),
01093   fStreamerType(cl.fStreamerType),
01094   fCurrentInfo(cl.fCurrentInfo),
01095   fRefStart(cl.fRefStart),
01096   fRefProxy(cl.fRefProxy),
01097   fSchemaRules(cl.fSchemaRules),
01098   fStreamerImpl(cl.fStreamerImpl)
01099 {
01100    //copy constructor
01101    
01102    R__ASSERT(0 /* TClass Object are not copyable */ );
01103 }
01104 
01105 //______________________________________________________________________________
01106 TClass& TClass::operator=(const TClass& cl)
01107 {
01108    //assignement operator
01109    if(this!=&cl) {
01110       R__ASSERT(0 /* TClass Object are not copyable */ );
01111    }
01112    return *this;
01113 }
01114 
01115 
01116 //______________________________________________________________________________
01117 TClass::~TClass()
01118 {
01119    // TClass dtor. Deletes all list that might have been created.
01120 
01121    R__LOCKGUARD(gCINTMutex);
01122    
01123    // Remove from the typedef hashtables.
01124    if (fgClassTypedefHash && TestBit (kHasNameMapNode)) {
01125       TString resolvedThis = TClassEdit::ResolveTypedef (GetName(), kTRUE);
01126       TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
01127       while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
01128          if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
01129             fgClassTypedefHash->Remove (htmp);
01130             delete htmp;
01131             break;
01132          }
01133       }
01134    }
01135    if (fgClassShortTypedefHash && TestBit (kHasNameMapNode)) {
01136       TString resolvedShort =
01137        TClassEdit::ResolveTypedef
01138          (TClassEdit::ShortType(GetName(),
01139                                 TClassEdit::kDropStlDefault).c_str(),
01140           kTRUE);
01141       TIter next (fgClassShortTypedefHash->GetListForObject (resolvedShort));
01142       while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
01143          if (resolvedShort == htmp->String() && htmp->fOrigName == GetName()) {
01144             fgClassShortTypedefHash->Remove (htmp);
01145             delete htmp;
01146             break;
01147          }
01148       }
01149    }
01150    
01151 
01152    // Not owning lists, don't call Delete()
01153    // But this still need to be done first because the TList desctructor
01154    // does access the object contained (via GetObject()->TestBit(kCanDelete))
01155    delete fStreamer;       fStreamer    =0;
01156    delete fAllPubData;     fAllPubData  =0;
01157    delete fAllPubMethod;   fAllPubMethod=0;
01158 
01159    if (fRefStart) {
01160       // Inform the TClassRef object that we are going away.
01161       fRefStart->ListReset();
01162       fRefStart = 0;
01163    }
01164    if (fBase)
01165       fBase->Delete();
01166    delete fBase;   fBase=0;
01167 
01168    if (fData)
01169       fData->Delete();
01170    delete fData;   fData = 0;
01171 
01172    if (fMethod)
01173       fMethod->Delete();
01174    delete fMethod;   fMethod=0;
01175 
01176    if (fRealData)
01177       fRealData->Delete();
01178    delete fRealData;  fRealData=0;
01179 
01180    if (fStreamerInfo)
01181       fStreamerInfo->Delete();
01182    delete fStreamerInfo; fStreamerInfo=0;
01183 
01184    if (fDeclFileLine >= -1)
01185       TClass::RemoveClass(this);
01186 
01187    gCint->ClassInfo_Delete(fClassInfo);  
01188    fClassInfo=0;
01189 
01190    if (fClassMenuList)
01191       fClassMenuList->Delete();
01192    delete fClassMenuList; fClassMenuList=0;
01193 
01194    fIsOffsetStreamerSet=kFALSE;
01195 
01196    if (fInterShowMembers) gCint->CallFunc_Delete(fInterShowMembers);
01197 
01198    if ( fIsA ) delete fIsA;
01199 
01200    if ( fRefProxy ) fRefProxy->Release();
01201    fRefProxy = 0;
01202 
01203    delete fStreamer;
01204    delete fCollectionProxy;
01205    delete fIsAMethod;
01206    delete fSchemaRules;
01207    if (fConversionStreamerInfo) {
01208       std::map<std::string, TObjArray*>::iterator it;
01209       std::map<std::string, TObjArray*>::iterator end = fConversionStreamerInfo->end();
01210       for( it = fConversionStreamerInfo->begin(); it != end; ++it ) {
01211          delete it->second;
01212       }
01213       delete fConversionStreamerInfo;
01214    }
01215 }
01216 
01217 //------------------------------------------------------------------------------
01218 namespace {
01219    Int_t ReadRulesContent(FILE *f) 
01220    {
01221       // Read a class.rules file which contains one rule per line with comment
01222       // starting with a #
01223       // Returns the number of rules loaded.
01224       // Returns -1 in case of error.
01225       
01226       R__ASSERT(f!=0);
01227       TString rule(1024);
01228       int c, state = 0;
01229       Int_t count = 0;
01230       
01231       while ((c = fgetc(f)) != EOF) {
01232          if (c == 13)        // ignore CR
01233             continue;
01234          if (c == '\n') {
01235             if (state != 3) {
01236                state = 0;
01237                if (rule.Length() > 0) {
01238                   if (TClass::AddRule(rule)) {
01239                      ++count;
01240                   }
01241                   rule.Clear();
01242                }
01243             }
01244             continue;
01245          }
01246          switch (state) {
01247             case 0:             // start of line
01248                switch (c) {
01249                   case ' ':
01250                   case '\t':
01251                      break;
01252                   case '#':
01253                      state = 1;
01254                      break;
01255                   default:
01256                      state = 2;
01257                      break;
01258                }
01259                break;
01260                
01261             case 1:             // comment
01262                break;
01263                
01264             case 2:             // rule
01265                switch (c) {
01266                   case '\\':
01267                      state = 3; // Continuation request
01268                   default:
01269                      break;
01270                }
01271                break;            
01272          }
01273          switch (state) {
01274             case 2:
01275                rule.Append(c);
01276                break;
01277          }
01278       }
01279       return count;
01280    }
01281 }
01282 
01283 //------------------------------------------------------------------------------
01284 Int_t TClass::ReadRules()
01285 {
01286    // Read the class.rules files from the default location:.
01287    //     $ROOTSYS/etc/class.rules (or ROOTETCDIR/class.rules)
01288    
01289    static const char *suffix = "class.rules";
01290    TString sname = suffix;
01291 #ifdef ROOTETCDIR
01292    gSystem->PrependPathName(ROOTETCDIR, sname);
01293 #else
01294    TString etc = gRootDir;
01295 #ifdef WIN32
01296    etc += "\\etc";
01297 #else
01298    etc += "/etc";
01299 #endif
01300    gSystem->PrependPathName(etc, sname);
01301 #endif
01302    
01303    Int_t res = -1;
01304    
01305    FILE * f = fopen(sname,"r");
01306    if (f != 0) {
01307       res = ReadRulesContent(f);
01308       fclose(f);
01309    }
01310    return res;
01311 }
01312 
01313 //------------------------------------------------------------------------------
01314 Int_t TClass::ReadRules( const char *filename )
01315 {
01316    // Read a class.rules file which contains one rule per line with comment
01317    // starting with a #
01318    // Returns the number of rules loaded.
01319    // Returns -1 in case of error.
01320    
01321    if (!filename || !strlen(filename)) {
01322       ::Error("TClass::ReadRules", "no file name specified");
01323       return -1;
01324    }
01325    
01326    FILE * f = fopen(filename,"r");
01327    if (f == 0) {
01328       ::Error("TClass::ReadRules","Failed to open %s\n",filename);
01329       return -1;
01330    }
01331    Int_t count = ReadRulesContent(f);
01332    
01333    fclose(f);
01334    return count;
01335    
01336 }
01337 
01338 //------------------------------------------------------------------------------
01339 Bool_t TClass::AddRule( const char *rule )
01340 {
01341    // Add a schema evolution customization rule.
01342    // The syntax of the rule can be either the short form:
01343    //  [type=Read] classname membername [attributes=... ] [version=[...] ] [checksum=[...] ] [oldtype=...] [code={...}]
01344    // or the long form
01345    //  [type=Read] sourceClass=classname [targetclass=newClassname] [ source="type membername; [type2 membername2]" ]
01346    //      [target="membername3;membername4"] [attributes=... ] [version=...] [checksum=...] [code={...}|functionname]
01347    //
01348    // For example to set HepMC::GenVertex::m_event to _not_ owned the object it is pointing to:
01349    //   HepMC::GenVertex m_event attributes=NotOwner
01350    //
01351    // Semantic of the tags:
01352    //   type : the type of the rule, valid values: Read, ReadRaw, Write, WriteRaw, the default is 'Read'.
01353    //   sourceClass : the name of the class as it is on the rule file
01354    //   targetClass : the name of the class as it is in the current code ; defaults to the value of sourceClass
01355    //   source : the types and names of the data members from the class on file that are needed, the list is separated by semi-colons ';'
01356    //   oldtype: in the short form only, indicates the type on disk of the data member.
01357    //   target : the names of the data members updated by this rule, the list is separated by semi-colons ';'
01358    //   attributes : list of possible qualifiers amongs:
01359    //      Owner, NotOwner
01360    //   version : list of the version of the class layout that this rule applies to.  The syntax can be [1,4,5] or [2-] or [1-3] or [-3]
01361    //   checksum : comma delimited list of the checksums of the class layout that this rule applies to.
01362    //   code={...} : code to be executed for the rule or name of the function implementing it.
01363  
01364    ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
01365    if (! ruleobj->SetFromRule( rule ) ) {
01366       delete ruleobj;
01367       return kFALSE;
01368    }
01369 
01370    TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
01371    if (!cl) {
01372       // Create an empty emulated class for now.
01373       cl = new TClass(ruleobj->GetTargetClass(), 1, 0, 0, -1, -1, kTRUE);
01374       cl->SetBit(TClass::kIsEmulation);
01375    }
01376    ROOT::TSchemaRuleSet* rset = cl->GetSchemaRules( kTRUE );
01377       
01378    if( !rset->AddRule( ruleobj, ROOT::TSchemaRuleSet::kCheckConflict ) ) {
01379       ::Warning( "TClass::AddRule", "The rule for class: \"%s\": version, \"%s\" and data members: \"%s\" has been skipped because it conflicts with one of the other rules.",
01380                 ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString() );
01381       delete ruleobj;
01382       return kFALSE;
01383    }
01384    return kTRUE;
01385 }
01386 
01387 //------------------------------------------------------------------------------
01388 void TClass::AdoptSchemaRules( ROOT::TSchemaRuleSet *rules )
01389 {
01390    // Adopt a new set of Data Model Evolution rules.
01391 
01392    R__LOCKGUARD(gCINTMutex);
01393 
01394    delete fSchemaRules;
01395    fSchemaRules = rules;
01396    fSchemaRules->SetClass( this );
01397 }
01398 
01399 //------------------------------------------------------------------------------
01400 const ROOT::TSchemaRuleSet* TClass::GetSchemaRules() const
01401 {
01402    // Return the set of the schema rules if any.
01403    return fSchemaRules;
01404 }
01405 
01406 //------------------------------------------------------------------------------
01407 ROOT::TSchemaRuleSet* TClass::GetSchemaRules(Bool_t create)
01408 {
01409    // Return the set of the schema rules if any.
01410    // If create is true, create an empty set
01411    if (create && fSchemaRules == 0) {
01412       fSchemaRules = new ROOT::TSchemaRuleSet();
01413       fSchemaRules->SetClass( this );
01414    }
01415    return fSchemaRules;
01416 }
01417 
01418 //______________________________________________________________________________
01419 void TClass::AddImplFile(const char* filename, int line) {
01420 
01421    // Currently reset the implementation file and line.
01422    // In the close future, it will actually add this file and line
01423    // to a "list" of implementation files.
01424 
01425    fImplFileName = filename;
01426    fImplFileLine = line;
01427 }
01428 
01429 //______________________________________________________________________________
01430 void TClass::AddRef(TClassRef *ref)
01431 {
01432    // Register a TClassRef object which points to this TClass object.
01433    // When this TClass object is deleted, 'ref' will be 'Reset'.
01434 
01435    R__LOCKGUARD(gCINTMutex);
01436    if (fRefStart==0) {
01437       fRefStart = ref;
01438    } else {
01439       fRefStart->fPrevious = ref;
01440       ref->fNext = fRefStart;
01441       fRefStart = ref;
01442    }
01443 }
01444 
01445 //______________________________________________________________________________
01446 Int_t TClass::AutoBrowse(TObject *obj, TBrowser *b)
01447 {
01448    // Browse external object inherited from TObject.
01449    // It passes through inheritance tree and calls TBrowser::Add
01450    // in appropriate cases. Static function.
01451 
01452    if (!obj) return 0;
01453 
01454    TAutoInspector insp(b);
01455    obj->ShowMembers(insp);
01456    return insp.fCount;
01457 }
01458 
01459 //______________________________________________________________________________
01460 Int_t TClass::Browse(void *obj, TBrowser *b) const
01461 {
01462    // Browse objects of of the class described by this TClass object.
01463 
01464    if (!obj) return 0;
01465 
01466    TClass *actual = GetActualClass(obj);
01467    if (IsTObject()) {
01468       // Call TObject::Browse.
01469 
01470       if (!fIsOffsetStreamerSet) {
01471          CalculateStreamerOffset();
01472       }
01473       TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
01474       realTObject->Browse(b);
01475       return 1;
01476    } else if (actual != this) {
01477       return actual->Browse(obj, b);
01478    } else if (GetCollectionProxy()) {
01479 
01480       // do something useful.
01481 
01482    } else {
01483       TAutoInspector insp(b);
01484       CallShowMembers(obj,insp,0);
01485       return insp.fCount;
01486    }
01487 
01488    return 0;
01489 }
01490 
01491 //______________________________________________________________________________
01492 void TClass::Browse(TBrowser *b)
01493 {
01494    // This method is called by a browser to get the class information.
01495 
01496    if (!fClassInfo) return;
01497 
01498    if (b) {
01499       if (!fRealData) BuildRealData();
01500 
01501       b->Add(GetListOfDataMembers(), "Data Members");
01502       b->Add(GetListOfRealData(), "Real Data Members");
01503       b->Add(GetListOfMethods(), "Methods");
01504       b->Add(GetListOfBases(), "Base Classes");
01505    }
01506 }
01507 
01508 //______________________________________________________________________________
01509 void TClass::BuildRealData(void* pointer, Bool_t isTransient)
01510 {
01511    // Build a full list of persistent data members.
01512    // Scans the list of all data members in the class itself and also
01513    // in all base classes. For each persistent data member, inserts a
01514    // TRealData object in the list fRealData.
01515    //
01516    // If pointer is not 0, uses the object at pointer
01517    // otherwise creates a temporary object of this class.
01518 
01519    R__LOCKGUARD(gCINTMutex);
01520 
01521    // Only do this once.
01522    if (fRealData) {
01523       return;
01524    }
01525 
01526    // When called via TMapFile (e.g. Update()) make sure that the dictionary
01527    // gets allocated on the heap and not in the mapped file.
01528    TMmallocDescTemp setreset;
01529 
01530    // Handle emulated classes and STL containers specially.
01531    if (!fClassInfo || TClassEdit::IsSTLCont(GetName(), 0) || TClassEdit::IsSTLBitset(GetName())) {
01532       // We are an emulated class or an STL container.
01533       fRealData = new TList;
01534       BuildEmulatedRealData("", 0, this);
01535       return;
01536    }
01537  
01538    void* realDataObject = pointer;
01539 
01540    // If we are not given an object, and the class
01541    // is abstract (so that we cannot make one), give up.
01542    if ((!pointer) && (Property() & kIsAbstract)) {
01543       return;
01544    }
01545 
01546    // If we are not given an object, make one.
01547    // Note: We handle singletons carefully.
01548    if (!realDataObject) {
01549       if (!strcmp(GetName(), "TROOT")) {
01550          realDataObject = gROOT;
01551       } else if (!strcmp(GetName(), "TGWin32")) {
01552          realDataObject = gVirtualX;
01553       } else if (!strcmp(GetName(), "TGQt")) {
01554          realDataObject = gVirtualX;
01555       } else {
01556          realDataObject = New();
01557          // The creation of the object might recursively end up calling BuildRealData
01558          // with a pointer and thus we do not have an infinite recursion but the 
01559          // inner call, set everything up correctly, so let's test again.
01560          // This happens for example with $ROOTSYS/test/Event.cxx where the call
01561          // to ' fWebHistogram.SetAction(this); ' requires the RealData for Event
01562          // to set correctly.
01563          if (fRealData) {
01564             Int_t delta = GetBaseClassOffset(TObject::Class());
01565             if (delta >= 0) {
01566                TObject* tobj = (TObject*) (((char*) realDataObject) + delta);
01567                tobj->SetBit(kZombie); //this info useful in object destructor
01568                delete tobj;
01569                tobj = 0;
01570             } else {
01571                Destructor(realDataObject);
01572                realDataObject = 0;
01573             }
01574             return;
01575          }
01576       }
01577    }
01578 
01579    // The following statement will recursively call
01580    // all the subclasses of this class.
01581    if (realDataObject) {
01582       fRealData = new TList;
01583       TBuildRealData brd(realDataObject, this);
01584 
01585       // CallShowMember will force a call to InheritsFrom, which indirectly
01586       // calls TClass::GetClass.  It forces the loading of new typedefs in 
01587       // case some of them were not yet loaded.
01588       Bool_t wasTransient = brd.TestBit(TRealData::kTransient);
01589       if (isTransient) {
01590          brd.SetBit(TRealData::kTransient);
01591       }
01592       if ( ! CallShowMembers(realDataObject, brd) ) {
01593          if ( brd.TestBit(TRealData::kTransient) ) {
01594             // This is a transient data member, so it is probably fine to not have 
01595             // access to its content.  However let's no mark it as definitively setup,
01596             // since another class might use this class for a persistent data member and
01597             // in this case we really want the error message.
01598             delete fRealData;
01599             fRealData = 0;            
01600          } else {
01601             Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
01602          }
01603       }
01604       if (isTransient && !wasTransient) {
01605          brd.ResetBit(TRealData::kTransient);
01606       }
01607 
01608       // Take this opportunity to build the real data for base classes.
01609       // In case one base class is abstract, it would not be possible later
01610       // to create the list of real data for this abstract class.
01611       TBaseClass* base = 0;
01612       TIter next(GetListOfBases());
01613       while ((base = (TBaseClass*) next())) {
01614          if (base->IsSTLContainer()) {
01615             continue;
01616          }
01617          TClass* c = base->GetClassPointer();
01618          if (c) {
01619             c->BuildRealData(((char*) realDataObject) + base->GetDelta(), isTransient);
01620          }
01621       }
01622    }
01623 
01624    // Clean up any allocated temporary object.
01625    if (!pointer && realDataObject && (realDataObject != gROOT) && (realDataObject != gVirtualX)) {
01626       Int_t delta = GetBaseClassOffset(TObject::Class());
01627       if (delta >= 0) {
01628          TObject* tobj = (TObject*) (((char*) realDataObject) + delta);
01629          tobj->SetBit(kZombie); //this info useful in object destructor
01630          delete tobj;
01631          tobj = 0;
01632       } else {
01633          Destructor(realDataObject);
01634          realDataObject = 0;
01635       }
01636    }
01637 }
01638 
01639 //______________________________________________________________________________
01640 void TClass::BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
01641 {
01642    // Build the list of real data for an emulated class
01643 
01644    R__LOCKGUARD(gCINTMutex);
01645 
01646    TIter next(GetStreamerInfo()->GetElements());
01647    TStreamerElement *element;
01648    while ((element = (TStreamerElement*)next())) {
01649       Int_t etype    = element->GetType();
01650       Long_t eoffset = element->GetOffset();
01651       TClass *cle    = element->GetClassPointer();
01652       if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
01653          //base class are skipped in this loop, they will be added at the end.
01654          continue;
01655       } else if (etype == TVirtualStreamerInfo::kTObject ||
01656                  etype == TVirtualStreamerInfo::kTNamed ||
01657                  etype == TVirtualStreamerInfo::kObject || 
01658                  etype == TVirtualStreamerInfo::kAny) {
01659          //member class
01660          TRealData *rd = new TRealData(Form("%s%s",name,element->GetFullName()),offset+eoffset,0);
01661          if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
01662          cl->GetListOfRealData()->Add(rd);
01663          TString rdname(Form("%s%s.",name,element->GetFullName()));
01664          if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl);
01665       } else {
01666          //others
01667          TString rdname(Form("%s%s",name,element->GetFullName()));
01668          TRealData *rd = new TRealData(rdname,offset+eoffset,0);
01669          if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
01670          cl->GetListOfRealData()->Add(rd);
01671       }
01672       //if (fClassInfo==0 && element->IsBase()) {
01673       //   if (fBase==0) fBase = new TList;
01674       //   TClass *base = element->GetClassPointer();
01675       //   fBase->Add(new TBaseClass(this, cl, eoffset));
01676       //}
01677    }
01678    // The base classes must added last on the list of real data (to help with ambiguous data member names)
01679    next.Reset();
01680    while ((element = (TStreamerElement*)next())) {
01681       Int_t etype    = element->GetType();
01682       if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
01683          //base class
01684          Long_t eoffset = element->GetOffset();
01685          TClass *cle    = element->GetClassPointer();
01686          if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl);
01687       }
01688    }   
01689 }
01690 
01691 
01692 //______________________________________________________________________________
01693 void TClass::CalculateStreamerOffset() const
01694 {
01695    // Calculate the offset between an object of this class to
01696    // its base class TObject. The pointer can be adjusted by
01697    // that offset to access any virtual method of TObject like
01698    // Streamer() and ShowMembers().
01699    R__LOCKGUARD(gCINTMutex);
01700    if (!fIsOffsetStreamerSet && fClassInfo) {
01701       // When called via TMapFile (e.g. Update()) make sure that the dictionary
01702       // gets allocated on the heap and not in the mapped file.
01703       TMmallocDescTemp setreset;
01704       fIsOffsetStreamerSet = kTRUE;
01705       fOffsetStreamer = const_cast<TClass*>(this)->GetBaseClassOffset(TObject::Class());
01706       if (fStreamerType == kTObject) {
01707          fStreamerImpl = &TClass::StreamerTObjectInitialized;
01708       }
01709    }
01710 }
01711 
01712 
01713 //______________________________________________________________________________
01714 Bool_t TClass::CallShowMembers(void* obj, TMemberInspector &insp,
01715                                Int_t isATObject) const
01716 {
01717    // Call ShowMembers() on the obj of this class type, passing insp and parent.
01718    // isATObject is -1 if unknown, 0 if it is not a TObject, and 1 if it is a TObject.
01719    // The function returns whether it was able to call ShowMembers().
01720 
01721    if (fShowMembers) {
01722       // This should always works since 'pointer' should be pointing
01723       // to an object of the actual type of this TClass object.
01724       fShowMembers(obj, insp);
01725       return kTRUE;
01726    } else {
01727 
01728       if (isATObject == -1 && IsLoaded()) {
01729          // Force a call to InheritsFrom. This function indirectly
01730          // calls TClass::GetClass.  It forces the loading of new
01731          // typedefs in case some of them were not yet loaded.
01732          isATObject = (Int_t) (InheritsFrom(TObject::Class()));
01733       }
01734 
01735       if (isATObject == 1) {
01736          // We have access to the TObject interface, so let's use it.
01737          if (!fIsOffsetStreamerSet) {
01738             CalculateStreamerOffset();
01739          }
01740          TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
01741          realTObject->ShowMembers(insp);
01742          return kTRUE;
01743       } else if (fClassInfo) {
01744          
01745          // Always call ShowMembers via the interpreter. A direct call
01746          // like:
01747          //
01748          //      realDataObject->ShowMembers(brd, parent);
01749          //
01750          // will not work if the class derives from TObject but does not
01751          // have TObject as the leftmost base class.
01752          //
01753 
01754          if (!fInterShowMembers) {
01755             CallFunc_t* ism = gCint->CallFunc_Factory();
01756             Long_t offset = 0;
01757             
01758             R__LOCKGUARD2(gCINTMutex);
01759             gCint->CallFunc_SetFuncProto(ism,fClassInfo,"ShowMembers", "TMemberInspector&", &offset);
01760             if (fIsOffsetStreamerSet && offset != fOffsetStreamer) {
01761                Error("CallShowMembers", "Logic Error: offset for Streamer() and ShowMembers() differ!");
01762                fInterShowMembers = 0;
01763                return kFALSE;
01764             }
01765 
01766             fInterShowMembers = ism;
01767          }
01768          if (!gCint->CallFunc_IsValid(fInterShowMembers)) {
01769             if (strcmp(GetName(), "string") == 0) {
01770                // For std::string we know that we do not have a ShowMembers
01771                // function and that it's okay.
01772                return kTRUE;
01773             }
01774             // Let the caller protest:
01775             // Error("CallShowMembers", "Cannot find any ShowMembers function for %s!", GetName());
01776             return kFALSE;
01777          } else {
01778             R__LOCKGUARD2(gCINTMutex);
01779             gCint->CallFunc_ResetArg(fInterShowMembers);
01780             gCint->CallFunc_SetArg(fInterShowMembers,(long) &insp);
01781             void* address = (void*) (((long) obj) + fOffsetStreamer);
01782             gCint->CallFunc_Exec((CallFunc_t*)fInterShowMembers,address);
01783             return kTRUE;
01784          }
01785       } else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
01786          sinfo->CallShowMembers(obj,insp);
01787          return kTRUE;
01788       } // isATObject
01789    } // fShowMembers is set
01790 
01791    return kFALSE;
01792 }
01793 
01794 //______________________________________________________________________________
01795 void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp)
01796 {
01797    // Do a ShowMembers() traversal of all members and base classes' members
01798    // using the reflection information from the interpreter. Works also for
01799    // ionterpreted objects.
01800 
01801    if (!fClassInfo) return;
01802 
01803    DataMemberInfo_t* dmi = gCint->DataMemberInfo_Factory(fClassInfo);
01804 
01805    TString name("*");
01806    while (gCint->DataMemberInfo_Next(dmi)) {
01807       name.Remove(1);
01808       name += gCint->DataMemberInfo_Name(dmi);
01809       if (name == "*G__virtualinfo") continue;
01810 
01811       // skip static members and the member G__virtualinfo inserted by the
01812       // CINT RTTI system
01813       Long_t prop = gCint->DataMemberInfo_Property(dmi) | gCint->DataMemberInfo_TypeProperty(dmi);
01814       if (prop & (G__BIT_ISSTATIC | G__BIT_ISENUM))
01815          continue;
01816       Bool_t isPointer =  gCint->DataMemberInfo_TypeProperty(dmi) & G__BIT_ISPOINTER;
01817 
01818       // Array handling
01819       if (prop & G__BIT_ISARRAY) {
01820          int arrdim = gCint->DataMemberInfo_ArrayDim(dmi);
01821          for (int dim = 0; dim < arrdim; dim++) {
01822             int nelem = gCint->DataMemberInfo_MaxIndex(dmi, dim);
01823             name += TString::Format("[%d]", nelem);
01824          }
01825       }
01826 
01827       const char* inspname = name;
01828       if (!isPointer) {
01829          // no '*':
01830          ++inspname;
01831       }
01832       void* maddr = ((char*)obj) + gCint->DataMemberInfo_Offset(dmi);
01833       insp.Inspect(this, insp.GetParent(), inspname, maddr);
01834 
01835       // If struct member: recurse.
01836       if (!isPointer && !(prop & G__BIT_ISFUNDAMENTAL)) {
01837          std::string clmName(TClassEdit::ShortType(gCint->DataMemberInfo_TypeName(dmi),
01838                                                    TClassEdit::kDropTrailStar) );
01839          TClass* clm = TClass::GetClass(clmName.c_str());
01840          if (clm) {
01841             insp.InspectMember(clm, maddr, name);
01842          }
01843       }
01844    } // while next data member
01845    gCint->DataMemberInfo_Delete(dmi);
01846 
01847    // Iterate over base classes
01848    BaseClassInfo_t* bci = gCint->BaseClassInfo_Factory(fClassInfo);
01849    while (gCint->BaseClassInfo_Next(bci)) {
01850       const char* bclname = gCint->BaseClassInfo_Name(bci);
01851       TClass* bcl = TClass::GetClass(bclname);
01852       void* baddr = ((char*)obj) + gCint->BaseClassInfo_Offset(bci);
01853       if (bcl) {
01854          bcl->CallShowMembers(baddr, insp);
01855       } else {
01856          Warning("InterpretedShowMembers()", "Unknown class %s", bclname);
01857       }
01858    }
01859    gCint->BaseClassInfo_Delete(bci);
01860 }
01861 
01862 //______________________________________________________________________________
01863 Bool_t TClass::CanSplit() const
01864 {
01865    // Return true if the data member of this TClass can be saved separately.
01866 
01867    // Note: add the possibility to set it for the class and the derived class.
01868    // save the info in TVirtualStreamerInfo
01869    // deal with the info in MakeProject
01870    if (fRefProxy)                 return kFALSE;
01871    if (InheritsFrom("TRef"))      return kFALSE;
01872    if (InheritsFrom("TRefArray")) return kFALSE;
01873    if (InheritsFrom("TArray"))    return kFALSE;
01874    if (fName.BeginsWith("TVectorT<")) return kFALSE;
01875    if (fName.BeginsWith("TMatrixT<")) return kFALSE;
01876    if (InheritsFrom("TCollection") && !InheritsFrom("TClonesArray")) return kFALSE;
01877    if (InheritsFrom("TTree"))     return kFALSE;
01878 
01879    // If we do not have a showMembers and we have a streamer,
01880    // we are in the case of class that can never be split since it is
01881    // opaque to us.
01882    if (GetShowMembersWrapper()==0 && GetStreamer()!=0) {
01883 
01884       // the exception are the STL containers.
01885       if (GetCollectionProxy()==0) {
01886          // We do NOT have a collection.  The class is true opaque
01887          return kFALSE;
01888 
01889       } else {
01890 
01891          // However we do not split collections of collections
01892          // nor collections of strings
01893          // nor collections of pointers
01894          // (actually we __could__ split collection of pointers to non-virtual class,
01895          //  but we dont for now).
01896 
01897          if (GetCollectionProxy()->HasPointers()) return kFALSE;
01898 
01899          TClass *valueClass = GetCollectionProxy()->GetValueClass();
01900          if (valueClass == 0) return kFALSE;
01901          if (valueClass==TString::Class() || valueClass==TClass::GetClass("string"))
01902             return kFALSE;
01903          if (!valueClass->CanSplit()) return kFALSE;
01904          if (valueClass->GetCollectionProxy() != 0) return kFALSE;
01905 
01906          Int_t stl = -TClassEdit::IsSTLCont(GetName(), 0);
01907          if ((stl==TClassEdit::kMap || stl==TClassEdit::kMultiMap)
01908               && valueClass->GetClassInfo()==0)
01909          {
01910             return kFALSE;
01911          }
01912       }
01913    }
01914    
01915    if (Size()==1) {
01916       // 'Empty' class there is nothing to split!.
01917       return kFALSE;
01918    }
01919 
01920    TClass *ncThis = const_cast<TClass*>(this);
01921    TIter nextb(ncThis->GetListOfBases());
01922    TBaseClass *base;
01923    while((base = (TBaseClass*)nextb())) {
01924       if (!TClass::GetClass(base->GetName())) return kFALSE;
01925    }
01926 
01927    return kTRUE;
01928 }
01929 
01930 //______________________________________________________________________________
01931 TObject *TClass::Clone(const char *new_name) const
01932 {
01933    // Create a Clone of this TClass object using a different name but using the same 'dictionary'.
01934    // This effectively creates a hard alias for the class name.
01935 
01936    if (new_name == 0 || new_name[0]=='\0' || fName == new_name) {
01937       Error("Clone","The name of the class must be changed when cloning a TClass object.");
01938       return 0;
01939    }
01940    // Temporarily remove the original from the list of classes.
01941    TClass::RemoveClass(const_cast<TClass*>(this));
01942  
01943    TClass *copy;
01944    if (fTypeInfo) {
01945       copy = new TClass(GetName(),
01946                         fClassVersion,
01947                         *fTypeInfo,
01948                         new TIsAProxy(*fTypeInfo),
01949                         fShowMembers,
01950                         GetDeclFileName(),
01951                         GetImplFileName(),
01952                         GetDeclFileLine(),
01953                         GetImplFileLine());
01954    } else {
01955       copy = new TClass(GetName(),
01956                         fClassVersion,
01957                         GetDeclFileName(),
01958                         GetImplFileName(),
01959                         GetDeclFileLine(),
01960                         GetImplFileLine());
01961       copy->fShowMembers = fShowMembers;
01962    }
01963    // Remove the copy before renaming it
01964    TClass::RemoveClass(copy);
01965    copy->SetName(new_name);
01966    TClass::AddClass(copy);
01967 
01968    copy->SetNew(fNew);
01969    copy->SetNewArray(fNewArray);
01970    copy->SetDelete(fDelete);
01971    copy->SetDeleteArray(fDeleteArray);
01972    copy->SetDestructor(fDestructor);
01973    copy->SetDirectoryAutoAdd(fDirAutoAdd);
01974    copy->fStreamerFunc = fStreamerFunc;
01975    if (fStreamer) {
01976       copy->AdoptStreamer(fStreamer->Generate());
01977    }
01978    // If IsZombie is true, something went wrong and we will not be
01979    // able to properly copy the collection proxy
01980    if (fCollectionProxy && !copy->IsZombie()) {
01981       copy->CopyCollectionProxy(*fCollectionProxy);
01982    }
01983    copy->SetClassSize(fSizeof);
01984    if (fRefProxy) {
01985       copy->AdoptReferenceProxy( fRefProxy->Clone() );
01986    }
01987    TClass::AddClass(const_cast<TClass*>(this));
01988    return copy;
01989 }   
01990 
01991 //______________________________________________________________________________
01992 void TClass::CopyCollectionProxy(const TVirtualCollectionProxy &orig)
01993 {
01994    // Copy the argument.
01995 
01996 //     // This code was used too quickly test the STL Emulation layer
01997 //    Int_t k = TClassEdit::IsSTLCont(GetName());
01998 //    if (k==1||k==-1) return;
01999 
02000    delete fCollectionProxy;
02001    fCollectionProxy = orig.Generate();
02002 }
02003 
02004 
02005 //______________________________________________________________________________
02006 void TClass::Draw(Option_t *option)
02007 {
02008    // Draw detailed class inheritance structure.
02009    // If a class B inherits from a class A, the description of B is drawn
02010    // on the right side of the description of A.
02011    // Member functions overridden by B are shown in class A with a blue line
02012    // erasing the corresponding member function
02013 
02014    if (!fClassInfo) return;
02015 
02016    TVirtualPad *padsav = gPad;
02017 
02018    // Should we create a new canvas?
02019    TString opt=option;
02020    if (!padsav || !opt.Contains("same")) {
02021       TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
02022       if (!padclass) {
02023          gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
02024       } else {
02025          padclass->cd();
02026       }
02027    }
02028 
02029    if (gPad) gPad->DrawClassObject(this,option);
02030 
02031    if (padsav) padsav->cd();
02032 }
02033 
02034 //______________________________________________________________________________
02035 void TClass::Dump(void *obj) const
02036 {
02037    // Dump contents of object on stdout.
02038    // Using the information in the object dictionary
02039    // each data member is interpreted.
02040    // If a data member is a pointer, the pointer value is printed
02041    // 'obj' is assume to point to an object of the class describe by this TClass
02042    //
02043    // The following output is the Dump of a TArrow object:
02044    //   fAngle                   0           Arrow opening angle (degrees)
02045    //   fArrowSize               0.2         Arrow Size
02046    //   fOption.*fData
02047    //   fX1                      0.1         X of 1st point
02048    //   fY1                      0.15        Y of 1st point
02049    //   fX2                      0.67        X of 2nd point
02050    //   fY2                      0.83        Y of 2nd point
02051    //   fUniqueID                0           object unique identifier
02052    //   fBits                    50331648    bit field status word
02053    //   fLineColor               1           line color
02054    //   fLineStyle               1           line style
02055    //   fLineWidth               1           line width
02056    //   fFillColor               19          fill area color
02057    //   fFillStyle               1001        fill area style
02058 
02059    Printf("==>Dumping object at:%lx, class=%s\n",(Long_t)obj,GetName());
02060    TDumpMembers dm;
02061    if (!CallShowMembers(obj, dm)) {
02062       Info("Dump", "No ShowMembers function, dumping disabled");
02063    }
02064 }
02065 
02066 //______________________________________________________________________________
02067 char *TClass::EscapeChars(const char *text) const
02068 {
02069    // Introduce an escape character (@) in front of a special chars.
02070    // You need to use the result immediately before it is being overwritten.
02071 
02072    static char name[128];
02073    Int_t nch = strlen(text);
02074    if (nch > 127) nch = 127;
02075    Int_t icur = -1;
02076    for (Int_t i = 0; i < nch; i++) {
02077       icur++;
02078       if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
02079           text[i] == ']'  || text[i] == '&' || text[i] == '#' ||
02080           text[i] == '!'  || text[i] == '^' || text[i] == '<' ||
02081           text[i] == '?'  || text[i] == '>') {
02082          name[icur] = '@';
02083          icur++;
02084       }
02085       name[icur] = text[i];
02086    }
02087    name[icur+1] = 0;
02088    return name;
02089 }
02090 
02091 //______________________________________________________________________________
02092 TClass *TClass::GetActualClass(const void *object) const
02093 {
02094    // Return a pointer the the real class of the object.
02095    // This is equivalent to object->IsA() when the class has a ClassDef.
02096    // It is REQUIRED that object is coming from a proper pointer to the
02097    // class represented by 'this'.
02098    // Example: Special case:
02099    //    class MyClass : public AnotherClass, public TObject
02100    // then on return, one must do:
02101    //    TObject *obj = (TObject*)((void*)myobject)directory->Get("some object of MyClass");
02102    //    MyClass::Class()->GetActualClass(obj); // this would be wrong!!!
02103    // Also if the class represented by 'this' and NONE of its parents classes
02104    // have a virtual ptr table, the result will be 'this' and NOT the actual
02105    // class.
02106 
02107    if (object==0) return (TClass*)this;
02108    if (!IsLoaded()) {
02109       TVirtualStreamerInfo* sinfo = GetStreamerInfo();
02110       if (sinfo) {
02111          return sinfo->GetActualClass(object);
02112       }
02113       return (TClass*)this;
02114    }
02115    if (fIsA) {
02116       return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
02117    } else if (fGlobalIsA) {
02118       return fGlobalIsA(this,object);
02119    } else {
02120       //Always call IsA via the interpreter. A direct call like
02121       //      object->IsA(brd, parent);
02122       //will not work if the class derives from TObject but not as primary
02123       //inheritance.
02124       if (fIsAMethod==0) {
02125          fIsAMethod = new TMethodCall((TClass*)this, "IsA", "");
02126 
02127          if (!fIsAMethod->GetMethod()) {
02128             delete fIsAMethod;
02129             fIsAMethod = 0;
02130             Error("IsA","Can not find any IsA function for %s!",GetName());
02131             return (TClass*)this;
02132          }
02133 
02134       }
02135       char * char_result = 0;
02136       fIsAMethod->Execute((void*)object, &char_result);
02137       return (TClass*)char_result;
02138    }
02139 }
02140 
02141 //______________________________________________________________________________
02142 TClass *TClass::GetBaseClass(const char *classname)
02143 {
02144    // Return pointer to the base class "classname". Returns 0 in case
02145    // "classname" is not a base class. Takes care of multiple inheritance.
02146 
02147    // check if class name itself is equal to classname
02148    if (strcmp(GetName(), classname) == 0) return this;
02149 
02150    if (!fClassInfo) return 0;
02151 
02152    TObjLink *lnk = GetListOfBases() ? fBase->FirstLink() : 0;
02153 
02154    // otherwise look at inheritance tree
02155    while (lnk) {
02156       TClass     *c, *c1;
02157       TBaseClass *base = (TBaseClass*) lnk->GetObject();
02158       c = base->GetClassPointer();
02159       if (c) {
02160          if (strcmp(c->GetName(), classname) == 0) return c;
02161          c1 = c->GetBaseClass(classname);
02162          if (c1) return c1;
02163       }
02164       lnk = lnk->Next();
02165    }
02166    return 0;
02167 }
02168 
02169 //______________________________________________________________________________
02170 TClass *TClass::GetBaseClass(const TClass *cl)
02171 {
02172    // Return pointer to the base class "cl". Returns 0 in case "cl"
02173    // is not a base class. Takes care of multiple inheritance.
02174 
02175    // check if class name itself is equal to classname
02176    if (cl == this) return this;
02177 
02178    if (!fClassInfo) return 0;
02179 
02180    TObjLink *lnk = GetListOfBases() ? fBase->FirstLink() : 0;
02181 
02182    // otherwise look at inheritance tree
02183    while (lnk) {
02184       TClass     *c, *c1;
02185       TBaseClass *base = (TBaseClass*) lnk->GetObject();
02186       c = base->GetClassPointer();
02187       if (c) {
02188          if (cl == c) return c;
02189          c1 = c->GetBaseClass(cl);
02190          if (c1) return c1;
02191       }
02192       lnk = lnk->Next();
02193    }
02194    return 0;
02195 }
02196 
02197 //______________________________________________________________________________
02198 Int_t TClass::GetBaseClassOffsetRecurse(const TClass *cl)
02199 {
02200    // Return data member offset to the base class "cl".
02201    // Returns -1 in case "cl" is not a base class.
02202    // Returns -2 if cl is a base class, but we can't find the offset
02203    // because it's virtual.
02204    // Takes care of multiple inheritance.
02205 
02206    // check if class name itself is equal to classname
02207    if (cl == this) return 0;
02208 
02209    if (!fClassInfo) {
02210       TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
02211       if (!sinfo) return -1;
02212       TStreamerElement *element;
02213       Int_t offset = 0;
02214 
02215       TObjArray &elems = *(sinfo->GetElements());
02216       Int_t size = elems.GetLast()+1;
02217       for(Int_t i=0; i<size; i++) {
02218          element = (TStreamerElement*)elems[i];
02219          if (element->IsA() == TStreamerBase::Class()) {
02220             TStreamerBase *base = (TStreamerBase*)element;
02221             TClass *baseclass = base->GetClassPointer();
02222             if (!baseclass) return -1;
02223             Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
02224             if (subOffset == -2) return -2;
02225             if (subOffset != -1) return offset+subOffset;
02226             offset += baseclass->Size();
02227          }
02228       }
02229       return -1;
02230    }
02231 
02232    TClass     *c;
02233    Int_t      off;
02234    TBaseClass *inh;
02235    TObjLink *lnk = 0;
02236    if (fBase==0) lnk = GetListOfBases()->FirstLink();
02237    else lnk = fBase->FirstLink();
02238 
02239    // otherwise look at inheritance tree
02240    while (lnk) {
02241       inh = (TBaseClass *)lnk->GetObject();
02242       //use option load=kFALSE to avoid a warning like:
02243       //"Warning in <TClass::TClass>: no dictionary for class TRefCnt is available"
02244       //We can not afford to not have the class if it exist, so we
02245       //use kTRUE.
02246       c = inh->GetClassPointer(kTRUE); // kFALSE);
02247       if (c) {
02248          if (cl == c) {
02249             if ((inh->Property() & G__BIT_ISVIRTUALBASE) != 0)
02250                return -2;
02251             return inh->GetDelta();
02252          }
02253          off = c->GetBaseClassOffsetRecurse(cl);
02254          if (off == -2) return -2;
02255          if (off != -1) return off + inh->GetDelta();
02256       }
02257       lnk = lnk->Next();
02258    }
02259    return -1;
02260 }
02261 
02262 //______________________________________________________________________________
02263 Int_t TClass::GetBaseClassOffset(const TClass *cl)
02264 {
02265    // Return data member offset to the base class "cl".
02266    // Returns -1 in case "cl" is not a base class.
02267    // Takes care of multiple inheritance.
02268 
02269    Int_t offset = GetBaseClassOffsetRecurse (cl);
02270    if (offset == -2) {
02271       // Can we get the offset from CINT?
02272       if (cl->GetClassInfo()) {
02273          R__LOCKGUARD(gCINTMutex);
02274          Long_t base_tagnum = gCint->ClassInfo_Tagnum(cl->GetClassInfo());
02275          BaseClassInfo_t *t = gCint->BaseClassInfo_Factory(GetClassInfo());
02276          while (gCint->BaseClassInfo_Next(t,0)) {
02277             if (gCint->BaseClassInfo_Tagnum(t) == base_tagnum) {
02278                if ((gCint->BaseClassInfo_Property(t) & G__BIT_ISVIRTUALBASE) != 0) {
02279                   break;
02280                }
02281                int off = gCint->BaseClassInfo_Offset(t);
02282                gCint->BaseClassInfo_Delete(t);
02283                return off;
02284             }
02285          }
02286          gCint->BaseClassInfo_Delete(t);
02287       }
02288       offset = -1;
02289    }
02290    return offset;
02291 }
02292 
02293 //______________________________________________________________________________
02294 TClass *TClass::GetBaseDataMember(const char *datamember)
02295 {
02296    // Return pointer to (base) class that contains datamember.
02297 
02298    if (!fClassInfo) return 0;
02299 
02300    // Check if data member exists in class itself
02301    TDataMember *dm = GetDataMember(datamember);
02302    if (dm) return this;
02303 
02304    // if datamember not found in class, search in next base classes
02305    TBaseClass *inh;
02306    TIter       next(GetListOfBases());
02307    while ((inh = (TBaseClass *) next())) {
02308       TClass *c = inh->GetClassPointer();
02309       if (c) {
02310          TClass *cdm = c->GetBaseDataMember(datamember);
02311          if (cdm) return cdm;
02312       }
02313    }
02314 
02315    return 0;
02316 }
02317 
02318 namespace {
02319    // A local Helper class used to keep 2 pointer (the collection proxy
02320    // and the class streamer) in the thread local storage.
02321 
02322    struct TClassLocalStorage {
02323       TClassLocalStorage() : fCollectionProxy(0), fStreamer(0) {};
02324 
02325       TVirtualCollectionProxy *fCollectionProxy;
02326       TClassStreamer          *fStreamer;
02327 
02328       static TClassLocalStorage *GetStorage(const TClass *cl) {
02329          void **thread_ptr = (*gThreadTsd)(0,1);
02330          if (thread_ptr) {
02331             if (*thread_ptr==0) *thread_ptr = new TExMap();
02332             TExMap *lmap = (TExMap*)(*thread_ptr);
02333             ULong_t hash = TString::Hash(&cl, sizeof(void*));
02334             ULong_t local = 0;
02335             UInt_t slot;
02336             if ((local = (ULong_t)lmap->GetValue(hash, (Long_t)cl, slot)) != 0) {
02337             } else {
02338                local = (ULong_t) new TClassLocalStorage();
02339                lmap->AddAt(slot, hash, (Long_t)cl, local);
02340             }
02341             return (TClassLocalStorage*)local;
02342          }
02343          return 0;
02344       }
02345    };
02346 }
02347 
02348 //______________________________________________________________________________
02349 TVirtualCollectionProxy *TClass::GetCollectionProxy() const
02350 {
02351    // Return the proxy describinb the collection (if any).
02352 
02353    if (gThreadTsd && fCollectionProxy) {
02354       TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
02355       if (local == 0) return fCollectionProxy;
02356       if (local->fCollectionProxy==0) local->fCollectionProxy = fCollectionProxy->Generate();
02357       return local->fCollectionProxy;
02358    }
02359    return fCollectionProxy;
02360 }
02361 
02362 //______________________________________________________________________________
02363 TClassStreamer *TClass::GetStreamer() const
02364 {
02365    // Return the Streamer Class allowing streaming (if any).
02366 
02367    if (gThreadTsd && fStreamer) {
02368       TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
02369       if (local==0) return fStreamer;
02370       if (local->fStreamer==0) {
02371          local->fStreamer = fStreamer->Generate();
02372          const type_info &orig = ( typeid(*fStreamer) );
02373          const type_info &copy = ( typeid(*local->fStreamer) );
02374          if (strcmp(orig.name(),copy.name())!=0) {
02375             Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s\n",GetName(),orig.name(),copy.name());
02376          }
02377       }
02378       return local->fStreamer;
02379    }
02380    return fStreamer;
02381 }
02382 //______________________________________________________________________________
02383 ClassStreamerFunc_t TClass::GetStreamerFunc() const
02384 {
02385    // Get a wrapper/accessor function around this class custom streamer (member function).
02386 
02387    return fStreamerFunc;
02388 }
02389 
02390 //______________________________________________________________________________
02391 TVirtualIsAProxy* TClass::GetIsAProxy() const
02392 {
02393    // Return the proxy implementing the IsA functionality.
02394 
02395    return fIsA;
02396 }
02397 
02398 
02399 //______________________________________________________________________________
02400 TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
02401 {
02402    // Static method returning pointer to TClass of the specified class name.
02403    // If load is true an attempt is made to obtain the class by loading
02404    // the appropriate shared library (directed by the rootmap file).
02405    // If silent is 'true', do not warn about missing dictionary for the class.
02406    // (typically used for class that are used only for transient members)
02407    // Returns 0 in case class is not found.
02408 
02409    if (!name || !strlen(name)) return 0;
02410    if (!gROOT->GetListOfClasses())    return 0;
02411 
02412    TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
02413    
02414    TClassEdit::TSplitType splitname( name, TClassEdit::kLong64 );
02415 
02416    if (!cl) {
02417       // Try the name where we strip out the STL default template arguments
02418       std::string resolvedName;
02419       splitname.ShortType(resolvedName, TClassEdit::kDropStlDefault);
02420       if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
02421       if (!cl) {
02422          // Attempt to resolve typedefs
02423          resolvedName = TClassEdit::ResolveTypedef(resolvedName.c_str(),kTRUE);
02424          if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
02425       }
02426       if (!cl) {
02427          // Try with Long64_t
02428          resolvedName = TClassEdit::GetLong64_Name(resolvedName);
02429          if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
02430       }         
02431    }
02432 
02433    if (cl) {
02434 
02435       if (cl->IsLoaded()) return cl;
02436 
02437       //we may pass here in case of a dummy class created by TVirtualStreamerInfo
02438       load = kTRUE;
02439 
02440       if (splitname.IsSTLCont()) {
02441 
02442          const char * itypename = gCint->GetInterpreterTypeName(name);
02443          if (itypename) {
02444             std::string altname( TClassEdit::ShortType(itypename, TClassEdit::kDropStlDefault) );
02445             if (altname != name) {
02446 
02447                // Remove the existing (soon to be invalid) TClass object to
02448                // avoid an infinite recursion.
02449                gROOT->GetListOfClasses()->Remove(cl);
02450                TClass *newcl = GetClass(altname.c_str(),load);
02451                
02452                // since the name are different but we got a TClass, we assume
02453                // we need to replace and delete this class.
02454                assert(newcl!=cl);
02455                newcl->ForceReload(cl);
02456                return newcl;
02457             }
02458          }
02459       }
02460 
02461    } else {
02462 
02463       if (!splitname.IsSTLCont()) {
02464 
02465          // If the name is actually an STL container we prefer the
02466          // short name rather than the true name (at least) in
02467          // a first try!
02468 
02469          TDataType *objType = gROOT->GetType(name, load);
02470          if (objType) {
02471             const char *typdfName = objType->GetTypeName();
02472             if (typdfName && strcmp(typdfName, name)) {
02473                cl = TClass::GetClass(typdfName, load);
02474                return cl;
02475             }
02476          }
02477 
02478       } else {
02479 
02480          cl = gROOT->FindSTLClass(name,kFALSE,silent);
02481 
02482          if (cl) {
02483             if (cl->IsLoaded()) return cl;
02484 
02485             //we may pass here in case of a dummy class created by TVirtualStreamerInfo
02486             //return TClass::GetClass(cl->GetName(),kTRUE);
02487             return TClass::GetClass(cl->GetName(),kTRUE);
02488          }
02489 
02490       }
02491 
02492    }
02493 
02494    if (!load) return 0;
02495 
02496    TClass *loadedcl = 0;
02497    if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
02498    else    loadedcl = gROOT->LoadClass(name,silent);
02499 
02500    if (loadedcl) return loadedcl;
02501 
02502    if (cl) return cl;  // If we found the class but we already have a dummy class use it.
02503 
02504    static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
02505    if (strcmp(name,full_string_name)==0
02506       || ( strncmp(name,"std::",5)==0 && ((strcmp(name+5,"string")==0)||(strcmp(name+5,full_string_name)==0)))) {
02507       return TClass::GetClass("string");
02508    }
02509    if (splitname.IsSTLCont()) {
02510 
02511       return gROOT->FindSTLClass(name,kTRUE,silent);
02512 
02513    } else if ( strncmp(name,"std::",5)==0 ) {
02514 
02515       return TClass::GetClass(name+5,load);
02516 
02517    } else if ( strstr(name,"std::") != 0 ) {
02518 
02519       // Let's try without the std:: in the template parameters.
02520       TString rname( TClassEdit::ResolveTypedef(name,kTRUE) );
02521       if (rname != name) {
02522          return TClass::GetClass( rname, load );
02523       }
02524    }
02525 
02526    if (!strcmp(name, "long long")||!strcmp(name,"unsigned long long"))
02527       return 0; // reject long longs
02528 
02529    //last attempt. Look in CINT list of all (compiled+interpreted) classes
02530 
02531    // CheckClassInfo might modify the content of its parameter if it is
02532    // a template and has extra or missing space (eg. one<two<tree>> becomes
02533    // one<two<three> >
02534    Int_t nch = strlen(name)*2;
02535    char *modifiable_name = new char[nch];
02536    strlcpy(modifiable_name,name,nch);
02537    if (gInterpreter->CheckClassInfo(modifiable_name)) {
02538       const char *altname = gInterpreter->GetInterpreterTypeName(modifiable_name,kTRUE);
02539       if (strcmp(altname,name)!=0) {
02540          // altname now contains the full name of the class including a possible
02541          // namespace if there has been a using namespace statement.
02542          delete [] modifiable_name;
02543          return GetClass(altname,load);
02544       }
02545       TClass *ncl = new TClass(name, 1, 0, 0, -1, -1, silent);
02546       if (!ncl->IsZombie()) {
02547          delete [] modifiable_name;
02548          return ncl;
02549       }
02550       delete ncl;
02551    }
02552    delete [] modifiable_name;
02553    return 0;
02554 }
02555 
02556 //______________________________________________________________________________
02557 THashTable *TClass::GetClassShortTypedefHash() {
02558    // Return the class' names massaged with TClassEdit::ShortType with kDropStlDefault.
02559    return fgClassShortTypedefHash;
02560 }
02561 
02562 //______________________________________________________________________________
02563 TClass *TClass::GetClass(const type_info& typeinfo, Bool_t load, Bool_t /* silent */)
02564 {
02565    // Return pointer to class with name.
02566 
02567    if (!gROOT->GetListOfClasses())    return 0;
02568 
02569 //printf("TClass::GetClass called, typeinfo.name=%s\n",typeinfo.name());
02570    TClass* cl = fgIdMap->Find(typeinfo.name());
02571 
02572    if (cl) {
02573       if (cl->IsLoaded()) return cl;
02574       //we may pass here in case of a dummy class created by TVirtualStreamerInfo
02575       load = kTRUE;
02576    } else {
02577      // Note we might need support for typedefs and simple types!
02578 
02579      //      TDataType *objType = GetType(name, load);
02580      //if (objType) {
02581      //    const char *typdfName = objType->GetTypeName();
02582      //    if (typdfName && strcmp(typdfName, name)) {
02583      //       cl = GetClass(typdfName, load);
02584      //       return cl;
02585      //    }
02586      // }
02587    }
02588 
02589    if (!load) return 0;
02590 
02591    VoidFuncPtr_t dict = TClassTable::GetDict(typeinfo);
02592    if (dict) {
02593       (dict)();
02594       cl = GetClass(typeinfo,kFALSE);
02595       if (cl) cl->PostLoadCheck();
02596       return cl;
02597    }
02598    if (cl) return cl;
02599 
02600    TIter next(gROOT->GetListOfClassGenerators());
02601    TClassGenerator *gen;
02602    while( (gen = (TClassGenerator*) next()) ) {
02603       cl = gen->GetClass(typeinfo,load);
02604       if (cl) {
02605          cl->PostLoadCheck();
02606          return cl;
02607       }
02608    }
02609 
02610    //last attempt. Look in CINT list of all (compiled+interpreted) classes
02611    //   if (gInterpreter->CheckClassInfo(name)) {
02612    //      TClass *ncl = new TClass(name, 1, 0, 0, 0, -1, -1);
02613    //      if (!ncl->IsZombie()) return ncl;
02614    //      delete ncl;
02615    //   }
02616    return 0;
02617 }
02618 
02619 //______________________________________________________________________________
02620 VoidFuncPtr_t  TClass::GetDict (const char *cname)
02621 {
02622    // Return a pointer to the dictionary loading function generated by
02623    // rootcint
02624 
02625    return TClassTable::GetDict(cname);
02626 }
02627 
02628 //______________________________________________________________________________
02629 VoidFuncPtr_t  TClass::GetDict (const type_info& info)
02630 {
02631    // Return a pointer to the dictionary loading function generated by
02632    // rootcint
02633 
02634    return TClassTable::GetDict(info);
02635 }
02636 
02637 //______________________________________________________________________________
02638 TDataMember *TClass::GetDataMember(const char *datamember) const
02639 {
02640    // Return pointer to datamember object with name "datamember".
02641 
02642    if (!fClassInfo) return 0;
02643 
02644    // Strip off leading *'s and trailing [
02645    const Int_t size_buffer = 256;
02646    char memb[size_buffer];
02647    char *s = (char*)datamember;
02648    while (*s == '*') s++;
02649 
02650    size_t len = strlen(s);
02651    if (len > size_buffer - 2)
02652       len = size_buffer - 2;
02653    strncpy(memb, s, len);
02654    memb[len] = 0;
02655 
02656    if ((s = strchr(memb, '['))) {
02657       *s = 0;
02658       len = strlen(memb);
02659    }
02660 
02661    TDataMember *dm;
02662    TIter   next(((TClass*)this)->GetListOfDataMembers());
02663 
02664    while ((dm = (TDataMember *) next()))
02665       if (len >= size_buffer - 2) {
02666          if (strncmp(memb, dm->GetName(), len) == 0)
02667             return dm;
02668       } else
02669          if (strcmp(memb, dm->GetName()) == 0)
02670             return dm;
02671    return 0;
02672 }
02673 
02674 //______________________________________________________________________________
02675 Long_t TClass::GetDataMemberOffset(const char *name) const
02676 {
02677    // return offset for member name. name can be a data member in
02678    // the class itself, one of its base classes, or one member in
02679    // one of the aggregated classes.
02680    //
02681    // In case of an emulated class, the list of emulated TRealData is built
02682 
02683    TRealData *rd = GetRealData(name);
02684    if (rd) return rd->GetThisOffset();
02685    if (strchr(name,'[')==0) {
02686       // If this is a simple name there is a chance to find it in the
02687       // StreamerInfo even if we did not find it in the RealData.
02688       // For example an array name would be fArray[3] in RealData but
02689       // just fArray in the streamerInfo.
02690       TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
02691       if (info) {
02692          return info->GetOffset(name);
02693       }
02694    }
02695    return 0;
02696 }
02697 
02698 //______________________________________________________________________________
02699 TRealData* TClass::GetRealData(const char* name) const
02700 {
02701    // -- Return pointer to TRealData element with name "name".
02702    //
02703    // Name can be a data member in the class itself,
02704    // one of its base classes, or a member in
02705    // one of the aggregated classes.
02706    //
02707    // In case of an emulated class, the list of emulated TRealData is built.
02708    //
02709 
02710    if (!fRealData) {
02711       const_cast<TClass*>(this)->BuildRealData();
02712    }
02713 
02714    if (!fRealData) {
02715       return 0;
02716    }
02717 
02718    if (!name) {
02719       return 0;
02720    }
02721 
02722    // First try just the whole name.
02723    TRealData* rd = (TRealData*) fRealData->FindObject(name);
02724    if (rd) {
02725       return rd;
02726    }
02727 
02728    std::string givenName(name);
02729 
02730    // Try ignoring the array dimensions.
02731    std::string::size_type firstBracket = givenName.find_first_of("[");
02732    if (firstBracket != std::string::npos) {
02733       // -- We are looking for an array data member.
02734       std::string nameNoDim(givenName.substr(0, firstBracket));
02735       TObjLink* lnk = fRealData->FirstLink();
02736       while (lnk) {
02737          TObject* obj = lnk->GetObject();
02738          std::string objName(obj->GetName());
02739          std::string::size_type pos = objName.find_first_of("[");
02740          // Only match arrays to arrays for now.
02741          if (pos != std::string::npos) {
02742             objName.erase(pos);
02743             if (objName == nameNoDim) {
02744                return static_cast<TRealData*>(obj);
02745             }
02746          }
02747          lnk = lnk->Next();
02748       }
02749    }
02750 
02751    // Now try it as a pointer.
02752    std::ostringstream ptrname;
02753    ptrname << "*" << givenName;
02754    rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
02755    if (rd) {
02756       return rd;
02757    }
02758 
02759    // Check for a dot in the name.
02760    std::string::size_type firstDot = givenName.find_first_of(".");
02761    if (firstDot == std::string::npos) {
02762       // -- Not found, a simple name, all done.
02763       return 0;
02764    }
02765 
02766    //
02767    //  At this point the name has a dot in it, so it is the name
02768    //  of some contained sub-object.
02769    //
02770 
02771    // May be a pointer like in TH1: fXaxis.fLabels (in TRealdata is named fXaxis.*fLabels)
02772    std::string::size_type lastDot = givenName.find_last_of(".");
02773    std::ostringstream starname;
02774    starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
02775    rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
02776    if (rd) {
02777       return rd;
02778    }
02779 
02780    // Strip the first component, it may be the name of
02781    // the branch (old TBranchElement code), and try again.
02782    std::string firstDotName(givenName.substr(firstDot + 1));
02783 
02784    // New attempt starting after the first "." if any,
02785    // this allows for the case that the first component
02786    // may have been a branch name (for TBranchElement).
02787    rd = (TRealData*) fRealData->FindObject(firstDotName.c_str());
02788    if (rd) {
02789       return rd;
02790    }
02791 
02792    // New attempt starting after the first "." if any,
02793    // but this time try ignoring the array dimensions.
02794    // Again, we are allowing for the case that the first
02795    // component may have been a branch name (for TBranchElement).
02796    std::string::size_type firstDotBracket = firstDotName.find_first_of("[");
02797    if (firstDotBracket != std::string::npos) {
02798       // -- We are looking for an array data member.
02799       std::string nameNoDim(firstDotName.substr(0, firstDotBracket));
02800       TObjLink* lnk = fRealData->FirstLink();
02801       while (lnk) {
02802          TObject* obj = lnk->GetObject();
02803          std::string objName(obj->GetName());
02804          std::string::size_type pos = objName.find_first_of("[");
02805          // Only match arrays to arrays for now.
02806          if (pos != std::string::npos) {
02807             objName.erase(pos);
02808             if (objName == nameNoDim) {
02809                return static_cast<TRealData*>(obj);
02810             }
02811          }
02812          lnk = lnk->Next();
02813       }
02814    }
02815 
02816    // New attempt starting after the first "." if any,
02817    // but this time check for a pointer type.  Again, we
02818    // are allowing for the case that the first component
02819    // may have been a branch name (for TBranchElement).
02820    ptrname.str("");
02821    ptrname << "*" << firstDotName;
02822    rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
02823    if (rd) {
02824       return rd;
02825    }
02826 
02827    // Last attempt in case a member has been changed from
02828    // a static array to a pointer, for example the member
02829    // was arr[20] and is now *arr.
02830    //
02831    // Note: In principle, one could also take into account
02832    // the opposite situation where a member like *arr has
02833    // been converted to arr[20].
02834    //
02835    // FIXME: What about checking after the first dot as well?
02836    //
02837    std::string::size_type bracket = starname.str().find_first_of("[");
02838    if (bracket == std::string::npos) {
02839       return 0;
02840    }
02841    rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
02842    if (rd) {
02843       return rd;
02844    }
02845 
02846    // Not found;
02847    return 0;
02848 }
02849 
02850 //______________________________________________________________________________
02851 const char *TClass::GetSharedLibs()
02852 {
02853    // Get the list of shared libraries containing the code for class cls.
02854    // The first library in the list is the one containing the class, the
02855    // others are the libraries the first one depends on. Returns 0
02856    // in case the library is not found.
02857 
02858    if (!gInterpreter) return 0;
02859 
02860    if (fSharedLibs.IsNull())
02861       fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
02862 
02863    return !fSharedLibs.IsNull() ? fSharedLibs.Data() : 0;
02864 }
02865 
02866 //______________________________________________________________________________
02867 TList *TClass::GetListOfBases()
02868 {
02869    // Return list containing the TBaseClass(es) of a class.
02870 
02871    if (!fBase) {
02872       if (!fClassInfo) return 0;
02873 
02874       if (!gInterpreter)
02875          Fatal("GetListOfBases", "gInterpreter not initialized");
02876 
02877       gInterpreter->CreateListOfBaseClasses(this);
02878    }
02879    return fBase;
02880 }
02881 
02882 //______________________________________________________________________________
02883 TList *TClass::GetListOfDataMembers()
02884 {
02885    // Return list containing the TDataMembers of a class.
02886 
02887    R__LOCKGUARD(gCINTMutex);
02888    if (!fClassInfo) {
02889       if (!fData) fData = new TList;
02890       return fData;
02891    }
02892 
02893    if (!fData) {
02894       if (!gInterpreter)
02895          Fatal("GetListOfDataMembers", "gInterpreter not initialized");
02896 
02897       gInterpreter->CreateListOfDataMembers(this);
02898    }
02899    return fData;
02900 }
02901 
02902 //______________________________________________________________________________
02903 TList *TClass::GetListOfMethods()
02904 {
02905    // Return list containing the TMethods of a class.
02906 
02907    R__LOCKGUARD(gCINTMutex);
02908    if (!fClassInfo) {
02909       if (!fMethod) fMethod = new THashList;
02910       return fMethod;
02911    }
02912 
02913    if (!fMethod) {
02914       if (!gInterpreter)
02915          Fatal("GetListOfMethods", "gInterpreter not initialized");
02916 
02917       TMmallocDescTemp setreset;
02918       gInterpreter->CreateListOfMethods(this);
02919    } else {
02920       gInterpreter->UpdateListOfMethods(this);
02921    }
02922    return fMethod;
02923 }
02924 
02925 //______________________________________________________________________________
02926 TList *TClass::GetListOfAllPublicMethods()
02927 {
02928    // Returns a list of all public methods of this class and its base classes.
02929    // Refers to a subset of the methods in GetListOfMethods() so don't do
02930    // GetListOfAllPublicMethods()->Delete().
02931    // Algorithm used to get the list is:
02932    // - put all methods of the class in the list (also protected and private
02933    //   ones).
02934    // - loop over all base classes and add only those methods not already in the
02935    //   list (also protected and private ones).
02936    // - once finished, loop over resulting list and remove all private and
02937    //   protected methods.
02938 
02939    R__LOCKGUARD(gCINTMutex);
02940    if (!fAllPubMethod) {
02941       fAllPubMethod = new TList;
02942 
02943       // put all methods in the list
02944       fAllPubMethod->AddAll(GetListOfMethods());
02945 
02946       // loop over all base classes and add new methods
02947       TIter nextBaseClass(GetListOfBases());
02948       TBaseClass *pB;
02949       TMethod    *p;
02950       while ((pB = (TBaseClass*) nextBaseClass())) {
02951          if (!pB->GetClassPointer()) continue;
02952          TIter next(pB->GetClassPointer()->GetListOfAllPublicMethods());
02953          TList temp;
02954          while ((p = (TMethod*) next()))
02955             if (!fAllPubMethod->Contains(p->GetName()))
02956                temp.Add(p);
02957          fAllPubMethod->AddAll(&temp);
02958          temp.Clear();
02959       }
02960 
02961       // loop over list and remove all non-public methods
02962       TIter next(fAllPubMethod);
02963       while ((p = (TMethod*) next()))
02964          if (!(p->Property() & kIsPublic)) fAllPubMethod->Remove(p);
02965    }
02966    return fAllPubMethod;
02967 }
02968 
02969 //______________________________________________________________________________
02970 TList *TClass::GetListOfAllPublicDataMembers()
02971 {
02972    // Returns a list of all public data members of this class and its base
02973    // classes. Refers to a subset of the data members in GetListOfDatamembers()
02974    // so don't do GetListOfAllPublicDataMembers()->Delete().
02975 
02976    R__LOCKGUARD(gCINTMutex);
02977    if (!fAllPubData) {
02978       fAllPubData = new TList;
02979       TIter next(GetListOfDataMembers());
02980       TDataMember *p;
02981 
02982       while ((p = (TDataMember*) next()))
02983          if (p->Property() & kIsPublic) fAllPubData->Add(p);
02984 
02985       TIter next_BaseClass(GetListOfBases());
02986       TBaseClass *pB;
02987       while ((pB = (TBaseClass*) next_BaseClass())) {
02988          if (!pB->GetClassPointer()) continue;
02989          fAllPubData->AddAll(pB->GetClassPointer()->GetListOfAllPublicDataMembers() );
02990       }
02991    }
02992    return fAllPubData;
02993 }
02994 
02995 //______________________________________________________________________________
02996 void TClass::GetMenuItems(TList *list)
02997 {
02998    // Returns list of methods accessible by context menu.
02999 
03000    if (!fClassInfo) return;
03001 
03002    // get the base class
03003    TIter nextBase(GetListOfBases(), kIterBackward);
03004    TBaseClass *baseClass;
03005    while ((baseClass = (TBaseClass *) nextBase())) {
03006       TClass *base = baseClass->GetClassPointer();
03007       if (base) base->GetMenuItems(list);
03008    }
03009 
03010    // remove methods redefined in this class with no menu
03011    TMethod *method, *m;
03012    TIter next(GetListOfMethods(), kIterBackward);
03013    while ((method = (TMethod*)next())) {
03014       m = (TMethod*)list->FindObject(method->GetName());
03015       if (method->IsMenuItem() != kMenuNoMenu) {
03016          if (!m)
03017             list->AddFirst(method);
03018       } else {
03019          if (m && m->GetNargs() == method->GetNargs())
03020             list->Remove(m);
03021       }
03022    }
03023 }
03024 
03025 //______________________________________________________________________________
03026 Bool_t TClass::IsFolder(void *obj) const
03027 {
03028    // Return kTRUE if the class has elements.
03029 
03030    return Browse(obj,(TBrowser*)0);
03031 }
03032 
03033 //______________________________________________________________________________
03034 void TClass::RemoveRef(TClassRef *ref)
03035 {
03036    // Unregister the TClassRef object.
03037 
03038    R__LOCKGUARD(gCINTMutex);
03039    if (ref==fRefStart) {
03040       fRefStart = ref->fNext;
03041       if (fRefStart) fRefStart->fPrevious = 0;
03042       ref->fPrevious = ref->fNext = 0;
03043    } else {
03044       TClassRef *next = ref->fNext;
03045       ref->fPrevious->fNext = next;
03046       if (next) next->fPrevious = ref->fPrevious;
03047       ref->fPrevious = ref->fNext = 0;
03048    }
03049 }
03050 
03051 //______________________________________________________________________________
03052 void TClass::ReplaceWith(TClass *newcl, Bool_t recurse) const
03053 {
03054    // Inform the other objects to replace this object by the new TClass (newcl)
03055 
03056    R__LOCKGUARD(gCINTMutex);
03057    //we must update the class pointers pointing to 'this' in all TStreamerElements
03058    TIter nextClass(gROOT->GetListOfClasses());
03059    TClass *acl;
03060    TVirtualStreamerInfo *info;
03061    TList tobedeleted;
03062 
03063    TString corename( TClassEdit::ResolveTypedef(newcl->GetName()) );
03064 
03065    if ( strchr( corename.Data(), '<' ) == 0 ) {
03066       // not a template, let's skip
03067       recurse = kFALSE;
03068    }
03069 
03070    while ((acl = (TClass*)nextClass())) {
03071       if (recurse && acl!=newcl && acl!=this) {
03072 
03073          TString aclCorename( TClassEdit::ResolveTypedef(acl->GetName()) );
03074 
03075          if (aclCorename == corename) {
03076 
03077             // 'acl' represents the same class as 'newcl' (and this object)
03078 
03079             acl->ReplaceWith(newcl, kFALSE);
03080             tobedeleted.Add(acl);
03081          }
03082       }
03083 
03084       TIter nextInfo(acl->GetStreamerInfos());
03085       while ((info = (TVirtualStreamerInfo*)nextInfo())) {
03086 
03087          info->Update(this, newcl);
03088       }
03089 
03090       if (acl->GetCollectionProxy() && acl->GetCollectionProxy()->GetValueClass()==this) {
03091          acl->GetCollectionProxy()->SetValueClass(newcl);
03092          // We should also inform all the TBranchElement :( but we do not have a master list :(
03093       }
03094    }
03095 
03096    TIter delIter( &tobedeleted );
03097    while ((acl = (TClass*)delIter())) {
03098       delete acl;
03099    }
03100 
03101 }
03102 
03103 //______________________________________________________________________________
03104 void TClass::ResetClassInfo(Long_t tagnum)
03105 {
03106    // Make sure that the current ClassInfo is up to date.
03107 
03108    if (fClassInfo && gCint->ClassInfo_Tagnum(fClassInfo) != tagnum) {
03109       gCint->ClassInfo_Init(fClassInfo,(Int_t)tagnum);
03110       if (fBase) {
03111          fBase->Delete();
03112          delete fBase; fBase = 0;
03113       }
03114    }
03115 }
03116 
03117 //______________________________________________________________________________
03118 void TClass::ResetMenuList()
03119 {
03120    // Resets the menu list to it's standard value.
03121 
03122    if (fClassMenuList)
03123       fClassMenuList->Delete();
03124    else
03125       fClassMenuList = new TList();
03126    fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, this));
03127 }
03128 
03129 //______________________________________________________________________________
03130 void TClass::ls(Option_t *options) const
03131 {
03132    // The ls function lists the contents of a class on stdout. Ls output
03133    // is typically much less verbose then Dump().
03134    // If options contains 'streamerinfo', run ls on the list of streamerInfos
03135    // and the list of conversion streamerInfos.
03136    
03137    TNamed::ls(options);
03138    if (options==0 || options[0]==0) return;
03139    
03140    if (strstr(options,"streamerinfo")!=0) {
03141       GetStreamerInfos()->ls(options);
03142 
03143       if (fConversionStreamerInfo) {
03144          std::map<std::string, TObjArray*>::iterator it;
03145          std::map<std::string, TObjArray*>::iterator end = fConversionStreamerInfo->end();
03146          for( it = fConversionStreamerInfo->begin(); it != end; ++it ) {
03147             it->second->ls(options);
03148          }
03149       }
03150    }
03151 }
03152    
03153 //______________________________________________________________________________
03154 void TClass::MakeCustomMenuList()
03155 {
03156    // Makes a customizable version of the popup menu list, i.e. makes a list
03157    // of TClassMenuItem objects of methods accessible by context menu.
03158    // The standard (and different) way consists in having just one element
03159    // in this list, corresponding to the whole standard list.
03160    // Once the customizable version is done, one can remove or add elements.
03161 
03162    R__LOCKGUARD(gCINTMutex);
03163    TClassMenuItem *menuItem;
03164 
03165    // Make sure fClassMenuList is initialized and empty.
03166    GetMenuList()->Delete();
03167 
03168    TList* methodList = new TList;
03169    GetMenuItems(methodList);
03170 
03171    TMethod *method;
03172    TMethodArg *methodArg;
03173    TClass  *classPtr = 0;
03174    TIter next(methodList);
03175 
03176    while ((method = (TMethod*) next())) {
03177       // if go to a mother class method, add separator
03178       if (classPtr != method->GetClass()) {
03179          menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
03180          fClassMenuList->AddLast(menuItem);
03181          classPtr = method->GetClass();
03182       }
03183       // Build the signature of the method
03184       TString sig;
03185       TList* margsList = method->GetListOfMethodArgs();
03186       TIter nextarg(margsList);
03187       while ((methodArg = (TMethodArg*)nextarg())) {
03188          sig = sig+","+methodArg->GetFullTypeName();
03189       }
03190       if (sig.Length()!=0) sig.Remove(0,1);  // remove first comma
03191       menuItem = new TClassMenuItem(TClassMenuItem::kPopupUserFunction, this,
03192                                     method->GetName(), method->GetName(),0,
03193                                     sig.Data(),-1,TClassMenuItem::kIsSelf);
03194       if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
03195       fClassMenuList->Add(menuItem);
03196    }
03197    delete methodList;
03198 }
03199 
03200 //______________________________________________________________________________
03201 void TClass::Move(void *arenaFrom, void *arenaTo) const
03202 {
03203    // Register the fact that an object was moved from the memory location
03204    // 'arenaFrom' to the memory location 'arenaTo'.
03205 
03206    // If/when we have access to a copy constructor (or better to a move
03207    // constructor), this function should also perform the data move.
03208    // For now we just information the repository.
03209 
03210    if (!fClassInfo && !fCollectionProxy) {
03211       MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
03212    }
03213 }
03214 
03215 //______________________________________________________________________________
03216 TList *TClass::GetMenuList() const {
03217    // Return the list of menu items associated with the class.
03218    if (!fClassMenuList) {
03219       fClassMenuList = new TList();
03220       fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, const_cast<TClass*>(this)));
03221    }
03222    return fClassMenuList;
03223 }
03224 
03225 
03226 //______________________________________________________________________________
03227 TMethod *TClass::GetMethodAny(const char *method)
03228 {
03229    // Return pointer to method without looking at parameters.
03230    // Does not look in (possible) base classes.
03231 
03232    if (!fClassInfo) return 0;
03233    return (TMethod*) GetListOfMethods()->FindObject(method);
03234 }
03235 
03236 //______________________________________________________________________________
03237 TMethod *TClass::GetMethodAllAny(const char *method)
03238 {
03239    // Return pointer to method without looking at parameters.
03240    // Does look in all base classes.
03241 
03242    if (!fClassInfo) return 0;
03243 
03244    TMethod* m = GetMethodAny(method);
03245    if (m) return m;
03246 
03247    TBaseClass *base;
03248    TIter       nextb(GetListOfBases());
03249    while ((base = (TBaseClass *) nextb())) {
03250       TClass *c = base->GetClassPointer();
03251       if (c) {
03252          m = c->GetMethodAllAny(method);
03253          if (m) return m;
03254       }
03255    }
03256 
03257    return 0;
03258 }
03259 
03260 //______________________________________________________________________________
03261 TMethod *TClass::GetMethod(const char *method, const char *params)
03262 {
03263    // Find the best method (if there is one) matching the parameters.
03264    // The params string must contain argument values, like "3189, \"aap\", 1.3".
03265    // The function invokes GetClassMethod to search for a possible method
03266    // in the class itself or in its base classes. Returns 0 in case method
03267    // is not found.
03268 
03269    if (!fClassInfo) return 0;
03270 
03271    if (!gInterpreter)
03272       Fatal("GetMethod", "gInterpreter not initialized");
03273 
03274    Long_t faddr = (Long_t)gInterpreter->GetInterfaceMethod(this, method,
03275                                                            params);
03276    if (!faddr) return 0;
03277 
03278    // loop over all methods in this class (and its baseclasses) till
03279    // we find a TMethod with the same faddr
03280 
03281 
03282    TMethod *m;
03283 
03284 #if defined(R__WIN32)
03285    // On windows CINT G__exec_bytecode can (seemingly) have several values :(
03286    // So we can not easily determine whether something is interpreted or
03287    // so the optimization of not looking at the mangled name can not be
03288    // used
03289    m = GetClassMethod(method,params);
03290 
03291 #else
03292    if (faddr == (Long_t)gCint->GetExecByteCode()) {
03293       // the method is actually interpreted, its address is
03294       // not a discriminant (it always point to the same
03295       // function pointed by CINT G__exec_bytecode.
03296       m = GetClassMethod(method,params);
03297    } else {
03298       m = GetClassMethod(faddr);
03299    }
03300 #endif
03301 
03302    if (m) return m;
03303 
03304    TBaseClass *base;
03305    TIter       next(GetListOfBases());
03306    while ((base = (TBaseClass *) next())) {
03307       TClass *c = base->GetClassPointer();
03308       if (c) {
03309          m = c->GetMethod(method,params);
03310          if (m) return m;
03311       }
03312    }
03313    Error("GetMethod",
03314          "\nDid not find matching TMethod <%s> with \"%s\" for %s",
03315          method,params,GetName());
03316    return 0;
03317 }
03318 
03319 //______________________________________________________________________________
03320 TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto)
03321 {
03322    // Find the method with a given prototype. The proto string must be of the
03323    // form: "char*,int,double". Returns 0 in case method is not found.
03324 
03325    if (!fClassInfo) return 0;
03326 
03327    if (!gInterpreter)
03328       Fatal("GetMethod", "gInterpreter not initialized");
03329 
03330    Long_t faddr = (Long_t)gInterpreter->GetInterfaceMethodWithPrototype(this,
03331                                                               method, proto);
03332    if (!faddr) return 0;
03333 
03334    // loop over all methods in this class (and its baseclasses) till
03335    // we find a TMethod with the same faddr
03336 
03337    TMethod *m = GetClassMethod(faddr);
03338    if (m) return m;
03339 
03340    TBaseClass *base;
03341    TIter       next(GetListOfBases());
03342    while ((base = (TBaseClass *) next())) {
03343       TClass *c = base->GetClassPointer();
03344       if (c) {
03345          m = c->GetMethodWithPrototype(method,proto);
03346          if (m) return m;
03347       }
03348    }
03349    Error("GetMethod", "Did not find matching TMethod (should never happen)");
03350    return 0;
03351 }
03352 
03353 //______________________________________________________________________________
03354 TMethod *TClass::GetClassMethod(Long_t faddr)
03355 {
03356    // Look for a method in this class that has the interface function
03357    // address faddr.
03358 
03359    if (!fClassInfo) return 0;
03360 
03361    TMethod *m;
03362    TIter    next(GetListOfMethods());
03363    while ((m = (TMethod *) next())) {
03364       if (faddr == (Long_t)m->InterfaceMethod())
03365          return m;
03366    }
03367    return 0;
03368 }
03369 
03370 //______________________________________________________________________________
03371 TMethod *TClass::GetClassMethod(const char *name, const char* params)
03372 {
03373    // Look for a method in this class that has the name and
03374    // signature
03375 
03376    if (!fClassInfo) return 0;
03377 
03378    // Need to go through those loops to get the signature from
03379    // the valued params (i.e. from "1.0,3" to "double,int")
03380 
03381    TList* bucketForMethod = ((THashList*)GetListOfMethods())->GetListForObject(name);
03382    if (bucketForMethod) {
03383       R__LOCKGUARD2(gCINTMutex);
03384       CallFunc_t  *func = gCint->CallFunc_Factory();
03385       Long_t       offset;
03386       gCint->CallFunc_SetFunc(func,GetClassInfo(), name, params, &offset);
03387       MethodInfo_t *info = gCint->CallFunc_FactoryMethod(func);
03388       TMethod request(info,this);
03389       TMethod *m;
03390       TIter    next(bucketForMethod);
03391       while ((m = (TMethod *) next())) {
03392          if (!strcmp(name,m->GetName())
03393              &&!strcmp(request.GetSignature(),m->GetSignature())) {
03394             gCint->CallFunc_Delete(func);
03395             return m;
03396          }
03397       }
03398       gCint->CallFunc_Delete(func);
03399    }
03400    return 0;
03401 }
03402 
03403 //______________________________________________________________________________
03404 Int_t TClass::GetNdata()
03405 {
03406    // Return the number of data members of this class
03407    // Note that in case the list of data members is not yet created, it will be done
03408    // by GetListOfDataMembers().
03409 
03410    if (!fClassInfo) return 0;
03411 
03412    TList *lm = GetListOfDataMembers();
03413    if (lm)
03414       return lm->GetSize();
03415    else
03416       return 0;
03417 }
03418 
03419 //______________________________________________________________________________
03420 Int_t TClass::GetNmethods()
03421 {
03422    // Return the number of methods of this class
03423    // Note that in case the list of methods is not yet created, it will be done
03424    // by GetListOfMethods().
03425 
03426    if (!fClassInfo) return 0;
03427 
03428    TList *lm = GetListOfMethods();
03429    if (lm)
03430       return lm->GetSize();
03431    else
03432       return 0;
03433 }
03434 
03435 //______________________________________________________________________________
03436 TVirtualStreamerInfo* TClass::GetStreamerInfo(Int_t version) const
03437 {
03438    // returns a pointer to the TVirtualStreamerInfo object for version
03439    // If the object doest not exist, it is created
03440    //
03441    // Note: There are two special version numbers:
03442    //
03443    //       0: Use the class version from the currently loaded class library.
03444    //      -1: Assume no class library loaded (emulated class).
03445    //
03446    // Warning:  If we create a new streamer info, whether or not the build
03447    //           optimizes is controlled externally to us by a global variable!
03448    //           Don't call us unless you have set that variable properly
03449    //           with TStreamer::Optimize()!
03450    //
03451 
03452    R__LOCKGUARD(gCINTMutex);
03453 
03454    // Handle special version, 0 means currently loaded version.
03455    // Warning:  This may be -1 for an emulated class.
03456    if (version == 0) {
03457       version = fClassVersion;
03458    }
03459    if (!fStreamerInfo) {
03460       TMmallocDescTemp setreset;
03461       fStreamerInfo = new TObjArray(version + 10, -1);
03462    } else {
03463       Int_t ninfos = fStreamerInfo->GetSize();
03464       if ((version < -1) || (version >= ninfos)) {
03465          Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
03466          // FIXME: Shouldn't we go to -1 here, or better just abort?
03467          version = 0;
03468       }
03469    }
03470    TVirtualStreamerInfo* sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
03471    if (!sinfo && (version != fClassVersion)) {
03472       // When the requested version does not exist we return
03473       // the TVirtualStreamerInfo for the currently loaded class vesion.
03474       // FIXME: This arguably makes no sense, we should warn and return nothing instead.
03475       // Note: This is done for STL collactions
03476       // Note: fClassVersion could be -1 here (for an emulated class).
03477       sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(fClassVersion);
03478    }
03479    if (!sinfo) {
03480       // We just were not able to find a streamer info, we have to make a new one.
03481       TMmallocDescTemp setreset;
03482       sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
03483       fStreamerInfo->AddAtAndExpand(sinfo, fClassVersion);
03484       if (gDebug > 0) {
03485          printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
03486       }
03487       if (fClassInfo || fCollectionProxy) {
03488          // If we do not have a StreamerInfo for this version and we do not
03489          // have dictionary information nor a proxy, there is nothing to build!
03490          //
03491          // Warning:  Whether or not the build optimizes is controlled externally
03492          //           to us by a global variable!  Don't call us unless you have
03493          //           set that variable properly with TStreamer::Optimize()!
03494          //
03495          // FIXME: Why don't we call BuildOld() like we do below?  Answer: We are new and so don't have to do schema evolution?
03496          sinfo->Build();
03497       }
03498    } else {
03499       if (!sinfo->IsCompiled()) {
03500          // Streamer info has not been compiled, but exists.
03501          // Therefore it was read in from a file and we have to do schema evolution?
03502          // Or it didn't have a dictionary before, but does now?
03503          sinfo->BuildOld();
03504       } else if (sinfo->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) {
03505          // Undo optimization if the global flag tells us to.
03506          sinfo->Compile();
03507       }
03508    }
03509    // Cache the current info if we now have it.
03510    if (version == fClassVersion) {
03511       fCurrentInfo = sinfo;
03512    }
03513    return sinfo;
03514 }
03515 
03516 //______________________________________________________________________________
03517 void TClass::IgnoreTObjectStreamer(Bool_t ignore)
03518 {
03519    //  When the class kIgnoreTObjectStreamer bit is set, the automatically
03520    //  generated Streamer will not call TObject::Streamer.
03521    //  This option saves the TObject space overhead on the file.
03522    //  However, the information (fBits, fUniqueID) of TObject is lost.
03523    //
03524    //  Note that this function must be called for the class deriving
03525    //  directly from TObject, eg, assuming that BigTrack derives from Track
03526    //  and Track derives from TObject, one must do:
03527    //     Track::Class()->IgnoreTObjectStreamer();
03528    //  and not:
03529    //     BigTrack::Class()->IgnoreTObjectStreamer();
03530 
03531    if ( ignore &&  TestBit(kIgnoreTObjectStreamer)) return;
03532    if (!ignore && !TestBit(kIgnoreTObjectStreamer)) return;
03533    TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
03534    if (sinfo) {
03535       if (sinfo->IsCompiled()) {
03536          // -- Warn the user that what he is doing cannot work.
03537          // Note: The reason is that TVirtualStreamerInfo::Build() examines
03538          // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
03539          // type for the TObject base class streamer element it creates
03540          // to -1 as a flag.  Later on the TStreamerInfo::Compile()
03541          // member function sees the flag and does not insert the base
03542          // class element into the compiled streamer info.  None of this
03543          // machinery works correctly if we are called after the streamer
03544          // info has already been built and compiled.
03545          Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
03546          return;
03547       }
03548    }
03549    if (ignore) SetBit  (kIgnoreTObjectStreamer);
03550    else        ResetBit(kIgnoreTObjectStreamer);
03551 }
03552 
03553 //______________________________________________________________________________
03554 Bool_t TClass::InheritsFrom(const char *classname) const
03555 {
03556    // Return kTRUE if this class inherits from a class with name "classname".
03557    // note that the function returns KTRUE in case classname is the class itself
03558 
03559    if (strcmp(GetName(), classname) == 0) return kTRUE;
03560 
03561    if (!fClassInfo) return InheritsFrom(TClass::GetClass("classname"));
03562 
03563    // cast const away (only for member fBase which can be set in GetListOfBases())
03564    if (((TClass *)this)->GetBaseClass(classname)) return kTRUE;
03565    return kFALSE;
03566 }
03567 
03568 //______________________________________________________________________________
03569 Bool_t TClass::InheritsFrom(const TClass *cl) const
03570 {
03571    // Return kTRUE if this class inherits from class cl.
03572    // note that the function returns KTRUE in case cl is the class itself
03573 
03574    if (cl == this) return kTRUE;
03575 
03576    if (!fClassInfo) {
03577       TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
03578       if (sinfo==0) sinfo = GetStreamerInfo();
03579       TIter next(sinfo->GetElements());
03580       TStreamerElement *element;
03581       while ((element = (TStreamerElement*)next())) {
03582          if (element->IsA() == TStreamerBase::Class()) {
03583             TClass *clbase = element->GetClassPointer();
03584             if (!clbase) return kFALSE; //missing class
03585             if (clbase->InheritsFrom(cl)) return kTRUE;
03586          }
03587       }
03588       return kFALSE;
03589    }
03590    // cast const away (only for member fBase which can be set in GetListOfBases())
03591    if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
03592    return kFALSE;
03593 }
03594 
03595 //______________________________________________________________________________
03596 void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
03597 {
03598    // Cast obj of this class type up to baseclass cl if up is true.
03599    // Cast obj of this class type down from baseclass cl if up is false.
03600    // If this class is not a baseclass of cl return 0, else the pointer
03601    // to the cl part of this (up) or to this (down).
03602 
03603    if (cl == this) return obj;
03604 
03605    if (!fClassInfo) return 0;
03606 
03607    Int_t off;
03608    if ((off = GetBaseClassOffset(cl)) != -1) {
03609       if (up)
03610          return (void*)((Long_t)obj+off);
03611       else
03612          return (void*)((Long_t)obj-off);
03613    }
03614    return 0;
03615 }
03616 
03617 //______________________________________________________________________________
03618 void *TClass::New(ENewType defConstructor) const
03619 {
03620    // Return a pointer to a newly allocated object of this class.
03621    // The class must have a default constructor. For meaning of
03622    // defConstructor, see TClass::IsCallingNew().
03623    //
03624    // The constructor actually called here can be customized by
03625    // using the rootcint pragma:
03626    //    #pragma link C++ ioctortype UserClass;
03627    // For example, with this pragma and a class named MyClass,
03628    // this method will called the first of the following 3
03629    // constructors which exists and is public:
03630    //    MyClass(UserClass*);
03631    //    MyClass(TRootIOCtor*);
03632    //    MyClass(); // Or a constructor with all its arguments defaulted.
03633    //
03634    // When more than one pragma ioctortype is used, the first seen as priority
03635    // For example with:
03636    //    #pragma link C++ ioctortype UserClass1;
03637    //    #pragma link C++ ioctortype UserClass2;
03638    // We look in the following order:
03639    //    MyClass(UserClass1*);
03640    //    MyClass(UserClass2*);
03641    //    MyClass(TRootIOCtor*);
03642    //    MyClass(); // Or a constructor with all its arguments defaulted.
03643    //
03644 
03645    void* p = 0;
03646 
03647    if (fNew) {
03648       // We have the new operator wrapper function,
03649       // so there is a dictionary and it was generated
03650       // by rootcint, so there should be a default
03651       // constructor we can call through the wrapper.
03652       fgCallingNew = defConstructor;
03653       p = fNew(0);
03654       fgCallingNew = kRealNew;
03655       if (!p) {
03656          //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
03657          Error("New", "cannot create object of class %s", GetName());
03658       }
03659    } else if (fClassInfo) {
03660       // We have the dictionary but do not have the
03661       // constructor wrapper, so the dictionary was
03662       // not generated by rootcint.  Let's try to
03663       // create the object by having the interpreter
03664       // call the new operator, hopefully the class
03665       // library is loaded and there will be a default
03666       // constructor we can call.
03667       // [This is very unlikely to work, but who knows!]
03668       fgCallingNew = defConstructor;
03669       R__LOCKGUARD2(gCINTMutex);
03670       p = gCint->ClassInfo_New(GetClassInfo());
03671       fgCallingNew = kRealNew;
03672       if (!p) {
03673          //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
03674          Error("New", "cannot create object of class %s", GetName());
03675       }
03676    } else if (!fClassInfo && fCollectionProxy) {
03677       // There is no dictionary at all, so this is an emulated
03678       // class; however we do have the services of a collection proxy,
03679       // so this is an emulated STL class.
03680       fgCallingNew = defConstructor;
03681       p = fCollectionProxy->New();
03682       fgCallingNew = kRealNew;
03683       if (!p) {
03684          //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
03685          Error("New", "cannot create object of class %s", GetName());
03686       }
03687    } else if (!fClassInfo && !fCollectionProxy) {
03688       // There is no dictionary at all and we do not have
03689       // the services of a collection proxy available, so
03690       // use the streamer info to approximate calling a
03691       // constructor (basically we just make sure that the
03692       // pointer data members are null, unless they are marked
03693       // as preallocated with the "->" comment, in which case
03694       // we default-construct an object to point at).
03695 
03696       // Do not register any TObject's that we create
03697       // as a result of creating this object.
03698       // FIXME: Why do we do this?
03699       // FIXME: Partial Answer: Is this because we may never actually deregister them???
03700 
03701       Bool_t statsave = GetObjectStat();
03702       SetObjectStat(kFALSE);
03703 
03704       TVirtualStreamerInfo* sinfo = GetStreamerInfo();
03705       if (!sinfo) {
03706          Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
03707          return 0;
03708       }
03709 
03710       fgCallingNew = defConstructor;
03711       p = sinfo->New();
03712       fgCallingNew = kRealNew;
03713 
03714       // FIXME: Mistake?  See note above at the GetObjectStat() call.
03715       // Allow TObject's to be registered again.
03716       SetObjectStat(statsave);
03717 
03718       // Register the object for special handling in the destructor.
03719       if (p) {
03720          RegisterAddressInRepository("New",p,this);
03721       }
03722    } else {
03723       Error("New", "This cannot happen!");
03724    }
03725 
03726    return p;
03727 }
03728 
03729 //______________________________________________________________________________
03730 void *TClass::New(void *arena, ENewType defConstructor) const
03731 {
03732    // Return a pointer to a newly allocated object of this class.
03733    // The class must have a default constructor. For meaning of
03734    // defConstructor, see TClass::IsCallingNew().
03735 
03736    void* p = 0;
03737 
03738    if (fNew) {
03739       // We have the new operator wrapper function,
03740       // so there is a dictionary and it was generated
03741       // by rootcint, so there should be a default
03742       // constructor we can call through the wrapper.
03743       fgCallingNew = defConstructor;
03744       p = fNew(arena);
03745       fgCallingNew = kRealNew;
03746       if (!p) {
03747          Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
03748       }
03749    } else if (fClassInfo) {
03750       // We have the dictionary but do not have the
03751       // constructor wrapper, so the dictionary was
03752       // not generated by rootcint.  Let's try to
03753       // create the object by having the interpreter
03754       // call the new operator, hopefully the class
03755       // library is loaded and there will be a default
03756       // constructor we can call.
03757       // [This is very unlikely to work, but who knows!]
03758       fgCallingNew = defConstructor;
03759       R__LOCKGUARD2(gCINTMutex);
03760       p = gCint->ClassInfo_New(GetClassInfo(),arena);
03761       fgCallingNew = kRealNew;
03762       if (!p) {
03763          Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
03764       }
03765    } else if (!fClassInfo && fCollectionProxy) {
03766       // There is no dictionary at all, so this is an emulated
03767       // class; however we do have the services of a collection proxy,
03768       // so this is an emulated STL class.
03769       fgCallingNew = defConstructor;
03770       p = fCollectionProxy->New(arena);
03771       fgCallingNew = kRealNew;
03772    } else if (!fClassInfo && !fCollectionProxy) {
03773       // There is no dictionary at all and we do not have
03774       // the services of a collection proxy available, so
03775       // use the streamer info to approximate calling a
03776       // constructor (basically we just make sure that the
03777       // pointer data members are null, unless they are marked
03778       // as preallocated with the "->" comment, in which case
03779       // we default-construct an object to point at).
03780 
03781       // ???BUG???  ???WHY???
03782       // Do not register any TObject's that we create
03783       // as a result of creating this object.
03784       Bool_t statsave = GetObjectStat();
03785       SetObjectStat(kFALSE);
03786 
03787       TVirtualStreamerInfo* sinfo = GetStreamerInfo();
03788       if (!sinfo) {
03789          Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
03790          return 0;
03791       }
03792 
03793       fgCallingNew = defConstructor;
03794       p = sinfo->New(arena);
03795       fgCallingNew = kRealNew;
03796 
03797       // ???BUG???
03798       // Allow TObject's to be registered again.
03799       SetObjectStat(statsave);
03800 
03801       // Register the object for special handling in the destructor.
03802       if (p) {
03803          RegisterAddressInRepository("TClass::New with placement",p,this);
03804       }
03805    } else {
03806       Error("New with placement", "This cannot happen!");
03807    }
03808 
03809    return p;
03810 }
03811 
03812 //______________________________________________________________________________
03813 void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
03814 {
03815    // Return a pointer to a newly allocated array of objects
03816    // of this class.
03817    // The class must have a default constructor. For meaning of
03818    // defConstructor, see TClass::IsCallingNew().
03819 
03820    void* p = 0;
03821 
03822    if (fNewArray) {
03823       // We have the new operator wrapper function,
03824       // so there is a dictionary and it was generated
03825       // by rootcint, so there should be a default
03826       // constructor we can call through the wrapper.
03827       fgCallingNew = defConstructor;
03828       p = fNewArray(nElements, 0);
03829       fgCallingNew = kRealNew;
03830       if (!p) {
03831          Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
03832       }
03833    } else if (fClassInfo) {
03834       // We have the dictionary but do not have the
03835       // constructor wrapper, so the dictionary was
03836       // not generated by rootcint.  Let's try to
03837       // create the object by having the interpreter
03838       // call the new operator, hopefully the class
03839       // library is loaded and there will be a default
03840       // constructor we can call.
03841       // [This is very unlikely to work, but who knows!]
03842       fgCallingNew = defConstructor;
03843       R__LOCKGUARD2(gCINTMutex);
03844       p = gCint->ClassInfo_New(GetClassInfo(),nElements);
03845       fgCallingNew = kRealNew;
03846       if (!p) {
03847          Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
03848       }
03849    } else if (!fClassInfo && fCollectionProxy) {
03850       // There is no dictionary at all, so this is an emulated
03851       // class; however we do have the services of a collection proxy,
03852       // so this is an emulated STL class.
03853       fgCallingNew = defConstructor;
03854       p = fCollectionProxy->NewArray(nElements);
03855       fgCallingNew = kRealNew;
03856    } else if (!fClassInfo && !fCollectionProxy) {
03857       // There is no dictionary at all and we do not have
03858       // the services of a collection proxy available, so
03859       // use the streamer info to approximate calling a
03860       // constructor (basically we just make sure that the
03861       // pointer data members are null, unless they are marked
03862       // as preallocated with the "->" comment, in which case
03863       // we default-construct an object to point at).
03864 
03865       // ???BUG???  ???WHY???
03866       // Do not register any TObject's that we create
03867       // as a result of creating this object.
03868       Bool_t statsave = GetObjectStat();
03869       SetObjectStat(kFALSE);
03870 
03871       TVirtualStreamerInfo* sinfo = GetStreamerInfo();
03872       if (!sinfo) {
03873          Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
03874          return 0;
03875       }
03876 
03877       fgCallingNew = defConstructor;
03878       p = sinfo->NewArray(nElements);
03879       fgCallingNew = kRealNew;
03880 
03881       // ???BUG???
03882       // Allow TObject's to be registered again.
03883       SetObjectStat(statsave);
03884 
03885       // Register the object for special handling in the destructor.
03886       if (p) {
03887          RegisterAddressInRepository("TClass::NewArray",p,this);
03888       }
03889    } else {
03890       Error("NewArray", "This cannot happen!");
03891    }
03892 
03893    return p;
03894 }
03895 
03896 //______________________________________________________________________________
03897 void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
03898 {
03899    // Return a pointer to a newly allocated object of this class.
03900    // The class must have a default constructor. For meaning of
03901    // defConstructor, see TClass::IsCallingNew().
03902 
03903    void* p = 0;
03904 
03905    if (fNewArray) {
03906       // We have the new operator wrapper function,
03907       // so there is a dictionary and it was generated
03908       // by rootcint, so there should be a default
03909       // constructor we can call through the wrapper.
03910       fgCallingNew = defConstructor;
03911       p = fNewArray(nElements, arena);
03912       fgCallingNew = kRealNew;
03913       if (!p) {
03914          Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
03915       }
03916    } else if (fClassInfo) {
03917       // We have the dictionary but do not have the constructor wrapper,
03918       // so the dictionary was not generated by rootcint (it was made either
03919       // by cint or by some external mechanism).  Let's try to create the
03920       // object by having the interpreter call the new operator, either the
03921       // class library is loaded and there is a default constructor we can
03922       // call, or the class is interpreted and we will call the default
03923       // constructor that way, or no default constructor is available and
03924       // we fail.
03925       fgCallingNew = defConstructor;
03926       R__LOCKGUARD2(gCINTMutex);
03927       p = gCint->ClassInfo_New(GetClassInfo(),nElements, arena);
03928       fgCallingNew = kRealNew;
03929       if (!p) {
03930          Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
03931       }
03932    } else if (!fClassInfo && fCollectionProxy) {
03933       // There is no dictionary at all, so this is an emulated
03934       // class; however we do have the services of a collection proxy,
03935       // so this is an emulated STL class.
03936       fgCallingNew = defConstructor;
03937       p = fCollectionProxy->NewArray(nElements, arena);
03938       fgCallingNew = kRealNew;
03939    } else if (!fClassInfo && !fCollectionProxy) {
03940       // There is no dictionary at all and we do not have
03941       // the services of a collection proxy available, so
03942       // use the streamer info to approximate calling a
03943       // constructor (basically we just make sure that the
03944       // pointer data members are null, unless they are marked
03945       // as preallocated with the "->" comment, in which case
03946       // we default-construct an object to point at).
03947 
03948       // ???BUG???  ???WHY???
03949       // Do not register any TObject's that we create
03950       // as a result of creating this object.
03951       Bool_t statsave = GetObjectStat();
03952       SetObjectStat(kFALSE);
03953 
03954       TVirtualStreamerInfo* sinfo = GetStreamerInfo();
03955       if (!sinfo) {
03956          Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
03957          return 0;
03958       }
03959 
03960       fgCallingNew = defConstructor;
03961       p = sinfo->NewArray(nElements, arena);
03962       fgCallingNew = kRealNew;
03963 
03964       // ???BUG???
03965       // Allow TObject's to be registered again.
03966       SetObjectStat(statsave);
03967 
03968       if (fStreamerType & kEmulated) {
03969          // We always register emulated objects, we need to always
03970          // use the streamer info to destroy them.
03971       }
03972 
03973       // Register the object for special handling in the destructor.
03974       if (p) {
03975          RegisterAddressInRepository("TClass::NewArray with placement",p,this);
03976       }
03977    } else {
03978       Error("NewArray with placement", "This cannot happen!");
03979    }
03980 
03981    return p;
03982 }
03983 
03984 //______________________________________________________________________________
03985 void TClass::Destructor(void *obj, Bool_t dtorOnly)
03986 {
03987    // Explicitly call destructor for object.
03988 
03989    // Do nothing if passed a null pointer.
03990    if (obj == 0) return;
03991 
03992    void* p = obj;
03993 
03994    if (dtorOnly && fDestructor) {
03995       // We have the destructor wrapper, use it.
03996       fDestructor(p);
03997    } else if ((!dtorOnly) && fDelete) {
03998       // We have the delete wrapper, use it.
03999       fDelete(p);
04000    } else if (fClassInfo) {
04001       // We have the dictionary but do not have the
04002       // destruct/delete wrapper, so the dictionary was
04003       // not generated by rootcint (it could have been
04004       // created by cint or by some external mechanism).
04005       // Let's have the interpreter call the destructor,
04006       // either the code will be in a loaded library,
04007       // or it will be interpreted, otherwise we fail
04008       // because there is no destructor code at all.
04009       if (dtorOnly) {
04010          gCint->ClassInfo_Destruct(fClassInfo,p);
04011       } else {
04012          gCint->ClassInfo_Delete(fClassInfo,p);
04013       }
04014    } else if (!fClassInfo && fCollectionProxy) {
04015       // There is no dictionary at all, so this is an emulated
04016       // class; however we do have the services of a collection proxy,
04017       // so this is an emulated STL class.
04018       fCollectionProxy->Destructor(p, dtorOnly);
04019    } else if (!fClassInfo && !fCollectionProxy) {
04020       // There is no dictionary at all and we do not have
04021       // the services of a collection proxy available, so
04022       // use the streamer info to approximate calling a
04023       // destructor.
04024 
04025       Bool_t inRepo = kTRUE;
04026       Bool_t verFound = kFALSE;
04027 
04028       // Was this object allocated through TClass?
04029       std::multiset<Version_t> knownVersions;
04030       std::multimap<void*, Version_t>::iterator iter = gObjectVersionRepository.find(p);
04031       if (iter == gObjectVersionRepository.end()) {
04032          // No, it wasn't, skip special version handling.
04033          //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
04034          inRepo = kFALSE;
04035       } else {
04036          //objVer = iter->second;
04037          for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
04038             Version_t ver = iter->second;
04039             knownVersions.insert(ver);
04040             if (ver == fClassVersion) {
04041                verFound = kTRUE;
04042             }
04043          }
04044       }
04045 
04046       if (!inRepo || verFound) {
04047          // The object was allocated using code for the same class version
04048          // as is loaded now.  We may proceed without worry.
04049          TVirtualStreamerInfo* si = GetStreamerInfo();
04050          if (si) {
04051             si->Destructor(p, dtorOnly);
04052          } else {
04053             Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
04054             Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
04055             Int_t i = fStreamerInfo->LowerBound();
04056             for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
04057                Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
04058                if (fStreamerInfo->At(i) != 0) {
04059                   Error("Destructor", "Doing Dump() ...");
04060                   ((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
04061                }
04062             }
04063          }
04064       } else {
04065          // The loaded class version is not the same as the version of the code
04066          // which was used to allocate this object.  The best we can do is use
04067          // the TVirtualStreamerInfo to try to free up some of the allocated memory.
04068          Error("Destructor", "Loaded class %s version %d is not registered for addr %p", GetName(), fClassVersion, p);
04069 #if 0
04070          TVirtualStreamerInfo* si = (TVirtualStreamerInfo*) fStreamerInfo->At(objVer);
04071          if (si) {
04072             si->Destructor(p, dtorOnly);
04073          } else {
04074             Error("Destructor2", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
04075             Error("Destructor2", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
04076             Int_t i = fStreamerInfo->LowerBound();
04077             for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
04078                Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
04079                if (fStreamerInfo->At(i) != 0) {
04080                   // Do some debugging output.
04081                   Error("Destructor2", "Doing Dump() ...");
04082                   ((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
04083                }
04084             }
04085          }
04086 #endif
04087       }
04088 
04089       if (inRepo && verFound && p) {
04090          UnregisterAddressInRepository("TClass::Destructor",p,this);
04091       }
04092    } else {
04093       Error("Destructor", "This cannot happen! (class %s)", GetName());
04094    }
04095 }
04096 
04097 //______________________________________________________________________________
04098 void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
04099 {
04100    // Explicitly call operator delete[] for an array.
04101 
04102    // Do nothing if passed a null pointer.
04103    if (ary == 0) return;
04104 
04105    // Make a copy of the address.
04106    void* p = ary;
04107 
04108    if (fDeleteArray) {
04109       if (dtorOnly) {
04110          Error("DeleteArray", "Destructor only is not supported!");
04111       } else {
04112          // We have the array delete wrapper, use it.
04113          fDeleteArray(ary);
04114       }
04115    } else if (fClassInfo) {
04116       // We have the dictionary but do not have the
04117       // array delete wrapper, so the dictionary was
04118       // not generated by rootcint.  Let's try to
04119       // delete the array by having the interpreter
04120       // call the array delete operator, hopefully
04121       // the class library is loaded and there will be
04122       // a destructor we can call.
04123       R__LOCKGUARD2(gCINTMutex);
04124       gCint->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
04125    } else if (!fClassInfo && fCollectionProxy) {
04126       // There is no dictionary at all, so this is an emulated
04127       // class; however we do have the services of a collection proxy,
04128       // so this is an emulated STL class.
04129       fCollectionProxy->DeleteArray(ary, dtorOnly);
04130    } else if (!fClassInfo && !fCollectionProxy) {
04131       // There is no dictionary at all and we do not have
04132       // the services of a collection proxy available, so
04133       // use the streamer info to approximate calling the
04134       // array destructor.
04135 
04136       Bool_t inRepo = kTRUE;
04137       Bool_t verFound = kFALSE;
04138 
04139       // Was this array object allocated through TClass?
04140       std::multiset<Version_t> knownVersions;
04141       std::multimap<void*, Version_t>::iterator iter = gObjectVersionRepository.find(p);
04142       if (iter == gObjectVersionRepository.end()) {
04143          // No, it wasn't, we cannot know what to do.
04144          //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
04145          inRepo = kFALSE;
04146       } else {
04147          for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
04148             Version_t ver = iter->second;
04149             knownVersions.insert(ver);
04150             if (ver == fClassVersion) {
04151                verFound = kTRUE;
04152             }
04153          }
04154       }
04155 
04156       if (!inRepo || verFound) {
04157          // The object was allocated using code for the same class version
04158          // as is loaded now.  We may proceed without worry.
04159          TVirtualStreamerInfo* si = GetStreamerInfo();
04160          if (si) {
04161             si->DeleteArray(ary, dtorOnly);
04162          } else {
04163             Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
04164             Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
04165             Int_t i = fStreamerInfo->LowerBound();
04166             for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
04167                Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
04168                if (fStreamerInfo->At(i)) {
04169                   Error("DeleteArray", "Doing Dump() ...");
04170                   ((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
04171                }
04172             }
04173          }
04174       } else {
04175          // The loaded class version is not the same as the version of the code
04176          // which was used to allocate this array.  The best we can do is use
04177          // the TVirtualStreamerInfo to try to free up some of the allocated memory.
04178          Error("DeleteArray", "Loaded class version %d is not registered for addr %p", fClassVersion, p);
04179 
04180 
04181 
04182 #if 0
04183          TVirtualStreamerInfo* si = (TVirtualStreamerInfo*) fStreamerInfo->At(objVer);
04184          if (si) {
04185             si->DeleteArray(ary, dtorOnly);
04186          } else {
04187             Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
04188             Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
04189             Int_t i = fStreamerInfo->LowerBound();
04190             for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
04191                Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
04192                if (fStreamerInfo->At(i)) {
04193                   // Print some debugging info.
04194                   Error("DeleteArray", "Doing Dump() ...");
04195                   ((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
04196                }
04197             }
04198          }
04199 #endif
04200 
04201 
04202       }
04203 
04204       // Deregister the object for special handling in the destructor.
04205       if (inRepo && verFound && p) {
04206          UnregisterAddressInRepository("TClass::DeleteArray",p,this);
04207       }
04208    } else {
04209       Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
04210    }
04211 }
04212 
04213 //______________________________________________________________________________
04214 void TClass::SetClassVersion(Version_t version) 
04215 { 
04216    // Private function.  Set the class version for the 'class' represented by
04217    // this TClass object.  See the public interface: 
04218    //    ROOT::ResetClassVersion 
04219    // defined in TClassTable.cxx
04220    //
04221    // Note on class version numbers:
04222    //   If no class number has been specified, TClass::GetVersion will return -1
04223    //   The Class Version 0 request the whole object to be transient
04224    //   The Class Version 1, unless specified via ClassDef indicates that the
04225    //      I/O should use the TClass checksum to distinguish the layout of the class   
04226    
04227    fClassVersion = version; 
04228    fCurrentInfo = 0; 
04229 }
04230 
04231 //______________________________________________________________________________
04232 void TClass::SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
04233 {
04234    // Set pointer to current TVirtualStreamerInfo
04235 
04236    fCurrentInfo = info;
04237 }
04238 
04239 //______________________________________________________________________________
04240 Int_t TClass::Size() const
04241 {
04242    // Return size of object of this class.
04243 
04244    if (fSizeof!=-1) return fSizeof;
04245    if (fCollectionProxy) return fCollectionProxy->Sizeof();
04246    if (fClassInfo) return gCint->ClassInfo_Size(GetClassInfo());
04247    return GetStreamerInfo()->GetSize();
04248 }
04249 
04250 //______________________________________________________________________________
04251 TClass *TClass::Load(TBuffer &b)
04252 {
04253    // Load class description from I/O buffer and return class object.
04254 
04255    UInt_t maxsize = 256;
04256    char *s = new char[maxsize];
04257 
04258    Int_t pos = b.Length();
04259 
04260    b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
04261    while (strlen(s) == (maxsize - 1)) {
04262       // The classname is too large, try again with a large buffer.
04263       b.SetBufferOffset(pos);
04264       maxsize = 2*maxsize;
04265       delete [] s;
04266       s = new char[maxsize];
04267       b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
04268    }
04269 
04270    TClass *cl = TClass::GetClass(s, kTRUE);
04271    if (!cl)
04272       ::Error("TClass::Load", "dictionary of class %s not found", s);
04273 
04274    delete [] s;
04275    return cl;
04276 }
04277 
04278 //______________________________________________________________________________
04279 void TClass::Store(TBuffer &b) const
04280 {
04281    // Store class description on I/O buffer.
04282 
04283    b.WriteString(GetName());
04284 }
04285 
04286 //______________________________________________________________________________
04287 TClass *ROOT::CreateClass(const char *cname, Version_t id,
04288                           const type_info &info, TVirtualIsAProxy *isa,
04289                           ShowMembersFunc_t show,
04290                           const char *dfil, const char *ifil,
04291                           Int_t dl, Int_t il)
04292 {
04293    // Global function called by a class' static Dictionary() method
04294    // (see the ClassDef macro).
04295 
04296    // When called via TMapFile (e.g. Update()) make sure that the dictionary
04297    // gets allocated on the heap and not in the mapped file.
04298    TMmallocDescTemp setreset;
04299    return new TClass(cname, id, info, isa, show, dfil, ifil, dl, il);
04300 }
04301 
04302 //______________________________________________________________________________
04303 TClass *ROOT::CreateClass(const char *cname, Version_t id,
04304                           const char *dfil, const char *ifil,
04305                           Int_t dl, Int_t il)
04306 {
04307    // Global function called by a class' static Dictionary() method
04308    // (see the ClassDef macro).
04309 
04310    // When called via TMapFile (e.g. Update()) make sure that the dictionary
04311    // gets allocated on the heap and not in the mapped file.
04312    TMmallocDescTemp setreset;
04313    return new TClass(cname, id, dfil, ifil, dl, il);
04314 }
04315 
04316 //______________________________________________________________________________
04317 TClass::ENewType TClass::IsCallingNew()
04318 {
04319    // Static method returning the defConstructor flag passed to TClass::New().
04320    // New type is either:
04321    //   TClass::kRealNew  - when called via plain new
04322    //   TClass::kClassNew - when called via TClass::New()
04323    //   TClass::kDummyNew - when called via TClass::New() but object is a dummy,
04324    //                       in which case the object ctor might take short cuts
04325 
04326    return fgCallingNew;
04327 }
04328 
04329 //______________________________________________________________________________
04330 Bool_t TClass::IsLoaded() const
04331 {
04332    // Return true if the shared library of this class is currently in the a
04333    // process's memory.  Return false, after the shared library has been
04334    // unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
04335 
04336    return (GetImplFileLine()>=0 && !TestBit(kUnloaded));
04337 }
04338 
04339 //______________________________________________________________________________
04340 Bool_t  TClass::IsStartingWithTObject() const
04341 {
04342    // Returns true if this class inherits from TObject and if the start of
04343    // the TObject parts is at the very beginning of the objects.
04344    // Concretly this means that the following code is proper for this class:
04345    //     ThisClass *ptr;
04346    //     void *void_ptr = (void)ptr;
04347    //     TObject *obj = (TObject*)void_ptr;
04348    // This code would be wrong if 'ThisClass' did not inherit 'first' from
04349    // TObject.
04350 
04351    if (fProperty==(-1)) Property();
04352    return TestBit(kStartWithTObject);
04353 }
04354 
04355 //______________________________________________________________________________
04356 Bool_t  TClass::IsTObject() const
04357 {
04358    // Return kTRUE is the class inherits from TObject.
04359 
04360    if (fProperty==(-1)) Property();
04361    return TestBit(kIsTObject);
04362 }
04363 
04364 //______________________________________________________________________________
04365 Bool_t  TClass::IsForeign() const
04366 {
04367    // Return kTRUE is the class is Foreign (the class does not have a Streamer method).
04368 
04369    if (fProperty==(-1)) Property();
04370    return TestBit(kIsForeign);
04371 }
04372 
04373 //______________________________________________________________________________
04374 void TClass::PostLoadCheck()
04375 {
04376    // Do the initialization that can only be done after the CINT dictionary has
04377    // been fully populated and can not be delayed efficiently.
04378 
04379    // In the case of a Foreign class (loaded class without a Streamer function)
04380    // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
04381    // be confused with a previously loaded streamerInfo.
04382 
04383    if (IsLoaded() && fClassInfo && fClassVersion==1 /*&& fStreamerInfo
04384        && fStreamerInfo->At(1)*/ && IsForeign() )
04385    {
04386       SetClassVersion(-1);
04387    }
04388    else if (IsLoaded() && fClassInfo && fStreamerInfo && (!IsForeign()||fClassVersion>1) )
04389    {
04390       TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)(fStreamerInfo->At(fClassVersion));
04391       // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
04392       // loaded from a file) is consistent with the definition in the library we just loaded.
04393       // BuildCheck is not appropriate here since it check a streamerinfo against the
04394       // 'current streamerinfo' which, at time point, would be the same as 'info'!
04395       if (info && GetListOfDataMembers() && !GetCollectionProxy()
04396           && (info->GetCheckSum()!=GetCheckSum() && info->GetCheckSum()!=GetCheckSum(1) && info->GetCheckSum()!=GetCheckSum(2)))
04397       {
04398          Bool_t warn = ! TestBit(kWarned);
04399          if (warn && info->GetOldVersion()<=2) {
04400             // Names of STL base classes was modified in vers==3. Allocators removed
04401             //
04402             TIter nextBC(GetListOfBases());
04403             TBaseClass *bc;
04404             while ((bc=(TBaseClass*)nextBC()))
04405             {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
04406          }
04407 
04408          if (warn) {
04409             if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
04410                Warning("PostLoadCheck","\n\
04411    The class %s transitioned from not having a specified class version\n\
04412    to having a specified class version (the current class version is %d).\n\
04413    However too many different non-versioned layouts of the class have\n\
04414    already been loaded so far.  To work around this problem you can\n\
04415    load fewer 'old' file in the same ROOT session or load the C++ library\n\
04416    describing the class %s before opening the files or increase the version\n\
04417    number of the class for example ClassDef(%s,%d).\n\
04418    Do not try to write objects with the current class definition,\n\
04419    the files might not be readable.\n",
04420                        GetName(), fClassVersion, GetName(), GetName(), fStreamerInfo->GetLast()+1);
04421             } else {
04422                Warning("PostLoadCheck","\n\
04423    The StreamerInfo version %d for the class %s which was read\n\
04424    from a file previously opened has the same version as the active class\n\
04425    but a different checksum. You should update the version to ClassDef(%s,%d).\n\
04426    Do not try to write objects with the current class definition,\n\
04427    the files will not be readable.\n"
04428                        , fClassVersion, GetName(), GetName(), fStreamerInfo->GetLast()+1);
04429             }
04430             info->CompareContent(this,0,kTRUE,kTRUE);
04431             SetBit(kWarned);
04432          }
04433       }
04434    }
04435 }
04436 
04437 //______________________________________________________________________________
04438 Long_t TClass::Property() const
04439 {
04440    // Set TObject::fBits and fStreamerType to cache information about the
04441    // class.  The bits are
04442    //    kIsTObject : the class inherits from TObject
04443    //    kStartWithTObject:  TObject is the left-most class in the inheritance tree
04444    //    kIsForeign : the class doe not have a Streamer method
04445    // The value of fStreamerType are
04446    //    kTObject : the class inherits from TObject
04447    //    kForeign : the class does not have a Streamer method
04448    //    kInstrumented: the class does have a Streamer method
04449    //    kExternal: the class has a free standing way of streaming itself
04450    //    kEmulated: the class is missing its shared library.
04451 
04452    R__LOCKGUARD(gCINTMutex);
04453 
04454    if (fProperty!=(-1)) return fProperty;
04455 
04456    // When called via TMapFile (e.g. Update()) make sure that the dictionary
04457    // gets allocated on the heap and not in the mapped file.
04458    TMmallocDescTemp setreset;
04459 
04460    Long_t dummy;
04461    TClass *kl = const_cast<TClass*>(this);
04462 
04463    kl->fStreamerType = kNone;
04464    kl->fStreamerImpl = &TClass::StreamerDefault;
04465 
04466    if (InheritsFrom(TObject::Class())) {
04467       kl->SetBit(kIsTObject);
04468 
04469       // Is it DIRECT inheritance from TObject?
04470       Int_t delta = kl->GetBaseClassOffset(TObject::Class());
04471       if (delta==0) kl->SetBit(kStartWithTObject);
04472 
04473       kl->fStreamerType  = kTObject;
04474       kl->fStreamerImpl  = &TClass::StreamerTObject;
04475    }
04476 
04477    if (fClassInfo) {
04478 
04479       kl->fProperty = gCint->ClassInfo_Property(fClassInfo);
04480 
04481       if (!gCint->ClassInfo_HasMethod(fClassInfo,"Streamer") ||
04482           !gCint->ClassInfo_IsValidMethod(fClassInfo,"Streamer","TBuffer&",&dummy) ) {
04483 
04484          kl->SetBit(kIsForeign);
04485          kl->fStreamerType  = kForeign;
04486          kl->fStreamerImpl  = &TClass::StreamerStreamerInfo;
04487 
04488       } else if ( kl->fStreamerType == kNone ) {
04489          if ( gCint->ClassInfo_FileName(fClassInfo) 
04490              && strcmp( gCint->ClassInfo_FileName(fClassInfo),"{CINTEX dictionary translator}")==0) {
04491             kl->SetBit(kIsForeign);
04492          }
04493          if (kl->fStreamerFunc) {
04494             kl->fStreamerType  = kInstrumented;
04495             kl->fStreamerImpl  = &TClass::StreamerInstrumented;            
04496          } else {
04497             // We have an automatic streamer using the StreamerInfo .. no need to go through the
04498             // Streamer method function itself.
04499             kl->fStreamerType  = kInstrumented;
04500             kl->fStreamerImpl  = &TClass::StreamerStreamerInfo;            
04501          }
04502       }
04503 
04504       if (fStreamer) {
04505          kl->fStreamerType  = kExternal;
04506          kl->fStreamerImpl  = &TClass::StreamerExternal;
04507       }
04508 
04509    } else {
04510 
04511       if (fStreamer) {
04512          kl->fStreamerType  = kExternal;
04513          kl->fStreamerImpl  = &TClass::StreamerExternal;
04514       }
04515 
04516       kl->fStreamerType |= kEmulated;
04517       switch (fStreamerType) {
04518          case kEmulated:               // intentional fall through
04519          case kForeign|kEmulated:      // intentional fall through
04520          case kInstrumented|kEmulated: kl->fStreamerImpl = &TClass::StreamerStreamerInfo; break;
04521          case kExternal|kEmulated:     kl->fStreamerImpl = &TClass::StreamerExternal; break;
04522          case kTObject|kEmulated:      kl->fStreamerImpl = &TClass::StreamerTObjectEmulated; break;
04523       }  
04524       return 0;
04525    }
04526 
04527    return fProperty;
04528 }
04529 
04530 //_____________________________________________________________________________
04531 void TClass::SetCollectionProxy(const ROOT::TCollectionProxyInfo &info)
04532 {
04533    // Create the collection proxy object (and the streamer object) from
04534    // using the information in the TCollectionProxyInfo.
04535 
04536    R__LOCKGUARD(gCINTMutex);
04537 
04538    delete fCollectionProxy;
04539 
04540    // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
04541    // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
04542    // set correctly.
04543 
04544    TVirtualCollectionProxy *p = TVirtualStreamerInfo::Factory()->GenExplicitProxy(info,this);
04545    fCollectionProxy = p;
04546 
04547    AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
04548 }
04549 
04550 //______________________________________________________________________________
04551 void TClass::SetContextMenuTitle(const char *title)
04552 {
04553    // Change (i.e. set) the title of the TNamed.
04554 
04555    fContextMenuTitle = title;
04556 }
04557 
04558 //______________________________________________________________________________
04559 void TClass::SetGlobalIsA(IsAGlobalFunc_t func)
04560 {
04561    // This function installs a global IsA function for this class.
04562    // The global IsA function will be used if there is no local IsA function (fIsA)
04563    //
04564    // A global IsA function has the signature:
04565    //
04566    //    TClass *func( TClass *cl, const void *obj);
04567    //
04568    // 'cl' is a pointer to the  TClass object that corresponds to the
04569    // 'pointer type' used to retrieve the value 'obj'
04570    //
04571    //  For example with:
04572    //    TNamed * m = new TNamed("example","test");
04573    //    TObject* o = m
04574    // and
04575    //    the global IsA function would be called with TObject::Class() as
04576    //    the first parameter and the exact numerical value in the pointer
04577    //    'o'.
04578    //
04579    //  In other word, inside the global IsA function. it is safe to C-style
04580    //  cast the value of 'obj' into a pointer to the class described by 'cl'.
04581 
04582    fGlobalIsA = func;
04583 }
04584 
04585 //______________________________________________________________________________
04586 void TClass::SetUnloaded()
04587 {
04588    // Call this method to indicate that the shared library containing this
04589    // class's code has been removed (unloaded) from the process's memory
04590 
04591    delete fIsA; fIsA = 0;
04592    // Disable the autoloader while calling SetClassInfo, to prevent
04593    // the library from being reloaded!
04594    int autoload_old = gCint->SetClassAutoloading(0);
04595    gInterpreter->SetClassInfo(this,kTRUE);
04596    gCint->SetClassAutoloading(autoload_old);
04597    fDeclFileName = 0;
04598    fDeclFileLine = 0;
04599    fImplFileName = 0;
04600    fImplFileLine = 0;
04601    fTypeInfo     = 0;
04602 
04603    if (fMethod) {
04604       fMethod->Delete();
04605       delete fMethod;
04606       fMethod=0;
04607    }
04608   
04609    SetBit(kUnloaded);
04610 }
04611 
04612 //______________________________________________________________________________
04613 TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
04614 {
04615    // Info is a string describing the names and types of attributes
04616    // written by the class Streamer function.
04617    // If info is an empty string (when called by TObject::StreamerInfo)
04618    // the default Streamer info string is build. This corresponds to
04619    // the case of an automatically generated Streamer.
04620    // In case of user defined Streamer function, it is the user responsability
04621    // to implement a StreamerInfo function (override TObject::StreamerInfo).
04622    // The user must call IsA()->SetStreamerInfo(info) from this function.
04623 
04624    // info is specified, nothing to do, except that we should verify
04625    // that it contains a valid descriptor.
04626 
04627 /*
04628    TDataMember *dm;
04629    Int_t nch = strlen(info);
04630    Bool_t update = kTRUE;
04631    if (nch != 0) {
04632       //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
04633       char *save, *temp, *blank, *colon, *comma;
04634       save = new char[10000];
04635       temp = save;
04636       strlcpy(temp,info,10000);
04637       //remove heading and trailing blanks
04638       while (*temp == ' ') temp++;
04639       while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
04640       if (nch == 0) {delete [] save; return;}
04641       if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
04642       //remove blanks around , or ;
04643       while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
04644       while ((blank = strstr(temp," ;"))) strcpy(blank,  blank+1);
04645       while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
04646       while ((blank = strstr(temp," ,"))) strcpy(blank,  blank+1);
04647       while ((blank = strstr(temp,"  "))) strcpy(blank,  blank+1);
04648       //loop on tokens separated by ;
04649       char *final = new char[1000];
04650       char token[100];
04651       while ((colon=strchr(temp,';'))) {
04652          *colon = 0;
04653          strlcpy(token,temp,100);
04654          blank = strchr(token,' ');
04655          if (blank) {
04656             *blank = 0;
04657             if (!gROOT->GetType(token)) {
04658                Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
04659                return;
04660             }
04661             while (blank) {
04662                strlcat(final,token,1000);
04663                strlcat(final," ",1000);
04664                comma = strchr(blank+1,','); if (comma) *comma=0;
04665                strlcat(final,blank+1,1000);
04666                strlcat(final,";",1000);
04667                blank = comma;
04668             }
04669 
04670          } else {
04671             if (TClass::GetClass(token,update)) {
04672                //a class name
04673                strlcat(final,token,1000); strlcat(final,";",1000);
04674             } else {
04675                //a data member name
04676                dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
04677                if (dm) {
04678                   strlcat(final,dm->GetFullTypeName(),1000);
04679                   strlcat(final," ",1000);
04680                   strlcat(final,token,1000); strlcat(final,";",1000);
04681                } else {
04682                   Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
04683                   return;
04684                }
04685             }
04686             update = kFALSE;
04687          }
04688          temp = colon+1;
04689          if (*temp == 0) break;
04690       }
04691  ////     fStreamerInfo = final;
04692       delete [] final;
04693       delete [] save;
04694       return;
04695    }
04696 
04697    //info is empty. Let's build the default Streamer descriptor
04698 
04699    char *temp = new char[10000];
04700    temp[0] = 0;
04701    char local[100];
04702 
04703    //add list of base classes
04704    TIter nextb(GetListOfBases());
04705    TBaseClass *base;
04706    while ((base = (TBaseClass*) nextb())) {
04707       snprintf(local,100,"%s;",base->GetName());
04708       strlcat(temp,local,10000);
04709    }
04710 
04711    //add list of data members and types
04712    TIter nextd(GetListOfDataMembers());
04713    while ((dm = (TDataMember *) nextd())) {
04714       if (dm->IsEnum()) continue;
04715       if (!dm->IsPersistent()) continue;
04716       Long_t property = dm->Property();
04717       if (property & kIsStatic) continue;
04718       TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
04719       update = kFALSE;
04720       if (acl) {
04721          if (acl->GetClassVersion() == 0) continue;
04722       }
04723 
04724       // dm->GetArrayIndex() returns an empty string if it does not
04725       // applies
04726       const char * index = dm->GetArrayIndex();
04727       if (strlen(index)==0)
04728          snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
04729       else
04730          snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
04731       strlcat(temp,local,10000);
04732    }
04733    //fStreamerInfo = temp;
04734    delete [] temp;
04735 */
04736    return 0;
04737 }
04738 
04739 //______________________________________________________________________________
04740 UInt_t TClass::GetCheckSum(UInt_t code) const
04741 {
04742    // Compute and/or return the class check sum.
04743    // The class ckecksum is used by the automatic schema evolution algorithm
04744    // to uniquely identify a class version.
04745    // The check sum is built from the names/types of base classes and
04746    // data members.
04747    // Algorithm from Victor Perevovchikov (perev@bnl.gov).
04748    //
04749    // if code==1 data members of type enum are not counted in the checksum
04750    // if code==2 return the checksum of data members and base classes, not including the ranges and array size found in comments.  
04751    //            This is needed for backward compatibility.
04752    //
04753    // WARNING: this function must be kept in sync with TClass::GetCheckSum.
04754    // They are both used to handle backward compatibility and should both return the same values.
04755    // TStreamerInfo uses the information in TStreamerElement while TClass uses the information
04756    // from TClass::GetListOfBases and TClass::GetListOfDataMembers.
04757 
04758    R__LOCKGUARD(gCINTMutex);
04759    
04760    if (fCheckSum && code == 0) return fCheckSum;
04761 
04762    UInt_t id = 0;
04763 
04764    int il;
04765    TString name = GetName();
04766    TString type;
04767    il = name.Length();
04768    for (int i=0; i<il; i++) id = id*3+name[i];
04769 
04770    TList *tlb = ((TClass*)this)->GetListOfBases();
04771    if (tlb) {   // Loop over bases
04772 
04773       TIter nextBase(tlb);
04774 
04775       TBaseClass *tbc=0;
04776       while((tbc=(TBaseClass*)nextBase())) {
04777          name = tbc->GetName();
04778          il = name.Length();
04779          for (int i=0; i<il; i++) id = id*3+name[i];
04780       }/*EndBaseLoop*/
04781    }
04782    TList *tlm = ((TClass*)this)->GetListOfDataMembers();
04783    if (tlm) {   // Loop over members
04784       TIter nextMemb(tlm);
04785       TDataMember *tdm=0;
04786       Long_t prop = 0;
04787       while((tdm=(TDataMember*)nextMemb())) {
04788          if (!tdm->IsPersistent())        continue;
04789          //  combine properties
04790          prop = (tdm->Property());
04791          TDataType* tdt = tdm->GetDataType();
04792          if (tdt) prop |= tdt->Property();
04793 
04794          if ( prop&kIsStatic)             continue;
04795          name = tdm->GetName(); il = name.Length();
04796          if ( (code != 1) && prop&kIsEnum) id = id*3 + 1;
04797 
04798          int i;
04799          for (i=0; i<il; i++) id = id*3+name[i];
04800          type = tdm->GetFullTypeName();
04801          if (TClassEdit::IsSTLCont(type))
04802             type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
04803 
04804          il = type.Length();
04805          for (i=0; i<il; i++) id = id*3+type[i];
04806 
04807          int dim = tdm->GetArrayDim();
04808          if (prop&kIsArray) {
04809             for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
04810          }
04811          if (code != 2) {
04812             const char *left = strstr(tdm->GetTitle(),"[");
04813             if (left) {
04814                const char *right = strstr(left,"]");
04815                if (right) {
04816                   ++left;
04817                   while (left != right) {
04818                      id = id*3 + *left;
04819                      ++left;
04820                   }
04821                }
04822             }
04823          }
04824       }/*EndMembLoop*/
04825    }
04826    if (code==0) fCheckSum = id;
04827    return id;
04828 }
04829 
04830 //______________________________________________________________________________
04831 void TClass::AdoptReferenceProxy(TVirtualRefProxy* proxy)
04832 {
04833    // Adopt the Reference proxy pointer to indicate that this class
04834    // represents a reference.
04835    // When a new proxy is adopted, the old one is deleted.
04836 
04837    R__LOCKGUARD(gCINTMutex);
04838 
04839    if ( fRefProxy )  {
04840       fRefProxy->Release();
04841    }
04842    fRefProxy = proxy;
04843    if ( fRefProxy )  {
04844       fRefProxy->SetClass(this);
04845    }
04846 }
04847 
04848 //______________________________________________________________________________
04849 void TClass::AdoptMemberStreamer(const char *name, TMemberStreamer *p)
04850 {
04851    // Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
04852    // member name.
04853 
04854    if (!fRealData) return;
04855 
04856    R__LOCKGUARD(gCINTMutex);
04857 
04858    TIter next(fRealData);
04859    TRealData *rd;
04860    while ((rd = (TRealData*)next())) {
04861       if (strcmp(rd->GetName(),name) == 0) {
04862          // If there is a TStreamerElement that took a pointer to the
04863          // streamer we should inform it!
04864          rd->AdoptStreamer(p);
04865          break;
04866       }
04867    }
04868 
04869 //  NOTE: This alternative was proposed but not is not used for now,
04870 //  One of the major difference with the code above is that the code below
04871 //  did not require the RealData to have been built
04872 //    if (!fData) return;
04873 //    const char *n = name;
04874 //    while (*n=='*') n++;
04875 //    TString ts(n);
04876 //    int i = ts.Index("[");
04877 //    if (i>=0) ts.Remove(i,999);
04878 //    TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
04879 //    if (!dm) {
04880 //       Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
04881 //       return;
04882 //    }
04883 //    dm->SetStreamer(p);
04884    return;
04885 }
04886 
04887 //______________________________________________________________________________
04888 void TClass::SetMemberStreamer(const char *name, MemberStreamerFunc_t p)
04889 {
04890    // Install a new member streamer (p will be copied).
04891 
04892    AdoptMemberStreamer(name,new TMemberStreamer(p));
04893 }
04894 
04895 //______________________________________________________________________________
04896 Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
04897 {
04898    // Function called by the Streamer functions to deserialize information
04899    // from buffer b into object at p.
04900    // This function assumes that the class version and the byte count information
04901    // have been read.
04902    //   version  is the version number of the class
04903    //   start    is the starting position in the buffer b
04904    //   count    is the number of bytes for this object in the buffer
04905 
04906    return b.ReadClassBuffer(this,pointer,version,start,count);
04907 }
04908 
04909 //______________________________________________________________________________
04910 Int_t TClass::ReadBuffer(TBuffer &b, void *pointer)
04911 {
04912    // Function called by the Streamer functions to deserialize information
04913    // from buffer b into object at p.
04914 
04915    return b.ReadClassBuffer(this,pointer);
04916 }
04917 
04918 //______________________________________________________________________________
04919 Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
04920 {
04921    // Function called by the Streamer functions to serialize object at p
04922    // to buffer b. The optional argument info may be specified to give an
04923    // alternative StreamerInfo instead of using the default StreamerInfo
04924    // automatically built from the class definition.
04925    // For more information, see class TVirtualStreamerInfo.
04926 
04927    b.WriteClassBuffer(this,pointer);
04928    return 0;
04929 }
04930 
04931 //______________________________________________________________________________
04932 void TClass::StreamerExternal(void *object, TBuffer &b, const TClass *onfile_class) const
04933 {
04934    //There is special streamer for the class
04935 
04936    //      case kExternal:
04937    //      case kExternal|kEmulated: 
04938 
04939    TClassStreamer *streamer = gThreadTsd ? GetStreamer() : fStreamer;
04940    streamer->Stream(b,object,onfile_class);   
04941 }
04942 
04943 //______________________________________________________________________________
04944 void TClass::StreamerTObject(void *object, TBuffer &b, const TClass * /* onfile_class */) const
04945 {
04946    // Case of TObjects
04947 
04948    // case kTObject:
04949 
04950    if (!fIsOffsetStreamerSet) {
04951       CalculateStreamerOffset();
04952    }
04953    TObject *tobj = (TObject*)((Long_t)object + fOffsetStreamer);
04954    tobj->Streamer(b);
04955 }
04956 
04957 //______________________________________________________________________________
04958 void TClass::StreamerTObjectInitialized(void *object, TBuffer &b, const TClass * /* onfile_class */) const
04959 {
04960    // Case of TObjects when fIsOffsetStreamerSet is known to have been set.
04961 
04962    TObject *tobj = (TObject*)((Long_t)object + fOffsetStreamer);
04963    tobj->Streamer(b);   
04964 }
04965 
04966 //______________________________________________________________________________
04967 void TClass::StreamerTObjectEmulated(void *object, TBuffer &b, const TClass *onfile_class) const
04968 {
04969    // Case of TObjects when we do not have the library defining the class.
04970    
04971    // case kTObject|kEmulated :
04972    if (b.IsReading()) {
04973       b.ReadClassEmulated(this, object, onfile_class);
04974    } else {
04975       b.WriteClassBuffer(this, object);
04976    }            
04977 }
04978 
04979 //______________________________________________________________________________
04980 void TClass::StreamerInstrumented(void *object, TBuffer &b, const TClass * /* onfile_class */) const
04981 {
04982    // Case of instrumented class with a library
04983    
04984    // case kInstrumented:
04985    fStreamerFunc(b,object);
04986 }
04987 
04988 //______________________________________________________________________________
04989 void TClass::StreamerStreamerInfo(void *object, TBuffer &b, const TClass *onfile_class) const
04990 {
04991    // Case of where we should directly use the StreamerInfo.
04992    //    case kForeign:
04993    //    case kForeign|kEmulated:
04994    //    case kInstrumented|kEmulated:
04995    //    case kEmulated:
04996 
04997    if (b.IsReading()) {
04998       b.ReadClassBuffer(this, object, onfile_class);
04999       //ReadBuffer (b, object);
05000    } else {
05001       //WriteBuffer(b, object);
05002       b.WriteClassBuffer(this, object);
05003    }
05004 }
05005 
05006 //______________________________________________________________________________
05007 void TClass::StreamerDefault(void *object, TBuffer &b, const TClass *onfile_class) const
05008 {
05009    // Default streaming in cases where either we have no way to know what to do
05010    // or if Property() has not yet been called.
05011    
05012    if (fProperty==(-1)) {
05013       Property();
05014       if (fStreamerImpl == &TClass::StreamerDefault) {
05015          Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", fStreamerType);        
05016       } else {
05017          (this->*fStreamerImpl)(object,b,onfile_class);
05018       }
05019    } else {
05020       Fatal("StreamerDefault", "fStreamerType not properly initialized (%d)", fStreamerType);
05021    }   
05022 }
05023 
05024 //______________________________________________________________________________
05025 void TClass::AdoptStreamer(TClassStreamer *str)
05026 {
05027    // Adopt a TClassStreamer object.  Ownership is transfered to this TClass
05028    // object.
05029 
05030 //    // This code can be used to quickly test the STL Emulation layer
05031 //    Int_t k = TClassEdit::IsSTLCont(GetName());
05032 //    if (k==1||k==-1) { delete str; return; }
05033 
05034    R__LOCKGUARD(gCINTMutex);
05035 
05036    if (fStreamer) delete fStreamer;
05037    if (str) {
05038       fStreamerType = kExternal | ( fStreamerType&kEmulated );
05039       fStreamer = str;
05040       fStreamerImpl = &TClass::StreamerExternal;
05041    } else if (fStreamer) {
05042       // Case where there was a custom streamer and it is hereby removed,
05043       // we need to reset fStreamerType
05044       fStreamer = str;
05045       fStreamerType = kNone;
05046       if (fProperty != -1) {
05047          fProperty = -1;
05048          Property();
05049       }
05050    }
05051 }
05052 
05053 //______________________________________________________________________________
05054 void TClass::SetStreamerFunc(ClassStreamerFunc_t strm)
05055 {
05056    // Set a wrapper/accessor function around this class custom streamer.
05057    
05058    if (fProperty != -1 && 
05059        ( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) ) 
05060    {
05061       // If the initialization has already been done, make sure to have it redone. 
05062       fStreamerFunc = strm;
05063       fProperty = -1;
05064       Property();
05065    } else {
05066       fStreamerFunc = strm;
05067    }
05068 }
05069 
05070 //______________________________________________________________________________
05071 void TClass::SetNew(ROOT::NewFunc_t newFunc)
05072 {
05073    // Install a new wrapper around 'new'.
05074 
05075    fNew = newFunc;
05076 }
05077 
05078 //______________________________________________________________________________
05079 void TClass::SetNewArray(ROOT::NewArrFunc_t newArrayFunc)
05080 {
05081    // Install a new wrapper around 'new []'.
05082 
05083    fNewArray = newArrayFunc;
05084 }
05085 
05086 //______________________________________________________________________________
05087 void TClass::SetDelete(ROOT::DelFunc_t deleteFunc)
05088 {
05089    // Install a new wrapper around 'delete'.
05090 
05091    fDelete = deleteFunc;
05092 }
05093 
05094 //______________________________________________________________________________
05095 void TClass::SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
05096 {
05097    // Install a new wrapper around 'delete []'.
05098 
05099    fDeleteArray = deleteArrayFunc;
05100 }
05101 
05102 //______________________________________________________________________________
05103 void TClass::SetDestructor(ROOT::DesFunc_t destructorFunc)
05104 {
05105    // Install a new wrapper around the destructor.
05106 
05107    fDestructor = destructorFunc;
05108 }
05109 
05110 //______________________________________________________________________________
05111 void TClass::SetDirectoryAutoAdd(ROOT::DirAutoAdd_t autoAddFunc)
05112 {
05113    // Install a new wrapper around the directory auto add function..
05114    // The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
05115    // and should register 'obj' to the directory if dir is not null
05116    // and unregister 'obj' from its current directory if dir is null
05117 
05118    fDirAutoAdd = autoAddFunc;
05119 }
05120 
05121 //______________________________________________________________________________
05122 TVirtualStreamerInfo *TClass::FindStreamerInfo(UInt_t checksum) const
05123 {
05124    // Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
05125 
05126    Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
05127    for (Int_t i=-1;i<ninfos;++i) {
05128       // TClass::fStreamerInfos has a lower bound not equal to 0,
05129       // so we have to use At and should not use UncheckedAt
05130       TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)fStreamerInfo->UncheckedAt(i);
05131       if (info && info->GetCheckSum() == checksum) {
05132          // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
05133          return info;
05134       }
05135    }
05136    return 0;
05137 }
05138 
05139 //______________________________________________________________________________
05140 TVirtualStreamerInfo *TClass::FindStreamerInfo(TObjArray* arr, UInt_t checksum) const
05141 {
05142    // Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
05143 
05144    Int_t ninfos = arr->GetEntriesFast()-1;
05145    for (Int_t i=-1;i<ninfos;i++) {
05146       // TClass::fStreamerInfos has a lower bound not equal to 0,
05147       // so we have to use At and should not use UncheckedAt
05148       TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)arr->UncheckedAt(i);
05149       if (!info) continue;
05150       if (info->GetCheckSum() == checksum) {
05151          R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
05152          return info;
05153       }
05154    }
05155    return 0;
05156 }
05157 
05158 //______________________________________________________________________________
05159 TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
05160 {
05161    // Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
05162    
05163    TClass *cl = TClass::GetClass( classname );
05164    if( !cl )
05165       return 0;
05166    return GetConversionStreamerInfo( cl, version );
05167 }
05168 
05169 //______________________________________________________________________________
05170 TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const TClass* cl, Int_t version ) const
05171 {
05172    // Return a Conversion StreamerInfo from the class represened by cl for version number 'version' to this class, if any.
05173 
05174    //----------------------------------------------------------------------------
05175    // Check if the classname was specified correctly
05176    //----------------------------------------------------------------------------
05177    if( !cl )
05178       return 0;
05179 
05180    if( cl == this )
05181       return GetStreamerInfo( version );
05182 
05183    //----------------------------------------------------------------------------
05184    // Check if we already have it
05185    //----------------------------------------------------------------------------
05186    TObjArray* arr = 0;
05187    if (fConversionStreamerInfo) {
05188       std::map<std::string, TObjArray*>::iterator it;
05189 
05190       it = fConversionStreamerInfo->find( cl->GetName() );
05191 
05192       if( it != fConversionStreamerInfo->end() ) {
05193          arr = it->second;
05194       }
05195 
05196       if( arr && version > -1 && version < arr->GetSize() && arr->At( version ) )
05197          return (TVirtualStreamerInfo*) arr->At( version );
05198    }
05199 
05200    R__LOCKGUARD(gCINTMutex);
05201 
05202    //----------------------------------------------------------------------------
05203    // We don't have the streamer info so find it in other class
05204    //----------------------------------------------------------------------------
05205    TObjArray *clSI = cl->GetStreamerInfos();
05206    TVirtualStreamerInfo* info = 0;
05207    if( version > -1 && version < clSI->GetSize() )
05208       info = (TVirtualStreamerInfo*)clSI->At( version );
05209 
05210    if( !info )
05211       return 0;
05212 
05213    //----------------------------------------------------------------------------
05214    // We have the right info so we need to clone it to create new object with
05215    // non artificial streamer elements and we should build it for current class
05216    //----------------------------------------------------------------------------
05217    info = (TVirtualStreamerInfo*)info->Clone();
05218 
05219    if( !info->BuildFor( this ) ) {
05220       delete info;
05221       return 0;
05222    }
05223 
05224    if (!info->IsCompiled()) {
05225       // Streamer info has not been compiled, but exists.
05226       // Therefore it was read in from a file and we have to do schema evolution?
05227       // Or it didn't have a dictionary before, but does now?
05228       info->BuildOld();
05229    } else if (info->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) {
05230       // Undo optimization if the global flag tells us to.
05231       info->Compile();
05232    }
05233    
05234    //----------------------------------------------------------------------------
05235    // Cache this treamer info
05236    //----------------------------------------------------------------------------
05237    if (!arr) {
05238       arr = new TObjArray(version+10, -1);
05239       if (!fConversionStreamerInfo) {
05240          fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
05241       }
05242       (*fConversionStreamerInfo)[cl->GetName()] = arr;
05243    }
05244    arr->AddAtAndExpand( info, info->GetClassVersion() );
05245    return info;
05246 }
05247 
05248 //______________________________________________________________________________
05249 TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
05250 {
05251    // Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
05252 
05253    TClass *cl = TClass::GetClass( classname );
05254    if( !cl )
05255       return 0;
05256    return FindConversionStreamerInfo( cl, checksum );
05257 }
05258 
05259 //______________________________________________________________________________
05260 TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const TClass* cl, UInt_t checksum ) const
05261 {
05262    // Return a Conversion StreamerInfo from the class represened by cl for the layout represented by 'checksum' to this class, if any.
05263 
05264    //---------------------------------------------------------------------------
05265    // Check if the classname was specified correctly
05266    //---------------------------------------------------------------------------
05267    if( !cl )
05268       return 0;
05269 
05270    if( cl == this )
05271       return FindStreamerInfo( checksum );
05272 
05273    //----------------------------------------------------------------------------
05274    // Check if we already have it
05275    //----------------------------------------------------------------------------
05276    TObjArray* arr = 0;
05277    TVirtualStreamerInfo* info = 0;
05278    if (fConversionStreamerInfo) {
05279       std::map<std::string, TObjArray*>::iterator it;
05280       
05281       it = fConversionStreamerInfo->find( cl->GetName() );
05282       
05283       if( it != fConversionStreamerInfo->end() ) {
05284          arr = it->second;
05285       }
05286       if (arr) {
05287          info = FindStreamerInfo( arr, checksum );
05288       }
05289    }
05290 
05291    if( info )
05292       return info;
05293 
05294    R__LOCKGUARD(gCINTMutex);
05295 
05296    //----------------------------------------------------------------------------
05297    // Get it from the foreign class
05298    //----------------------------------------------------------------------------
05299    info = cl->FindStreamerInfo( checksum );
05300 
05301    if( !info )
05302       return 0;
05303 
05304    //----------------------------------------------------------------------------
05305    // We have the right info so we need to clone it to create new object with
05306    // non artificial streamer elements and we should build it for current class
05307    //----------------------------------------------------------------------------
05308    info = (TVirtualStreamerInfo*)info->Clone();
05309    if( !info->BuildFor( this ) ) {
05310       delete info;
05311       return 0;
05312    }
05313 
05314    if (!info->IsCompiled()) {
05315       // Streamer info has not been compiled, but exists.
05316       // Therefore it was read in from a file and we have to do schema evolution?
05317       // Or it didn't have a dictionary before, but does now?
05318       info->BuildOld();
05319    } else if (info->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) {
05320       // Undo optimization if the global flag tells us to.
05321       info->Compile();
05322    }
05323    
05324    //----------------------------------------------------------------------------
05325    // Cache this treamer info
05326    //----------------------------------------------------------------------------
05327    if (!arr) {
05328       arr = new TObjArray(16, -1);
05329       if (!fConversionStreamerInfo) {
05330          fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
05331       }
05332       (*fConversionStreamerInfo)[cl->GetName()] = arr;
05333    }
05334    arr->AddAtAndExpand( info, info->GetClassVersion() );
05335 
05336    return info;
05337 }
05338 
05339 //______________________________________________________________________________
05340 Bool_t TClass::HasDefaultConstructor() const
05341 {
05342    // Return true if we have access to a default constructor.
05343 
05344    
05345    if (fNew) return kTRUE;
05346 
05347    if (GetClassInfo()) {
05348       R__LOCKGUARD(gCINTMutex);
05349       return gCint->ClassInfo_HasDefaultConstructor(GetClassInfo());
05350    }
05351    if (fCollectionProxy) {
05352       return kTRUE;
05353    }
05354    if (fCurrentInfo) {
05355       // Emulated class, we know how to construct them via the TStreamerInfo
05356       return kTRUE;
05357    }
05358    return kFALSE;
05359 }
05360 
05361 //______________________________________________________________________________
05362 ROOT::NewFunc_t TClass::GetNew() const
05363 {
05364    // Return the wrapper around new ThisClass().
05365 
05366    return fNew;
05367 }
05368 
05369 //______________________________________________________________________________
05370 ROOT::NewArrFunc_t TClass::GetNewArray() const
05371 {
05372    // Return the wrapper around new ThisClass[].
05373 
05374    return fNewArray;
05375 }
05376 
05377 //______________________________________________________________________________
05378 ROOT::DelFunc_t TClass::GetDelete() const
05379 {
05380    // Return the wrapper around delete ThiObject.
05381 
05382    return fDelete;
05383 }
05384 
05385 //______________________________________________________________________________
05386 ROOT::DelArrFunc_t TClass::GetDeleteArray() const
05387 {
05388    // Return the wrapper around delete [] ThiObject.
05389 
05390    return fDeleteArray;
05391 }
05392 
05393 //______________________________________________________________________________
05394 ROOT::DesFunc_t TClass::GetDestructor() const
05395 {
05396    // Return the wrapper around the destructor
05397 
05398    return fDestructor;
05399 }
05400 
05401 //______________________________________________________________________________
05402 ROOT::DirAutoAdd_t TClass::GetDirectoryAutoAdd() const
05403 {
05404    // Return the wrapper around the directory auto add function.
05405 
05406    return fDirAutoAdd;
05407 }
05408 

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