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