Logo ROOT  
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
28#include "TClonesArray.h"
29#include "TStreamerInfo.h"
31#include "TError.h"
33#include "TClassStreamer.h"
34#include <stdlib.h>
35
36namespace {
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
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
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}
void Class()
Definition: Class.C:29
#define b(i)
Definition: RSha256.hxx:100
static RooMathCoreReg dummy
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Int_t kMapOffset
Definition: TBufferFile.cxx:55
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
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:4440
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5169
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2852
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5454
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2835
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:2906
An array of clone (identical) objects.
Definition: TClonesArray.h:32
Class streamer object to implement TClassStreamer functionality for I/O emulation.
TGenCollectionProxy * GetXYZ()
void operator()(TBuffer &b, void *pmember, Int_t size=0)
Read a TClonesArray from the TBuffer b and load it into a (stl) collection.
TConvertClonesArrayToProxy(TVirtualCollectionProxy *proxy, Bool_t isPointer, Bool_t isPrealloc)
Constructor.
TConvertMapToProxy(TClassStreamer *streamer, Bool_t isPointer, Bool_t isPrealloc)
Constructor.
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.
virtual void StreamerAsMap(TBuffer &refBuffer)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
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.
TClass * GetClass() const
Basic string class.
Definition: TString.h:131
virtual void * New() const
virtual TClass * GetValueClass() const =0
virtual void Commit(void *)=0
virtual void * At(UInt_t idx)=0
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
virtual TClass * GetCollectionClass() const
virtual TObjArray * GetElements() const =0
static Bool_t CanDelete()
static function returning true if ReadBuffer can delete object
static constexpr double s