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