Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
TStreamerInfoReadBuffer.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Rene Brun 12/10/2000
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#include "TBuffer.h"
13#include "TFile.h"
14#include "TClass.h"
15#include "TBufferFile.h"
16#include "TClonesArray.h"
17#include "TError.h"
18#include "TRef.h"
19#include "TProcessID.h"
20#include "TStreamer.h"
21#include "TStreamerElement.h"
22#include "TStreamerInfo.h"
25#include "TVirtualArray.h"
26#include "TVirtualObject.h"
27#include "ThreadLocalStorage.h"
28
29// GetCurrentElement.
30// Currently only used by TRef::Streamer.
31
33{
34 //Pointer to current TStreamerElement
35 //Thread local storage.
36
38
39 return fgElement;
40}
41
42////////////////////////////////////////////////////////////////////////////////
43///static function returning a pointer to the current TStreamerElement
44///fgElement points to the current TStreamerElement being read in ReadBuffer
45
50
51//==========CPP macros
52
53#define DOLOOP for(Int_t k=0; k<narr; ++k)
54
55#define ReadBasicTypeElem(name,index) \
56 { \
57 name *x=(name*)(arr[index]+ioffset); \
58 b >> *x; \
59 }
60
61#define ReadBasicType(name) \
62 { \
63 ReadBasicTypeElem(name,0); \
64 }
65
66#define ReadBasicTypeLoop(name) \
67 { \
68 for(Int_t k=0; k<narr; ++k) ReadBasicTypeElem(name,k); \
69 }
70
71#define ReadBasicArrayElem(name,index) \
72 { \
73 name *x=(name*)(arr[index]+ioffset); \
74 b.ReadFastArray(x,compinfo[i]->fLength); \
75 }
76
77#define ReadBasicArray(name) \
78 { \
79 ReadBasicArrayElem(name,0); \
80 }
81
82#define ReadBasicArrayLoop(name) \
83 { \
84 for(Int_t k=0; k<narr; ++k) ReadBasicArrayElem(name,k) \
85 }
86
87#define ReadBasicPointerElem(name,index) \
88 { \
89 Char_t isArray; \
90 b >> isArray; \
91 Int_t *l = (Int_t*)(arr[index]+imethod); \
92 if (*l < 0 || *l > b.BufferSize()) continue; \
93 name **f = (name**)(arr[index]+ioffset); \
94 int j; \
95 if (isArray) for(j=0;j<compinfo[i]->fLength;j++) { \
96 delete [] f[j]; \
97 f[j] = 0; if (*l <=0) continue; \
98 f[j] = new name[*l]; \
99 b.ReadFastArray(f[j],*l); \
100 } \
101 else for(j=0;j<compinfo[i]->fLength;j++) { \
102 delete [] f[j]; \
103 f[j] = 0; \
104 } \
105 }
106
107#define ReadBasicPointer(name) \
108 { \
109 const int imethod = compinfo[i]->fMethod+eoffset; \
110 ReadBasicPointerElem(name,0); \
111 }
112
113#define ReadBasicPointerLoop(name) \
114 { \
115 int imethod = compinfo[i]->fMethod+eoffset; \
116 for(int k=0; k<narr; ++k) { \
117 ReadBasicPointerElem(name,k); \
118 } \
119 }
120
121#define SkipCBasicType(name) \
122 { \
123 name dummy; \
124 DOLOOP{ b >> dummy; } \
125 break; \
126 }
127
128#define SkipCFloat16(name) \
129 { \
130 name dummy; \
131 DOLOOP { b.ReadFloat16(&dummy,aElement); } \
132 break; \
133 }
134
135#define SkipCDouble32(name) \
136 { \
137 name dummy; \
138 DOLOOP { b.ReadDouble32(&dummy,aElement); }\
139 break; \
140 }
141
142#define SkipCBasicArray(name,ReadArrayFunc) \
143 { \
144 name* readbuf = new name[compinfo->fLength]; \
145 DOLOOP { \
146 b.ReadArrayFunc(readbuf, compinfo->fLength); \
147 } \
148 delete[] readbuf; \
149 break; \
150 }
151
152#define SkipCBasicPointer(name,ReadArrayFunc) \
153 { \
154 Int_t addCounter = -111; \
155 if ((imethod>0) && (compinfo->fMethod>0)) addCounter = -1; \
156 if((addCounter<-1) && (aElement!=0) && (aElement->IsA()==TStreamerBasicPointer::Class())) { \
157 TStreamerElement* elemCounter = (TStreamerElement*) thisVar->GetElements()->FindObject(((TStreamerBasicPointer*)aElement)->GetCountName()); \
158 if (elemCounter) addCounter = elemCounter->GetTObjectOffset(); \
159 } \
160 if (addCounter>=-1) { \
161 int len = aElement->GetArrayDim()?aElement->GetArrayLength():1; \
162 Char_t isArray; \
163 DOLOOP { \
164 b >> isArray; \
165 char *arr_k = arr[k]; \
166 Int_t *l = (addCounter==-1 && arr_k) ? (Int_t*)(arr_k+imethod) : &addCounter; \
167 if (*l>0) { \
168 name* readbuf = new name[*l]; \
169 for (int j=0;j<len;j++) \
170 b.ReadArrayFunc(readbuf, *l); \
171 delete[] readbuf; \
172 } \
173 } \
174 } \
175 break; \
176 }
177
178////////////////////////////////////////////////////////////////////////////////
179/// Skip an element.
180
181template <class T>
185{
186 TStreamerInfo* thisVar = this;
187
188 // Skip elements in a TClonesArray
189
190 TClass* cle = compinfo->fClass;
191
192 Int_t imethod = compinfo->fMethod+eoffset;
193
194 switch (kase) {
195
196 // skip basic types
213 UInt_t dummy;
214 DOLOOP{
215 b >> dummy;
216 if ((dummy & kIsReferenced) != 0) {
218 b >> pidf;
219 }
220 }
221 break;
222 }
223
224 // skip array of basic types array[8]
240
241 // skip pointer to an array of basic types array[n]
257
258 // skip char*
260 DOLOOP {
261 Int_t nch; b >> nch;
262 if (nch>0) {
263 char* readbuf = new char[nch];
264 b.ReadFastArray(readbuf,nch);
265 delete[] readbuf;
266 }
267 }
268 break;
269 }
270
271 // skip Class* derived from TObject
273 DOLOOP{
274 for (Int_t j=0;j<compinfo->fLength;j++) {
275 b.SkipObjectAny();
276 }
277 }
278 break;
279 }
280
281 // skip array counter //[n]
283 DOLOOP {
284 Int_t dummy; b >> dummy;
285 aElement->SetTObjectOffset(dummy);
286 }
287 break;
288 }
289
290 // skip Class * derived from TObject with comment field //->
291 // skip Class derived from TObject
294 if (cle == TRef::Class()) {
296 DOLOOP{ refjunk.Streamer(b);}
297 } else {
298 DOLOOP{
299 b.SkipObjectAny();
300 }
301 }
302 break;
303 }
304
305 // skip Special case for TString, TObject, TNamed
307 TString s;
308 DOLOOP {
309 s.Streamer(b);
310 }
311 break;
312 }
314 TObject x;
315 DOLOOP {
316 x.Streamer(b);
317 }
318 break;
319 }
321 TNamed n;
322 DOLOOP {
323 n.Streamer(b);
324 }
325 break;
326 }
327
328 // skip Class * not derived from TObject with comment field //->
331 DOLOOP {
332 for (Int_t j = 0; j < compinfo->fLength; j++) {
333 b.SkipObjectAny();
334 }
335 }
336 break;
337 }
338
339 // skip Class* not derived from TObject
342 DOLOOP {
343 for (Int_t j=0;j<compinfo->fLength;j++) {
344 b.SkipObjectAny();
345 }
346 }
347 break;
348 }
349
350 // skip Any Class not derived from TObject
353 DOLOOP {
354 for (Int_t j = 0; j < compinfo->fLength; j++) {
355 b.SkipObjectAny();
356 }
357 }
358 break;
359 }
360
361 // skip Any Class not derived from TObject
365 if (fOldVersion<3) return 0;
366 b.SkipObjectAny();
367 break;
368 }
369
370 // skip Base Class
372 DOLOOP {
373 b.SkipObjectAny();
374 }
375 break;
376 }
377
381 DOLOOP {
382 for (Int_t j = 0; j < compinfo->fLength; j++) {
383 b.SkipObjectAny();
384 }
385 }
386 break;
387 }
388 default:
389 //Error("ReadBufferClones","The element type %d is not supported yet\n",compinfo->fType);
390 return -1;
391 }
392 return 0;
393}
394
395#define ConvCBasicType(name,stream) \
396 { \
397 DOLOOP { \
398 name u; \
399 stream; \
400 switch(compinfo->fNewType) { \
401 case TStreamerInfo::kBool: {Bool_t *x=(Bool_t*)(arr[k]+ioffset); *x = (Bool_t)u; break;} \
402 case TStreamerInfo::kChar: {Char_t *x=(Char_t*)(arr[k]+ioffset); *x = (Char_t)u; break;} \
403 case TStreamerInfo::kShort: {Short_t *x=(Short_t*)(arr[k]+ioffset); *x = (Short_t)u; break;} \
404 case TStreamerInfo::kInt: {Int_t *x=(Int_t*)(arr[k]+ioffset); *x = (Int_t)u; break;} \
405 case TStreamerInfo::kLong: {Long_t *x=(Long_t*)(arr[k]+ioffset); *x = (Long_t)u; break;} \
406 case TStreamerInfo::kLong64: {Long64_t *x=(Long64_t*)(arr[k]+ioffset); *x = (Long64_t)u; break;} \
407 case TStreamerInfo::kFloat: {Float_t *x=(Float_t*)(arr[k]+ioffset); *x = (Float_t)u; break;} \
408 case TStreamerInfo::kFloat16: {Float_t *x=(Float_t*)(arr[k]+ioffset); *x = (Float_t)u; break;} \
409 case TStreamerInfo::kDouble: {Double_t *x=(Double_t*)(arr[k]+ioffset); *x = (Double_t)u; break;} \
410 case TStreamerInfo::kDouble32:{Double_t *x=(Double_t*)(arr[k]+ioffset); *x = (Double_t)u; break;} \
411 case TStreamerInfo::kUChar: {UChar_t *x=(UChar_t*)(arr[k]+ioffset); *x = (UChar_t)u; break;} \
412 case TStreamerInfo::kUShort: {UShort_t *x=(UShort_t*)(arr[k]+ioffset); *x = (UShort_t)u; break;} \
413 case TStreamerInfo::kUInt: {UInt_t *x=(UInt_t*)(arr[k]+ioffset); *x = (UInt_t)u; break;} \
414 case TStreamerInfo::kULong: {ULong_t *x=(ULong_t*)(arr[k]+ioffset); *x = (ULong_t)u; break;} \
415 case TStreamerInfo::kULong64: {ULong64_t*x=(ULong64_t*)(arr[k]+ioffset);*x = (ULong64_t)u;break;} \
416 } \
417 } break; \
418 }
419
420#define ConvCBasicArrayTo(newtype) \
421 { \
422 newtype *f=(newtype*)(arr[k]+ioffset); \
423 for (j=0;j<len;j++) f[j] = (newtype)readbuf[j]; \
424 break; \
425 }
426
427#define ConvCBasicArray(name,ReadArrayFunc) \
428 { \
429 int j, len = compinfo->fLength; \
430 name* readbuf = new name[len]; \
431 int newtype = compinfo->fNewType%20; \
432 DOLOOP { \
433 b.ReadArrayFunc(readbuf, len); \
434 switch(newtype) { \
435 case TStreamerInfo::kBool: ConvCBasicArrayTo(Bool_t); \
436 case TStreamerInfo::kChar: ConvCBasicArrayTo(Char_t); \
437 case TStreamerInfo::kShort: ConvCBasicArrayTo(Short_t); \
438 case TStreamerInfo::kInt: ConvCBasicArrayTo(Int_t); \
439 case TStreamerInfo::kLong: ConvCBasicArrayTo(Long_t); \
440 case TStreamerInfo::kLong64: ConvCBasicArrayTo(Long64_t); \
441 case TStreamerInfo::kFloat: ConvCBasicArrayTo(Float_t); \
442 case TStreamerInfo::kFloat16: ConvCBasicArrayTo(Float_t); \
443 case TStreamerInfo::kDouble: ConvCBasicArrayTo(Double_t); \
444 case TStreamerInfo::kDouble32: ConvCBasicArrayTo(Double_t); \
445 case TStreamerInfo::kUChar: ConvCBasicArrayTo(UChar_t); \
446 case TStreamerInfo::kUShort: ConvCBasicArrayTo(UShort_t); \
447 case TStreamerInfo::kUInt: ConvCBasicArrayTo(UInt_t); \
448 case TStreamerInfo::kULong: ConvCBasicArrayTo(ULong_t); \
449 case TStreamerInfo::kULong64: ConvCBasicArrayTo(ULong64_t); \
450 } \
451 } \
452 delete[] readbuf; \
453 break; \
454 }
455
456#define ConvCBasicPointerToOutOfRange(newtype,ReadArrayFunc) \
457 { \
458 newtype **f=(newtype**)(arr[k]+ioffset); \
459 for (j=0;j<len;j++) { \
460 delete [] f[j]; \
461 f[j] = 0; \
462 } \
463 break; \
464 }
465
466#define ConvCBasicPointerTo(newtype,ReadArrayFunc) \
467 { \
468 newtype **f=(newtype**)(arr[k]+ioffset); \
469 for (j=0;j<len;j++) { \
470 delete [] f[j]; \
471 f[j] = new newtype[*l]; \
472 newtype *af = f[j]; \
473 b.ReadArrayFunc(readbuf, *l); \
474 for (jj=0;jj<*l;jj++) af[jj] = (newtype)readbuf[jj]; \
475 } \
476 break; \
477 }
478
479#define ConvCBasicPointer(name,ReadArrayFunc) \
480 { \
481 Char_t isArray; \
482 int j, jj, len = aElement->GetArrayDim()?aElement->GetArrayLength():1; \
483 name* readbuf = 0; \
484 int newtype = compinfo->fNewType %20; \
485 Int_t imethod = compinfo->fMethod+eoffset; \
486 DOLOOP { \
487 b >> isArray; \
488 Int_t *l = (Int_t*)(arr[k]+imethod); \
489 if (*l>0 && *l < b.BufferSize()) { \
490 readbuf = new name[*l]; \
491 switch(newtype) { \
492 case TStreamerInfo::kBool: ConvCBasicPointerTo(Bool_t,ReadArrayFunc); \
493 case TStreamerInfo::kChar: ConvCBasicPointerTo(Char_t,ReadArrayFunc); \
494 case TStreamerInfo::kShort: ConvCBasicPointerTo(Short_t,ReadArrayFunc); \
495 case TStreamerInfo::kInt: ConvCBasicPointerTo(Int_t,ReadArrayFunc); \
496 case TStreamerInfo::kLong: ConvCBasicPointerTo(Long_t,ReadArrayFunc); \
497 case TStreamerInfo::kLong64: ConvCBasicPointerTo(Long64_t,ReadArrayFunc); \
498 case TStreamerInfo::kFloat: ConvCBasicPointerTo(Float_t,ReadArrayFunc); \
499 case TStreamerInfo::kFloat16: ConvCBasicPointerTo(Float_t,ReadArrayFunc); \
500 case TStreamerInfo::kDouble: ConvCBasicPointerTo(Double_t,ReadArrayFunc); \
501 case TStreamerInfo::kDouble32: ConvCBasicPointerTo(Double_t,ReadArrayFunc); \
502 case TStreamerInfo::kUChar: ConvCBasicPointerTo(UChar_t,ReadArrayFunc); \
503 case TStreamerInfo::kUShort: ConvCBasicPointerTo(UShort_t,ReadArrayFunc); \
504 case TStreamerInfo::kUInt: ConvCBasicPointerTo(UInt_t,ReadArrayFunc); \
505 case TStreamerInfo::kULong: ConvCBasicPointerTo(ULong_t,ReadArrayFunc); \
506 case TStreamerInfo::kULong64: ConvCBasicPointerTo(ULong64_t,ReadArrayFunc); \
507 } \
508 delete[] readbuf; \
509 } else { \
510 switch(newtype) { \
511 case TStreamerInfo::kBool: ConvCBasicPointerToOutOfRange(Bool_t,ReadArrayFunc); \
512 case TStreamerInfo::kChar: ConvCBasicPointerToOutOfRange(Char_t,ReadArrayFunc); \
513 case TStreamerInfo::kShort: ConvCBasicPointerToOutOfRange(Short_t,ReadArrayFunc); \
514 case TStreamerInfo::kInt: ConvCBasicPointerToOutOfRange(Int_t,ReadArrayFunc); \
515 case TStreamerInfo::kLong: ConvCBasicPointerToOutOfRange(Long_t,ReadArrayFunc); \
516 case TStreamerInfo::kLong64: ConvCBasicPointerToOutOfRange(Long64_t,ReadArrayFunc); \
517 case TStreamerInfo::kFloat: ConvCBasicPointerToOutOfRange(Float_t,ReadArrayFunc); \
518 case TStreamerInfo::kFloat16: ConvCBasicPointerToOutOfRange(Float_t,ReadArrayFunc); \
519 case TStreamerInfo::kDouble: ConvCBasicPointerToOutOfRange(Double_t,ReadArrayFunc); \
520 case TStreamerInfo::kDouble32: ConvCBasicPointerToOutOfRange(Double_t,ReadArrayFunc); \
521 case TStreamerInfo::kUChar: ConvCBasicPointerToOutOfRange(UChar_t,ReadArrayFunc); \
522 case TStreamerInfo::kUShort: ConvCBasicPointerToOutOfRange(UShort_t,ReadArrayFunc); \
523 case TStreamerInfo::kUInt: ConvCBasicPointerToOutOfRange(UInt_t,ReadArrayFunc); \
524 case TStreamerInfo::kULong: ConvCBasicPointerToOutOfRange(ULong_t,ReadArrayFunc); \
525 case TStreamerInfo::kULong64: ConvCBasicPointerToOutOfRange(ULong64_t,ReadArrayFunc); \
526 } \
527 } \
528 readbuf = 0; \
529 } break; \
530 }
531
532////////////////////////////////////////////////////////////////////////////////
533/// Handle Artificial StreamerElement
534
535template <class T>
539{
542
543 if (rawfunc) {
544 for(Int_t k=0; k<narr; ++k) {
545 rawfunc( arr[k], b ); // Intentionally pass the object, so that the member can be set from other members.
546 }
547 return 0;
548 }
549
551 // Process the result
552 if (readfunc) {
553 TVirtualObject obj(0);
554 TVirtualArray *objarr = b.PeekDataCache();
555 if (objarr) {
556 obj.fClass = objarr->fClass;
557
558 for(Int_t k=0; k<narr; ++k) {
559 obj.fObject = objarr->GetObjectAt(k);
560 readfunc(arr[k]+eoffset, &obj);
561 }
562 obj.fObject = 0; // Prevent auto deletion
563 } else {
564 for(Int_t k=0; k<narr; ++k) {
565 readfunc(arr[k]+eoffset, &obj);
566 }
567 }
568 return 0;
569 }
570
571 return 0;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Convert elements of a TClonesArray
576
577template <class T>
581{
582 Int_t ioffset = eoffset+compinfo->fOffset;
583
584 switch (kase) {
585
586 // convert basic types
593 } else {
595 }
605#if defined(_MSC_VER) && (_MSC_VER <= 1200)
607#else
609#endif
610 } else {
612 }
613#if defined(_MSC_VER) && (_MSC_VER <= 1200)
615#else
617#endif
619 DOLOOP {
620 UInt_t u;
621 b >> u;
622 u |= kNotDeleted; // by definition de-serialized object are not yet deleted.
623 if ((u & kIsReferenced) != 0) {
625 b >> pidf;
626 pidf += b.GetPidOffset();
627 TProcessID *pid = b.ReadProcessID(pidf);
628 if (pid!=0) {
629 TObject *obj = (TObject*)(arr[k]+eoffset);
630 UInt_t gpid = pid->GetUniqueID();
631 UInt_t uid;
632 if (gpid>=0xff) {
633 uid = obj->GetUniqueID() | 0xff000000;
634 } else {
635 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
636 }
637 obj->SetUniqueID(uid);
638 pid->PutObjectWithID(obj);
639 }
640 }
641 switch(compinfo->fNewType) {
642 case TStreamerInfo::kBool: {Bool_t *x=(Bool_t*)(arr[k]+ioffset); *x = (Bool_t)u; break;}
643 case TStreamerInfo::kChar: {Char_t *x=(Char_t*)(arr[k]+ioffset); *x = (Char_t)u; break;}
644 case TStreamerInfo::kShort: {Short_t *x=(Short_t*)(arr[k]+ioffset); *x = (Short_t)u; break;}
645 case TStreamerInfo::kInt: {Int_t *x=(Int_t*)(arr[k]+ioffset); *x = (Int_t)u; break;}
646 case TStreamerInfo::kLong: {Long_t *x=(Long_t*)(arr[k]+ioffset); *x = (Long_t)u; break;}
647 case TStreamerInfo::kLong64: {Long64_t *x=(Long64_t*)(arr[k]+ioffset); *x = (Long64_t)u; break;}
648 case TStreamerInfo::kFloat: {Float_t *x=(Float_t*)(arr[k]+ioffset); *x = (Float_t)u; break;}
649 case TStreamerInfo::kFloat16: {Float_t *x=(Float_t*)(arr[k]+ioffset); *x = (Float_t)u; break;}
650 case TStreamerInfo::kDouble: {Double_t *x=(Double_t*)(arr[k]+ioffset); *x = (Double_t)u; break;}
651 case TStreamerInfo::kDouble32:{Double_t *x=(Double_t*)(arr[k]+ioffset); *x = (Double_t)u; break;}
652 case TStreamerInfo::kUChar: {UChar_t *x=(UChar_t*)(arr[k]+ioffset); *x = (UChar_t)u; break;}
653 case TStreamerInfo::kUShort: {UShort_t *x=(UShort_t*)(arr[k]+ioffset); *x = (UShort_t)u; break;}
654 case TStreamerInfo::kUInt: {UInt_t *x=(UInt_t*)(arr[k]+ioffset); *x = (UInt_t)u; break;}
655 case TStreamerInfo::kULong: {ULong_t *x=(ULong_t*)(arr[k]+ioffset); *x = (ULong_t)u; break;}
657 }
658 } break;
659 }
660
661 // convert array of basic types array[8]
668 ConvCBasicArray(Long64_t,ReadFastArray);
669 } else {
670 ConvCBasicArray(Long_t,ReadFastArray);
671 }
682#if defined(_MSC_VER) && (_MSC_VER <= 1200)
683 ConvCBasicArray(Long64_t,ReadFastArray)
684#else
685 ConvCBasicArray(ULong64_t,ReadFastArray)
686#endif
687 } else {
688 ConvCBasicArray(ULong_t,ReadFastArray);
689 }
690#if defined(_MSC_VER) && (_MSC_VER <= 1200)
692#else
694#endif
695
696 // convert pointer to an array of basic types array[n]
703 ConvCBasicPointer(Long64_t,ReadFastArray);
704 } else {
705 ConvCBasicPointer(Long_t,ReadFastArray);
706 }
717#if defined(_MSC_VER) && (_MSC_VER <= 1200)
718 ConvCBasicPointer(Long64_t,ReadFastArray)
719#else
720 ConvCBasicPointer(ULong64_t,ReadFastArray)
721#endif
722 } else {
723 ConvCBasicPointer(ULong_t,ReadFastArray);
724 }
725#if defined(_MSC_VER) && (_MSC_VER <= 1200)
727#else
729#endif
730
731 default:
732 // Warning("ReadBufferConv","The element type %d is not supported yet",compinfo->fType);
733 return -1;
734
735 }
736
737 return 0;
738}
739
740// Helper function for TStreamerInfo::ReadBuffer
741namespace {
743 {
744 return element->TestBit(TStreamerElement::kCache);
745 }
746
748 {
749 // We are already using the cache, no need to recurse one more time.
750 return kFALSE;
751 }
752}
753
754////////////////////////////////////////////////////////////////////////////////
755/// Deserialize information from buffer b into object at pointer
756/// if (arrayMode & 1) ptr is a pointer to array of pointers to the objects
757/// otherwise it is a pointer to a pointer to a single object.
758/// This also means that T is of a type such that arr[i] is a pointer to an
759/// object. Currently the only anticipated instantiation are for T==char**
760/// and T==TVirtualCollectionProxy
761
762template <class T>
764 TCompInfo *const*const compinfo, Int_t first, Int_t last,
766{
767 TStreamerInfo *thisVar = this;
768 Bool_t needIncrement = !( arrayMode & 2 );
769 arrayMode = arrayMode & (~2);
770
771 if (needIncrement) b.IncrementLevel(thisVar);
772
773 //loop on all active members
774
775 // In order to speed up the case where the object being written is
776 // not in a collection (i.e. arrayMode is false), we actually
777 // duplicate the code for the elementary types using this typeOffset.
778 static const int kHaveLoop = 1024;
779 const Int_t typeOffset = arrayMode ? kHaveLoop : 0;
780
781 TClass *cle = 0;
782 TClass *newCle = 0;
784 Int_t isPreAlloc = 0;
785 for (Int_t i=first;i<last;i++) {
788
789 if (needIncrement) b.SetStreamerElementNumber(aElement,compinfo[i]->fType);
790
791 if (aElement->TestBit(TStreamerElement::kWrite)) continue;
792
794 Int_t bufpos = b.Length();
795 if (b.PeekDataCache() == 0) {
796 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",thisVar->GetName(),aElement->GetName());
797 thisVar->ReadBufferSkip(b,arr,compinfo[i],compinfo[i]->fType+TStreamerInfo::kSkip,aElement,narr,eoffset);
798 } else {
799 if (gDebug > 1) {
800 printf("ReadBuffer, class:%s, name=%s, fType[%d]=%d,"
801 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
802 fClass->GetName(), aElement->GetName(), i, compinfo[i]->fType, aElement->ClassName(), b.Length(),
803 arr[0], eoffset, b.PeekDataCache()->GetObjectAt(0));
804 }
805 thisVar->ReadBuffer(b, *b.PeekDataCache(), compinfo, i, i + 1, narr, eoffset, arrayMode);
806 }
807 if (aElement->TestBit(TStreamerElement::kRepeat)) { b.SetBufferOffset(bufpos); }
808 continue;
809 }
810 const Int_t ioffset = compinfo[i]->fOffset+eoffset;
811
812 if (gDebug > 1) {
813 printf("ReadBuffer, class:%s, name=%s, fType[%d]=%d,"
814 " %s, bufpos=%d, arr=%p, offset=%d\n",
815 fClass->GetName(),aElement->GetName(),i,compinfo[i]->fType,
816 aElement->ClassName(),b.Length(),arr[0], ioffset);
817 }
818
819 Int_t kase = compinfo[i]->fType;
820
821 switch (kase + typeOffset) {
822
823 // read basic types
827 case TStreamerInfo::kInt: ReadBasicType(Int_t); continue;
838 Float_t *x=(Float_t*)(arr[0]+ioffset);
839 b.ReadFloat16(x,aElement);
840 continue;
841 }
843 Double_t *x=(Double_t*)(arr[0]+ioffset);
844 b.ReadDouble32(x,aElement);
845 continue;
846 }
847
862 for(Int_t k=0; k<narr; ++k) {
863 Float_t *x=(Float_t*)(arr[k]+ioffset);
864 b.ReadFloat16(x,aElement);
865 }
866 continue;
867 }
869 for(Int_t k=0; k<narr; ++k) {
870 Double_t *x=(Double_t*)(arr[k]+ioffset);
871 b.ReadDouble32(x,aElement);
872 }
873 continue;
874 }
875
876 // read array of basic types like array[8]
891 b.ReadFastArrayFloat16((Float_t*)(arr[0]+ioffset),compinfo[i]->fLength,aElement);
892 continue;
893 }
895 b.ReadFastArrayDouble32((Double_t*)(arr[0]+ioffset),compinfo[i]->fLength,aElement);
896 continue;
897 }
898
913 for(Int_t k=0; k<narr; ++k) {
914 b.ReadFastArrayFloat16((Float_t*)(arr[k]+ioffset),compinfo[i]->fLength,aElement);
915 }
916 continue;
917 }
919 for(Int_t k=0; k<narr; ++k) {
920 b.ReadFastArrayDouble32((Double_t*)(arr[k]+ioffset),compinfo[i]->fLength,aElement);
921 }
922 continue;
923 }
924
925 // read pointer to an array of basic types array[n]
941 b >> isArray;
942 const int imethod = compinfo[i]->fMethod+eoffset;
943 Int_t *l = (Int_t*)(arr[0]+imethod);
944 Float_t **f = (Float_t**)(arr[0]+ioffset);
945 int j;
946 for(j=0;j<compinfo[i]->fLength;j++) {
947 delete [] f[j];
948 f[j] = 0; if (*l <=0) continue;
949 f[j] = new Float_t[*l];
950 b.ReadFastArrayFloat16(f[j],*l,aElement);
951 }
952 continue;
953 }
956 b >> isArray;
957 const int imethod = compinfo[i]->fMethod+eoffset;
958 Int_t *l = (Int_t*)(arr[0]+imethod);
959 Double_t **f = (Double_t**)(arr[0]+ioffset);
960 int j;
961 for(j=0;j<compinfo[i]->fLength;j++) {
962 delete [] f[j];
963 f[j] = 0; if (*l <=0) continue;
964 f[j] = new Double_t[*l];
965 b.ReadFastArrayDouble32(f[j],*l,aElement);
966 }
967 continue;
968 }
969
984 const int imethod = compinfo[i]->fMethod+eoffset;
985 for(Int_t k=0; k<narr; ++k) {
987 b >> isArray;
988 Int_t *l = (Int_t*)(arr[k]+imethod);
989 Float_t **f = (Float_t**)(arr[k]+ioffset);
990 int j;
991 for(j=0;j<compinfo[i]->fLength;j++) {
992 delete [] f[j];
993 f[j] = 0; if (*l <=0) continue;
994 f[j] = new Float_t[*l];
995 b.ReadFastArrayFloat16(f[j],*l,aElement);
996 }
997 }
998 continue;
999 }
1001 const int imethod = compinfo[i]->fMethod+eoffset;
1002 for(Int_t k=0; k<narr; ++k) {
1004 b >> isArray;
1005 Int_t *l = (Int_t*)(arr[k]+imethod);
1006 Double_t **f = (Double_t**)(arr[k]+ioffset);
1007 int j;
1008 for(j=0;j<compinfo[i]->fLength;j++) {
1009 delete [] f[j];
1010 f[j] = 0; if (*l <=0) continue;
1011 f[j] = new Double_t[*l];
1012 b.ReadFastArrayDouble32(f[j],*l,aElement);
1013 }
1014 }
1015 continue;
1016 }
1017 }
1018
1019 switch (kase) {
1020
1021 // char*
1023 DOLOOP {
1024 char **f = (char**)(arr[k]+ioffset);
1025 b.ReadCharStar(*f);
1026 }
1027 }
1028 continue;
1029
1030 // special case for TObject::fBits in case of a referenced object
1031 case TStreamerInfo::kBits: {
1032 DOLOOP {
1033 UInt_t *x=(UInt_t*)(arr[k]+ioffset);
1034 const UInt_t isonheap = *x & TObject::kIsOnHeap; // Record how this instance was actually allocated.
1035 b >> *x;
1036 *x |= isonheap | TObject::kNotDeleted; // by definition de-serialized object are not yet deleted.
1037 if ((*x & kIsReferenced) != 0) {
1038 UShort_t pidf;
1039 b >> pidf;
1040 pidf += b.GetPidOffset();
1041 TProcessID *pid = b.ReadProcessID(pidf);
1042 if (pid!=0) {
1043 TObject *obj = (TObject*)(arr[k]+eoffset);
1044 UInt_t gpid = pid->GetUniqueID();
1045 UInt_t uid;
1046 if (gpid>=0xff) {
1047 uid = obj->GetUniqueID() | 0xff000000;
1048 } else {
1049 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
1050 }
1051 obj->SetUniqueID(uid);
1052 pid->PutObjectWithID(obj);
1053 }
1054 }
1055 }
1056 }
1057 continue;
1058
1059 // array counter //[n]
1061 DOLOOP {
1062 Int_t *x=(Int_t*)(arr[k]+ioffset);
1063 b >> *x;
1064 }
1065 }
1066 continue;
1067
1068
1069 // Special case for TString, TObject, TNamed
1070 case TStreamerInfo::kTString: { DOLOOP { ((TString*)(arr[k]+ioffset))->Streamer(b); } } continue;
1071 case TStreamerInfo::kTObject: { DOLOOP { ((TObject*)(arr[k]+ioffset))->TObject::Streamer(b);} } continue;
1072 case TStreamerInfo::kTNamed: { DOLOOP { ((TNamed*) (arr[k]+ioffset))->TNamed::Streamer(b) ;} } continue;
1073
1074 }
1075
1076 SWIT:
1077 isPreAlloc= 0;
1078 cle = compinfo[i]->fClass;
1079 newCle = compinfo[i]->fNewClass;
1080 pstreamer = compinfo[i]->fStreamer;
1081
1082 switch (kase) {
1083
1084 case TStreamerInfo::kAnyp: // Class* not derived from TObject with comment field //->
1086 case TStreamerInfo::kObjectp: // Class* derived from TObject with comment field //->
1088 isPreAlloc = 1;
1089 // Intentional fallthrough now that isPreAlloc is set.
1090 case TStreamerInfo::kObjectP: // Class* derived from TObject with no comment field NOTE: Re-added by Phil
1092 case TStreamerInfo::kAnyP: // Class* not derived from TObject with no comment field NOTE:: Re-added by Phil
1094 DOLOOP {
1095 b.ReadFastArray((void **)(arr[k] + ioffset), newCle ? newCle : cle, compinfo[i]->fLength, isPreAlloc,
1096 pstreamer, cle);
1097 }
1098 }
1099 continue;
1100
1101// case TStreamerInfo::kSTLvarp: // Variable size array of STL containers.
1102// {
1103// TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
1104// TClass *cl = compinfo[i]->fClass;
1105// ROOT::NewArrFunc_t arraynew = cl->GetNewArray();
1106// ROOT::DelArrFunc_t arraydel = cl->GetDeleteArray();
1107// UInt_t start,count;
1108// // Version_t v =
1109// b.ReadVersion(&start, &count, cle);
1110// if (pstreamer == 0) {
1111// Int_t size = cl->Size();
1112// Int_t imethod = compinfo[i]->fMethod+eoffset;
1113// DOLOOP {
1114// char **contp = (char**)(arr[k]+ioffset);
1115// const Int_t *counter = (Int_t*)(arr[k]+imethod);
1116// const Int_t sublen = (*counter);
1117
1118// for(int j=0;j<compinfo[i]->fLength;++j) {
1119// if (arraydel) arraydel(contp[j]);
1120// contp[j] = 0;
1121// if (sublen<=0) continue;
1122// if (arraynew) {
1123// contp[j] = (char*)arraynew(sublen, 0);
1124// char *cont = contp[j];
1125// for(int k=0;k<sublen;++k) {
1126// cl->Streamer( cont, b );
1127// cont += size;
1128// }
1129// } else {
1130// // Can't create an array of object
1131// Error("ReadBuffer","The element %s::%s type %d (%s) can be read because of the class does not have access to new %s[..]\n",
1132// GetName(),aElement->GetFullName(),kase,aElement->GetTypeName(),GetName());
1133// void *cont = cl->New();
1134// for(int k=0;k<sublen;++k) {
1135// cl->Streamer( cont, b );
1136// }
1137// }
1138// }
1139// }
1140// } else {
1141// DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
1142// }
1143// b.CheckByteCount(start,count,aElement->GetFullName());
1144// }
1145// continue;
1146
1147 case TStreamerInfo::kSTLp: // Pointer to Container with no virtual table (stl) and no comment
1148 case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to Container with no virtual table (stl) and no comment
1149 {
1150 UInt_t start,count;
1151 Version_t vers = b.ReadVersion(&start, &count, cle);
1152
1154 // Collection was saved member-wise
1155
1157
1158 TClass *newClass = aElement->GetNewClass();
1159 TClass *oldClass = aElement->GetClassPointer();
1160 if( vers < 9 && newClass && newClass!=oldClass ) {
1161 Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1162 vers, b.GetParent() ? b.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1163 continue;
1164 }
1165
1166 Version_t vClVersion = 0; // For vers less than 9, we have to use the current version.
1167 if( vers >= 9 ) {
1168 vClVersion = b.ReadVersionForMemberWise( cle->GetCollectionProxy()->GetValueClass() );
1169 }
1170
1171 TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : 0);
1172 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1174
1175 if( newProxy ) {
1176 // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
1177 subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
1178 } else {
1179 subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( vClVersion );
1181 }
1182 if (subinfo) {
1183 DOLOOP {
1184 void* env;
1185 void **contp = (void**)(arr[k]+ioffset);
1186 int j;
1187 for(j=0;j<compinfo[i]->fLength;j++) {
1188 void *cont = contp[j];
1189 if (cont==0) {
1190 contp[j] = cle->New();
1191 cont = contp[j];
1192 }
1195 b >> nobjects;
1196 env = newProxy->Allocate(nobjects,true);
1197 if (!nobjects && (vers>=7)) {
1198 // Do nothing but in version 6 of TStreamerInfo and below,
1199 // we were calling ReadBuffer for empty collection.
1200 } else {
1202 if (newProxy != oldProxy) {
1203 actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1204 } else {
1205 actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1206 }
1209 void *begin = &(startbuf[0]);
1210 void *end = &(endbuf[0]);
1211 newProxy->GetFunctionCreateIterators(/* read = */ kTRUE)(env, &begin, &end, newProxy);
1212 // We can not get here with a split vector of pointer, so we can indeed assume
1213 // that actions->fConfiguration != null.
1214 b.ApplySequence(*actions, begin, end);
1215 if (begin != &(startbuf[0])) {
1216 // assert(end != endbuf);
1217 newProxy->GetFunctionDeleteTwoIterators()(begin,end);
1218 }
1219 }
1220 newProxy->Commit(env);
1221 }
1222 }
1223 }
1224 b.CheckByteCount(start,count,aElement->GetFullName());
1225 continue;
1226 }
1227 if (pstreamer == 0) {
1228 DOLOOP {
1229 void **contp = (void**)(arr[k]+ioffset);
1230 int j;
1231 for(j=0;j<compinfo[i]->fLength;j++) {
1232 void *cont = contp[j];
1233 if (cont==0) {
1234 // int R__n;
1235 // b >> R__n;
1236 // b.SetOffset(b.GetOffset()-4); // rewind to the start of the int
1237 // if (R__n) continue;
1238 contp[j] = cle->New();
1239 cont = contp[j];
1240 }
1241 cle->Streamer( cont, b );
1242 }
1243 }
1244 } else {
1245 DOLOOP {(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
1246 }
1247 b.CheckByteCount(start,count,aElement->GetFullName());
1248 }
1249 continue;
1250
1251 case TStreamerInfo::kSTL: // Container with no virtual table (stl) and no comment
1252 case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL: // array of Container with no virtual table (stl) and no comment
1253 {
1254 UInt_t start, count;
1255 Version_t vers = b.ReadVersion(&start, &count, cle);
1256
1258 // Collection was saved member-wise
1260
1261 TClass *newClass = aElement->GetNewClass();
1262 TClass *oldClass = aElement->GetClassPointer();
1263
1264 if( vers < 8 && newClass && newClass!=oldClass ) {
1265 Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1266 vers, b.GetParent() ? b.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1267 continue;
1268 }
1269 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1270 TClass *valueClass = oldProxy ? oldProxy->GetValueClass() : 0;
1271 Version_t vClVersion = 0; // For vers less than 8, we have to use the current version.
1272 if( vers >= 8 ) {
1273 vClVersion = b.ReadVersionForMemberWise( valueClass );
1274 }
1275
1276 if (valueClass == 0) {
1277 // MemberWise streaming applies to only collection of classes, and hence
1278 // valueClass can only be null if we are reading without the original library
1279 // and the collection is always empty,
1280 // So let's skip the rest (which requires the StreamerInfo of the valueClass ... which we do not have)
1281
1282 b.SetBufferOffset(start+count+sizeof(UInt_t));
1283 continue;
1284 }
1285
1286 TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : 0);
1288
1289 if( newProxy ) {
1290 // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
1291 subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
1292 } else {
1293 subinfo = (TStreamerInfo*)valueClass->GetStreamerInfo( vClVersion );
1295 }
1296 if (subinfo) {
1297 DOLOOP {
1298 int objectSize = cle->Size();
1299 char *obj = arr[k]+ioffset;
1300 char *end = obj + compinfo[i]->fLength*objectSize;
1301
1302 for(; obj<end; obj+=objectSize) {
1305 b >> nobjects;
1306 void* env = newProxy->Allocate(nobjects,true);
1307 if (!nobjects && (vers>=7)) {
1308 // Do nothing but in version 6 of TStreamerInfo and below,
1309 // we were calling ReadBuffer for empty collection.
1310 } else {
1312 if (newProxy != oldProxy) {
1313 actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1314 } else {
1315 actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1316 }
1317
1320 void *begin_iter = &(startbuf[0]);
1321 void *end_iter = &(endbuf[0]);
1322 newProxy->GetFunctionCreateIterators(/* read = */ kTRUE)(env, &begin_iter, &end_iter, newProxy);
1323 // We can not get here with a split vector of pointer, so we can indeed assume
1324 // that actions->fConfiguration != null.
1325 b.ApplySequence(*actions, begin_iter, end_iter);
1326 if (begin_iter != &(startbuf[0])) {
1327 // assert(end != endbuf);
1328 newProxy->GetFunctionDeleteTwoIterators()(begin_iter,end_iter);
1329 }
1330 }
1331 newProxy->Commit(env);
1332 }
1333 }
1334 }
1335 b.CheckByteCount(start,count,aElement->GetTypeName());
1336 continue;
1337 }
1338 if (fOldVersion<3){ // case of old TStreamerInfo
1339 // Backward compatibility. Some TStreamerElement's where without
1340 // Streamer but were not removed from element list
1341 if (aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()) {
1342 b.SetBufferOffset(start); //there is no byte count
1343 } else if (vers==0) {
1344 b.SetBufferOffset(start); //there is no byte count
1345 }
1346 }
1347 if (pstreamer == 0) {
1348 if( !newCle ) {
1349 newCle = cle;
1350 cle = 0;
1351 }
1352 DOLOOP {
1353 b.ReadFastArray((void*)(arr[k]+ioffset),newCle,compinfo[i]->fLength,(TMemberStreamer*)0, cle );
1354 }
1355 } else {
1356 DOLOOP {(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
1357 }
1358 b.CheckByteCount(start,count,aElement->GetTypeName());
1359 }
1360 continue;
1361
1362 case TStreamerInfo::kObject: // Class derived from TObject
1363 if (cle == newCle && cle->IsStartingWithTObject() && cle->GetState() > TClass::kEmulated) {
1364 DOLOOP {((TObject*)(arr[k]+ioffset))->Streamer(b);}
1365 continue; // intentionally inside the if statement.
1366 // if the class does not start with its TObject part (or does
1367 // not have one), we use the generic case.
1368 }
1369 case TStreamerInfo::kAny: // Class not derived from TObject
1370 if (pstreamer) {
1371 DOLOOP {(*pstreamer)(b,arr[k]+ioffset,0);}
1372 } else {
1373 if( newCle )
1374 DOLOOP { newCle->Streamer( arr[k]+ioffset, b, cle ); }
1375 else
1376 DOLOOP { cle->Streamer(arr[k]+ioffset,b);}
1377 }
1378 continue;
1379
1381 TFile *file = (TFile*)b.GetParent();
1382 if (file && file->GetVersion() < 30208) {
1383 // For older ROOT file we use a totally different case to treat
1384 // this situation, so we change 'kase' and restart.
1386 goto SWIT;
1387 }
1388 // there is intentionally no break/continue statement here.
1389 // For newer ROOT file, we always use the generic case for kOffsetL(s)
1390 }
1391
1393 DOLOOP {
1394 b.ReadFastArray((void *)(arr[k] + ioffset), newCle ? newCle : cle, compinfo[i]->fLength, pstreamer, cle);
1395 }
1396 continue;
1397 }
1398
1399 // Base Class
1401 if (!(arrayMode&1)) {
1403 DOLOOP { ((TStreamerBase*)aElement)->ReadBuffer(b,arr[k]);}
1404 } else {
1405 // FIXME: Rather than relying on the StreamerElement to
1406 // contain the base class version information we should
1407 // embed it in the bytestream even in the member-wise case.
1408 // For now rely, on the StreamerElement:
1409 TStreamerInfo *binfo = ((TStreamerInfo*)((TStreamerBase*)aElement)->GetBaseStreamerInfo());
1410 binfo->ReadBuffer(b,arr,binfo->fCompFull,0,binfo->fNfulldata,narr,ioffset,arrayMode);
1411 }
1412 continue;
1413
1417 {
1418 // Backward compatibility. Some TStreamerElement's where without
1419 // Streamer but were not removed from element list
1420 UInt_t start,count;
1421 Version_t v = b.ReadVersion(&start, &count, cle);
1422 if (fOldVersion<3){ // case of old TStreamerInfo
1423 if (count<= 0 || v != fOldVersion) {
1424 b.SetBufferOffset(start);
1425 continue;
1426 }
1427 }
1428 DOLOOP {
1429 b.ReadFastArray((void*)(arr[k]+ioffset),cle,compinfo[i]->fLength,pstreamer);
1430 }
1431 b.CheckByteCount(start,count,aElement->GetFullName());
1432 continue;
1433 }
1434
1435
1437 // Backward compatibility. Some TStreamerElement's where without
1438 // Streamer but were not removed from element list
1439 UInt_t start,count;
1440 Version_t v = b.ReadVersion(&start, &count, this->IsA());
1441 if (fOldVersion<3){ // case of old TStreamerInfo
1442 if (aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()) {
1443 b.SetBufferOffset(start); //it was no byte count
1445 count<= 0 || v != fOldVersion) {
1446 b.SetBufferOffset(start);
1447 continue;
1448 }
1449 }
1450 if (pstreamer == 0) {
1451 Error("ReadBuffer","Streamer for %s is null\n",aElement->GetName());
1452 if (gDebug > 0) {
1453 aElement->ls(); continue;
1454 }
1455 } else {
1456 DOLOOP {(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
1457 }
1458 b.CheckByteCount(start,count,aElement->GetFullName());
1459 }
1460 continue;
1461
1463 // -- A pointer to a varying-length array of objects.
1464 // MyClass* ary; //[n]
1465 // -- Or a pointer to a varying-length array of pointers to objects.
1466 // MyClass** ary; //[n]
1468 // -- An array of pointers to a varying-length array of objects.
1469 // MyClass* ary[d]; //[n]
1470 // -- Or an array of pointers to a varying-length array of pointers to objects.
1471 // MyClass** ary[d]; //[n]
1472 {
1473 // Get the class of the data member.
1474 TClass* cl = compinfo[i]->fClass;
1475 // Which are we, an array of objects or an array of pointers to objects?
1476 Bool_t isPtrPtr = (strstr(aElement->GetTypeName(), "**") != 0);
1477 // Check for a private streamer.
1478 if (pstreamer) {
1479 // -- We have a private streamer.
1480 // Read the class version and byte count from the buffer.
1481 UInt_t start = 0;
1482 UInt_t count = 0;
1483 b.ReadVersion(&start, &count, cl);
1484 // Loop over the entries in the clones array or the STL container.
1485 for (Int_t k = 0; k < narr; ++k) {
1486 Int_t* counter = (Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/);
1487 // And call the private streamer, passing it the buffer, the object, and the counter.
1488 (*pstreamer)(b, arr[k] /*entry pointer*/ + ioffset /*object offset*/, *counter);
1489 }
1490 b.CheckByteCount(start, count, aElement->GetFullName());
1491 // We are done, next streamer element.
1492 continue;
1493 }
1494 // At this point we do *not* have a private streamer.
1495 // Get the version of the file we are reading from.
1496 TFile* file = (TFile*) b.GetParent();
1497 // By default assume the file version is the newest.
1499 if (file) {
1500 fileVersion = file->GetVersion();
1501 }
1502 // Read the class version and byte count from the buffer.
1503 UInt_t start = 0;
1504 UInt_t count = 0;
1505 b.ReadVersion(&start, &count, cl);
1506 if (fileVersion > 51508) {
1507 // -- Newer versions allow polymorphic pointers.
1508 // Loop over the entries in the clones array or the STL container.
1509 for (Int_t k = 0; k < narr; ++k) {
1510 // Get the counter for the varying length array.
1511 Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
1512 //Int_t realLen;
1513 //b >> realLen;
1514 //if (realLen != vlen) {
1515 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1516 //}
1517 // Get a pointer to the array of pointers.
1518 char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
1519 if (!pp) {
1520 continue;
1521 }
1522 // Loop over each element of the array of pointers to varying-length arrays.
1523 for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
1524 //if (!pp[ndx]) {
1525 // -- We do not have a pointer to a varying-length array.
1526 //Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1527 //continue;
1528 //}
1529 // Delete any memory at pp[ndx].
1530 if (!isPtrPtr) {
1531 cl->DeleteArray(pp[ndx]);
1532 pp[ndx] = 0;
1533 } else {
1534 // Using vlen is wrong here because it has already
1535 // been overwritten with the value needed to read
1536 // the current record. Fixing this will require
1537 // doing a pass over the object at the beginning
1538 // of the I/O and releasing all the buffer memory
1539 // for varying length arrays before we overwrite
1540 // the counter values.
1541 //
1542 // For now we will just leak memory, just as we
1543 // have always done in the past. Fix this.
1544 //
1545 //char** r = (char**) pp[ndx];
1546 //if (r) {
1547 // for (Int_t v = 0; v < vlen; ++v) {
1548 // cl->Destructor(r[v]);
1549 // r[v] = 0;
1550 // }
1551 //}
1552 delete[] pp[ndx];
1553 pp[ndx] = 0;
1554 }
1555 if (!vlen) {
1556 continue;
1557 }
1558 // Note: We now have pp[ndx] is null.
1559 // Allocate memory to read into.
1560 if (!isPtrPtr) {
1561 // -- We are a varying-length array of objects.
1562 // Note: Polymorphism is not allowed here.
1563 // Allocate a new array of objects to read into.
1564 pp[ndx] = (char*) cl->NewArray(vlen);
1565 if (!pp[ndx]) {
1566 Error("ReadBuffer", "Memory allocation failed!\n");
1567 continue;
1568 }
1569 } else {
1570 // -- We are a varying-length array of pointers to objects.
1571 // Note: The object pointers are allowed to be polymorphic.
1572 // Allocate a new array of pointers to objects to read into.
1573 pp[ndx] = (char*) new char*[vlen];
1574 if (!pp[ndx]) {
1575 Error("ReadBuffer", "Memory allocation failed!\n");
1576 continue;
1577 }
1578 // And set each pointer to null.
1579 memset(pp[ndx], 0, vlen * sizeof(char*)); // This is the right size we really have a char**: pp[ndx] = (char*) new char*[vlen];
1580 }
1581 if (!isPtrPtr) {
1582 // -- We are a varying-length array of objects.
1583 b.ReadFastArray(pp[ndx], cl, vlen, 0);
1584 }
1585 else {
1586 // -- We are a varying-length array of object pointers.
1587 b.ReadFastArray((void**) pp[ndx], cl, vlen, kFALSE, 0);
1588 } // isPtrPtr
1589 } // ndx
1590 } // k
1591 }
1592 else {
1593 // -- Older versions do *not* allow polymorphic pointers.
1594 // Loop over the entries in the clones array or the STL container.
1595 for (Int_t k = 0; k < narr; ++k) {
1596 // Get the counter for the varying length array.
1597 Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
1598 //Int_t realLen;
1599 //b >> realLen;
1600 //if (realLen != vlen) {
1601 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1602 //}
1603 // Get a pointer to the array of pointers.
1604 char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
1605 if (!pp) {
1606 continue;
1607 }
1608 // Loop over each element of the array of pointers to varying-length arrays.
1609 for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
1610 //if (!pp[ndx]) {
1611 // -- We do not have a pointer to a varying-length array.
1612 //Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1613 //continue;
1614 //}
1615 // Delete any memory at pp[ndx].
1616 if (!isPtrPtr) {
1617 cl->DeleteArray(pp[ndx]);
1618 pp[ndx] = 0;
1619 } else {
1620 // Using vlen is wrong here because it has already
1621 // been overwritten with the value needed to read
1622 // the current record. Fixing this will require
1623 // doing a pass over the object at the beginning
1624 // of the I/O and releasing all the buffer memory
1625 // for varying length arrays before we overwrite
1626 // the counter values.
1627 //
1628 // For now we will just leak memory, just as we
1629 // have always done in the past. Fix this.
1630 //
1631 //char** r = (char**) pp[ndx];
1632 //if (r) {
1633 // for (Int_t v = 0; v < vlen; ++v) {
1634 // cl->Destructor(r[v]);
1635 // r[v] = 0;
1636 // }
1637 //}
1638 delete[] pp[ndx];
1639 pp[ndx] = 0;
1640 }
1641 if (!vlen) {
1642 continue;
1643 }
1644 // Note: We now have pp[ndx] is null.
1645 // Allocate memory to read into.
1646 if (!isPtrPtr) {
1647 // -- We are a varying-length array of objects.
1648 // Note: Polymorphism is not allowed here.
1649 // Allocate a new array of objects to read into.
1650 pp[ndx] = (char*) cl->NewArray(vlen);
1651 if (!pp[ndx]) {
1652 Error("ReadBuffer", "Memory allocation failed!\n");
1653 continue;
1654 }
1655 } else {
1656 // -- We are a varying-length array of pointers to objects.
1657 // Note: The object pointers are allowed to be polymorphic.
1658 // Allocate a new array of pointers to objects to read into.
1659 pp[ndx] = (char*) new char*[vlen];
1660 if (!pp[ndx]) {
1661 Error("ReadBuffer", "Memory allocation failed!\n");
1662 continue;
1663 }
1664 // And set each pointer to null.
1665 memset(pp[ndx], 0, vlen * sizeof(char*)); // This is the right size we really have a char**: pp[ndx] = (char*) new char*[vlen];
1666 }
1667 if (!isPtrPtr) {
1668 // -- We are a varying-length array of objects.
1669 // Loop over the elements of the varying length array.
1670 for (Int_t v = 0; v < vlen; ++v) {
1671 // Read the object from the buffer.
1672 cl->Streamer(pp[ndx] + (v * cl->Size()), b);
1673 } // v
1674 }
1675 else {
1676 // -- We are a varying-length array of object pointers.
1677 // Get a pointer to the object pointer array.
1678 char** r = (char**) pp[ndx];
1679 // Loop over the elements of the varying length array.
1680 for (Int_t v = 0; v < vlen; ++v) {
1681 // Allocate an object to read into.
1682 r[v] = (char*) cl->New();
1683 if (!r[v]) {
1684 // Do not print a second error message here.
1685 //Error("ReadBuffer", "Memory allocation failed!\n");
1686 continue;
1687 }
1688 // Read the object from the buffer.
1689 cl->Streamer(r[v], b);
1690 } // v
1691 } // isPtrPtr
1692 } // ndx
1693 } // k
1694 } // fileVersion
1695 b.CheckByteCount(start, count, aElement->GetFullName());
1696 continue;
1697 }
1698
1699 case TStreamerInfo::kCacheNew: b.PushDataCache(new TVirtualArray(aElement->GetClassPointer(), narr)); continue;
1700 case TStreamerInfo::kCacheDelete: delete b.PopDataCache(); continue;
1701
1702 case -1:
1703 // -- Skip an ignored TObject base class.
1704 continue;
1705
1706 default: {
1707 int ans = -1;
1708
1710
1711 //T &cache_add = *(T*)b.PeekDataCacheArray();
1712 R__ASSERT(kFALSE); // cache_add);
1713
1714 // thisVar->ReadBuffer(b,cache_addr,i,kase-TStreamerInfo::kCache,aElement,narr,eoffset)
1715
1716 continue;
1717 }
1718
1720 ans = thisVar->ReadBufferConv(b,arr,compinfo[i],kase,aElement,narr,eoffset);
1721 if (ans==0) continue;
1722
1724 ans = thisVar->ReadBufferSkip(b,arr,compinfo[i],kase,aElement,narr,eoffset);
1725 if (ans==0) continue;
1726
1728 ans = thisVar->ReadBufferArtificial(b,arr,aElement,narr,eoffset);
1729 }
1730 if (ans==0) continue;
1731 }
1732 if (aElement)
1733 Error("ReadBuffer","The element %s::%s type %d (%s) is not supported yet\n",
1734 thisVar->GetName(),aElement->GetFullName(),kase,aElement->GetTypeName());
1735 else
1736 Error("ReadBuffer","The TStreamerElement for %s %d is missing!\n",
1737 thisVar->GetName(),i);
1738
1739 continue;
1740 }
1741 }
1742 if (needIncrement) b.DecrementLevel(thisVar);
1743 return 0;
1744}
1745
1746template Int_t TStreamerInfo::ReadBufferSkip<char**>(TBuffer &b, char** const &arr, const TCompInfo *compinfo, Int_t kase,
1748 Int_t eoffset);
1749template Int_t TStreamerInfo::ReadBufferSkip<TVirtualCollectionProxy>(TBuffer &b, const TVirtualCollectionProxy &arr, const TCompInfo *compinfo, Int_t kase,
1751 Int_t eoffset);
1752template Int_t TStreamerInfo::ReadBufferSkip<TVirtualArray>(TBuffer &b, const TVirtualArray &arr, const TCompInfo *compinfo, Int_t kase,
1754 Int_t eoffset);
1755
1756template Int_t TStreamerInfo::ReadBufferConv<char**>(TBuffer &b, char** const &arr, const TCompInfo *compinfo, Int_t kase,
1758 Int_t eoffset);
1759template Int_t TStreamerInfo::ReadBufferConv<TVirtualCollectionProxy>(TBuffer &b, const TVirtualCollectionProxy &arr, const TCompInfo *compinfo, Int_t kase,
1761 Int_t eoffset);
1762template Int_t TStreamerInfo::ReadBufferConv<TVirtualArray>(TBuffer &b, const TVirtualArray &arr, const TCompInfo *compinfo, Int_t kase,
1764 Int_t eoffset);
1765
1766template Int_t TStreamerInfo::ReadBufferArtificial<char**>(TBuffer &b, char** const &arr,
1768 Int_t eoffset);
1769template Int_t TStreamerInfo::ReadBufferArtificial<TVirtualCollectionProxy>(TBuffer &b, const TVirtualCollectionProxy &arr,
1771 Int_t eoffset);
1772template Int_t TStreamerInfo::ReadBufferArtificial<TVirtualArray>(TBuffer &b, const TVirtualArray &arr,
1774 Int_t eoffset);
1775
1776template Int_t TStreamerInfo::ReadBuffer<char**>(TBuffer &b, char** const &arr,
1777 TCompInfo *const*const compinfo, Int_t first, Int_t last,
1779template Int_t TStreamerInfo::ReadBuffer<TVirtualCollectionProxy>(TBuffer &b, const TVirtualCollectionProxy &arr,
1780 TCompInfo *const*const compinfo, Int_t first, Int_t last,
1782template Int_t TStreamerInfo::ReadBuffer<TVirtualArray>(TBuffer &b, const TVirtualArray &arr,
1783 TCompInfo *const*const compinfo, Int_t first, Int_t last,
1785
1786////////////////////////////////////////////////////////////////////////////////
1787/// The STL vector/list is deserialized from the buffer b
1788
1790 Int_t nc, Int_t eoffset, Bool_t v7 /* = kTRUE */)
1791{
1792 if (!nc && v7) return 0; // in version 6 of TStreamerInfo and below, we were calling ReadBuffer for empty collection.
1794 return ret;
1795}
1796
1797////////////////////////////////////////////////////////////////////////////////
1798/// Read for TClonesArray.
1799/// Note: This is no longer used.
1800
1802 Int_t nc, Int_t first, Int_t eoffset)
1803{
1804 char **arr = (char **)clones->GetObjectRef(0);
1805 return ReadBuffer(b,arr,fCompFull,first==-1?0:first,first==-1?fNfulldata:first+1,nc,eoffset,1);
1806}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
bool Bool_t
Definition RtypesCore.h:63
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
constexpr Int_t kMaxInt
Definition RtypesCore.h:105
short Version_t
Definition RtypesCore.h:65
unsigned char UChar_t
Definition RtypesCore.h:38
char Char_t
Definition RtypesCore.h:37
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:69
unsigned long long ULong64_t
Definition RtypesCore.h:70
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define DOLOOP(x)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Int_t gDebug
Definition TROOT.cxx:597
#define ReadBasicArray(name)
#define ConvCBasicPointer(name, ReadArrayFunc)
#define SkipCBasicPointer(name, ReadArrayFunc)
#define ReadBasicType(name)
#define ReadBasicPointerLoop(name)
static TStreamerElement *& CurrentElement()
#define ReadBasicArrayLoop(name)
#define SkipCFloat16(name)
#define ReadBasicTypeLoop(name)
#define SkipCBasicArray(name, ReadArrayFunc)
#define ConvCBasicArray(name, ReadArrayFunc)
#define SkipCDouble32(name)
#define ConvCBasicType(name, stream)
#define ReadBasicPointer(name)
#define SkipCBasicType(name)
void(* ReadFuncPtr_t)(char *, TVirtualObject *)
Definition TSchemaRule.h:77
void(* ReadRawFuncPtr_t)(char *, TBuffer &)
Definition TSchemaRule.h:78
@ kStreamedMemberWise
Definition TBufferFile.h:69
Buffer base class used for serializing objects.
Definition TBuffer.h:43
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:616
void * NewArray(Long_t nElements, ENewType defConstructor=kClassNew) const
Return a pointer to a newly allocated array of objects of this class.
Definition TClass.cxx:5319
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5104
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5830
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5655
@ kEmulated
Definition TClass.h:128
An array of clone (identical) objects.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
Int_t GetVersion() const
Definition TFile.h:328
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
void Streamer(TBuffer &) override
Stream an object of class TObject.
Mother of all ROOT objects.
Definition TObject.h:41
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:475
@ kIsOnHeap
object is on heap
Definition TObject.h:87
@ kNotDeleted
object has not been deleted
Definition TObject.h:88
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:972
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:875
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:71
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
void PutObjectWithID(TObject *obj, UInt_t uid=0)
stores the object at the uid th slot in the table of objects The object uniqued is set as well as its...
Persistent Reference link to a TObject A TRef is a lightweight object pointing to any TObject.
Definition TRef.h:32
static TClass * Class()
static TClass * Class()
Describe one element (data member) to be Streamed.
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
Describes a persistent version of a class.
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.
Int_t fNfulldata
!number of elements
TCompInfo ** fCompFull
![fElements->GetEntries()]
Int_t ReadBuffer(TBuffer &b, const T &arrptr, TCompInfo *const *const compinfo, Int_t first, Int_t last, Int_t narr=1, Int_t eoffset=0, Int_t mode=0)
Deserialize information from buffer b into object at pointer if (arrayMode & 1) ptr is a pointer to a...
Int_t ReadBufferConv(TBuffer &b, const T &arrptr, const TCompInfo *compinfo, Int_t kase, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Convert elements of a TClonesArray.
Int_t ReadBufferClones(TBuffer &b, TClonesArray *clones, Int_t nc, Int_t first, Int_t eoffset)
Read for TClonesArray.
TClass * IsA() const override
TClass * fClass
!pointer to class
void Streamer(TBuffer &) override
Stream an object of class TStreamerInfo.
static TStreamerElement * GetCurrentElement()
static function returning a pointer to the current TStreamerElement fgElement points to the current T...
Int_t ReadBufferArtificial(TBuffer &b, const T &arrptr, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Handle Artificial StreamerElement.
Int_t ReadBufferSkip(TBuffer &b, const T &arrptr, const TCompInfo *compinfo, Int_t kase, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Skip an element.
Version_t fOldVersion
! Version of the TStreamerInfo object read from the file
Basic string class.
Definition TString.h:139
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1412
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
static const Int_t fgIteratorArenaSize
The size of a small buffer that can be allocated on the stack to store iterator-specific information.
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
@ kUChar
Equal to TDataType's kchar.
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TLine l
Definition textangle.C:4