ROOT  6.06/09
Reference Guide
TContainerConverters.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id: 56ae10c519627872e1dd40872fd459c2dd89acf6 $
2 // Author: Philippe Canal 11/11/2004
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // Helper classes to convert collection from ROOT collection to STL //
15 // collections //
16 // //
17 //////////////////////////////////////////////////////////////////////////
18 
19 /**
20  \class TConvertClonesArrayToProxy TContainerConverters.cxx
21  \ingroup IO
22 
23  Small helper to read a TBuffer containing a TClonesArray into any valid
24  collection.
25 */
26 
27 #include "TContainerConverters.h"
28 #include "TClonesArray.h"
29 #include "TStreamerInfo.h"
31 #include "TError.h"
32 #include "TGenCollectionStreamer.h"
33 #include "TClassStreamer.h"
34 #include <stdlib.h>
35 
36 namespace {
37  const Int_t kMapOffset = 2;
38 }
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 /// Constructor.
42 
45  Bool_t isPointer, Bool_t isPrealloc) :
46  fIsPointer(isPointer),
47  fIsPrealloc(isPrealloc),
48  fCollectionClass(proxy?proxy->GetCollectionClass():0)
49 {
50  if (isPointer) fOffset = sizeof(TClonesArray*);
51  else fOffset = sizeof(TClonesArray*);
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// Destructor.
56 
58 {
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Read a TClonesArray from the TBuffer b and load it into a (stl) collection
63 
65 {
66  // For thread-safety we need to go through TClass::GetCollectionProxy
67  // to get a thread local proxy.
70  R__ASSERT(subinfo);
71 
72  Int_t nobjects, dummy;
73  char nch;
74  TString s;
75  char classv[256];
76  void *env;
77  UInt_t start, bytecount;
78 
79  R__ASSERT(b.IsReading());
80 
81  Bool_t needAlloc = fIsPointer && !fIsPrealloc;
82 
83  if (needAlloc) {
84  char *addr = (char*)pmember;
85  for(Int_t k=0; k<size; ++k, addr += fOffset ) {
86  if (*(void**)addr && TStreamerInfo::CanDelete()) {
87  proxy->GetValueClass()->Destructor(*(void**)addr,kFALSE); // call delete and desctructor
88  }
89  //*(void**)addr = proxy->New();
90  //TClonesArray *clones = (TClonesArray*)ReadObjectAny(TClonesArray::Class());
91  }
92  }
93 
94  char *addr = (char*)pmember;
95  if (size==0) size=1;
96  for(Int_t k=0; k<size; ++k, addr += fOffset ) {
97 
98  if (needAlloc) {
99  // Read the class name.
100 
101  // make sure fMap is initialized
102  b.InitMap();
103 
104  // before reading object save start position
105  UInt_t startpos = b.Length();
106 
107  // attempt to load next object as TClass clCast
108  UInt_t tag; // either tag or byte count
109  TClass *clRef = b.ReadClass(TClonesArray::Class(), &tag);
110 
111  if (clRef==0) {
112  // Got a reference to an already read object.
113  if (b.GetBufferVersion() > 0) {
114  tag += b.GetBufferDisplacement();
115  } else {
116  if (tag > (UInt_t)b.GetMapCount()) {
117  Error("TConvertClonesArrayToProxy", "object tag too large, I/O buffer corrupted");
118  return;
119  }
120  }
121  void *objptr;
122  b.GetMappedObject( tag, objptr, clRef);
123  if ( objptr == (void*)-1 ) {
124  Error("TConvertClonesArrayToProxy",
125  "Object can not be found in the buffer's map (at %d)",tag);
126  continue;
127  }
128  if ( objptr == 0 ) {
129  if (b.GetBufferVersion()==0) continue;
130 
131  // No object found at this location in map. It might have been skipped
132  // as part of a skipped object. Try to explicitly read the object.
133  b.MapObject(*(void**)addr, fCollectionClass, 0);
134  Int_t currentpos = b.Length();
135  b.SetBufferOffset( tag - kMapOffset );
136 
137  (*this)(b,&objptr,1);
138  b.SetBufferOffset( currentpos);
139 
140  if (objptr==0) continue;
141 
142  clRef = fCollectionClass;
143 
144  }
145  R__ASSERT(clRef);
146  if (clRef==TClonesArray::Class()) {
147  Error("TConvertClonesArrayToProxy",
148  "Object refered to has not been converted from TClonesArray to %s",
150  continue;
151  } else if (clRef!=fCollectionClass) {
152  Error("TConvertClonesArrayToProxy",
153  "Object refered to is of type %s instead of %s",
154  clRef->GetName(),fCollectionClass->GetName());
155  continue;
156  }
157  *(void**)addr = objptr;
158  continue;
159 
160  } else if (clRef != TClonesArray::Class()) {
161  Warning("TConvertClonesArrayToProxy",
162  "Only the TClonesArray part of %s will be read into %s!\n",
163  (clRef!=((TClass*)-1)&&clRef) ? clRef->GetName() : "N/A",
165  } else {
166  *(void**)addr = proxy->New();
167  if (b.GetBufferVersion()>0) {
168  b.MapObject(*(void**)addr, fCollectionClass, startpos+kMapOffset);
169  } else {
170  b.MapObject(*(void**)addr, fCollectionClass, b.GetMapCount() );
171  }
172  }
173  }
174  void *obj;
175  if (fIsPointer) obj = *(void**)addr;
176  else obj = addr;
177 
178  TObject objdummy;
179  Version_t v = b.ReadVersion(&start, &bytecount);
180 
181  //if (v == 3) {
182  // const int_t koldbypassstreamer = bit(14);
183  // if (testbit(koldbypassstreamer)) bypassstreamer();
184  //}
185  if (v > 2) objdummy.Streamer(b);
186  TString fName;
187  if (v > 1) fName.Streamer(b);
188  s.Streamer(b);
189  strncpy(classv,s.Data(),255);
190  //Int_t clv = 0;
191  char *semicolon = strchr(classv,';');
192  if (semicolon) {
193  *semicolon = 0;
194  //clv = atoi(semicolon+1);
195  }
196  TClass *cl = TClass::GetClass(classv);
197  if (!cl) {
198  printf("TClonesArray::Streamer expecting class %s\n", classv);
199  b.CheckByteCount(start, bytecount, TClonesArray::Class());
200  return;
201  }
202 
203  b >> nobjects;
204  if (nobjects < 0) nobjects = -nobjects; // still there for backward compatibility
205  b >> dummy; // fLowerBound is ignored
206  if (cl != subinfo->GetClass()) {
207  Error("TClonesArray::Conversion to vector","Bad class");
208  }
209  TVirtualCollectionProxy::TPushPop helper( proxy, obj );
210  env = proxy->Allocate(nobjects,true);
211 
212  if (objdummy.TestBit(TClonesArray::kBypassStreamer)) {
213 
214  subinfo->ReadBufferSTL(b,proxy,nobjects,0);
215 
216  } else {
217  for (Int_t i = 0; i < nobjects; i++) {
218  b >> nch;
219  if (nch) {
220  void* elem = proxy->At(i);
221  b.StreamObject(elem,subinfo->GetClass());
222  }
223  }
224  }
225  proxy->Commit(env);
226  b.CheckByteCount(start, bytecount,TClonesArray::Class());
227  }
228 }
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Constructor.
232 
234  Bool_t isPointer, Bool_t isPrealloc) :
235  fIsPointer(isPointer),
236  fIsPrealloc(isPrealloc),
237  fSizeOf(0),
238  fCollectionClass(0)
239 {
240  TCollectionClassStreamer *middleman = dynamic_cast<TCollectionClassStreamer*>(streamer);
241  if (middleman) {
242  TVirtualCollectionProxy *proxy = middleman->GetXYZ();
243  TGenCollectionStreamer *collStreamer = dynamic_cast<TGenCollectionStreamer*>(proxy);
244 
246 
247  if (isPointer) fSizeOf = sizeof(void*);
248  else fSizeOf = fCollectionClass->Size();
249 
250  if (proxy->GetValueClass()->GetStreamerInfo() == 0
251  || proxy->GetValueClass()->GetStreamerInfo()->GetElements()->At(1) == 0 ) {
252  // We do not have enough information on the pair (or its not a pair).
253  collStreamer = 0;
254  }
255  if (!collStreamer) fCollectionClass = 0;
256  }
257 }
258 
259 
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Read a std::map or std::multimap from the TBuffer b and load it into a (stl) collection
263 
264 void TConvertMapToProxy::operator()(TBuffer &b, void *pmember, Int_t size)
265 {
266  R__ASSERT(b.IsReading());
268 
269  // For thread-safety we need to go through TClass::GetStreamer
270  // to get a thread local proxy.
272  TVirtualCollectionProxy *proxy = middleman->GetXYZ();
273  TGenCollectionStreamer *collStreamer = dynamic_cast<TGenCollectionStreamer*>(proxy);
274 
275  Bool_t needAlloc = fIsPointer && !fIsPrealloc;
276 
277  R__ASSERT(!needAlloc); // not yet implemented
278 
279  if (needAlloc) {
280  char *addr = (char*)pmember;
281  for(Int_t k=0; k<size; ++k, addr += fSizeOf ) {
282  if (*(void**)addr && TStreamerInfo::CanDelete()) {
283  proxy->GetValueClass()->Destructor(*(void**)addr,kFALSE); // call delete and desctructor
284  }
285  //*(void**)addr = proxy->New();
286  //TClonesArray *clones = (TClonesArray*)ReadObjectAny(TClonesArray::Class());
287  }
288  }
289 
290 
291  char *addr = (char*)pmember;
292  if (size==0) size=1;
293  for(Int_t k=0; k<size; ++k, addr += fSizeOf) {
294 
295  if (needAlloc) {
296 
297  // Read the class name.
298 
299  }
300 
301  void *obj;
302  if (fIsPointer) obj = *(void**)addr;
303  else obj = addr;
304 
305  TVirtualCollectionProxy::TPushPop env(proxy, obj);
306  collStreamer->StreamerAsMap(b);
307 
308  }
309 }
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:88
static Bool_t CanDelete()
static function returning true if ReadBuffer can delete object
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
Class streamer object to implement TClassStreamer functionality for I/O emulation.
const Int_t kMapOffset
Definition: TBufferFile.cxx:59
virtual void GetMappedObject(UInt_t tag, void *&ptr, TClass *&ClassPtr) const =0
Bool_t IsReading() const
Definition: TBuffer.h:81
short Version_t
Definition: RtypesCore.h:61
virtual void StreamObject(void *obj, const type_info &typeinfo, const TClass *onFileClass=0)=0
virtual TClass * GetValueClass() const =0
TGenCollectionProxy * GetXYZ()
virtual void Commit(void *)=0
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
#define R__ASSERT(e)
Definition: TError.h:98
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
void operator()(TBuffer &b, void *pmember, Int_t size=0)
Read a TClonesArray from the TBuffer b and load it into a (stl) collection.
virtual TClass * GetCollectionClass() const
virtual void StreamerAsMap(TBuffer &refBuffer)
const char * Data() const
Definition: TString.h:349
void Class()
Definition: Class.C:29
virtual void InitMap()=0
TClass * GetClass() const
void Error(const char *location, const char *msgfmt,...)
Int_t GetBufferVersion() const
Definition: TBuffer.h:80
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4337
SVector< double, 2 > v
Definition: Dict.h:5
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5040
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
virtual void * New() const
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
void Warning(const char *location, const char *msgfmt,...)
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
virtual TObjArray * GetElements() const =0
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
static RooMathCoreReg dummy
virtual void * At(UInt_t idx)=0
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2827
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2810
Mother of all ROOT objects.
Definition: TObject.h:58
An array of clone (identical) objects.
Definition: TClonesArray.h:32
Int_t Length() const
Definition: TBuffer.h:94
virtual TClass * ReadClass(const TClass *cl=0, UInt_t *objTag=0)=0
virtual Int_t GetMapCount() const =0
TConvertMapToProxy(TClassStreamer *streamer, Bool_t isPointer, Bool_t isPrealloc)
Constructor.
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
Int_t ReadBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t eoffset, Bool_t v7=kTRUE)
The STL vector/list is deserialized from the buffer b.
TObject * obj
TConvertClonesArrayToProxy(TVirtualCollectionProxy *proxy, Bool_t isPointer, Bool_t isPrealloc)
Constructor.
virtual Int_t GetBufferDisplacement() const =0
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5325
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
void operator()(TBuffer &b, void *pmember, Int_t size=0)
Read a std::map or std::multimap from the TBuffer b and load it into a (stl) collection.