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