00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00041
00042 if (isPointer) fOffset = sizeof(TClonesArray*);
00043 else fOffset = sizeof(TClonesArray*);
00044 }
00045
00046
00047 TConvertClonesArrayToProxy::~TConvertClonesArrayToProxy()
00048 {
00049
00050
00051 delete fProxy;
00052 }
00053
00054
00055 void TConvertClonesArrayToProxy::operator()(TBuffer &b, void *pmember, Int_t size)
00056 {
00057
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);
00078 }
00079
00080
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
00090
00091
00092 b.InitMap();
00093
00094
00095 UInt_t startpos = b.Length();
00096
00097
00098 UInt_t tag;
00099 TClass *clRef = b.ReadClass(TClonesArray::Class(), &tag);
00100
00101 if (clRef==0) {
00102
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
00122
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
00172
00173
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;
00195 b >> dummy;
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
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
00240 fCollectionStreamer = 0;
00241 }
00242 }
00243 }
00244
00245
00246
00247
00248 void TConvertMapToProxy::operator()(TBuffer &b, void *pmember, Int_t size)
00249 {
00250
00251
00252 R__ASSERT(b.IsReading());
00253 R__ASSERT(fCollectionStreamer);
00254
00255 Bool_t needAlloc = fIsPointer && !fIsPrealloc;
00256
00257 R__ASSERT(!needAlloc);
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);
00264 }
00265
00266
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
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 }