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