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