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