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