TContainerConverters.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TContainerConverters.cxx 34914 2010-08-20 19:28:06Z pcanal $
00002 // Author: Philippe Canal  11/11/2004
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 // Helper classes to convert collection from ROOT collection to STL     //
00015 // collections                                                          //
00016 //                                                                      //
00017 //////////////////////////////////////////////////////////////////////////
00018 
00019 #include "TContainerConverters.h"
00020 #include "TClonesArray.h"
00021 #include "TStreamerInfo.h"
00022 #include "TVirtualCollectionProxy.h"
00023 #include "TError.h"
00024 #include "TGenCollectionStreamer.h"
00025 #include "TClassStreamer.h"
00026 #include <stdlib.h>
00027 
00028 namespace {
00029    const Int_t  kMapOffset = 2;
00030 }
00031 
00032 //________________________________________________________________________
00033 TConvertClonesArrayToProxy::TConvertClonesArrayToProxy(
00034    TVirtualCollectionProxy *proxy,
00035    Bool_t isPointer, Bool_t isPrealloc) :
00036       fIsPointer(isPointer),
00037       fIsPrealloc(isPrealloc),
00038       fProxy(proxy?proxy->Generate():0)
00039 {
00040    // Constructor.
00041 
00042    if (isPointer) fOffset = sizeof(TClonesArray*);
00043    else fOffset = sizeof(TClonesArray*);
00044 }
00045 
00046 //________________________________________________________________________
00047 TConvertClonesArrayToProxy::~TConvertClonesArrayToProxy()
00048 {
00049    // Destructor.
00050 
00051    delete fProxy;
00052 }
00053 
00054 //________________________________________________________________________
00055 void TConvertClonesArrayToProxy::operator()(TBuffer &b, void *pmember, Int_t size)
00056 {
00057    // Read a TClonesArray from the TBuffer b and load it into a (stl) collection
00058 
00059    TStreamerInfo *subinfo = (TStreamerInfo*)fProxy->GetValueClass()->GetStreamerInfo();
00060    R__ASSERT(subinfo);
00061 
00062    Int_t   nobjects, dummy;
00063    char    nch;
00064    TString s;
00065    char classv[256];
00066    void *env;
00067    UInt_t start, bytecount;
00068 
00069    R__ASSERT(b.IsReading());
00070 
00071    Bool_t needAlloc = fIsPointer && !fIsPrealloc;
00072 
00073    if (needAlloc) {
00074       char *addr = (char*)pmember;
00075       for(Int_t k=0; k<size; ++k, addr += fOffset ) {
00076          if (*(void**)addr && TStreamerInfo::CanDelete()) {
00077             fProxy->GetValueClass()->Destructor(*(void**)addr,kFALSE); // call delete and desctructor
00078          }
00079          //*(void**)addr = fProxy->New();
00080          //TClonesArray *clones = (TClonesArray*)ReadObjectAny(TClonesArray::Class());
00081       }
00082    }
00083 
00084    char *addr = (char*)pmember;
00085    if (size==0) size=1;
00086    for(Int_t k=0; k<size; ++k, addr += fOffset ) {
00087 
00088       if (needAlloc) {
00089          // Read the class name.
00090 
00091          // make sure fMap is initialized
00092          b.InitMap();
00093 
00094          // before reading object save start position
00095          UInt_t startpos = b.Length();
00096 
00097          // attempt to load next object as TClass clCast
00098          UInt_t tag;       // either tag or byte count
00099          TClass *clRef = b.ReadClass(TClonesArray::Class(), &tag);
00100 
00101          if (clRef==0) {
00102             // Got a reference to an already read object.
00103             if (b.GetBufferVersion() > 0) {
00104                tag += b.GetBufferDisplacement();
00105             } else {
00106                if (tag > (UInt_t)b.GetMapCount()) {
00107                   Error("TConvertClonesArrayToProxy", "object tag too large, I/O buffer corrupted");
00108                   return;
00109                }
00110             }
00111             void *objptr;
00112             b.GetMappedObject( tag, objptr, clRef);
00113             if ( objptr == (void*)-1 ) {
00114                Error("TConvertClonesArrayToProxy",
00115                   "Object can not be found in the buffer's map (at %d)",tag);
00116                continue;
00117             }
00118             if ( objptr == 0 ) {
00119                if (b.GetBufferVersion()==0) continue;
00120 
00121                // No object found at this location in map. It might have been skipped
00122                // as part of a skipped object. Try to explicitely read the object.
00123                b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), 0);
00124                Int_t currentpos = b.Length();
00125                b.SetBufferOffset( tag - kMapOffset );
00126 
00127                (*this)(b,&objptr,1);
00128                b.SetBufferOffset( currentpos);
00129 
00130                if (objptr==0) continue;
00131 
00132                clRef = fProxy->GetCollectionClass();
00133 
00134             }
00135             R__ASSERT(clRef);
00136             if (clRef==TClonesArray::Class()) {
00137                Error("TConvertClonesArrayToProxy",
00138                   "Object refered to has not been converted from TClonesArray to %s",
00139                   fProxy->GetCollectionClass()->GetName());
00140                continue;
00141             } else if (clRef!=fProxy->GetCollectionClass()) {
00142                Error("TConvertClonesArrayToProxy",
00143                   "Object refered to is of type %s instead of %s",
00144                   clRef->GetName(),fProxy->GetCollectionClass()->GetName());
00145                continue;
00146             }
00147             *(void**)addr = objptr;
00148             continue;
00149 
00150          } else if (clRef != TClonesArray::Class()) {
00151             Warning("TConvertClonesArrayToProxy",
00152                     "Only the TClonesArray part of %s will be read into %s!\n",
00153                     (clRef!=((TClass*)-1)&&clRef) ? clRef->GetName() : "N/A",
00154                     fProxy->GetCollectionClass()->GetName());
00155          } else {
00156             *(void**)addr = fProxy->New();
00157             if (b.GetBufferVersion()>0) {
00158                b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), startpos+kMapOffset);
00159             } else {
00160                b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), b.GetMapCount() );
00161             }
00162          }
00163       }
00164       void *obj;
00165       if (fIsPointer) obj = *(void**)addr;
00166       else obj = addr;
00167 
00168       TObject objdummy;
00169       Version_t v = b.ReadVersion(&start, &bytecount);
00170 
00171       //if (v == 3) {
00172       //   const int_t koldbypassstreamer = bit(14);
00173       //   if (testbit(koldbypassstreamer)) bypassstreamer();
00174       //}
00175       if (v > 2) objdummy.Streamer(b);
00176       TString fName;
00177       if (v > 1) fName.Streamer(b);
00178       s.Streamer(b);
00179       strncpy(classv,s.Data(),255);
00180       Int_t clv = 0;
00181       char *semicolon = strchr(classv,';');
00182       if (semicolon) {
00183          *semicolon = 0;
00184          clv = atoi(semicolon+1);
00185       }
00186       TClass *cl = TClass::GetClass(classv);
00187       if (!cl) {
00188          printf("TClonesArray::Streamer expecting class %s\n", classv);
00189          b.CheckByteCount(start, bytecount, TClonesArray::Class());
00190          return;
00191       }
00192 
00193       b >> nobjects;
00194       if (nobjects < 0) nobjects = -nobjects;  // still there for backward compatibility
00195       b >> dummy; // fLowerBound is ignored
00196       if (cl != subinfo->GetClass()) {
00197          Error("TClonesArray::Conversion to vector","Bad class");
00198       }
00199       TVirtualCollectionProxy::TPushPop helper( fProxy, obj );
00200       env = fProxy->Allocate(nobjects,true);
00201 
00202       if (objdummy.TestBit(TClonesArray::kBypassStreamer)) {
00203 
00204          subinfo->ReadBufferSTL(b,fProxy,nobjects,-1,0);
00205 
00206       } else {
00207          for (Int_t i = 0; i < nobjects; i++) {
00208             b >> nch;
00209             if (nch) {
00210                void* elem = fProxy->At(i);
00211                b.StreamObject(elem,subinfo->GetClass());
00212             }
00213          }
00214       }
00215       fProxy->Commit(env);
00216       b.CheckByteCount(start, bytecount,TClonesArray::Class());
00217    }
00218 }
00219 
00220 //________________________________________________________________________
00221 TConvertMapToProxy::TConvertMapToProxy(TClassStreamer *streamer,
00222                                        Bool_t isPointer, Bool_t isPrealloc) :
00223    fIsPointer(isPointer),
00224    fIsPrealloc(isPrealloc),
00225    fSizeOf(0)
00226 {
00227    // Constructor.
00228 
00229    TCollectionClassStreamer *middleman = dynamic_cast<TCollectionClassStreamer*>(streamer);
00230    if (middleman) {
00231       fProxy = middleman->GetXYZ();
00232       fCollectionStreamer = dynamic_cast<TGenCollectionStreamer*>(middleman->GetXYZ());
00233 
00234       if (isPointer) fSizeOf = sizeof(void*);
00235       else fSizeOf = fProxy->GetCollectionClass()->Size();
00236 
00237       if (fProxy->GetValueClass()->GetStreamerInfo() == 0
00238           || fProxy->GetValueClass()->GetStreamerInfo()->GetElements()->At(1) == 0 ) {
00239          // We do not have enough information on the pair (or its not a pair).
00240          fCollectionStreamer = 0;
00241       }
00242    }
00243 }
00244 
00245 
00246 
00247 //________________________________________________________________________
00248 void TConvertMapToProxy::operator()(TBuffer &b, void *pmember, Int_t size)
00249 {
00250    // Read a std::map or std::multimap from the TBuffer b and load it into a (stl) collection
00251 
00252    R__ASSERT(b.IsReading());
00253    R__ASSERT(fCollectionStreamer);
00254 
00255    Bool_t needAlloc = fIsPointer && !fIsPrealloc;
00256 
00257    R__ASSERT(!needAlloc); // not yet implemented
00258 
00259    if (needAlloc) {
00260       char *addr = (char*)pmember;
00261       for(Int_t k=0; k<size; ++k, addr += fSizeOf ) {
00262          if (*(void**)addr && TStreamerInfo::CanDelete()) {
00263             fProxy->GetValueClass()->Destructor(*(void**)addr,kFALSE); // call delete and desctructor
00264          }
00265          //*(void**)addr = fProxy->New();
00266          //TClonesArray *clones = (TClonesArray*)ReadObjectAny(TClonesArray::Class());
00267       }
00268    }
00269 
00270    
00271    char *addr = (char*)pmember;
00272    if (size==0) size=1;
00273    for(Int_t k=0; k<size; ++k, addr += fSizeOf) {
00274 
00275       if (needAlloc) {
00276          
00277          // Read the class name.
00278 
00279       }
00280 
00281       void *obj;
00282       if (fIsPointer) obj = *(void**)addr;
00283       else obj = addr;
00284 
00285       TVirtualCollectionProxy::TPushPop env(fProxy, obj);
00286       fCollectionStreamer->StreamerAsMap(b);
00287 
00288    }
00289 }

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