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