Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TStreamerElement.cxx
Go to the documentation of this file.
1 // @(#)root/meta:$Id$
2 // Author: Rene Brun 12/10/2000
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 // //
14 // //
15 //////////////////////////////////////////////////////////////////////////
16 
17 
18 #include "TROOT.h"
19 #include "TStreamerElement.h"
20 #include "TVirtualStreamerInfo.h"
21 #include "TClass.h"
22 #include "TClassEdit.h"
23 #include "TClassStreamer.h"
24 #include "TClassTable.h"
25 #include "TBaseClass.h"
26 #include "TDataMember.h"
27 #include "TDataType.h"
28 #include "TRealData.h"
29 #include "TRef.h"
30 #include "TInterpreter.h"
31 #include "TError.h"
32 #include "TVirtualMutex.h"
34 #include <iostream>
35 
36 #include <string>
37 namespace std {} using namespace std;
38 
39 const Int_t kMaxLen = 1024;
40 
41 static TString &IncludeNameBuffer() {
42  TTHREAD_TLS_DECL_ARG(TString,includeName,kMaxLen);
43  return includeName;
44 }
45 
46 static TString ExtractClassName(const TString &type_name)
47 {
48  TString className = type_name.Strip(TString::kTrailing, '*');
49  if (className.Index("const ")==0) className.Remove(0,6);
50  return className;
51 }
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Helper function to initialize the 'index/counter' value of
54 /// the Pointer streamerElements. If directive is a StreamerInfo and it correspond to the
55 /// same class a 'countClass' the streamerInfo is used instead of the current StreamerInfo of the TClass
56 /// for 'countClass'.
57 
58 static TStreamerBasicType *InitCounter(const char *countClass, const char *countName, TVirtualStreamerInfo *directive)
59 {
60  TStreamerBasicType *counter = 0;
61 
62  TClass *cl = TClass::GetClass(countClass);
63 
64  if (directive) {
65 
66  if (directive->GetClass() == cl) {
67  // The info we have been passed is indeed describing the counter holder, just look there.
68 
69  TStreamerElement *element = (TStreamerElement *)directive->GetElements()->FindObject(countName);
70  if (!element) return 0;
71  if (element->IsA() != TStreamerBasicType::Class()) return 0;
72  counter = (TStreamerBasicType*)element;
73 
74  } else {
75  if (directive->GetClass()->GetListOfRealData()) {
76  TRealData* rdCounter = (TRealData*) directive->GetClass()->GetListOfRealData()->FindObject(countName);
77  if (!rdCounter) return 0;
78  TDataMember *dmCounter = rdCounter->GetDataMember();
79  cl = dmCounter->GetClass();
80  } else {
81  TStreamerElement *element = (TStreamerElement *)directive->GetElements()->FindObject(countName);
82  if (!element) return 0;
83  if (element->IsA() != TStreamerBasicType::Class()) return 0;
84  cl = directive->GetClass();
85  }
86  if (cl==0) return 0;
87  counter = TVirtualStreamerInfo::GetElementCounter(countName,cl);
88  }
89  } else {
90 
91  if (cl==0) return 0;
92  counter = TVirtualStreamerInfo::GetElementCounter(countName,cl);
93  }
94 
95  //at this point the counter may be declared to be skipped
96  if (counter) {
97  if (counter->GetType() < TVirtualStreamerInfo::kCounter) counter->SetType(TVirtualStreamerInfo::kCounter);
98  }
99  return counter;
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// Parse comments to search for a range specifier of the style:
104 /// [xmin,xmax] or [xmin,xmax,nbits]
105 /// [0,1]
106 /// [-10,100];
107 /// [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi]
108 /// [-10,100,16]
109 /// [0,0,8]
110 /// if nbits is not specified, or nbits <2 or nbits>32 it is set to 32
111 /// if (xmin==0 and xmax==0 and nbits <=16) the double word will be converted
112 /// to a float and its mantissa truncated to nbits significative bits.
113 ///
114 /// see comments in TBufferFile::WriteDouble32.
115 
116 static void GetRange(const char *comments, Double_t &xmin, Double_t &xmax, Double_t &factor)
117 {
118  const Double_t kPi =3.14159265358979323846 ;
119  factor = xmin = xmax = 0;
120  if (!comments) return;
121  const char *left = strstr(comments,"[");
122  if (!left) return;
123  const char *right = strstr(left,"]");
124  if (!right) return;
125  const char *comma = strstr(left,",");
126  if (!comma || comma > right) {
127  //may be first bracket was a dimension specifier
128  left = strstr(right,"[");
129  if (!left) return;
130  right = strstr(left,"]");
131  if (!right) return;
132  comma = strstr(left,",");
133  if (!comma || comma >right) return;
134  }
135  //search if nbits is specified
136  const char *comma2 = 0;
137  if (comma) comma2 = strstr(comma+1,",");
138  if (comma2 > right) comma2 = 0;
139  Int_t nbits = 32;
140  if (comma2) {
141  TString sbits(comma2+1,right-comma2-1);
142  sscanf(sbits.Data(),"%d",&nbits);
143  if (nbits < 2 || nbits > 32) {
144  ::Error("GetRange","Illegal specification for the number of bits; %d. reset to 32.",nbits);
145  nbits = 32;
146  }
147  right = comma2;
148  }
149  TString range(left+1,right-left-1);
150  TString sxmin(left+1,comma-left-1);
151  sxmin.ToLower();
152  sxmin.ReplaceAll(" ","");
153  if (sxmin.Contains("pi")) {
154  if (sxmin.Contains("2pi")) xmin = 2*kPi;
155  else if (sxmin.Contains("2*pi")) xmin = 2*kPi;
156  else if (sxmin.Contains("twopi")) xmin = 2*kPi;
157  else if (sxmin.Contains("pi/2")) xmin = kPi/2;
158  else if (sxmin.Contains("pi/4")) xmin = kPi/4;
159  else if (sxmin.Contains("pi")) xmin = kPi;
160  if (sxmin.Contains("-")) xmin = -xmin;
161  } else {
162  sscanf(sxmin.Data(),"%lg",&xmin);
163  }
164  TString sxmax(comma+1,right-comma-1);
165  sxmax.ToLower();
166  sxmax.ReplaceAll(" ","");
167  if (sxmax.Contains("pi")) {
168  if (sxmax.Contains("2pi")) xmax = 2*kPi;
169  else if (sxmax.Contains("2*pi")) xmax = 2*kPi;
170  else if (sxmax.Contains("twopi")) xmax = 2*kPi;
171  else if (sxmax.Contains("pi/2")) xmax = kPi/2;
172  else if (sxmax.Contains("pi/4")) xmax = kPi/4;
173  else if (sxmax.Contains("pi")) xmax = kPi;
174  if (sxmax.Contains("-")) xmax = -xmax;
175  } else {
176  sscanf(sxmax.Data(),"%lg",&xmax);
177  }
178  UInt_t bigint;
179  if (nbits < 32) bigint = 1<<nbits;
180  else bigint = 0xffffffff;
181  if (xmin < xmax) factor = bigint/(xmax-xmin);
182  if (xmin >= xmax && nbits <15) xmin = nbits+0.1;
183 }
184 
185 ClassImp(TStreamerElement);
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Default ctor.
189 
190 TStreamerElement::TStreamerElement()
191 {
192  fType = 0;
193  fSize = 0;
194  fNewType = 0;
195  fArrayDim = 0;
196  fArrayLength = 0;
197  fStreamer = 0;
198  fOffset = 0;
199  fClassObject = (TClass*)(-1);
200  fNewClass = 0;
201  fTObjectOffset = 0;
202  fFactor = 0;
203  fXmin = 0;
204  fXmax = 0;
205  for (Int_t i=0;i<5;i++) fMaxIndex[i] = 0;
206 }
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 /// Create a TStreamerElement object.
210 
211 TStreamerElement::TStreamerElement(const char *name, const char *title, Int_t offset, Int_t dtype, const char *typeName)
212  : TNamed(name,title)
213 {
214  fOffset = offset;
215  fType = dtype;
216  fSize = 0;
217  fNewType = fType;
218  fArrayDim = 0;
219  fArrayLength = 0;
220  if (typeName && !strcmp(typeName, "BASE")) {
221  // TStreamerBase case; fTypeName should stay "BASE".
222  fTypeName = typeName;
223  } else {
224  //must protect call into the interpreter
225  R__LOCKGUARD(gInterpreterMutex);
226  fTypeName = TClassEdit::ResolveTypedef(typeName);
227  }
228  fStreamer = 0;
229  fClassObject = (TClass*)(-1);
230  fNewClass = 0;
231  fTObjectOffset = 0;
232  fFactor = 0;
233  fXmin = 0;
234  fXmax = 0;
235  for (Int_t i=0;i<5;i++) fMaxIndex[i] = 0;
236  if (fTypeName == "Float16_t" || fTypeName == "Float16_t*") {
237  GetRange(title,fXmin,fXmax,fFactor);
238  if (fFactor > 0 || fXmin > 0) SetBit(kHasRange);
239  }
240  if (fTypeName == "Double32_t" || fTypeName == "Double32_t*") {
241  GetRange(title,fXmin,fXmax,fFactor);
242  if (fFactor > 0 || fXmin > 0) SetBit(kHasRange);
243  }
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// TStreamerElement dtor.
248 
249 TStreamerElement::~TStreamerElement()
250 {
251 }
252 
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Returns true if the element cannot be split, false otherwise.
256 /// An element cannot be split if the corresponding class member has
257 /// the special characters "||" as the first characters in the
258 /// comment field.
259 
260 Bool_t TStreamerElement::CannotSplit() const
261 {
262  if (GetTitle()[0] != 0 && strspn(GetTitle(),"||") == 2) return kTRUE;
263  TClass *cl = GetClassPointer();
264  if (!cl) return kFALSE; //basic type
265 
266  static TClassRef clonesArray("TClonesArray");
267  if (IsaPointer() && cl != clonesArray && !cl->GetCollectionProxy()) return kTRUE;
268 
269  switch(fType) {
270  case TVirtualStreamerInfo::kAny +TVirtualStreamerInfo::kOffsetL:
271  case TVirtualStreamerInfo::kObject +TVirtualStreamerInfo::kOffsetL:
272  case TVirtualStreamerInfo::kTObject+TVirtualStreamerInfo::kOffsetL:
273  case TVirtualStreamerInfo::kTString+TVirtualStreamerInfo::kOffsetL:
274  case TVirtualStreamerInfo::kTNamed +TVirtualStreamerInfo::kOffsetL:
275  return kTRUE;
276  }
277 
278  if ( !cl->CanSplit() ) return kTRUE;
279 
280  return kFALSE;
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Returns a pointer to the TClass of this element.
285 
286 TClass *TStreamerElement::GetClassPointer() const
287 {
288  if (fClassObject!=(TClass*)(-1)) return fClassObject;
289 
290  TString className(ExtractClassName(fTypeName));
291  bool quiet = (fType == TVirtualStreamerInfo::kArtificial);
292  ((TStreamerElement*)this)->fClassObject = TClass::GetClass(className, kTRUE, quiet);
293  return fClassObject;
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 /// Returns the TExec id for the EXEC instruction in the comment field
298 /// of a TRef data member.
299 
300 Int_t TStreamerElement::GetExecID() const
301 {
302  //check if element is a TRef or TRefArray
303  if (strncmp(fTypeName.Data(),"TRef",4) != 0) return 0;
304 
305  //if the UniqueID of this element has already been set, we assume
306  //that it contains the exec id of a TRef object.
307  if (GetUniqueID()) return GetUniqueID();
308 
309  //check if an Exec is specified in the comment field
310  char *action = (char*)strstr(GetTitle(),"EXEC:");
311  if (!action) return 0;
312  Int_t nch = strlen(action)+1;
313  char *caction = new char[nch];
314  strlcpy(caction,action+5,nch);
315  char *blank = (char*)strchr(caction,' ');
316  if (blank) *blank = 0;
317  //we have found the Exec name in the comment
318  //we register this Exec to the list of Execs.
319  Int_t index = TRef::AddExec(caction);
320  delete [] caction;
321  //we save the Exec index as the uniqueid of this STreamerElement
322  const_cast<TStreamerElement*>(this)->SetUniqueID(index+1);
323  return index+1;
324 }
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 /// Return element name including dimensions, if any
328 /// Note that this function stores the name into a static array.
329 /// You should copy the result.
330 
331 const char *TStreamerElement::GetFullName() const
332 {
333  TTHREAD_TLS_DECL_ARG(TString,name,kMaxLen);
334  char cdim[20];
335  name = GetName();
336  for (Int_t i=0;i<fArrayDim;i++) {
337  snprintf(cdim,19,"[%d]",fMaxIndex[i]);
338  name += cdim;
339  }
340  return name;
341 }
342 
343 ////////////////////////////////////////////////////////////////////////////////
344 /// Fill type with the string representation of sequence
345 /// information including 'cached','repeat','write' or
346 /// 'nodelete'.
347 
348 void TStreamerElement::GetSequenceType(TString &sequenceType) const
349 {
350  sequenceType.Clear();
351  Bool_t first = kTRUE;
352  if (TestBit(TStreamerElement::kWholeObject)) {
353  if (!first) sequenceType += ",";
354  first = kFALSE;
355  sequenceType += "wholeObject";
356  }
357  if (TestBit(TStreamerElement::kCache)) {
358  first = kFALSE;
359  sequenceType += "cached";
360  }
361  if (TestBit(TStreamerElement::kRepeat)) {
362  if (!first) sequenceType += ",";
363  first = kFALSE;
364  sequenceType += "repeat";
365  }
366  if (TestBit(TStreamerElement::kDoNotDelete)) {
367  if (!first) sequenceType += ",";
368  first = kFALSE;
369  sequenceType += "nodelete";
370  }
371  if (TestBit(TStreamerElement::kWrite)) {
372  if (!first) sequenceType += ",";
373  first = kFALSE;
374  sequenceType += "write";
375  }
376 }
377 
378 ////////////////////////////////////////////////////////////////////////////////
379 /// Returns size of this element in bytes.
380 
381 Int_t TStreamerElement::GetSize() const
382 {
383  return fSize;
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Return the local streamer object.
388 
389 TMemberStreamer *TStreamerElement::GetStreamer() const
390 {
391  return fStreamer;
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Return type name of this element
396 /// in case the type name is not a standard basic type, return
397 /// the basic type name known to CINT.
398 
399 const char *TStreamerElement::GetTypeNameBasic() const
400 {
401  TDataType *dt = gROOT->GetType(fTypeName.Data());
402  if (fType < 1 || fType > 55) return fTypeName.Data();
403  if (dt && dt->GetType() > 0) return fTypeName.Data();
404  Int_t dtype = fType%20;
405  return TDataType::GetTypeName((EDataType)dtype);
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// Initliaze the element.
410 
411 void TStreamerElement::Init(TVirtualStreamerInfo *)
412 {
413  fClassObject = GetClassPointer();
414  if (fClassObject && fClassObject->IsTObject()) {
415  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
416  }
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// The early 3.00/00 and 3.01/01 versions used to store
421 /// dm->GetTypeName instead of dm->GetFullTypename
422 /// if this case is detected, the element type name is modified.
423 
424 Bool_t TStreamerElement::IsOldFormat(const char *newTypeName)
425 {
426  //if (!IsaPointer()) return kFALSE;
427  if (!strstr(newTypeName,fTypeName.Data())) return kFALSE;
428  //if (!strstr(fTypeName.Data(),newTypeName)) return kFALSE;
429  fTypeName = newTypeName;
430  return kTRUE;
431 }
432 
433 ////////////////////////////////////////////////////////////////////////////////
434 /// Return kTRUE if the element represent a base class.
435 
436 Bool_t TStreamerElement::IsBase() const
437 {
438  return kFALSE;
439 }
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 /// Return kTRUE if the element represent an entity that is not written
443 /// to the disk (transient members, cache allocator/deallocator, etc.)
444 
445 Bool_t TStreamerElement::IsTransient() const
446 {
447  if (fType == TVirtualStreamerInfo::kArtificial) {
448  // if (((const TStreamerArtificial*)this)->GetWriteFunc() == 0)
449  return kTRUE;
450  }
451  if (fType == TVirtualStreamerInfo::kCacheNew) return kTRUE;
452  if (fType == TVirtualStreamerInfo::kCacheDelete) return kTRUE;
453  if (fType == TVirtualStreamerInfo::kCache) return kTRUE;
454  if (fType == TVirtualStreamerInfo::kMissing) return kTRUE;
455  if (TVirtualStreamerInfo::kSkip <= fType && fType < TVirtualStreamerInfo::kConv) return kTRUE;
456 
457  return kFALSE;
458 }
459 
460 ////////////////////////////////////////////////////////////////////////////////
461 /// Print the content of the element.
462 
463 void TStreamerElement::ls(Option_t *) const
464 {
465  TString temp(GetTypeName());
466  if (IsaPointer() && !fTypeName.Contains("*")) temp += "*";
467 
468  TString sequenceType;
469  GetSequenceType(sequenceType);
470  if (sequenceType.Length()) {
471  sequenceType.Prepend(" (");
472  sequenceType += ") ";
473  }
474  printf(" %-14s %-15s offset=%3d type=%2d %s%-20s\n",
475  temp.Data(),GetFullName(),fOffset,fType,sequenceType.Data(),
476  GetTitle());
477 }
478 
479 ////////////////////////////////////////////////////////////////////////////////
480 /// Set number of array dimensions.
481 
482 void TStreamerElement::SetArrayDim(Int_t dim)
483 {
484  fArrayDim = dim;
485  if (dim) fType += TVirtualStreamerInfo::kOffsetL;
486  fNewType = fType;
487 }
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 ///set maximum index for array with dimension dim
491 
492 void TStreamerElement::SetMaxIndex(Int_t dim, Int_t max)
493 {
494  if (dim < 0 || dim > 4) return;
495  fMaxIndex[dim] = max;
496  if (fArrayLength == 0) fArrayLength = max;
497  else fArrayLength *= max;
498 }
499 
500 ////////////////////////////////////////////////////////////////////////////////
501 ///set pointer to Streamer function for this element
502 
503 void TStreamerElement::SetStreamer(TMemberStreamer *streamer)
504 {
505  fStreamer = streamer;
506 }
507 
508 ////////////////////////////////////////////////////////////////////////////////
509 /// Stream an object of class TStreamerElement.
510 
511 void TStreamerElement::Streamer(TBuffer &R__b)
512 {
513  UInt_t R__s, R__c;
514  if (R__b.IsReading()) {
515  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
516  //NOTE that when reading, one cannot use Class()->ReadBuffer
517  // TBuffer::Class methods used for reading streamerinfos from SQL database
518  // Any changes of class structure should be reflected by them starting from version 4
519 
520  R__b.ClassBegin(TStreamerElement::Class(), R__v);
521  R__b.ClassMember("TNamed");
522  TNamed::Streamer(R__b);
523  R__b.ClassMember("fType","Int_t");
524  R__b >> fType;
525  R__b.ClassMember("fSize","Int_t");
526  R__b >> fSize;
527  R__b.ClassMember("fArrayLength","Int_t");
528  R__b >> fArrayLength;
529  R__b.ClassMember("fArrayDim","Int_t");
530  R__b >> fArrayDim;
531  R__b.ClassMember("fMaxIndex","Int_t", 5);
532  if (R__v == 1) R__b.ReadStaticArray(fMaxIndex);
533  else R__b.ReadFastArray(fMaxIndex,5);
534  R__b.ClassMember("fTypeName","TString");
535  fTypeName.Streamer(R__b);
536  if (fType==11&&(fTypeName=="Bool_t"||fTypeName=="bool")) fType = 18;
537  if (R__v > 1) {
538  SetUniqueID(0);
539  //check if element is a TRef or TRefArray
540  GetExecID();
541  }
542  if (R__v <= 2 && this->IsA()==TStreamerBasicType::Class()) {
543  // In TStreamerElement v2, fSize was holding the size of
544  // the underlying data type. In later version it contains
545  // the full length of the data member.
546  TDataType *type = gROOT->GetType(GetTypeName());
547  if (type && fArrayLength) fSize = fArrayLength * type->Size();
548  }
549  if (R__v == 3) {
550  R__b >> fXmin;
551  R__b >> fXmax;
552  R__b >> fFactor;
553  if (fFactor > 0) SetBit(kHasRange);
554  }
555  if (R__v > 3) {
556  if (TestBit(kHasRange)) GetRange(GetTitle(),fXmin,fXmax,fFactor);
557  }
558  //R__b.CheckByteCount(R__s, R__c, TStreamerElement::IsA());
559  R__b.ClassEnd(TStreamerElement::Class());
560  R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
561 
562  ResetBit(TStreamerElement::kCache);
563  ResetBit(TStreamerElement::kWrite);
564  } else {
565  R__b.WriteClassBuffer(TStreamerElement::Class(),this);
566  }
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 ///function called by the TClass constructor when replacing an emulated class
571 ///by the real class
572 
573 void TStreamerElement::Update(const TClass *oldClass, TClass *newClass)
574 {
575  if (fClassObject == oldClass) {
576  fClassObject = newClass;
577  if (fClassObject && fClassObject->IsTObject()) {
578  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
579  }
580  } else if (fClassObject == nullptr) {
581  // Well since some emulated class is replaced by a real class, we can
582  // assume a new library has been loaded. If this is the case, we should
583  // check whether the class now exist (this would be the case for example
584  // for reading STL containers).
585 
586  TString classname(ExtractClassName(fTypeName));
587 
588  if (classname == newClass->GetName()) {
589  fClassObject = newClass;
590  if (fClassObject && fClassObject->IsTObject()) {
591  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
592  }
593  } else if (TClassTable::GetDict(classname)) {
594  fClassObject = (TClass*)-1;
595  GetClassPointer(); //force fClassObject
596  if (fClassObject && fClassObject->IsTObject()) {
597  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
598  }
599  }
600  }
601 }
602 
603 //______________________________________________________________________________
604 
605 //////////////////////////////////////////////////////////////////////////
606 // //
607 // TStreamerBase implement the streamer of the base class //
608 // //
609 //////////////////////////////////////////////////////////////////////////
610 
611 ClassImp(TStreamerBase);
612 
613 ////////////////////////////////////////////////////////////////////////////////
614 
615 TStreamerBase::TStreamerBase() :
616  // Abuse TStreamerElement data member that is not used by TStreamerBase
617  fBaseCheckSum( *( (UInt_t*)&(fMaxIndex[1]) ) ),
618  fStreamerFunc(0), fConvStreamerFunc(0), fStreamerInfo(0)
619 {
620  // Default ctor.
621 
622  fBaseClass = (TClass*)(-1);
623  fBaseVersion = 0;
624  fNewBaseClass = 0;
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 
629 TStreamerBase::TStreamerBase(const char *name, const char *title, Int_t offset)
630  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kBase,"BASE"),
631  // Abuse TStreamerElement data member that is not used by TStreamerBase
632  fBaseCheckSum( *( (UInt_t*)&(fMaxIndex[1]) ) ),
633  fStreamerFunc(0), fConvStreamerFunc(0), fStreamerInfo(0)
634 
635 {
636  // Create a TStreamerBase object.
637 
638  if (strcmp(name,"TObject") == 0) fType = TVirtualStreamerInfo::kTObject;
639  if (strcmp(name,"TNamed") == 0) fType = TVirtualStreamerInfo::kTNamed;
640  fNewType = fType;
641  fBaseClass = TClass::GetClass(GetName());
642  if (fBaseClass) {
643  if (fBaseClass->IsVersioned()) {
644  fBaseVersion = fBaseClass->GetClassVersion();
645  } else {
646  fBaseVersion = -1;
647  }
648  fBaseCheckSum = fBaseClass->GetCheckSum();
649  } else {
650  fBaseVersion = 0;
651  }
652  fNewBaseClass = 0;
653  Init();
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// TStreamerBase dtor
658 
659 TStreamerBase::~TStreamerBase()
660 {
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 /// Returns a pointer to the TClass of this element.
665 
666 TClass *TStreamerBase::GetClassPointer() const
667 {
668  if (fBaseClass!=(TClass*)(-1)) return fBaseClass;
669  ((TStreamerBase*)this)->fBaseClass = TClass::GetClass(GetName());
670  return fBaseClass;
671 }
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Returns size of baseclass in bytes.
675 
676 Int_t TStreamerBase::GetSize() const
677 {
678  TClass *cl = GetClassPointer();
679  if (cl) return cl->Size();
680  return 0;
681 }
682 
683 ////////////////////////////////////////////////////////////////////////////////
684 /// Setup the element.
685 
686 void TStreamerBase::Init(TVirtualStreamerInfo *)
687 {
688  fBaseClass = TClass::GetClass(GetName());
689  if (!fBaseClass) return;
690 
691  InitStreaming();
692 }
693 
694 ////////////////////////////////////////////////////////////////////////////////
695 /// Setup the fStreamerFunc and fStreamerinfo
696 
697 void TStreamerBase::InitStreaming()
698 {
699  if (fNewBaseClass) {
700  fStreamerFunc = fNewBaseClass->GetStreamerFunc();
701  fConvStreamerFunc = fNewBaseClass->GetConvStreamerFunc();
702  if (fBaseVersion > 0 || fBaseCheckSum == 0) {
703  fStreamerInfo = fNewBaseClass->GetConversionStreamerInfo(fBaseClass,fBaseVersion);
704  } else {
705  fStreamerInfo = fNewBaseClass->FindConversionStreamerInfo(fBaseClass,fBaseCheckSum);
706  }
707  } else if (fBaseClass && fBaseClass != (TClass*)-1) {
708  fStreamerFunc = fBaseClass->GetStreamerFunc();
709  fConvStreamerFunc = fBaseClass->GetConvStreamerFunc();
710  if (fBaseVersion >= 0 || fBaseCheckSum == 0) {
711  fStreamerInfo = fBaseClass->GetStreamerInfo(fBaseVersion);
712  } else {
713  fStreamerInfo = fBaseClass->FindStreamerInfo(fBaseCheckSum);
714  }
715  } else {
716  fStreamerFunc = 0;
717  fConvStreamerFunc = 0;
718  fStreamerInfo = 0;
719  }
720 }
721 
722 ////////////////////////////////////////////////////////////////////////////////
723 /// Return kTRUE if the element represent a base class.
724 
725 Bool_t TStreamerBase::IsBase() const
726 {
727  return kTRUE;
728 }
729 
730 ////////////////////////////////////////////////////////////////////////////////
731 /// Return the proper include for this element.
732 
733 const char *TStreamerBase::GetInclude() const
734 {
735  if (GetClassPointer() && fBaseClass->HasInterpreterInfo()) {
736  IncludeNameBuffer().Form("\"%s\"",fBaseClass->GetDeclFileName());
737  } else {
738  std::string shortname( TClassEdit::ShortType( GetName(), 1 ) );
739  IncludeNameBuffer().Form("\"%s.h\"",shortname.c_str());
740  }
741  return IncludeNameBuffer();
742 }
743 
744 ////////////////////////////////////////////////////////////////////////////////
745 /// Print the content of the element.
746 
747 void TStreamerBase::ls(Option_t *) const
748 {
749  TString sequenceType;
750  GetSequenceType(sequenceType);
751  if (sequenceType.Length()) {
752  sequenceType.Prepend(" (");
753  sequenceType += ") ";
754  }
755  printf(" %-14s %-15s offset=%3d type=%2d %s%-20s\n",GetFullName(),GetTypeName(),fOffset,fType,sequenceType.Data(),GetTitle());
756 }
757 
758 ////////////////////////////////////////////////////////////////////////////////
759 /// Read the content of the buffer.
760 
761 Int_t TStreamerBase::ReadBuffer (TBuffer &b, char *pointer)
762 {
763  if (fConvStreamerFunc) {
764  // We have a custom Streamer member function, we must use it.
765  fConvStreamerFunc(b,pointer+fOffset,fNewBaseClass ? fBaseClass : nullptr);
766  } else if (fStreamerFunc) {
767  // We have a custom Streamer member function, we must use it.
768  fStreamerFunc(b,pointer+fOffset);
769  } else {
770  // We don't have a custom Streamer member function. That still doesn't mean
771  // that there is no streamer - it could be an external one:
772  // If the old base class has an adopted streamer we take that
773  // one instead of the new base class:
774  if( fNewBaseClass ) {
775  TClassStreamer* extstrm = fNewBaseClass->GetStreamer();
776  if (extstrm) {
777  // The new base class has an adopted streamer:
778  extstrm->SetOnFileClass(fBaseClass);
779  (*extstrm)(b, pointer);
780  } else {
781  b.ReadClassBuffer( fNewBaseClass, pointer+fOffset, fBaseClass );
782  }
783  } else {
784  TClassStreamer* extstrm = fBaseClass->GetStreamer();
785  if (extstrm) {
786  // The class has an adopted streamer:
787  (*extstrm)(b, pointer);
788  } else {
789  b.ReadClassBuffer( fBaseClass, pointer+fOffset );
790  }
791  }
792  }
793  return 0;
794 }
795 
796 ////////////////////////////////////////////////////////////////////////////////
797 /// Stream an object of class TStreamerBase.
798 
799 void TStreamerBase::Streamer(TBuffer &R__b)
800 {
801  UInt_t R__s, R__c;
802  if (R__b.IsReading()) {
803  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
804 
805  R__b.ClassBegin(TStreamerBase::Class(), R__v);
806 
807  R__b.ClassMember("TStreamerElement");
808  TStreamerElement::Streamer(R__b);
809  // If the class owning the TStreamerElement and the base class are not
810  // loaded, on the file their streamer info might be in the following
811  // order (derived class,base class) and hence the base class is not
812  // yet emulated.
813  fBaseClass = (TClass*)-1;
814  fNewBaseClass = 0;
815  // Eventually we need a v3 that stores directly fBaseCheckSum (and
816  // a version of TStreamerElement should not stored fMaxIndex)
817  if (R__v > 2) {
818  R__b.ClassMember("fBaseVersion","Int_t");
819  R__b >> fBaseVersion;
820  } else {
821  // could have been: fBaseVersion = GetClassPointer()->GetClassVersion();
822  fBaseClass = TClass::GetClass(GetName());
823  fBaseVersion = fBaseClass->GetClassVersion();
824  }
825  R__b.ClassEnd(TStreamerBase::Class());
826  R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
827  } else {
828  R__b.WriteClassBuffer(TStreamerBase::Class(),this);
829  }
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 ///Function called by the TClass constructor when replacing an emulated class
834 ///by the real class.
835 
836 void TStreamerBase::Update(const TClass *oldClass, TClass *newClass)
837 {
838  TStreamerElement::Update(oldClass, newClass);
839 
840  if (fBaseClass == oldClass) {
841  fBaseClass = newClass;
842  InitStreaming();
843  } else if (fBaseClass == nullptr) {
844  if (fName == newClass->GetName()) {
845  fBaseClass = newClass;
846  InitStreaming();
847  } else if (TClassTable::GetDict(fName)) {
848  fBaseClass = TClass::GetClass(fName);
849  InitStreaming();
850  }
851  }
852 }
853 
854 ////////////////////////////////////////////////////////////////////////////////
855 /// Write the base class into the buffer.
856 
857 Int_t TStreamerBase::WriteBuffer (TBuffer &b, char *pointer)
858 {
859  if (fStreamerFunc) {
860  // We have a custom Streamer member function, we must use it.
861  fStreamerFunc(b,pointer+fOffset);
862  } else {
863  // We don't have a custom Streamer member function. That still doesn't mean
864  // that there is no streamer - it could be an external one:
865  // If the old base class has an adopted streamer we take that
866  // one instead of the new base class:
867  if (fNewBaseClass) {
868  TClassStreamer* extstrm = fNewBaseClass->GetStreamer();
869  if (extstrm) {
870  // The new base class has an adopted streamer:
871  extstrm->SetOnFileClass(fBaseClass);
872  (*extstrm)(b, pointer);
873  return 0;
874  } else {
875  fNewBaseClass->WriteBuffer(b,pointer+fOffset);
876  return 0;
877  }
878  } else {
879  TClassStreamer* extstrm = fBaseClass->GetStreamer();
880  if (extstrm) {
881  (*extstrm)(b, pointer);
882  return 0;
883  } else {
884  fBaseClass->WriteBuffer(b,pointer+fOffset);
885  return 0;
886  }
887  }
888  }
889  return 0;
890 }
891 
892 //______________________________________________________________________________
893 
894 //////////////////////////////////////////////////////////////////////////
895 // //
896 // TStreamerBasicPointer implements the streamering of pointer to //
897 // fundamental types. //
898 // //
899 //////////////////////////////////////////////////////////////////////////
900 
901 ClassImp(TStreamerBasicPointer);
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 /// Default ctor.
905 
906 TStreamerBasicPointer::TStreamerBasicPointer() : fCountVersion(0),fCountName(),fCountClass(),fCounter(0)
907 {
908  fCounter = 0;
909 }
910 
911 ////////////////////////////////////////////////////////////////////////////////
912 /// Create a TStreamerBasicPointer object.
913 
914 TStreamerBasicPointer::TStreamerBasicPointer(const char *name, const char *title, Int_t offset, Int_t dtype, const char *countName, const char *countClass, Int_t countVersion, const char *typeName)
915  : TStreamerElement(name,title,offset,dtype,typeName)
916 {
917  fType += TVirtualStreamerInfo::kOffsetP;
918  fCountName = countName;
919  fCountClass = countClass;
920  fCountVersion = countVersion; //currently unused
921  Init();
922 // printf("BasicPointer Init:%s, countName=%s, countClass=%s, countVersion=%d, fCounter=%x\n",
923 // name,countName,countClass,countVersion,fCounter);
924 }
925 
926 ////////////////////////////////////////////////////////////////////////////////
927 /// TStreamerBasicPointer dtor.
928 
929 TStreamerBasicPointer::~TStreamerBasicPointer()
930 {
931 }
932 
933 ////////////////////////////////////////////////////////////////////////////////
934 /// return offset of counter
935 
936 ULong_t TStreamerBasicPointer::GetMethod() const
937 {
938  if (!fCounter) ((TStreamerBasicPointer*)this)->Init();
939  if (!fCounter) return 0;
940  // FIXME: does not suport multiple inheritance for counter in base class.
941  // This is wrong in case counter is not in the same class or one of
942  // the left most (non virtual) base classes. For the other we would
943  // really need to use the object coming from the list of real data.
944  // (and even that need analysis for virtual base class).
945  return (ULong_t)fCounter->GetOffset();
946 }
947 
948 ////////////////////////////////////////////////////////////////////////////////
949 /// Returns size of basicpointer in bytes.
950 
951 Int_t TStreamerBasicPointer::GetSize() const
952 {
953  if (fArrayLength) return fArrayLength*sizeof(void *);
954  return sizeof(void *);
955 }
956 
957 ////////////////////////////////////////////////////////////////////////////////
958 /// Setup the element.
959 /// If directive is a StreamerInfo and it correspond to the
960 /// same class a 'countClass' the streamerInfo is used instead of the current StreamerInfo of the TClass
961 /// for 'countClass'.
962 
963 void TStreamerBasicPointer::Init(TVirtualStreamerInfo *directive)
964 {
965  fCounter = InitCounter( fCountClass, fCountName, directive );
966 }
967 
968 ////////////////////////////////////////////////////////////////////////////////
969 /// Set number of array dimensions.
970 
971 void TStreamerBasicPointer::SetArrayDim(Int_t dim)
972 {
973  fArrayDim = dim;
974  //if (dim) fType += TVirtualStreamerInfo::kOffsetL;
975  fNewType = fType;
976 }
977 
978 ////////////////////////////////////////////////////////////////////////////////
979 /// Stream an object of class TStreamerBasicPointer.
980 
981 void TStreamerBasicPointer::Streamer(TBuffer &R__b)
982 {
983  UInt_t R__s, R__c;
984  if (R__b.IsReading()) {
985  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
986  if (R__v > 1) {
987  R__b.ReadClassBuffer(TStreamerBasicPointer::Class(), this, R__v, R__s, R__c);
988  //Init();
989  //fCounter = InitCounter( fCountClass, fCountName );
990  return;
991  }
992  //====process old versions before automatic schema evolution
993  TStreamerElement::Streamer(R__b);
994  R__b >> fCountVersion;
995  fCountName.Streamer(R__b);
996  fCountClass.Streamer(R__b);
997  R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
998  } else {
999  R__b.WriteClassBuffer(TStreamerBasicPointer::Class(),this);
1000  }
1001 }
1002 
1003 
1004 //______________________________________________________________________________
1005 
1006 //////////////////////////////////////////////////////////////////////////
1007 // //
1008 // TStreamerLoop implement streaming of a few construct that require //
1009 // looping over the data member and are not convered by other case //
1010 // (most deprecated). //
1011 // //
1012 //////////////////////////////////////////////////////////////////////////
1013 
1014 ClassImp(TStreamerLoop);
1015 
1016 ////////////////////////////////////////////////////////////////////////////////
1017 /// Default ctor.
1018 
1019 TStreamerLoop::TStreamerLoop() : fCountVersion(0),fCountName(),fCountClass(),fCounter(0)
1020 {
1021 }
1022 
1023 ////////////////////////////////////////////////////////////////////////////////
1024 /// Create a TStreamerLoop object.
1025 
1026 TStreamerLoop::TStreamerLoop(const char *name, const char *title, Int_t offset, const char *countName, const char *countClass, Int_t countVersion, const char *typeName)
1027  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kStreamLoop,typeName)
1028 {
1029  fCountName = countName;
1030  fCountClass = countClass;
1031  fCountVersion = countVersion; //currently unused
1032  Init();
1033 }
1034 
1035 ////////////////////////////////////////////////////////////////////////////////
1036 /// TStreamerLoop dtor.
1037 
1038 TStreamerLoop::~TStreamerLoop()
1039 {
1040 }
1041 
1042 ////////////////////////////////////////////////////////////////////////////////
1043 /// return address of counter
1044 
1045 ULong_t TStreamerLoop::GetMethod() const
1046 {
1047  //if (!fCounter) {
1048  // Init();
1049  // if (!fCounter) return 0;
1050  //}
1051  if (!fCounter) return 0;
1052  return (ULong_t)fCounter->GetOffset();
1053 }
1054 
1055 ////////////////////////////////////////////////////////////////////////////////
1056 /// Returns size of counter in bytes.
1057 
1058 Int_t TStreamerLoop::GetSize() const
1059 {
1060  if (fArrayLength) return fArrayLength*sizeof(void*);
1061  return sizeof(void*);
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// Setup the element.
1066 /// If directive is a StreamerInfo and it correspond to the
1067 /// same class a 'countClass' the streamerInfo is used instead of the current StreamerInfo of the TClass
1068 /// for 'countClass'.
1069 
1070 void TStreamerLoop::Init(TVirtualStreamerInfo *directive)
1071 {
1072  fCounter = InitCounter( fCountClass, fCountName, directive );
1073 }
1074 
1075 ////////////////////////////////////////////////////////////////////////////////
1076 /// Return the proper include for this element.
1077 
1078 const char *TStreamerLoop::GetInclude() const
1079 {
1080  IncludeNameBuffer().Form("<%s>","TString.h"); //to be generalized
1081  return IncludeNameBuffer();
1082 }
1083 
1084 ////////////////////////////////////////////////////////////////////////////////
1085 /// Stream an object of class TStreamerLoop.
1086 
1087 void TStreamerLoop::Streamer(TBuffer &R__b)
1088 {
1089  UInt_t R__s, R__c;
1090  if (R__b.IsReading()) {
1091  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1092  if (R__v > 1) {
1093  R__b.ReadClassBuffer(TStreamerLoop::Class(), this, R__v, R__s, R__c);
1094  //Init();
1095  return;
1096  }
1097  //====process old versions before automatic schema evolution
1098  TStreamerElement::Streamer(R__b);
1099  R__b >> fCountVersion;
1100  fCountName.Streamer(R__b);
1101  fCountClass.Streamer(R__b);
1102  R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
1103  } else {
1104  R__b.WriteClassBuffer(TStreamerLoop::Class(),this);
1105  }
1106 }
1107 
1108 
1109 //______________________________________________________________________________
1110 
1111 //////////////////////////////////////////////////////////////////////////
1112 // //
1113 // TStreamerBasicType implement streaming of fundamental types (int, //
1114 // float, etc.). //
1115 // //
1116 //////////////////////////////////////////////////////////////////////////
1117 
1118 ClassImp(TStreamerBasicType);
1119 
1120 ////////////////////////////////////////////////////////////////////////////////
1121 /// Default ctor.
1122 
1123 TStreamerBasicType::TStreamerBasicType() : fCounter(0)
1124 {
1125 }
1126 
1127 ////////////////////////////////////////////////////////////////////////////////
1128 /// Create a TStreamerBasicType object.
1129 
1130 TStreamerBasicType::TStreamerBasicType(const char *name, const char *title, Int_t offset, Int_t dtype, const char *typeName)
1131  : TStreamerElement(name,title,offset,dtype,typeName),fCounter(0)
1132 {
1133 }
1134 
1135 ////////////////////////////////////////////////////////////////////////////////
1136 /// TStreamerBasicType dtor.
1137 
1138 TStreamerBasicType::~TStreamerBasicType()
1139 {
1140 }
1141 
1142 ////////////////////////////////////////////////////////////////////////////////
1143 /// return address of counter
1144 
1145 ULong_t TStreamerBasicType::GetMethod() const
1146 {
1147  if (fType == TVirtualStreamerInfo::kCounter ||
1148  fType == (TVirtualStreamerInfo::kCounter+TVirtualStreamerInfo::kSkip)) return (ULong_t)&fCounter;
1149  return 0;
1150 }
1151 
1152 ////////////////////////////////////////////////////////////////////////////////
1153 /// Returns size of this element in bytes.
1154 
1155 Int_t TStreamerBasicType::GetSize() const
1156 {
1157  return fSize;
1158 }
1159 
1160 ////////////////////////////////////////////////////////////////////////////////
1161 /// Stream an object of class TStreamerBasicType.
1162 
1163 void TStreamerBasicType::Streamer(TBuffer &R__b)
1164 {
1165  UInt_t R__s, R__c;
1166  if (R__b.IsReading()) {
1167  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1168  if (R__v > 1) {
1169  R__b.ReadClassBuffer(TStreamerBasicType::Class(), this, R__v, R__s, R__c);
1170  } else {
1171  //====process old versions before automatic schema evolution
1172  TStreamerElement::Streamer(R__b);
1173  R__b.CheckByteCount(R__s, R__c, TStreamerBasicType::IsA());
1174  }
1175  Int_t type = fType;
1176  if (TVirtualStreamerInfo::kOffsetL < type && type < TVirtualStreamerInfo::kOffsetP) {
1177  type -= TVirtualStreamerInfo::kOffsetL;
1178  }
1179  switch(type) {
1180  // basic types
1181  case TVirtualStreamerInfo::kBool: fSize = sizeof(Bool_t); break;
1182  case TVirtualStreamerInfo::kShort: fSize = sizeof(Short_t); break;
1183  case TVirtualStreamerInfo::kInt: fSize = sizeof(Int_t); break;
1184  case TVirtualStreamerInfo::kLong: fSize = sizeof(Long_t); break;
1185  case TVirtualStreamerInfo::kLong64: fSize = sizeof(Long64_t); break;
1186  case TVirtualStreamerInfo::kFloat: fSize = sizeof(Float_t); break;
1187  case TVirtualStreamerInfo::kFloat16: fSize = sizeof(Float_t); break;
1188  case TVirtualStreamerInfo::kDouble: fSize = sizeof(Double_t); break;
1189  case TVirtualStreamerInfo::kDouble32: fSize = sizeof(Double_t); break;
1190  case TVirtualStreamerInfo::kUChar: fSize = sizeof(UChar_t); break;
1191  case TVirtualStreamerInfo::kUShort: fSize = sizeof(UShort_t); break;
1192  case TVirtualStreamerInfo::kUInt: fSize = sizeof(UInt_t); break;
1193  case TVirtualStreamerInfo::kULong: fSize = sizeof(ULong_t); break;
1194  case TVirtualStreamerInfo::kULong64: fSize = sizeof(ULong64_t); break;
1195  case TVirtualStreamerInfo::kBits: fSize = sizeof(UInt_t); break;
1196  case TVirtualStreamerInfo::kCounter: fSize = sizeof(Int_t); break;
1197  case TVirtualStreamerInfo::kChar: fSize = sizeof(Char_t); break;
1198  case TVirtualStreamerInfo::kCharStar: fSize = sizeof(Char_t*); break;
1199  default: return; // If we don't change the size let's not remultiply it.
1200  }
1201  if (fArrayLength) fSize *= GetArrayLength();
1202  } else {
1203  R__b.WriteClassBuffer(TStreamerBasicType::Class(),this);
1204  }
1205 }
1206 
1207 
1208 
1209 //______________________________________________________________________________
1210 
1211 //////////////////////////////////////////////////////////////////////////
1212 // //
1213 // TStreamerObject implements streaming of embedded objects whose type //
1214 // inherits from TObject. //
1215 // //
1216 //////////////////////////////////////////////////////////////////////////
1217 
1218 ClassImp(TStreamerObject);
1219 
1220 ////////////////////////////////////////////////////////////////////////////////
1221 /// Default ctor.
1222 
1223 TStreamerObject::TStreamerObject()
1224 {
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// Create a TStreamerObject object.
1229 
1230 TStreamerObject::TStreamerObject(const char *name, const char *title, Int_t offset, const char *typeName)
1231  : TStreamerElement(name,title,offset,0,typeName)
1232 {
1233  fType = TVirtualStreamerInfo::kObject;
1234  if (strcmp(typeName,"TObject") == 0) fType = TVirtualStreamerInfo::kTObject;
1235  if (strcmp(typeName,"TNamed") == 0) fType = TVirtualStreamerInfo::kTNamed;
1236  fNewType = fType;
1237  Init();
1238 }
1239 
1240 ////////////////////////////////////////////////////////////////////////////////
1241 /// TStreamerObject dtor.
1242 
1243 TStreamerObject::~TStreamerObject()
1244 {
1245 }
1246 
1247 ////////////////////////////////////////////////////////////////////////////////
1248 /// Setup the element.
1249 
1250 void TStreamerObject::Init(TVirtualStreamerInfo *)
1251 {
1252  fClassObject = GetClassPointer();
1253  if (fClassObject && fClassObject->IsTObject()) {
1254  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
1255  }
1256 }
1257 
1258 ////////////////////////////////////////////////////////////////////////////////
1259 /// Return the proper include for this element.
1260 
1261 const char *TStreamerObject::GetInclude() const
1262 {
1263  TClass *cl = GetClassPointer();
1264  if (cl && cl->HasInterpreterInfo()) {
1265  IncludeNameBuffer().Form("\"%s\"",cl->GetDeclFileName());
1266  } else {
1267  std::string shortname( TClassEdit::ShortType( GetTypeName(), 1 ) );
1268  IncludeNameBuffer().Form("\"%s.h\"",shortname.c_str());
1269  }
1270  return IncludeNameBuffer();
1271 }
1272 
1273 ////////////////////////////////////////////////////////////////////////////////
1274 /// Returns size of object class in bytes.
1275 
1276 Int_t TStreamerObject::GetSize() const
1277 {
1278  TClass *cl = GetClassPointer();
1279  Int_t classSize = 8;
1280  if (cl) classSize = cl->Size();
1281  if (fArrayLength) return fArrayLength*classSize;
1282  return classSize;
1283 }
1284 
1285 ////////////////////////////////////////////////////////////////////////////////
1286 /// Stream an object of class TStreamerObject.
1287 
1288 void TStreamerObject::Streamer(TBuffer &R__b)
1289 {
1290  UInt_t R__s, R__c;
1291  if (R__b.IsReading()) {
1292  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1293  if (R__v > 1) {
1294  R__b.ReadClassBuffer(TStreamerObject::Class(), this, R__v, R__s, R__c);
1295  return;
1296  }
1297  //====process old versions before automatic schema evolution
1298  TStreamerElement::Streamer(R__b);
1299  R__b.CheckByteCount(R__s, R__c, TStreamerObject::IsA());
1300  } else {
1301  R__b.WriteClassBuffer(TStreamerObject::Class(),this);
1302  }
1303 }
1304 
1305 
1306 //______________________________________________________________________________
1307 
1308 //////////////////////////////////////////////////////////////////////////
1309 // //
1310 // TStreamerObjectAny implement streaming of embedded object not //
1311 // inheriting from TObject. //
1312 // //
1313 //////////////////////////////////////////////////////////////////////////
1314 
1315 ClassImp(TStreamerObjectAny);
1316 
1317 ////////////////////////////////////////////////////////////////////////////////
1318 /// Default ctor.
1319 
1320 TStreamerObjectAny::TStreamerObjectAny()
1321 {
1322 }
1323 
1324 ////////////////////////////////////////////////////////////////////////////////
1325 /// Create a TStreamerObjectAny object.
1326 
1327 TStreamerObjectAny::TStreamerObjectAny(const char *name, const char *title, Int_t offset, const char *typeName)
1328  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kAny,typeName)
1329 {
1330  Init();
1331 }
1332 
1333 ////////////////////////////////////////////////////////////////////////////////
1334 /// TStreamerObjectAny dtor.
1335 
1336 TStreamerObjectAny::~TStreamerObjectAny()
1337 {
1338 }
1339 
1340 ////////////////////////////////////////////////////////////////////////////////
1341 /// Setup the element.
1342 
1343 void TStreamerObjectAny::Init(TVirtualStreamerInfo *)
1344 {
1345  fClassObject = GetClassPointer();
1346  if (fClassObject && fClassObject->IsTObject()) {
1347  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
1348  }
1349 }
1350 
1351 ////////////////////////////////////////////////////////////////////////////////
1352 /// Return the proper include for this element.
1353 
1354 const char *TStreamerObjectAny::GetInclude() const
1355 {
1356  TClass *cl = GetClassPointer();
1357  if (cl && cl->HasInterpreterInfo()) {
1358  IncludeNameBuffer().Form("\"%s\"",cl->GetDeclFileName());
1359  } else {
1360  std::string shortname( TClassEdit::ShortType( GetTypeName(), 1 ) );
1361  IncludeNameBuffer().Form("\"%s.h\"",shortname.c_str());
1362  }
1363  return IncludeNameBuffer();
1364 }
1365 
1366 ////////////////////////////////////////////////////////////////////////////////
1367 /// Returns size of anyclass in bytes.
1368 
1369 Int_t TStreamerObjectAny::GetSize() const
1370 {
1371  TClass *cl = GetClassPointer();
1372  Int_t classSize = 8;
1373  if (cl) classSize = cl->Size();
1374  if (fArrayLength) return fArrayLength*classSize;
1375  return classSize;
1376 }
1377 
1378 ////////////////////////////////////////////////////////////////////////////////
1379 /// Stream an object of class TStreamerObjectAny.
1380 
1381 void TStreamerObjectAny::Streamer(TBuffer &R__b)
1382 {
1383  UInt_t R__s, R__c;
1384  if (R__b.IsReading()) {
1385  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1386  if (R__v > 1) {
1387  R__b.ReadClassBuffer(TStreamerObjectAny::Class(), this, R__v, R__s, R__c);
1388  return;
1389  }
1390  //====process old versions before automatic schema evolution
1391  TStreamerElement::Streamer(R__b);
1392  R__b.CheckByteCount(R__s, R__c, TStreamerObjectAny::IsA());
1393  } else {
1394  R__b.WriteClassBuffer(TStreamerObjectAny::Class(),this);
1395  }
1396 }
1397 
1398 
1399 
1400 //______________________________________________________________________________
1401 
1402 //////////////////////////////////////////////////////////////////////////
1403 // //
1404 // TStreamerObjectPointer implements streaming of pointer to object //
1405 // inheriting from TObject. //
1406 // //
1407 //////////////////////////////////////////////////////////////////////////
1408 
1409 ClassImp(TStreamerObjectPointer);
1410 
1411 ////////////////////////////////////////////////////////////////////////////////
1412 /// Default ctor.
1413 
1414 TStreamerObjectPointer::TStreamerObjectPointer()
1415 {
1416 }
1417 
1418 ////////////////////////////////////////////////////////////////////////////////
1419 /// Create a TStreamerObjectPointer object.
1420 
1421 TStreamerObjectPointer::TStreamerObjectPointer(const char *name, const char *title,
1422  Int_t offset, const char *typeName)
1423  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kObjectP,typeName)
1424 {
1425  if (strncmp(title,"->",2) == 0) fType = TVirtualStreamerInfo::kObjectp;
1426  fNewType = fType;
1427  Init();
1428 }
1429 
1430 ////////////////////////////////////////////////////////////////////////////////
1431 /// TStreamerObjectPointer dtor.
1432 
1433 TStreamerObjectPointer::~TStreamerObjectPointer()
1434 {
1435 }
1436 
1437 ////////////////////////////////////////////////////////////////////////////////
1438 /// Setup the element.
1439 
1440 void TStreamerObjectPointer::Init(TVirtualStreamerInfo *)
1441 {
1442  fClassObject = GetClassPointer();
1443  if (fClassObject && fClassObject->IsTObject()) {
1444  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
1445  }
1446 }
1447 
1448 ////////////////////////////////////////////////////////////////////////////////
1449 /// Return the proper include for this element.
1450 
1451 const char *TStreamerObjectPointer::GetInclude() const
1452 {
1453  TClass *cl = GetClassPointer();
1454  if (cl && cl->HasInterpreterInfo()) {
1455  IncludeNameBuffer().Form("\"%s\"",cl->GetDeclFileName());
1456  } else {
1457  std::string shortname( TClassEdit::ShortType( GetTypeName(), 1 ) );
1458  IncludeNameBuffer().Form("\"%s.h\"",shortname.c_str());
1459  }
1460 
1461  return IncludeNameBuffer();
1462 }
1463 
1464 ////////////////////////////////////////////////////////////////////////////////
1465 /// Returns size of objectpointer in bytes.
1466 
1467 Int_t TStreamerObjectPointer::GetSize() const
1468 {
1469  if (fArrayLength) return fArrayLength*sizeof(void *);
1470  return sizeof(void *);
1471 }
1472 
1473 ////////////////////////////////////////////////////////////////////////////////
1474 /// Set number of array dimensions.
1475 
1476 void TStreamerObjectPointer::SetArrayDim(Int_t dim)
1477 {
1478  fArrayDim = dim;
1479  //if (dim) fType += TVirtualStreamerInfo::kOffsetL;
1480  fNewType = fType;
1481 }
1482 
1483 ////////////////////////////////////////////////////////////////////////////////
1484 /// Stream an object of class TStreamerObjectPointer.
1485 
1486 void TStreamerObjectPointer::Streamer(TBuffer &R__b)
1487 {
1488  UInt_t R__s, R__c;
1489  if (R__b.IsReading()) {
1490  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1491  if (R__v > 1) {
1492  R__b.ReadClassBuffer(TStreamerObjectPointer::Class(), this, R__v, R__s, R__c);
1493  return;
1494  }
1495  //====process old versions before automatic schema evolution
1496  TStreamerElement::Streamer(R__b);
1497  R__b.CheckByteCount(R__s, R__c, TStreamerObjectPointer::IsA());
1498  } else {
1499  R__b.WriteClassBuffer(TStreamerObjectPointer::Class(),this);
1500  }
1501 }
1502 
1503 
1504 //______________________________________________________________________________
1505 
1506 //////////////////////////////////////////////////////////////////////////
1507 // //
1508 // TStreamerObjectPointerAny implements streaming of pointer to object //
1509 // not inheriting from TObject. //
1510 // //
1511 //////////////////////////////////////////////////////////////////////////
1512 
1513 ClassImp(TStreamerObjectAnyPointer);
1514 
1515 ////////////////////////////////////////////////////////////////////////////////
1516 /// Default ctor.
1517 
1518 TStreamerObjectAnyPointer::TStreamerObjectAnyPointer()
1519 {
1520 }
1521 
1522 ////////////////////////////////////////////////////////////////////////////////
1523 /// Create a TStreamerObjectAnyPointer object.
1524 
1525 TStreamerObjectAnyPointer::TStreamerObjectAnyPointer(const char *name, const char *title,
1526  Int_t offset, const char *typeName)
1527  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kAnyP,typeName)
1528 {
1529  if (strncmp(title,"->",2) == 0) fType = TVirtualStreamerInfo::kAnyp;
1530  fNewType = fType;
1531  Init();
1532 }
1533 
1534 ////////////////////////////////////////////////////////////////////////////////
1535 /// TStreamerObjectAnyPointer dtor.
1536 
1537 TStreamerObjectAnyPointer::~TStreamerObjectAnyPointer()
1538 {
1539 }
1540 
1541 ////////////////////////////////////////////////////////////////////////////////
1542 /// Setup the element.
1543 
1544 void TStreamerObjectAnyPointer::Init(TVirtualStreamerInfo *)
1545 {
1546  fClassObject = GetClassPointer();
1547  if (fClassObject && fClassObject->IsTObject()) {
1548  fTObjectOffset = fClassObject->GetBaseClassOffset(TObject::Class());
1549  }
1550 }
1551 
1552 ////////////////////////////////////////////////////////////////////////////////
1553 /// Return the proper include for this element.
1554 
1555 const char *TStreamerObjectAnyPointer::GetInclude() const
1556 {
1557  TClass *cl = GetClassPointer();
1558  if (cl && cl->HasInterpreterInfo()) {
1559  IncludeNameBuffer().Form("\"%s\"",cl->GetDeclFileName());
1560  } else {
1561  std::string shortname( TClassEdit::ShortType( GetTypeName(), 1 ) );
1562  IncludeNameBuffer().Form("\"%s.h\"",shortname.c_str());
1563  }
1564 
1565  return IncludeNameBuffer();
1566 }
1567 
1568 ////////////////////////////////////////////////////////////////////////////////
1569 /// Returns size of objectpointer in bytes.
1570 
1571 Int_t TStreamerObjectAnyPointer::GetSize() const
1572 {
1573  if (fArrayLength) return fArrayLength*sizeof(void *);
1574  return sizeof(void *);
1575 }
1576 
1577 ////////////////////////////////////////////////////////////////////////////////
1578 /// Set number of array dimensions.
1579 
1580 void TStreamerObjectAnyPointer::SetArrayDim(Int_t dim)
1581 {
1582  fArrayDim = dim;
1583  //if (dim) fType += TVirtualStreamerInfo::kOffsetL;
1584  fNewType = fType;
1585 }
1586 
1587 ////////////////////////////////////////////////////////////////////////////////
1588 /// Stream an object of class TStreamerObjectAnyPointer.
1589 
1590 void TStreamerObjectAnyPointer::Streamer(TBuffer &R__b)
1591 {
1592  if (R__b.IsReading()) {
1593  R__b.ReadClassBuffer(TStreamerObjectAnyPointer::Class(), this);
1594  } else {
1595  R__b.WriteClassBuffer(TStreamerObjectAnyPointer::Class(),this);
1596  }
1597 }
1598 
1599 
1600 //______________________________________________________________________________
1601 
1602 //////////////////////////////////////////////////////////////////////////
1603 // //
1604 // TSreamerString implements streaming of TString. //
1605 // //
1606 //////////////////////////////////////////////////////////////////////////
1607 
1608 ClassImp(TStreamerString);
1609 
1610 ////////////////////////////////////////////////////////////////////////////////
1611 /// Default ctor.
1612 
1613 TStreamerString::TStreamerString()
1614 {
1615 }
1616 
1617 ////////////////////////////////////////////////////////////////////////////////
1618 /// Create a TStreamerString object.
1619 
1620 TStreamerString::TStreamerString(const char *name, const char *title, Int_t offset)
1621  : TStreamerElement(name,title,offset,TVirtualStreamerInfo::kTString,"TString")
1622 {
1623 }
1624 
1625 ////////////////////////////////////////////////////////////////////////////////
1626 /// TStreamerString dtor.
1627 
1628 TStreamerString::~TStreamerString()
1629 {
1630 }
1631 
1632 ////////////////////////////////////////////////////////////////////////////////
1633 /// Return the proper include for this element.
1634 
1635 const char *TStreamerString::GetInclude() const
1636 {
1637  IncludeNameBuffer().Form("<%s>","TString.h");
1638  return IncludeNameBuffer();
1639 }
1640 
1641 ////////////////////////////////////////////////////////////////////////////////
1642 /// Returns size of anyclass in bytes.
1643 
1644 Int_t TStreamerString::GetSize() const
1645 {
1646  if (fArrayLength) return fArrayLength*sizeof(TString);
1647  return sizeof(TString);
1648 }
1649 
1650 ////////////////////////////////////////////////////////////////////////////////
1651 /// Stream an object of class TStreamerString.
1652 
1653 void TStreamerString::Streamer(TBuffer &R__b)
1654 {
1655  UInt_t R__s, R__c;
1656  if (R__b.IsReading()) {
1657  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1658  if (R__v > 1) {
1659  R__b.ReadClassBuffer(TStreamerString::Class(), this, R__v, R__s, R__c);
1660  return;
1661  }
1662  //====process old versions before automatic schema evolution
1663  TStreamerElement::Streamer(R__b);
1664  R__b.CheckByteCount(R__s, R__c, TStreamerString::IsA());
1665  } else {
1666  R__b.WriteClassBuffer(TStreamerString::Class(),this);
1667  }
1668 }
1669 
1670 //______________________________________________________________________________
1671 
1672 //////////////////////////////////////////////////////////////////////////
1673 // //
1674 // TStreamerSTL implements streamer of STL container. //
1675 // //
1676 //////////////////////////////////////////////////////////////////////////
1677 
1678 ClassImp(TStreamerSTL);
1679 
1680 ////////////////////////////////////////////////////////////////////////////////
1681 /// Default ctor.
1682 
1683 TStreamerSTL::TStreamerSTL() : fSTLtype(0),fCtype(0)
1684 {
1685 }
1686 
1687 ////////////////////////////////////////////////////////////////////////////////
1688 /// Create a TStreamerSTL object.
1689 
1690 TStreamerSTL::TStreamerSTL(const char *name, const char *title, Int_t offset,
1691  const char *typeName, const TVirtualCollectionProxy &proxy, Bool_t dmPointer)
1692  : TStreamerElement(name,title,offset,ROOT::kSTLany,typeName)
1693 {
1694  fTypeName = TClassEdit::ShortType(fTypeName,TClassEdit::kDropStlDefault).c_str();
1695 
1696  if (name==typeName /* intentional pointer comparison */
1697  || strcmp(name,typeName)==0) {
1698  // We have a base class.
1699  fName = fTypeName;
1700  }
1701  fSTLtype = proxy.GetCollectionType();
1702  fCtype = 0;
1703 
1704  if (dmPointer) fSTLtype += TVirtualStreamerInfo::kOffsetP;
1705 
1706  if (fSTLtype == ROOT::kSTLbitset) {
1707  // Nothing to check
1708  } else if (proxy.GetValueClass()) {
1709  if (proxy.HasPointers()) fCtype = TVirtualStreamerInfo::kObjectp;
1710  else fCtype = TVirtualStreamerInfo::kObject;
1711  } else {
1712  fCtype = proxy.GetType();
1713  if (proxy.HasPointers()) fCtype += TVirtualStreamerInfo::kOffsetP;
1714  }
1715  if (TStreamerSTL::IsaPointer()) fType = TVirtualStreamerInfo::kSTLp;
1716 }
1717 
1718 ////////////////////////////////////////////////////////////////////////////////
1719 /// Create a TStreamerSTL object.
1720 
1721 TStreamerSTL::TStreamerSTL(const char *name, const char *title, Int_t offset,
1722  const char *typeName, const char *trueType, Bool_t dmPointer)
1723  : TStreamerElement(name,title,offset,ROOT::kSTLany,typeName)
1724 {
1725  const char *t = trueType;
1726  if (!t || !*t) t = typeName;
1727 
1728  fTypeName = TClassEdit::ShortType(fTypeName,TClassEdit::kDropStlDefault).c_str();
1729 
1730  if (name==typeName /* intentional pointer comparison */
1731  || strcmp(name,typeName)==0) {
1732  // We have a base class.
1733  fName = fTypeName;
1734  }
1735 
1736  Int_t nch = strlen(t);
1737  char *s = new char[nch+1];
1738  strlcpy(s,t,nch+1);
1739  char *sopen = strchr(s,'<');
1740  if (sopen == 0) {
1741  Fatal("TStreamerSTL","For %s, the type name (%s) is seemingly not a template (template argument not found)", name, s);
1742  return;
1743  }
1744  *sopen = 0; sopen++;
1745  // We are looking for the first arguments of the STL container, because
1746  // this arguments can be a templates we need to count the < and >
1747  char* current=sopen;
1748  for(int count = 0; *current!='\0'; current++) {
1749  if (*current=='<') count++;
1750  if (*current=='>') {
1751  if (count==0) break;
1752  count--;
1753  }
1754  if (*current==',' && count==0) break;
1755  }
1756  char *sclose = current; *sclose = 0; sclose--;
1757  char *sconst = strstr(sopen,"const ");
1758  char *sbracket = strstr(sopen,"<");
1759  if (sconst && (sbracket==0 || sconst < sbracket)) {
1760  // the string "const" may be part of the classname!
1761  char *pconst = sconst-1;
1762  if (*pconst == ' ' || *pconst == '<' || *pconst == '*' || *pconst == '\0') sopen = sconst + 5;
1763  }
1764  fSTLtype = TClassEdit::STLKind(s);
1765  fCtype = 0;
1766  if (fSTLtype == ROOT::kNotSTL) { delete [] s; return;}
1767  if (dmPointer) fSTLtype += TVirtualStreamerInfo::kOffsetP;
1768 
1769  // find STL contained type
1770  while (*sopen==' ') sopen++;
1771  Bool_t isPointer = kFALSE;
1772  // Find stars outside of any template definitions in the
1773  // first template argument.
1774  char *star = strrchr(sopen,'>');
1775  if (star) star = strchr(star,'*');
1776  else star = strchr(sopen,'*');
1777  if (star) {
1778  isPointer = kTRUE;
1779  *star = 0;
1780  sclose = star - 1;
1781  }
1782  while (*sclose == ' ') {*sclose = 0; sclose--;}
1783 
1784 
1785  TDataType *dt = (TDataType*)gROOT->GetListOfTypes()->FindObject(sopen);
1786  if (fSTLtype == ROOT::kSTLbitset) {
1787  // Nothing to check
1788  } else if (dt) {
1789  fCtype = dt->GetType();
1790  if (isPointer) fCtype += TVirtualStreamerInfo::kOffsetP;
1791  } else {
1792  // this could also be a nested enums ... which should work ... be let's see.
1793  TClass *cl = TClass::GetClass(sopen);
1794  if (cl) {
1795  if (isPointer) fCtype = TVirtualStreamerInfo::kObjectp;
1796  else fCtype = TVirtualStreamerInfo::kObject;
1797  } else {
1798  if (gCling->ClassInfo_IsEnum(sopen)) {
1799  if (isPointer) fCtype += TVirtualStreamerInfo::kOffsetP;
1800  } else {
1801  if(strcmp(sopen,"string")) {
1802  // This case can happens when 'this' is a TStreamerElement for
1803  // a STL container containing something for which we do not have
1804  // a TVirtualStreamerInfo (This happens in particular is the collection
1805  // objects themselves are always empty) and we do not have the
1806  // dictionary/shared library for the container.
1807  if (GetClassPointer() && GetClassPointer()->IsLoaded()) {
1808  Warning("TStreamerSTL","For %s we could not find any information about the type %s %d %s",fTypeName.Data(),sopen,fSTLtype,s);
1809  }
1810  }
1811  }
1812  }
1813  }
1814  delete [] s;
1815 
1816  if (TStreamerSTL::IsaPointer()) fType = TVirtualStreamerInfo::kSTLp;
1817 }
1818 
1819 ////////////////////////////////////////////////////////////////////////////////
1820 /// TStreamerSTL dtor.
1821 
1822 TStreamerSTL::~TStreamerSTL()
1823 {
1824 }
1825 
1826 ////////////////////////////////////////////////////////////////////////////////
1827 /// We can not split STL's which are inside a variable size array.
1828 /// At least for now.
1829 
1830 Bool_t TStreamerSTL::CannotSplit() const
1831 {
1832  if (IsaPointer()) {
1833  if (GetTitle()[0]=='[') return kTRUE; // can not split variable size array
1834  return kTRUE;
1835  }
1836 
1837  if (GetArrayDim()>=1 && GetArrayLength()>1) return kTRUE;
1838 
1839  if (TStreamerElement::CannotSplit()) return kTRUE;
1840 
1841  return kFALSE;
1842 }
1843 
1844 ////////////////////////////////////////////////////////////////////////////////
1845 /// Return true if the data member is a pointer.
1846 
1847 Bool_t TStreamerSTL::IsaPointer() const
1848 {
1849  const char *type_name = GetTypeName();
1850  if ( type_name[strlen(type_name)-1]=='*' ) return kTRUE;
1851  else return kFALSE;
1852 }
1853 
1854 
1855 ////////////////////////////////////////////////////////////////////////////////
1856 /// Return kTRUE if the element represent a base class.
1857 
1858 Bool_t TStreamerSTL::IsBase() const
1859 {
1860  TString ts(GetName());
1861 
1862  if (strcmp(ts.Data(),GetTypeName())==0) return kTRUE;
1863  if (strcmp(ts.Data(),GetTypeNameBasic())==0) return kTRUE;
1864  return kFALSE;
1865 }
1866 ////////////////////////////////////////////////////////////////////////////////
1867 /// Returns size of STL container in bytes.
1868 
1869 Int_t TStreamerSTL::GetSize() const
1870 {
1871  // Since the STL collection might or might not be emulated and that the
1872  // sizeof the object depends on this, let's just always retrieve the
1873  // current size!
1874  TClass *cl = GetClassPointer();
1875  UInt_t size = 0;
1876  if (cl==0) {
1877  if (!TestBit(kWarned)) {
1878  Error("GetSize","Could not find the TClass for %s.\n"
1879  "This is likely to have been a typedef, if possible please declare it in CINT to work around the issue\n",fTypeName.Data());
1880  const_cast<TStreamerSTL*>(this)->SetBit(kWarned);
1881  }
1882  } else {
1883  size = cl->Size();
1884  }
1885 
1886  if (fArrayLength) return fArrayLength*size;
1887  return size;
1888 }
1889 
1890 ////////////////////////////////////////////////////////////////////////////////
1891 /// Print the content of the element.
1892 
1893 void TStreamerSTL::ls(Option_t *) const
1894 {
1895  TString name(kMaxLen);
1896  TString cdim;
1897  name = GetName();
1898  for (Int_t i=0;i<fArrayDim;i++) {
1899  cdim.Form("[%d]",fMaxIndex[i]);
1900  name += cdim;
1901  }
1902  TString sequenceType;
1903  GetSequenceType(sequenceType);
1904  if (sequenceType.Length()) {
1905  sequenceType.Prepend(" (");
1906  sequenceType += ") ";
1907  }
1908  printf(" %-14s %-15s offset=%3d type=%2d %s,stl=%d, ctype=%d, %-20s\n",
1909  GetTypeName(),name.Data(),fOffset,fType,sequenceType.Data(),
1910  fSTLtype,fCtype,GetTitle());
1911 }
1912 
1913 ////////////////////////////////////////////////////////////////////////////////
1914 /// Return the proper include for this element.
1915 
1916 const char *TStreamerSTL::GetInclude() const
1917 {
1918  if (fSTLtype == ROOT::kSTLvector) IncludeNameBuffer().Form("<%s>","vector");
1919  else if (fSTLtype == ROOT::kSTLlist) IncludeNameBuffer().Form("<%s>","list");
1920  else if (fSTLtype == ROOT::kSTLforwardlist) IncludeNameBuffer().Form("<%s>","forward_list");
1921  else if (fSTLtype == ROOT::kSTLdeque) IncludeNameBuffer().Form("<%s>","deque");
1922  else if (fSTLtype == ROOT::kSTLmap) IncludeNameBuffer().Form("<%s>","map");
1923  else if (fSTLtype == ROOT::kSTLmultimap) IncludeNameBuffer().Form("<%s>","map");
1924  else if (fSTLtype == ROOT::kSTLset) IncludeNameBuffer().Form("<%s>","set");
1925  else if (fSTLtype == ROOT::kSTLmultiset) IncludeNameBuffer().Form("<%s>","set");
1926  else if (fSTLtype == ROOT::kSTLunorderedset) IncludeNameBuffer().Form("<%s>","unordered_set");
1927  else if (fSTLtype == ROOT::kSTLunorderedmultiset) IncludeNameBuffer().Form("<%s>","unordered_set");
1928  else if (fSTLtype == ROOT::kSTLunorderedmap) IncludeNameBuffer().Form("<%s>","unordered_map");
1929  else if (fSTLtype == ROOT::kSTLunorderedmultimap) IncludeNameBuffer().Form("<%s>","unordered_map");
1930  else if (fSTLtype == ROOT::kSTLbitset) IncludeNameBuffer().Form("<%s>","bitset");
1931  return IncludeNameBuffer();
1932 }
1933 
1934 ////////////////////////////////////////////////////////////////////////////////
1935 /// Set pointer to Streamer function for this element
1936 /// NOTE: we do not take ownership
1937 
1938 void TStreamerSTL::SetStreamer(TMemberStreamer *streamer)
1939 {
1940  fStreamer = streamer;
1941 }
1942 
1943 ////////////////////////////////////////////////////////////////////////////////
1944 /// Stream an object of class TStreamerSTL.
1945 
1946 void TStreamerSTL::Streamer(TBuffer &R__b)
1947 {
1948  UInt_t R__s, R__c;
1949  if (R__b.IsReading()) {
1950  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1951  if (R__v > 2) {
1952  R__b.ReadClassBuffer(TStreamerSTL::Class(), this, R__v, R__s, R__c);
1953  } else {
1954  //====process old versions before automatic schema evolution
1955  TStreamerElement::Streamer(R__b);
1956  R__b >> fSTLtype;
1957  R__b >> fCtype;
1958  R__b.CheckByteCount(R__s, R__c, TStreamerSTL::IsA());
1959  }
1960  if (fSTLtype == ROOT::kSTLmultimap || fSTLtype == ROOT::kSTLset) {
1961  // For a long time those where inverted in TStreamerElement
1962  // compared to the other definitions. When we moved to version '4',
1963  // this got standardized, but we now need to fix it.
1964 
1965  if (fTypeName.BeginsWith("std::set") || fTypeName.BeginsWith("set")) {
1966  fSTLtype = ROOT::kSTLset;
1967  } else if (fTypeName.BeginsWith("std::multimap") || fTypeName.BeginsWith("multimap")) {
1968  fSTLtype = ROOT::kSTLmultimap;
1969  }
1970  }
1971 
1972  if (IsaPointer()) fType = TVirtualStreamerInfo::kSTLp;
1973  else fType = TVirtualStreamerInfo::kSTL;
1974  if (GetArrayLength() > 0) {
1975  fType += TVirtualStreamerInfo::kOffsetL;
1976  }
1977  if (R__b.GetParent()) { // Avoid resetting during a cloning.
1978  if (fCtype==TVirtualStreamerInfo::kObjectp || fCtype==TVirtualStreamerInfo::kAnyp || fCtype==TVirtualStreamerInfo::kObjectP || fCtype==TVirtualStreamerInfo::kAnyP) {
1979  SetBit(kDoNotDelete); // For backward compatibility
1980  } else if ( fSTLtype == ROOT::kSTLmap || fSTLtype == ROOT::kSTLmultimap) {
1981  // Here we would like to set the bit only if one of the element of the pair is a pointer,
1982  // however we have no easy to determine this short of parsing the class name.
1983  SetBit(kDoNotDelete); // For backward compatibility
1984  }
1985  }
1986  return;
1987  } else {
1988  // To enable forward compatibility we actually save with the old value
1989  Int_t tmp = fType;
1990  fType = TVirtualStreamerInfo::kStreamer;
1991  R__b.WriteClassBuffer(TStreamerSTL::Class(),this);
1992  fType = tmp;
1993  }
1994 }
1995 
1996 //______________________________________________________________________________
1997 
1998 //////////////////////////////////////////////////////////////////////////
1999 // //
2000 // TStreamerSTLstring implements streaming std::string. //
2001 // //
2002 //////////////////////////////////////////////////////////////////////////
2003 
2004 ClassImp(TStreamerSTLstring);
2005 
2006 ////////////////////////////////////////////////////////////////////////////////
2007 /// Default ctor.
2008 
2009 TStreamerSTLstring::TStreamerSTLstring()
2010 {
2011 }
2012 
2013 ////////////////////////////////////////////////////////////////////////////////
2014 /// Create a TStreamerSTLstring object.
2015 
2016 TStreamerSTLstring::TStreamerSTLstring(const char *name, const char *title, Int_t offset,
2017  const char *typeName, Bool_t dmPointer)
2018  : TStreamerSTL()
2019 {
2020  SetName(name);
2021  SetTitle(title);
2022 
2023  if (dmPointer) {
2024  fType = TVirtualStreamerInfo::kSTLp;
2025  } else {
2026  fType = TVirtualStreamerInfo::kSTL;
2027  }
2028 
2029  fNewType = fType;
2030  fOffset = offset;
2031  fSTLtype = ROOT::kSTLstring;
2032  fCtype = ROOT::kSTLstring;
2033  fTypeName= typeName;
2034 
2035 }
2036 
2037 ////////////////////////////////////////////////////////////////////////////////
2038 /// TStreamerSTLstring dtor.
2039 
2040 TStreamerSTLstring::~TStreamerSTLstring()
2041 {
2042 }
2043 
2044 ////////////////////////////////////////////////////////////////////////////////
2045 /// Return the proper include for this element.
2046 
2047 const char *TStreamerSTLstring::GetInclude() const
2048 {
2049  IncludeNameBuffer() = "<string>";
2050  return IncludeNameBuffer();
2051 }
2052 
2053 ////////////////////////////////////////////////////////////////////////////////
2054 /// Returns size of anyclass in bytes.
2055 
2056 Int_t TStreamerSTLstring::GetSize() const
2057 {
2058  if (fArrayLength) return fArrayLength*sizeof(string);
2059  return sizeof(string);
2060 }
2061 
2062 ////////////////////////////////////////////////////////////////////////////////
2063 /// Stream an object of class TStreamerSTLstring.
2064 
2065 void TStreamerSTLstring::Streamer(TBuffer &R__b)
2066 {
2067  UInt_t R__s, R__c;
2068  if (R__b.IsReading()) {
2069  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2070  if (R__v > 1) {
2071  R__b.ReadClassBuffer(TStreamerSTLstring::Class(), this, R__v, R__s, R__c);
2072  return;
2073  }
2074  //====process old versions before automatic schema evolution
2075  TStreamerSTL::Streamer(R__b);
2076  R__b.CheckByteCount(R__s, R__c, TStreamerSTLstring::IsA());
2077  } else {
2078  R__b.WriteClassBuffer(TStreamerSTLstring::Class(),this);
2079  }
2080 }
2081 
2082 //______________________________________________________________________________
2083 
2084 ///////////////////////////////////////////////////////////////////////////////
2085 // //
2086 // TStreamerArtificial implements StreamerElement injected by a TSchemaRule. //
2087 // //
2088 ///////////////////////////////////////////////////////////////////////////////
2089 
2090 ClassImp(TStreamerSTLstring);
2091 
2092 void TStreamerArtificial::Streamer(TBuffer& /* R__b */)
2093 {
2094  // Avoid streaming the synthetic/artificial streamer elements.
2095 
2096  // Intentionally, nothing to do at all.
2097  return;
2098 }
2099 
2100 ROOT::TSchemaRule::ReadFuncPtr_t TStreamerArtificial::GetReadFunc()
2101 {
2102  // Return the read function if any.
2103 
2104  return fReadFunc;
2105 }
2106 
2107 ROOT::TSchemaRule::ReadRawFuncPtr_t TStreamerArtificial::GetReadRawFunc()
2108 {
2109  // Return the raw read function if any.
2110 
2111  return fReadRawFunc;
2112 }