TEmulatedCollectionProxy.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TEmulatedCollectionProxy.cxx 37087 2010-11-29 21:59:13Z pcanal $
00002 // Author: Markus Frank 28/10/04
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 // TEmulatedCollectionProxy
00015 //
00016 // Streamer around an arbitrary container, which implements basic
00017 // functionality and iteration.
00018 //
00019 // In particular this is used to implement splitting and abstract
00020 // element access of any container. Access to compiled code is necessary
00021 // to implement the abstract iteration sequence and functionality like
00022 // size(), clear(), resize(). resize() may be a void operation.
00023 //
00024 //////////////////////////////////////////////////////////////////////////
00025 
00026 #include "TEmulatedCollectionProxy.h"
00027 #include "TStreamerElement.h"
00028 #include "TStreamerInfo.h"
00029 #include "TClassEdit.h"
00030 #include "TError.h"
00031 #include "TROOT.h"
00032 #include "Riostream.h"
00033 
00034 #include "TVirtualMutex.h" // For R__LOCKGUARD
00035 
00036 //
00037 // Utility function to allow the creation of a TClass for a std::pair without
00038 // a dictionary (See end of file for implementation
00039 //
00040 
00041 static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset);
00042 static TStreamerInfo *R__GenerateTClassForPair(const string &f, const string &s);
00043 
00044 TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy)
00045    : TGenCollectionProxy(copy)
00046 {
00047    // Build a Streamer for an emulated vector whose type is 'name'.
00048    fProperties |= kIsEmulated;
00049 }
00050 
00051 TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name)
00052    : TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator))
00053 {
00054    // Build a Streamer for a collection whose type is described by 'collectionClass'.
00055 
00056    fName = cl_name;
00057    if ( this->TEmulatedCollectionProxy::InitializeEx() ) {
00058       fCreateEnv = TGenCollectionProxy::Env_t::Create;
00059    }
00060    fProperties |= kIsEmulated;
00061 }
00062 
00063 TEmulatedCollectionProxy::~TEmulatedCollectionProxy()
00064 {
00065    // Standard destructor
00066    if ( fEnv && fEnv->fObject ) {
00067       Clear();
00068    }
00069 }
00070 
00071 TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate() const
00072 {
00073    // Virtual copy constructor
00074 
00075    if ( !fClass ) Initialize();
00076    return new TEmulatedCollectionProxy(*this);
00077 }
00078 
00079 void TEmulatedCollectionProxy::Destructor(void* p, Bool_t dtorOnly)
00080 {
00081    // Virtual destructor
00082 
00083    if (!p) return;
00084    if (!fEnv || fEnv->fObject != p) { // Envoid the cost of TPushPop if we don't need it
00085       TVirtualCollectionProxy::TPushPop env(this, p);
00086       Clear("force");
00087    } else {
00088       Clear("force");
00089    }      
00090    if (dtorOnly) {
00091       ((Cont_t*)p)->~Cont_t();
00092    } else {
00093       delete (Cont_t*) p;
00094    }
00095 }
00096 
00097 void TEmulatedCollectionProxy::DeleteArray(void* p, Bool_t dtorOnly)
00098 {
00099    // Virtual array destructor
00100 
00101    // Cannot implement this properly, we do not know
00102    // how many elements are in the array.
00103    Warning("DeleteArray", "Cannot properly delete emulated array of %s at %p, I don't know how many elements it has!", fClass->GetName(), p);
00104    if (!dtorOnly) {
00105       delete[] (Cont_t*) p;
00106    }
00107 }
00108 
00109 TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx()
00110 {
00111    // Proxy initializer
00112    R__LOCKGUARD2(gCollectionMutex);
00113    if (fClass) return this;
00114 
00115 
00116    TClass *cl = TClass::GetClass(fName.c_str());
00117    fEnv = 0;
00118    fKey = 0;
00119    if ( cl )  {
00120       int nested = 0;
00121       std::vector<std::string> inside;
00122       fPointers  = false;
00123       int num = TClassEdit::GetSplit(fName.c_str(),inside,nested);
00124       if ( num > 1 )  {
00125          std::string nam;
00126          if ( inside[0].find("stdext::hash_") != std::string::npos ) {
00127             inside[0].replace(3,10,"::");
00128          }
00129          if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos ) {
00130             inside[0].replace(0,16,"std::");
00131          }
00132          fSTL_type = TClassEdit::STLKind(inside[0].c_str());
00133          // Note: an emulated collection proxy is never really associative
00134          // since under-neath is actually an array.
00135 
00136          // std::cout << "Initialized " << typeid(*this).name() << ":" << fName << std::endl;
00137          int slong = sizeof(void*);
00138          switch ( fSTL_type )  {
00139             case TClassEdit::kMap:
00140             case TClassEdit::kMultiMap:
00141                nam = "pair<"+inside[1]+","+inside[2];
00142                nam += (nam[nam.length()-1]=='>') ? " >" : ">";
00143                if (0==TClass::GetClass(nam.c_str())) {
00144                   // We need to emulate the pair
00145                   R__GenerateTClassForPair(inside[1],inside[2]);
00146                }
00147                fValue = new Value(nam);
00148                fKey   = new Value(inside[1]);
00149                fVal   = new Value(inside[2]);
00150                if ( !fValue->IsValid() || !fKey->IsValid() || !fVal->IsValid() ) {
00151                   return 0;
00152                }
00153                fPointers |= 0 != (fKey->fCase&G__BIT_ISPOINTER);
00154                if ( 0 == fValDiff )  {
00155                   fValDiff = fKey->fSize + fVal->fSize;
00156                   fValDiff += (slong - fKey->fSize%slong)%slong;
00157                   fValDiff += (slong - fValDiff%slong)%slong;
00158                }
00159                if ( 0 == fValOffset )  {
00160                   fValOffset  = fKey->fSize;
00161                   fValOffset += (slong - fKey->fSize%slong)%slong;
00162                }
00163                break;
00164             case TClassEdit::kBitSet:
00165                inside[1] = "bool";
00166                // Intentional fall through
00167             default:
00168                fValue = new Value(inside[1]);
00169                fVal   = new Value(*fValue);
00170                if ( !fValue->IsValid() || !fVal->IsValid() ) {
00171                   return 0;
00172                }
00173                if ( 0 == fValDiff )  {
00174                   fValDiff  = fVal->fSize;
00175                   if (fVal->fCase != G__BIT_ISFUNDAMENTAL) {
00176                      fValDiff += (slong - fValDiff%slong)%slong;
00177                   }
00178                }
00179                break;
00180          }
00181          fPointers |= 0 != (fVal->fCase&G__BIT_ISPOINTER);
00182          fClass = cl;
00183          return this;
00184       }
00185       Fatal("TEmulatedCollectionProxy","Components of %s not analysed!",cl->GetName());
00186    }
00187    Fatal("TEmulatedCollectionProxy","Collection class %s not found!",fTypeinfo.name());
00188    return 0;
00189 }
00190 
00191 Bool_t TEmulatedCollectionProxy::IsValid() const 
00192 {
00193    // Return true if the collection proxy was well initialized.
00194    return  (0 != fCreateEnv.call);
00195 }
00196 
00197 UInt_t TEmulatedCollectionProxy::Size() const
00198 {
00199    // Return the current size of the container
00200 
00201    if ( fEnv && fEnv->fObject )   {
00202       return fEnv->fSize = PCont_t(fEnv->fObject)->size()/fValDiff;
00203    }
00204    Fatal("TEmulatedCollectionProxy","Size> Logic error - no proxy object set.");
00205    return 0;
00206 }
00207 
00208 void TEmulatedCollectionProxy::Clear(const char* opt)
00209 {
00210    // Clear the emulated collection.
00211    Resize(0, opt && *opt=='f');
00212 }
00213 
00214 void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t force )
00215 {
00216    // Shrink the container
00217 
00218    typedef std::string  String_t;
00219    PCont_t c   = PCont_t(fEnv->fObject);
00220    char* addr  = ((char*)fEnv->fStart) + fValDiff*left;
00221    size_t i;
00222 
00223    switch ( fSTL_type )  {
00224       case TClassEdit::kMap:
00225       case TClassEdit::kMultiMap:
00226          addr = ((char*)fEnv->fStart) + fValDiff*left;
00227          switch(fKey->fCase)  {
00228             case G__BIT_ISFUNDAMENTAL:  // Only handle primitives this way
00229             case G__BIT_ISENUM:
00230                break;
00231             case G__BIT_ISCLASS:
00232                for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) {
00233                   // Call emulation in case non-compiled content
00234                   fKey->fType->Destructor(addr, kTRUE);
00235                }
00236                break;
00237             case kBIT_ISSTRING:
00238                for( i=left; i<nCurr; ++i, addr += fValDiff ) {
00239                   ((std::string*)addr)->~String_t();
00240                }
00241                break;
00242             case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00243                for( i=left; i<nCurr; ++i, addr += fValDiff )  {
00244                   StreamHelper* h = (StreamHelper*)addr;
00245                   //Eventually we'll need to delete this
00246                   //(but only when needed).
00247                   void* ptr = h->ptr();
00248                   if (force) fKey->fType->Destructor(ptr);
00249                   h->set(0);
00250                }
00251                break;
00252             case G__BIT_ISPOINTER|kBIT_ISSTRING:
00253                for( i=nCurr; i<left; ++i, addr += fValDiff )   {
00254                   StreamHelper* h = (StreamHelper*)addr;
00255                   //Eventually we'll need to delete this
00256                   //(but only when needed).
00257                   if (force) delete (std::string*)h->ptr();
00258                   h->set(0);
00259                }
00260                break;
00261             case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
00262                for( i=nCurr; i<left; ++i, addr += fValDiff )   {
00263                   StreamHelper* h = (StreamHelper*)addr;
00264                   if (force) delete (TString*)h->ptr();
00265                   h->set(0);
00266                }
00267                break;
00268          }
00269          addr = ((char*)fEnv->fStart)+fValOffset+fValDiff*left;
00270          // DO NOT break; just continue
00271 
00272          // General case for all values
00273       default:
00274          switch( fVal->fCase )  {
00275             case G__BIT_ISFUNDAMENTAL:  // Only handle primitives this way
00276             case G__BIT_ISENUM:
00277                break;
00278             case G__BIT_ISCLASS:
00279                for( i=left; i<nCurr; ++i, addr += fValDiff )  {
00280                   // Call emulation in case non-compiled content
00281                   fVal->fType->Destructor(addr,kTRUE);
00282                }
00283                break;
00284             case kBIT_ISSTRING:
00285                for( i=left; i<nCurr; ++i, addr += fValDiff )
00286                   ((std::string*)addr)->~String_t();
00287                break;
00288             case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00289                for( i=left; i<nCurr; ++i, addr += fValDiff )  {
00290                   StreamHelper* h = (StreamHelper*)addr;
00291                   void* p = h->ptr();
00292                   if ( p && force )  {
00293                      fVal->fType->Destructor(p);
00294                   }
00295                   h->set(0);
00296                }
00297                break;
00298             case G__BIT_ISPOINTER|kBIT_ISSTRING:
00299                for( i=nCurr; i<left; ++i, addr += fValDiff )   {
00300                   StreamHelper* h = (StreamHelper*)addr;
00301                   if (force) delete (std::string*)h->ptr();
00302                   h->set(0);
00303                }
00304                break;
00305             case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
00306                for( i=nCurr; i<left; ++i, addr += fValDiff )   {
00307                   StreamHelper* h = (StreamHelper*)addr;
00308                   if (force) delete (TString*)h->ptr();
00309                   h->set(0);
00310                }
00311                break;
00312          }
00313    }
00314    c->resize(left*fValDiff,0);
00315    fEnv->fStart = left>0 ? &(*c->begin()) : 0;
00316    return;
00317 }
00318 
00319 void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left)
00320 {
00321    // Expand the container
00322    size_t i;
00323    PCont_t c   = PCont_t(fEnv->fObject);
00324    c->resize(left*fValDiff,0);
00325    void *oldstart = fEnv->fStart;
00326    fEnv->fStart = left>0 ? &(*c->begin()) : 0;
00327 
00328    char* addr = ((char*)fEnv->fStart) + fValDiff*nCurr;
00329    switch ( fSTL_type )  {
00330       case TClassEdit::kMap:
00331       case TClassEdit::kMultiMap:
00332          switch(fKey->fCase)  {
00333             case G__BIT_ISFUNDAMENTAL:  // Only handle primitives this way
00334             case G__BIT_ISENUM:
00335                break;
00336             case G__BIT_ISCLASS:
00337                if (oldstart && oldstart != fEnv->fStart) {
00338                   Long_t offset = 0;
00339                   for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
00340                      // For now 'Move' only register the change of location
00341                      // so per se this is wrong since the object are copied via memcpy
00342                      // rather than a copy (or move) constructor.
00343                      fKey->fType->Move(((char*)oldstart)+offset,((char*)fEnv->fStart)+offset);
00344                   }
00345                }
00346                for( i=nCurr; i<left; ++i, addr += fValDiff )
00347                   fKey->fType->New(addr);
00348                break;
00349             case kBIT_ISSTRING:
00350                for( i=nCurr; i<left; ++i, addr += fValDiff )
00351                   ::new(addr) std::string();
00352                break;
00353             case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00354             case G__BIT_ISPOINTER|kBIT_ISSTRING:
00355             case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
00356                for( i=nCurr; i<left; ++i, addr += fValDiff )
00357                   *(void**)addr = 0;
00358                break;
00359          }
00360          addr = ((char*)fEnv->fStart)+fValOffset+fValDiff*nCurr;
00361          // DO NOT break; just continue
00362 
00363          // General case for all values
00364       default:
00365          switch(fVal->fCase)  {
00366             case G__BIT_ISFUNDAMENTAL:  // Only handle primitives this way
00367             case G__BIT_ISENUM:
00368                break;
00369             case G__BIT_ISCLASS:
00370                if (oldstart && oldstart != fEnv->fStart) {
00371                   Long_t offset = 0;
00372                   for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
00373                      // For now 'Move' only register the change of location
00374                      // so per se this is wrong since the object are copied via memcpy
00375                      // rather than a copy (or move) constructor.
00376                      fVal->fType->Move(((char*)oldstart)+offset,((char*)fEnv->fStart)+offset);
00377                   }
00378                }
00379                for( i=nCurr; i<left; ++i, addr += fValDiff ) {
00380                   fVal->fType->New(addr);
00381                }
00382                break;
00383             case kBIT_ISSTRING:
00384                for( i=nCurr; i<left; ++i, addr += fValDiff )
00385                   ::new(addr) std::string();
00386                break;
00387             case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00388             case G__BIT_ISPOINTER|kBIT_ISSTRING:
00389             case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
00390                for( i=nCurr; i<left; ++i, addr += fValDiff )
00391                   *(void**)addr = 0;
00392                break;
00393          }
00394          break;
00395    }
00396 }
00397 
00398 void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force)
00399 {
00400    // Resize the container
00401 
00402    if ( fEnv && fEnv->fObject )   {
00403       size_t nCurr = Size();
00404       PCont_t c = PCont_t(fEnv->fObject);
00405       fEnv->fStart = nCurr>0 ? &(*c->begin()) : 0;
00406       if ( left == nCurr )  {
00407          return;
00408       }
00409       else if ( left < nCurr )  {
00410          Shrink(nCurr, left, force);
00411          return;
00412       }
00413       Expand(nCurr, left);
00414       return;
00415    }
00416    Fatal("TEmulatedCollectionProxy","Resize> Logic error - no proxy object set.");
00417 }
00418 
00419 void* TEmulatedCollectionProxy::At(UInt_t idx)
00420 {
00421    // Return the address of the value at index 'idx'
00422    if ( fEnv && fEnv->fObject )   {
00423       PCont_t c = PCont_t(fEnv->fObject);
00424       size_t  s = c->size();
00425       if ( idx >= (s/fValDiff) )  {
00426          return 0;
00427       }
00428       return idx<(s/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
00429    }
00430    Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set.");
00431    return 0;
00432 }
00433 
00434 void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete)
00435 {
00436    // Allocate the necessary space.
00437 
00438    Resize(n, forceDelete);
00439    return fEnv->fObject;
00440 }
00441 
00442 void TEmulatedCollectionProxy::Commit(void* /* env */ )
00443 {
00444 }
00445 
00446 void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b)
00447 {
00448    // Object input streamer
00449    Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3;
00450    StreamHelper* itm = (StreamHelper*)At(0);
00451    switch (fVal->fCase) {
00452       case G__BIT_ISFUNDAMENTAL:  //  Only handle primitives this way
00453       case G__BIT_ISENUM:
00454          switch( int(fVal->fKind) )   {
00455             case kBool_t:    b.ReadFastArray(&itm->boolean   , nElements); break;
00456             case kChar_t:    b.ReadFastArray(&itm->s_char    , nElements); break;
00457             case kShort_t:   b.ReadFastArray(&itm->s_short   , nElements); break;
00458             case kInt_t:     b.ReadFastArray(&itm->s_int     , nElements); break;
00459             case kLong_t:    b.ReadFastArray(&itm->s_long    , nElements); break;
00460             case kLong64_t:  b.ReadFastArray(&itm->s_longlong, nElements); break;
00461             case kFloat_t:   b.ReadFastArray(&itm->flt       , nElements); break;
00462             case kFloat16_t: b.ReadFastArrayFloat16(&itm->flt, nElements); break;
00463             case kDouble_t:  b.ReadFastArray(&itm->dbl       , nElements); break;
00464             case kBOOL_t:    b.ReadFastArray(&itm->boolean   , nElements); break;
00465             case kUChar_t:   b.ReadFastArray(&itm->u_char    , nElements); break;
00466             case kUShort_t:  b.ReadFastArray(&itm->u_short   , nElements); break;
00467             case kUInt_t:    b.ReadFastArray(&itm->u_int     , nElements); break;
00468             case kULong_t:   b.ReadFastArray(&itm->u_long    , nElements); break;
00469             case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break;
00470             case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break;
00471             case kchar:
00472             case kNoType_t:
00473             case kOther_t:
00474                Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind);
00475          }
00476          break;
00477 
00478 #define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
00479 
00480       case G__BIT_ISCLASS:
00481          DOLOOP( b.StreamObject(i,fVal->fType) );
00482       case kBIT_ISSTRING:
00483          DOLOOP( i->read_std_string(b) );
00484       case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00485          DOLOOP( i->read_any_object(fVal,b) );
00486       case G__BIT_ISPOINTER|kBIT_ISSTRING:
00487          DOLOOP( i->read_std_string_pointer(b) );
00488       case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
00489          DOLOOP( i->read_tstring_pointer(vsn3,b) );
00490    }
00491 
00492 #undef DOLOOP
00493 
00494 }
00495 
00496 void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b)
00497 {
00498    // Object output streamer
00499    StreamHelper* itm = (StreamHelper*)At(0);
00500    switch (fVal->fCase) {
00501       case G__BIT_ISFUNDAMENTAL:  // Only handle primitives this way
00502       case G__BIT_ISENUM:
00503          itm = (StreamHelper*)At(0);
00504             switch( int(fVal->fKind) )   {
00505             case kBool_t:    b.WriteFastArray(&itm->boolean   , nElements); break;
00506             case kChar_t:    b.WriteFastArray(&itm->s_char    , nElements); break;
00507             case kShort_t:   b.WriteFastArray(&itm->s_short   , nElements); break;
00508             case kInt_t:     b.WriteFastArray(&itm->s_int     , nElements); break;
00509             case kLong_t:    b.WriteFastArray(&itm->s_long    , nElements); break;
00510             case kLong64_t:  b.WriteFastArray(&itm->s_longlong, nElements); break;
00511             case kFloat_t:   b.WriteFastArray(&itm->flt       , nElements); break;
00512             case kFloat16_t: b.WriteFastArrayFloat16(&itm->flt, nElements); break;
00513             case kDouble_t:  b.WriteFastArray(&itm->dbl       , nElements); break;
00514             case kBOOL_t:    b.WriteFastArray(&itm->boolean   , nElements); break;
00515             case kUChar_t:   b.WriteFastArray(&itm->u_char    , nElements); break;
00516             case kUShort_t:  b.WriteFastArray(&itm->u_short   , nElements); break;
00517             case kUInt_t:    b.WriteFastArray(&itm->u_int     , nElements); break;
00518             case kULong_t:   b.WriteFastArray(&itm->u_long    , nElements); break;
00519             case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break;
00520             case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break;
00521             case kchar:
00522             case kNoType_t:
00523             case kOther_t:
00524                Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind);
00525          }
00526          break;
00527 #define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
00528       case G__BIT_ISCLASS:
00529          DOLOOP( b.StreamObject(i,fVal->fType) );
00530       case kBIT_ISSTRING:
00531          DOLOOP( TString(i->c_str()).Streamer(b) );
00532       case G__BIT_ISPOINTER|G__BIT_ISCLASS:
00533          DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) );
00534       case kBIT_ISSTRING|G__BIT_ISPOINTER:
00535          DOLOOP( i->write_std_string_pointer(b) );
00536       case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER:
00537          DOLOOP( i->write_tstring_pointer(b) );
00538    }
00539 #undef DOLOOP
00540 }
00541 
00542 void TEmulatedCollectionProxy::ReadBuffer(TBuffer &b, void *obj, const TClass *onfileClass)
00543 {
00544    // Read portion of the streamer.
00545    
00546    SetOnFileClass((TClass*)onfileClass);
00547    ReadBuffer(b,obj);
00548 }
00549 
00550 void TEmulatedCollectionProxy::ReadBuffer(TBuffer &b, void *obj)
00551 {
00552    // Read portion of the streamer.
00553 
00554    TPushPop env(this,obj);
00555    int nElements = 0;
00556    b >> nElements;
00557    if ( fEnv->fObject )  {
00558       Resize(nElements,true);
00559    }
00560    if ( nElements > 0 )  {
00561       ReadItems(nElements, b);
00562    }
00563 }
00564 
00565 void TEmulatedCollectionProxy::Streamer(TBuffer &b)
00566 {
00567    // TClassStreamer IO overload
00568    if ( b.IsReading() ) {  //Read mode
00569       int nElements = 0;
00570       b >> nElements;
00571       if ( fEnv->fObject )  {
00572          Resize(nElements,true);
00573       }
00574       if ( nElements > 0 )  {
00575          ReadItems(nElements, b);
00576       }
00577    }
00578    else {     // Write case
00579       int nElements = fEnv->fObject ? Size() : 0;
00580       b << nElements;
00581       if ( nElements > 0 )  {
00582          WriteItems(nElements, b);
00583       }
00584    }
00585 }
00586 
00587 //
00588 // Utility functions
00589 //
00590 static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset)
00591 {
00592    // Create a TStreamerElement for the type 'dmFull' and whose data member name is 'dmName'.
00593 
00594    TString s1( TClassEdit::ShortType(dmFull,0) );
00595    TString dmType( TClassEdit::ShortType(dmFull,1) );
00596    bool dmIsPtr = (s1 != dmType);
00597    const char *dmTitle = "Emulation";
00598 
00599    TDataType *dt = gROOT->GetType(dmType);
00600    if (dt && dt->GetType() > 0 ) {  // found a basic type
00601       Int_t dsize,dtype;
00602       dtype = dt->GetType();
00603       dsize = dt->Size();
00604       if (dmIsPtr && dtype != kCharStar) {
00605          Error("Pair Emulation Building","%s is not yet supported in pair emulation",
00606                dmFull);
00607          return 0;
00608       } else {
00609          TStreamerElement *el = new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
00610          el->SetSize(dsize);
00611          return el;
00612       }
00613    } else {
00614 
00615       static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
00616       if (strcmp(dmType,"string") == 0 || strcmp(dmType,full_string_name)==0 ) {
00617          return new TStreamerSTLstring(dmName,dmTitle,offset,dmFull,dmIsPtr);
00618       }
00619       if (TClassEdit::IsSTLCont(dmType)) {
00620          return new TStreamerSTL(dmName,dmTitle,offset,dmFull,dmFull,dmIsPtr);
00621       }
00622       TClass *clm = TClass::GetClass(dmType);
00623       if (!clm) {
00624          // either we have an Emulated enum or a really unknown class!
00625          // let's just claim its an enum :(
00626          Int_t dtype = kInt_t;
00627          return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
00628       }
00629       // a pointer to a class
00630       if ( dmIsPtr ) {
00631          if (clm->InheritsFrom(TObject::Class())) {
00632             return new TStreamerObjectPointer(dmName,dmTitle,offset,dmFull);
00633          } else {
00634             return new TStreamerObjectAnyPointer(dmName,dmTitle,offset,dmFull);
00635          }
00636       }
00637       // a class
00638       if (clm->InheritsFrom(TObject::Class())) {
00639          return new TStreamerObject(dmName,dmTitle,offset,dmFull);
00640       } else if(clm == TString::Class() && !dmIsPtr) {
00641          return new TStreamerString(dmName,dmTitle,offset);
00642       } else {
00643          return new TStreamerObjectAny(dmName,dmTitle,offset,dmFull);
00644       }
00645    }
00646 }
00647 
00648 
00649 static TStreamerInfo *R__GenerateTClassForPair(const string &fname, const string &sname)
00650 {
00651    // Generate a TStreamerInfo for a pair<fname,sname>
00652    // This TStreamerInfo is then used as if it was read from a file to generate
00653    // and emulated TClass.
00654    
00655    TStreamerInfo *i = (TStreamerInfo*)TClass::GetClass("pair<const int,int>")->GetStreamerInfo()->Clone();
00656    std::string pname = "pair<"+fname+","+sname;
00657    pname += (pname[pname.length()-1]=='>') ? " >" : ">";
00658    i->SetName(pname.c_str());
00659    i->SetClass(0);
00660    i->GetElements()->Delete();
00661    TStreamerElement *fel = R__CreateEmulatedElement("first", fname.c_str(), 0);
00662    Int_t size = 0;
00663    if (fel) {
00664       i->GetElements()->Add( fel );
00665       
00666       size = fel->GetSize();
00667       Int_t sp = sizeof(void *);
00668 #if defined(R__SGI64)
00669       sp = 8;
00670 #endif
00671       //align the non-basic data types (required on alpha and IRIX!!)
00672       if (size%sp != 0) size = size - size%sp + sp;
00673    } else {
00674       delete i;
00675       return 0;
00676    }
00677    TStreamerElement *second = R__CreateEmulatedElement("second", sname.c_str(), size);
00678    if (second) {
00679       i->GetElements()->Add( second );
00680    } else {
00681       delete i;
00682       return 0;
00683    }
00684    Int_t oldlevel = gErrorIgnoreLevel;
00685    // Hide the warning about the missing pair dictionary.
00686    gErrorIgnoreLevel = kError;
00687    i->BuildCheck();
00688    gErrorIgnoreLevel = oldlevel;
00689    i->BuildOld();
00690    return i;
00691 }

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