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