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