Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TBufferFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Rene Brun 17/01/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, 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\file TBufferFile.cxx
14\class TBufferFile
15\ingroup IO
16
17The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
18*/
19
20#include <cstring>
21#include <typeinfo>
22#include <string>
23#include <limits>
24#include <cassert>
25
26#include "TFile.h"
27#include "TBufferFile.h"
28#include "TExMap.h"
29#include "TClass.h"
30#include "TStorage.h"
31#include "TError.h"
32#include "TStreamer.h"
33#include "TStreamerInfo.h"
34#include "TStreamerElement.h"
35#include "TSchemaRuleSet.h"
37#include "TInterpreter.h"
38#include "TVirtualMutex.h"
39
40#if (defined(__linux) || defined(__APPLE__)) && defined(__i386__) && \
41 defined(__GNUC__)
42#define USE_BSWAPCPY
43#endif
44
45#ifdef USE_BSWAPCPY
46#include "Bswapcpy.h"
47#endif
48
49
50const UInt_t kNewClassTag = 0xFFFFFFFF;
51const UInt_t kClassMask = 0x80000000; // OR the class index with this
52const UInt_t kByteCountMask = 0x40000000; // OR the byte count with this
53const UInt_t kMaxMapCount = 0x3FFFFFFE; // last valid fMapCount and byte count
54const Version_t kByteCountVMask = 0x4000; // OR the version byte count with this
55const Version_t kMaxVersion = 0x3FFF; // highest possible version number
56const Int_t kMapOffset = 2; // first 2 map entries are taken by null obj and self obj
57
58
59
60////////////////////////////////////////////////////////////////////////////////
61/// Thread-safe check on StreamerInfos of a TClass
62
63static inline bool Class_Has_StreamerInfo(const TClass* cl)
64{
65 // NOTE: we do not need a R__LOCKGUARD2 since we know the
66 // mutex is available since the TClass constructor will make
67 // it
69 return cl->GetStreamerInfos()->GetLast()>1;
70}
71
72////////////////////////////////////////////////////////////////////////////////
73/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
74/// TBuffer::kWrite. By default the I/O buffer has a size of
75/// TBuffer::kInitialSize (1024) bytes.
76
79 fInfo(nullptr), fInfoStack()
80{
81}
82
83////////////////////////////////////////////////////////////////////////////////
84/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
85/// TBuffer::kWrite.
86
89 fInfo(nullptr), fInfoStack()
90{
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Create an I/O buffer object.
95/// Mode should be either TBuffer::kRead or
96/// TBuffer::kWrite. By default the I/O buffer has a size of
97/// TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
98/// to TBuffer via the buf argument. By default this buffer will be adopted
99/// unless adopt is false.
100/// If the new buffer is <b>not</b> adopted and no memory allocation routine
101/// is provided, a Fatal error will be issued if the Buffer attempts to
102/// expand.
103
109
110////////////////////////////////////////////////////////////////////////////////
111/// Delete an I/O buffer object.
112
116
117////////////////////////////////////////////////////////////////////////////////
118/// Increment level.
119
125
126////////////////////////////////////////////////////////////////////////////////
127/// Decrement level.
128
130{
131 fInfo = fInfoStack.back();
132 fInfoStack.pop_back();
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Handle old file formats.
137///
138/// Files written with versions older than 3.00/06 had a non-portable
139/// implementation of Long_t/ULong_t. These types should not have been
140/// used at all. However, because some users had already written many
141/// files with these types we provide this dirty patch for "backward
142/// compatibility"
143
144static void frombufOld(char *&buf, Long_t *x)
145{
146#ifdef R__BYTESWAP
147#ifdef R__B64
148 char *sw = (char *)x;
149 sw[0] = buf[7];
150 sw[1] = buf[6];
151 sw[2] = buf[5];
152 sw[3] = buf[4];
153 sw[4] = buf[3];
154 sw[5] = buf[2];
155 sw[6] = buf[1];
156 sw[7] = buf[0];
157#else
158 char *sw = (char *)x;
159 sw[0] = buf[3];
160 sw[1] = buf[2];
161 sw[2] = buf[1];
162 sw[3] = buf[0];
163#endif
164#else
165 memcpy(x, buf, sizeof(Long_t));
166#endif
167 buf += sizeof(Long_t);
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Read Long from TBuffer.
172
174{
175 TFile *file = (TFile*)fParent;
176 if (file && file->GetVersion() < 30006) {
178 } else {
179 frombuf(fBufCur, &l);
180 }
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// Read TString from TBuffer.
185
187{
188 Int_t nbig;
189 UChar_t nwh;
190 *this >> nwh;
191 if (nwh == 0) {
192 s.UnLink();
193 s.Zero();
194 } else {
195 if (nwh == 255)
196 *this >> nbig;
197 else
198 nbig = nwh;
199
200 nbig = s.Clobber(nbig); // update length since Clobber clamps to MaxSize (if Fatal does not abort)
201 char *data = s.GetPointer();
202 data[nbig] = 0;
203 s.SetSize(nbig);
205 }
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Write TString to TBuffer.
210
212{
213 Int_t nbig = s.Length();
214 UChar_t nwh;
215 if (nbig > 254) {
216 nwh = 255;
217 *this << nwh;
218 *this << nbig;
219 } else {
220 nwh = UChar_t(nbig);
221 *this << nwh;
222 }
223 const char *data = s.GetPointer();
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Read std::string from TBuffer.
229
230void TBufferFile::ReadStdString(std::string *obj)
231{
232 if (obj == nullptr) {
233 Error("TBufferFile::ReadStdString","The std::string address is nullptr but should not");
234 return;
235 }
236 Int_t nbig;
237 UChar_t nwh;
238 *this >> nwh;
239 if (nwh == 0) {
240 obj->clear();
241 } else {
242 if( obj->size() ) {
243 // Insure that the underlying data storage is not shared
244 (*obj)[0] = '\0';
245 }
246 if (nwh == 255) {
247 *this >> nbig;
248 obj->resize(nbig,'\0');
249 ReadFastArray((char*)obj->data(),nbig);
250 }
251 else {
252 obj->resize(nwh,'\0');
253 ReadFastArray((char*)obj->data(),nwh);
254 }
255 }
256}
257
258////////////////////////////////////////////////////////////////////////////////
259/// Write std::string to TBuffer.
260
261void TBufferFile::WriteStdString(const std::string *obj)
262{
263 if (obj==0) {
264 *this << (UChar_t)0;
265 WriteFastArray("",0);
266 return;
267 }
268
269 UChar_t nwh;
270 Int_t nbig = obj->length();
271 if (nbig > 254) {
272 nwh = 255;
273 *this << nwh;
274 *this << nbig;
275 } else {
276 nwh = UChar_t(nbig);
277 *this << nwh;
278 }
279 WriteFastArray(obj->data(),nbig);
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// Read char* from TBuffer.
284
286{
287 delete [] s;
288 s = nullptr;
289
290 Int_t nch;
291 *this >> nch;
292 if (nch > 0) {
293 if (nch == std::numeric_limits<Int_t>::max()) {
294 Error("ReadCharStar", "Cannot allocate buffer: maximum capacity exceeded (%d bytes)!", std::numeric_limits<Int_t>::max());
295 return;
296 }
297 s = new char[nch+1];
298 ReadFastArray(s, nch);
299 s[nch] = 0;
300 }
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Write char* into TBuffer.
305
307{
308 Int_t nch = 0;
309 if (s) {
310 nch = strlen(s);
311 *this << nch;
313 } else {
314 *this << nch;
315 }
316
317}
318
319////////////////////////////////////////////////////////////////////////////////
320/// Set byte count at position cntpos in the buffer. Generate warning if
321/// count larger than kMaxMapCount. The count is excluded its own size.
322/// \note If underflow or overflow, an Error ir raised (stricter checks in Debug mode)
323
325{
326 assert( (sizeof(UInt_t) + cntpos) < static_cast<UInt_t>(fBufCur - fBuffer)
327 && (fBufCur >= fBuffer)
328 && static_cast<ULong64_t>(fBufCur - fBuffer) <= std::numeric_limits<UInt_t>::max()
329 && "Byte count position is after the end of the buffer");
330 const UInt_t cnt = UInt_t(fBufCur - fBuffer) - cntpos - sizeof(UInt_t);
331 char *buf = (char *)(fBuffer + cntpos);
332
333 // if true, pack byte count in two consecutive shorts, so it can
334 // be read by ReadVersion()
335 if (packInVersion) {
336 union {
337 UInt_t cnt;
338 Version_t vers[2];
339 } v;
340 v.cnt = cnt;
341#ifdef R__BYTESWAP
342 tobuf(buf, Version_t(v.vers[1] | kByteCountVMask));
343 tobuf(buf, v.vers[0]);
344#else
345 tobuf(buf, Version_t(v.vers[0] | kByteCountVMask));
346 tobuf(buf, v.vers[1]);
347#endif
348 } else
349 tobuf(buf, cnt | kByteCountMask);
350
351 if (cnt >= kMaxMapCount) {
352 Error("WriteByteCount", "bytecount too large (more than %d)", kMaxMapCount);
353 // exception
354 }
355}
356
357////////////////////////////////////////////////////////////////////////////////
358/// Check byte count with current buffer position. They should
359/// match. If not print warning and position buffer in correct
360/// place determined by the byte count. Startpos is position of
361/// first byte where the byte count is written in buffer.
362/// Returns 0 if everything is ok, otherwise the bytecount offset
363/// (< 0 when read too little, >0 when read too much).
364
366{
367 if (!bcnt) return 0;
368
369 Int_t offset = 0;
370
372
373 if (Longptr_t(fBufCur) != endpos) {
375
376 const char *name = clss ? clss->GetName() : classname ? classname : 0;
377
378 if (name) {
379 if (offset < 0) {
380 Error("CheckByteCount", "object of class %s read too few bytes: %d instead of %d",
382 }
383 if (offset > 0) {
384 Error("CheckByteCount", "object of class %s read too many bytes: %d instead of %d",
386 if (fParent)
387 Warning("CheckByteCount","%s::Streamer() not in sync with data on file %s, fix Streamer()",
388 name, fParent->GetName());
389 else
390 Warning("CheckByteCount","%s::Streamer() not in sync with data, fix Streamer()",
391 name);
392 }
393 }
394 if ( ((char *)endpos) > fBufMax ) {
396 Error("CheckByteCount",
397 "Byte count probably corrupted around buffer position %d:\n\t%d for a possible maximum of %d",
400
401 } else {
402
403 fBufCur = (char *) endpos;
404
405 }
406 }
407 return offset;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// Check byte count with current buffer position. They should
412/// match. If not print warning and position buffer in correct
413/// place determined by the byte count. Startpos is position of
414/// first byte where the byte count is written in buffer.
415/// Returns 0 if everything is ok, otherwise the bytecount offset
416/// (< 0 when read too little, >0 when read too much).
417
419{
420 if (!bcnt) return 0;
421 return CheckByteCount( startpos, bcnt, clss, nullptr);
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Check byte count with current buffer position. They should
426/// match. If not print warning and position buffer in correct
427/// place determined by the byte count. Startpos is position of
428/// first byte where the byte count is written in buffer.
429/// Returns 0 if everything is ok, otherwise the bytecount offset
430/// (< 0 when read too little, >0 when read too much).
431
433{
434 if (!bcnt) return 0;
435 return CheckByteCount( startpos, bcnt, nullptr, classname);
436}
437
438////////////////////////////////////////////////////////////////////////////////
439/// Read a Float16_t from the buffer,
440/// see comments about Float16_t encoding at TBufferFile::WriteFloat16().
441
443{
444 // The parameter should be const, however we have not yet decided how to
445 // transition the signature since the function is virtual. This ensures
446 // that the function does not inadvertently use non-const parts of
447 // TStreamerElement.
448 const TStreamerElement *ele = elem;
449
450 if (ele && ele->GetFactor() != 0) {
451 ReadWithFactor(f, ele->GetFactor(), ele->GetXmin());
452 } else {
453 Int_t nbits = 0;
454 if (ele) nbits = (Int_t)ele->GetXmin();
455 if (!nbits) nbits = 12;
457 }
458}
459
460////////////////////////////////////////////////////////////////////////////////
461/// Read a Double32_t from the buffer,
462/// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
463
465{
466 // The parameter should be const, however we have not yet decided how to
467 // transition the signature since the function is virtual. This ensures
468 // that the function does not inadvertently use non-const parts of
469 // TStreamerElement.
470 const TStreamerElement *ele = elem;
471
472 if (ele && ele->GetFactor() != 0) {
473 ReadWithFactor(d, ele->GetFactor(), ele->GetXmin());
474 } else {
475 Int_t nbits = 0;
476 if (ele) nbits = (Int_t)ele->GetXmin();
477 if (!nbits) {
478 //we read a float and convert it to double
480 *this >> afloat;
481 d[0] = (Double_t)afloat;
482 } else {
484 }
485 }
486}
487
488////////////////////////////////////////////////////////////////////////////////
489/// Read a Float16_t from the buffer when the factor and minimum value have been specified
490/// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
491
493{
494 //a range was specified. We read an integer and convert it back to a double.
495 UInt_t aint;
496 frombuf(this->fBufCur,&aint);
497 ptr[0] = (Float_t)(aint/factor + minvalue);
498}
499
500////////////////////////////////////////////////////////////////////////////////
501/// Read a Float16_t from the buffer when the number of bits is specified (explicitly or not)
502/// see comments about Float16_t encoding at TBufferFile::WriteFloat16().
503
505{
506 //we read the exponent and the truncated mantissa of the float
507 //and rebuild the float.
508 union {
511 } temp;
514 frombuf(this->fBufCur,&theExp);
515 frombuf(this->fBufCur,&theMan);
516 temp.fIntValue = theExp;
517 temp.fIntValue <<= 23;
518 temp.fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
519 if(1<<(nbits+1) & theMan) temp.fFloatValue = -temp.fFloatValue;
520 ptr[0] = temp.fFloatValue;
521}
522
523////////////////////////////////////////////////////////////////////////////////
524/// Read a Double32_t from the buffer when the factor and minimum value have been specified
525/// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
526
528{
529 //a range was specified. We read an integer and convert it back to a double.
530 UInt_t aint;
531 frombuf(this->fBufCur,&aint);
532 ptr[0] = (Double_t)(aint/factor + minvalue);
533}
534
535////////////////////////////////////////////////////////////////////////////////
536/// Read a Double32_t from the buffer when the number of bits is specified (explicitly or not)
537/// see comments about Double32_t encoding at TBufferFile::WriteDouble32().
538
540{
541 //we read the exponent and the truncated mantissa of the float
542 //and rebuild the float.
543 union {
546 } temp;
549 frombuf(this->fBufCur,&theExp);
550 frombuf(this->fBufCur,&theMan);
551 temp.fIntValue = theExp;
552 temp.fIntValue <<= 23;
553 temp.fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
554 if(1<<(nbits+1) & theMan) temp.fFloatValue = -temp.fFloatValue;
555 ptr[0] = (Double_t)temp.fFloatValue;
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Write a Float16_t to the buffer.
560///
561/// The following cases are supported for streaming a Float16_t type
562/// depending on the range declaration in the comment field of the data member:
563/// Case | Example |
564/// -----|---------|
565/// A | Float16_t fNormal; |
566/// B | Float16_t fTemperature; //[0,100]|
567/// C | Float16_t fCharge; //[-1,1,2]|
568/// D | Float16_t fVertex[3]; //[-30,30,10]|
569/// E | Float16_t fChi2; //[0,0,6]|
570/// F | Int_t fNsp;<br>Float16_t* fPointValue; //[fNsp][0,3]|
571///
572/// - In case A fNormal is converted from a Float_t to a Float_t with mantissa truncated to 12 bits
573/// - In case B fTemperature is converted to a 32 bit unsigned integer
574/// - In case C fCharge is converted to a 2 bits unsigned integer
575/// - In case D the array elements of fVertex are converted to an unsigned 10 bits integer
576/// - In case E fChi2 is converted to a Float_t with truncated precision at 6 bits
577/// - In case F the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer
578/// Note that the range specifier must follow the dimension specifier.
579/// Case B has more precision (9 to 10 significative digits than case A (6 to 7 digits).
580/// In Case A and E, the exponent is stored as is (8 bits), for a total of 21 bits (including 1 bit for sign)
581///
582/// The range specifier has the general format: [xmin,xmax] or [xmin,xmax,nbits]
583/// - [0,1];
584/// - [-10,100];
585/// - [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi]
586/// - [-10,100,16]
587/// - [0,0,8]
588/// if nbits is not specified, or nbits <2 or nbits>16 it is set to 16. If
589/// (xmin==0 and xmax==0 and nbits <=14) the float word will have
590/// its mantissa truncated to nbits significative bits.
591///
592/// ## IMPORTANT NOTE
593/// ### NOTE 1
594/// Lets assume an original variable float x:
595/// When using the format [0,0,8] (ie range not specified) you get the best
596/// relative precision when storing and reading back the truncated x, say xt.
597/// The variance of (x-xt)/x will be better than when specifying a range
598/// for the same number of bits. However the precision relative to the
599/// range (x-xt)/(xmax-xmin) will be worst, and vice-versa.
600/// The format [0,0,8] is also interesting when the range of x is infinite
601/// or unknown.
602///
603/// ### NOTE 2
604/// It is important to understand the difference with the meaning of nbits
605/// - in case of [-1,1,nbits], nbits is the total number of bits used to make
606/// the conversion from a float to an integer
607/// - in case of [0,0,nbits], nbits is the number of bits used for the mantissa, to which is added 8 bits for the exponent.
608///
609/// See example of use of the Float16_t data type in tutorial float16.C
610/// \image html tbufferfile_double32.gif
611
613{
614 // The parameter should be const, however we have not yet decided how to
615 // transition the signature since the function is virtual. This ensures
616 // that the function does not inadvertently use non-const parts of
617 // TStreamerElement.
618 const TStreamerElement *ele = elem;
619
620 if (ele && ele->GetFactor() != 0) {
621 //A range is specified. We normalize the double to the range and
622 //convert it to an integer using a scaling factor that is a function of nbits.
623 //see TStreamerElement::GetRange.
624 Double_t x = f[0];
625 Double_t xmin = ele->GetXmin();
626 Double_t xmax = ele->GetXmax();
627 if (x < xmin) x = xmin;
628 if (x > xmax) x = xmax;
629 UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
630 } else {
631 Int_t nbits = 0;
632 //number of bits stored in fXmin (see TStreamerElement::GetRange)
633 if (ele) nbits = (Int_t)ele->GetXmin();
634 if (!nbits) nbits = 12;
635 //a range is not specified, but nbits is.
636 //In this case we truncate the mantissa to nbits and we stream
637 //the exponent as a UChar_t and the mantissa as a UShort_t.
638 union {
641 };
642 fFloatValue = f[0];
643 UChar_t theExp = (UChar_t)(0x000000ff & ((fIntValue<<1)>>24));
644 UShort_t theMan = ((1<<(nbits+1))-1) & (fIntValue>>(23-nbits-1));
645 theMan++;
646 theMan = theMan>>1;
647 if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
648 if (fFloatValue < 0) theMan |= 1<<(nbits+1);
649 *this << theExp;
650 *this << theMan;
651 }
652}
653
654////////////////////////////////////////////////////////////////////////////////
655/// Write a Double32_t to the buffer.
656///
657/// The following cases are supported for streaming a Double32_t type
658/// depending on the range declaration in the comment field of the data member:
659/// Case | Example |
660/// -----|---------|
661/// A | Double32_t fNormal; |
662/// B | Double32_t fTemperature; //[0,100]|
663/// C | Double32_t fCharge; //[-1,1,2]|
664/// D | Double32_t fVertex[3]; //[-30,30,10]|
665/// E | Double32_t fChi2; //[0,0,6]|
666/// F | Int_t fNsp;<br>Double32_t* fPointValue; //[fNsp][0,3]|
667///
668/// In case A fNormal is converted from a Double_t to a Float_t
669/// In case B fTemperature is converted to a 32 bit unsigned integer
670/// In case C fCharge is converted to a 2 bits unsigned integer
671/// In case D the array elements of fVertex are converted to an unsigned 10 bits integer
672/// In case E fChi2 is converted to a Float_t with mantissa truncated precision at 6 bits
673/// In case F the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer
674/// Note that the range specifier must follow the dimension specifier.
675/// Case B has more precision (9 to 10 significative digits than case A (6 to 7 digits).
676/// See TBufferFile::WriteFloat16 for more information.
677///
678/// see example of use of the Double32_t data type in tutorial double32.C
679/// \image html tbufferfile_double32.gif
680
682{
683 // The parameter should be const, however we have not yet decided how to
684 // transition the signature since the function is virtual. This ensures
685 // that the function does not inadvertently use non-const parts of
686 // TStreamerElement.
687 const TStreamerElement *ele = elem;
688
689 if (ele && ele->GetFactor() != 0) {
690 //A range is specified. We normalize the double to the range and
691 //convert it to an integer using a scaling factor that is a function of nbits.
692 //see TStreamerElement::GetRange.
693 Double_t x = d[0];
694 Double_t xmin = ele->GetXmin();
695 Double_t xmax = ele->GetXmax();
696 if (x < xmin) x = xmin;
697 if (x > xmax) x = xmax;
698 UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
699 } else {
700 Int_t nbits = 0;
701 //number of bits stored in fXmin (see TStreamerElement::GetRange)
702 if (ele) nbits = (Int_t)ele->GetXmin();
703 if (!nbits) {
704 //if no range and no bits specified, we convert from double to float
705 Float_t afloat = (Float_t)d[0];
706 *this << afloat;
707 } else {
708 //a range is not specified, but nbits is.
709 //In this case we truncate the mantissa to nbits and we stream
710 //the exponent as a UChar_t and the mantissa as a UShort_t.
711 union {
714 };
715 fFloatValue = (Float_t)d[0];
716 UChar_t theExp = (UChar_t)(0x000000ff & ((fIntValue<<1)>>24));
717 UShort_t theMan = ((1<<(nbits+1))-1) & (fIntValue>>(23-nbits-1)) ;
718 theMan++;
719 theMan = theMan>>1;
720 if (theMan&1<<nbits) theMan = (1<<nbits)-1 ;
721 if (fFloatValue < 0) theMan |= 1<<(nbits+1);
722 *this << theExp;
723 *this << theMan;
724 }
725 }
726}
727
728////////////////////////////////////////////////////////////////////////////////
729/// Read array of bools from the I/O buffer. Returns the number of
730/// bools read. If argument is a 0 pointer then space will be
731/// allocated for the array.
732
734{
736
737 Int_t n;
738 *this >> n;
739
740 if (ShouldNotReadCollection(n)) return 0;
741
742 if (!b) b = new Bool_t[n];
743
744 if (sizeof(Bool_t) > 1) {
745 for (int i = 0; i < n; i++)
746 frombuf(fBufCur, &b[i]);
747 } else {
748 Int_t l = sizeof(Bool_t)*n;
749 memcpy(b, fBufCur, l);
750 fBufCur += l;
751 }
752
753 return n;
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Read array of characters from the I/O buffer. Returns the number of
758/// characters read. If argument is a 0 pointer then space will be
759/// allocated for the array.
760
762{
764
765 Int_t n;
766 *this >> n;
767 Int_t l = sizeof(Char_t)*n;
768
769 if (ShouldNotReadCollection(l, n)) return 0;
770
771 if (!c) c = new Char_t[n];
772
773 memcpy(c, fBufCur, l);
774 fBufCur += l;
775
776 return n;
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// Read array of shorts from the I/O buffer. Returns the number of shorts
781/// read. If argument is a 0 pointer then space will be allocated for the
782/// array.
783
785{
787
788 Int_t n;
789 *this >> n;
790 Int_t l = sizeof(Short_t)*n;
791
792 if (ShouldNotReadCollection(l, n)) return 0;
793
794 if (!h) h = new Short_t[n];
795
796#ifdef R__BYTESWAP
797# ifdef USE_BSWAPCPY
799 fBufCur += l;
800# else
801 for (int i = 0; i < n; i++)
802 frombuf(fBufCur, &h[i]);
803# endif
804#else
805 memcpy(h, fBufCur, l);
806 fBufCur += l;
807#endif
808
809 return n;
810}
811
812////////////////////////////////////////////////////////////////////////////////
813/// Read array of ints from the I/O buffer. Returns the number of ints
814/// read. If argument is a 0 pointer then space will be allocated for the
815/// array.
816
818{
820
821 Int_t n;
822 *this >> n;
823 Int_t l = sizeof(Int_t)*n;
824
825 if (ShouldNotReadCollection(l, n)) return 0;
826
827 if (!ii) ii = new Int_t[n];
828
829#ifdef R__BYTESWAP
830# ifdef USE_BSWAPCPY
832 fBufCur += l;
833# else
834 for (int i = 0; i < n; i++)
835 frombuf(fBufCur, &ii[i]);
836# endif
837#else
838 memcpy(ii, fBufCur, l);
839 fBufCur += l;
840#endif
841
842 return n;
843}
844
845////////////////////////////////////////////////////////////////////////////////
846/// Read array of longs from the I/O buffer. Returns the number of longs
847/// read. If argument is a 0 pointer then space will be allocated for the
848/// array.
849
851{
853
854 Int_t n;
855 *this >> n;
856 Int_t l = sizeof(Long_t)*n;
857
858 if (ShouldNotReadCollection(l, n)) return 0;
859
860 if (!ll) ll = new Long_t[n];
861
862 TFile *file = (TFile*)fParent;
863 if (file && file->GetVersion() < 30006) {
864 for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
865 } else {
866 for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
867 }
868 return n;
869}
870
871////////////////////////////////////////////////////////////////////////////////
872/// Read array of long longs from the I/O buffer. Returns the number of
873/// long longs read. If argument is a 0 pointer then space will be
874/// allocated for the array.
875
877{
879
880 Int_t n;
881 *this >> n;
882 Int_t l = sizeof(Long64_t)*n;
883
884 if (ShouldNotReadCollection(l, n)) return 0;
885
886 if (!ll) ll = new Long64_t[n];
887
888#ifdef R__BYTESWAP
889 for (int i = 0; i < n; i++)
890 frombuf(fBufCur, &ll[i]);
891#else
892 memcpy(ll, fBufCur, l);
893 fBufCur += l;
894#endif
895
896 return n;
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Read array of floats from the I/O buffer. Returns the number of floats
901/// read. If argument is a 0 pointer then space will be allocated for the
902/// array.
903
905{
907
908 Int_t n;
909 *this >> n;
910 Int_t l = sizeof(Float_t)*n;
911
912 if (ShouldNotReadCollection(l, n)) return 0;
913
914 if (!f) f = new Float_t[n];
915
916#ifdef R__BYTESWAP
917# ifdef USE_BSWAPCPY
919 fBufCur += l;
920# else
921 for (int i = 0; i < n; i++)
922 frombuf(fBufCur, &f[i]);
923# endif
924#else
925 memcpy(f, fBufCur, l);
926 fBufCur += l;
927#endif
928
929 return n;
930}
931
932////////////////////////////////////////////////////////////////////////////////
933/// Read array of doubles from the I/O buffer. Returns the number of doubles
934/// read. If argument is a 0 pointer then space will be allocated for the
935/// array.
936
938{
940
941 Int_t n;
942 *this >> n;
943 Int_t l = sizeof(Double_t)*n;
944
945 if (ShouldNotReadCollection(l, n)) return 0;
946
947 if (!d) d = new Double_t[n];
948
949#ifdef R__BYTESWAP
950 for (int i = 0; i < n; i++)
951 frombuf(fBufCur, &d[i]);
952#else
953 memcpy(d, fBufCur, l);
954 fBufCur += l;
955#endif
956
957 return n;
958}
959
960////////////////////////////////////////////////////////////////////////////////
961/// Read array of floats (written as truncated float) from the I/O buffer.
962/// Returns the number of floats read.
963/// If argument is a 0 pointer then space will be allocated for the array.
964/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
965
967{
969
970 Int_t n;
971 *this >> n;
972
973 if (ShouldNotReadCollection(3*n, n)) return 0;
974
975 if (!f) f = new Float_t[n];
976
978
979 return n;
980}
981
982////////////////////////////////////////////////////////////////////////////////
983/// Read array of doubles (written as float) from the I/O buffer.
984/// Returns the number of doubles read.
985/// If argument is a 0 pointer then space will be allocated for the array.
986/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
987
989{
991
992 Int_t n;
993 *this >> n;
994
995 if (ShouldNotReadCollection(3*n, n)) return 0;
996
997 if (!d) d = new Double_t[n];
998
1000
1001 return n;
1002}
1003
1004////////////////////////////////////////////////////////////////////////////////
1005/// Read array of bools from the I/O buffer. Returns the number of bools
1006/// read.
1007
1009{
1011
1012 Int_t n;
1013 *this >> n;
1014
1015 if (ShouldNotReadCollection(n)) return 0;
1016
1017 if (!b) return 0;
1018
1019 if (sizeof(Bool_t) > 1) {
1020 for (int i = 0; i < n; i++)
1021 frombuf(fBufCur, &b[i]);
1022 } else {
1023 Int_t l = sizeof(Bool_t)*n;
1024 memcpy(b, fBufCur, l);
1025 fBufCur += l;
1026 }
1027
1028 return n;
1029}
1030
1031////////////////////////////////////////////////////////////////////////////////
1032/// Read array of characters from the I/O buffer. Returns the number of
1033/// characters read.
1034
1036{
1038
1039 Int_t n;
1040 *this >> n;
1041 Int_t l = sizeof(Char_t)*n;
1042
1043 if (ShouldNotReadCollection(l, n)) return 0;
1044
1045 if (!c) return 0;
1046
1047 memcpy(c, fBufCur, l);
1048 fBufCur += l;
1049
1050 return n;
1051}
1052
1053////////////////////////////////////////////////////////////////////////////////
1054/// Read array of shorts from the I/O buffer. Returns the number of shorts
1055/// read.
1056
1058{
1060
1061 Int_t n;
1062 *this >> n;
1063 Int_t l = sizeof(Short_t)*n;
1064
1065 if (ShouldNotReadCollection(l, n)) return 0;
1066
1067 if (!h) return 0;
1068
1069#ifdef R__BYTESWAP
1070# ifdef USE_BSWAPCPY
1071 bswapcpy16(h, fBufCur, n);
1072 fBufCur += l;
1073# else
1074 for (int i = 0; i < n; i++)
1075 frombuf(fBufCur, &h[i]);
1076# endif
1077#else
1078 memcpy(h, fBufCur, l);
1079 fBufCur += l;
1080#endif
1081
1082 return n;
1083}
1084
1085////////////////////////////////////////////////////////////////////////////////
1086/// Read array of ints from the I/O buffer. Returns the number of ints
1087/// read.
1088
1090{
1092
1093 Int_t n;
1094 *this >> n;
1095 Int_t l = sizeof(Int_t)*n;
1096
1097 if (ShouldNotReadCollection(l, n)) return 0;
1098
1099 if (!ii) return 0;
1100
1101#ifdef R__BYTESWAP
1102# ifdef USE_BSWAPCPY
1104 fBufCur += sizeof(Int_t)*n;
1105# else
1106 for (int i = 0; i < n; i++)
1107 frombuf(fBufCur, &ii[i]);
1108# endif
1109#else
1110 memcpy(ii, fBufCur, l);
1111 fBufCur += l;
1112#endif
1113
1114 return n;
1115}
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Read array of longs from the I/O buffer. Returns the number of longs
1119/// read.
1120
1122{
1124
1125 Int_t n;
1126 *this >> n;
1127 Int_t l = sizeof(Long_t)*n;
1128
1129 if (ShouldNotReadCollection(l, n)) return 0;
1130
1131 if (!ll) return 0;
1132
1133 TFile *file = (TFile*)fParent;
1134 if (file && file->GetVersion() < 30006) {
1135 for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
1136 } else {
1137 for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
1138 }
1139 return n;
1140}
1141
1142////////////////////////////////////////////////////////////////////////////////
1143/// Read array of long longs from the I/O buffer. Returns the number of
1144/// long longs read.
1145
1147{
1149
1150 Int_t n;
1151 *this >> n;
1152 Int_t l = sizeof(Long64_t)*n;
1153
1154 if (ShouldNotReadCollection(l, n)) return 0;
1155
1156 if (!ll) return 0;
1157
1158#ifdef R__BYTESWAP
1159 for (int i = 0; i < n; i++)
1160 frombuf(fBufCur, &ll[i]);
1161#else
1162 memcpy(ll, fBufCur, l);
1163 fBufCur += l;
1164#endif
1165
1166 return n;
1167}
1168
1169////////////////////////////////////////////////////////////////////////////////
1170/// Read array of floats from the I/O buffer. Returns the number of floats
1171/// read.
1172
1174{
1176
1177 Int_t n;
1178 *this >> n;
1179 Int_t l = sizeof(Float_t)*n;
1180
1181 if (ShouldNotReadCollection(l, n)) return 0;
1182
1183 if (!f) return 0;
1184
1185#ifdef R__BYTESWAP
1186# ifdef USE_BSWAPCPY
1187 bswapcpy32(f, fBufCur, n);
1188 fBufCur += sizeof(Float_t)*n;
1189# else
1190 for (int i = 0; i < n; i++)
1191 frombuf(fBufCur, &f[i]);
1192# endif
1193#else
1194 memcpy(f, fBufCur, l);
1195 fBufCur += l;
1196#endif
1197
1198 return n;
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// Read array of doubles from the I/O buffer. Returns the number of doubles
1203/// read.
1204
1206{
1208
1209 Int_t n;
1210 *this >> n;
1211 Int_t l = sizeof(Double_t)*n;
1212
1213 if (ShouldNotReadCollection(l, n)) return 0;
1214
1215 if (!d) return 0;
1216
1217#ifdef R__BYTESWAP
1218 for (int i = 0; i < n; i++)
1219 frombuf(fBufCur, &d[i]);
1220#else
1221 memcpy(d, fBufCur, l);
1222 fBufCur += l;
1223#endif
1224
1225 return n;
1226}
1227
1228////////////////////////////////////////////////////////////////////////////////
1229/// Read array of floats (written as truncated float) from the I/O buffer.
1230/// Returns the number of floats read.
1231/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
1232
1234{
1236
1237 Int_t n;
1238 *this >> n;
1239
1240 if (ShouldNotReadCollection(3*n, n)) return 0;
1241
1242 if (!f) return 0;
1243
1245
1246 return n;
1247}
1248
1249////////////////////////////////////////////////////////////////////////////////
1250/// Read array of doubles (written as float) from the I/O buffer.
1251/// Returns the number of doubles read.
1252/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
1253
1255{
1257
1258 Int_t n;
1259 *this >> n;
1260
1261 if (ShouldNotReadCollection(3*n, n)) return 0;
1262
1263 if (!d) return 0;
1264
1266
1267 return n;
1268}
1269
1270////////////////////////////////////////////////////////////////////////////////
1271/// Read array of n bools from the I/O buffer.
1272
1274{
1275 if (ShouldNotReadCollection(n)) return;
1276
1277 if (sizeof(Bool_t) > 1) {
1278 for (int i = 0; i < n; i++)
1279 frombuf(fBufCur, &b[i]);
1280 } else {
1281 Int_t l = sizeof(Bool_t)*n;
1282 memcpy(b, fBufCur, l);
1283 fBufCur += l;
1284 }
1285}
1286
1287////////////////////////////////////////////////////////////////////////////////
1288/// Read array of n characters from the I/O buffer.
1289
1291{
1292 if (ShouldNotReadCollection(n)) return;
1293
1294 Int_t l = sizeof(Char_t)*n;
1295 memcpy(c, fBufCur, l);
1296 fBufCur += l;
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Read array of n characters from the I/O buffer.
1301
1303{
1304 Int_t len;
1306 *this >> lenchar;
1307 if (lenchar < 255) {
1308 len = lenchar;
1309 } else {
1310 *this >> len;
1311 }
1312 if (len) {
1313 if (ShouldNotReadCollection(len)) return;
1314 Int_t blen = len;
1315 if (len >= n) len = n-1;
1316
1317 Int_t l = sizeof(Char_t)*len;
1318 memcpy(c, fBufCur, l);
1319 fBufCur += blen;
1320
1321 c[len] = 0;
1322 } else {
1323 c[0] = 0;
1324 }
1325}
1326
1327////////////////////////////////////////////////////////////////////////////////
1328/// Read array of n shorts from the I/O buffer.
1329
1331{
1332 Int_t l = sizeof(Short_t)*n;
1333 if (ShouldNotReadCollection(l, n)) return;
1334
1335#ifdef R__BYTESWAP
1336# ifdef USE_BSWAPCPY
1337 bswapcpy16(h, fBufCur, n);
1338 fBufCur += sizeof(Short_t)*n;
1339# else
1340 for (int i = 0; i < n; i++)
1341 frombuf(fBufCur, &h[i]);
1342# endif
1343#else
1344 memcpy(h, fBufCur, l);
1345 fBufCur += l;
1346#endif
1347}
1348
1349////////////////////////////////////////////////////////////////////////////////
1350/// Read array of n ints from the I/O buffer.
1351
1353{
1354 Int_t l = sizeof(Int_t)*n;
1355 if (ShouldNotReadCollection(l, n)) return;
1356
1357#ifdef R__BYTESWAP
1358# ifdef USE_BSWAPCPY
1360 fBufCur += sizeof(Int_t)*n;
1361# else
1362 for (int i = 0; i < n; i++)
1363 frombuf(fBufCur, &ii[i]);
1364# endif
1365#else
1366 memcpy(ii, fBufCur, l);
1367 fBufCur += l;
1368#endif
1369}
1370
1371////////////////////////////////////////////////////////////////////////////////
1372/// Read array of n longs from the I/O buffer.
1373
1375{
1376 Int_t l = sizeof(Long_t)*n;
1377 if (ShouldNotReadCollection(l, n)) return;
1378
1379 TFile *file = (TFile*)fParent;
1380 if (file && file->GetVersion() < 30006) {
1381 for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
1382 } else {
1383 for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
1384 }
1385}
1386
1387////////////////////////////////////////////////////////////////////////////////
1388/// Read array of n long longs from the I/O buffer.
1389
1391{
1392 Int_t l = sizeof(Long64_t)*n;
1393 if (ShouldNotReadCollection(l, n)) return;
1394
1395#ifdef R__BYTESWAP
1396 for (int i = 0; i < n; i++)
1397 frombuf(fBufCur, &ll[i]);
1398#else
1399 memcpy(ll, fBufCur, l);
1400 fBufCur += l;
1401#endif
1402}
1403
1404////////////////////////////////////////////////////////////////////////////////
1405/// Read array of n floats from the I/O buffer.
1406
1408{
1409 Int_t l = sizeof(Float_t)*n;
1410 if (ShouldNotReadCollection(l, n)) return;
1411
1412#ifdef R__BYTESWAP
1413# ifdef USE_BSWAPCPY
1414 bswapcpy32(f, fBufCur, n);
1415 fBufCur += sizeof(Float_t)*n;
1416# else
1417 for (int i = 0; i < n; i++)
1418 frombuf(fBufCur, &f[i]);
1419# endif
1420#else
1421 memcpy(f, fBufCur, l);
1422 fBufCur += l;
1423#endif
1424}
1425
1426////////////////////////////////////////////////////////////////////////////////
1427/// Read array of n doubles from the I/O buffer.
1428
1430{
1431 Int_t l = sizeof(Double_t)*n;
1432 if (ShouldNotReadCollection(l, n)) return;
1433
1434#ifdef R__BYTESWAP
1435 for (int i = 0; i < n; i++)
1436 frombuf(fBufCur, &d[i]);
1437#else
1438 memcpy(d, fBufCur, l);
1439 fBufCur += l;
1440#endif
1441}
1442
1443////////////////////////////////////////////////////////////////////////////////
1444/// Read array of n floats (written as truncated float) from the I/O buffer.
1445/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
1446
1448{
1449 if (ShouldNotReadCollection(3*n, n)) return;
1450
1451 // The parameter should be const, however we have not yet decided how to
1452 // transition the signature since the function is virtual. This ensures
1453 // that the function does not inadvertently use non-const parts of
1454 // TStreamerElement.
1455 const TStreamerElement *ele = elem;
1456
1457 if (ele && ele->GetFactor() != 0) {
1458 //a range was specified. We read an integer and convert it back to a float
1459 Double_t xmin = ele->GetXmin();
1460 Double_t factor = ele->GetFactor();
1461 for (int j=0;j < n; j++) {
1462 UInt_t aint; *this >> aint; f[j] = (Float_t)(aint/factor + xmin);
1463 }
1464 } else {
1465 Int_t i;
1466 Int_t nbits = 0;
1467 if (ele) nbits = (Int_t)ele->GetXmin();
1468 if (!nbits) nbits = 12;
1469 //we read the exponent and the truncated mantissa of the float
1470 //and rebuild the new float.
1471 union {
1474 };
1477 for (i = 0; i < n; i++) {
1478 *this >> theExp;
1479 *this >> theMan;
1480 fIntValue = theExp;
1481 fIntValue <<= 23;
1482 fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
1483 if(1<<(nbits+1) & theMan) fFloatValue = -fFloatValue;
1484 f[i] = fFloatValue;
1485 }
1486 }
1487}
1488
1489////////////////////////////////////////////////////////////////////////////////
1490/// Read array of n floats (written as truncated float) from the I/O buffer.
1491/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
1492
1494{
1495 if (ShouldNotReadCollection(3*n, n)) return;
1496
1497 //a range was specified. We read an integer and convert it back to a float
1498 for (int j=0;j < n; j++) {
1499 UInt_t aint; *this >> aint; ptr[j] = (Float_t)(aint/factor + minvalue);
1500 }
1501}
1502
1503////////////////////////////////////////////////////////////////////////////////
1504/// Read array of n floats (written as truncated float) from the I/O buffer.
1505/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
1506
1508{
1509 if (ShouldNotReadCollection(3*n, n)) return;
1510
1511 if (!nbits) nbits = 12;
1512 //we read the exponent and the truncated mantissa of the float
1513 //and rebuild the new float.
1514 union {
1517 };
1520 for (Int_t i = 0; i < n; i++) {
1521 *this >> theExp;
1522 *this >> theMan;
1523 fIntValue = theExp;
1524 fIntValue <<= 23;
1525 fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
1526 if(1<<(nbits+1) & theMan) fFloatValue = -fFloatValue;
1527 ptr[i] = fFloatValue;
1528 }
1529}
1530
1531////////////////////////////////////////////////////////////////////////////////
1532/// Read array of n doubles (written as float) from the I/O buffer.
1533/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
1534
1536{
1537 // The parameter should be const, however we have not yet decided how to
1538 // transition the signature since the function is virtual. This ensures
1539 // that the function does not inadvertently use non-const parts of
1540 // TStreamerElement.
1541 const TStreamerElement *ele = elem;
1542 if (ShouldNotReadCollection(3*n, n)) return;
1543
1544 if (ele && ele->GetFactor() != 0) {
1545 //a range was specified. We read an integer and convert it back to a double.
1546 Double_t xmin = ele->GetXmin();
1547 Double_t factor = ele->GetFactor();
1548 for (int j=0;j < n; j++) {
1549 UInt_t aint; *this >> aint; d[j] = (Double_t)(aint/factor + xmin);
1550 }
1551 } else {
1552 Int_t i;
1553 Int_t nbits = 0;
1554 if (ele) nbits = (Int_t)ele->GetXmin();
1555 if (!nbits) {
1556 //we read a float and convert it to double
1558 for (i = 0; i < n; i++) {
1559 *this >> afloat;
1560 d[i] = (Double_t)afloat;
1561 }
1562 } else {
1563 //we read the exponent and the truncated mantissa of the float
1564 //and rebuild the double.
1565 union {
1568 };
1571 for (i = 0; i < n; i++) {
1572 *this >> theExp;
1573 *this >> theMan;
1574 fIntValue = theExp;
1575 fIntValue <<= 23;
1576 fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
1577 if (1<<(nbits+1) & theMan) fFloatValue = -fFloatValue;
1578 d[i] = (Double_t)fFloatValue;
1579 }
1580 }
1581 }
1582}
1583
1584////////////////////////////////////////////////////////////////////////////////
1585/// Read array of n doubles (written as float) from the I/O buffer.
1586/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
1587
1589{
1590 if (ShouldNotReadCollection(3*n, n)) return;
1591
1592 //a range was specified. We read an integer and convert it back to a double.
1593 for (int j=0;j < n; j++) {
1594 UInt_t aint; *this >> aint; d[j] = (Double_t)(aint/factor + minvalue);
1595 }
1596}
1597
1598////////////////////////////////////////////////////////////////////////////////
1599/// Read array of n doubles (written as float) from the I/O buffer.
1600/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
1601
1603{
1604 if (ShouldNotReadCollection(3*n, n)) return;
1605
1606 if (!nbits) {
1607 //we read a float and convert it to double
1609 for (Int_t i = 0; i < n; i++) {
1610 *this >> afloat;
1611 d[i] = (Double_t)afloat;
1612 }
1613 } else {
1614 //we read the exponent and the truncated mantissa of the float
1615 //and rebuild the double.
1616 union {
1619 };
1622 for (Int_t i = 0; i < n; i++) {
1623 *this >> theExp;
1624 *this >> theMan;
1625 fIntValue = theExp;
1626 fIntValue <<= 23;
1627 fIntValue |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
1628 if (1<<(nbits+1) & theMan) fFloatValue = -fFloatValue;
1629 d[i] = (Double_t)fFloatValue;
1630 }
1631 }
1632}
1633
1634////////////////////////////////////////////////////////////////////////////////
1635/// Read an array of 'n' objects from the I/O buffer.
1636/// Stores the objects read starting at the address 'start'.
1637/// The objects in the array are assume to be of class 'cl'.
1638
1639void TBufferFile::ReadFastArray(void *start, const TClass *cl, Int_t n,
1641{
1642 if (streamer) {
1643 streamer->SetOnFileClass(onFileClass);
1644 (*streamer)(*this,start,0);
1645 return;
1646 }
1647
1648 int objectSize = cl->Size();
1649 char *obj = (char*)start;
1650 char *end = obj + n*objectSize;
1651
1652 for(; obj<end; obj+=objectSize) ((TClass*)cl)->Streamer(obj,*this, onFileClass);
1653}
1654
1655////////////////////////////////////////////////////////////////////////////////
1656/// Read an array of 'n' objects from the I/O buffer.
1657///
1658/// The objects read are stored starting at the address '*start'
1659/// The objects in the array are assumed to be of class 'cl' or a derived class.
1660/// 'mode' indicates whether the data member is marked with '->'
1661
1662void TBufferFile::ReadFastArray(void **start, const TClass *cl, Int_t n,
1664{
1665 // if isPreAlloc is true (data member has a ->) we can assume that the pointer (*start)
1666 // is never 0.
1667
1668 if (streamer) {
1669 if (isPreAlloc) {
1670 for (Int_t j=0;j<n;j++) {
1671 if (!start[j]) start[j] = cl->New();
1672 }
1673 }
1674 streamer->SetOnFileClass(onFileClass);
1675 (*streamer)(*this,(void*)start,0);
1676 return;
1677 }
1678
1679 if (!isPreAlloc) {
1680
1681 for (Int_t j=0; j<n; j++){
1682 //delete the object or collection
1683 void *old = start[j];
1684 start[j] = ReadObjectAny(cl);
1685 if (old && old!=start[j] &&
1687 // There are some cases where the user may set up a pointer in the (default)
1688 // constructor but not mark this pointer as transient. Sometime the value
1689 // of this pointer is the address of one of the object with just created
1690 // and the following delete would result in the deletion (possibly of the
1691 // top level object we are goint to return!).
1692 // Eventhough this is a user error, we could prevent the crash by simply
1693 // adding:
1694 // && !CheckObject(start[j],cl)
1695 // However this can increase the read time significantly (10% in the case
1696 // of one TLine pointer in the test/Track and run ./Event 200 0 0 20 30000
1697 //
1698 // If ReadObjectAny returned the same value as we previous had, this means
1699 // that when writing this object (start[j] had already been written and
1700 // is indeed pointing to the same object as the object the user set up
1701 // in the default constructor).
1702 ) {
1703 ((TClass*)cl)->Destructor(old,kFALSE); // call delete and destructor
1704 }
1705 }
1706
1707 } else {
1708 //case //-> in comment
1709
1710 for (Int_t j=0; j<n; j++){
1711 if (!start[j]) start[j] = ((TClass*)cl)->New();
1712 ((TClass*)cl)->Streamer(start[j],*this,onFileClass);
1713 }
1714
1715 }
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// Write array of n bools into the I/O buffer.
1720
1722{
1724
1725 *this << n;
1726
1727 if (n <= 0) return;
1728
1729 R__ASSERT(b);
1730
1731 Int_t l = sizeof(UChar_t)*n;
1733
1734 if (sizeof(Bool_t) > 1) {
1735 for (int i = 0; i < n; i++)
1736 tobuf(fBufCur, b[i]);
1737 } else {
1738 memcpy(fBufCur, b, l);
1739 fBufCur += l;
1740 }
1741}
1742
1743////////////////////////////////////////////////////////////////////////////////
1744/// Write array of n characters into the I/O buffer.
1745
1747{
1749
1750 *this << n;
1751
1752 if (n <= 0) return;
1753
1754 R__ASSERT(c);
1755
1756 Int_t l = sizeof(Char_t)*n;
1758
1759 memcpy(fBufCur, c, l);
1760 fBufCur += l;
1761}
1762
1763////////////////////////////////////////////////////////////////////////////////
1764/// Write array of n shorts into the I/O buffer.
1765
1767{
1769
1770 *this << n;
1771
1772 if (n <= 0) return;
1773
1774 R__ASSERT(h);
1775
1776 Int_t l = sizeof(Short_t)*n;
1778
1779#ifdef R__BYTESWAP
1780# ifdef USE_BSWAPCPY
1781 bswapcpy16(fBufCur, h, n);
1782 fBufCur += l;
1783# else
1784 for (int i = 0; i < n; i++)
1785 tobuf(fBufCur, h[i]);
1786# endif
1787#else
1788 memcpy(fBufCur, h, l);
1789 fBufCur += l;
1790#endif
1791}
1792
1793////////////////////////////////////////////////////////////////////////////////
1794/// Write array of n ints into the I/O buffer.
1795
1797{
1799
1800 *this << n;
1801
1802 if (n <= 0) return;
1803
1804 R__ASSERT(ii);
1805
1806 Int_t l = sizeof(Int_t)*n;
1808
1809#ifdef R__BYTESWAP
1810# ifdef USE_BSWAPCPY
1812 fBufCur += l;
1813# else
1814 for (int i = 0; i < n; i++)
1815 tobuf(fBufCur, ii[i]);
1816# endif
1817#else
1818 memcpy(fBufCur, ii, l);
1819 fBufCur += l;
1820#endif
1821}
1822
1823////////////////////////////////////////////////////////////////////////////////
1824/// Write array of n longs into the I/O buffer.
1825
1827{
1829
1830 *this << n;
1831
1832 if (n <= 0) return;
1833
1834 R__ASSERT(ll);
1835
1836 Int_t l = 8*n;
1838 for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
1839}
1840
1841////////////////////////////////////////////////////////////////////////////////
1842/// Write array of n unsigned longs into the I/O buffer.
1843/// This is an explicit case for unsigned longs since signed longs
1844/// have a special tobuf().
1845
1847{
1849
1850 *this << n;
1851
1852 if (n <= 0) return;
1853
1854 R__ASSERT(ll);
1855
1856 Int_t l = 8*n;
1858 for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
1859}
1860
1861////////////////////////////////////////////////////////////////////////////////
1862/// Write array of n long longs into the I/O buffer.
1863
1865{
1867
1868 *this << n;
1869
1870 if (n <= 0) return;
1871
1872 R__ASSERT(ll);
1873
1874 Int_t l = sizeof(Long64_t)*n;
1876
1877#ifdef R__BYTESWAP
1878 for (int i = 0; i < n; i++)
1879 tobuf(fBufCur, ll[i]);
1880#else
1881 memcpy(fBufCur, ll, l);
1882 fBufCur += l;
1883#endif
1884}
1885
1886////////////////////////////////////////////////////////////////////////////////
1887/// Write array of n floats into the I/O buffer.
1888
1890{
1892
1893 *this << n;
1894
1895 if (n <= 0) return;
1896
1897 R__ASSERT(f);
1898
1899 Int_t l = sizeof(Float_t)*n;
1901
1902#ifdef R__BYTESWAP
1903# ifdef USE_BSWAPCPY
1904 bswapcpy32(fBufCur, f, n);
1905 fBufCur += l;
1906# else
1907 for (int i = 0; i < n; i++)
1908 tobuf(fBufCur, f[i]);
1909# endif
1910#else
1911 memcpy(fBufCur, f, l);
1912 fBufCur += l;
1913#endif
1914}
1915
1916////////////////////////////////////////////////////////////////////////////////
1917/// Write array of n doubles into the I/O buffer.
1918
1920{
1922
1923 *this << n;
1924
1925 if (n <= 0) return;
1926
1927 R__ASSERT(d);
1928
1929 Int_t l = sizeof(Double_t)*n;
1931
1932#ifdef R__BYTESWAP
1933 for (int i = 0; i < n; i++)
1934 tobuf(fBufCur, d[i]);
1935#else
1936 memcpy(fBufCur, d, l);
1937 fBufCur += l;
1938#endif
1939}
1940
1941////////////////////////////////////////////////////////////////////////////////
1942/// Write array of n floats (as truncated float) into the I/O buffer.
1943/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
1944
1946{
1948
1949 *this << n;
1950
1951 if (n <= 0) return;
1952
1953 R__ASSERT(f);
1954
1955 Int_t l = sizeof(Float_t)*n;
1957
1959}
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Write array of n doubles (as float) into the I/O buffer.
1963/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
1964
1966{
1968
1969 *this << n;
1970
1971 if (n <= 0) return;
1972
1973 R__ASSERT(d);
1974
1975 Int_t l = sizeof(Float_t)*n;
1977
1979}
1980
1981////////////////////////////////////////////////////////////////////////////////
1982/// Write array of n bools into the I/O buffer.
1983/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
1984
1986{
1987 if (n == 0) return;
1988
1989 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(UChar_t));
1990 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
1992 {
1993 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
1994 return; // In case the user re-routes the error handler to not die when Fatal is called
1995 }
1996
1997 Int_t l = sizeof(UChar_t)*n;
1999
2000 if (sizeof(Bool_t) > 1) {
2001 for (int i = 0; i < n; i++)
2002 tobuf(fBufCur, b[i]);
2003 } else {
2004 memcpy(fBufCur, b, l);
2005 fBufCur += l;
2006 }
2007}
2008
2009////////////////////////////////////////////////////////////////////////////////
2010/// Write array of n characters into the I/O buffer.
2011/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2012
2014{
2015 if (n == 0) return;
2016
2017 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Char_t));
2018 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2020 {
2021 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2022 return; // In case the user re-routes the error handler to not die when Fatal is called
2023 }
2024
2025 Int_t l = sizeof(Char_t)*n;
2027
2028 memcpy(fBufCur, c, l);
2029 fBufCur += l;
2030}
2031
2032////////////////////////////////////////////////////////////////////////////////
2033/// Write array of n characters into the I/O buffer.
2034/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2035
2037{
2038 if (n == 0) return;
2039
2040 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Char_t));
2041 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2043 {
2044 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2045 return; // In case the user re-routes the error handler to not die when Fatal is called
2046 }
2047
2048 if (n < 255) {
2049 *this << (UChar_t)n;
2050 } else {
2051 *this << (UChar_t)255;
2052 *this << (Int_t)n;
2053 }
2054
2055 Int_t l = sizeof(Char_t)*n;
2057
2058 memcpy(fBufCur, c, l);
2059 fBufCur += l;
2060}
2061
2062////////////////////////////////////////////////////////////////////////////////
2063/// Write array of n shorts into the I/O buffer.
2064/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2065
2067{
2068 if (n == 0) return;
2069
2070 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Short_t));
2071 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2073 {
2074 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2075 return; // In case the user re-routes the error handler to not die when Fatal is called
2076 }
2077
2078 Int_t l = sizeof(Short_t)*n;
2080
2081#ifdef R__BYTESWAP
2082# ifdef USE_BSWAPCPY
2083 bswapcpy16(fBufCur, h, n);
2084 fBufCur += l;
2085# else
2086 for (int i = 0; i < n; i++)
2087 tobuf(fBufCur, h[i]);
2088# endif
2089#else
2090 memcpy(fBufCur, h, l);
2091 fBufCur += l;
2092#endif
2093}
2094
2095////////////////////////////////////////////////////////////////////////////////
2096/// Write array of n ints into the I/O buffer.
2097/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2098
2100{
2101 if (n == 0) return;
2102
2103 constexpr Int_t dataWidth = 4;
2104 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2106 {
2107 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2108 return; // In case the user re-routes the error handler to not die when Fatal is called
2109 }
2110
2111 Int_t l = sizeof(Int_t)*n;
2113
2114#ifdef R__BYTESWAP
2115# ifdef USE_BSWAPCPY
2117 fBufCur += l;
2118# else
2119 for (int i = 0; i < n; i++)
2120 tobuf(fBufCur, ii[i]);
2121# endif
2122#else
2123 memcpy(fBufCur, ii, l);
2124 fBufCur += l;
2125#endif
2126}
2127
2128////////////////////////////////////////////////////////////////////////////////
2129/// Write array of n longs into the I/O buffer with 8-byte width.
2130/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2131
2133{
2134 if (n == 0) return;
2135
2136 constexpr Int_t dataWidth = 8;
2137 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2139 {
2140 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2141 return; // In case the user re-routes the error handler to not die when Fatal is called
2142 }
2143
2144 Int_t l = 8*n;
2146
2147 for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
2148}
2149
2150////////////////////////////////////////////////////////////////////////////////
2151/// Write array of n unsigned longs into the I/O buffer with 8-byte width.
2152/// This is an explicit case for unsigned longs since signed longs
2153/// have a special tobuf().
2154/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2155
2157{
2158 if (n == 0) return;
2159
2160 constexpr Int_t dataWidth = 8;
2161 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2163 {
2164 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2165 return; // In case the user re-routes the error handler to not die when Fatal is called
2166 }
2167
2168 Int_t l = 8*n;
2170
2171 for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
2172}
2173
2174////////////////////////////////////////////////////////////////////////////////
2175/// Write array of n long longs into the I/O buffer.
2176/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2177
2179{
2180 if (n == 0) return;
2181
2182 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Long64_t));
2183 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2185 {
2186 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2187 return; // In case the user re-routes the error handler to not die when Fatal is called
2188 }
2189
2190 Int_t l = sizeof(Long64_t)*n;
2192
2193#ifdef R__BYTESWAP
2194 for (int i = 0; i < n; i++)
2195 tobuf(fBufCur, ll[i]);
2196#else
2197 memcpy(fBufCur, ll, l);
2198 fBufCur += l;
2199#endif
2200}
2201
2202////////////////////////////////////////////////////////////////////////////////
2203/// Write array of n floats into the I/O buffer.
2204/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2205
2207{
2208 if (n == 0) return;
2209
2210 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Float_t));
2211 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2213 {
2214 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2215 return; // In case the user re-routes the error handler to not die when Fatal is called
2216 }
2217
2218 Int_t l = sizeof(Float_t)*n;
2220
2221#ifdef R__BYTESWAP
2222# ifdef USE_BSWAPCPY
2223 bswapcpy32(fBufCur, f, n);
2224 fBufCur += l;
2225# else
2226 for (int i = 0; i < n; i++)
2227 tobuf(fBufCur, f[i]);
2228# endif
2229#else
2230 memcpy(fBufCur, f, l);
2231 fBufCur += l;
2232#endif
2233}
2234
2235////////////////////////////////////////////////////////////////////////////////
2236/// Write array of n doubles into the I/O buffer.
2237/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2238
2240{
2241 if (n == 0) return;
2242
2243 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Double_t));
2244 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2246 {
2247 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2248 return; // In case the user re-routes the error handler to not die when Fatal is called
2249 }
2250
2251 Int_t l = sizeof(Double_t)*n;
2253
2254#ifdef R__BYTESWAP
2255 for (int i = 0; i < n; i++)
2256 tobuf(fBufCur, d[i]);
2257#else
2258 memcpy(fBufCur, d, l);
2259 fBufCur += l;
2260#endif
2261}
2262
2263////////////////////////////////////////////////////////////////////////////////
2264/// Write array of n floats (as truncated float) into the I/O buffer.
2265/// see comments about Float16_t encoding at TBufferFile::WriteFloat16
2266/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2267
2269{
2270 if (n == 0) return;
2271
2272 // The parameter should be const, however we have not yet decided how to
2273 // transition the signature since the function is virtual. This ensures
2274 // that the function does not inadvertently use non-const parts of
2275 // TStreamerElement.
2276 const TStreamerElement *ele = elem;
2277
2278 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Float_t));
2279 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2281 {
2282 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2283 return; // In case the user re-routes the error handler to not die when Fatal is called
2284 }
2285
2286 Int_t l = sizeof(Float_t)*n;
2288
2289 if (ele && ele->GetFactor()) {
2290 //A range is specified. We normalize the float to the range and
2291 //convert it to an integer using a scaling factor that is a function of nbits.
2292 //see TStreamerElement::GetRange.
2293 Double_t factor = ele->GetFactor();
2294 Double_t xmin = ele->GetXmin();
2295 Double_t xmax = ele->GetXmax();
2296 for (int j = 0; j < n; j++) {
2297 Float_t x = f[j];
2298 if (x < xmin) x = xmin;
2299 if (x > xmax) x = xmax;
2300 UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
2301 }
2302 } else {
2303 Int_t nbits = 0;
2304 //number of bits stored in fXmin (see TStreamerElement::GetRange)
2305 if (ele) nbits = (Int_t)ele->GetXmin();
2306 if (!nbits) nbits = 12;
2307 Int_t i;
2308 //a range is not specified, but nbits is.
2309 //In this case we truncate the mantissa to nbits and we stream
2310 //the exponent as a UChar_t and the mantissa as a UShort_t.
2311 union {
2314 };
2315 for (i = 0; i < n; i++) {
2316 fFloatValue = f[i];
2317 UChar_t theExp = (UChar_t)(0x000000ff & ((fIntValue<<1)>>24));
2318 UShort_t theMan = ((1<<(nbits+1))-1) & (fIntValue>>(23-nbits-1));
2319 theMan++;
2320 theMan = theMan>>1;
2321 if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
2322 if (fFloatValue < 0) theMan |= 1<<(nbits+1);
2323 *this << theExp;
2324 *this << theMan;
2325 }
2326 }
2327}
2328
2329////////////////////////////////////////////////////////////////////////////////
2330/// Write array of n doubles (as float) into the I/O buffer.
2331/// see comments about Double32_t encoding at TBufferFile::WriteDouble32
2332/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2333
2335{
2336 if (n == 0) return;
2337
2338 // The parameter should be const, however we have not yet decided how to
2339 // transition the signature since the function is virtual. This ensures
2340 // that the function does not inadvertently use non-const parts of
2341 // TStreamerElement.
2342 const TStreamerElement *ele = elem;
2343
2344 constexpr Int_t dataWidth = static_cast<Int_t>(sizeof(Float_t));
2345 const Int_t maxElements = (std::numeric_limits<Int_t>::max() - Length())/dataWidth;
2347 {
2348 Fatal("WriteFastArray", "Not enough space left in the buffer (1GB limit). %lld elements is greater than the max left of %d", n, maxElements);
2349 return; // In case the user re-routes the error handler to not die when Fatal is called
2350 }
2351
2352 Int_t l = sizeof(Float_t)*n;
2354
2355 if (ele && ele->GetFactor()) {
2356 //A range is specified. We normalize the double to the range and
2357 //convert it to an integer using a scaling factor that is a function of nbits.
2358 //see TStreamerElement::GetRange.
2359 Double_t factor = ele->GetFactor();
2360 Double_t xmin = ele->GetXmin();
2361 Double_t xmax = ele->GetXmax();
2362 for (int j = 0; j < n; j++) {
2363 Double_t x = d[j];
2364 if (x < xmin) x = xmin;
2365 if (x > xmax) x = xmax;
2366 UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
2367 }
2368 } else {
2369 Int_t nbits = 0;
2370 //number of bits stored in fXmin (see TStreamerElement::GetRange)
2371 if (ele) nbits = (Int_t)ele->GetXmin();
2372 Int_t i;
2373 if (!nbits) {
2374 //if no range and no bits specified, we convert from double to float
2375 for (i = 0; i < n; i++) {
2376 Float_t afloat = (Float_t)d[i];
2377 *this << afloat;
2378 }
2379 } else {
2380 //a range is not specified, but nbits is.
2381 //In this case we truncate the mantissa to nbits and we stream
2382 //the exponent as a UChar_t and the mantissa as a UShort_t.
2383 union {
2386 };
2387 for (i = 0; i < n; i++) {
2388 fFloatValue = (Float_t)d[i];
2389 UChar_t theExp = (UChar_t)(0x000000ff & ((fIntValue<<1)>>24));
2390 UShort_t theMan = ((1<<(nbits+1))-1) & (fIntValue>>(23-nbits-1));
2391 theMan++;
2392 theMan = theMan>>1;
2393 if(theMan&1<<nbits) theMan = (1<<nbits) - 1;
2394 if (fFloatValue < 0) theMan |= 1<<(nbits+1);
2395 *this << theExp;
2396 *this << theMan;
2397 }
2398 }
2399 }
2400}
2401
2402////////////////////////////////////////////////////////////////////////////////
2403/// Write an array of object starting at the address 'start' and of length 'n'
2404/// the objects in the array are assumed to be of class 'cl'
2405/// \note Due to the current limit of the buffer size, the function aborts execution of the program in case of underflow or overflow. See https://github.com/root-project/root/issues/6734 for more details.
2406
2407void TBufferFile::WriteFastArray(void *start, const TClass *cl, Long64_t n,
2409{
2410 if (streamer) {
2411 (*streamer)(*this, start, 0);
2412 return;
2413 }
2414
2415 char *obj = (char*)start;
2416 if (!n) n=1;
2417 else if (n < 0)
2418 {
2419 Fatal("WriteFastArray", "Negative number of elements %lld", n);
2420 return; // In case the user re-routes the error handler to not die when Fatal is called
2421 }
2422 int size = cl->Size();
2423
2424 for(Int_t j=0; j<n; j++,obj+=size) {
2425 ((TClass*)cl)->Streamer(obj,*this);
2426 }
2427}
2428
2429////////////////////////////////////////////////////////////////////////////////
2430/// Write an array of object starting at the address '*start' and of length 'n'
2431/// the objects in the array are of class 'cl'
2432/// 'isPreAlloc' indicates whether the data member is marked with '->'
2433/// Return:
2434/// - 0: success
2435/// - 2: truncated success (i.e actual class is missing. Only ptrClass saved.)
2436/// - -1: underflow, operation skipped
2437
2440{
2441 // if isPreAlloc is true (data member has a ->) we can assume that the pointer
2442 // is never 0.
2443
2444 if (streamer) {
2445 (*streamer)(*this,(void*)start,0);
2446 return 0;
2447 }
2448 if (n < 0) return -1;
2449 int strInfo = 0;
2450
2451 Int_t res = 0;
2452
2453 if (!isPreAlloc) {
2454
2455 for (Int_t j=0;j<n;j++) {
2456 //must write StreamerInfo if pointer is null
2457 if (!strInfo && !start[j]) {
2458 if (cl->Property() & kIsAbstract) {
2459 // Do not try to generate the StreamerInfo for an abstract class
2460 } else {
2461 TStreamerInfo *info = (TStreamerInfo*)((TClass*)cl)->GetStreamerInfo();
2463 }
2464 }
2465 strInfo = 2003;
2466 res |= WriteObjectAny(start[j],cl);
2467 }
2468
2469 } else {
2470 //case //-> in comment
2471
2472 for (Int_t j=0;j<n;j++) {
2473 if (!start[j]) start[j] = ((TClass*)cl)->New();
2474 ((TClass*)cl)->Streamer(start[j],*this);
2475 }
2476
2477 }
2478 return res;
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Read object from I/O buffer. clReq is NOT used.
2483///
2484/// The value returned is the address of the actual start in memory of
2485/// the object. Note that if the actual class of the object does not
2486/// inherit first from TObject, the type of the pointer is NOT 'TObject*'.
2487/// [More accurately, the class needs to start with the TObject part, for
2488/// the pointer to be a real TObject*].
2489/// We recommend using ReadObjectAny instead of ReadObject
2490
2492{
2493 return (TObject*) ReadObjectAny(nullptr);
2494}
2495
2496////////////////////////////////////////////////////////////////////////////////
2497/// Skip any kind of object from buffer
2498
2500{
2501 UInt_t start, count;
2502 ReadVersion(&start, &count);
2503 SetBufferOffset(start+count+sizeof(UInt_t));
2504}
2505
2506////////////////////////////////////////////////////////////////////////////////
2507/// Read object from I/O buffer.
2508///
2509/// A typical use for this function is:
2510///
2511/// MyClass *ptr = (MyClass*)b.ReadObjectAny(MyClass::Class());
2512///
2513/// I.e. clCast should point to a TClass object describing the class pointed
2514/// to by your pointer.
2515/// In case of multiple inheritance, the return value might not be the
2516/// real beginning of the object in memory. You will need to use a
2517/// dynamic_cast later if you need to retrieve it.
2518
2520{
2522
2523 // make sure fMap is initialized
2524 InitMap();
2525
2526 // before reading object save start position
2528
2529 // attempt to load next object as TClass clCast
2530 UInt_t tag; // either tag or byte count
2531 TClass *clRef = ReadClass(clCast, &tag);
2532 TClass *clOnfile = nullptr;
2533 Int_t baseOffset = 0;
2534 if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
2535 //baseOffset will be -1 if clRef does not inherit from clCast.
2536 baseOffset = clRef->GetBaseClassOffset(clCast);
2537 if (baseOffset == -1) {
2538 // The 2 classes are unrelated, maybe there is a converter between the 2.
2539
2540 if (!clCast->GetSchemaRules() ||
2541 !clCast->GetSchemaRules()->HasRuleWithSourceClass(clRef->GetName()))
2542 {
2543 // There is no converter
2544 Error("ReadObject", "got object of wrong class! requested %s but got %s",
2545 clCast->GetName(), clRef->GetName());
2546
2547 CheckByteCount(startpos, tag, (TClass *)nullptr); // avoid mis-leading byte count error message
2548 return 0; // We better return at this point
2549 }
2550 baseOffset = 0; // For now we do not support requesting from a class that is the base of one of the class for which there is transformation to ....
2551
2552 if (gDebug > 0)
2553 Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clRef->GetName(),clCast->GetName());
2554 clOnfile = clRef;
2555 clRef = const_cast<TClass*>(clCast);
2556
2557 }
2558 if (clCast->GetState() > TClass::kEmulated && clRef->GetState() <= TClass::kEmulated) {
2559 //we cannot mix a compiled class with an emulated class in the inheritance
2560 Error("ReadObject", "trying to read an emulated class (%s) to store in a compiled pointer (%s)",
2561 clRef->GetName(),clCast->GetName());
2562 CheckByteCount(startpos, tag, (TClass *)nullptr); // avoid mis-leading byte count error message
2563 return 0;
2564 }
2565 }
2566
2567 // check if object has not already been read
2568 // (this can only happen when called via CheckObject())
2569 char *obj;
2570 if (fVersion > 0) {
2571 obj = (char *) (Longptr_t)fMap->GetValue(startpos+kMapOffset);
2572 if (obj == (void*) -1) obj = nullptr;
2573 if (obj) {
2574 CheckByteCount(startpos, tag, (TClass *)nullptr);
2575 return (obj + baseOffset);
2576 }
2577 }
2578
2579 // unknown class, skip to next object and return 0 obj
2580 if (clRef == (TClass*) -1) {
2581 if (fBufCur >= fBufMax) return 0;
2582 if (fVersion > 0)
2584 else
2585 MapObject((void*)nullptr, nullptr, fMapCount);
2586 CheckByteCount(startpos, tag, (TClass *)nullptr);
2587 return 0;
2588 }
2589
2590 if (!clRef) {
2591
2592 // got a reference to an already read object
2593 if (fVersion > 0) {
2594 tag += fDisplacement;
2595 tag = CheckObject(tag, clCast);
2596 } else {
2597 if (tag > (UInt_t)fMap->GetSize()) {
2598 Error("ReadObject", "object tag too large, I/O buffer corrupted");
2599 return 0;
2600 // exception
2601 }
2602 }
2603 obj = (char *) (Longptr_t)fMap->GetValue(tag);
2605
2606 if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
2607 //baseOffset will be -1 if clRef does not inherit from clCast.
2608 baseOffset = clRef->GetBaseClassOffset(clCast);
2609 if (baseOffset == -1) {
2610 Error("ReadObject", "Got object of wrong class (Got %s while expecting %s)",
2611 clRef->GetName(),clCast->GetName());
2612 // exception
2613 baseOffset = 0;
2614 }
2615 }
2616
2617 // There used to be a warning printed here when:
2618 // obj && isTObject && !((TObject*)obj)->IsA()->InheritsFrom(clReq)
2619 // however isTObject was based on clReq (now clCast).
2620 // If the test was to fail, then it is as likely that the object is not a TObject
2621 // and then we have a potential core dump.
2622 // At this point (missing clRef), we do NOT have enough information to really
2623 // answer the question: is the object read of the type I requested.
2624
2625 } else {
2626
2627 // allocate a new object based on the class found
2628 obj = (char*)clRef->New();
2629 if (!obj) {
2630 Error("ReadObject", "could not create object of class %s",
2631 clRef->GetName());
2632 // exception
2633 return 0;
2634 }
2635
2636 // add to fMap before reading rest of object
2637 if (fVersion > 0)
2639 else
2640 MapObject(obj, clRef, fMapCount);
2641
2642 // let the object read itself
2643 clRef->Streamer( obj, *this, clOnfile );
2644
2646 }
2647
2648 return obj+baseOffset;
2649}
2650
2651////////////////////////////////////////////////////////////////////////////////
2652/// Write object to I/O buffer.
2653/// This function assumes that the value of 'actualObjectStart' is the actual start of
2654/// the object of class 'actualClass'
2655/// If 'cacheReuse' is true (default) upon seeing an object address a second time,
2656/// we record the offset where its was written the first time rather than streaming
2657/// the object a second time.
2658/// If 'cacheReuse' is false, we always stream the object. This allows the (re)use
2659/// of temporary object to store different data in the same buffer.
2660
2662{
2664
2665 if (!actualObjectStart) {
2666
2667 // save kNullTag to represent nullptr pointer
2668 *this << (UInt_t) kNullTag;
2669
2670 } else {
2671
2672 // make sure fMap is initialized
2673 InitMap();
2674
2675 ULongptr_t idx;
2676 UInt_t slot;
2678
2679 if ((idx = (ULongptr_t)fMap->GetValue(hash, (Longptr_t)actualObjectStart, slot)) != 0) {
2680
2681 // truncation is OK the value we did put in the map is an 30-bit offset
2682 // and not a pointer
2683 UInt_t objIdx = UInt_t(idx);
2684
2685 // save index of already stored object
2686 *this << objIdx;
2687
2688 } else {
2689
2690 // A warning to let the user know it will need to change the class code
2691 // to be able to read this back.
2692 if (!actualClass->HasDefaultConstructor(kTRUE)) {
2693 Warning("WriteObjectAny", "since %s has no public constructor\n"
2694 "\twhich can be called without argument, objects of this class\n"
2695 "\tcan not be read with the current library. You will need to\n"
2696 "\tadd a default constructor before attempting to read it.",
2697 actualClass->GetName());
2698 }
2699
2700 // reserve space for leading byte count
2702 fBufCur += sizeof(UInt_t);
2703
2704 // write class of object first
2705 Int_t mapsize = fMap->Capacity(); // The slot depends on the capacity and WriteClass might induce an increase.
2707
2708 if (cacheReuse) {
2709 // add to map before writing rest of object (to handle self reference)
2710 // (+kMapOffset so it's != kNullTag)
2711 //MapObject(actualObjectStart, actualClass, cntpos+kMapOffset);
2713 if (mapsize == fMap->Capacity()) {
2715 } else {
2716 // The slot depends on the capacity and WriteClass has induced an increase.
2718 }
2719 // No need to keep track of the class in write mode
2720 // fClassMap->Add(hash, (Long_t)obj, (Long_t)((TObject*)obj)->IsA());
2721 fMapCount++;
2722 }
2723
2724 ((TClass*)actualClass)->Streamer((void*)actualObjectStart,*this);
2725
2726 // write byte count
2728 }
2729 }
2730}
2731
2732////////////////////////////////////////////////////////////////////////////////
2733/// Read class definition from I/O buffer.
2734///
2735/// \param[in] clReq Can be used to cross check if the actually read object is of the requested class.
2736/// \param[in] objTag Set in case the object is a reference to an already read object.
2737
2739{
2741
2742 // read byte count and/or tag (older files don't have byte count)
2743 TClass *cl;
2745 fBufCur = fBufMax;
2746 cl = (TClass*)-1;
2747 return cl;
2748 }
2749 UInt_t bcnt, tag, startpos = 0;
2750 *this >> bcnt;
2751 if (!(bcnt & kByteCountMask) || bcnt == kNewClassTag) {
2752 tag = bcnt;
2753 bcnt = 0;
2754 } else {
2755 fVersion = 1;
2757 *this >> tag;
2758 }
2759
2760 // in case tag is object tag return tag
2761 if (!(tag & kClassMask)) {
2762 if (objTag) *objTag = tag;
2763 return 0;
2764 }
2765
2766 if (tag == kNewClassTag) {
2767
2768 // got a new class description followed by a new object
2769 // (class can be 0 if class dictionary is not found, in that
2770 // case object of this class must be skipped)
2771 cl = TClass::Load(*this);
2772
2773 // add class to fMap for later reference
2774 if (fVersion > 0) {
2775 // check if class was already read
2777 if (cl1 != cl)
2778 MapObject(cl ? cl : (TObject*) -1, startpos+kMapOffset);
2779 } else
2780 MapObject(cl, fMapCount);
2781
2782 } else {
2783
2784 // got a tag to an already seen class
2785 UInt_t clTag = (tag & ~kClassMask);
2786
2787 if (fVersion > 0) {
2790 } else {
2791 if (clTag == 0 || clTag > (UInt_t)fMap->GetSize()) {
2792 Error("ReadClass", "illegal class tag=%d (0<tag<=%d), I/O buffer corrupted",
2793 clTag, fMap->GetSize());
2794 // exception
2795 }
2796 }
2797
2798 // class can be 0 if dictionary was not found
2799 cl = (TClass *)(Longptr_t)fMap->GetValue(clTag);
2800 }
2801
2802 if (cl && clReq &&
2803 (!cl->InheritsFrom(clReq) &&
2804 !(clReq->GetSchemaRules() &&
2805 clReq->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()) )
2806 ) ) {
2807 Error("ReadClass", "The on-file class is \"%s\" which is not compatible with the requested class: \"%s\"",
2808 cl->GetName(), clReq->GetName());
2809 // exception
2810 }
2811
2812 // return bytecount in objTag
2813 if (objTag) *objTag = (bcnt & ~kByteCountMask);
2814
2815 // case of unknown class
2816 if (!cl) cl = (TClass*)-1;
2817
2818 return cl;
2819}
2820
2821////////////////////////////////////////////////////////////////////////////////
2822/// Write class description to I/O buffer.
2823
2825{
2827
2828 ULongptr_t idx;
2829 ULong_t hash = Void_Hash(cl);
2830 UInt_t slot;
2831
2832 if ((idx = (ULongptr_t)fMap->GetValue(hash, (Longptr_t)cl,slot)) != 0) {
2833
2834 // truncation is OK the value we did put in the map is an 30-bit offset
2835 // and not a pointer
2836 UInt_t clIdx = UInt_t(idx);
2837
2838 // save index of already stored class
2839 *this << (clIdx | kClassMask);
2840
2841 } else {
2842
2843 // offset in buffer where class info is written
2845
2846 // save new class tag
2847 *this << kNewClassTag;
2848
2849 // write class name
2850 cl->Store(*this);
2851
2852 // store new class reference in fMap (+kMapOffset so it's != kNullTag)
2855 fMapCount++;
2856 }
2857}
2858
2859////////////////////////////////////////////////////////////////////////////////
2860/// Skip class version from I/O buffer.
2861
2863{
2865
2866 // not interested in byte count
2867 frombuf(this->fBufCur,&version);
2868
2869 // if this is a byte count, then skip next short and read version
2870 if (version & kByteCountVMask) {
2871 frombuf(this->fBufCur,&version);
2872 frombuf(this->fBufCur,&version);
2873 }
2874
2875 if (cl && cl->GetClassVersion() != 0 && version<=1) {
2876 if (version <= 0) {
2877 UInt_t checksum = 0;
2878 //*this >> checksum;
2879 frombuf(this->fBufCur,&checksum);
2881 if (vinfo) {
2882 return;
2883 } else {
2884 // There are some cases (for example when the buffer was stored outside of
2885 // a ROOT file) where we do not have a TStreamerInfo. If the checksum is
2886 // the one from the current class, we can still assume that we can read
2887 // the data so let use it.
2888 if (checksum==cl->GetCheckSum() || cl->MatchLegacyCheckSum(checksum)) {
2889 version = cl->GetClassVersion();
2890 } else {
2891 if (fParent) {
2892 Error("SkipVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
2893 checksum, cl->GetName(), ((TFile*)fParent)->GetName());
2894 } else {
2895 Error("SkipVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" (buffer with no parent)",
2896 checksum, cl->GetName());
2897 }
2898 return;
2899 }
2900 }
2901 } else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 ) {
2902 // We could have a file created using a Foreign class before
2903 // the introduction of the CheckSum. We need to check
2904 if ((!cl->IsLoaded() || cl->IsForeign()) &&
2906
2907 const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
2908 const TStreamerInfo *local = list ? (TStreamerInfo*)list->FindObject(cl->GetName()) : 0;
2909 if ( local ) {
2910 UInt_t checksum = local->GetCheckSum();
2912 if (vinfo) {
2913 version = vinfo->GetClassVersion();
2914 } else {
2915 Error("SkipVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
2916 checksum, cl->GetName(), ((TFile*)fParent)->GetName());
2917 return;
2918 }
2919 }
2920 else {
2921 Error("SkipVersion", "Class %s not known to file %s.",
2922 cl->GetName(), ((TFile*)fParent)->GetName());
2923 version = 0;
2924 }
2925 }
2926 }
2927 }
2928}
2929
2930////////////////////////////////////////////////////////////////////////////////
2931/// Read class version from I/O buffer.
2932
2934{
2936
2937 if (startpos) {
2938 // before reading object save start position
2940 }
2941
2942 // read byte count (older files don't have byte count)
2943 // byte count is packed in two individual shorts, this to be
2944 // backward compatible with old files that have at this location
2945 // only a single short (i.e. the version)
2946 union {
2947 UInt_t cnt;
2948 Version_t vers[2];
2949 } v;
2950#ifdef R__BYTESWAP
2951 frombuf(this->fBufCur,&v.vers[1]);
2952 frombuf(this->fBufCur,&v.vers[0]);
2953#else
2954 frombuf(this->fBufCur,&v.vers[0]);
2955 frombuf(this->fBufCur,&v.vers[1]);
2956#endif
2957
2958 // no bytecount, backup and read version
2959 if (!(v.cnt & kByteCountMask)) {
2960 fBufCur -= sizeof(UInt_t);
2961 v.cnt = 0;
2962 }
2963 if (bcnt) *bcnt = (v.cnt & ~kByteCountMask);
2964 frombuf(this->fBufCur,&version);
2965
2966 if (version<=1) {
2967 if (version <= 0) {
2968 if (cl) {
2969 auto clversion = cl->GetClassVersion();
2970 if ((clversion != 0
2971 // If v.cnt < 6 then we have a class with a version that used to be zero and so there is no checksum.
2972 && (v.cnt && v.cnt >= 6)) ||
2973 // ::WriteVersion for a foreign class (no ClassDef) but defining Class_Version() { return 0; } does write checksum.
2974 (clversion == 0 && version == 0 && cl->IsForeign())
2975 ) {
2976 UInt_t checksum = 0;
2977 //*this >> checksum;
2978 frombuf(this->fBufCur,&checksum);
2980 if (vinfo) {
2981 return vinfo->TStreamerInfo::GetClassVersion(); // Try to get inlining.
2982 } else {
2983 // There are some cases (for example when the buffer was stored outside of
2984 // a ROOT file) where we do not have a TStreamerInfo. If the checksum is
2985 // the one from the current class, we can still assume that we can read
2986 // the data so let use it.
2987 if (checksum==cl->GetCheckSum() || cl->MatchLegacyCheckSum(checksum)) {
2989 } else {
2990 if (fParent) {
2991 Error("ReadVersion", "Could not find the StreamerInfo with a checksum of 0x%x for the class \"%s\" in %s.",
2992 checksum, cl->GetName(), ((TFile*)fParent)->GetName());
2993 } else {
2994 Error("ReadVersion", "Could not find the StreamerInfo with a checksum of 0x%x for the class \"%s\" (buffer with no parent)",
2995 checksum, cl->GetName());
2996 }
2997 return 0;
2998 }
2999 }
3000 }
3001 } else { // of if (cl) {
3002 UInt_t checksum = 0;
3003 //*this >> checksum;
3004 // If *bcnt < 6 then we have a class with 'just' version zero and no checksum
3005 if (v.cnt && v.cnt >= 6)
3006 frombuf(this->fBufCur,&checksum);
3007 }
3008 } else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 && cl && cl->GetClassVersion() != 0) {
3009 // We could have a file created using a Foreign class before
3010 // the introduction of the CheckSum. We need to check
3011 if ((!cl->IsLoaded() || cl->IsForeign()) &&
3013
3014 const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
3015 const TStreamerInfo *local = list ? (TStreamerInfo*)list->FindObject(cl->GetName()) : 0;
3016 if ( local ) {
3017 UInt_t checksum = local->GetCheckSum();
3019 if (vinfo) {
3020 version = vinfo->GetClassVersion();
3021 } else {
3022 Error("ReadVersion", "Could not find the StreamerInfo with a checksum of 0x%x for the class \"%s\" in %s.",
3023 checksum, cl->GetName(), ((TFile*)fParent)->GetName());
3024 return 0;
3025 }
3026 }
3027 else {
3028 Error("ReadVersion", "Class %s not known to file %s.",
3029 cl->GetName(), ((TFile*)fParent)->GetName());
3030 version = 0;
3031 }
3032 }
3033 }
3034 }
3035 return version;
3036}
3037
3038////////////////////////////////////////////////////////////////////////////////
3039/// Read class version from I/O buffer, when the caller knows for sure that
3040/// there is no checksum written/involved.
3041
3043{
3045
3046 if (startpos) {
3047 // before reading object save start position
3049 }
3050
3051 // read byte count (older files don't have byte count)
3052 // byte count is packed in two individual shorts, this to be
3053 // backward compatible with old files that have at this location
3054 // only a single short (i.e. the version)
3055 union {
3056 UInt_t cnt;
3057 Version_t vers[2];
3058 } v;
3059#ifdef R__BYTESWAP
3060 frombuf(this->fBufCur,&v.vers[1]);
3061 frombuf(this->fBufCur,&v.vers[0]);
3062#else
3063 frombuf(this->fBufCur,&v.vers[0]);
3064 frombuf(this->fBufCur,&v.vers[1]);
3065#endif
3066
3067 // no bytecount, backup and read version
3068 if (!(v.cnt & kByteCountMask)) {
3069 fBufCur -= sizeof(UInt_t);
3070 v.cnt = 0;
3071 }
3072 if (bcnt) *bcnt = (v.cnt & ~kByteCountMask);
3073 frombuf(this->fBufCur,&version);
3074
3075 return version;
3076}
3077
3078////////////////////////////////////////////////////////////////////////////////
3079/// Read class version from I/O buffer
3080///
3081/// To be used when streaming out member-wise streamed collection where we do not
3082/// care (not save) about the byte count and can safely ignore missing streamerInfo
3083/// (since they usually indicate empty collections).
3084
3086{
3088
3089 // not interested in byte count
3090 frombuf(this->fBufCur,&version);
3091
3092 if (version<=1) {
3093 if (version <= 0) {
3094 if (cl) {
3095 if (cl->GetClassVersion() != 0) {
3096 UInt_t checksum = 0;
3097 frombuf(this->fBufCur,&checksum);
3099 if (vinfo) {
3100 return vinfo->TStreamerInfo::GetClassVersion(); // Try to get inlining.
3101 } else {
3102 // There are some cases (for example when the buffer was stored outside of
3103 // a ROOT file) where we do not have a TStreamerInfo. If the checksum is
3104 // the one from the current class, we can still assume that we can read
3105 // the data so let use it.
3106 if (checksum==cl->GetCheckSum() || cl->MatchLegacyCheckSum(checksum)) {
3107 version = cl->GetClassVersion();
3108 } else {
3109 // If we can not find the streamerInfo this means that
3110 // we do not actually need it (the collection is always empty
3111 // in this file), so no need to issue a warning.
3112 return 0;
3113 }
3114 }
3115 }
3116 } else { // of if (cl) {
3117 UInt_t checksum = 0;
3118 frombuf(this->fBufCur,&checksum);
3119 }
3120 } else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 && cl && cl->GetClassVersion() != 0) {
3121 // We could have a file created using a Foreign class before
3122 // the introduction of the CheckSum. We need to check
3123 if ((!cl->IsLoaded() || cl->IsForeign()) && Class_Has_StreamerInfo(cl) ) {
3124
3125 const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
3126 const TStreamerInfo *local = list ? (TStreamerInfo*)list->FindObject(cl->GetName()) : 0;
3127 if ( local ) {
3128 UInt_t checksum = local->GetCheckSum();
3130 if (vinfo) {
3131 version = vinfo->GetClassVersion();
3132 } else {
3133 // If we can not find the streamerInfo this means that
3134 // we do not actually need it (the collection is always empty
3135 // in this file), so no need to issue a warning.
3136 return 0;
3137 }
3138 }
3139 else {
3140 Error("ReadVersion", "Class %s not known to file %s.",
3141 cl->GetName(), ((TFile*)fParent)->GetName());
3142 version = 0;
3143 }
3144 }
3145 }
3146 }
3147 return version;
3148}
3149
3150////////////////////////////////////////////////////////////////////////////////
3151/// Write class version to I/O buffer.
3152
3154{
3155 UInt_t cntpos = 0;
3156 if (useBcnt) {
3157 // reserve space for leading byte count
3159 fBufCur += sizeof(UInt_t);
3160 }
3161
3163 if (version<=1 && cl->IsForeign()) {
3164 *this << Version_t(0);
3165 *this << cl->GetCheckSum();
3166 } else {
3167 if (version > kMaxVersion) {
3168 Error("WriteVersion", "version number cannot be larger than %hd)",
3169 kMaxVersion);
3171 }
3172 *this <<version;
3173 }
3174
3175 // return position where to store possible byte count
3176 return cntpos;
3177}
3178
3179////////////////////////////////////////////////////////////////////////////////
3180/// Write class version to I/O buffer after setting the kStreamedMemberWise
3181/// bit in the version number.
3182
3184{
3185 UInt_t cntpos = 0;
3186 if (useBcnt) {
3187 // reserve space for leading byte count
3189 fBufCur += sizeof(UInt_t);
3190 }
3191
3193 if (version<=1 && cl->IsForeign()) {
3194 Error("WriteVersionMemberWise", "Member-wise streaming of foreign collection not yet implemented!");
3195 *this << Version_t(0);
3196 *this << cl->GetCheckSum();
3197 } else {
3198 if (version > kMaxVersion) {
3199 Error("WriteVersionMemberWise", "version number cannot be larger than %hd)",
3200 kMaxVersion);
3202 }
3204 *this <<version;
3205 }
3206
3207 // return position where to store possible byte count
3208 return cntpos;
3209}
3210
3211////////////////////////////////////////////////////////////////////////////////
3212/// Stream an object given its C++ typeinfo information.
3213
3214void TBufferFile::StreamObject(void *obj, const std::type_info &typeinfo, const TClass* onFileClass )
3215{
3217 if (cl) cl->Streamer(obj, *this, (TClass*)onFileClass );
3218 else Warning("StreamObject","No TClass for the type %s is available, the object was not read.", typeinfo.name());
3219}
3220
3221////////////////////////////////////////////////////////////////////////////////
3222/// Stream an object given the name of its actual class.
3223
3224void TBufferFile::StreamObject(void *obj, const char *className, const TClass* onFileClass)
3225{
3226 TClass *cl = TClass::GetClass(className);
3227 if (cl) cl->Streamer(obj, *this, (TClass*)onFileClass );
3228 else Warning("StreamObject","No TClass for the type %s is available, the object was not read.", className);
3229}
3230
3231////////////////////////////////////////////////////////////////////////////////
3232/// Stream an object given a pointer to its actual class.
3233
3234void TBufferFile::StreamObject(void *obj, const TClass *cl, const TClass* onFileClass )
3235{
3236 ((TClass*)cl)->Streamer(obj, *this, (TClass*)onFileClass );
3237}
3238
3239////////////////////////////////////////////////////////////////////////////////
3240/// Stream an object inheriting from TObject using its streamer.
3241
3243{
3244 obj->Streamer(*this);
3245}
3246
3247////////////////////////////////////////////////////////////////////////////////
3248/// Check if offset is not too large (< kMaxMapCount) when writing.
3249
3251{
3252 if (IsWriting()) {
3253 if (offset >= kMaxMapCount) {
3254 Error("CheckCount", "buffer offset too large (larger than %d)", kMaxMapCount);
3255 // exception
3256 }
3257 }
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// Check for object in the read map. If the object is 0 it still has to be
3262/// read. Try to read it from the buffer starting at location offset. If the
3263/// object is -1 then it really does not exist and we return 0. If the object
3264/// exists just return the offset.
3265
3267{
3268 // in position 0 we always have the reference to the null object
3269 if (!offset) return offset;
3270
3271 Longptr_t cli;
3272
3273 if (readClass) {
3274 if ((cli = fMap->GetValue(offset)) == 0) {
3275 // No class found at this location in map. It might have been skipped
3276 // as part of a skipped object. Try to explicitly read the class.
3277
3278 // save fBufCur and set to place specified by offset (-kMapOffset-sizeof(bytecount))
3279 char *bufsav = fBufCur;
3280 fBufCur = (char *)(fBuffer + offset-kMapOffset-sizeof(UInt_t));
3281
3282 TClass *c = ReadClass(cl);
3283 if (c == (TClass*) -1) {
3284 // mark class as really not available
3285 fMap->Remove(offset);
3286 fMap->Add(offset, -1);
3287 offset = 0;
3288 if (cl)
3289 Warning("CheckObject", "reference to unavailable class %s,"
3290 " pointers of this type will be 0", cl->GetName());
3291 else
3292 Warning("CheckObject", "reference to an unavailable class,"
3293 " pointers of that type will be 0");
3294 }
3295
3296 fBufCur = bufsav;
3297
3298 } else if (cli == -1) {
3299
3300 // class really does not exist
3301 return 0;
3302 }
3303
3304 } else {
3305
3306 if ((cli = fMap->GetValue(offset)) == 0) {
3307 // No object found at this location in map. It might have been skipped
3308 // as part of a skipped object. Try to explicitly read the object.
3309
3310 // save fBufCur and set to place specified by offset (-kMapOffset)
3311 char *bufsav = fBufCur;
3312 fBufCur = (char *)(fBuffer + offset-kMapOffset);
3313
3314 TObject *obj = ReadObject(cl);
3315 if (!obj) {
3316 // mark object as really not available
3317 fMap->Remove(offset);
3318 fMap->Add(offset, -1);
3319 Warning("CheckObject", "reference to object of unavailable class %s, offset=%d"
3320 " pointer will be 0", cl ? cl->GetName() : "TObject",offset);
3321 offset = 0;
3322 }
3323
3324 fBufCur = bufsav;
3325
3326 } else if (cli == -1) {
3327
3328 // object really does not exist
3329 return 0;
3330 }
3331
3332 }
3333
3334 return offset;
3335}
3336
3337
3338////////////////////////////////////////////////////////////////////////////////
3339/// Read max bytes from the I/O buffer into buf. The function returns
3340/// the actual number of bytes read.
3341
3343{
3345
3346 if (max == 0) return 0;
3347
3348 Int_t n = std::min(max, (Int_t)(fBufMax - fBufCur));
3349
3350 memcpy(buf, fBufCur, n);
3351 fBufCur += n;
3352
3353 return n;
3354}
3355
3356////////////////////////////////////////////////////////////////////////////////
3357/// Write max bytes from buf into the I/O buffer.
3358
3359void TBufferFile::WriteBuf(const void *buf, Int_t max)
3360{
3362
3363 if (max == 0) return;
3364
3365 if (fBufCur + max > fBufMax) AutoExpand(fBufSize+max); // a more precise request would be: fBufSize + max - (fBufMax - fBufCur)
3366
3367 memcpy(fBufCur, buf, max);
3368 fBufCur += max;
3369}
3370
3371////////////////////////////////////////////////////////////////////////////////
3372/// Read string from I/O buffer. String is read till 0 character is
3373/// found or till max-1 characters are read (i.e. string s has max
3374/// bytes allocated). If max = -1 no check on number of character is
3375/// made, reading continues till 0 character is found.
3376
3378{
3380
3381 char ch;
3382 Int_t nr = 0;
3383
3384 if (max == -1) max = kMaxInt;
3385
3386 while (nr < max-1) {
3387
3388 *this >> ch;
3389
3390 // stop when 0 read
3391 if (ch == 0) break;
3392
3393 s[nr++] = ch;
3394 }
3395
3396 s[nr] = 0;
3397 return s;
3398}
3399
3400////////////////////////////////////////////////////////////////////////////////
3401/// Write string to I/O buffer. Writes string upto and including the
3402/// terminating 0.
3403
3404void TBufferFile::WriteString(const char *s)
3405{
3406 WriteBuf(s, (strlen(s)+1)*sizeof(char));
3407}
3408
3409////////////////////////////////////////////////////////////////////////////////
3410/// Read emulated class.
3411
3413{
3414 UInt_t start,count;
3415 //We assume that the class was written with a standard streamer
3416 //We attempt to recover if a version count was not written
3417 Version_t v = ReadVersion(&start,&count);
3418
3419 TStreamerInfo *sinfo = nullptr;
3420 if (onFileClass) {
3422 if (!sinfo)
3423 return 0;
3424 }
3425 if (!sinfo)
3427
3428 if (count) {
3429 ApplySequence(*(sinfo->GetReadObjectWiseActions()), object);
3430 if (sinfo->IsRecovered()) count=0;
3431 CheckByteCount(start,count,cl);
3432 } else {
3433 SetBufferOffset(start);
3434 ApplySequence(*(sinfo->GetReadObjectWiseActions()), object);
3435 }
3436 return 0;
3437}
3438
3439////////////////////////////////////////////////////////////////////////////////
3440/// Deserialize information from a buffer into an object.
3441///
3442/// Note: This function is called by the xxx::Streamer() functions in
3443/// rootcling-generated dictionaries.
3444/// This function assumes that the class version and the byte count
3445/// information have been read.
3446///
3447/// \param[in] cl pointer to the local TClass
3448/// \param[out] pointer void pointer to object
3449/// \param[in] version The version number of the class
3450/// \param[in] start The starting position in the buffer b
3451/// \param[in] count The number of bytes for this object in the buffer
3452/// \param[in] onFileClass pointer to TClass object on file
3453///
3454
3455Int_t TBufferFile::ReadClassBuffer(const TClass *cl, void *pointer, Int_t version, UInt_t start, UInt_t count, const TClass *onFileClass)
3456{
3457
3458 //---------------------------------------------------------------------------
3459 // The ondisk class has been specified so get foreign streamer info
3460 /////////////////////////////////////////////////////////////////////////////
3461
3462 TStreamerInfo *sinfo = nullptr;
3463 if( onFileClass ) {
3465 if( !sinfo ) {
3466 Error("ReadClassBuffer",
3467 "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d",
3468 onFileClass->GetName(), version, cl->GetName(), Length() );
3469 CheckByteCount(start, count, onFileClass);
3470 return 0;
3471 }
3472 }
3473 //---------------------------------------------------------------------------
3474 // Get local streamer info
3475 /////////////////////////////////////////////////////////////////////////////
3476 /// The StreamerInfo should exist at this point.
3477
3478 else {
3480 auto infos = cl->GetStreamerInfos();
3481 auto ninfos = infos->GetSize();
3483 Error("ReadClassBuffer", "class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
3484 cl->GetName(), version, Length() );
3485 CheckByteCount(start, count, cl);
3486 return 0;
3487 }
3489 if (sinfo == nullptr) {
3490 // Unless the data is coming via a socket connection from with schema evolution
3491 // (tracking) was not enabled. So let's create the StreamerInfo if it is the
3492 // one for the current version, otherwise let's complain ...
3493 // We could also get here if there old class version was '1' and the new class version is higher than 1
3494 // AND the checksum is the same.
3496 // check if another thread took care of this already
3498 if (sinfo == nullptr) {
3499 if ( version == cl->GetClassVersion() || version == 1 ) {
3500 const_cast<TClass*>(cl)->BuildRealData(pointer);
3501 // This creation is alright since we just checked within the
3502 // current 'locked' section.
3503 sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
3504 const_cast<TClass*>(cl)->RegisterStreamerInfo(sinfo);
3505 if (gDebug > 0) Info("ReadClassBuffer", "Creating StreamerInfo for class: %s, version: %d", cl->GetName(), version);
3506 sinfo->Build();
3507 } else if (version==0) {
3508 // When the object was written the class was version zero, so
3509 // there is no StreamerInfo to be found.
3510 // Check that the buffer position corresponds to the byte count.
3511 CheckByteCount(start, count, cl);
3512 return 0;
3513 } else {
3514 Error("ReadClassBuffer", "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
3515 version, cl->GetName(), Length() );
3516 CheckByteCount(start, count, cl);
3517 return 0;
3518 }
3519 }
3520 } else if (!sinfo->IsCompiled()) { // Note this read is protected by the above lock.
3521 // Streamer info has not been compiled, but exists.
3522 // Therefore it was read in from a file and we have to do schema evolution.
3524 // check if another thread took care of this already
3525 if (!sinfo->IsCompiled()) {
3526 const_cast<TClass*>(cl)->BuildRealData(pointer);
3527 sinfo->BuildOld();
3528 }
3529 }
3530 }
3531
3532 // Deserialize the object.
3533 ApplySequence(*(sinfo->GetReadObjectWiseActions()), (char*)pointer);
3534 if (sinfo->IsRecovered()) count=0;
3535
3536 // Check that the buffer position corresponds to the byte count.
3537 CheckByteCount(start, count, cl);
3538 return 0;
3539}
3540
3541////////////////////////////////////////////////////////////////////////////////
3542/// Deserialize information from a buffer into an object.
3543///
3544/// Note: This function is called by the xxx::Streamer()
3545/// functions in rootcling-generated dictionaries.
3546///
3547
3549{
3550 // Read the class version from the buffer.
3551 UInt_t R__s = 0; // Start of object.
3552 UInt_t R__c = 0; // Count of bytes.
3554
3555 if( onFileClass )
3557 else
3558 version = ReadVersion(&R__s, &R__c, cl);
3559
3561 TFile *file = (TFile*)GetParent();
3562 if (file && file->GetVersion() < 30000) {
3563 version = -1; //This is old file
3564 v2file = kTRUE;
3565 }
3566
3567 //---------------------------------------------------------------------------
3568 // The ondisk class has been specified so get foreign streamer info
3569 /////////////////////////////////////////////////////////////////////////////
3570
3571 TStreamerInfo *sinfo = nullptr;
3572 if( onFileClass ) {
3574 if( !sinfo ) {
3575 Error("ReadClassBuffer",
3576 "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d",
3577 onFileClass->GetName(), version, cl->GetName(), Length() );
3579 return 0;
3580 }
3581 }
3582 //---------------------------------------------------------------------------
3583 // Get local streamer info
3584 /////////////////////////////////////////////////////////////////////////////
3585 /// The StreamerInfo should exist at this point.
3586
3587 else {
3589 if (guess && guess->GetClassVersion() == version) {
3590 sinfo = guess;
3591 } else {
3592 // The last one is not the one we are looking for.
3593 {
3595
3596 const TObjArray *infos = cl->GetStreamerInfos();
3597 Int_t infocapacity = infos->Capacity();
3598 if (infocapacity) {
3600 Error("ReadClassBuffer","class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
3601 cl->GetName(), version, Length());
3602 CheckByteCount(R__s, R__c, cl);
3603 return 0;
3604 }
3605 sinfo = (TStreamerInfo*) infos->UncheckedAt(version);
3606 if (sinfo) {
3607 if (!sinfo->IsCompiled())
3608 {
3609 // Streamer info has not been compiled, but exists.
3610 // Therefore it was read in from a file and we have to do schema evolution?
3612 const_cast<TClass*>(cl)->BuildRealData(pointer);
3613 sinfo->BuildOld();
3614 }
3615 // If the compilation succeeded, remember this StreamerInfo.
3616 // const_cast okay because of the lock on gInterpreterMutex.
3617 if (sinfo->IsCompiled()) const_cast<TClass*>(cl)->SetLastReadInfo(sinfo);
3618 }
3619 }
3620 }
3621
3622 if (sinfo == nullptr) {
3623 // Unless the data is coming via a socket connection from with schema evolution
3624 // (tracking) was not enabled. So let's create the StreamerInfo if it is the
3625 // one for the current version, otherwise let's complain ...
3626 // We could also get here when reading a file prior to the introduction of StreamerInfo.
3627 // We could also get here if the old class version was '1' and the new class version is higher than 1
3628 // We could also get here if the stored-in-file class version was '3' and the current-in-memory class version is not defined
3629 // AND the checksum is the same.
3630 if (v2file || version == cl->GetClassVersion() || version == 1 || (version > 0 && cl->GetClassVersion() == -1) ) {
3632
3633 // We need to check if another thread did not get here first
3634 // and did the StreamerInfo creation already.
3635 auto infos = cl->GetStreamerInfos();
3636 auto ninfos = infos->GetSize();
3638 sinfo = (TStreamerInfo *) infos->At(version);
3639 }
3640 if (!sinfo) {
3641 const_cast<TClass *>(cl)->BuildRealData(pointer);
3642 sinfo = new TStreamerInfo(const_cast<TClass *>(cl));
3643 sinfo->SetClassVersion(version);
3644 const_cast<TClass *>(cl)->RegisterStreamerInfo(sinfo);
3645 if (gDebug > 0)
3646 Info("ReadClassBuffer", "Creating StreamerInfo for class: %s, version: %d",
3647 cl->GetName(), version);
3648 if (v2file) {
3649 sinfo->Build(); // Get the elements.
3650 sinfo->Clear("build"); // Undo compilation.
3651 sinfo->BuildEmulated(file); // Fix the types and redo compilation.
3652 } else {
3653 sinfo->Build();
3654 }
3655 }
3656 } else if (version==0) {
3657 // When the object was written the class was version zero, so
3658 // there is no StreamerInfo to be found.
3659 // Check that the buffer position corresponds to the byte count.
3660 CheckByteCount(R__s, R__c, cl);
3661 return 0;
3662 } else {
3663 Error( "ReadClassBuffer", "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
3664 version, cl->GetName(), Length() );
3665 CheckByteCount(R__s, R__c, cl);
3666 return 0;
3667 }
3668 }
3669 }
3670 }
3671
3672 //deserialize the object
3673 ApplySequence(*(sinfo->GetReadObjectWiseActions()), (char*)pointer );
3674 if (sinfo->TStreamerInfo::IsRecovered()) R__c=0; // 'TStreamerInfo::' avoids going via a virtual function.
3675
3676 // Check that the buffer position corresponds to the byte count.
3677 CheckByteCount(R__s, R__c, cl);
3678
3679 if (gDebug > 2) Info("ReadClassBuffer", "For class: %s has read %d bytes", cl->GetName(), R__c);
3680
3681 return 0;
3682}
3683
3684////////////////////////////////////////////////////////////////////////////////
3685/// Function called by the Streamer functions to serialize object at p
3686/// to buffer b. The optional argument info may be specified to give an
3687/// alternative StreamerInfo instead of using the default StreamerInfo
3688/// automatically built from the class definition.
3689/// For more information, see class TStreamerInfo.
3690
3692{
3693 //build the StreamerInfo if first time for the class
3695 if (sinfo == nullptr) {
3696 //Have to be sure between the check and the taking of the lock if the current streamer has changed
3698 sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetCurrentStreamerInfo();
3699 if (sinfo == nullptr)
3700 sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetStreamerInfo();
3701 if (sinfo == nullptr) {
3702 const_cast<TClass*>(cl)->BuildRealData(pointer);
3703 sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
3704 const_cast<TClass*>(cl)->SetCurrentStreamerInfo(sinfo);
3705 const_cast<TClass*>(cl)->RegisterStreamerInfo(sinfo);
3706 if (gDebug > 0) Info("WritedClassBuffer", "Creating StreamerInfo for class: %s, version: %d",cl->GetName(),cl->GetClassVersion());
3707 sinfo->Build();
3708 }
3709 } else if (!sinfo->IsCompiled()) {
3711 // Redo the test in case we have been victim of a data race on fIsCompiled.
3712 if (!sinfo->IsCompiled()) {
3713 const_cast<TClass*>(cl)->BuildRealData(pointer);
3714 sinfo->BuildOld();
3715 }
3716 }
3717
3718 //write the class version number and reserve space for the byte count
3720
3721 //NOTE: In the future Philippe wants this to happen via a custom action
3723 ApplySequence(*(sinfo->GetWriteObjectWiseActions()), (char*)pointer);
3724
3725 //write the byte count at the start of the buffer
3727
3728 if (gDebug > 2) Info("WritedClassBuffer", "For class: %s version %d has written %d bytes",cl->GetName(),cl->GetClassVersion(),UInt_t(fBufCur - fBuffer) - R__c - (UInt_t)sizeof(UInt_t));
3729 return 0;
3730}
3731
3732////////////////////////////////////////////////////////////////////////////////
3733/// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3734/// The collection needs to be a split TClonesArray or a split vector of pointers.
3735
3737{
3738 if (gDebug) {
3739 //loop on all active members
3740 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3741 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3742 iter != end;
3743 ++iter) {
3744 (*iter).PrintDebug(*this,obj);
3745 (*iter)(*this,obj);
3746 }
3747
3748 } else {
3749 //loop on all active members
3750 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3751 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3752 iter != end;
3753 ++iter) {
3754 (*iter)(*this,obj);
3755 }
3756 }
3757
3758 return 0;
3759}
3760
3761////////////////////////////////////////////////////////////////////////////////
3762/// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3763/// The collection needs to be a split TClonesArray or a split vector of pointers.
3764
3766{
3767 if (gDebug) {
3768 //loop on all active members
3769 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3770 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3771 iter != end;
3772 ++iter) {
3774 (*iter).PrintDebug(*this, nullptr); // Warning: This limits us to TClonesArray and vector of pointers.
3775 else
3776 (*iter).PrintDebug(*this, *(char**)start_collection); // Warning: This limits us to TClonesArray and vector of pointers.
3777 (*iter)(*this, start_collection, end_collection);
3778 }
3779
3780 } else {
3781 //loop on all active members
3782 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3783 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3784 iter != end;
3785 ++iter) {
3786 (*iter)(*this,start_collection,end_collection);
3787 }
3788 }
3789
3790 return 0;
3791}
3792
3793////////////////////////////////////////////////////////////////////////////////
3794/// Read one collection of objects from the buffer using the StreamerInfoLoopAction.
3795
3797{
3799 if (gDebug) {
3800
3801 // Get the address of the first item for the PrintDebug.
3802 // (Performance is not essential here since we are going to print to
3803 // the screen anyway).
3804 void *arr0 = start_collection ? loopconfig->GetFirstAddress(start_collection,end_collection) : 0;
3805 // loop on all active members
3806 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3807 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3808 iter != end;
3809 ++iter) {
3810 (*iter).PrintDebug(*this,arr0);
3812 }
3813
3814 } else {
3815 //loop on all active members
3816 TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
3817 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
3818 iter != end;
3819 ++iter) {
3821 }
3822 }
3823
3824 return 0;
3825}
void * bswapcpy16(void *to, const void *from, size_t n)
Definition Bswapcpy.h:45
void * bswapcpy32(void *to, const void *from, size_t n)
Definition Bswapcpy.h:60
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:278
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:54
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
constexpr Int_t kMaxInt
Definition RtypesCore.h:119
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:52
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:51
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
unsigned long ULongptr_t
Unsigned integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:90
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Definition RtypesCore.h:84
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const UInt_t kMaxMapCount
const Int_t kMapOffset
const UInt_t kNewClassTag
static void frombufOld(char *&buf, Long_t *x)
Handle old file formats.
const Version_t kMaxVersion
const UInt_t kClassMask
static bool Class_Has_StreamerInfo(const TClass *cl)
Thread-safe check on StreamerInfos of a TClass.
const Version_t kByteCountVMask
const UInt_t kByteCountMask
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
@ kIsAbstract
Definition TDictionary.h:71
#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 data
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 Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
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 Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition TGX11.cxx:145
float xmin
float xmax
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:632
char *(* ReAllocCharFun_t)(char *, size_t, size_t)
Definition TStorage.h:30
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
const_iterator begin() const
const_iterator end() const
void WriteFastArrayFloat16(const Float_t *f, Long64_t n, TStreamerElement *ele=nullptr) override
Write array of n floats (as truncated float) into the I/O buffer.
void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue) override
Read a Float16_t from the buffer when the factor and minimum value have been specified see comments a...
void WriteBuf(const void *buf, Int_t max) override
Write max bytes from buf into the I/O buffer.
void WriteFastArray(const Bool_t *b, Long64_t n) override
Write array of n bools into the I/O buffer.
TObject * ReadObject(const TClass *cl) override
Read object from I/O buffer.
void ReadDouble32(Double_t *d, TStreamerElement *ele=nullptr) override
Read a Double32_t from the buffer, see comments about Double32_t encoding at TBufferFile::WriteDouble...
Int_t ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele=nullptr) override
Read array of floats (written as truncated float) from the I/O buffer.
void DecrementLevel(TVirtualStreamerInfo *) override
Decrement level.
Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr) override
Read class version from I/O buffer.
Version_t ReadVersionNoCheckSum(UInt_t *start=nullptr, UInt_t *bcnt=nullptr) override
Read class version from I/O buffer, when the caller knows for sure that there is no checksum written/...
void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE) override
Set byte count at position cntpos in the buffer.
~TBufferFile() override
Delete an I/O buffer object.
void ReadWithNbits(Float_t *ptr, Int_t nbits) override
Read a Float16_t from the buffer when the number of bits is specified (explicitly or not) see comment...
void WriteObjectClass(const void *actualObjStart, const TClass *actualClass, Bool_t cacheReuse) override
Write object to I/O buffer.
void ReadTString(TString &s) override
Read TString from TBuffer.
void ReadCharStar(char *&s) override
Read char* from TBuffer.
void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=nullptr) override
Stream an object given its C++ typeinfo information.
UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE) override
Write class version to I/O buffer.
Int_t ReadBuf(void *buf, Int_t max) override
Read max bytes from the I/O buffer into buf.
void WriteString(const char *s) override
Write string to I/O buffer.
char * ReadString(char *s, Int_t max) override
Read string from I/O buffer.
void WriteArray(const Bool_t *b, Int_t n) override
Write array of n bools into the I/O buffer.
void ReadFastArray(Bool_t *b, Int_t n) override
Read array of n bools from the I/O buffer.
void ReadFastArrayString(Char_t *c, Int_t n) override
Read array of n characters from the I/O buffer.
Int_t ReadArray(Bool_t *&b) override
Read array of bools from the I/O buffer.
Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object) override
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
void * ReadObjectAny(const TClass *cast) override
Read object from I/O buffer.
void SkipObjectAny() override
Skip any kind of object from buffer.
Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=nullptr) override
Read array of doubles (written as float) from the I/O buffer.
TClass * ReadClass(const TClass *cl=nullptr, UInt_t *objTag=nullptr) override
Read class definition from I/O buffer.
Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class) override
Deserialize information from a buffer into an object.
void SkipVersion(const TClass *cl=nullptr) override
Skip class version from I/O buffer.
void ReadFloat16(Float_t *f, TStreamerElement *ele=nullptr) override
Read a Float16_t from the buffer, see comments about Float16_t encoding at TBufferFile::WriteFloat16(...
void Streamer(TBuffer &) override
Stream an object of class TObject.
void WriteFastArrayDouble32(const Double_t *d, Long64_t n, TStreamerElement *ele=nullptr) override
Write array of n doubles (as float) into the I/O buffer.
void WriteFastArrayString(const Char_t *c, Long64_t n) override
Write array of n characters into the I/O buffer.
Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss, const char *classname)
Check byte count with current buffer position.
void WriteCharStar(char *s) override
Write char* into TBuffer.
Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection) override
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
void WriteStdString(const std::string *s) override
Write std::string to TBuffer.
Int_t WriteClassBuffer(const TClass *cl, void *pointer) override
Function called by the Streamer functions to serialize object at p to buffer b.
void WriteClass(const TClass *cl) override
Write class description to I/O buffer.
void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=nullptr) override
Read array of n doubles (written as float) from the I/O buffer.
UInt_t WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt=kFALSE) override
Write class version to I/O buffer after setting the kStreamedMemberWise bit in the version number.
void CheckCount(UInt_t offset) override
Check if offset is not too large (< kMaxMapCount) when writing.
bool ShouldNotReadCollection(Int_t lengthInBytes, Int_t nElements=1) const
Int_t ReadArrayFloat16(Float_t *&f, TStreamerElement *ele=nullptr) override
Read array of floats (written as truncated float) from the I/O buffer.
void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=nullptr) override
Read array of n floats (written as truncated float) from the I/O buffer.
void ReadStdString(std::string *s) override
Read std::string from TBuffer.
void WriteFloat16(Float_t *f, TStreamerElement *ele=nullptr) override
Write a Float16_t to the buffer.
Int_t ReadStaticArray(Bool_t *b) override
Read array of bools from the I/O buffer.
void WriteTString(const TString &s) override
Write TString to TBuffer.
UInt_t CheckObject(UInt_t offset, const TClass *cl, Bool_t readClass=kFALSE)
Check for object in the read map.
InfoList_t fInfoStack
Stack of pointers to the TStreamerInfos.
Definition TBufferFile.h:53
void WriteDouble32(Double_t *d, TStreamerElement *ele=nullptr) override
Write a Double32_t to the buffer.
void ReadLong(Long_t &l) override
Read Long from TBuffer.
void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits) override
Read array of n floats (written as truncated float) from the I/O buffer.
void IncrementLevel(TVirtualStreamerInfo *info) override
Increment level.
Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=nullptr) override
Read array of doubles (written as float) from the I/O buffer.
void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=nullptr) override
Write array of n doubles (as float) into the I/O buffer.
void WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele=nullptr) override
Write array of n floats (as truncated float) into the I/O buffer.
void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue) override
Read array of n floats (written as truncated float) from the I/O buffer.
Version_t ReadVersionForMemberWise(const TClass *cl=nullptr) override
Read class version from I/O buffer.
TStreamerInfo * fInfo
Pointer to TStreamerInfo object writing/reading the buffer.
Definition TBufferFile.h:52
Int_t ReadClassEmulated(const TClass *cl, void *object, const TClass *onfile_class) override
Read emulated class.
@ kStreamedMemberWise
Definition TBufferFile.h:70
Direct subclass of TBuffer, implements common methods for TBufferFile and TBufferText classes.
Definition TBufferIO.h:30
void InitMap() override
Create the fMap container and initialize them with the null object.
void ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t force) override
force writing the TStreamerInfo to the file
TExMap * fMap
Map containing object,offset pairs for reading/writing.
Definition TBufferIO.h:39
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
TExMap * fClassMap
Map containing object,class pairs for reading.
Definition TBufferIO.h:40
Int_t fDisplacement
Value to be added to the map offsets.
Definition TBufferIO.h:37
static R__ALWAYS_INLINE ULong_t Void_Hash(const void *ptr)
Return hash value for provided object.
Definition TBufferIO.h:53
Int_t fMapCount
Number of objects or classes in map.
Definition TBufferIO.h:35
void TagStreamerInfo(TVirtualStreamerInfo *info) override
Mark the classindex of the current file as using this TStreamerInfo.
Int_t WriteObjectAny(const void *obj, const TClass *ptrClass, Bool_t cacheReuse=kTRUE) override
Write object to I/O buffer.
Int_t fBufSize
Definition TBuffer.h:50
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition TBuffer.cxx:261
char * fBufMax
Definition TBuffer.h:53
char * fBufCur
Definition TBuffer.h:52
void AutoExpand(Int_t size_needed)
Automatically calculate a new size and expand the buffer to fit at least size_needed.
Definition TBuffer.cxx:157
Bool_t IsWriting() const
Definition TBuffer.h:87
Bool_t IsReading() const
Definition TBuffer.h:86
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
char * fBuffer
Definition TBuffer.h:51
TObject * fParent
Definition TBuffer.h:54
Int_t fVersion
Definition TBuffer.h:49
Int_t Length() const
Definition TBuffer.h:100
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition TClass.cxx:6616
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:626
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5048
static TClass * Load(TBuffer &b)
Load class description from I/O buffer and return class object.
Definition TClass.cxx:5817
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition TClass.h:454
void SetLastReadInfo(TVirtualStreamerInfo *info)
Definition TClass.h:460
Bool_t MatchLegacyCheckSum(UInt_t checksum) const
Return true if the checksum passed as argument is one of the checksum value produced by the older che...
Definition TClass.cxx:6605
TVirtualStreamerInfo * GetLastReadInfo() const
Definition TClass.h:459
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5806
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition TClass.cxx:5965
const TObjArray * GetStreamerInfos() const
Definition TClass.h:508
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:6017
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition TClass.cxx:6052
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4657
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4932
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6191
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition TClass.cxx:7209
@ kEmulated
Definition TClass.h:128
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition TClass.cxx:7189
Version_t GetClassVersion() const
Definition TClass.h:434
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:2994
Int_t GetSize() const
Definition TExMap.h:71
void Remove(ULong64_t hash, Long64_t key)
Remove entry with specified key from the TExMap.
Definition TExMap.cxx:216
void Add(ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table. The key should be unique.
Definition TExMap.cxx:87
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition TExMap.cxx:173
Int_t Capacity() const
Definition TExMap.h:69
void AddAt(UInt_t slot, ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table.
Definition TExMap.cxx:116
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
Int_t GetVersion() const
Definition TFile.h:333
A doubly linked list.
Definition TList.h:38
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:459
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:994
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1081
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1095
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1123
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1069
Describe one element (data member) to be Streamed.
Base class of the Configurations for the member wise looping routines.
Describes a persistent version of a class.
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void UnLink() const
Definition TString.h:271
Ssiz_t Clobber(Ssiz_t nc)
Clear string and make sure it has a capacity of nc.
Definition TString.cxx:1252
void SetSize(Ssiz_t s)
Definition TString.h:256
void Zero()
Definition TString.h:272
char * GetPointer()
Definition TString.h:264
Abstract Interface class describing Streamer information for one class.
static Bool_t CanDelete()
static function returning true if ReadBuffer can delete object
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
R__EXTERN TVirtualRWMutex * gCoreMutex
TLine l
Definition textangle.C:4