ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TStreamerInfo.cxx
Go to the documentation of this file.
1 // @(#)root/io:$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 \class TStreamerInfo TStreamerInfo.cxx
14 \ingroup IO
15 
16 Describes a persistent version of a class.
17 
18 A ROOT file contains the list of TStreamerInfo objects for all the
19 class versions written to this file.
20 When reading a file, all the TStreamerInfo objects are read back in
21 memory and registered to the TClass list of TStreamerInfo.
22 One can see the list and contents of the TStreamerInfo on a file
23 with, e.g.,
24 ~~~{.cpp}
25  TFile f("myfile.root");
26  f.ShowStreamerInfo();
27 ~~~
28 A TStreamerInfo is a list of TStreamerElement objects (one per data
29 member or base class).
30 When streaming an object, the system (TClass) loops on all the
31 TStreamerElement objects and calls the appropriate function for each
32 element type.
33 */
34 
35 #include <memory>
36 #include "TStreamerInfo.h"
37 #include "TFile.h"
38 #include "TROOT.h"
39 #include "TClonesArray.h"
40 #include "TStreamerElement.h"
41 #include "TClass.h"
42 #include "TClassEdit.h"
43 #include "TDataMember.h"
44 #include "TMethodCall.h"
45 #include "TDataType.h"
46 #include "TRealData.h"
47 #include "TBaseClass.h"
48 #include "TBuffer.h"
49 #include "TArrayC.h"
50 #include "TArrayI.h"
51 #include "TArrayF.h"
52 #include "TArrayD.h"
53 #include "TArrayS.h"
54 #include "TArrayL.h"
55 #include "TError.h"
56 #include "TRef.h"
57 #include "TProcessID.h"
58 #include "TSystem.h"
59 
60 #include "TStreamer.h"
61 #include "TContainerConverters.h"
64 #include "TInterpreter.h"
65 
66 #include "TMemberInspector.h"
67 
68 #include "TMakeProject.h"
69 
70 #include "TSchemaRuleSet.h"
71 #include "TSchemaRule.h"
72 
73 #include "TVirtualMutex.h"
74 
75 #include "TStreamerInfoActions.h"
76 
77 std::atomic<Int_t> TStreamerInfo::fgCount{0};
78 
79 const Int_t kMaxLen = 1024;
80 
82 
83 static void R__TObjArray_InsertAt(TObjArray *arr, TObject *obj, Int_t at)
84 {
85  // Slide by one.
86  Int_t last = arr->GetLast();
87  arr->AddAtAndExpand(arr->At(last),last+1);
88  for(Int_t ind = last-1; ind >= at; --ind) {
89  arr->AddAt( arr->At(ind), ind+1);
90  };
91  arr->AddAt( obj, at);
92 }
93 
94 static void R__TObjArray_InsertAt(TObjArray *arr, std::vector<TStreamerArtificial*> &objs, Int_t at)
95 {
96  // Slide by enough.
97  Int_t offset = objs.size();
98  Int_t last = arr->GetLast();
99  arr->AddAtAndExpand(arr->At(last),last+offset);
100  for(Int_t ind = last-1; ind >= at; --ind) {
101  arr->AddAt( arr->At(ind), ind+offset);
102  };
103  for(size_t ins = 0; ins < objs.size(); ++ins) {
104  arr->AddAt(objs[ins], at+ins);
105  }
106 }
107 
108 static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *oldobj)
109 {
110  // Slide by one.
111  Int_t last = arr->GetLast();
112  Int_t at = 0;
113  while (at<last && arr->At(at) != oldobj) {
114  ++at;
115  }
116  ++at; // we found the object, insert after it
117  R__TObjArray_InsertAt(arr, newobj, at);
118 }
119 
120 static void R__TObjArray_InsertBefore(TObjArray *arr, TObject *newobj, TObject *oldobj)
121 {
122  // Slide by one.
123  Int_t last = arr->GetLast();
124  Int_t at = 0;
125  while (at<last && arr->At(at) != oldobj) {
126  ++at;
127  }
128  R__TObjArray_InsertAt(arr, newobj, at);
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Default ctor.
133 
135 {
136  fNumber = fgCount;
137  fClass = 0;
138  fElements = 0;
139  fComp = 0;
140  fCompFull = 0;
141  fCompOpt = 0;
142  fCheckSum = 0;
143  fNdata = 0;
144  fNfulldata= 0;
145  fNslots = 0;
146  fSize = 0;
147  fClassVersion = 0;
149  fOldVersion = Class()->GetClassVersion();
150  fNVirtualInfoLoc = 0;
151  fVirtualInfoLoc = 0;
152  fLiveCount = 0;
153 
154  fReadObjectWise = 0;
155  fReadMemberWise = 0;
157  fWriteObjectWise = 0;
158  fWriteMemberWise = 0;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Create a TStreamerInfo object.
164 
167 {
168  fgCount++;
169  fNumber = fgCount;
170  fClass = cl;
171  fElements = new TObjArray();
172  fComp = 0;
173  fCompFull = 0;
174  fCompOpt = 0;
175  fCheckSum = 0;
176  fNdata = 0;
177  fNfulldata= 0;
178  fNslots = 0;
179  fSize = 0;
180  fClassVersion = fClass->GetClassVersion();
182  fOldVersion = Class()->GetClassVersion();
183  fNVirtualInfoLoc = 0;
184  fVirtualInfoLoc = 0;
185  fLiveCount = 0;
186 
187  fReadObjectWise = 0;
188  fReadMemberWise = 0;
190  fWriteObjectWise = 0;
191  fWriteMemberWise = 0;
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// TStreamerInfo dtor.
197 
199 {
200  delete [] fComp; fComp = 0;
201  delete [] fCompFull; fCompFull = 0;
202  delete [] fCompOpt; fCompOpt = 0;
203  delete [] fVirtualInfoLoc; fVirtualInfoLoc =0;
204 
205  delete fReadObjectWise;
206  delete fReadMemberWise;
207  delete fReadMemberWiseVecPtr;
208  delete fWriteObjectWise;
209  delete fWriteMemberWise;
210  delete fWriteMemberWiseVecPtr;
211 
212  if (!fElements) return;
213  fElements->Delete();
214  delete fElements; fElements=0;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// Makes sure kBuildOldUsed set once Build or BuildOld finishes.
219 /// Makes sure kBuildRunning reset once Build finishes.
220 
221 namespace {
222  struct TPreventRecursiveBuildGuard {
223  TPreventRecursiveBuildGuard(TStreamerInfo* info): fInfo(info) {
224  fInfo->SetBit(TStreamerInfo::kBuildRunning);
225  fInfo->SetBit(TStreamerInfo::kBuildOldUsed);
226  }
227  ~TPreventRecursiveBuildGuard() {
228  fInfo->ResetBit(TStreamerInfo::kBuildOldUsed);
229  fInfo->ResetBit(TStreamerInfo::kBuildRunning);
230  }
231  TStreamerInfo* fInfo;
232  };
233 
234 }
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 /// Build the I/O data structure for the current class version.
238 ///
239 /// A list of TStreamerElement derived classes is built by scanning
240 /// one by one the list of data members of the analyzed class.
241 
243 {
244  // Did another thread already do the work?
245  if (fIsCompiled) return;
246 
248 
249  // Did another thread already do the work while we were waiting ..
250  if (fIsCompiled) return;
251 
252  // Has Build already been run?
253  if (fIsBuilt) return;
254 
255  // Are we recursing on ourself?
257 
258  // This is used to avoid unwanted recursive call to Build or BuildOld.
259  TPreventRecursiveBuildGuard buildGuard(this);
260 
261  if (fClass->GetCollectionProxy()) {
263  TString title;
264  if (proxy->GetValueClass()) {
265  title.Form("<%s%s> Used to call the proper TStreamerInfo case",proxy->GetValueClass()->GetName(),proxy->HasPointers() ? "*" : "");
266  } else {
267  title .Form("<%s%s> Used to call the proper TStreamerInfo case",TDataType::GetTypeName(proxy->GetType()),proxy->HasPointers() ? "*" : "");
268  }
269  TStreamerElement* element = new TStreamerSTL("This", title.Data(), 0, fClass->GetName(), *proxy, 0);
270  fElements->Add(element);
271  Compile();
272  fCheckSum = fClass->GetCheckSum();
273  fIsBuilt = kTRUE;
274  return;
275  }
276 
277  TStreamerElement::Class()->IgnoreTObjectStreamer();
278 
280 
281  fCheckSum = fClass->GetCheckSum();
282 
283  Bool_t needAllocClass = kFALSE;
284  Bool_t wasCompiled = fComp != 0;
285  ROOT::TSchemaRuleSet::TMatches rules;
286  if (fClass->GetSchemaRules()) {
288  }
289 
290  //
291  // Iterate over base classes.
292  //
293 
294  bool isCollection = fClass->GetCollectionProxy();
295  bool isString = !strcmp(fClass->GetName(), "string");
296 
297  TBaseClass* base = 0;
298  TIter nextb(fClass->GetListOfBases());
299  while ((base = (TBaseClass*)nextb())) {
300  TStreamerElement* element = 0;
301  Int_t offset = base->GetDelta();
302  if (offset == kMissing) {
303  continue;
304  }
305  if (offset == kNeedObjectForVirtualBaseClass) {
306  Error("Build()", "Cannot stream virtual base %s of class %s",
307  base->GetName(), fClass->GetName());
308  continue;
309  }
310  const char* bname = base->GetName();
311  const char* btitle = base->GetTitle();
312  // this case appears with STL collections as base class.
313  if (!strcmp(bname, "string")) {
314  element = new TStreamerSTLstring(bname, btitle, offset, bname, kFALSE);
315  } else if (base->IsSTLContainer()) {
316  TVirtualCollectionProxy *proxy = base->GetClassPointer()->GetCollectionProxy();
317  if (proxy) element = new TStreamerSTL(bname, btitle, offset, bname, *proxy, kFALSE);
318  else element = new TStreamerSTL(bname, btitle, offset, bname, 0, kFALSE);
319  if (fClass->IsLoaded() && ((TStreamerSTL*)element)->GetSTLtype() != ROOT::kSTLvector) {
320  if (!element->GetClassPointer()->IsLoaded()) {
321  Error("Build","The class \"%s\" is compiled and its base class \"%s\" is a collection and we do not have a dictionary for it, we will not be able to read or write this base class.",GetName(),bname);
322  delete element;
323  continue;
324  }
325  }
326  } else {
327  element = new TStreamerBase(bname, btitle, offset);
328  TClass* clm = element->GetClassPointer();
329  if (!clm) {
330  // We have no information about the class yet, except that since it
331  // is a base class, we know it is a class. So let's create it (in v5
332  // it would have been created as a side effect of the dictionary of
333  // for the derived class having a forward declaration of the base class).
334  clm = new TClass(bname,1,TClass::kForwardDeclared, true /*silent*/);
335  Warning("Build", "%s: base class %s has no streamer or dictionary it will not be saved", GetName(), clm->GetName());
336  element->Init(0);
337  } else {
338  // Now part of the TStreamerBase constructor.
339  // clm->GetStreamerInfo();
340  if ((clm == TObject::Class()) && fClass->CanIgnoreTObjectStreamer()) {
341  // -- An ignored TObject base class.
342  // Note: The TClass kIgnoreTObjectStreamer == BIT(15), but
343  // the TStreamerInfo kIgnoreTobjectStreamer == BIT(13) which
344  // is confusing.
346  // Flag the element to be ignored by setting its type to -1.
347  // This flag will be used later by Compile() to prevent this
348  // element from being inserted into the compiled info.
349  element->SetType(-1);
350  }
351  if (!clm->IsLoaded() && !(isCollection || isString)) {
352  // Don't complain about the base classes of collections nor of
353  // std::string.
354  Warning("Build", "%s: base class %s has no streamer or dictionary it will not be saved", GetName(), clm->GetName());
355  }
356  }
357  }
358  if (element) {
359  fElements->Add(element);
360  }
361  } // end of base class loop
362 
363  //
364  // Iterate over data members.
365  //
366 
367  Int_t dsize;
368  TDataMember* dm = 0;
370  while ((dm = (TDataMember*) nextd())) {
371  if (fClass->GetClassVersion() == 0) {
372  continue;
373  }
374  if (!dm->IsPersistent()) {
375  continue;
376  }
377  TMemberStreamer* streamer = 0;
378  Int_t offset = GetDataMemberOffset(dm, streamer);
379  if (offset == kMissing) {
380  continue;
381  }
382  TStreamerElement* element = 0;
383  dsize = 0;
384  const char* dmName = dm->GetName();
385  const char* dmTitle = dm->GetTitle();
386  const char* dmType = dm->GetTypeName();
387  const char* dmFull = dm->GetTrueTypeName(); // Used to be GetFullTypeName ...
388  Bool_t dmIsPtr = dm->IsaPointer();
389  TDataMember* dmCounter = 0;
390  if (dmIsPtr) {
391  //
392  // look for a pointer data member with a counter
393  // in the comment string, like so:
394  //
395  // int n;
396  // double* MyArray; //[n]
397  //
398  const char* lbracket = TVirtualStreamerInfo::GetElementCounterStart(dmTitle);
399  const char* rbracket = ::strchr(dmTitle, ']');
400  if (lbracket && rbracket) {
401  const char* counterName = dm->GetArrayIndex();
402  TRealData* rdCounter = (TRealData*) fClass->GetListOfRealData()->FindObject(counterName);
403  if (!rdCounter || rdCounter->TestBit(TRealData::kTransient)) {
404  Error("Build", "%s, discarding: %s %s, illegal %s\n", GetName(), dmFull, dmName, dmTitle);
405  continue;
406  }
407  dmCounter = rdCounter->GetDataMember();
408  TDataType* dtCounter = dmCounter->GetDataType();
409  Bool_t isInteger = dtCounter && ((dtCounter->GetType() == 3) || (dtCounter->GetType() == 13));
410  if (!dtCounter || !isInteger) {
411  Error("Build", "%s, discarding: %s %s, illegal [%s] (must be Int_t)\n", GetName(), dmFull, dmName, counterName);
412  continue;
413  }
414  TStreamerBasicType* bt = TStreamerInfo::GetElementCounter(counterName, dmCounter->GetClass());
415  if (!bt) {
416  if (dmCounter->GetClass()->Property() & kIsAbstract) {
417  continue;
418  }
419  Error("Build", "%s, discarding: %s %s, illegal [%s] must be placed before \n", GetName(), dmFull, dmName, counterName);
420  continue;
421  }
422  }
423  }
424  TDataType* dt = dm->GetDataType();
425  if (dt) {
426  // found a basic type
427  Int_t dtype = dt->GetType();
428  dsize = dt->Size();
429  if (!dmCounter && (strstr(dmFull, "char*") || strstr(dmFull, "Char_t*"))) {
430  dtype = kCharStar;
431  dsize = sizeof(char*);
432  }
433  if (dtype == kOther_t || dtype == kNoType_t) {
434  Error("Build", "%s, unknown type: %s %s", GetName(), dmFull, dmName);
435  continue;
436  } else if (dmIsPtr && (dtype != kCharStar)) {
437  if (dmCounter) {
438  // data member is pointer to an array of basic types
439  element = new TStreamerBasicPointer(dmName, dmTitle, offset, dtype, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
440  } else {
441  if ((fName == "TString") || (fName == "TClass")) {
442  continue;
443  }
444  Error("Build", "%s, discarding: %s %s, no [dimension]\n", GetName(), dmFull, dmName);
445  continue;
446  }
447  } else {
448  // data member is a basic type
449  if ((fClass == TObject::Class()) && !strcmp(dmName, "fBits")) {
450  //printf("found fBits, changing dtype from %d to 15\n", dtype);
451  dtype = kBits;
452  }
453  element = new TStreamerBasicType(dmName, dmTitle, offset, dtype, dmFull);
454  }
455  } else {
456  // try STL container or string
457  static const char* full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
458  if (!strcmp(dmType, "string") || !strcmp(dmType, "std::string") || !strcmp(dmType, full_string_name)) {
459  element = new TStreamerSTLstring(dmName, dmTitle, offset, dmFull, dmIsPtr);
460  } else if (dm->IsSTLContainer()) {
461  TVirtualCollectionProxy *proxy = TClass::GetClass(dm->GetTypeName() /* the underlying type */)->GetCollectionProxy();
462  if (proxy) element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, *proxy, dmIsPtr);
463  else element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, dm->GetTrueTypeName(), dmIsPtr);
464  if (((TStreamerSTL*)element)->GetSTLtype() != ROOT::kSTLvector) {
465  if (fClass->IsLoaded()) {
466  if (!element->GetClassPointer()->IsLoaded()) {
467  Error("Build","The class \"%s\" is compiled and for its the data member \"%s\", we do not have a dictionary for the collection \"%s\", we will not be able to read or write this data member.",GetName(),dmName,element->GetClassPointer()->GetName());
468  delete element;
469  continue;
470  }
471  } else if (fClass->GetState() == TClass::kInterpreted) {
473  Error("Build","The class \"%s\" is interpreted and for its the data member \"%s\", we do not have a dictionary for the collection \"%s\", we will not be able to read or write this data member.",GetName(),dmName,element->GetClassPointer()->GetName());
474  delete element;
475  continue;
476  }
477  }
478  }
479  } else {
480  TClass* clm = TClass::GetClass(dmType);
481  if (!clm) {
482  Error("Build", "%s, unknown type: %s %s\n", GetName(), dmFull, dmName);
483  continue;
484  }
485  if (dmIsPtr) {
486  // a pointer to a class
487  if (dmCounter) {
488  element = new TStreamerLoop(dmName, dmTitle, offset, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
489  } else {
490  if (clm->IsTObject()) {
491  element = new TStreamerObjectPointer(dmName, dmTitle, offset, dmFull);
492  } else {
493  element = new TStreamerObjectAnyPointer(dmName, dmTitle, offset, dmFull);
494  if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
495  Error("Build", "%s: %s has no streamer or dictionary, data member %s will not be saved", GetName(), dmFull, dmName);
496  }
497  }
498  }
499  } else if (clm->IsTObject()) {
500  element = new TStreamerObject(dmName, dmTitle, offset, dmFull);
501  } else if ((clm == TString::Class()) && !dmIsPtr) {
502  element = new TStreamerString(dmName, dmTitle, offset);
503  } else {
504  element = new TStreamerObjectAny(dmName, dmTitle, offset, dmFull);
505  if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
506  Warning("Build", "%s: %s has no streamer or dictionary, data member \"%s\" will not be saved", GetName(), dmFull, dmName);
507  }
508  }
509  }
510  }
511  if (!element) {
512  // If we didn't make an element, there is nothing to do.
513  continue;
514  }
515  Int_t ndim = dm->GetArrayDim();
516  if (!dsize) {
517  dsize = dm->GetUnitSize();
518  }
519  for (Int_t i = 0; i < ndim; ++i) {
520  element->SetMaxIndex(i, dm->GetMaxIndex(i));
521  }
522  element->SetArrayDim(ndim);
523  Int_t narr = element->GetArrayLength();
524  if (!narr) {
525  narr = 1;
526  }
527  element->SetSize(dsize*narr);
528  element->SetStreamer(streamer);
529  if (!streamer) {
530  Int_t k = element->GetType();
531  if (k == kStreamer) {
532  //if ((k == kSTL) || (k == kSTL + kOffsetL) || (k == kStreamer) || (k == kStreamLoop))
533  element->SetType(-1);
534  }
535  }
536 
537  if ( !wasCompiled && (rules && rules.HasRuleWithSource( element->GetName(), kTRUE )) ) {
538  needAllocClass = kTRUE;
539 
540  // If this is optimized to re-use TStreamerElement(s) in case of variable renaming,
541  // then we must revisit the code in TBranchElement::InitInfo that recalculate the
542  // fID (i.e. the index of the TStreamerElement to be used for streaming).
543 
544  TStreamerElement *cached = element;
545  // Now that we are caching the unconverted element, we do not assign it to the real type even if we could have!
546  if (element->GetNewType()>0 /* intentionally not including base class for now */
547  && rules && !rules.HasRuleWithTarget( element->GetName(), kTRUE ) )
548  {
549  TStreamerElement *copy = (TStreamerElement*)element->Clone();
550  fElements->Add(copy);
552  cached = copy;
553 
554  // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
555  } else {
556  // If the element is just cached and not repeat, we need to inject an element
557  // to insure the writing.
558  TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
559  fElements->Add(element);
560  writecopy->SetBit(TStreamerElement::kWrite);
561  writecopy->SetNewType( writecopy->GetType() );
562  // Put the write element after the read element (that does caching).
563  element = writecopy;
564  }
566  cached->SetNewType( cached->GetType() );
567  }
568 
569  fElements->Add(element);
570  } // end of member loop
571 
572  // Now add artificial TStreamerElement (i.e. rules that creates new members or set transient members).
574 
575  if (needAllocClass) {
577  if (!infoalloc) {
578  Error("Build","Could you create a TStreamerInfo for %s\n",TString::Format("%s@@%d",GetName(),GetClassVersion()).Data());
579  } else {
580  // Tell clone we should rerun BuildOld
581  infoalloc->SetBit(kBuildOldUsed,false);
582  infoalloc->BuildCheck();
583  infoalloc->BuildOld();
584  TClass *allocClass = infoalloc->GetClass();
585 
586  {
587  TIter next(fElements);
588  TStreamerElement* element;
589  while ((element = (TStreamerElement*) next())) {
590  if (element->TestBit(TStreamerElement::kRepeat) && element->IsaPointer()) {
591  TStreamerElement *other = (TStreamerElement*) infoalloc->GetElements()->FindObject(element->GetName());
592  if (other) {
594  }
595  }
596  }
597  infoalloc->GetElements()->Compress();
598  }
599  {
600  TIter next(fElements);
601  TStreamerElement* element;
602  while ((element = (TStreamerElement*) next())) {
603  if (element->TestBit(TStreamerElement::kCache)) {
604  element->SetOffset(infoalloc->GetOffset(element->GetName()));
605  }
606  }
607  }
608 
609  TStreamerElement *el = new TStreamerArtificial("@@alloc","", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
610  R__TObjArray_InsertAt( fElements, el, 0 );
611 
612  el = new TStreamerArtificial("@@dealloc","", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
613  fElements->Add( el );
614  }
615  }
616 
617  //
618  // Make a more compact version.
619  //
620  Compile();
621  fIsBuilt = kTRUE;
622 }
623 
624 ////////////////////////////////////////////////////////////////////////////////
625 /// Check if built and consistent with the class dictionary.
626 /// This method is called by TFile::ReadStreamerInfo.
627 
629 {
631 
633  if (!fClass) {
634  // fClassVersion should have been a Version_t and/or Version_t
635  // should have been an Int_t. Changing the on-file format
636  // of the StreamerInfo is 'hard' (for forward compatibility), so
637  // leave it as is for now.
638  fClass = new TClass(GetName(), (Version_t)fClassVersion);
640 
641  // Case of a custom collection (the user provided a CollectionProxy
642  // for a class that is not an STL collection).
643  if (GetElements()->GetEntries() == 1) {
644  TObject *element = GetElements()->UncheckedAt(0);
645  Bool_t isstl = element && strcmp("This",element->GetName())==0;
646  if (isstl) {
647  if (element->GetTitle()[0] == '<') {
648  // We know the content.
649  TString content = element->GetTitle();
650  Int_t level = 1;
651  for(Int_t c = 1; c < content.Length(); ++c) {
652  if (content[c] == '<') ++level;
653  else if (content[c] == '>') --level;
654  if (level == 0) {
655  content.Remove(c+1);
656  break;
657  }
658  }
659  content.Prepend("vector");
660  TClass *clequiv = TClass::GetClass(content);
661  TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
662  if (gDebug > 1)
663  Info("BuildCheck",
664  "Update the collection proxy of the class \"%s\" \n"
665  "\tto be similar to \"%s\".",
666  GetName(),content.Data());
667  fClass->CopyCollectionProxy( *proxy );
668  } else {
669  Warning("BuildCheck", "\n\
670  The class %s had a collection proxy when written but it is not an STL\n \
671  collection and we did not record the type of the content of the collection.\n \
672  We will claim the content is a bool (i.e. no data will be read).",
673  GetName());
674  }
675  }
676  }
677 
678  } else {
681  // We have a collection that is indeed an STL collection,
682  // we know we don't need its streamerInfo.
684  return;
685  }
686  }
687  const TObjArray *array = fClass->GetStreamerInfos();
688  TStreamerInfo* info = 0;
689 
690  if (fClass->TestBit(TClass::kIsEmulation) && array->GetEntries()==0) {
691  // We have an emulated class that has no TStreamerInfo, this
692  // means it was created to insert a (default) rule. Consequently
693  // the error message about the missing dictionary was not printed.
694  // For consistency, let's print it now!
695 
696  ::Warning("TClass::TClass", "no dictionary for class %s is available", GetName());
697  }
698 
699  // Case of a custom collection (the user provided a CollectionProxy
700  // for a class that is not an STL collection).
701  if (GetElements()->GetEntries() == 1) {
702  TObject *element = GetElements()->UncheckedAt(0);
703  Bool_t isstl = element && strcmp("This",element->GetName())==0;
704  if (isstl && !fClass->GetCollectionProxy()) {
705  if (element->GetTitle()[0] == '<') {
706  // We know the content.
707  TString content = element->GetTitle();
708  Int_t level = 1;
709  for(Int_t c = 1; c < content.Length(); ++c) {
710  if (content[c] == '<') ++level;
711  else if (content[c] == '>') --level;
712  if (level == 0) {
713  content.Remove(c+1);
714  break;
715  }
716  }
717  content.Prepend("vector");
718  TClass *clequiv = TClass::GetClass(content);
719  TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
720  if (gDebug > 1)
721  Info("BuildCheck",
722  "Update the collection proxy of the class \"%s\" \n"
723  "\tto be similar to \"%s\".",
724  GetName(),content.Data());
725  fClass->CopyCollectionProxy( *proxy );
726  } else {
727  Warning("BuildCheck", "\n\
728  The class %s had a collection proxy when written but it is not an STL\n \
729  collection and we did not record the type of the content of the collection.\n \
730  We will claim the content is a bool (i.e. no data will be read).",
731  GetName());
732  }
734  return;
735  }
736  }
737 
738  // If the user has not specified a class version (this _used to_
739  // always be the case when the class is Foreign) or if the user
740  // has specified a version to be explicitly 1. [We can not
741  // distinguish the two cases using the information in the "on
742  // file" StreamerInfo.]
743 
744  Bool_t searchOnChecksum = kFALSE;
745  if (fClass->IsLoaded() && fClass->GetClassVersion() >= 2) {
746  // We know for sure that the user specified the version.
747 
748  if (fOnFileClassVersion >= 2) {
749  // The class version was specified when the object was
750  // written
751 
752  searchOnChecksum = kFALSE;
753 
754  } else {
755  // The class version was not specified when the object was
756  // written OR it was specified to be 1.
757 
758  searchOnChecksum = kTRUE;
759  }
760  } else if (fClass->IsLoaded() && !fClass->IsForeign()) {
761  // We are in the case where the class has a Streamer function.
762  // and fClass->GetClassVersion is 1, we still assume that the
763  // Class Version is specified (to be one).
764 
765  searchOnChecksum = kFALSE;
766 
767  } else if (fClass->IsLoaded() /* implied: && fClass->IsForeign() */ ) {
768  // We are in the case of a Foreign class with no specified
769  // class version.
770 
771  searchOnChecksum = kTRUE;
772 
773  }
774  else {
775  // We are in the case of an 'emulated' class.
776 
777  if (fOnFileClassVersion >= 2) {
778  // The class version was specified when the object was
779  // written
780 
781  searchOnChecksum = kFALSE;
782 
783  } else {
784  // The class version was not specified when the object was
785  // written OR it was specified to be 1.
786 
787  searchOnChecksum = kTRUE;
788 
789  TStreamerInfo* v1 = (TStreamerInfo*) array->At(1);
790  if (v1) {
791  if (fCheckSum != v1->GetCheckSum()) {
792  fClassVersion = array->GetLast() + 1;
793  }
794  }
795  }
796  }
797 
798  if (!searchOnChecksum) {
799  if (fClassVersion < (array->GetEntriesFast() - 1)) {
800  info = (TStreamerInfo*) array->At(fClassVersion);
801  }
802  } else {
803  Int_t ninfos = array->GetEntriesFast() - 1;
804  for (Int_t i = -1; i < ninfos; ++i) {
805  info = (TStreamerInfo*) array->UncheckedAt(i);
806  if (!info) {
807  continue;
808  }
809  if (fCheckSum == info->GetCheckSum() && (info->GetOnFileClassVersion()==1 || info->GetOnFileClassVersion()==0)) {
810  // We must match on the same checksum, an existing TStreamerInfo
811  // for one of the 'unversioned' class layout (i.e. version was 1).
812  fClassVersion = i;
813  break;
814  }
815  info = 0;
816  }
817  if (info==0) {
818  // Find an empty slot.
819  ninfos = array->GetEntriesFast() - 1;
820  Int_t slot = 1; // Start of Class version 1.
821  while ((slot < ninfos) && (array->UncheckedAt(slot) != 0)) {
822  ++slot;
823  }
824  fClassVersion = slot;
825  }
826  }
827 
828  // NOTE: Should we check if the already existing info is the same as
829  // the current one? Yes
830  // In case a class (eg Event.h) has a TClonesArray of Tracks, it could be
831  // that the old info does not have the class name (Track) in the data
832  // member title. Set old title to new title
833  if (info) {
834  // We found an existing TStreamerInfo for our ClassVersion
835  Bool_t match = kTRUE;
836  Bool_t done = kFALSE;
837  Bool_t oldIsNonVersioned = kFALSE;
838  if (fClassVersion!=0 && !fClass->TestBit(TClass::kWarned) && (fClassVersion == info->GetClassVersion()) && (fCheckSum != info->GetCheckSum())) {
839  // The TStreamerInfo's checksum is different from the checksum for the compile class.
840 
841  match = kFALSE;
842  oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
843 
844  if (fClass->IsLoaded() && (fClassVersion == fClass->GetClassVersion()) && fClass->HasDataMemberInfo()) {
845  // In the case where the read-in TStreamerInfo does not
846  // match in the 'current' in memory TStreamerInfo for
847  // a non foreign class (we can not get here if this is
848  // a foreign class so we do not need to test it),
849  // we need to add this one more test since the CINT behaviour
850  // with enums changed over time, so verify the checksum ignoring
851  // members of type enum. We also used to not count the //[xyz] comment
852  // in the checksum, so test for that too.
853  if ( (fCheckSum == fClass->GetCheckSum() || fClass->MatchLegacyCheckSum(fCheckSum) )
854  &&(info->GetCheckSum() == fClass->GetCheckSum() || fClass->MatchLegacyCheckSum(info->GetCheckSum()))
855  )
856  {
857  match = kTRUE;
858  }
859  if (fOldVersion <= 2) {
860  // Names of STL base classes was modified in vers==3. Allocators removed
861  // (We could be more specific (see test for the same case below)
862  match = kTRUE;
863  }
864  if (!match && CompareContent(0,info,kFALSE,kFALSE,file)) {
865  match = kTRUE;
866  }
867 #ifdef TEST_FOR_BACKWARD_COMPATIBILITY_ABSTRACT_CLASSES
868  if (!match && file->GetVersion() < 51800 && fClass && (fClass->Property() & kIsAbstract)
869  && fClass->GetListOfDataMembers()->GetEntries() != 0)
870  {
871  // In some instances of old files (v5.17 and less), some StreamerInfo for
872  // an abstract class where not written correctly, and add no
873  // data member listed. If in addition one of the data member
874  // was declared using a typedef _and_ the current class definition
875  // uses a different typedef, we are unable to recalculate the
876  // checksum as it was, because the information is missing from
877  // the StreamerInfo, and for the same reason CompareContent can
878  // not know whether this is okay or not ...
879  //
880  // Since this is such an unlikely scenario, let's complain
881  // about it anyway (The class layout *may* have changed, we
882  // don't know).
883 
884  // if (this has only base classes) {
885  // match = kTRUE;
886  // }
887  }
888 #endif
889  } else {
890  // The on-file TStreamerInfo's checksum differs from the checksum of a TStreamerInfo on another file.
891 
892  match = kFALSE;
893  oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
894 
895  // In the case where the read-in TStreamerInfo does not
896  // match in the 'current' in memory TStreamerInfo for
897  // a non foreign class (we can not get here if this is
898  // a foreign class so we do not need to test it),
899  // we need to add this one more test since the CINT behaviour
900  // with enums changed over time, so verify the checksum ignoring
901  // members of type enum. We also used to not count the //[xyz] comment
902  // in the checksum, so test for that too.
903  if (fCheckSum == info->GetCheckSum(TClass::kCurrentCheckSum)
904  || info->MatchLegacyCheckSum(fCheckSum)
906  || MatchLegacyCheckSum(info->GetCheckSum())
908  {
909  match = kTRUE;
910  }
911  if (fOldVersion <= 2) {
912  // Names of STL base classes was modified in vers==3. Allocators removed
913  // (We could be more specific (see test for the same case below)
914  match = kTRUE;
915  }
916  if (!match && CompareContent(0,info,kFALSE,kFALSE,file)) {
917  match = kTRUE;
918  }
919  }
920  }
921  if (info->IsBuilt()) {
923  fNumber = info->GetNumber();
924  Int_t nel = fElements->GetEntriesFast();
925  TObjArray* elems = info->GetElements();
926  TStreamerElement* e1 = 0;
927  TStreamerElement* e2 = 0;
928  for (Int_t i = 0; i < nel; ++i) {
929  e1 = (TStreamerElement*) fElements->UncheckedAt(i);
930  e2 = (TStreamerElement*) elems->At(i);
931  if (!e1 || !e2) {
932  continue;
933  }
934  if (strlen(e1->GetTitle()) != strlen(e2->GetTitle())) {
935  e2->SetTitle(e1->GetTitle());
936  }
937  }
938 
939  done = kTRUE;
940  } else {
941  fClass->RemoveStreamerInfo(fClassVersion);
942  info = 0;
943  }
944  TString origin;
945  if (!match && !fClass->TestBit(TClass::kWarned)) {
946  if (oldIsNonVersioned) {
947  if (file) {
948  Warning("BuildCheck", "\n\
949  The class %s transitioned from not having a specified class version\n\
950  to having a specified class version (the current class version is %d).\n\
951  However too many different non-versioned layouts of the class have been\n\
952  loaded so far. This prevent the proper reading of objects written with\n\
953  the class layout version %d, in particular from the file:\n\
954  %s.\n\
955  To work around this issue, load fewer 'old' files in the same ROOT session.",
957  } else {
958  Warning("BuildCheck", "\n\
959  The class %s transitioned from not having a specified class version\n\
960  to having a specified class version (the current class version is %d).\n\
961  However too many different non-versioned layouts of the class have been\n\
962  loaded so far. This prevent the proper reading of objects written with\n\
963  the class layout version %d.\n\
964  To work around this issue, load fewer 'old' files in the same ROOT session.",
966  }
967  } else {
968  if (file) {
969  if (done) {
970  Warning("BuildCheck", "\n\
971  The StreamerInfo for version %d of class %s read from the file %s\n\
972  has a different checksum than the previously loaded StreamerInfo.\n\
973  Reading objects of type %s from the file %s \n\
974  (and potentially other files) might not work correctly.\n\
975  Most likely the version number of the class was not properly\n\
976  updated [See ClassDef(%s,%d)].",
977  fClassVersion, GetName(), file->GetName(), GetName(), file->GetName(), GetName(), fClassVersion);
978  } else {
979  Warning("BuildCheck", "\n\
980  The StreamerInfo from %s does not match existing one (%s:%d)\n\
981  The existing one has not been used yet and will be discarded.\n\
982  Reading the file %s will work properly, however writing object of\n\
983  type %s will not work properly. Most likely the version number\n\
984  of the class was not properly updated [See ClassDef(%s,%d)].",
985  file->GetName(), GetName(), fClassVersion,file->GetName(),GetName(), GetName(), fClassVersion);
986  }
987  } else {
988  if (done) {
989  Warning("BuildCheck", "\n\
990  The StreamerInfo for version %d of class %s\n\
991  has a different checksum than the previously loaded StreamerInfo.\n\
992  Reading objects of type %s\n\
993  (and potentially other files) might not work correctly.\n\
994  Most likely the version number of the class was not properly\n\
995  updated [See ClassDef(%s,%d)].",
996  fClassVersion, GetName(), GetName(), GetName(), fClassVersion);
997  } else {
998  Warning("BuildCheck", "\n\
999  The StreamerInfo from %s does not match existing one (%s:%d)\n\
1000  The existing one has not been used yet and will be discarded.\n\
1001  Reading should work properly, however writing object of\n\
1002  type %s will not work properly. Most likely the version number\n\
1003  of the class was not properly updated [See ClassDef(%s,%d)].",
1005  }
1006  }
1007  }
1008  CompareContent(0,info,kTRUE,kTRUE,file);
1010  }
1011  if (done) {
1012  return;
1013  }
1014  }
1015  // The slot was free, however it might still be reserved for the current
1016  // loaded version of the class
1017  if (fClass->IsLoaded()
1019  && (fClassVersion != 0) // We don't care about transient classes
1020  && (fClassVersion == fClass->GetClassVersion())
1021  && (fCheckSum != fClass->GetCheckSum())) {
1022 
1023  // If the old TStreamerInfo matches the in-memory one when we either
1024  // - ignore the members of type enum
1025  // or
1026  // - ignore the comments annotation (//[xyz])
1027  // we can accept the old TStreamerInfo.
1028 
1029  if (!fClass->MatchLegacyCheckSum(fCheckSum)) {
1030 
1032  if (warn) {
1033  warn = !CompareContent(fClass,0,kFALSE,kFALSE,file);
1034  }
1035 #ifdef TEST_FOR_BACKWARD_COMPATIBILITY_ABSTRACT_CLASSES
1036  if (warn && file->GetVersion() < 51800 && fClass && (fClass->Property() & kIsAbstract)
1037  && fClass->GetListOfDataMembers()->GetEntries() != 0)
1038  {
1039  // In some instances of old files (v5.17 and less), some StreamerInfo for
1040  // an abstract class where not written correctly, and add no
1041  // data member listed. If in addition one of the data member
1042  // was declared using a typedef _and_ the current class definition
1043  // uses a different typedef, we are unable to recalculate the
1044  // checksum as it was, because the information is missing from
1045  // the StreamerInfo, and for the same reason CompareContent can
1046  // not know whether this is okay or not ...
1047  //
1048  // Since this is such an unlikely scenario, let's complain
1049  // about it anyway (The class layout *may* have changed, we
1050  // don't know).
1051 
1052  // if (this has only base classes) {
1053  // warn = kFALSE;
1054  // }
1055  }
1056 #endif // TEST_FOR_BACKWARD_COMPATIBILITY
1057  if (warn && (fOldVersion <= 2)) {
1058  // Names of STL base classes was modified in vers==3. Allocators removed
1059  //
1060  TIter nextBC(fClass->GetListOfBases());
1061  TBaseClass* bc = 0;
1062  while ((bc = (TBaseClass*) nextBC())) {
1063  if (bc->GetClassPointer()->GetCollectionType()) {
1064  warn = kFALSE;
1065  }
1066  }
1067  }
1068  if (warn) {
1069  if (file) {
1070  Warning("BuildCheck", "\n\
1071  The StreamerInfo of class %s read from file %s\n\
1072  has the same version (=%d) as the active class but a different checksum.\n\
1073  You should update the version to ClassDef(%s,%d).\n\
1074  Do not try to write objects with the current class definition,\n\
1075  the files will not be readable.\n", GetName(), file->GetName(), fClassVersion, GetName(), fClassVersion + 1);
1076  } else {
1077  Warning("BuildCheck", "\n\
1078  The StreamerInfo of class %s \n\
1079  has the same version (=%d) as the active class but a different checksum.\n\
1080  You should update the version to ClassDef(%s,%d).\n\
1081  Do not try to write objects with the current class definition,\n\
1082  the files will not be readable.\n", GetName(), fClassVersion, GetName(), fClassVersion + 1);
1083  }
1084  CompareContent(fClass,0,kTRUE,kTRUE,file);
1086  }
1087  } else {
1088  if (!fClass->IsVersioned()) {
1089  Fatal("BuildCheck", "\n\
1090  The StreamerInfo of unversioned class %s \n\
1091  has the same version (=%d) as the active class but an old checksum.\n\
1092  This should not happen. An assert will follow.\n", GetName(), fClassVersion);
1093  }
1094  }
1095  }
1096  if (!fClass->IsLoaded() && this->fOnFileClassVersion>1)
1097  {
1098  ROOT::ResetClassVersion(fClass,(const char*)-1, this->fClassVersion);
1099  }
1100  }
1101  // FIXME: This code can never execute because Build() calls
1102  // TStreamerElement::Class()->IgnoreTObjectStreamer()
1103  // so our bits are never saved to the file.
1106  }
1107  if ((fClassVersion < -1) || (fClassVersion > 65000)) {
1108  printf("ERROR reading TStreamerInfo: %s fClassVersion=%d\n", GetName(), fClassVersion);
1109  SetBit(kCanDelete);
1110  fNumber = -1;
1111  return;
1112  }
1113 
1116  && GetCheckSum() != fClass->GetCheckSum()
1117  && fClassVersion == fClass->GetClassVersion()) {
1118  // We got here, thus we are a perfect alias for the current streamerInfo,
1119  // but we might had odd v5 style name spelling, so let's prefer the
1120  // current one.
1121  SetBit(kCanDelete);
1122  return;
1123  }
1124 
1126  ++fgCount;
1127  fNumber = fgCount;
1128 
1129  // Since we just read this streamerInfo from file, it has already been built.
1130  fIsBuilt = kTRUE;
1131 
1132  //add to the global list of StreamerInfo
1133  TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
1134  infos->AddAtAndExpand(this, fNumber);
1135 }
1136 
1137 ////////////////////////////////////////////////////////////////////////////////
1138 /// Create an Emulation TStreamerInfo object.
1139 
1141 {
1143 
1144  TString duName;
1145  R__ASSERT(file);
1146  Int_t fv = file->GetVersion()%100000;
1147  R__ASSERT(fv < 30000);
1148  fClassVersion = -1;
1149  fCheckSum = 2001;
1150  TObjArray *elements = GetElements();
1151  Int_t ndata = elements ? elements->GetEntries() : 0;
1152  for (Int_t i=0;i < ndata;i++) {
1153  TStreamerElement *element = (TStreamerElement*)elements->UncheckedAt(i);
1154  if (!element) break;
1155  int ty = element->GetType();
1156  if (ty < kChar || ty >kULong+kOffsetL) continue;
1157  if (ty == kLong) element->SetType(kInt);
1158  if (ty == kULong) element->SetType(kUInt);
1159  if (ty == kLong + kOffsetL) element->SetType(kInt + kOffsetL);
1160  if (ty == kULong + kOffsetL) element->SetType(kUInt + kOffsetL);
1161  if (ty <= kULong) continue;
1162  duName = element->GetName();
1163  duName.Append("QWERTY");
1164  TStreamerBasicType *bt = new TStreamerBasicType(duName, "", 0, kInt,"Int_t");
1165  {for (int j=ndata-1;j>=i;j--) {elements->AddAtAndExpand(elements->At(j),j+1);}}
1166  elements->AddAt(bt,i);
1167  ndata++;
1168  i++;
1169  }
1170  BuildOld();
1171 }
1172 
1173 ////////////////////////////////////////////////////////////////////////////////
1174 /// Check if we can build this for foreign class - do we have some rules
1175 /// to do that.
1176 
1177 Bool_t TStreamerInfo::BuildFor( const TClass *in_memory_cl )
1178 {
1180 
1181  if( !in_memory_cl || !in_memory_cl->GetSchemaRules() ) {
1182  return kFALSE;
1183  }
1184 
1185  auto rules = in_memory_cl->GetSchemaRules()->FindRules( GetName(), fOnFileClassVersion, fCheckSum );
1186 
1187  if( rules.empty() && !in_memory_cl->GetCollectionType() ) {
1188  Warning( "BuildFor", "The build of %s streamer info for %s has been requested, but no matching conversion rules were specified", GetName(), in_memory_cl->GetName() );
1189  return kFALSE;
1190  }
1191 
1192  fClass = const_cast<TClass*>(in_memory_cl);
1193 
1194  return kTRUE;
1195 }
1196 
1197 
1198 namespace {
1199 ////////////////////////////////////////////////////////////////////////////////
1200 /// Helper function for BuildOld
1201  Bool_t ClassWasMovedToNamespace(TClass *oldClass, TClass *newClass)
1202  {
1203  // Returns true if oldClass is the same as newClass but newClass is in a
1204  // namespace (and oldClass was not in a namespace).
1205 
1206  if (oldClass == 0 || newClass == 0) return kFALSE;
1207 
1208  UInt_t newlen = strlen(newClass->GetName());
1209  UInt_t oldlen = strlen(oldClass->GetName());
1210 
1211  const char *oldname = oldClass->GetName();
1212  for (UInt_t i = oldlen, done = false, nest = 0; (i>0) && !done ; --i) {
1213  switch (oldClass->GetName()[i-1]) {
1214  case '>' : ++nest; break;
1215  case '<' : if (nest==0) return kFALSE; // the name is not well formed, give up.
1216  --nest; break;
1217  case ':' : if (nest == 0) oldname= &(oldClass->GetName()[i]); done = kTRUE; break;
1218  }
1219  }
1220  oldlen = strlen(oldname);
1221  if (!(strlen(newClass->GetName()) > strlen(oldClass->GetName()))) {
1222  return kFALSE;
1223  }
1224 
1225  const char* newEnd = & (newClass->GetName()[newlen-oldlen]);
1226 
1227  if (0 != strcmp(newEnd, oldname)) {
1228  return kFALSE;
1229  }
1230 
1231  Int_t oldv = oldClass->GetStreamerInfo()->GetClassVersion();
1232 
1233  if (newClass->GetStreamerInfos() && oldv < newClass->GetStreamerInfos()->GetSize() && newClass->GetStreamerInfos()->At(oldv) && strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(), oldClass->GetName()) != 0) {
1234  // The new class has already a TStreamerInfo for the the same version as
1235  // the old class and this was not the result of an import. So we do not
1236  // have a match
1237  return kFALSE;
1238  }
1239  return kTRUE;
1240  }
1241 
1242 ////////////////////////////////////////////////////////////////////////////////
1243 /// Import the streamerInfo from oldClass to newClass.
1244 ///
1245 /// In case of conflict, returns the version number of the StreamerInfo
1246 /// with the conflict.
1247 /// Return 0 in case of success
1248  Int_t ImportStreamerInfo(TClass *oldClass, TClass *newClass) {
1249 
1250  TIter next(oldClass->GetStreamerInfos());
1251  TStreamerInfo *info;
1252  while ((info = (TStreamerInfo*)next())) {
1253  info = (TStreamerInfo*)info->Clone();
1254  if (!info) {
1255  Error("ImportStreamerInfo","Unable to clone the StreamerInfo for %s.",(*next)->GetName());
1256  } else {
1257  info->SetClass(newClass);
1258  Int_t oldv = info->GetClassVersion();
1259  if (oldv > newClass->GetStreamerInfos()->GetSize() || newClass->GetStreamerInfos()->At(oldv) == 0) {
1260  // All is good.
1261  newClass->RegisterStreamerInfo(info);
1262  } else {
1263  // We verify that we are consistent and that
1264  // newcl->GetStreamerInfos()->UncheckedAt(info->GetClassVersion)
1265  // is already the same as info.
1266  if (strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(),
1267  oldClass->GetName()) != 0) {
1268  // The existing StreamerInfo does not already come from OldClass.
1269  // This is a real problem!
1270  return oldv;
1271  }
1272  }
1273  }
1274  }
1275  return 0;
1276  }
1277 
1278  Bool_t ContainerMatchTClonesArray(TClass *newClass)
1279  {
1280  // Return true if newClass is a likely valid conversion from
1281  // a TClonesArray
1282 
1283  return newClass->GetCollectionProxy()
1284  && newClass->GetCollectionProxy()->GetValueClass()
1285  && !newClass->GetCollectionProxy()->HasPointers();
1286  }
1287 
1288  Bool_t CollectionMatch(const TClass *oldClass, const TClass* newClass)
1289  {
1290  // Return true if oldClass and newClass points to 2 compatible collection.
1291  // i.e. they contains the exact same type.
1292 
1293  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1294  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1295 
1296  TClass *oldContent = oldProxy->GetValueClass();
1297  TClass *newContent = newProxy->GetValueClass();
1298 
1299  Bool_t contentMatch = kFALSE;
1300  if (oldContent) {
1301  if (oldContent == newContent) {
1302  contentMatch = kTRUE;
1303  } else if (newContent) {
1304  TString oldFlatContent( TMakeProject::UpdateAssociativeToVector(oldContent->GetName()) );
1305  TString newFlatContent( TMakeProject::UpdateAssociativeToVector(newContent->GetName()) );
1306  if (oldFlatContent == newFlatContent) {
1307  contentMatch = kTRUE;
1308  }
1309  } else {
1310  contentMatch = kFALSE;
1311  }
1312  } else {
1313  contentMatch = (newContent==0);
1314  }
1315 
1316  if (contentMatch) {
1317  if ((oldContent==0 && oldProxy->GetType() == newProxy->GetType())
1318  ||(oldContent && oldProxy->HasPointers() == newProxy->HasPointers())) {
1319  // We have compatibles collections (they have the same content)!
1320  return kTRUE;
1321  }
1322  }
1323  return kFALSE;
1324  }
1325 
1326  Bool_t CollectionMatchFloat16(const TClass *oldClass, const TClass* newClass)
1327  {
1328  // Return true if oldClass and newClass points to 2 compatible collection.
1329  // i.e. they contains the exact same type.
1330 
1331  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1332  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1333 
1334  if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1335  && (oldProxy->GetType() == kFloat_t || oldProxy->GetType() == kFloat16_t)
1336  && (newProxy->GetType() == kFloat_t || newProxy->GetType() == kFloat16_t )) {
1337  // We have compatibles collections (they have the same content)!
1338  return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1339  }
1340  return kFALSE;
1341  }
1342 
1343  Bool_t CollectionMatchDouble32(const TClass *oldClass, const TClass* newClass)
1344  {
1345  // Return true if oldClass and newClass points to 2 compatible collection.
1346  // i.e. they contains the exact same type.
1347 
1348  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1349  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1350 
1351  if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1352  && (oldProxy->GetType() == kDouble_t || oldProxy->GetType() == kDouble32_t)
1353  && (newProxy->GetType() == kDouble_t || newProxy->GetType() == kDouble32_t )) {
1354  // We have compatibles collections (they have the same content)!
1355  return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1356  }
1357  return kFALSE;
1358  }
1359 
1360  Bool_t CollectionMatchLong64(const TClass *oldClass, const TClass* newClass)
1361  {
1362  // Return true if oldClass and newClass points to 2 compatible collection.
1363  // i.e. they contains the exact same type.
1364 
1365  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1366  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1367 
1368  if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1369  && (oldProxy->GetType() == kLong_t || oldProxy->GetType() == kLong64_t)
1370  && (newProxy->GetType() == kLong_t || newProxy->GetType() == kLong64_t )) {
1371  // We have compatibles collections (they have the same content)!
1372  return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1373  }
1374  return kFALSE;
1375  }
1376 
1377  Bool_t CollectionMatchULong64(const TClass *oldClass, const TClass* newClass)
1378  {
1379  // Return true if oldClass and newClass points to 2 compatible collection.
1380  // i.e. they contains the exact same type.
1381 
1382  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1383  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1384 
1385  if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1386  && (oldProxy->GetType() == kULong_t || oldProxy->GetType() == kULong64_t)
1387  && (newProxy->GetType() == kULong_t || newProxy->GetType() == kULong64_t )) {
1388  // We have compatibles collections (they have the same content)!
1389  return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1390  }
1391  return kFALSE;
1392  }
1393 
1394  TClass *FindAlternate(TClass *context, const std::string &i_name, std::string& newName)
1395  {
1396  // Return a class whose has the name as oldClass and can be found
1397  // within the scope of the class 'context'.
1398 
1399  // First strip any 'const ' prefix or trailing '*'.
1400  std::string name(i_name);
1401  newName.clear();
1402  if (name.compare(0,6,"const ")==0) {
1403  newName = "const ";
1404  name.erase(0,6);
1405  }
1406  std::string suffix;
1407  UInt_t nstars = 0;
1408  while(name[name.length()-nstars-1]=='*') {
1409  ++nstars;
1410  suffix.append("*");
1411  }
1412  if (nstars) {
1413  name.erase(name.length()-nstars,nstars);
1414  }
1415 
1416  std::string alternate(context->GetName());
1417  alternate.append("::");
1418  alternate.append(name);
1419 
1420  TClass *altcl = TClass::GetClass(alternate.c_str(),/*load=*/ false,true);
1421  if (altcl) {
1422  newName.append(altcl->GetName());
1423  newName.append(suffix);
1424  return altcl;
1425  }
1426 
1427  size_t ctxt_cursor = strlen(context->GetName());
1428  for (size_t level = 0; ctxt_cursor != 0; --ctxt_cursor) {
1429  switch (context->GetName()[ctxt_cursor]) {
1430  case '<': --level; break;
1431  case '>': ++level; break;
1432  case ':': if (level == 0) {
1433  // we encountered a scope not within a template
1434  // parameter.
1435  alternate.clear();
1436  alternate.append(context->GetName(),ctxt_cursor+1);
1437  alternate.append(name);
1438  altcl = TClass::GetClass(alternate.c_str(),/*load=*/ false,true);
1439  if (altcl) {
1440  newName.append(altcl->GetName());
1441  newName.append(suffix);
1442  return altcl;
1443  }
1444  }
1445  }
1446  }
1447  newName.clear();
1448  return 0;
1449  }
1450 
1451  bool HasScope(const std::string &name)
1452  {
1453  // return true if the type name has a scope in it.
1454 
1455  for(size_t i = 0, level = 0; i<name.length(); ++i) {
1456  switch (name[i]) {
1457  case '<': ++level; break;
1458  case '>': --level; break;
1459  case ':': if (level == 0) {
1460  // we encountered a scope not within a template
1461  // parameter.
1462  return true;
1463  }
1464  }
1465  } // for each in name
1466  return false;
1467  }
1468 
1469  TClass *FixCollectionV5(TClass *context, TClass *oldClass, TClass *newClass)
1470  {
1471  assert(oldClass->GetCollectionProxy() && newClass->GetCollectionProxy());
1472 
1473  TVirtualCollectionProxy *old = oldClass->GetCollectionProxy();
1474  TVirtualCollectionProxy *current = newClass->GetCollectionProxy();
1475  Int_t stlkind = old->GetCollectionType();
1476 
1477  if (stlkind == ROOT::kSTLmap || stlkind == ROOT::kSTLmultimap) {
1478 
1479  TVirtualStreamerInfo *info = current->GetValueClass()->GetStreamerInfo();
1480  if (info->GetElements()->GetEntries() != 2) {
1481  return oldClass;
1482  }
1483  TStreamerElement *f = (TStreamerElement*) info->GetElements()->At(0);
1484  TStreamerElement *s = (TStreamerElement*) info->GetElements()->At(1);
1485 
1486  info = old->GetValueClass()->GetStreamerInfo();
1487  assert(info->GetElements()->GetEntries() == 2);
1488  TStreamerElement *of = (TStreamerElement*) info->GetElements()->At(0);
1489  TStreamerElement *os = (TStreamerElement*) info->GetElements()->At(1);
1490 
1491  TClass *firstNewCl = f ? f->GetClass() : 0;
1492  TClass *secondNewCl = s ? s->GetClass() : 0;
1493 
1494  TClass *firstOldCl = of ? of->GetClass() : 0;
1495  TClass *secondOldCl = os ? os->GetClass() : 0;
1496 
1497  if ((firstNewCl && !firstOldCl) || (secondNewCl && !secondOldCl))
1498  {
1499  std::vector<std::string> inside;
1500  int nestedLoc;
1501  TClassEdit::GetSplit( oldClass->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
1502 
1503  TClass *firstAltCl = firstOldCl;
1504  TClass *secondAltCl = secondOldCl;
1505  std::string firstNewName;
1506  std::string secondNewName;
1507  if (firstNewCl && !HasScope(inside[1])) {
1508  firstAltCl = FindAlternate(context, inside[1], firstNewName);
1509  }
1510  if (secondNewCl && !HasScope(inside[2])) {
1511  secondAltCl = FindAlternate(context, inside[2], secondNewName);
1512  }
1513  if ((firstNewCl && firstAltCl != firstOldCl) ||
1514  (secondNewCl && secondAltCl != secondOldCl) ) {
1515 
1516  // Need to produce new name.
1517  std::string alternate = inside[0];
1518  alternate.append("<");
1519  alternate.append(firstAltCl ? firstNewName : inside[1]);
1520  alternate.append(",");
1521  alternate.append(secondAltCl? secondNewName : inside[2]);
1522  // We are intentionally dropping any further arguments,
1523  // they would be using the wrong typename and would also be
1524  // somewhat superflous since this is for the old layout.
1525  if (alternate[alternate.length()-1]=='>') {
1526  alternate.append(" ");
1527  }
1528  alternate.append(">");
1529  return TClass::GetClass(alternate.c_str(),true,true);
1530  }
1531  }
1532 
1533  } else if (current->GetValueClass() && !old->GetValueClass()
1534  && old->GetType() == kInt_t) {
1535 
1536  // The old CollectionProxy claims it contains int (or enums) while
1537  // the new one claims to contain a class. It is likely that we have
1538  // in the collection name a class (typedef) name that is missing its
1539  // scope. Let's try to check.
1540 
1541  std::vector<std::string> inside;
1542  int nestedLoc;
1543  TClassEdit::GetSplit( oldClass->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
1544 
1545  // Does the type already have a scope, in which case,
1546  // (at least for now), let's assume it is already fine.
1547  if (HasScope(inside[1])) {
1548  return oldClass;
1549  }
1550 
1551  // Now let's if we can find this missing type.
1552  std::string newName;
1553  TClass *altcl = FindAlternate(context, inside[1], newName);
1554 
1555  if (altcl) {
1556  std::string alternate = inside[0];
1557  alternate.append("<");
1558  alternate.append(newName);
1559  // We are intentionally dropping any further arguments,
1560  // they would be using the wrong typename and would also be
1561  // somewhat superflous since this is for the old layout.
1562  if (alternate[alternate.length()-1]=='>') {
1563  alternate.append(" ");
1564  }
1565  alternate.append(">");
1566  return TClass::GetClass(alternate.c_str(),true,true);
1567  }
1568  }
1569  return 0;
1570  }
1571 
1572  // Makes sure kBuildOldUsed set once BuildOld finishes
1573  struct TBuildOldGuard {
1574  TBuildOldGuard(TStreamerInfo* info): fInfo(info) {
1575  fInfo->SetBit(TStreamerInfo::kBuildRunning);
1576  }
1577  ~TBuildOldGuard() {
1578  fInfo->ResetBit(TStreamerInfo::kBuildRunning);
1579  fInfo->SetBit(TStreamerInfo::kBuildOldUsed);
1580  }
1581  TStreamerInfo* fInfo;
1582  };
1583 }
1584 
1585 ////////////////////////////////////////////////////////////////////////////////
1586 /// rebuild the TStreamerInfo structure
1587 
1589 {
1591 
1592  if ( TestBit(kBuildOldUsed) ) return;
1593 
1594  // Are we recursing on ourself?
1596 
1597  // This is used to avoid unwanted recursive call to Build and make sure
1598  // that we record the execution of BuildOld.
1599  TBuildOldGuard buildOldGuard(this);
1600 
1601  if (gDebug > 0) {
1602  printf("\n====>Rebuilding TStreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
1603  }
1604 
1605  Bool_t wasCompiled = IsCompiled();
1606 
1607  if (fClass->GetClassVersion() == fClassVersion) {
1609  {
1610  // Handle emulated classes and STL containers specially.
1611  // in this case BuildRealData would call BuildOld for this same
1612  // TStreamerInfo to be able to build the real data on it.
1613  } else {
1614  fClass->BuildRealData();
1615  }
1616  }
1617  else {
1618  // This is to support the following case
1619  // Shared library: Event v2
1620  // calling cl->GetStreamerInfo(1)->BuildOld(); (or equivalent)
1621  // which calls cl->BuildReadData()
1622  // which set fRealData to some value
1623  // then call Event()
1624  // which call cl->GetStreamerInfo()
1625  // which call cl->BuildRealData();
1626  // which returns immediately (upon seeing fRealData!=0)
1627  // then the main StreamerInfo build using the partial content of fRealData
1628  // then BuildRealData returns
1629  // then GetStreamerInfo() returns
1630  // then Event() returns
1631  // then fRealData is finished being populated
1632  // then this function continue,
1633  // then it uses the main streamerInfo
1634  // .... which is incomplete.
1635  //
1636  // Instead we force the creation of the main streamerInfo object
1637  // before the creation of fRealData.
1639  }
1640 
1641  TIter next(fElements);
1642  TStreamerElement* element;
1643  Int_t offset = 0;
1644  TMemberStreamer* streamer = 0;
1645 
1646  Int_t sp = sizeof(void*);
1647 
1648  int nBaze = 0;
1649 
1650  if ((fElements->GetEntries() == 1) && !strcmp(fElements->At(0)->GetName(), "This")) {
1651  if (fClass->GetCollectionProxy()) {
1652  element = (TStreamerElement*)next();
1653  element->SetNewType( element->GetType() );
1654  element->SetNewClass( fClass );
1655  } else if (((TStreamerElement*)fElements->At(0))->GetType() == TStreamerInfo::kSTL &&
1656  strcmp( ((TStreamerElement*)fElements->At(0))->GetTypeName(),GetName()) != 0) {
1657  // We have a collection that was proxied but does not have a collection proxy,
1658  // let's put one in place just for fun ... humm however we have no clue what is the value
1659  // type ....
1660 
1661  // For now wild guess ....
1662 
1663  }
1664  }
1665 
1666  TClass *allocClass = 0;
1667  TStreamerInfo *infoalloc = 0;
1668 
1669  //---------------------------------------------------------------------------
1670  // Get schema rules for this class
1671  /////////////////////////////////////////////////////////////////////////////
1672 
1673  ROOT::TSchemaRuleSet::TMatches rules;
1674  const ROOT::TSchemaRuleSet* ruleSet = fClass->GetSchemaRules();
1675 
1676  if (ruleSet) rules = ruleSet->FindRules( GetName(), fOnFileClassVersion, fCheckSum );
1677 
1679  Int_t virtualInfoLocAlloc = 0;
1680  fNVirtualInfoLoc = 0;
1681  delete [] fVirtualInfoLoc;
1682  fVirtualInfoLoc = 0;
1683 
1684  while ((element = (TStreamerElement*) next())) {
1685  if (element->IsA()==TStreamerArtificial::Class()
1686  || element->TestBit(TStreamerElement::kCache) )
1687  {
1688  // Prevent BuildOld from modifying existing ArtificialElement (We need to review when and why BuildOld
1689  // needs to be re-run; it might be needed if the 'current' class change (for example from being an onfile
1690  // version to being a version loaded from a shared library) and we thus may have to remove the artifical
1691  // element at the beginning of BuildOld)
1692 
1693  continue;
1694  };
1695 
1696  element->SetNewType(element->GetType());
1697  if (element->IsBase()) {
1698  //---------------------------------------------------------------------
1699  // Dealing with nonSTL bases
1700  ///////////////////////////////////////////////////////////////////////
1701 
1702  if (element->IsA() == TStreamerBase::Class()) {
1703  TStreamerBase* base = (TStreamerBase*) element;
1704 #if defined(PROPER_IMPLEMEMANTION_OF_BASE_CLASS_RENAMING)
1705  TClass* baseclass = fClass->GetBaseClass( base->GetName() );
1706 #else
1707  // Currently the base class renaming does not work, so we use the old
1708  // version of the code which essentially disable the next if(!baseclass ..
1709  // statement.
1710  TClass* baseclass = base->GetClassPointer();
1711 #endif
1712 
1713  //------------------------------------------------------------------
1714  // We do not have this base class - check if we're renaming
1715  ////////////////////////////////////////////////////////////////////
1716 
1717  if( !baseclass && !fClass->TestBit( TClass::kIsEmulation ) ) {
1718  const ROOT::TSchemaRule* rule = (rules ? rules.GetRuleWithSource( base->GetName() ) : 0);
1719 
1720  //---------------------------------------------------------------
1721  // No renaming, sorry
1722  /////////////////////////////////////////////////////////////////
1723 
1724  if( !rule ) {
1725  Error("BuildOld", "Could not find base class: %s for %s and could not find any matching rename rule\n", base->GetName(), GetName());
1726  continue;
1727  }
1728 
1729  //----------------------------------------------------------------
1730  // Find a new target class
1731  /////////////////////////////////////////////////////////////////
1732 
1733  const TObjArray* targets = rule->GetTarget();
1734  if( !targets ) {
1735  Error("BuildOld", "Could not find base class: %s for %s, renaming rule was found but is malformed\n", base->GetName(), GetName());
1736  }
1737  TString newBaseClass = ((TObjString*)targets->At(0))->GetString();
1738  baseclass = TClass::GetClass( newBaseClass );
1739  base->SetNewBaseClass( baseclass );
1740  }
1741  //-------------------------------------------------------------------
1742  // No base class in emulated mode
1743  ////////////////////////////////////////////////////////////////////
1744 
1745  else if( !baseclass ) {
1746  baseclass = base->GetClassPointer();
1747  if (!baseclass) {
1748  Warning("BuildOld", "Missing base class: %s skipped", base->GetName());
1749  // FIXME: Why is the version number 1 here? Answer: because we don't know any better at this point
1750  baseclass = new TClass(element->GetName(), 1, 0, 0, -1, -1);
1751  element->Update(0, baseclass);
1752  }
1753  }
1754  baseclass->BuildRealData();
1755 
1756  // Calculate the offset using the 'real' base class name (as opposed to the
1757  // '@@emulated' in the case of the emulation of an abstract base class.
1758  Int_t baseOffset = fClass->GetBaseClassOffset(baseclass);
1759 
1760  // Deal with potential schema evolution (renaming) of the base class.
1761  if (baseOffset < 0) {
1762 
1763  // See if this base element can be converted into one of
1764  // the existing base class.
1765  TList* listOfBases = fClass->GetListOfBases();
1766  if (listOfBases) {
1767  TBaseClass* bc = 0;
1768  TIter nextBC(fClass->GetListOfBases());
1769  while ((bc = (TBaseClass*) nextBC())) {
1770  TClass *in_memory_bcl = bc->GetClassPointer();
1771  if (in_memory_bcl && in_memory_bcl->GetSchemaRules()) {
1772  auto baserule = in_memory_bcl->GetSchemaRules()->FindRules( base->GetName(), base->GetBaseVersion(), base->GetBaseCheckSum() );
1773  if (!baserule.empty()) {
1774  base->SetNewBaseClass(in_memory_bcl);
1775  baseOffset = bc->GetDelta();
1776 
1777  }
1778  }
1779  }
1780  }
1781  }
1782  // We need to initialize the element now, as we need the
1783  // correct StraemerInfo next.
1784  element->Init(this);
1785 
1786  // Force the StreamerInfo "Compilation" of the base classes first. This is necessary in
1787  // case the base class contains a member used as an array dimension in the derived classes.
1788  TStreamerInfo* infobase;
1789  if (fClass->TestBit(TClass::kIsEmulation) && (baseclass->Property() & kIsAbstract)) {
1790  Int_t version = base->GetBaseVersion();
1791  if (version >= 0 || base->GetBaseCheckSum() == 0) {
1792  infobase = (TStreamerInfo*)baseclass->GetStreamerInfoAbstractEmulated(version);
1793  } else {
1794  infobase = (TStreamerInfo*)baseclass->FindStreamerInfoAbstractEmulated(base->GetBaseCheckSum());
1795  }
1796  if (infobase) baseclass = infobase->GetClass();
1797  }
1798  else {
1799  infobase = (TStreamerInfo*)base->GetBaseStreamerInfo();
1800  }
1801 
1802  if (infobase && infobase->fComp == 0) {
1803  infobase->BuildOld();
1804  }
1805 
1806  if (infobase && shouldHaveInfoLoc && baseclass->TestBit(TClass::kIsEmulation) ) {
1807  if ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) > virtualInfoLocAlloc ) {
1808  ULong_t *store = fVirtualInfoLoc;
1809  virtualInfoLocAlloc = 16 * ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) / 16 + 1);
1810  fVirtualInfoLoc = new ULong_t[virtualInfoLocAlloc];
1811  if (store) {
1812  memcpy(fVirtualInfoLoc, store, sizeof(ULong_t)*fNVirtualInfoLoc);
1813  delete [] store;
1814  }
1815  }
1816  for (int nloc = 0; nloc < infobase->fNVirtualInfoLoc; ++nloc) {
1817  fVirtualInfoLoc[ fNVirtualInfoLoc + nloc ] = baseOffset + infobase->fVirtualInfoLoc[nloc];
1818  }
1819  fNVirtualInfoLoc += infobase->fNVirtualInfoLoc;
1820  }
1821 
1822 
1823  {
1824  if (baseOffset < 0) {
1825  element->SetNewType(-1);
1826  }
1827  }
1828  element->SetOffset(baseOffset);
1829  offset += baseclass->Size();
1830 
1831  continue;
1832  } else {
1833  // Not a base elem but still base, string or STL as a base
1834  nBaze++;
1835  TList* listOfBases = fClass->GetListOfBases();
1836  Int_t baseOffset = -1;
1837  Int_t asize = 0;
1838  if (listOfBases) {
1839  // Do a search for the classname and some of its alternatives spelling.
1840 
1841  TBaseClass* bc = 0;
1842  TIter nextBC(fClass->GetListOfBases());
1843  while ((bc = (TBaseClass*) nextBC())) {
1844  if (strchr(bc->GetName(), '<') || !strcmp(bc->GetName(),"string")) {
1847  if (bcName == elName) {
1848  break;
1849  }
1850  }
1851  }
1852 
1853  if (!bc) {
1854  Error("BuildOld", "Could not find STL base class: %s for %s\n", element->GetName(), GetName());
1855  continue;
1856  } else if (bc->GetClassPointer()->GetCollectionProxy()
1857  && !bc->GetClassPointer()->IsLoaded()
1859  Error("BuildOld","The class \"%s\" is compiled and its base class \"%s\" is a collection and we do not have a dictionary for it, we will not be able to read or write this base class.",GetName(),bc->GetName());
1860  offset = kMissing;
1861  element->SetOffset(kMissing);
1862  element->SetNewType(-1);
1863  continue;
1864  }
1865  baseOffset = bc->GetDelta();
1866  asize = bc->GetClassPointer()->Size();
1867 
1868  } else if (fClass->TestBit( TClass::kIsEmulation )) {
1869  // Do a search for the classname and some of its alternatives spelling.
1870 
1872  if (newInfo == this) {
1873  baseOffset = offset;
1874  asize = element->GetSize();
1875  } else if (newInfo) {
1876  TIter newElems( newInfo->GetElements() );
1877  TStreamerElement *newElement;
1878  while( (newElement = (TStreamerElement*)newElems()) ) {
1879  const char *newElName = newElement->GetName();
1880  if (newElement->IsBase() && (strchr(newElName,'<') || !strcmp(newElName,"string")) ) {
1881  TString bcName(TClassEdit::ShortType(newElName, TClassEdit::kDropStlDefault).c_str());
1883  if (bcName == elName) {
1884  break;
1885  }
1886  }
1887  }
1888  if (!newElement) {
1889  Error("BuildOld", "Could not find STL base class: %s for %s\n", element->GetName(), GetName());
1890  continue;
1891  }
1892  baseOffset = newElement->GetOffset();
1893  asize = newElement->GetSize();
1894  }
1895  }
1896  if (baseOffset == -1) {
1897  TClass* cb = element->GetClassPointer();
1898  if (!cb) {
1899  element->SetNewType(-1);
1900  continue;
1901  }
1902  asize = cb->Size();
1903  baseOffset = fClass->GetBaseClassOffset(cb);
1904  }
1905 
1906  // we know how to read but do we know where to read?
1907  if (baseOffset < 0) {
1908  element->SetNewType(-1);
1909  continue;
1910  }
1911  element->SetOffset(baseOffset);
1912  offset += asize;
1913  element->Init(this);
1914  continue;
1915  }
1916  }
1917 
1918  // If we get here, this means that we looked at all the base classes.
1919  if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
1920  fNVirtualInfoLoc = 1;
1921  fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement.
1922  fVirtualInfoLoc[0] = offset;
1923  offset += sizeof(TStreamerInfo*);
1924  }
1925 
1926  TDataMember* dm = 0;
1927 
1928  // First set the offset and sizes.
1929  if (fClass->GetState() <= TClass::kEmulated) {
1930  // Note the initilization in this case are
1931  // delayed until __after__ the schema evolution
1932  // section, just in case the info has changed.
1933 
1934  // We are in the emulated case
1935  streamer = 0;
1936  element->Init(this);
1937  } else {
1938  // The class is known to Cling (and thus is not emulated)
1939  // and we need to use the real offsets.
1940  // However we may not have a 'proper' TClass for it
1941  // (in which case IsLoaded will be false and GetImplFileLine will be -1)
1942 
1943  // First look for the data member in the current class
1944  dm = (TDataMember*) fClass->GetListOfDataMembers()->FindObject(element->GetName());
1945  if (dm && dm->IsPersistent()) {
1946  fClass->BuildRealData();
1947  streamer = 0;
1948  offset = GetDataMemberOffset(dm, streamer);
1949  element->SetOffset(offset);
1950  element->Init(this);
1951  // We have a loaded class, let's make sure that if we have a collection
1952  // it is also loaded.
1954  dmClassName = dmClassName.Strip(TString::kTrailing, '*');
1955  if (dmClassName.Index("const ")==0) dmClassName.Remove(0,6);
1956  TClass *elemDm = !dm->IsBasic() ? TClass::GetClass(dmClassName.Data()) : 0;
1957  if (elemDm && elemDm->GetCollectionProxy()
1958  && !elemDm->IsLoaded()
1960  Error("BuildOld","The class \"%s\" is compiled and for its data member \"%s\", we do not have a dictionary for the collection \"%s\", we will not be able to read or write this data member.",GetName(),dm->GetName(),elemDm->GetName());
1961  offset = kMissing;
1962  element->SetOffset(kMissing);
1963  element->SetNewType(-1);
1964  }
1965  element->SetStreamer(streamer);
1966  int narr = element->GetArrayLength();
1967  if (!narr) {
1968  narr = 1;
1969  }
1970  int dsize = dm->GetUnitSize();
1971  element->SetSize(dsize*narr);
1972  } else {
1973  // We did not find it, let's look for it in the base classes via TRealData
1974  TRealData* rd = fClass->GetRealData(element->GetName());
1975  if (rd && rd->GetDataMember()) {
1976  element->SetOffset(rd->GetThisOffset());
1977  element->Init(this);
1978  dm = rd->GetDataMember();
1979  int narr = element->GetArrayLength();
1980  if (!narr) {
1981  narr = 1;
1982  }
1983  int dsize = dm->GetUnitSize();
1984  element->SetSize(dsize*narr);
1985  }
1986  }
1987  }
1988 
1989  // Now let's deal with Schema evolution
1990  Int_t newType = -1;
1991  TClassRef newClass;
1992 
1993  if (dm && dm->IsPersistent()) {
1994  if (dm->GetDataType()) {
1995  Bool_t isPointer = dm->IsaPointer();
1996  Bool_t isArray = element->GetArrayLength() >= 1;
1997  Bool_t hasCount = element->HasCounter();
1998  // data member is a basic type
1999  if ((fClass == TObject::Class()) && !strcmp(dm->GetName(), "fBits")) {
2000  //printf("found fBits, changing dtype from %d to 15\n", dtype);
2001  newType = kBits;
2002  } else {
2003  // All the values of EDataType have the same semantic in EReadWrite
2004  newType = (EReadWrite)dm->GetDataType()->GetType();
2005  }
2006  if ((newType == ::kChar_t) && isPointer && !isArray && !hasCount) {
2007  newType = ::kCharStar;
2008  } else if (isPointer) {
2009  newType += kOffsetP;
2010  } else if (isArray) {
2011  newType += kOffsetL;
2012  }
2013  }
2014  if (newType == -1) {
2015  newClass = TClass::GetClass(dm->GetTypeName());
2016  }
2017  } else {
2018  // Either the class is not loaded or the data member is gone
2019  if (!fClass->IsLoaded()) {
2021  if (newInfo && (newInfo != this)) {
2022  TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(element->GetName());
2023  newClass = newElems ? newElems->GetClassPointer() : 0;
2024  if (newClass == 0) {
2025  newType = newElems ? newElems->GetType() : -1;
2026  if (!(newType < kObject)) {
2027  // sanity check.
2028  newType = -1;
2029  }
2030  }
2031  } else {
2032  newClass = element->GetClassPointer();
2033  if (newClass.GetClass() == 0) {
2034  newType = element->GetType();
2035  if (!(newType < kObject)) {
2036  // sanity check.
2037  newType = -1;
2038  }
2039  }
2040  }
2041  }
2042  }
2043 
2044  if (newType > 0) {
2045  // Case of a numerical type
2046  if (element->GetType() >= TStreamerInfo::kObject) {
2047  // Old type was not a numerical type.
2048  element->SetNewType(-2);
2049  } else if (element->GetType() != newType) {
2050  element->SetNewType(newType);
2051  if (gDebug > 0) {
2052  // coverity[mixed_enums] - All the values of EDataType have the same semantic in EReadWrite
2053  Info("BuildOld", "element: %s %s::%s has new type: %s/%d", element->GetTypeName(), GetName(), element->GetName(), dm ? dm->GetFullTypeName() : TDataType::GetTypeName((EDataType)newType), newType);
2054  }
2055  }
2056  } else if (newClass.GetClass()) {
2057  // Sometime BuildOld is called again.
2058  // In that case we migth already have fix up the streamer element.
2059  // So we need to go back to the original information!
2060  newClass.Reset();
2062  if (oldClass == newClass.GetClass()) {
2063  // Nothing to do :)
2064  } else if (ClassWasMovedToNamespace(oldClass, newClass.GetClass())) {
2065  Int_t oldv;
2066  if (0 != (oldv = ImportStreamerInfo(oldClass, newClass.GetClass()))) {
2067  Warning("BuildOld", "Can not properly load the TStreamerInfo from %s into %s due to a conflict for the class version %d", oldClass->GetName(), newClass->GetName(), oldv);
2068  } else {
2069  element->SetTypeName(newClass->GetName());
2070  if (gDebug > 0) {
2071  Warning("BuildOld", "element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2072  }
2073  }
2074  } else if (oldClass == TClonesArray::Class()) {
2075  if (ContainerMatchTClonesArray(newClass.GetClass())) {
2076  Int_t elemType = element->GetType();
2077  Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
2078  element->Update(oldClass, newClass.GetClass());
2079  TVirtualCollectionProxy *cp = newClass->GetCollectionProxy();
2080  TConvertClonesArrayToProxy *ms = new TConvertClonesArrayToProxy(cp, element->IsaPointer(), isPrealloc);
2081  element->SetStreamer(ms);
2082 
2083  // When the type is kObject, the TObject::Streamer is used instead
2084  // of the TStreamerElement's streamer. So let force the usage
2085  // of our streamer
2086  if (element->GetType() == kObject) {
2087  element->SetNewType(kAny);
2088  element->SetType(kAny);
2089  }
2090  if (gDebug > 0) {
2091  Warning("BuildOld","element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2092  }
2093  } else {
2094  element->SetNewType(-2);
2095  }
2096  } else if (oldClass && oldClass->GetCollectionProxy() && newClass->GetCollectionProxy()) {
2097  {
2098  TClass *oldFixedClass = FixCollectionV5(GetClass(),oldClass,newClass);
2099  if (oldFixedClass && oldFixedClass != oldClass) {
2100  element->Update(oldClass,oldFixedClass);
2101  oldClass = oldFixedClass;
2102  }
2103  }
2104  if (CollectionMatch(oldClass, newClass)) {
2105  Int_t oldkind = oldClass->GetCollectionType();
2106  Int_t newkind = newClass->GetCollectionType();
2107 
2108  if ( (oldkind==ROOT::kSTLmap || oldkind==ROOT::kSTLmultimap) &&
2109  (newkind!=ROOT::kSTLmap && newkind!=ROOT::kSTLmultimap) ) {
2110 
2111  Int_t elemType = element->GetType();
2112  Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
2113 
2114  TClassStreamer *streamer2 = newClass->GetStreamer();
2115  if (streamer2) {
2116  TConvertMapToProxy *ms = new TConvertMapToProxy(streamer2, element->IsaPointer(), isPrealloc);
2117  if (ms && ms->IsValid()) {
2118  element->SetStreamer(ms);
2119  switch( element->GetType() ) {
2120  //case TStreamerInfo::kSTLvarp: // Variable size array of STL containers.
2121  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
2122  case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
2123  element->SetNewType(-2);
2124  break;
2125  case TStreamerInfo::kSTL: // container with no virtual table (stl) and no comment
2126  case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL: // array of containers with no virtual table (stl) and no comment
2127  break;
2128  }
2129  } else {
2130  delete ms;
2131  }
2132  }
2133  element->Update(oldClass, newClass.GetClass());
2134 
2135  } else if ( (newkind==ROOT::kSTLmap || newkind==ROOT::kSTLmultimap) &&
2136  (oldkind!=ROOT::kSTLmap && oldkind!=ROOT::kSTLmultimap) ) {
2137  element->SetNewType(-2);
2138  } else {
2139  element->Update(oldClass, newClass.GetClass());
2140  }
2141  // Is this needed ? : element->SetSTLtype(newelement->GetSTLtype());
2142  if (gDebug > 0) {
2143  Warning("BuildOld","element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2144  }
2145  } else if (CollectionMatchFloat16(oldClass,newClass)) {
2146  // Actually nothing to do, since both are the same collection of double in memory.
2147  } else if (CollectionMatchDouble32(oldClass,newClass)) {
2148  // Actually nothing to do, since both are the same collection of double in memory.
2149  } else if (CollectionMatchLong64(oldClass,newClass)) {
2150  // Not much to do since both are the same collection of 8 bits entities on file.
2151  element->Update(oldClass, newClass.GetClass());
2152  } else if (CollectionMatchULong64(oldClass,newClass)) {
2153  // Not much to do since both are the same collection of 8 bits unsigned entities on file
2154  element->Update(oldClass, newClass.GetClass());
2155  } else if (newClass->GetSchemaRules()->HasRuleWithSourceClass( oldClass->GetName() )) {
2156  //------------------------------------------------------------------------
2157  // We can convert one type to another (at least for some of the versions).
2158  /////////////////////////////////////////////////////////////////
2159 
2160  element->SetNewClass( newClass );
2161  } else {
2162  element->SetNewType(-2);
2163  }
2164 
2165  } else if(oldClass &&
2166  newClass.GetClass() &&
2167  newClass->GetSchemaRules() &&
2168  newClass->GetSchemaRules()->HasRuleWithSourceClass( oldClass->GetName() ) ) {
2169  //------------------------------------------------------------------------
2170  // We can convert one type to another (at least for some of the versions).
2171  ////////////////////////////////////////////////////////////////////
2172 
2173  element->SetNewClass( newClass );
2174  } else {
2175  element->SetNewType(-2);
2176  }
2177  // Humm we still need to make sure we have the same 'type' (pointer, embedded object, array, etc..)
2178  Bool_t cannotConvert = kFALSE;
2179  if (element->GetNewType() != -2) {
2180  if (dm) {
2181  if (dm->IsaPointer()) {
2182  if (strncmp(dm->GetTitle(),"->",2)==0) {
2183  // We are fine, nothing to do.
2184  if (newClass->IsTObject()) {
2185  newType = kObjectp;
2186  } else if (newClass->GetCollectionProxy()) {
2187  newType = kSTLp;
2188  } else {
2189  newType = kAnyp;
2190  }
2191  } else {
2192  if (TClass::GetClass(dm->GetTypeName())->IsTObject()) {
2193  newType = kObjectP;
2194  } else if (newClass->GetCollectionProxy()) {
2195  newType = kSTLp;
2196  } else {
2197  newType = kAnyP;
2198  }
2199  }
2200  } else {
2201  if (newClass->GetCollectionProxy()) {
2202  newType = kSTL;
2203  } else if (newClass == TString::Class()) {
2204  newType = kTString;
2205  } else if (newClass == TObject::Class()) {
2206  newType = kTObject;
2207  } else if (newClass == TNamed::Class()) {
2208  newType = kTNamed;
2209  } else if (newClass->IsTObject()) {
2210  newType = kObject;
2211  } else {
2212  newType = kAny;
2213  }
2214  }
2215  if ((!dm->IsaPointer() || newType==kSTLp) && dm->GetArrayDim() > 0) {
2216  newType += kOffsetL;
2217  }
2218  } else if (!fClass->IsLoaded()) {
2220  if (newInfo && (newInfo != this)) {
2221  TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(element->GetName());
2222  if (newElems) {
2223  newType = newElems->GetType();
2224  }
2225  } else {
2226  newType = element->GetType();
2227  }
2228  }
2229  if (element->GetType() == kSTL
2230  || ((element->GetType() == kObject || element->GetType() == kAny || element->GetType() == kObjectp || element->GetType() == kAnyp)
2231  && oldClass == TClonesArray::Class()))
2232  {
2233  cannotConvert = (newType != kSTL && newType != kObject && newType != kAny && newType != kSTLp && newType != kObjectp && newType != kAnyp);
2234 
2235  } else if (element->GetType() == kSTLp || ((element->GetType() == kObjectP || element->GetType() == kAnyP) && oldClass == TClonesArray::Class()) )
2236  {
2237  cannotConvert = (newType != kSTL && newType != kObject && newType != kAny && newType != kSTLp && newType != kObjectP && newType != kAnyP);
2238 
2239  } else if (element->GetType() == kSTL + kOffsetL
2240  || ((element->GetType() == kObject + kOffsetL|| element->GetType() == kAny + kOffsetL|| element->GetType() == kObjectp+ kOffsetL || element->GetType() == kAnyp+ kOffsetL)
2241  && oldClass == TClonesArray::Class()))
2242  {
2243  cannotConvert = (newType != kSTL + kOffsetL && newType != kObject+ kOffsetL && newType != kAny+ kOffsetL && newType != kSTLp+ kOffsetL && newType != kObjectp+ kOffsetL && newType != kAnyp+ kOffsetL);
2244 
2245  } else if (element->GetType() == kSTLp + kOffsetL || ((element->GetType() == kObjectP+ kOffsetL || element->GetType() == kAnyP+ kOffsetL) && oldClass == TClonesArray::Class()) )
2246  {
2247  cannotConvert = (newType != kSTL+ kOffsetL && newType != kObject+ kOffsetL && newType != kAny+ kOffsetL && newType != kSTLp + kOffsetL&& newType != kObjectP+ kOffsetL && newType != kAnyP+ kOffsetL);
2248 
2249  } else if ((element->GetType() == kObjectp || element->GetType() == kAnyp
2250  || element->GetType() == kObject || element->GetType() == kAny
2251  || element->GetType() == kTObject || element->GetType() == kTNamed || element->GetType() == kTString )) {
2252  // We had Type* ... ; //-> or Type ...;
2253  // this is completely compatible with the same and with a embedded object.
2254  if (newType != -1) {
2255  if (newType == kObjectp || newType == kAnyp
2256  || newType == kObject || newType == kAny
2257  || newType == kTObject || newType == kTNamed || newType == kTString) {
2258  // We are fine, no transformation to make
2259  element->SetNewType(newType);
2260  } else {
2261  // We do not support this yet.
2262  cannotConvert = kTRUE;
2263  }
2264  } else {
2265  // We have no clue
2266  cannotConvert = kTRUE;
2267  }
2268  } else if (element->GetType() == kObjectP || element->GetType() == kAnyP) {
2269  if (newType != -1) {
2270  if (newType == kObjectP || newType == kAnyP ) {
2271  // nothing to do}
2272  } else {
2273  cannotConvert = kTRUE;
2274  }
2275  } else {
2276  // We have no clue
2277  cannotConvert = kTRUE;
2278  }
2279  }
2280  }
2281  if (cannotConvert) {
2282  element->SetNewType(-2);
2283  if (gDebug > 0) {
2284  // coverity[mixed_enums] - All the values of EDataType have the same semantic in EReadWrite
2285  Info("BuildOld", "element: %s %s::%s has new type: %s/%d", element->GetTypeName(), GetName(), element->GetName(), dm ? dm->GetFullTypeName() : TDataType::GetTypeName((EDataType)newType), newType);
2286  }
2287  }
2288  } else {
2289  element->SetNewType(-1);
2290  offset = kMissing;
2291  element->SetOffset(kMissing);
2292  }
2293 
2294  if (offset != kMissing && fClass->GetState() <= TClass::kEmulated) {
2295  // Note the initialization in this case are
2296  // delayed until __after__ the schema evolution
2297  // section, just in case the info has changed.
2298 
2299  // The class is NOT known to Cling, i.e. is emulated,
2300  // and we need to use the calculated offset.
2301 
2302  Int_t asize;
2303  if (element->GetType() == TStreamerInfo::kSTL &&
2304  strcmp(element->GetName(),"This") == 0 &&
2305  strcmp(element->GetTypeName(),GetName()) == 0 &&
2306  !fClass->GetCollectionProxy()) {
2307  // Humm .. we are missing the collection Proxy
2308  // for a proxied (custom) collection ... avoid
2309  // an infinite recursion and take a wild guess
2310  asize = sizeof(std::vector<int>);
2311  } else {
2312  // Regular case
2313  asize = element->GetSize();
2314  }
2315  // align the non-basic data types (required on alpha and IRIX!!)
2316  if ((offset % sp) != 0) {
2317  offset = offset - (offset % sp) + sp;
2318  }
2319  element->SetOffset(offset);
2320  offset += asize;
2321  }
2322 
2323  if (!wasCompiled && rules) {
2324  if (rules.HasRuleWithSource( element->GetName(), kTRUE ) ) {
2325 
2326  if (allocClass == 0) {
2327  infoalloc = (TStreamerInfo *)Clone(TString::Format("%s@@%d",GetName(),GetOnFileClassVersion()));
2328  if (!infoalloc) {
2329  Error("BuildOld","Unable to create the StreamerInfo for %s.",TString::Format("%s@@%d",GetName(),GetOnFileClassVersion()).Data());
2330  } else {
2331  infoalloc->SetBit(kBuildOldUsed,false);
2332  infoalloc->BuildCheck();
2333  infoalloc->BuildOld();
2334  allocClass = infoalloc->GetClass();
2335  }
2336  }
2337 
2338  // Now that we are caching the unconverted element, we do not assign it to the real type even if we could have!
2339  if (element->GetNewType()>0 /* intentionally not including base class for now */
2340  && !rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2341 
2342  TStreamerElement *copy = (TStreamerElement*)element->Clone();
2343  R__TObjArray_InsertBefore( fElements, copy, element );
2344  next(); // move the cursor passed the insert object.
2346  element = copy;
2347 
2348  // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
2349  } else {
2350  // If the element is just cached and not repeat, we need to inject an element
2351  // to insure the writing.
2352  TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
2353  R__TObjArray_InsertAfter( fElements, writecopy, element );
2354  next(); // move the cursor passed the insert object.
2355  writecopy->SetBit(TStreamerElement::kWrite);
2356  writecopy->SetNewType( writecopy->GetType() );
2357  writecopy->SetBit(TStreamerElement::kCache);
2358  writecopy->SetOffset(infoalloc ? infoalloc->GetOffset(element->GetName()) : 0);
2359  }
2360  element->SetBit(TStreamerElement::kCache);
2361  element->SetNewType( element->GetType() );
2362  element->SetOffset(infoalloc ? infoalloc->GetOffset(element->GetName()) : 0);
2363  } else if (rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2364  // The data member exist in the onfile StreamerInfo and there is a rule
2365  // that has the same member 'only' has a target ... so this means we are
2366  // asked to ignore the input data ...
2367  if (element->GetType() == kCounter) {
2368  // If the element is a counter, we will need its value to read
2369  // other data member, so let's do so (by not disabling it) even
2370  // if the value will be over-written by a rule.
2371  } else {
2372  element->SetOffset(kMissing);
2373  }
2374  }
2375  } else if (rules && rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2376  // The data member exist in the onfile StreamerInfo and there is a rule
2377  // that has the same member 'only' has a target ... so this means we are
2378  // asked to ignore the input data ...
2379  if (element->GetType() == kCounter) {
2380  // If the element is a counter, we will need its value to read
2381  // other data member, so let's do so (by not disabling it) even
2382  // if the value will be over-written by a rule.
2383  } else {
2384  element->SetOffset(kMissing);
2385  }
2386  }
2387 
2388  if (element->GetNewType() == -2) {
2389  Warning("BuildOld", "Cannot convert %s::%s from type: %s to type: %s, skip element", GetName(), element->GetName(), element->GetTypeName(), newClass ? newClass->GetName() : (dm ? dm->GetFullTypeName() : "unknown") );
2390  }
2391  }
2392 
2393  // If we get here, this means that there no data member after the last base class
2394  // (or no base class at all).
2395  if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
2396  fNVirtualInfoLoc = 1;
2397  fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement.
2398  fVirtualInfoLoc[0] = offset;
2399  offset += sizeof(TStreamerInfo*);
2400  }
2401 
2402  // change order , move "bazes" to the end. Workaround old bug
2403  if ((fOldVersion <= 2) && nBaze) {
2404  SetBit(kRecovered);
2405  TObjArray& arr = *fElements;
2406  TObjArray tai(nBaze);
2407  int narr = arr.GetLast() + 1;
2408  int iel;
2409  int jel = 0;
2410  int kel = 0;
2411  for (iel = 0; iel < narr; ++iel) {
2412  element = (TStreamerElement*) arr[iel];
2413  if (element->IsBase() && (element->IsA() != TStreamerBase::Class())) {
2414  tai[kel++] = element;
2415  } else {
2416  arr[jel++] = element;
2417  }
2418  }
2419  for (kel = 0; jel < narr;) {
2420  arr[jel++] = tai[kel++];
2421  }
2422  }
2423 
2424  // Now add artificial TStreamerElement (i.e. rules that creates new members or set transient members).
2425  if (!wasCompiled) InsertArtificialElements(rules);
2426 
2427  if (!wasCompiled && allocClass) {
2428 
2429  TStreamerElement *el = new TStreamerArtificial("@@alloc","", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
2430  R__TObjArray_InsertAt( fElements, el, 0 );
2431 
2432  el = new TStreamerArtificial("@@dealloc","", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
2433  fElements->Add( el );
2434  }
2435 
2436  Compile();
2437 }
2438 
2439 ////////////////////////////////////////////////////////////////////////////////
2440 /// If opt cointains 'built', reset this StreamerInfo as if Build or BuildOld
2441 /// was never called on it (usefull to force their re-running).
2442 
2444 {
2445  TString opt = option;
2446  opt.ToLower();
2447 
2448  if (opt.Contains("build")) {
2450 
2451  delete [] fComp; fComp = 0;
2452  delete [] fCompFull; fCompFull= 0;
2453  delete [] fCompOpt; fCompOpt = 0;
2454  fNdata = 0;
2455  fNfulldata = 0;
2456  fNslots= 0;
2457  fSize = 0;
2458  ResetIsCompiled();
2460 
2467  }
2468 }
2469 
2470 namespace {
2471  // TMemberInfo
2472  // Local helper class to be able to compare data member represened by
2473  // 2 distinct TStreamerInfos
2474  class TMemberInfo {
2475  public:
2476  TClass *fParent;
2477  TString fName;
2478  TString fClassName;
2479  TString fComment;
2480  Int_t fDataType;
2481 
2482  TMemberInfo(TClass *parent) : fParent(parent) {};
2483 
2484  void SetDataType(Int_t datatype) {
2485  fDataType = datatype;
2486  }
2487 
2488  void SetName(const char *name) {
2489  fName = name;
2490  }
2491  void SetClassName(const char *name) {
2493  }
2494  void SetComment(const char *title) {
2495  const char *left = strstr(title,"[");
2496  if (left) {
2497  const char *right = strstr(left,"]");
2498  if (right) {
2499  ++left;
2500  fComment.Append(left,right-left);
2501  }
2502  }
2503  }
2504  void Clear() {
2505  fName.Clear();
2506  fClassName.Clear();
2507  fComment.Clear();
2508  }
2509  /* Hide this not yet used implementation to suppress warnings message
2510  from icc 11
2511  Bool_t operator==(const TMemberInfo &other) {
2512  return fName==other.fName
2513  && fClassName == other.fClassName
2514  && fComment == other.fComment;
2515  }
2516  */
2517  Bool_t operator!=(const TMemberInfo &other) {
2518  if (fName != other.fName) return kTRUE;
2519  if (fDataType < TStreamerInfo::kObject) {
2520  // For simple type, let compare the data type
2521  if (fDataType != other.fDataType) {
2522  if ( (fDataType == 4 && other.fDataType == 16)
2523  || (fDataType == 16 && other.fDataType == 4) ) {
2524  // long and 'long long' have the same file format
2525  } else if ( (fDataType == 14 && other.fDataType == 17)
2526  || (fDataType == 17 && other.fDataType == 14) ) {
2527  // unsigned long and 'unsigned long long' have the same file format
2528  } else if ( (fDataType == 3 && other.fDataType == 6)
2529  ||(fDataType == 6 && other.fDataType == 3) ){
2530  // Int_t and kCounter. As the switch from Int_t (3) to
2531  // kCounter (6) might be triggered by a derived class using
2532  // the field as an array size, the class itself has no
2533  // control on what the field type really use.
2534  } else {
2535  return kTRUE;
2536  }
2537  }
2538  } else if (fClassName != other.fClassName) {
2539  if ( (fClassName == "long" && (other.fClassName == "long long" || other.fClassName == "Long64_t"))
2540  || ( (fClassName == "long long" || fClassName == "Long64_t") && other.fClassName == "long") ) {
2541  // This is okay both have the same on file format.
2542  } else if ( (fClassName == "unsigned long" && (other.fClassName == "unsigned long long" || other.fClassName == "ULong64_t"))
2543  || ( (fClassName == "unsigned long long" || fClassName == "ULong64_t") && other.fClassName == "unsigned long") ) {
2544  // This is okay both have the same on file format.
2545  } else if (TClassEdit::IsSTLCont(fClassName)) {
2547  TString othername = TClassEdit::ShortType( other.fClassName, TClassEdit::kDropStlDefault );
2548  if (name != othername) {
2549  TClass *cl = TClass::GetClass(name);
2550  TClass *otherCl = TClass::GetClass(othername);
2551  if (!CollectionMatch(cl,otherCl)) {
2552  TClass *oldFixedClass = FixCollectionV5(fParent,cl,otherCl);
2553  if (!oldFixedClass || !CollectionMatch(oldFixedClass,otherCl)) {
2554  return kTRUE;
2555  }
2556  }
2557  }
2558  } else {
2559  return kTRUE;
2560  }
2561  }
2562  return fComment != other.fComment;
2563  }
2564  };
2565 }
2566 
2567 ////////////////////////////////////////////////////////////////////////////////
2568 /// Emulated a call ShowMembers() on the obj of this class type, passing insp and parent.
2569 
2570 void TStreamerInfo::CallShowMembers(const void* obj, TMemberInspector &insp, Bool_t isTransient) const
2571 {
2572  TIter next(fElements);
2573  TStreamerElement* element = (TStreamerElement*) next();
2574 
2575  TString elementName;
2576 
2577  for (; element; element = (TStreamerElement*) next()) {
2578 
2579  // Skip elements which have not been allocated memory.
2580  if (element->GetOffset() == kMissing) {
2581  continue;
2582  }
2583 
2584  char* eaddr = ((char*)obj) + element->GetOffset();
2585 
2586  if (element->IsBase()) {
2587  // Nothing to do this round.
2588  } else if (element->IsaPointer()) {
2589  elementName.Form("*%s",element->GetFullName());
2590  insp.Inspect(fClass, insp.GetParent(), elementName.Data(), eaddr, isTransient);
2591  } else {
2592  insp.Inspect(fClass, insp.GetParent(), element->GetFullName(), eaddr, isTransient);
2593  Int_t etype = element->GetType();
2594  switch(etype) {
2595  case kObject:
2596  case kAny:
2597  case kTObject:
2598  case kTString:
2599  case kTNamed:
2600  case kSTL:
2601  {
2602  TClass *ecl = element->GetClassPointer();
2603  if (ecl && (fClass!=ecl /* This happens 'artificially for stl container see the use of "This" */)) {
2604  insp.InspectMember(ecl, eaddr, TString(element->GetName()) + ".", isTransient);
2605  }
2606  break;
2607  }
2608  } // switch(etype)
2609  } // if IsaPointer()
2610  } // Loop over elements
2611 
2612  // And now do the base classes
2613  next.Reset();
2614  element = (TStreamerElement*) next();
2615  for (; element; element = (TStreamerElement*) next()) {
2616  if (element->IsBase()) {
2617  // Skip elements which have not been allocated memory.
2618  if (element->GetOffset() == kMissing) {
2619  continue;
2620  }
2621 
2622  char* eaddr = ((char*)obj) + element->GetOffset();
2623 
2624  TClass *ecl = element->GetClassPointer();
2625  if (ecl) {
2626  ecl->CallShowMembers(eaddr, insp, isTransient);
2627  }
2628  } // If is a abse
2629  } // Loop over elements
2630 }
2631 
2632 ////////////////////////////////////////////////////////////////////////////////
2633 /// Make a clone of an object using the Streamer facility.
2634 /// If newname is specified, this will be the name of the new object.
2635 
2636 TObject *TStreamerInfo::Clone(const char *newname) const
2637 {
2638  TStreamerInfo *newinfo = (TStreamerInfo*)TNamed::Clone(newname);
2639  if (newname && newname[0] && fName != newname) {
2640  TObjArray *newelems = newinfo->GetElements();
2641  Int_t ndata = newelems->GetEntries();
2642  for(Int_t i = 0; i < ndata; ++i) {
2643  TObject *element = newelems->UncheckedAt(i);
2644  if (element->IsA() == TStreamerLoop::Class()) {
2645  TStreamerLoop *eloop = (TStreamerLoop*)element;
2646  if (fName == eloop->GetCountClass()) {
2647  eloop->SetCountClass(newname);
2648  eloop->Init();
2649  }
2650  } else if (element->IsA() == TStreamerBasicPointer::Class()) {
2651  TStreamerBasicPointer *eptr = (TStreamerBasicPointer*)element;
2652  if (fName == eptr->GetCountClass()) {
2653  eptr->SetCountClass(newname);
2654  eptr->Init();
2655  }
2656  }
2657  }
2658  }
2659  return newinfo;
2660 }
2661 
2662 ////////////////////////////////////////////////////////////////////////////////
2663 /// Return True if the current StreamerInfo in cl or info is equivalent to this TStreamerInfo.
2664 ///
2665 /// In this context 'Equivalent' means the same number of persistent data member which the same actual C++ type and
2666 /// the same name.
2667 /// If 'warn' is true, Warning message are printed to explicit the differences.
2668 /// If 'complete' is false, stop at the first error, otherwise continue until all members have been checked.
2669 
2671 {
2672  Bool_t result = kTRUE;
2673  R__ASSERT( (cl==0 || info==0) && (cl!=0 || info!=0) /* must compare to only one thhing! */);
2674 
2675  TString name;
2676  TString type;
2677  TStreamerElement *el;
2678  TStreamerElement *infoel = 0;
2679 
2680  TIter next(GetElements());
2681  TIter infonext((TList*)0);
2682  TIter basenext((TList*)0);
2683  TIter membernext((TList*)0);
2684  if (info) {
2685  infonext = info->GetElements();
2686  }
2687  if (cl) {
2688  TList *tlb = cl->GetListOfBases();
2689  if (tlb) { // Loop over bases
2690  basenext = tlb;
2691  }
2692  tlb = cl->GetListOfDataMembers();
2693  if (tlb) {
2694  membernext = tlb;
2695  }
2696  }
2697 
2698  // First let's compare base classes
2699  Bool_t done = kFALSE;
2700  TString localClass;
2701  TString otherClass;
2702  while(!done) {
2703  localClass.Clear();
2704  otherClass.Clear();
2705  el = (TStreamerElement*)next();
2706  if (el && el->IsBase()) {
2707  localClass = el->GetName();
2708  } else {
2709  el = 0;
2710  }
2711  if (cl) {
2712  TBaseClass *tbc = (TBaseClass*)basenext();
2713  if (tbc) {
2714  otherClass = tbc->GetName();
2715  } else if (el==0) {
2716  done = kTRUE;
2717  break;
2718  }
2719  } else {
2720  infoel = (TStreamerElement*)infonext();
2721  if (infoel && infoel->IsBase()) {
2722  otherClass = infoel->GetName();
2723  } else if (el==0) {
2724  done = kTRUE;
2725  break;
2726  }
2727  }
2728  if (TClassEdit::IsSTLCont(localClass)) {
2729  localClass = TClassEdit::ShortType( localClass, TClassEdit::kDropStlDefault );
2730  otherClass = TClassEdit::ShortType( otherClass, TClassEdit::kDropStlDefault );
2731  }
2732  // Need to normalize the name
2733  if (localClass != otherClass) {
2734  if (warn) {
2735  if (el==0) {
2736  Warning("CompareContent",
2737  "The in-memory layout version %d for class '%s' has a base class (%s) that the on-file layout version %d does not have.",
2738  GetClassVersion(), GetName(), otherClass.Data(), GetClassVersion());
2739  } else if (otherClass.Length()==0) {
2740  Warning("CompareContent",
2741  "The on-file layout version %d for class '%s' has a base class (%s) that the in-memory layout version %d does not have",
2742  GetClassVersion(), GetName(), localClass.Data(), GetClassVersion());
2743  } else {
2744  Warning("CompareContent",
2745  "One base class of the on-file layout version %d and of the in memory layout version %d for '%s' is different: '%s' vs '%s'",
2746  GetClassVersion(), GetClassVersion(), GetName(), localClass.Data(), otherClass.Data());
2747  }
2748  }
2749  if (!complete) return kFALSE;
2750  result = result && kFALSE;
2751  }
2752  if (cl) {
2753  TStreamerBase *localBase = dynamic_cast<TStreamerBase*>(el);
2754  if (!localBase) continue;
2755  // We already have localBaseClass == otherBaseClass
2756  TClass *otherBaseClass = localBase->GetClassPointer();
2757  if (!otherBaseClass) continue;
2758  if (otherBaseClass->IsVersioned() && localBase->GetBaseVersion() != otherBaseClass->GetClassVersion()) {
2759  TString msg;
2760  msg.Form(" The StreamerInfo of class %s read from %s%s\n"
2761  " has the same version (=%d) as the active class but a different checksum.\n"
2762  " You should update the version to ClassDef(%s,%d).\n"
2763  " The objects on this file might not be readable because:\n"
2764  " The in-memory layout version %d for class '%s' has a base class (%s) with version %d but the on-file layout version %d recorded the version number %d for this base class (%s).",
2765  GetName(), file ? "file " : "", file ? file->GetName() : "", fClassVersion, GetName(), fClassVersion + 1,
2766  GetClassVersion(), GetName(), otherClass.Data(), otherBaseClass->GetClassVersion(),
2767  GetClassVersion(), localBase->GetBaseVersion(), localClass.Data());
2768  TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2769  otherBase->SetErrorMessage(msg);
2770 
2771  } else if (!otherBaseClass->IsVersioned() && localBase->GetBaseCheckSum() != otherBaseClass->GetCheckSum()) {
2772  TVirtualStreamerInfo *localBaseInfo = otherBaseClass->FindStreamerInfo(localBase->GetBaseCheckSum());
2773  if (!localBaseInfo) {
2774  // We are likely in the situation where the base class comes after the derived
2775  // class in the TFile's list of StreamerInfo, so it has not yet been loaded,
2776  // let's see if it is there.
2777  const TList *list = file->GetStreamerInfoCache();
2778  localBaseInfo = list ? (TStreamerInfo*)list->FindObject(localBase->GetName()) : 0;
2779  }
2780  if (!localBaseInfo) {
2781  TString msg;
2782  msg.Form(" The StreamerInfo of the base class %s (of class %s) read from %s%s\n"
2783  " refers to a checksum (%x) that can not be found neither in memory nor in the file.\n",
2784  otherBaseClass->GetName(), localClass.Data(),
2785  file ? "file " : "", file ? file->GetName() : "",
2786  localBase->GetBaseCheckSum()
2787  );
2788  TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2789  otherBase->SetErrorMessage(msg);
2790  continue;
2791  }
2792  if (localBaseInfo->CompareContent(otherBaseClass,0,kFALSE,kFALSE,file) ) {
2793  // They are equivalent, no problem.
2794  continue;
2795  }
2796  TString msg;
2797  msg.Form(" The StreamerInfo of class %s read from %s%s\n"
2798  " has the same version (=%d) as the active class but a different checksum.\n"
2799  " You should update the version to ClassDef(%s,%d).\n"
2800  " The objects on this file might not be readable because:\n"
2801  " The in-memory layout version %d for class '%s' has a base class (%s) with checksum %x but the on-file layout version %d recorded the checksum value %x for this base class (%s).",
2802  GetName(), file ? "file " : "", file ? file->GetName() : "", fClassVersion, GetName(), fClassVersion + 1,
2803  GetClassVersion(), GetName(), otherClass.Data(), otherBaseClass->GetCheckSum(),
2804  GetClassVersion(), localBase->GetBaseCheckSum(), localClass.Data());
2805  TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2806  otherBase->SetErrorMessage(msg);
2807  }
2808  } else {
2809  TStreamerBase *localBase = dynamic_cast<TStreamerBase*>(el);
2810  TStreamerBase *otherBase = dynamic_cast<TStreamerBase*>(infoel);
2811  if (!localBase || !otherBase) continue;
2812 
2813  // We already have localBaseClass == otherBaseClass
2814  TClass *otherBaseClass = localBase->GetClassPointer();
2815  if (otherBaseClass->IsVersioned() && localBase->GetBaseVersion() != otherBase->GetBaseVersion()) {
2816  TString msg;
2817  msg.Form(" The StreamerInfo of class %s read from %s%s\n"
2818  " has the same version (=%d) as the active class but a different checksum.\n"
2819  " You should update the version to ClassDef(%s,%d).\n"
2820  " The objects on this file might not be readable because:\n"
2821  " The in-memory layout version %d for class '%s' has a base class (%s) with version %d but the on-file layout version %d recorded the version number %d for this base class (%s).",
2822  GetName(), file ? "file " : "", file ? file->GetName() : "", fClassVersion, GetName(), fClassVersion + 1,
2823  GetClassVersion(), GetName(), otherClass.Data(), otherBase->GetBaseVersion(),
2824  GetClassVersion(), localBase->GetBaseVersion(), localClass.Data());
2825  otherBase->SetErrorMessage(msg);
2826 
2827  } else if (!otherBaseClass->IsVersioned() && localBase->GetBaseCheckSum() != otherBase->GetBaseCheckSum())
2828  {
2829  TVirtualStreamerInfo *localBaseInfo = otherBaseClass->FindStreamerInfo(localBase->GetBaseCheckSum());
2830  TVirtualStreamerInfo *otherBaseInfo = otherBaseClass->FindStreamerInfo(otherBase->GetBaseCheckSum());
2831  if (localBaseInfo == otherBaseInfo ||
2832  localBaseInfo->CompareContent(0,otherBaseInfo,kFALSE,kFALSE,file) ) {
2833  // They are equivalent, no problem.
2834  continue;
2835  }
2836  TString msg;
2837  msg.Form(" The StreamerInfo of class %s read from %s%s\n"
2838  " has the same version (=%d) as the active class but a different checksum.\n"
2839  " You should update the version to ClassDef(%s,%d).\n"
2840  " The objects on this file might not be readable because:\n"
2841  " The in-memory layout version %d for class '%s' has a base class (%s) with checksum %x but the on-file layout version %d recorded the checksum value %x for this base class (%s).",
2842  GetName(), file ? "file " : "", file ? file->GetName() : "", fClassVersion, GetName(), fClassVersion + 1,
2843  GetClassVersion(), GetName(), otherClass.Data(), otherBase->GetBaseCheckSum(),
2844  GetClassVersion(), localBase->GetBaseCheckSum(), localClass.Data());
2845  otherBase->SetErrorMessage(msg);
2846  }
2847  }
2848  }
2849  if (!result && !complete) {
2850  return result;
2851  }
2852  // Next the datamembers
2853  done = kFALSE;
2854  next.Reset();
2855  infonext.Reset();
2856 
2857  TMemberInfo local(GetClass());
2858  TMemberInfo other(cl ? cl : info->GetClass());
2859  UInt_t idx = 0;
2860  while(!done) {
2861  local.Clear();
2862  other.Clear();
2863  el = (TStreamerElement*)next();
2864  while (el && (el->IsBase() || el->IsA() == TStreamerArtificial::Class())) {
2865  el = (TStreamerElement*)next();
2866  ++idx;
2867  }
2868  if (el) {
2869  local.SetName( el->GetName() );
2870  local.SetClassName( el->GetTypeName() );
2871  local.SetComment( el->GetTitle() );
2872  local.SetDataType( el->GetType() );
2873  }
2874  if (cl) {
2875  TDataMember *tdm = (TDataMember*)membernext();
2876  while(tdm && ( (!tdm->IsPersistent()) || (tdm->Property()&kIsStatic) || (el && local.fName != tdm->GetName()) )) {
2877  tdm = (TDataMember*)membernext();
2878  }
2879  if (tdm) {
2880  other.SetName( tdm->GetName() );
2881  other.SetClassName( tdm->GetTrueTypeName() );
2882  other.SetComment( tdm->GetTitle() );
2883  if (tdm->GetDataType()) {
2884  // Need to update the type for arrays.
2885  if (tdm->IsaPointer()) {
2886  if (tdm->GetDataType()->GetType() == TVirtualStreamerInfo::kChar && !tdm->GetArrayDim() && tdm->GetArrayIndex()[0]==0) {
2887  other.SetDataType( TVirtualStreamerInfo::kCharStar );
2888  } else {
2889  other.SetDataType( tdm->GetDataType()->GetType() + TVirtualStreamerInfo::kOffsetP);
2890  }
2891  } else {
2892  if (tdm->GetArrayDim()) {
2893  other.SetDataType( tdm->GetDataType()->GetType() + TVirtualStreamerInfo::kOffsetL);
2894  } else {
2895  other.SetDataType( tdm->GetDataType()->GetType() );
2896  }
2897  }
2898  }
2899  } else if (el==0) {
2900  done = kTRUE;
2901  break;
2902  }
2903  } else {
2904  infoel = (TStreamerElement*)infonext();
2905  while (infoel && (infoel->IsBase() || infoel->IsA() == TStreamerArtificial::Class())) {
2906  infoel = (TStreamerElement*)infonext();
2907  }
2908  if (infoel) {
2909  other.SetName( infoel->GetName() );
2910  other.SetClassName( infoel->GetTypeName() );
2911  other.SetComment( infoel->GetTitle() );
2912  other.SetDataType( infoel->GetType() );
2913  } else if (el==0) {
2914  done = kTRUE;
2915  break;
2916  }
2917  }
2918  if (local!=other) {
2919  if (warn) {
2920  if (!el) {
2921  Warning("CompareContent","The following data member of\nthe in-memory layout version %d of class '%s' is missing from \nthe on-file layout version %d:\n"
2922  " %s %s; //%s"
2924  ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
2925 
2926  } else if (other.fName.Length()==0) {
2927  Warning("CompareContent","The following data member of\nthe in-memory layout version %d of class '%s' is missing from \nthe on-file layout version %d:\n"
2928  " %s %s; //%s"
2930  ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data());
2931  } else {
2932  Warning("CompareContent","The following data member of\nthe on-file layout version %d of class '%s' differs from \nthe in-memory layout version %d:\n"
2933  " %s %s; //%s\n"
2934  "vs\n"
2935  " %s %s; //%s"
2937  ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data()
2938  ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
2939  }
2940  }
2941  result = result && kFALSE;
2942  if (!complete) return result;
2943  }
2944  ++idx;
2945  }
2946  return result;
2947 }
2948 
2949 
2950 ////////////////////////////////////////////////////////////////////////////////
2951 /// Compute total size of all persistent elements of the class
2952 
2954 {
2955  TStreamerElement *element = (TStreamerElement*)fElements->Last();
2956  //faster and more precise to use last element offset +size
2957  //on 64 bit machines, offset may be forced to be a multiple of 8 bytes
2958  fSize = element ? element->GetOffset() + element->GetSize() : 0;
2959  if (fNVirtualInfoLoc > 0 && (fVirtualInfoLoc[0]+sizeof(TStreamerInfo*)) >= (ULong_t)fSize) {
2960  fSize = fVirtualInfoLoc[0] + sizeof(TStreamerInfo*);
2961  }
2962 }
2963 
2964 ////////////////////////////////////////////////////////////////////////////////
2965 /// Recursively mark streamer infos for writing to a file.
2966 ///
2967 /// Will force this TStreamerInfo to the file and also
2968 /// all the dependencies.
2969 /// If argument force > 0 the loop on class dependencies is forced.
2970 /// This function is called when streaming a class that contains
2971 /// a null pointer. In this case, the TStreamerInfo for the class
2972 /// with the null pointer must be written to the file and also all
2973 /// the TStreamerInfo of all the classes referenced by the class.
2974 /// We must be given a file to write to.
2975 
2977 {
2978  if (!file) {
2979  return;
2980  }
2981  // Get the given file's list of streamer infos marked for writing.
2982  TArrayC* cindex = file->GetClassIndex();
2983  //the test below testing fArray[fNumber]>1 is to avoid a recursivity
2984  //problem in some cases like:
2985  // class aProblemChild: public TNamed {
2986  // aProblemChild *canBeNull;
2987  // };
2988  if ( // -- Done if already marked, and we are not forcing, or forcing is blocked.
2989  (cindex->fArray[fNumber] && !force) || // Streamer info is already marked, and not forcing, or
2990  (cindex->fArray[fNumber] > 1) // == 2 means ignore forcing to prevent infinite recursion.
2991  ) {
2992  return;
2993  }
2994  // We do not want to write streamer info to the file
2995  // for std::string.
2996  static TClassRef string_classref("string");
2997  if (fClass == string_classref) { // We are std::string.
2998  return;
2999  }
3000  // We do not want to write streamer info to the file
3001  // for STL containers.
3002  if (fClass==0) {
3003  // Build or BuildCheck has not been called yet.
3004  // Let's use another means of checking.
3005  if (fElements && fElements->GetEntries()==1 && strcmp("This",fElements->UncheckedAt(0)->GetName())==0) {
3006  // We are an STL collection.
3007  return;
3008  }
3009  } else if (fClass->GetCollectionProxy()) { // We are an STL collection.
3010  return;
3011  }
3012  // Mark ourselves for output, and block
3013  // forcing to prevent infinite recursion.
3014  cindex->fArray[fNumber] = 2;
3015  // Signal the file that the marked streamer info list has changed.
3016  cindex->fArray[0] = 1;
3017  // Recursively mark the streamer infos for
3018  // all of our elements.
3019  TIter next(fElements);
3020  TStreamerElement* element = (TStreamerElement*) next();
3021  for (; element; element = (TStreamerElement*) next()) {
3022  if (element->IsTransient()) continue;
3023  TClass* cl = element->GetClassPointer();
3024  if (cl) {
3025  TVirtualStreamerInfo* si = 0;
3026  if (cl->Property() & kIsAbstract) {
3027  // If the class of the element is abstract, register the
3028  // TStreamerInfo only if it has already been built.
3029  // Otherwise call cl->GetStreamerInfo() would generate an
3030  // incorrect StreamerInfo.
3031  si = cl->GetCurrentStreamerInfo();
3032  } else {
3033  si = cl->GetStreamerInfo();
3034  }
3035  if (si) {
3036  si->ForceWriteInfo(file, force);
3037  }
3038  }
3039  }
3040 }
3041 
3042 ////////////////////////////////////////////////////////////////////////////////
3043 /// Assuming that obj points to (the part of) an object that is of the
3044 /// type described by this streamerInfo, return the actual type of the
3045 /// object (i.e. the type described by this streamerInfo is a base class
3046 /// of the actual type of the object.
3047 /// This routine should only be called if the class decribed by this
3048 /// StreamerInfo is 'emulated'.
3049 
3050 TClass *TStreamerInfo::GetActualClass(const void *obj) const
3051 {
3052  R__ASSERT(!fClass->IsLoaded());
3053 
3054  if (fNVirtualInfoLoc != 0) {
3055  TStreamerInfo *allocator = *(TStreamerInfo**)( (const char*)obj + fVirtualInfoLoc[0] );
3056  if (allocator) return allocator->GetClass();
3057  }
3058  return (TClass*)fClass;
3059 }
3060 
3061 ////////////////////////////////////////////////////////////////////////////////
3062 /// Return true if the checksum passed as argument is one of the checksum
3063 /// value produced by the older checksum calulcation algorithm.
3064 
3066 {
3067  for(UInt_t i = 1; i < TClass::kLatestCheckSum; ++i) {
3068  if ( checksum == GetCheckSum( (TClass::ECheckSum) i) ) return kTRUE;
3069  }
3070  return kFALSE;
3071 }
3072 
3073 ////////////////////////////////////////////////////////////////////////////////
3074 /// Recalculate the checksum of this TStreamerInfo based on its code.
3075 ///
3076 /// The class ckecksum is used by the automatic schema evolution algorithm
3077 /// to uniquely identify a class version.
3078 /// The check sum is built from the names/types of base classes and
3079 /// data members.
3080 /// The valid range of code is determined by ECheckSum.
3081 /// - kNoEnum: data members of type enum are not counted in the checksum
3082 /// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
3083 /// - kWithTypeDef: use the sugared type name in the calculation.
3084 ///
3085 /// This is needed for backward compatibility.
3086 /// ### WARNING
3087 /// This function must be kept in sync with TClass::GetCheckSum.
3088 /// They are both used to handle backward compatibility and should both return the same values.
3089 /// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
3090 /// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
3091 /// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
3092 
3094 {
3095  // kCurrentCheckSum (0) should be kept for backward compatibility, to be
3096  // able to use the inequality checks, we need to set the code to the largest
3097  // value.
3099 
3100  UInt_t id = 0;
3101 
3102  int il;
3103  TString name = GetName();
3104  TString type;
3105  il = name.Length();
3106  for (int i=0; i<il; i++) id = id*3+name[i];
3107 
3108  TIter next(GetElements());
3109  TStreamerElement *el;
3110  while ( (el=(TStreamerElement*)next()) && !fClass->GetCollectionProxy()) { // loop over bases if not a proxied collection
3111  if (el->IsBase()) {
3112  name = el->GetName();
3113  il = name.Length();
3114  for (int i=0; i<il; i++) id = id*3+name[i];
3115  if (code > TClass::kNoBaseCheckSum && el->IsA() == TStreamerBase::Class()) {
3116  TStreamerBase *base = (TStreamerBase*)el;
3117  id = id*3 + base->GetBaseCheckSum();
3118  }
3119  }
3120  } /* End of Base Loop */
3121 
3122  next.Reset();
3123  while ( (el=(TStreamerElement*)next()) ) {
3124  if (el->IsBase()) continue;
3125 
3126  // humm can we tell if a TStreamerElement is an enum?
3127  // Maybe something like:
3128  Bool_t isenum = kFALSE;
3129  if ( el->GetType()==3 && gROOT->GetType(el->GetTypeName())==0) {
3130  // If the type is not an enum but a typedef to int then
3131  // el->GetTypeName() should be return 'int'
3132  isenum = kTRUE;
3133  }
3134  if ( (code > TClass::kNoEnum) && isenum) id = id*3 + 1;
3135 
3136  name = el->GetName(); il = name.Length();
3137 
3138  int i;
3139  for (i=0; i<il; i++) id = id*3+name[i];
3140 
3141  if (code == TClass::kReflex || code == TClass::kReflexNoComment) {
3142  // With TClass::kReflexV5 we do not want the Long64 in the name
3143  // nor any typedef.
3145 
3146  } else if (code <= TClass::kWithTypeDef) {
3147  // humm ... In the streamerInfo we only have the desugared/normalized
3148  // names, so we are unable to calculate the name with typedefs ...
3149  // except for the case of the ROOT typedef (Int_t, etc.) which are
3150  // kept by TClassEdit::ResolveTypedef(typeName) but not by TCling's
3151  // normalization ...
3152  //
3153  type = el->GetTypeName();
3154  } else {
3156  }
3157  if (TClassEdit::IsSTLCont(type)) {
3159  }
3160  if (code == TClass::kReflex || code == TClass::kReflexNoComment) {
3161  type.ReplaceAll("ULong64_t","unsigned long long");
3162  type.ReplaceAll("Long64_t","long long");
3163  type.ReplaceAll("signed char","char");
3164  type.ReplaceAll("<signed char","<char");
3165  type.ReplaceAll(",signed char",",char");
3166  if (type=="signed char") type = "char";
3167  }
3168 
3169  il = type.Length();
3170  for (i=0; i<il; i++) id = id*3+type[i];
3171 
3172  int dim = el->GetArrayDim();
3173  if (dim) {
3174  for (i=0;i<dim;i++) id = id*3+el->GetMaxIndex(i);
3175  }
3176 
3177 
3178  if (code > TClass::kNoRange) {
3179  const char *left;
3180  if (code > TClass::kNoRangeCheck)
3182  else
3183  left = strstr(el->GetTitle(),"[");
3184  if (left) {
3185  const char *right = strstr(left,"]");
3186  if (right) {
3187  ++left;
3188  while (left != right) {
3189  id = id*3 + *left;
3190  ++left;
3191  }
3192  }
3193  }
3194  }
3195  }
3196  return id;
3197 }
3198 
3199 ////////////////////////////////////////////////////////////////////////////////
3200 
3202 {
3203  TStreamerElement *element = 0;
3204  next.Reset();
3205  while ((element = (TStreamerElement*)next())) {
3210  if(element->GetArrayLength() <= 1) {
3211  fprintf(file," %s = 0;\n",element->GetName());
3212  } else {
3213  fprintf(file," memset(%s,0,%d);\n",element->GetName(),element->GetSize());
3214  }
3215  }
3216  if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3217  fprintf(file," %s = 0;\n",element->GetName());
3218  }
3219  }
3220 }
3221 
3222 ////////////////////////////////////////////////////////////////////////////////
3223 /// Write down the body of the 'move' constructor.
3224 
3225 static void R__WriteMoveConstructorBody(FILE *file, const TString &protoname, TIter &next)
3226 {
3227  TStreamerElement *element = 0;
3228  next.Reset();
3229  Bool_t atstart = kTRUE;
3230  while ((element = (TStreamerElement*)next())) {
3231  if (element->IsBase()) {
3232  if (atstart) { fprintf(file," : "); atstart = kFALSE; }
3233  else fprintf(file," , ");
3234  fprintf(file, "%s(const_cast<%s &>( rhs ))\n", element->GetName(),protoname.Data());
3235  } else {
3236  if (element->GetArrayLength() <= 1) {
3237  if (atstart) { fprintf(file," : "); atstart = kFALSE; }
3238  else fprintf(file," , ");
3239  fprintf(file, "%s(const_cast<%s &>( rhs ).%s)\n",element->GetName(),protoname.Data(),element->GetName());
3240  }
3241  }
3242  }
3243  fprintf(file,"{\n");
3244  fprintf(file," // This is NOT a copy constructor. This is actually a move constructor (for stl container's sake).\n");
3245  fprintf(file," // Use at your own risk!\n");
3246  fprintf(file," (void)rhs; // avoid warning about unused parameter\n");
3247  next.Reset();
3248  Bool_t defMod = kFALSE;
3249  while ((element = (TStreamerElement*)next())) {
3252  || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT)
3253  {
3254  if (!defMod) { fprintf(file," %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
3255  const char *ename = element->GetName();
3256  const char *colon2 = strstr(ename,"::");
3257  if (colon2) ename = colon2+2;
3258  if(element->GetArrayLength() <= 1) {
3259  fprintf(file," modrhs.%s = 0;\n",ename);
3260  } else {
3261  fprintf(file," memset(modrhs.%s,0,%d);\n",ename,element->GetSize());
3262  }
3263  } else {
3264  const char *ename = element->GetName();
3265  if (element->GetType() == kCharStar) {
3266  if (!defMod) {
3267  fprintf(file," %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3268  };
3269  fprintf(file," modrhs.%s = 0;\n",ename);
3270  } else if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3271  if (!defMod) {
3272  fprintf(file," %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3273  };
3274  fprintf(file," modrhs.%s = 0;\n",ename);
3275  } else if (element->GetArrayLength() > 1) {
3276  // FIXME: Need to add support for variable length array.
3277  if (element->GetArrayDim() == 1) {
3278  fprintf(file," for (Int_t i=0;i<%d;i++) %s[i] = rhs.%s[i];\n",element->GetArrayLength(),ename,ename);
3279  } else if (element->GetArrayDim() >= 2) {
3280  fprintf(file," for (Int_t i=0;i<%d;i++) (&(%s",element->GetArrayLength(),ename);
3281  for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
3282  fprintf(file,"[0]");
3283  }
3284  fprintf(file,"))[i] = (&(rhs.%s",ename);
3285  for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
3286  fprintf(file,"[0]");
3287  }
3288  fprintf(file,"))[i];\n");
3289  }
3290  } else if (element->GetType() == TVirtualStreamerInfo::kSTLp) {
3291  if (!defMod) { fprintf(file," %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
3292  fprintf(file," modrhs.%s = 0;\n",ename);
3293  } else if (element->GetType() == TVirtualStreamerInfo::kSTL) {
3294  if (!defMod) {
3295  fprintf(file," %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3296  }
3297  TClass *cle = element->GetClassPointer();
3298  TVirtualCollectionProxy *proxy = cle ? element->GetClassPointer()->GetCollectionProxy() : 0;
3299  std::string method_name = "clear";
3300  if (!element->TestBit(TStreamerElement::kDoNotDelete) && proxy && (((TStreamerSTL*)element)->GetSTLtype() == ROOT::kSTLbitset)) {
3301  method_name = "reset";
3302  }
3303  if (element->IsBase()) {
3304  fprintf(file," modrhs.%s();\n", method_name.c_str());
3305  } else {
3306  fprintf(file," modrhs.%s.%s();\n",ename, method_name.c_str());
3307  }
3308  }
3309  }
3310  }
3311 }
3312 
3313 ////////////////////////////////////////////////////////////////////////////////
3314 
3316 {
3317  TStreamerElement *element = 0;
3318  next.Reset();
3319  while ((element = (TStreamerElement*)next())) {
3322  || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT)
3323  {
3324  const char *ename = element->GetName();
3325  const char *colon2 = strstr(ename,"::");
3326  if (colon2) ename = colon2+2;
3327  if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3328  if(element->GetArrayLength() <= 1) {
3329  fprintf(file," %s = 0;\n",ename);
3330  } else {
3331  fprintf(file," memset(%s,0,%d);\n",ename,element->GetSize());
3332  }
3333  } else {
3334  if(element->GetArrayLength() <= 1) {
3335  fprintf(file," delete %s; %s = 0;\n",ename,ename);
3336  } else {
3337  fprintf(file," for (Int_t i=0;i<%d;i++) delete %s[i]; memset(%s,0,%d);\n",element->GetArrayLength(),ename,ename,element->GetSize());
3338  }
3339  }
3340  }
3341  if (element->GetType() == TVirtualStreamerInfo::kCharStar) {
3342  const char *ename = element->GetName();
3343  if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3344  fprintf(file," %s = 0;\n",ename);
3345  } else {
3346  fprintf(file," delete [] %s; %s = 0;\n",ename,ename);
3347  }
3348  }
3349  if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3350  const char *ename = element->GetName();
3351  if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3352  fprintf(file," %s = 0;\n",ename);
3353  } else if (element->HasCounter()) {
3354  fprintf(file," delete %s; %s = 0;\n",ename,ename);
3355  } else {
3356  fprintf(file," delete [] %s; %s = 0;\n",ename,ename);
3357  }
3358  }
3359  if (element->GetType() == TVirtualStreamerInfo::kSTL || element->GetType() == TVirtualStreamerInfo::kSTLp) {
3360  const char *ename = element->GetName();
3361  const char *prefix = "";
3362  if ( element->GetType() == TVirtualStreamerInfo::kSTLp ) {
3363  prefix = "*";
3364  } else if ( element->IsBase() ) {
3365  ename = "this";
3366  }
3367  TClass *cle = element->GetClassPointer();
3368  TVirtualCollectionProxy *proxy = cle ? element->GetClassPointer()->GetCollectionProxy() : 0;
3369  if (!element->TestBit(TStreamerElement::kDoNotDelete) && proxy) {
3370  Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
3371 
3372  if (proxy->HasPointers()) {
3373  fprintf(file," std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
3374  //fprintf(file," %s::iterator iter;\n");
3375  //fprintf(file," %s::iterator begin = (%s %s).begin();\n");
3376  //fprintf(file," %s::iterator end (%s %s).end();\n");
3377  //fprintf(file," for( iter = begin; iter != end; ++iter) { delete *iter; }\n");
3378  } else {
3379  if (stltype == ROOT::kSTLmap || stltype == ROOT::kSTLmultimap) {
3381  std::vector<std::string> inside;
3382  int nestedLoc;
3383  TClassEdit::GetSplit(enamebasic, inside, nestedLoc, TClassEdit::kLong64);
3384  if (inside[1][inside[1].size()-1]=='*' || inside[2][inside[2].size()-1]=='*') {
3385  fprintf(file," std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
3386  }
3387  }
3388  }
3389  }
3390  if ( prefix[0] ) {
3391  fprintf(file," delete %s; %s = 0;\n",ename,ename);
3392  }
3393  }
3394  }
3395 }
3396 
3397 ////////////////////////////////////////////////////////////////////////////////
3398 /// Write the Declaration of class.
3399 
3400 void TStreamerInfo::GenerateDeclaration(FILE *fp, FILE *sfp, const TList *subClasses, Bool_t top)
3401 {
3402  if (fClassVersion == -3) {
3403  return;
3404  }
3405 
3406  Bool_t needGenericTemplate = fElements==0 || fElements->GetEntries() == 0;
3407  Bool_t isTemplate = kFALSE;
3408  const char *clname = GetName();
3409  TString template_protoname;
3410  if (strchr(clname, ':')) {
3411  // We might have a namespace in front of the classname.
3412  Int_t len = strlen(clname);
3413  const char *name = clname;
3414  UInt_t nest = 0;
3415  UInt_t pr_pos = 0;
3416  for (Int_t cur = 0; cur < len; ++cur) {
3417  switch (clname[cur]) {
3418  case '<':
3419  ++nest;
3420  pr_pos = cur;
3421  isTemplate = kTRUE;
3422  break;
3423  case '>':
3424  if (nest == 0) { cur = len; continue; } // the name is not well formed, give up.
3425  --nest;
3426  break;
3427  case ':': {
3428  if (nest == 0 && clname[cur+1] == ':') {
3429  // We have a scope
3430  isTemplate = kFALSE;
3431  name = clname + cur + 2;
3432  }
3433  break;
3434  }
3435  }
3436  }
3437  if (isTemplate) {
3438  template_protoname.Append(clname,pr_pos);
3439  }
3440  clname = name;
3441  } else {
3442  const char *where = strstr(clname, "<");
3443  isTemplate = where != 0;
3444  if (isTemplate) {
3445  template_protoname.Append(clname,where-clname);
3446  }
3447  }
3448 
3449  if (needGenericTemplate && isTemplate) {
3450  TString templateName(TMakeProject::GetHeaderName("template "+template_protoname,0));
3451  fprintf(fp, "#ifndef %s_h\n", templateName.Data());
3452  fprintf(fp, "#define %s_h\n", templateName.Data());
3453  }
3454 
3455  TString protoname;
3456  UInt_t numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, GetName(), top, protoname, 0, kFALSE, needGenericTemplate);
3457 
3458  // Generate class statement with base classes.
3459  TStreamerElement *element;
3460  TIter next(fElements);
3461  Int_t nbase = 0;
3462  while ((element = (TStreamerElement*)next())) {
3463  if (!element->IsBase()) continue;
3464  nbase++;
3465  const char *ename = element->GetName();
3466  if (nbase == 1) fprintf(fp," : public %s",ename);
3467  else fprintf(fp," , public %s",ename);
3468  }
3469  fprintf(fp," {\n");
3470 
3471  // Generate forward declaration nested classes.
3472  if (subClasses && subClasses->GetEntries()) {
3473  Bool_t needheader = true;
3474 
3475  TIter subnext(subClasses);
3476  TStreamerInfo *subinfo;
3477  Int_t len = strlen(GetName());
3478  while ((subinfo = (TStreamerInfo*)subnext())) {
3479  if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==':') ) {
3480  if (subinfo->GetName()[len+1]==':' && strstr(subinfo->GetName()+len+2,":")==0) {
3481  if (needheader) {
3482  fprintf(fp,"\npublic:\n");
3483  fprintf(fp,"// Nested classes forward declaration.\n");
3484  needheader = false;
3485  }
3486  TString sub_protoname;
3487  UInt_t sub_numberOfClasses = 0;
3488  UInt_t sub_numberOfNamespaces;
3489  if (subinfo->GetClassVersion() == -3) {
3490  sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, 3);
3491  } else {
3492  sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, kFALSE);
3493  fprintf(fp, ";\n");
3494  }
3495 
3496  for (UInt_t i = 0;i < sub_numberOfClasses;++i) {
3497  fprintf(fp, "}; // end of class.\n");
3498  }
3499  if (sub_numberOfNamespaces > 0) {
3500  Error("GenerateDeclaration","Nested classes %s thought to be inside a namespace inside the class %s",subinfo->GetName(),GetName());
3501  }
3502  }
3503  }
3504  }
3505  }
3506 
3507  fprintf(fp,"\npublic:\n");
3508  fprintf(fp,"// Nested classes declaration.\n");
3509 
3510  // Generate nested classes.
3511  if (subClasses && subClasses->GetEntries()) {
3512  TIter subnext(subClasses,kIterBackward);
3513  TStreamerInfo *subinfo;
3514  Int_t len = strlen(GetName());
3515  while ((subinfo = (TStreamerInfo*)subnext())) {
3516  if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==':')) {
3517  if (subinfo->GetName()[len+1]==':' && strstr(subinfo->GetName()+len+2,":")==0) {
3518  subinfo->GenerateDeclaration(fp, sfp, subClasses, kFALSE);
3519  }
3520  }
3521  }
3522  }
3523 
3524  fprintf(fp,"\npublic:\n");
3525  fprintf(fp,"// Data Members.\n");
3526 
3527  {
3528  // Generate data members.
3529  TString name(128);
3530  Int_t ltype = 12;
3531  Int_t ldata = 10;
3532  Int_t lt,ld,is;
3533  TString line;
3534  line.Resize(kMaxLen);
3535  next.Reset();
3536  while ((element = (TStreamerElement*)next())) {
3537 
3538  if (element->IsBase()) continue;
3539  const char *ename = element->GetName();
3540 
3541  name = ename;
3542  for (Int_t i=0;i < element->GetArrayDim();i++) {
3543  name += TString::Format("[%d]",element->GetMaxIndex(i));
3544  }
3545  name += ";";
3546  ld = name.Length();
3547 
3548  TString enamebasic = element->GetTypeNameBasic();
3549  if (element->IsA() == TStreamerSTL::Class()) {
3550  // If we have a map, multimap, set or multiset,
3551  // and the key is a class, we need to replace the
3552  // container by a vector since we don't have the
3553  // comparator function.
3554  Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
3555  switch (stltype) {
3556  case ROOT::kSTLmap:
3557  case ROOT::kSTLmultimap:
3558  case ROOT::kSTLset:
3559  case ROOT::kSTLmultiset:
3562  {
3563  enamebasic = TMakeProject::UpdateAssociativeToVector(enamebasic);
3564  }
3565  default:
3566  // nothing to do.
3567  break;
3568  }
3569  }
3570 
3571  lt = enamebasic.Length();
3572 
3573  line = " ";
3574  line += enamebasic;
3575  if (lt>=ltype) ltype = lt+1;
3576 
3577  for (is = 3+lt; is < (3+ltype); ++is) line += ' ';
3578 
3579  line += name;
3580  if (element->IsaPointer() && !strchr(line,'*')) line[2+ltype] = '*';
3581 
3582  if (ld>=ldata) ldata = ld+1;
3583  for (is = 3+ltype+ld; is < (3+ltype+ldata); ++is) line += ' ';
3584 
3585  line += " //";
3586  line += element->GetTitle();
3587  fprintf(fp,"%s\n",line.Data());
3588  }
3589  }
3590  if (needGenericTemplate && isTemplate) {
3591  // Generate default functions, ClassDef and trailer.
3592  fprintf(fp,"\n %s() {\n",protoname.Data());
3593  R__WriteConstructorBody(fp,next);
3594  fprintf(fp," }\n");
3595  fprintf(fp," %s(const %s & rhs )\n",protoname.Data(),protoname.Data());
3596  R__WriteMoveConstructorBody(fp,protoname,next);
3597  fprintf(fp," }\n");
3598  fprintf(fp," virtual ~%s() {\n",protoname.Data());
3599  R__WriteDestructorBody(fp,next);
3600  fprintf(fp," }\n\n");
3601 
3602  } else {
3603  // Generate default functions, ClassDef and trailer.
3604  fprintf(fp,"\n %s();\n",protoname.Data());
3605  fprintf(fp," %s(const %s & );\n",protoname.Data(),protoname.Data());
3606  fprintf(fp," virtual ~%s();\n\n",protoname.Data());
3607 
3608  // Add the implementations to the source.cxx file.
3610  fprintf(sfp,"#ifndef %s_cxx\n",guard.Data());
3611  fprintf(sfp,"#define %s_cxx\n",guard.Data());
3612  fprintf(sfp,"%s::%s() {\n",GetName(),protoname.Data());
3613  R__WriteConstructorBody(sfp,next);
3614  fprintf(sfp,"}\n");
3615 
3616  fprintf(sfp,"%s::%s(const %s & rhs)\n",GetName(),protoname.Data(),protoname.Data());
3617  R__WriteMoveConstructorBody(sfp,protoname,next);
3618  fprintf(sfp,"}\n");
3619 
3620  fprintf(sfp,"%s::~%s() {\n",GetName(),protoname.Data());
3621  R__WriteDestructorBody(sfp,next);
3622  fprintf(sfp,"}\n");
3623  fprintf(sfp,"#endif // %s_cxx\n\n",guard.Data());
3624  }
3625 
3626  TClass *cl = gROOT->GetClass(GetName());
3627  if (fClassVersion > 1 || (cl && cl->IsTObject()) ) {
3628  // add 1 to class version in case we didn't manage reproduce the class layout to 100%.
3629  if (fClassVersion == 0) {
3630  // If the class was declared 'transient', keep it that way.
3631  fprintf(fp," ClassDef(%s,%d); // Generated by MakeProject.\n",protoname.Data(),0);
3632  } else {
3633  fprintf(fp," ClassDef(%s,%d); // Generated by MakeProject.\n",protoname.Data(),fClassVersion + 1);
3634  }
3635  }
3636  fprintf(fp,"};\n");
3637 
3638  for(UInt_t i=0;i<numberOfNamespaces;++i) {
3639  fprintf(fp,"} // namespace\n");
3640  }
3641 
3642  if (needGenericTemplate && isTemplate) {
3643  fprintf(fp,"#endif // generic template declaration\n");
3644  }
3645 }
3646 
3647 ////////////////////////////////////////////////////////////////////////////////
3648 /// Add to the header file, the #include need for this class.
3649 
3650 UInt_t TStreamerInfo::GenerateIncludes(FILE *fp, char *inclist, const TList *extrainfos)
3651 {
3652  UInt_t ninc = 0;
3653 
3654  const char *clname = GetName();
3655  if (strchr(clname,'<')) {
3656  // This is a template, we need to check the template parameter.
3657  ninc += TMakeProject::GenerateIncludeForTemplate(fp, clname, inclist, kFALSE, extrainfos);
3658  }
3659 
3660  TString name(1024);
3661  Int_t ltype = 10;
3662  Int_t ldata = 10;
3663  Int_t lt;
3664  Int_t ld;
3665  TIter next(fElements);
3666  TStreamerElement *element;
3667  Bool_t incRiostream = kFALSE;
3668  while ((element = (TStreamerElement*)next())) {
3669  //if (element->IsA() == TStreamerBase::Class()) continue;
3670  const char *ename = element->GetName();
3671  const char *colon2 = strstr(ename,"::");
3672  if (colon2) ename = colon2+2;
3673  name = ename;
3674  for (Int_t i=0;i < element->GetArrayDim();i++) {
3675  name += TString::Format("[%d]",element->GetMaxIndex(i));
3676  }
3677  ld = name.Length();
3678  lt = strlen(element->GetTypeName());
3679  if (ltype < lt) ltype = lt;
3680  if (ldata < ld) ldata = ld;
3681 
3682  //must include Riostream.h in case of an STL container
3683  if (!incRiostream && element->InheritsFrom(TStreamerSTL::Class())) {
3684  incRiostream = kTRUE;
3685  TMakeProject::AddInclude( fp, "Riostream.h", kFALSE, inclist);
3686  }
3687 
3688  //get include file name if any
3689  const char *include = element->GetInclude();
3690  if (!include[0]) continue;
3691 
3692  Bool_t greater = (include[0]=='<');
3693  include++;
3694 
3695  if (strncmp(include,"include/",8)==0) {
3696  include += 8;
3697  }
3698  if (strncmp(include,"include\\",9)==0) {
3699  include += 9;
3700  }
3701  if (strncmp(element->GetTypeName(),"pair<",strlen("pair<"))==0) {
3702  TMakeProject::AddInclude( fp, "utility", kTRUE, inclist);
3703  } else if (strncmp(element->GetTypeName(),"auto_ptr<",strlen("auto_ptr<"))==0) {
3704  TMakeProject::AddInclude( fp, "memory", kTRUE, inclist);
3705  } else {
3706  TString incName( include, strlen(include)-1 );
3707  incName = TMakeProject::GetHeaderName(incName,extrainfos);
3708  TMakeProject::AddInclude( fp, incName.Data(), greater, inclist);
3709  }
3710 
3711  if (strchr(element->GetTypeName(),'<')) {
3712  // This is a template, we need to check the template parameter.
3713  ninc += TMakeProject::GenerateIncludeForTemplate(fp, element->GetTypeName(), inclist, kFALSE, extrainfos);
3714  }
3715  }
3716  if (inclist[0]==0) {
3717  TMakeProject::AddInclude( fp, "TNamed.h", kFALSE, inclist);
3718  }
3719  return ninc;
3720 }
3721 
3722 ////////////////////////////////////////////////////////////////////////////////
3723 /// Generate header file for the class described by this TStreamerInfo
3724 /// the function is called by TFile::MakeProject for each class in the file
3725 
3726 Int_t TStreamerInfo::GenerateHeaderFile(const char *dirname, const TList *subClasses, const TList *extrainfos)
3727 {
3728  // if (fClassVersion == -4) return 0;
3729  if ((fClass && fClass->GetCollectionType()) || TClassEdit::IsSTLCont(GetName())) return 0;
3730  if (strncmp(GetName(),"pair<",strlen("pair<"))==0) return 0;
3731  if (strncmp(GetName(),"auto_ptr<",strlen("auto_ptr<"))==0) return 0;
3732 
3733  TClass *cl = TClass::GetClass(GetName());
3734  if (cl) {
3735  if (cl->HasInterpreterInfo()) return 0; // skip known classes
3736  }
3737  Bool_t isTemplate = kFALSE;
3738  if (strchr(GetName(),':')) {
3739  UInt_t len = strlen(GetName());
3740  UInt_t nest = 0;
3741  UInt_t scope = 0;
3742  for(UInt_t i=len; i>0; --i) {
3743  switch(GetName()[i]) {
3744  case '>': ++nest; if (scope==0) { isTemplate = kTRUE; } break;
3745  case '<': --nest; break;
3746  case ':':
3747  if (nest==0 && GetName()[i-1]==':') {
3748  // We have a scope
3749  TString nsname(GetName(), i-1);
3750  cl = gROOT->GetClass(nsname);
3751  if (cl && (cl->Size()!=0 || (cl->Size()==0 && !cl->HasInterpreterInfo() /*empty 'base' class on file*/))) {
3752  // This class is actually nested.
3753  return 0;
3754  } else if (cl == 0 && extrainfos != 0) {
3755  TStreamerInfo *clinfo = (TStreamerInfo*)extrainfos->FindObject(nsname);
3756  if (clinfo && clinfo->GetClassVersion() == -5) {
3757  // This class is actually nested.
3758  return 0;
3759  }
3760  }
3761  ++scope;
3762  }
3763  break;
3764  }
3765  }
3766  }
3767  Bool_t needGenericTemplate = isTemplate && (fElements==0 || fElements->GetEntries()==0);
3768 
3769  if (gDebug) printf("generating code for class %s\n",GetName());
3770 
3771  // Open the file
3772 
3773  TString headername( TMakeProject::GetHeaderName( GetName(), extrainfos ) );
3774  TString filename;
3775  filename.Form("%s/%s.h",dirname,headername.Data());
3776 
3777  FILE *fp = fopen(filename.Data(),"w");
3778  if (!fp) {
3779  Error("MakeProject","Cannot open output file:%s\n",filename.Data());
3780  return 0;
3781  }
3782 
3783  filename.Form("%s/%sProjectHeaders.h",dirname,gSystem->BaseName(dirname));
3784  FILE *allfp = fopen(filename.Data(),"a");
3785  if (!allfp) {
3786  Error("MakeProject","Cannot open output file:%s\n",filename.Data());
3787  fclose(fp);
3788  return 0;
3789  }
3790  fprintf(allfp,"#include \"%s.h\"\n", headername.Data());
3791  fclose(allfp);
3792 
3793  char *inclist = new char[50000];
3794  inclist[0] = 0;
3795 
3796  // Generate class header.
3797  TDatime td;
3798  fprintf(fp,"//////////////////////////////////////////////////////////\n");
3799  fprintf(fp,"// This class has been generated by TFile::MakeProject\n");
3800  fprintf(fp,"// (%s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
3801  fprintf(fp,"// from the StreamerInfo in file %s\n",gDirectory->GetFile()->GetName());
3802  fprintf(fp,"//////////////////////////////////////////////////////////\n");
3803  fprintf(fp,"\n");
3804  fprintf(fp,"\n");
3805  fprintf(fp,"#ifndef %s_h\n",headername.Data());
3806  fprintf(fp,"#define %s_h\n",headername.Data());
3807  TMakeProject::GenerateForwardDeclaration(fp, GetName(), inclist, kFALSE, needGenericTemplate, extrainfos);
3808  fprintf(fp,"\n");
3809 
3810  UInt_t ninc = 0;
3811  ninc += GenerateIncludes(fp, inclist, extrainfos);
3812  if (subClasses) {
3813  TIter subnext(subClasses);
3814  TStreamerInfo *subinfo;
3815  while ((subinfo = (TStreamerInfo*)subnext())) {
3816  ninc = subinfo->GenerateIncludes(fp, inclist, extrainfos);
3817  }
3818  }
3819  fprintf(fp,"\n");
3820 
3821  TString sourcename; sourcename.Form( "%s/%sProjectSource.cxx", dirname, gSystem->BaseName(dirname) );
3822  FILE *sfp = fopen( sourcename.Data(), "a" );
3823  if (sfp) {
3824  GenerateDeclaration(fp, sfp, subClasses);
3825  } else {
3826  Error("GenerateHeaderFile","Could not open %s for appending",sourcename.Data());
3827  }
3828  TMakeProject::GeneratePostDeclaration(fp, this, inclist);
3829 
3830  fprintf(fp,"#endif\n");
3831 
3832  delete [] inclist;
3833  fclose(fp);
3834  if (sfp) fclose(sfp);
3835  return 1;
3836 }
3837 
3838 ////////////////////////////////////////////////////////////////////////////////
3839 /// Compute data member offset.
3840 /// Return pointer to the Streamer function if one exists
3841 
3843 {
3844  TIter nextr(fClass->GetListOfRealData());
3845  char dmbracket[256];
3846  snprintf(dmbracket,255,"%s[",dm->GetName());
3847  Int_t offset = kMissing;
3848  if (!fClass->IsLoaded()) {
3849  // If the 'class' is not loaded, we do not have a TClass bootstrap and thus
3850  // the 'RealData' might not have enough information because of the lack
3851  // of proper ShowMember imlementation.
3852  if (! (dm->Property() & kIsStatic) ) {
3853  // Give an offset only to non-static members.
3854  offset = dm->GetOffset();
3855  }
3856  }
3857  TRealData *rdm;
3858  while ((rdm = (TRealData*)nextr())) {
3859  char *rdmc = (char*)rdm->GetName();
3860  //next statement required in case a class and one of its parent class
3861  //have data members with the same name
3862  if (dm->IsaPointer() && rdmc[0] == '*') rdmc++;
3863 
3864  if (rdm->GetDataMember() != dm) continue;
3865  if (strcmp(rdmc,dm->GetName()) == 0) {
3866  offset = rdm->GetThisOffset();
3867  streamer = rdm->GetStreamer();
3868  break;
3869  }
3870  if (strcmp(rdm->GetName(),dm->GetName()) == 0) {
3871  if (rdm->IsObject()) {
3872  offset = rdm->GetThisOffset();
3873  streamer = rdm->GetStreamer();
3874  break;
3875  }
3876  }
3877  if (strstr(rdm->GetName(),dmbracket)) {
3878  offset = rdm->GetThisOffset();
3879  streamer = rdm->GetStreamer();
3880  break;
3881  }
3882  }
3883  return offset;
3884 }
3885 
3886 ////////////////////////////////////////////////////////////////////////////////
3887 /// Return the offset of the data member as indicated by this StreamerInfo.
3888 
3889 Int_t TStreamerInfo::GetOffset(const char *elementName) const
3890 {
3891  if (elementName == 0) return 0;
3892 
3893  Int_t offset = 0;
3894  TStreamerElement *elem = (TStreamerElement*)fElements->FindObject(elementName);
3895  if (elem) offset = elem->GetOffset();
3896 
3897  return offset;
3898 }
3899 
3900 ////////////////////////////////////////////////////////////////////////////////
3901 /// Return total size of all persistent elements of the class (with offsets).
3902 
3904 {
3905  return fSize;
3906 }
3907 
3908 ////////////////////////////////////////////////////////////////////////////////
3909 /// Return total size of all persistent elements of the class
3910 /// use GetSize if you want to get the real size in memory.
3911 
3913 {
3914  TIter next(fElements);
3915  TStreamerElement *element;
3916  Int_t asize = 0;
3917  while ((element = (TStreamerElement*)next())) {
3918  asize += element->GetSize();
3919  }
3920  return asize;
3921 }
3922 
3923 ////////////////////////////////////////////////////////////////////////////////
3924 /// Return the StreamerElement of "datamember" inside our
3925 /// class or any of its base classes.
3926 ///
3927 /// The offset information
3928 /// contained in the StreamerElement is related to its immediately
3929 /// containing class, so we return in 'offset' the offset inside
3930 /// our class.
3931 
3933 {
3934  if (!fElements) {
3935  return 0;
3936  }
3937 
3938  // Look first at the data members and base classes
3939  // of our class.
3940  TStreamerElement* element = (TStreamerElement*) fElements->FindObject(datamember);
3941  if (element) {
3942  offset = element->GetOffset();
3943  return element;
3944  }
3945 
3946  // Not found, so now try the data members and base classes
3947  // of the base classes of our class.
3948  if (fClass->HasDataMemberInfo()) {
3949  // Our class has a dictionary loaded, use it to search the base classes.
3950  TStreamerElement* base_element = 0;
3951  TBaseClass* base = 0;
3952  TClass* base_cl = 0;
3953  Int_t base_offset = 0;
3954  Int_t local_offset = 0;
3955  TIter nextb(fClass->GetListOfBases());
3956  // Iterate on list of base classes.
3957  while ((base = (TBaseClass*) nextb())) {
3958  base_cl = TClass::GetClass(base->GetName());
3959  base_element = (TStreamerElement*) fElements->FindObject(base->GetName());
3960  if (!base_cl || !base_element) {
3961  continue;
3962  }
3963  base_offset = base_element->GetOffset();
3964  element = ((TStreamerInfo*)base_cl->GetStreamerInfo())->GetStreamerElement(datamember, local_offset);
3965  if (element) {
3966  offset = base_offset + local_offset;
3967  return element;
3968  }
3969  }
3970  } else {
3971  // Our class's dictionary is not loaded. Search through the base class streamer elements.
3972  TIter next(fElements);
3973  TStreamerElement* curelem = 0;
3974  while ((curelem = (TStreamerElement*) next())) {
3975  if (curelem->InheritsFrom(TStreamerBase::Class())) {
3976  TClass* baseClass = curelem->GetClassPointer();
3977  if (!baseClass) {
3978  continue;
3979  }
3980  Int_t base_offset = curelem->GetOffset();
3981  Int_t local_offset = 0;
3982  TStreamerInfo *baseInfo;
3983  if (baseClass->Property() & kIsAbstract) {
3984  baseInfo = (TStreamerInfo*)baseClass->GetStreamerInfoAbstractEmulated();
3985  } else {
3986  baseInfo = (TStreamerInfo*)baseClass->GetStreamerInfo();
3987  }
3988  if (baseInfo) element = baseInfo->GetStreamerElement(datamember, local_offset);
3989  if (element) {
3990  offset = base_offset + local_offset;
3991  return element;
3992  }
3993  }
3994  }
3995  }
3996  return 0;
3997 }
3998 
3999 ////////////////////////////////////////////////////////////////////////////////
4000 /// <b>Obsolete</b>: this routine is obsolete and should not longer be used.
4001 ///
4002 /// TStreamerInfo holds two types of data structures
4003 /// - TObjArray* fElements; containing the list of all TStreamerElement
4004 /// objects for this class version.
4005 /// - ULong_t* fElem; containing the preprocessed information
4006 /// by TStreamerInfo::Compile In case consecutive data members
4007 /// are of the same type, the Compile function declares the consecutive
4008 /// elements as one single element in fElems.
4009 ///
4010 /// Example with the class TAttLine:
4011 /// ~~~{.cpp}
4012 /// TClass::GetClass("TAttLine")->GetStreamerInfo()->ls(); produces;
4013 /// StreamerInfo for class: TAttLine, version=1
4014 /// short fLineColor offset= 4 type= 2 line color
4015 /// short fLineStyle offset= 6 type= 2 line style
4016 /// short fLineWidth offset= 8 type= 2 line width
4017 /// i= 0, fLineColor type= 22, offset= 4, len=3, method=0
4018 /// ~~~
4019 /// For I/O implementations (eg. XML) , one has to know the original name
4020 /// of the data member. This function can be used to return a pointer
4021 /// to the original TStreamerElement object corresponding to the j-th
4022 /// element of a compressed array in fElems.
4023 /// Parameters description:
4024 /// - i: the serial number in array fElem
4025 /// - j: the element number in the array of consecutive types
4026 /// In the above example the class TAttLine has 3 consecutive data members
4027 /// of the same type "short". Compile makes one single array of 3 elements.
4028 /// To access the TStreamerElement for the second element
4029 /// of this array, one can call:
4030 /// ~~~{.cpp}
4031 /// auto el = GetStreamerElementReal(0,1);
4032 /// auto membername = el->GetName();
4033 /// ~~~
4034 /// This function is typically called from TBuffer, TXmlBuffer.
4035 
4037 {
4038  ::Obsolete("TStreamerInfo::GetStreamerElementReal", "v5-34-20", "v6-00-02");
4039 
4040  if (i < 0 || i >= fNdata) return 0;
4041  if (j < 0) return 0;
4042  if (!fElements) return 0;
4043  TStreamerElement *se = (TStreamerElement*)fCompOpt[i]->fElem;
4044  if (!se) return 0;
4045  Int_t nelems = fElements->GetEntriesFast();
4046  for (Int_t ise=0;ise < nelems;ise++) {
4047  if (se != (TStreamerElement*)fElements->UncheckedAt(ise)) continue;
4048  if (ise+j >= nelems) return 0;
4049  return (TStreamerElement*)fElements->UncheckedAt(ise+j);
4050  }
4051  return 0;
4052 }
4053 
4054 ////////////////////////////////////////////////////////////////////////////////
4055 /// Get the value from inside a collection.
4056 
4057 template <typename T>
4059 {
4060  if (type>=kConv && type<kSTL) {
4061  type -= kConv;
4062  }
4063  switch (type) {
4064  // basic types
4065  case kBool: {Bool_t *val = (Bool_t*)ladd; return T(*val);}
4066  case kChar: {Char_t *val = (Char_t*)ladd; return T(*val);}
4067  case kShort: {Short_t *val = (Short_t*)ladd; return T(*val);}
4068  case kInt: {Int_t *val = (Int_t*)ladd; return T(*val);}
4069  case kLong: {Long_t *val = (Long_t*)ladd; return T(*val);}
4070  case kLong64: {Long64_t *val = (Long64_t*)ladd; return T(*val);}
4071  case kFloat: {Float_t *val = (Float_t*)ladd; return T(*val);}
4072  case kFloat16: {Float_t *val = (Float_t*)ladd; return T(*val);}
4073  case kDouble: {Double_t *val = (Double_t*)ladd; return T(*val);}
4074  case kDouble32: {Double_t *val = (Double_t*)ladd; return T(*val);}
4075  case kUChar: {UChar_t *val = (UChar_t*)ladd; return T(*val);}
4076  case kUShort: {UShort_t *val = (UShort_t*)ladd; return T(*val);}
4077  case kUInt: {UInt_t *val = (UInt_t*)ladd; return T(*val);}
4078  case kULong: {ULong_t *val = (ULong_t*)ladd; return T(*val);}
4079 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4080  case kULong64: {Long64_t *val = (Long64_t*)ladd; return T(*val);}
4081 #else
4082  case kULong64: {ULong64_t *val= (ULong64_t*)ladd; return T(*val);}
4083 #endif
4084  case kBits: {UInt_t *val = (UInt_t*)ladd; return T(*val);}
4085 
4086  // array of basic types array[8]
4087  case kOffsetL + kBool: {Bool_t *val = (Bool_t*)ladd; return T(val[k]);}
4088  case kOffsetL + kChar: {Char_t *val = (Char_t*)ladd; return T(val[k]);}
4089  case kOffsetL + kShort: {Short_t *val = (Short_t*)ladd; return T(val[k]);}
4090  case kOffsetL + kInt: {Int_t *val = (Int_t*)ladd; return T(val[k]);}
4091  case kOffsetL + kLong: {Long_t *val = (Long_t*)ladd; return T(val[k]);}
4092  case kOffsetL + kLong64: {Long64_t *val = (Long64_t*)ladd; return T(val[k]);}
4093  case kOffsetL + kFloat: {Float_t *val = (Float_t*)ladd; return T(val[k]);}
4094  case kOffsetL + kFloat16: {Float_t *val = (Float_t*)ladd; return T(val[k]);}
4095  case kOffsetL + kDouble: {Double_t *val = (Double_t*)ladd; return T(val[k]);}
4096  case kOffsetL + kDouble32:{Double_t *val = (Double_t*)ladd; return T(val[k]);}
4097  case kOffsetL + kUChar: {UChar_t *val = (UChar_t*)ladd; return T(val[k]);}
4098  case kOffsetL + kUShort: {UShort_t *val = (UShort_t*)ladd; return T(val[k]);}
4099  case kOffsetL + kUInt: {UInt_t *val = (UInt_t*)ladd; return T(val[k]);}
4100  case kOffsetL + kULong: {ULong_t *val = (ULong_t*)ladd; return T(val[k]);}
4101 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4102  case kOffsetL + kULong64: {Long64_t *val = (Long64_t*)ladd; return T(val[k]);}
4103 #else
4104  case kOffsetL + kULong64:{ULong64_t *val= (ULong64_t*)ladd; return T(val[k]);}
4105 #endif
4106 
4107 #define READ_ARRAY(TYPE_t) \
4108  { \
4109  Int_t sub_instance, index; \
4110  Int_t instance = k; \
4111  if (len) { \
4112  index = instance / len; \
4113  sub_instance = instance % len; \
4114  } else { \
4115  index = instance; \
4116  sub_instance = 0; \
4117  } \
4118  TYPE_t **val =(TYPE_t**)(ladd); \
4119  return T((val[sub_instance])[index]); \
4120  }
4121 
4122  // pointer to an array of basic types array[n]
4126  case kOffsetP + kInt_t: READ_ARRAY(Int_t)
4129  case kOffsetP + kFloat16_t:
4131  case kOffsetP + kDouble32_t:
4137 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4139 #else
4141 #endif
4142 
4143  // array counter //[n]
4144  case kCounter: {Int_t *val = (Int_t*)ladd; return T(*val);}
4145  }
4146  return 0;
4147 }
4148 
4149 
4150 
4151 template Double_t TStreamerInfo::GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const;
4152 template Long64_t TStreamerInfo::GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const;
4153 template LongDouble_t TStreamerInfo::GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const;
4154 
4155 ////////////////////////////////////////////////////////////////////////////////
4156 /// Return value of element i in object at pointer.
4157 /// The function may be called in two ways:
4158 /// - method1 len < 0: i is assumed to be the TStreamerElement number i in StreamerInfo
4159 /// - method2 len >= 0: i is the type, address of variable is directly pointer.
4160 
4161 template <typename T>
4162 T TStreamerInfo::GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const
4163 {
4164  char *ladd;
4165  Int_t atype;
4166  if (len >= 0) {
4167  ladd = pointer;
4168  atype = i;
4169  } else {
4170  if (i < 0) return 0;
4171  ladd = pointer + fCompFull[i]->fOffset;
4172  atype = fCompFull[i]->fNewType;
4173  len = fCompFull[i]->fElem->GetArrayLength();
4174  if (atype == kSTL) {
4175  TClass *newClass = fCompFull[i]->fElem->GetNewClass();
4176  if (newClass == 0) {
4177  newClass = fCompFull[i]->fElem->GetClassPointer();
4178  }
4179  TClass *innerClass = newClass->GetCollectionProxy()->GetValueClass();
4180  if (innerClass) {
4181  return 0; // We don't know which member of the class we would want.
4182  } else {
4183  TVirtualCollectionProxy *proxy = newClass->GetCollectionProxy();
4184  // EDataType is a subset of TStreamerInfo::EReadWrite
4185  atype = (TStreamerInfo::EReadWrite)proxy->GetType();
4186  TVirtualCollectionProxy::TPushPop pop(proxy,ladd);
4187  Int_t nc = proxy->Size();
4188  if (j >= nc) return 0;
4189  char *element_ptr = (char*)proxy->At(j);
4190  return GetTypedValueAux<T>(atype,element_ptr,0,1);
4191  }
4192  }
4193  }
4194  return GetTypedValueAux<T>(atype,ladd,j,len);
4195 }
4196 
4197 ////////////////////////////////////////////////////////////////////////////////
4198 
4199 template Double_t TStreamerInfo::GetTypedValueClones<Double_t>(TClonesArray *clones, Int_t i, Int_t j, int k, Int_t eoffset) const;
4200 template Long64_t TStreamerInfo::GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, int k, Int_t eoffset) const;
4201 template LongDouble_t TStreamerInfo::GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, int k, Int_t eoffset) const;
4202 
4203 template <typename T>
4205 {
4206  // return value of element i in object number j in a TClonesArray and eventually
4207  // element k in a sub-array.
4208 
4209  Int_t nc = clones->GetEntriesFast();
4210  if (j >= nc) return 0;
4211 
4212  char *pointer = (char*)clones->UncheckedAt(j);
4213  char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4214  return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4215 }
4216 
4217 template Double_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4218 template Long64_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4219 template LongDouble_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4220 
4221 ////////////////////////////////////////////////////////////////////////////////
4222 /// Return value of element i in object number j in a TClonesArray and eventually
4223 /// element k in a sub-array.
4224 
4225 template <typename T>
4227 {
4228  Int_t nc = cont->Size();
4229  if (j >= nc) return 0;
4230 
4231  char *pointer = (char*)cont->At(j);
4232  char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4233  return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4234 }
4235 
4236 template Double_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4237 template Long64_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4238 template LongDouble_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const;
4239 
4240 ////////////////////////////////////////////////////////////////////////////////
4241 /// Return value of element i in object number j in a TClonesArray and eventually
4242 /// element k in a sub-array.
4243 
4244 template <typename T>
4246 {
4247  Int_t nc = cont->Size();
4248 
4249  if (j >= nc) return 0;
4250 
4251  char **ptr = (char**)cont->At(j);
4252  char *pointer = *ptr;
4253 
4254  char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4255  return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4256 }
4257 
4258 ////////////////////////////////////////////////////////////////////////////////
4259 /// Insert new members as expressed in the array of TSchemaRule(s).
4260 
4261 void TStreamerInfo::InsertArtificialElements(std::vector<const ROOT::TSchemaRule*> &rules)
4262 {
4263  if (rules.empty()) return;
4264 
4265  TIter next(fElements);
4266  UInt_t count = 0;
4267 
4268  for(auto rule : rules) {
4269  if( rule->IsRenameRule() || rule->IsAliasRule() )
4270  continue;
4271  next.Reset();
4272  TStreamerElement *element;
4273  while ((element = (TStreamerElement*) next())) {
4274  if ( rule->HasTarget( element->GetName() ) ) {
4275 
4276  // Check whether this is an 'attribute' rule.
4277  if ( rule->GetAttributes()[0] != 0 ) {
4278  TString attr( rule->GetAttributes() );
4279  attr.ToLower();
4280  if (attr.Contains("owner")) {
4281  if (attr.Contains("notowner")) {
4283  } else {
4285  }
4286  }
4287 
4288  }
4289  break;
4290  }
4291  }
4292 
4293  // NOTE: Before adding the rule we should check that the source do
4294  // existing in this StreamerInfo.
4295  const TObjArray *sources = rule->GetSource();
4296  TIter input(sources);
4297  TObject *src;
4298  while((src = input())) {
4299  if ( !GetElements()->FindObject(src->GetName()) ) {
4300  // Missing source.
4301 #if 0 // Don't warn about not activating the rule. If don't warn the user can
4302  // have more flexibility in specifiying when the rule applies and relying
4303  // on both the version number *and* the presence of the source members.
4304  // Activating this warning would for example mean that we need to carefully
4305  // tweak $ROOTSYS/etc/class.rules.
4306  TString ruleStr;
4307  rule->AsString(ruleStr);
4308  Warning("InsertArtificialElements","For class %s in StreamerInfo %d is missing the source data member %s when trying to apply the rule:\n %s",
4309  GetName(),GetClassVersion(),src->GetName(),ruleStr.Data());
4310  rule = 0;
4311 #endif
4312  break;
4313  }
4314  }
4315 
4316  if (!rule) continue;
4317 
4318  TStreamerArtificial *newel;
4319  typedef std::vector<TStreamerArtificial*> vec_t;
4320  vec_t toAdd;
4321 
4322  if (rule->GetTarget()==0) {
4323  TString newName;
4324  newName.Form("%s_rule%d",fClass->GetName(),count);
4325  newel = new TStreamerArtificial(newName,"",
4326  fClass->GetDataMemberOffset(newName),
4328  "void");
4330  newel->SetReadFunc( rule->GetReadFunctionPointer() );
4331  newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
4332  toAdd.push_back(newel);
4333  } else {
4334  toAdd.reserve(rule->GetTarget()->GetEntries());
4335  TObjString * objstr = (TObjString*)(rule->GetTarget()->At(0));
4336  if (objstr) {
4337  TString newName = objstr->String();
4338  TString realDataName;
4339  if ( TDataMember* dm = fClass->GetDataMember( newName ) ) {
4340  TRealData::GetName(realDataName,dm);
4341  newel = new TStreamerArtificial(realDataName,"",
4342  fClass->GetDataMemberOffset(newName),
4344  fClass->GetDataMember( newName )->GetTypeName());
4345  newel->SetReadFunc( rule->GetReadFunctionPointer() );
4346  newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
4347  toAdd.push_back(newel);
4348  } else {
4349  // This would be a completely new member (so it would need to be cached)
4350  // TOBEDONE
4351  }
4352  for(Int_t other = 1; other < rule->GetTarget()->GetEntries(); ++other) {
4353  objstr = (TObjString*)(rule->GetTarget()->At(other));
4354  if (objstr) {
4355  newName = objstr->String();
4356  if ( TDataMember* dm = fClass->GetDataMember( newName ) ) {
4357  TRealData::GetName(realDataName,dm);
4358  newel = new TStreamerArtificial(realDataName,"",
4359  fClass->GetDataMemberOffset(newName),
4361  fClass->GetDataMember( newName )->GetTypeName());
4362  toAdd.push_back(newel);
4363  }
4364  }
4365  }
4366  } // For each target of the rule
4367  }
4368  // Now find we with need to add them
4369  TIter s_iter(rule->GetSource());
4370  Int_t loc = -1;
4371  while( TObjString *s = (TObjString*)s_iter() ) {
4372  for(Int_t i = fElements->GetLast(); i >= 0 && (i+1) >= loc; --i) {
4373  if (s->String() == fElements->UncheckedAt(i)->GetName()) {
4374  if (loc == -1 || (i+1)>loc) {
4375  loc = i+1;
4376  }
4377  }
4378  }
4379  }
4380  if (loc == -1) {
4381  // Verify if the last one is not 'skipped'.
4382  for(Int_t i = fElements->GetLast(); i >= 0 && (i+1) >= loc; --i) {
4383  if ( ((TStreamerElement*)fElements->UncheckedAt(i))->GetNewType() != -2 ) {
4384  break;
4385  }
4386  loc = i;
4387  }
4388  }
4389  if (loc == -1) {
4390  for(vec_t::iterator iter = toAdd.begin(); iter != toAdd.end(); ++iter) {
4391  fElements->Add(*iter);
4392  }
4393  } else {
4394  R__TObjArray_InsertAt(fElements, toAdd, loc);
4395  }
4396  } // None of the target of the rule are on file.
4397 }
4398 
4399 ////////////////////////////////////////////////////////////////////////////////
4400 /// List the TStreamerElement list and also the precomputed tables
4401 /// if option contains the string "incOrig", also prints the original
4402 /// (non-optimized elements in the list of compiled elements.
4403 
4404 void TStreamerInfo::ls(Option_t *option) const
4405 {
4406  if (fClass && (fName != fClass->GetName())) {
4407  if (fClass->IsVersioned()) {
4408  Printf("\nStreamerInfo for conversion to %s from: %s, version=%d, checksum=0x%x",fClass->GetName(),GetName(),fClassVersion,GetCheckSum());
4409  } else {
4410  Printf("\nStreamerInfo for conversion to %s from: %s, checksum=0x%x",fClass->GetName(),GetName(),GetCheckSum());
4411  }
4412  } else {
4413  if (!fClass || fClass->IsVersioned()) {
4414  Printf("\nStreamerInfo for class: %s, version=%d, checksum=0x%x",GetName(),fClassVersion,GetCheckSum());
4415  } else {
4416  Printf("\nStreamerInfo for class: %s, checksum=0x%x",GetName(),GetCheckSum());
4417  }
4418  }
4419 
4420  if (fElements) {
4421  TIter next(fElements);
4422  TObject *obj;
4423  while ((obj = next()))
4424  obj->ls(option);
4425  }
4426  if (strstr(option,"full") != 0) {
4427  for (Int_t i=0; i < fNfulldata; ++i) {
4428  TStreamerElement *element = (TStreamerElement*)fCompFull[i]->fElem;
4429  TString sequenceType;
4430  element->GetSequenceType(sequenceType);
4431  // by definition of the loop (i+1) <= fNdata
4432  if (sequenceType.Length()) {
4433  sequenceType.Prepend(" [");
4434  sequenceType += "]";
4435  }
4436  Printf(" i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4437  i,element->GetName(),fCompFull[i]->fType,fCompFull[i]->fOffset,fCompFull[i]->fLength,fCompFull[i]->fMethod,
4438  sequenceType.Data());
4439  }
4440 
4441  } else {
4442  Bool_t wantOrig = strstr(option,"incOrig") != 0;
4443  Bool_t optimized = kFALSE;
4444  for (Int_t i=0,j=0;i < fNdata;++i,++j) {
4445  TStreamerElement *element = (TStreamerElement*)fCompOpt[i]->fElem;
4446  TString sequenceType;
4447  element->GetSequenceType(sequenceType);
4448  // by definition of the loop (i+1) <= fNdata
4450  if (optimized) {
4451  // This was optimized.
4452  if (sequenceType.Length() != 0) {
4453  sequenceType += ',';
4454  }
4455  sequenceType += "optimized";
4456  }
4457  if (sequenceType.Length()) {
4458  sequenceType.Prepend(" [");
4459  sequenceType += "]";
4460  }
4461  Printf(" i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4462  i,element->GetName(),fCompOpt[i]->fType,fCompOpt[i]->fOffset,fCompOpt[i]->fLength,fCompOpt[i]->fMethod,
4463  sequenceType.Data());
4464  if (optimized && wantOrig) {
4465  Bool_t done;
4466  do {
4467  element = (TStreamerElement*)fCompFull[j]->fElem;
4468  element->GetSequenceType(sequenceType);
4469  if (sequenceType.Length()) {
4470  sequenceType.Prepend(" [");
4471  sequenceType += "]";
4472  }
4473  Printf(" j=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4474  j,element->GetName(),fCompFull[j]->fType,fCompFull[j]->fOffset,fCompFull[j]->fLength,fCompFull[j]->fMethod,
4475  sequenceType.Data());
4476  ++j;
4477  done = j >= fNfulldata || ( (i+1 < fNdata) && fCompOpt[i+1]->fElem == fCompFull[j+1]->fElem );
4478  } while (!done);
4479 
4480  }
4481  }
4482  }
4483 }
4484 
4485 ////////////////////////////////////////////////////////////////////////////////
4486 /// An emulated object is created at address obj, if obj is null we
4487 /// allocate memory for the object.
4488 
4489 void* TStreamerInfo::New(void *obj)
4490 {
4491  //???FIX ME: What about varying length array elements?
4492 
4493  char* p = (char*) obj;
4494 
4495  TIter next(fElements);
4496 
4497  if (!p) {
4498  // Allocate and initialize the memory block.
4499  p = new char[fSize];
4500  memset(p, 0, fSize);
4501  }
4502 
4503  next.Reset();
4504  TStreamerElement* element = (TStreamerElement*) next();
4505 
4506  for (; element; element = (TStreamerElement*) next()) {
4507 
4508  // Skip elements which have not been allocated memory.
4509  if (element->GetOffset() == kMissing) {
4510  continue;
4511  }
4512 
4513  // Skip elements for which we do not have any class
4514  // information. FIXME: Document how this could happen.
4515  TClass* cle = element->GetClassPointer();
4516  if (!cle) {
4517  continue;
4518  }
4519 
4520  char* eaddr = p + element->GetOffset();
4521  Int_t etype = element->GetType();
4522 
4523  //cle->GetStreamerInfo(); //necessary in case "->" is not specified
4524 
4525  switch (etype) {
4526 
4527  case kAnyP:
4528  case kObjectP:
4529  case kSTLp:
4530  {
4531  // Initialize array of pointers with null pointers.
4532  char** r = (char**) eaddr;
4533  Int_t len = element->GetArrayLength();
4534  for (Int_t i = 0; i < len; ++i) {
4535  r[i] = 0;
4536  }
4537  }
4538  break;
4539 
4540  case kObjectp:
4541  case kAnyp:
4542  {
4543  // If the option "->" is given in the data member comment field
4544  // it is assumed that the object exists before reading data in,
4545  // so we create an object.
4546  if (cle != TClonesArray::Class()) {
4547  void** r = (void**) eaddr;
4548  *r = cle->New();
4549  } else {
4550  // In the case of a TClonesArray, the class name of
4551  // the contained objects must be specified in the
4552  // data member comment in this format:
4553  // TClonesArray* myVar; //->(className)
4554  const char* title = element->GetTitle();
4555  const char* bracket1 = strrchr(title, '(');
4556  const char* bracket2 = strrchr(title, ')');
4557  if (bracket1 && bracket2 && (bracket2 != (bracket1 + 1))) {
4558  Int_t len = bracket2 - (bracket1 + 1);
4559  char* clonesClass = new char[len+1];
4560  clonesClass[0] = '\0';
4561  strncat(clonesClass, bracket1 + 1, len);
4562  void** r = (void**) eaddr;
4563  *r = (void*) new TClonesArray(clonesClass);
4564  delete[] clonesClass;
4565  } else {
4566  //Warning("New", "No class name found for TClonesArray initializer in data member comment (expected \"//->(className)\"");
4567  void** r = (void**) eaddr;
4568  *r = (void*) new TClonesArray();
4569  }
4570  }
4571  }
4572  break;
4573 
4574  case kBase:
4575  {
4576  if (cle->Property() & kIsAbstract) {
4578  if (einfo) einfo->New(eaddr);
4579  } else {
4580  cle->New(eaddr);
4581  }
4582  break;
4583  }
4584  case kObject:
4585  case kAny:
4586  case kTObject:
4587  case kTString:
4588  case kTNamed:
4589  {
4590  cle->New(eaddr);
4591  }
4592  break;
4593 
4594  case kSTL:
4595  {
4596  if (strcmp(element->GetName(),"This")==0 &&
4597  !cle->GetCollectionProxy()) {
4598  // missing information, avoid infinite loop
4599  // by doing nothing ....
4600  } else {
4601  cle->New(eaddr);
4602  }
4603  }
4604  break;
4605 
4606  case kObject + kOffsetL:
4607  case kAny + kOffsetL:
4608  case kTObject + kOffsetL:
4609  case kTString + kOffsetL:
4610  case kTNamed + kOffsetL:
4611  case kSTL + kOffsetL:
4612  {
4613  Int_t size = cle->Size();
4614  char* r = eaddr;
4615  Int_t len = element->GetArrayLength();
4616  for (Int_t i = 0; i < len; ++i, r += size) {
4617  cle->New(r);
4618  }
4619  }
4620  break;
4621 
4622  } // switch etype
4623  } // for TIter next(fElements)
4624 
4625  for(int nbase = 0; nbase < fNVirtualInfoLoc; ++nbase) {
4626  *(TStreamerInfo**)(p + fVirtualInfoLoc[nbase]) = this;
4627  }
4628  ++fLiveCount;
4629  return p;
4630 }
4631 
4632 ////////////////////////////////////////////////////////////////////////////////
4633 /// An array of emulated objects is created at address ary, if ary is null,
4634 /// we allocate memory for the array.
4635 
4636 void* TStreamerInfo::NewArray(Long_t nElements, void *ary)
4637 {
4638  if (fClass == 0) {
4639  Error("NewArray", "TClass pointer is null!");
4640  return 0;
4641  }
4642 
4643  Int_t size = fClass->Size();
4644 
4645  char* p = (char*) ary;
4646 
4647  if (!p) {
4648  Long_t len = nElements * size + sizeof(Long_t)*2;
4649  p = new char[len];
4650  memset(p, 0, len);
4651  }
4652 
4653  // Store the array cookie
4654  Long_t* r = (Long_t*) p;
4655  r[0] = size;
4656  r[1] = nElements;
4657  char* dataBegin = (char*) &r[2];
4658 
4659  // Do a placement new for each element.
4660  p = dataBegin;
4661  for (Long_t cnt = 0; cnt < nElements; ++cnt) {
4662  New(p);
4663  p += size;
4664  } // for nElements
4665 
4666  return dataBegin;
4667 }
4668 
4669 
4670 #define DeleteBasicPointer(addr,element,name) \
4671  { \
4672  name **f = (name**)(addr); \
4673  int n = element->GetArrayLength() ? element->GetArrayLength() : 1;\
4674  for(int j=0;j<n;j++) { \
4675  delete [] f[j]; \
4676  f[j] = 0; \
4677  } \
4678  }
4679 
4680 ////////////////////////////////////////////////////////////////////////////////
4681 /// Internal part of the destructor.
4682 /// Destruct each of the datamembers in the same order
4683 /// as the implicit destructor would.
4684 
4685 void TStreamerInfo::DestructorImpl(void* obj, Bool_t dtorOnly)
4686 {
4687  R__ASSERT(obj != 0);
4688 
4689  char *p = (char*)obj;
4690 
4691  Int_t nelements = fElements->GetEntriesFast();
4692  //for (; ele; ele = (TStreamerElement*) next())
4693  for (Int_t elenum = nelements - 1; elenum >= 0; --elenum) {
4694  TStreamerElement* ele = (TStreamerElement*) fElements->UncheckedAt(elenum);
4695  if (ele->GetOffset() == kMissing) continue;
4696  char* eaddr = p + ele->GetOffset();
4697 
4698 
4699  Int_t etype = ele->GetType();
4700 
4701  switch(etype) {
4717  }
4718 
4719 
4720 
4721  TClass* cle = ele->GetClassPointer();
4722  if (!cle) continue;
4723 
4724 
4725  if (etype == kObjectp || etype == kAnyp) {
4726  // Destroy an array of pre-allocated objects.
4727  Int_t len = ele->GetArrayLength();
4728  if (!len) {
4729  len = 1;
4730  }
4731  void** r = (void**) eaddr;
4732  for (Int_t j = len - 1; j >= 0; --j) {
4733  if (r[j]) {
4734  cle->Destructor(r[j]);
4735  r[j] = 0;
4736  }
4737  }
4738  }
4739 
4740  if ((etype == kObjectP || etype == kAnyP || etype == kSTLp) && !ele->TestBit(TStreamerElement::kDoNotDelete)) {
4741  // Destroy an array of pointers to not-pre-allocated objects.
4742  Int_t len = ele->GetArrayLength();
4743  if (!len) {
4744  len = 1;
4745  }
4746  void** r = (void**) eaddr;
4747  for (Int_t j = len - 1; j >= 0; --j) {
4748  if (r[j]) {
4749  cle->Destructor(r[j]);
4750  r[j] = 0;
4751  }
4752  }
4753  }
4754 
4755  if (etype == kBase) {
4756  if (cle->Property() & kIsAbstract) {
4758  if (einfo) einfo->Destructor(eaddr, kTRUE);
4759  } else {
4760  cle->Destructor(eaddr, kTRUE);
4761  }
4762  }
4763 
4764  if (etype == kObject || etype == kAny ||
4765  etype == kTObject || etype == kTString || etype == kTNamed) {
4766  // A data member is destroyed, but not deleted.
4767  cle->Destructor(eaddr, kTRUE);
4768  }
4769 
4770  if (etype == kSTL) {
4771  // A data member is destroyed, but not deleted.
4773  if (!pr) {
4774  if (strcmp(ele->GetName(),"This")==0) {
4775  // missing information, avoid infinite loop
4776  // by doing nothing ....
4777  } else {
4778  cle->Destructor(eaddr, kTRUE);
4779  }
4780  } else {
4782  TVirtualCollectionProxy::TPushPop env(cle->GetCollectionProxy(), eaddr); // used for both this 'clear' and the 'clear' inside destructor.
4783  cle->GetCollectionProxy()->Clear(); // empty the collection without deleting the pointer
4784  pr->Destructor(eaddr, kTRUE);
4785  } else {
4786  pr->Destructor(eaddr, kTRUE);
4787  }
4788  }
4789  }
4790 
4791  if (etype == kObject + kOffsetL || etype == kAny + kOffsetL ||
4792  etype == kTObject + kOffsetL || etype == kTString + kOffsetL ||
4793  etype == kTNamed + kOffsetL || etype == kSTL + kOffsetL) {
4794  // For a data member which is an array of objects, we
4795  // destroy the objects, but do not delete them.
4796  Int_t len = ele->GetArrayLength();
4797  Int_t size = cle->Size();
4798  char* r = eaddr + (size * (len - 1));
4799  for (Int_t j = len - 1; j >= 0; --j, r -= size) {
4800  cle->Destructor(r, kTRUE);
4801  }
4802  }
4803  } // iter over elements
4804 
4805  if (!dtorOnly) {
4806  delete[] p;
4807  }
4808  --fLiveCount;
4809 }
4810 
4811 ////////////////////////////////////////////////////////////////////////////////
4812 /// Emulated destructor for this class.
4813 ///
4814 /// An emulated object is destroyed at address p.
4815 /// Destruct each of the datamembers in the same order
4816 /// as the implicit destructor would.
4817 
4818 void TStreamerInfo::Destructor(void* obj, Bool_t dtorOnly)
4819 {
4820  // Do nothing if passed a null pointer.
4821  if (obj == 0) return;
4822 
4823  char* p = (char*) obj;
4824 
4825  if (!dtorOnly && fNVirtualInfoLoc) {
4826  // !dtorOnly is used to filter out the case where this is called for
4827  // a base class or embeded object of the outer most class.
4828  TStreamerInfo *allocator = *(TStreamerInfo**)(p + fVirtualInfoLoc[0]);
4829  if (allocator != this) {
4830 
4831  Int_t baseoffset = allocator->GetClass()->GetBaseClassOffset(GetClass());
4832 
4833  p -= baseoffset;
4834  allocator->DestructorImpl(p, kFALSE);
4835  return;
4836  }
4837  }
4838  DestructorImpl(p, dtorOnly);
4839 }
4840 
4841 ////////////////////////////////////////////////////////////////////////////////
4842 /// Destroy an array of emulated objects, with optional delete.
4843 
4844 void TStreamerInfo::DeleteArray(void* ary, Bool_t dtorOnly)
4845 {
4846  // Do nothing if passed a null pointer.
4847  if (ary == 0) return;
4848 
4849  //???FIX ME: What about varying length arrays?
4850 
4851  Long_t* r = (Long_t*) ary;
4852  Long_t arrayLen = r[-1];
4853  Long_t size = r[-2];
4854  char* memBegin = (char*) &r[-2];
4855 
4856  char* p = ((char*) ary) + ((arrayLen - 1) * size);
4857  for (Long_t cnt = 0; cnt < arrayLen; ++cnt, p -= size) {
4858  // Destroy each element, but do not delete it.
4859  Destructor(p, kTRUE);
4860  } // for arrayItemSize
4861 
4862  if (!dtorOnly) {
4863  delete[] memBegin;
4864  }
4865 }
4866 
4867 ////////////////////////////////////////////////////////////////////////////////
4868 /// print value of element i in object at pointer
4869 /// The function may be called in two ways:
4870 /// -method1 len < 0
4871 /// i is assumed to be the TStreamerElement number i in StreamerInfo
4872 /// -method2 len >= 0
4873 /// i is the type
4874 /// address of variable is directly pointer.
4875 /// len is the number of elements to be printed starting at pointer.
4876 
4877 void TStreamerInfo::PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax) const
4878 {
4879  char *ladd;
4880  Int_t atype,aleng;
4881  printf(" %-15s = ",name);
4882 
4883  TStreamerElement * aElement = 0;
4884  Int_t *count = 0;
4885  if (len >= 0) {
4886  ladd = pointer;
4887  atype = i;
4888  aleng = len;
4889  } else {
4890  if (i < 0) {
4891  if (pointer==0) {
4892  printf("NULL\n");
4893  } else {
4894  const static TClassRef stringClass("string");
4895  if (fClass == stringClass) {
4896  std::string *st = (std::string*)(pointer);
4897  printf("%s\n",st->c_str());
4898  } else if (fClass == TString::Class()) {
4899  TString *st = (TString*)(pointer);
4900  printf("%s\n",st->Data());
4901  } else {
4902  printf("(%s*)0x%lx\n",GetName(),(ULong_t)pointer);
4903  }
4904  }
4905  return;
4906  }
4907  ladd = pointer + fCompFull[i]->fOffset;
4908  atype = fCompFull[i]->fNewType;
4909  aleng = fCompFull[i]->fLength;
4910  aElement = (TStreamerElement*)fCompFull[i]->fElem;
4911  count = (Int_t*)(pointer+fCompFull[i]->fMethod);
4912  }
4913  if (aleng > lenmax) aleng = lenmax;
4914 
4915  PrintValueAux(ladd,atype,aElement,aleng,count);
4916  printf("\n");
4917 }
4918 
4919 ////////////////////////////////////////////////////////////////////////////////
4920 /// Print value of element i in a TClonesArray.
4921 
4922 void TStreamerInfo::PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax) const
4923 {
4924  if (!clones) {printf(" %-15s = \n",name); return;}
4925  printf(" %-15s = ",name);
4926  Int_t nc = clones->GetEntriesFast();
4927  if (nc > lenmax) nc = lenmax;
4928 
4929  Int_t offset = eoffset + fCompFull[i]->fOffset;
4930  TStreamerElement *aElement = (TStreamerElement*)fCompFull[i]->fElem;
4931  int aleng = fCompFull[i]->fLength;
4932  if (aleng > lenmax) aleng = lenmax;
4933 
4934  for (Int_t k=0;k < nc;k++) {
4935  char *pointer = (char*)clones->UncheckedAt(k);
4936  char *ladd = pointer+offset;
4937  Int_t *count = (Int_t*)(pointer+fCompFull[i]->fMethod);
4938  PrintValueAux(ladd,fCompFull[i]->fNewType,aElement, aleng, count);
4939  if (k < nc-1) printf(", ");
4940  }
4941  printf("\n");
4942 }
4943 
4944 ////////////////////////////////////////////////////////////////////////////////
4945 /// Print value of element i in a TClonesArray.
4946 
4947 void TStreamerInfo::PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax) const
4948 {
4949  if (!cont) {printf(" %-15s = \n",name); return;}
4950  printf(" %-15s = ",name);
4951  Int_t nc = cont->Size();
4952  if (nc > lenmax) nc = lenmax;
4953 
4954  Int_t offset = eoffset + fCompFull[i]->fOffset;
4955  TStreamerElement *aElement = (TStreamerElement*)fCompFull[i]->fElem;
4956  int aleng = fCompFull[i]->fLength;
4957  if (aleng > lenmax) aleng = lenmax;
4958 
4959  for (Int_t k=0;k < nc;k++) {
4960  char *pointer = (char*)cont->At(k);
4961  char *ladd = pointer+offset;
4962  Int_t *count = (Int_t*)(pointer+fCompFull[i]->fMethod);
4963  PrintValueAux(ladd,fCompFull[i]->fNewType,aElement, aleng, count);
4964  if (k < nc-1) printf(", ");
4965  }
4966  printf("\n");
4967 }
4968 
4969 ////////////////////////////////////////////////////////////////////////////////
4970 /// Stream an object of class TStreamerInfo.
4971 
4972 void TStreamerInfo::Streamer(TBuffer &R__b)
4973 {
4974  UInt_t R__s, R__c;
4975  if (R__b.IsReading()) {
4976  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
4977  fOldVersion = R__v;
4978  if (R__v > 1) {
4979  //R__b.ReadClassBuffer(TStreamerInfo::Class(), this, R__v, R__s, R__c);
4980  R__b.ClassBegin(TStreamerInfo::Class(), R__v);
4981  R__b.ClassMember("TNamed");
4982  TNamed::Streamer(R__b);
4983  fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
4984  R__b.ClassMember("fCheckSum","UInt_t");
4985  R__b >> fCheckSum;
4986  R__b.ClassMember("fClassVersion","Int_t");
4987  R__b >> fClassVersion;
4989  R__b.ClassMember("fElements","TObjArray*");
4990  R__b >> fElements;
4992  R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
4996 
4997  if (R__b.GetParent() && R__b.GetVersionOwner() < 50000)
4998  {
4999  // In some older files, the type of the TStreamerElement was not
5000  // as we (now) expect.
5001  Int_t nobjects = fElements->GetEntriesFast();
5002  TClass *basic = TStreamerBasicType::Class();
5003  for (Int_t i = 0; i < nobjects; i++) {
5004  TStreamerElement *el = (TStreamerElement*)fElements->UncheckedAt(i);
5005  TStreamerElement *rel = 0;
5006  if ( el->IsA() == basic ) {
5007  switch (el->GetType()) {
5008  default: break; /* nothing */
5009  case TStreamerInfo::kObject: /*61*/
5010  rel = new TStreamerObject(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5011  break;
5012  case TStreamerInfo::kAny: /*62*/
5013  rel = new TStreamerObjectAny(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5014  break;
5015  case TStreamerInfo::kObjectp: /* 63 */
5016  rel = new TStreamerObjectPointer(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5017  break;
5018  case TStreamerInfo::kObjectP: /* 64 */
5019  rel = new TStreamerObjectPointer(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5020  break;
5021  case TStreamerInfo::kTString: /* 65 */
5022  rel = new TStreamerObject(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5023  break;
5024  }
5025  if (rel) {
5026  (*fElements)[i] = rel;
5027  delete el;
5028  }
5029  }
5030  }
5031  }
5032  return;
5033  }
5034  //====process old versions before automatic schema evolution
5035  TNamed::Streamer(R__b);
5036  fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
5037  R__b >> fCheckSum;
5038  R__b >> fClassVersion;
5040  R__b >> fElements;
5041  R__b.CheckByteCount(R__s, R__c, TStreamerInfo::IsA());
5042  } else {
5043  R__c = R__b.WriteVersion(TStreamerInfo::IsA(), kTRUE);
5045  R__b.ClassMember("TNamed");
5046  TNamed::Streamer(R__b);
5047  R__b.ClassMember("fCheckSum","UInt_t");
5048  R__b << fCheckSum;
5049  R__b.ClassMember("fClassVersion","Int_t");
5050  R__b << ((fClassVersion > 0) ? fClassVersion : -fClassVersion);
5051 
5052  //------------------------------------------------------------------------
5053  // Stream only non-artificial streamer elements
5054  //////////////////////////////////////////////////////////////////////////
5055 
5056  R__b.ClassMember("fElements","TObjArray*");
5057 #if NOTYET
5058  if (has_no_artificial_member) {
5059  R__b << fElements;
5060  } else
5061 #endif
5062  {
5064  Int_t nobjects = fElements->GetEntriesFast();
5065  TObjArray store( *fElements );
5066  TStreamerElement *el;
5067  for (Int_t i = 0; i < nobjects; i++) {
5068  el = (TStreamerElement*)fElements->UncheckedAt(i);
5069  if( el != 0 && (el->IsA() == TStreamerArtificial::Class() || el->TestBit(TStreamerElement::kRepeat))) {
5070  fElements->RemoveAt( i );
5071  } else if( el !=0 && (el->TestBit(TStreamerElement::kCache) && !el->TestBit(TStreamerElement::kWrite)) ) {
5072  fElements->RemoveAt( i );
5073  }
5074  }
5075  fElements->Compress();
5076  R__b << fElements;
5077  R__ASSERT(!fElements->IsOwner());
5078  *fElements = store;
5079  }
5081  R__b.SetByteCount(R__c, kTRUE);
5082  }
5083 }
5084 
5085 ////////////////////////////////////////////////////////////////////////////////
5086 /// Mark the classindex of the current file as using this TStreamerInfo.
5087 /// This function is deprecated and its functionality is now done by
5088 /// the overloads of TBuffer::TagStreamerInfo.
5089 
5091 {
5092  if (file) {
5093  // If the value of the atomic is kFALSE (equal to expected), change its value
5094  // to kTRUE and return true. Leave it as it is otherwise and return false.
5095  static std::atomic<Bool_t> onlyonce(kFALSE);
5096  Bool_t expected = kFALSE;
5097  if (onlyonce.compare_exchange_strong(expected,kTRUE)) {
5098  Warning("TagFile","This function is deprecated, use TBuffer::TagStreamerInfo instead");
5099  }
5100  TArrayC *cindex = file->GetClassIndex();
5101  Int_t nindex = cindex->GetSize();
5102  if (fNumber < 0 || fNumber >= nindex) {
5103  Error("TagFile","StreamerInfo: %s number: %d out of range[0,%d] in file: %s",
5104  GetName(),fNumber,nindex,file->GetName());
5105  return;
5106  }
5107  if (cindex->fArray[fNumber] == 0) {
5108  cindex->fArray[0] = 1;
5109  cindex->fArray[fNumber] = 1;
5110  }
5111  }
5112 }
5113 
5114 ////////////////////////////////////////////////////////////////////////////////
5115 
5116 #ifdef DOLOOP
5117 #undef DOLOOP
5118 #endif
5119 #define DOLOOP for (k = 0, pointer = arr[0]; k < narr; pointer = arr[++k])
5120 
5121 namespace {
5122  static void PrintCR(int j,Int_t aleng, UInt_t ltype)
5123  {
5124  if (j == aleng-1) printf("\n");
5125  else {
5126  printf(", ");
5127  if (j%ltype == ltype-1) printf("\n ");
5128  }
5129  }
5130 }
5131 
5132 ////////////////////////////////////////////////////////////////////////////////
5133 /// print value of element in object at pointer, type atype, leng aleng or *count
5134 /// The function may be called in two ways:
5135 /// -method1 len < 0
5136 /// i is assumed to be the TStreamerElement number i in StreamerInfo
5137 /// -method2 len >= 0
5138 /// i is the type
5139 /// address of variable is directly pointer.
5140 /// len is the number of elements to be printed starting at pointer.
5141 
5142 void TStreamerInfo::PrintValueAux(char *ladd, Int_t atype, TStreamerElement *aElement, Int_t aleng, Int_t *count)
5143 {
5144  int j;
5145 
5146  //assert(!((kOffsetP + kChar) <= atype && atype <= (kOffsetP + kBool) && count == 0));
5147  switch (atype) {
5148  // basic types
5149  case kBool: {Bool_t *val = (Bool_t* )ladd; printf("%d" ,*val); break;}
5150  case kChar: {Char_t *val = (Char_t* )ladd; printf("%d" ,*val); break;}
5151  case kShort: {Short_t *val = (Short_t* )ladd; printf("%d" ,*val); break;}
5152  case kInt: {Int_t *val = (Int_t* )ladd; printf("%d" ,*val); break;}
5153  case kLong: {Long_t *val = (Long_t* )ladd; printf("%ld",*val); break;}
5154  case kLong64: {Long64_t *val = (Long64_t* )ladd; printf("%lld",*val); break;}
5155  case kFloat: {Float_t *val = (Float_t* )ladd; printf("%f" ,*val); break;}
5156  case kFloat16: {Float_t *val = (Float_t* )ladd; printf("%f" ,*val); break;}
5157  case kDouble: {Double_t *val = (Double_t* )ladd; printf("%g" ,*val); break;}
5158  case kDouble32: {Double_t *val = (Double_t* )ladd; printf("%g" ,*val); break;}
5159  case kUChar: {UChar_t *val = (UChar_t* )ladd; printf("%u" ,*val); break;}
5160  case kUShort: {UShort_t *val = (UShort_t* )ladd; printf("%u" ,*val); break;}
5161  case kUInt: {UInt_t *val = (UInt_t* )ladd; printf("%u" ,*val); break;}
5162  case kULong: {ULong_t *val = (ULong_t* )ladd; printf("%lu",*val); break;}
5163  case kULong64: {ULong64_t *val = (ULong64_t*)ladd; printf("%llu",*val); break;}
5164  case kBits: {UInt_t *val = (UInt_t* )ladd; printf("%d" ,*val); break;}
5165 
5166  // array of basic types array[8]
5167  case kOffsetL + kBool: {Bool_t *val = (Bool_t* )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
5168  case kOffsetL + kChar: {Char_t *val = (Char_t* )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
5169  case kOffsetL + kShort: {Short_t *val = (Short_t* )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
5170  case kOffsetL + kInt: {Int_t *val = (Int_t* )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
5171  case kOffsetL + kLong: {Long_t *val = (Long_t* )ladd; for(j=0;j<aleng;j++) { printf("%ld ",val[j]); PrintCR(j,aleng, 5); } break;}
5172  case kOffsetL + kLong64: {Long64_t *val = (Long64_t* )ladd; for(j=0;j<aleng;j++) { printf("%lld ",val[j]);PrintCR(j,aleng, 5); } break;}
5173  case kOffsetL + kFloat: {Float_t *val = (Float_t* )ladd; for(j=0;j<aleng;j++) { printf("%f " ,val[j]); PrintCR(j,aleng, 5); } break;}
5174  case kOffsetL + kFloat16: {Float_t *val = (Float_t* )ladd; for(j=0;j<aleng;j++) { printf("%f " ,val[j]); PrintCR(j,aleng, 5); } break;}
5175  case kOffsetL + kDouble: {Double_t *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
5176  case kOffsetL + kDouble32:{Double_t *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
5177  case kOffsetL + kUChar: {UChar_t *val = (UChar_t* )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,20); } break;}
5178  case kOffsetL + kUShort: {UShort_t *val = (UShort_t* )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,10); } break;}
5179  case kOffsetL + kUInt: {UInt_t *val = (UInt_t* )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng, 5); } break;}
5180  case kOffsetL + kULong: {ULong_t *val = (ULong_t* )ladd; for(j=0;j<aleng;j++) { printf("%lu ",val[j]); PrintCR(j,aleng, 5); } break;}
5181  case kOffsetL + kULong64: {ULong64_t *val = (ULong64_t*)ladd; for(j=0;j<aleng;j++) { printf("%llu ",val[j]);PrintCR(j,aleng, 5); } break;}
5182  case kOffsetL + kBits: {UInt_t *val = (UInt_t* )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng, 5); } break;}
5183 
5184  // pointer to an array of basic types array[n]
5185  case kOffsetP + kBool: {Bool_t **val = (Bool_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]); PrintCR(j,aleng,20); } break;}
5186  case kOffsetP + kChar: {Char_t **val = (Char_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]); PrintCR(j,aleng,20); } break;}
5187  case kOffsetP + kShort: {Short_t **val = (Short_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]); PrintCR(j,aleng,10); } break;}
5188  case kOffsetP + kInt: {Int_t **val = (Int_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]); PrintCR(j,aleng,10); } break;}
5189  case kOffsetP + kLong: {Long_t **val = (Long_t** )ladd; for(j=0;j<*count;j++) { printf("%ld ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
5190  case kOffsetP + kLong64: {Long64_t **val = (Long64_t**)ladd; for(j=0;j<*count;j++) { printf("%lld ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
5191  case kOffsetP + kFloat: {Float_t **val = (Float_t** )ladd; for(j=0;j<*count;j++) { printf("%f " ,(*val)[j]); PrintCR(j,aleng, 5); } break;}
5192  case kOffsetP + kFloat16: {Float_t **val = (Float_t** )ladd; for(j=0;j<*count;j++) { printf("%f " ,(*val)[j]); PrintCR(j,aleng, 5); } break;}
5193  case kOffsetP + kDouble: {Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]); PrintCR(j,aleng, 5); } break;}
5194  case kOffsetP + kDouble32:{Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]); PrintCR(j,aleng, 5); } break;}
5195  case kOffsetP + kUChar: {UChar_t **val = (UChar_t** )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]); PrintCR(j,aleng,20); } break;}
5196  case kOffsetP + kUShort: {UShort_t **val = (UShort_t**)ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]); PrintCR(j,aleng,10); } break;}
5197  case kOffsetP + kUInt: {UInt_t **val = (UInt_t** )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]); PrintCR(j,aleng, 5); } break;}
5198  case kOffsetP + kULong: {ULong_t **val = (ULong_t** )ladd; for(j=0;j<*count;j++) { printf("%lu ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
5199  case kOffsetP + kULong64: {ULong64_t**val = (ULong64_t**)ladd; for(j=0;j<*count;j++){ printf("%llu ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
5200 
5201  // array counter //[n]
5202  case kCounter: {Int_t *val = (Int_t*)ladd; printf("%d",*val); break;}
5203  // char *
5204  case kCharStar:{
5205  char **val = (char**)ladd;
5206  if (*val) printf("%s",*val);
5207  break;
5208  }
5209  // Class * derived from TObject with comment field //->
5210  case kObjectp: {
5211  TObject **obj = (TObject**)(ladd);
5213  printf("(%s*)%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
5214  break;
5215  }
5216 
5217  // Class* derived from TObject
5218  case kObjectP: {
5219  TObject **obj = (TObject**)(ladd);
5221  printf("(%s*)%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
5222  break;
5223  }
5224 
5225  // Class derived from TObject
5226  case kObject: {
5227  TObject *obj = (TObject*)(ladd);
5228  printf("%s",obj->GetName());
5229  break;
5230  }
5231 
5232  // Special case for TString, TObject, TNamed
5233  case kTString: {
5234  TString *st = (TString*)(ladd);
5235  printf("%s",st->Data());
5236  break;
5237  }
5238  case kTObject: {
5239  TObject *obj = (TObject*)(ladd);
5240  printf("%s",obj->GetName());
5241  break;
5242  }
5243  case kTNamed: {
5244  TNamed *named = (TNamed*) (ladd);
5245  printf("%s/%s",named->GetName(),named->GetTitle());
5246  break;
5247  }
5248 
5249  // Class * not derived from TObject with comment field //->
5250  case kAnyp: {
5251  TObject **obj = (TObject**)(ladd);
5253  printf("(%s*)0x%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
5254  break;
5255  }
5256 
5257  // Class* not derived from TObject
5258  case kAnyP: {
5259  TObject **obj = (TObject**)(ladd);
5261  printf("(%s*)0x%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
5262  break;
5263  }
5264  // Any Class not derived from TObject
5265  case kOffsetL + kObjectp:
5266  case kOffsetL + kObjectP:
5267  case kAny: {
5268  printf("printing kAny case (%d)",atype);
5269 // if (aElement) {
5270 // TMemberStreamer *pstreamer = aElement->GetStreamer();
5271 // if (pstreamer == 0) {
5272 // //printf("ERROR, Streamer is null\n");
5273 // //aElement->ls();
5274 // break;
5275 // }
5276 // //(*pstreamer)(b,ladd,0);
5277 // }
5278  break;
5279  }
5280  // Base Class
5281  case kBase: {
5282  printf("printing kBase case (%d)",atype);
5283  //aElement->ReadBuffer(b,pointer);
5284  break;
5285  }
5286 
5287  case kOffsetL + kObject:
5288  case kOffsetL + kTString:
5289  case kOffsetL + kTObject:
5290  case kOffsetL + kTNamed:
5291  case kStreamer: {
5292  printf("printing kStreamer case (%d)",atype);
5293 // TMemberStreamer *pstreamer = aElement->GetStreamer();
5294 // if (pstreamer == 0) {
5295 // //printf("ERROR, Streamer is null\n");
5296 // //aElement->ls();
5297 // break;
5298 // }
5299 // //UInt_t start,count;
5300 // //b.ReadVersion(&start, &count);
5301 // //(*pstreamer)(b,ladd,0);
5302 // //b.CheckByteCount(start,count,IsA());
5303  break;
5304  }
5305 
5306  case kStreamLoop: {
5307  printf("printing kStreamLoop case (%d)",atype);
5308 // TMemberStreamer *pstreamer = aElement->GetStreamer();
5309 // if (pstreamer == 0) {
5310 // //printf("ERROR, Streamer is null\n");
5311 // //aElement->ls();
5312 // break;
5313 // }
5314  //Int_t *counter = (Int_t*)(count);
5315  //UInt_t start,count;
5316  ///b.ReadVersion(&start, &count);
5317  //(*pstreamer)(b,ladd,*counter);
5318  //b.CheckByteCount(start,count,IsA());
5319  break;
5320  }
5321  case kSTL: {
5322  if (aElement) {
5323  static TClassRef stringClass("string");
5324  if (ladd && aElement->GetClass() == stringClass) {
5325  std::string *st = (std::string*)(ladd);
5326  printf("%s",st->c_str());
5327  } else {
5328  printf("(%s*)0x%lx",aElement->GetClass()->GetName(),(Long_t)(ladd));
5329  }
5330  } else {
5331  printf("(unknown_type*)0x%lx",(Long_t)(ladd));
5332  }
5333  break;
5334  }
5335  }
5336 }
5337 
5338 ////////////////////////////////////////////////////////////////////////////////
5339 ///function called by the TClass constructor when replacing an emulated class
5340 ///by the real class
5341 
5342 void TStreamerInfo::Update(const TClass *oldcl, TClass *newcl)
5343 {
5344  TStreamerElement *element;
5345  TIter nextElement(GetElements());
5346  while ((element = (TStreamerElement*)nextElement())) {
5347  element->Update(oldcl,newcl);
5348  }
5349  for (Int_t i=0;i < fNslots;i++) {
5350  fComp[i].Update(oldcl,newcl);
5351  }
5352 }
5353 
5354 ////////////////////////////////////////////////////////////////////////////////
5355 /// Update the TClass pointer cached in this object.
5356 
5358 {
5359  if (fType != -1) {
5360  if (fClass == oldcl)
5361  fClass = newcl;
5362  else if (fClass == 0)
5364  }
5365 }
5366 
5367 ////////////////////////////////////////////////////////////////////////////////
5368 /// Generate emulated collection proxy for a given class.
5369 
5371 TStreamerInfo::GenEmulatedProxy(const char* class_name, Bool_t silent)
5372 {
5373  return TCollectionProxyFactory::GenEmulatedProxy(class_name, silent);
5374 }
5375 
5376 ////////////////////////////////////////////////////////////////////////////////
5377 /// Generate emulated class streamer for a given collection class.
5378 
5380 TStreamerInfo::GenEmulatedClassStreamer(const char* class_name, Bool_t silent)
5381 {
5382  return TCollectionProxyFactory::GenEmulatedClassStreamer(class_name, silent);
5383 }
5384 
5385 ////////////////////////////////////////////////////////////////////////////////
5386 /// Generate proxy from static functions.
5387 
5389 TStreamerInfo::GenExplicitProxy( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
5390 {
5392 }
5393 
5394 ////////////////////////////////////////////////////////////////////////////////
5395 /// Generate class streamer from static functions.
5396 
5398 TStreamerInfo::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
5399 {
5401 }
EState GetState() const
Definition: TClass.h:442
const int ndata
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:229
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
Small helper to read a TBuffer containing a TClonesArray into any valid collection.
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:912
virtual Int_t GetEntries() const
Definition: TCollection.h:92
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual void * New(void *obj=0)=0
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
virtual Int_t GetCollectionType() const =0
Int_t fClassVersion
Class version identifier.
Definition: TStreamerInfo.h:97
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3368
static std::atomic< Int_t > fgCount
Number of TStreamerInfo instances.
An array of TObjects.
Definition: TObjArray.h:39
static void R__TObjArray_InsertBefore(TObjArray *arr, TObject *newobj, TObject *oldobj)
virtual Int_t GetProperties() const
virtual void ClassBegin(const TClass *, Version_t=-1)=0
virtual void SetOffset(Int_t offset)
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
Version_t fOldVersion
! Version of the TStreamerInfo object read from the file
void PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
T GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const
Return value of element i in object at pointer.
Int_t GetOffset() const
long long Long64_t
Definition: RtypesCore.h:69
static void PrintValueAux(char *ladd, Int_t atype, TStreamerElement *aElement, Int_t aleng, Int_t *count)
print value of element in object at pointer, type atype, leng aleng or *count The function may be cal...
const Double_t * v1
Definition: TArcBall.cxx:33
const char * GetTypeName() const
void BuildEmulated(TFile *file)
Create an Emulation TStreamerInfo object.
TStreamerInfoActions::TActionSequence * fWriteMemberWiseVecPtr
! List of write action resulting from the compilation for use in member wise streaming.
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
short Version_t
Definition: RtypesCore.h:61
virtual Bool_t CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete, TFile *file)=0
Int_t GetType() const
Definition: TDataType.h:70
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Ssiz_t Length() const
Definition: TString.h:390
TLine * line
Int_t GetUnitSize() const
Get the sizeof the underlying type of the data member (i.e.
virtual TClass * GetClass() const =0
Collectable string class.
Definition: TObjString.h:32
float Float_t
Definition: RtypesCore.h:53
Equal to TDataType's kchar.
virtual void SetSize(Int_t dsize)
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:528
return c
const char Option_t
Definition: RtypesCore.h:62
virtual TClass * GetValueClass() const =0
tuple offset
Definition: tree.py:93
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the splited type.
Definition: TClassEdit.cxx:927
static TString GetHeaderName(const char *name, const TList *extrainfos, Bool_t includeNested=kFALSE)
Return the header name containing the description of name.
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
T GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
#define assert(cond)
Definition: unittest.h:542
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
unsigned short UShort_t
Definition: RtypesCore.h:36
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5462
UInt_t GetBaseCheckSum()
void Update(const TClass *oldcl, TClass *newcl)
Update the TClass pointer cached in this object.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
void InsertArtificialElements(std::vector< const ROOT::TSchemaRule * > &rules)
Insert new members as expressed in the array of TSchemaRule(s).
static TClassStreamer * GenEmulatedClassStreamer(const char *class_name, Bool_t silent)
Generate emulated class streamer for a given collection class.
const char * GetCountClass() const
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5560
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual void SetTypeName(const char *name)
static const char * filename()
Bool_t IsPersistent() const
Definition: TDataMember.h:89
#define R__ASSERT(e)
Definition: TError.h:98
TClass * GetNewClass() const
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:344
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3459
void SetReadFunc(ROOT::TSchemaRule::ReadFuncPtr_t val)
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
virtual Bool_t IsTransient() const
Return kTRUE if the element represent an entity that is not written to the disk (transient members...
void * New(void *obj=0)
An emulated object is created at address obj, if obj is null we allocate memory for the object...
virtual Int_t GetSize() const
Returns size of this element in bytes.
Basic string class.
Definition: TString.h:137
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method). ...
Definition: TClass.cxx:5471
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition: TClass.h:392
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1075
void DestructorImpl(void *p, Bool_t dtorOnly)
Internal part of the destructor.
int Int_t
Definition: RtypesCore.h:41
static void GeneratePostDeclaration(FILE *fp, const TVirtualStreamerInfo *info, char *inclist)
Add to the header file anything that need to appear after the class declaration (this includes some #...
bool Bool_t
Definition: RtypesCore.h:59
TDataType * GetDataType() const
Definition: TDataMember.h:74
void Reset()
Definition: TClassRef.h:76
virtual void Clear(const char *opt="")=0
Bool_t IsaPointer() const
Return true if data member is a pointer.
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
Int_t GenerateHeaderFile(const char *dirname, const TList *subClasses=0, const TList *extrainfos=0)
Generate header file for the class described by this TStreamerInfo the function is called by TFile::M...
Cache the value in memory than is not part of the object but is accessible via a SchemaRule.
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
static const char * GetElementCounterStart(const char *dmTitle)
Given a comment/title declaring an array counter, for example: //[fArraySize] array of size fArraySiz...
Int_t fNdata
!number of optimized elements
TVirtualStreamerInfo * FindStreamerInfoAbstractEmulated(UInt_t checksum) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4399
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
bool IsSTLBitset(const char *type)
Return true is the name is std::bitset<number> or bitset<number>
virtual void SetArrayDim(Int_t dim)
Set number of array dimensions.
ULong_t * fVirtualInfoLoc
![fNVirtualInfoLoc] Location of the pointer to the TStreamerInfo inside the object (when emulated) ...
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
TString & Prepend(const char *cs)
Definition: TString.h:604
Abstract base class for accessing the data-members of a class.
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Int_t GetBaseVersion()
Int_t GetType(Int_t id) const
virtual EDataType GetType() const =0
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
virtual void SetMaxIndex(Int_t dim, Int_t max)
set maximum index for array with dimension dim
virtual void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)=0
void Destructor(void *p, Bool_t dtorOnly=kFALSE)
Emulated destructor for this class.
static Proxy_t * GenExplicitProxy(const ::ROOT::TCollectionProxyInfo &info, TClass *cl)
Generate proxy from static functions.
void DeleteArray(void *p, Bool_t dtorOnly=kFALSE)
Destroy an array of emulated objects, with optional delete.
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TObject Int_t at
void Reset()
Definition: TCollection.h:161
TCompInfo ** fCompFull
![fElements->GetEntries()]
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
Bool_t IsVersioned() const
Definition: TClass.h:462
TClass * GetActualClass(const void *obj) const
Assuming that obj points to (the part of) an object that is of the type described by this streamerInf...
void ComputeSize()
Compute total size of all persistent elements of the class.
TList * GetListOfRealData() const
Definition: TClass.h:404
static void R__TObjArray_InsertAt(TObjArray *arr, std::vector< TStreamerArtificial * > &objs, Int_t at)
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
TTree * T
const char * Data() const
Definition: TString.h:349
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
Int_t fSize
!size of the persistent class
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2625
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:946
virtual void ClassMember(const char *, const char *=0, Int_t=-1, Int_t=-1)=0
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:536
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:5939
virtual Int_t GetClassVersion() const =0
ClassImp(TStreamerInfo) static void R__TObjArray_InsertAt(TObjArray *arr
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
virtual TVirtualCollectionProxy * GenEmulatedProxy(const char *class_name, Bool_t silent)
Generate emulated collection proxy for a given class.
friend class TClonesArray
Definition: TObject.h:214
#define READ_ARRAY(TYPE_t)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2321
virtual void Init(TObject *obj=0)
Initliaze the element.
virtual TClassStreamer * GenEmulatedClassStreamer(const char *class_name, Bool_t silent)
Generate emulated class streamer for a given collection class.
const char * GetCountClass() const
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
virtual TVirtualCollectionProxy * GenExplicitProxy(const ::ROOT::Detail::TCollectionProxyInfo &info, TClass *cl)
Generate proxy from static functions.
void Class()
Definition: Class.C:29
virtual Int_t GetVersionOwner() const =0
ECheckSum
Definition: TClass.h:102
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
int d
Definition: tornado.py:11
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4602
Int_t GetOnFileClassVersion() const
Int_t GetDelta()
Get offset from "this" to part of base class.
Definition: TBaseClass.cxx:75
#define DeleteBasicPointer(addr, element, name)
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1126
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
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...
virtual void SetNewClass(TClass *cl)
virtual Bool_t IsaPointer() const
Int_t fNfulldata
!number of elements
T GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
TString & Append(const char *cs)
Definition: TString.h:492
std::vector< std::vector< double > > Data
TStreamerInfoActions::TActionSequence * fReadObjectWise
! List of read action resulting from the compilation.
virtual TClassStreamer * GenExplicitClassStreamer(const ::ROOT::Detail::TCollectionProxyInfo &info, TClass *cl)
Generate class streamer from static functions.
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:63
TClass * GetClass() const
static UInt_t GenerateForwardDeclaration(FILE *fp, const char *clname, char *inclist, Bool_t implementEmptyClass, Bool_t needGenericTemplate, const TList *extrainfos)
Insert a (complete) forward declaration for the class 'clname'.
static void R__WriteMoveConstructorBody(FILE *file, const TString &protoname, TIter &next)
Write down the body of the 'move' constructor.
XFontStruct * id
Definition: TGX11.cxx:108
void SetCountClass(const char *clname)
void RegisterStreamerInfo(TVirtualStreamerInfo *info)
Register the StreamerInfo in the given slot, change the State of the TClass as appropriate.
Definition: TClass.cxx:6715
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Bool_t IsObject() const
Definition: TRealData.h:60
Bool_t operator!=(const TDatime &d1, const TDatime &d2)
Definition: TDatime.h:103
UInt_t fCheckSum
Checksum of original class.
Definition: TStreamerInfo.h:96
virtual const char * GetInclude() const
void GenerateDeclaration(FILE *fp, FILE *sfp, const TList *subClasses, Bool_t top=kTRUE)
Write the Declaration of class.
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
Definition: TClassEdit.cxx:806
Eventhough BIT(13) is taken up by TObject (to preserverse forward compatibility)
void Error(const char *location, const char *msgfmt,...)
Int_t GetClassVersion() const
Int_t GetArrayDim() const
static void AddInclude(FILE *fp, const char *header, Bool_t system, char *inclist)
Add an include statement, if it has not already been added.
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6502
virtual void Update(const TClass *oldClass, TClass *newClass)
function called by the TClass constructor when replacing an emulated class by the real class ...
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:5950
static T GetTypedValueAux(Int_t type, void *ladd, int k, Int_t len)
Get the value from inside a collection.
virtual void SetStreamer(TMemberStreamer *streamer)
set pointer to Streamer function for this element
A doubly linked list.
Definition: TList.h:47
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
static void R__WriteDestructorBody(FILE *file, TIter &next)
void PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax=1000) const
print value of element i in object at pointer The function may be called in two ways: -method1 len < ...
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition: TClass.cxx:2504
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual void Update(const TClass *oldClass, TClass *newClass)
function called by the TClass constructor when replacing an emulated class by the real class ...
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3195
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1933
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:228
TClass * fClass
!pointer to class
void SetErrorMessage(const char *msg)
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
void ResetClassVersion(TClass *, const char *, Short_t)
Global function to update the version number.
Int_t GetOffset(const char *) const
Return the offset of the data member as indicated by this StreamerInfo.
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
TObjArray * fElements
Array of TStreamerElements.
UInt_t GenerateIncludes(FILE *fp, char *inclist, const TList *extrainfos)
Add to the header file, the #include need for this class.
void ls(Option_t *option="") const
List the TStreamerElement list and also the precomputed tables if option contains the string "incOrig...
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
ROOT::R::TRInterface & r
Definition: Object.C:4
TObjArray * GetElements() const
Long_t GetOffset() const
Get offset from "this".
R__EXTERN TSystem * gSystem
Definition: TSystem.h:545
void BuildOld()
rebuild the TStreamerInfo structure
void Clear(Option_t *)
If opt cointains 'built', reset this StreamerInfo as if Build or BuildOld was never called on it (use...
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4256
TPaveLabel title(3, 27.1, 15, 28.7,"ROOT Environment and Tools")
TClass * GetClass() const
Definition: TDataMember.h:73
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
const char * GetTypeNameBasic() const
Return type name of this element in case the type name is not a standard basic type, return the basic type name known to CINT.
void SetCountClass(const char *clname)
Int_t GetMaxIndex(Int_t i) const
Int_t fOnFileClassVersion
!Class version identifier as stored on file.
Definition: TStreamerInfo.h:98
virtual Bool_t HasPointers() const =0
TClass * IsA() const
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:4959
void IgnoreTObjectStreamer(Bool_t ignore=kTRUE)
When the class kIgnoreTObjectStreamer bit is set, the automatically generated Streamer will not call ...
Definition: TClass.cxx:4465
UInt_t GetCheckSum() const
Bool_t HasInterpreterInfo() const
Definition: TClass.h:373
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2308
virtual Bool_t BuildFor(const TClass *cl)
Check if we can build this for foreign class - do we have some rules to do that.
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
Int_t GetDataMemberOffset(TDataMember *dm, TMemberStreamer *&streamer) const
Compute data member offset.
short Short_t
Definition: RtypesCore.h:35
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:34
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:357
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
static void R__WriteConstructorBody(FILE *file, TIter &next)
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1056
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
long double LongDouble_t
Definition: RtypesCore.h:57
Version_t GetClassVersion() const
Definition: TClass.h:381
static TVirtualCollectionProxy * GenEmulatedProxy(const char *class_name, Bool_t silent)
Generate emulated collection proxy for a given class.
TClass * fClass
Not Owned.
Definition: TStreamerInfo.h:61
TString fName
Definition: TNamed.h:36
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
TString & String()
Definition: TObjString.h:52
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:239
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:35
#define Printf
Definition: TGeoToOCC.h:18
Int_t GetNumber() const
TCompInfo * fComp
![fNslots with less than fElements->GetEntries()*1.5 used] Compiled info
TStreamerInfoActions::TActionSequence * fWriteMemberWise
! List of write action resulting from the compilation for use in member wise streaming.
Bool_t fIsBuilt
true if the StreamerInfo has been optimized
Int_t GetSize() const
Definition: TArray.h:49
Bool_t CallShowMembers(const void *obj, TMemberInspector &insp, Bool_t isTransient=kFALSE) const
Call ShowMembers() on the obj of this class type, passing insp and parent.
Definition: TClass.cxx:2107
TStreamerElement * fElem
Not Owned.
Definition: TStreamerInfo.h:59
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE)=0
static UInt_t GenerateIncludeForTemplate(FILE *fp, const char *clname, char *inclist, Bool_t forward, const TList *extrainfos)
Add to the header file, the #include needed for the argument of this template.
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
std::atomic< Bool_t > fIsCompiled
true if the StreamerInfo has been 'built' (i.e. has all the StreamerElements it should have) ...
long Long_t
Definition: RtypesCore.h:50
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5436
void CallShowMembers(const void *obj, TMemberInspector &insp, Bool_t isTransient) const
Emulated a call ShowMembers() on the obj of this class type, passing insp and parent.
void Obsolete(const char *method, const char *asOfVers, const char *removedFromVers) const
Use this method to declare a method obsolete.
Definition: TObject.cxx:980
TStreamerElement * GetStreamerElementReal(Int_t i, Int_t j) const
Obsolete: this routine is obsolete and should not longer be used.
void Build()
Build the I/O data structure for the current class version.
virtual Int_t GetSize() const
Definition: TCollection.h:95
TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const
Return the StreamerElement of "datamember" inside our class or any of its base classes.
T GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Int_t GetSizeElements() const
Return total size of all persistent elements of the class use GetSize if you want to get the real siz...
tuple file
Definition: fildir.py:20
const char * GetParent() const
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
double Double_t
Definition: RtypesCore.h:55
virtual TObjArray * GetElements() const =0
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t fNslots
!total numbrer of slots in fComp.
TStreamerInfoActions::TActionSequence * fReadMemberWiseVecPtr
! List of read action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fWriteObjectWise
! List of write action resulting from the compilation.
void RemoveStreamerInfo(Int_t slot)
Remove and delete the StreamerInfo in the given slot.
Definition: TClass.cxx:6739
int type
Definition: TGX11.cxx:120
Int_t GetNewType(Int_t id) const
unsigned long long ULong64_t
Definition: RtypesCore.h:70
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
void SetNewBaseClass(TClass *cl)
unsigned long ULong_t
Definition: RtypesCore.h:51
const TObjArray * GetTarget() const
Get the target data members of this rule (i.e. the in memory data member).
EDataType
Definition: TDataType.h:30
virtual void SetType(Int_t dtype)
Int_t fNVirtualInfoLoc
! Number of virtual info location to update.
Int_t GetNewType() const
virtual void * At(UInt_t idx)=0
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2747
#define R__LOCKGUARD(mutex)
void InspectMember(const T &obj, const char *name, Bool_t isTransient)
Long_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition: TClass.cxx:3169
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
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:2801
const TMatches FindRules(const TString &source) const
Return all the rules that are about the given 'source' class.
void Compile()
loop on the TStreamerElement list regroup members with same type Store predigested information into l...
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2730
void TagFile(TFile *fFile)
Mark the classindex of the current file as using this TStreamerInfo.
#define name(a, b)
Definition: linkTestLib0.cpp:5
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3141
const TList * GetStreamerInfoCache()
Returns the cached list of StreamerInfos used in this file.
Definition: TFile.cxx:1298
TClass * GetClass() const
Mother of all ROOT objects.
Definition: TObject.h:58
Int_t Size() const
Get size of basic typedef'ed type.
Definition: TDataType.cxx:362
virtual void Init(TObject *obj=0)
Setup the element.
Int_t GetArrayDim() const
Return number of array dimensions.
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr)
Int_t GetSize() const
Return total size of all persistent elements of the class (with offsets).
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
TMemberStreamer * GetStreamer() const
Return the associate streamer object.
Definition: TRealData.cxx:98
TClass * GetClass() const
Definition: TClassRef.h:75
virtual UInt_t Size() const =0
TClassRef is used to implement a permanent reference to a TClass object.
Definition: TClassRef.h:33
char Char_t
Definition: RtypesCore.h:29
static TString UpdateAssociativeToVector(const char *name)
If we have a map, multimap, set or multiset, plus unordered partners, and the key is a class...
An array of clone (identical) objects.
Definition: TClonesArray.h:32
Int_t fNumber
!Unique identifier
Definition: TStreamerInfo.h:99
void BuildCheck(TFile *file=0)
Check if built and consistent with the class dictionary.
void GetSequenceType(TString &type) const
Fill type with the string representation of sequence information including 'cached','repeat','write' or 'nodelete'.
virtual ~TStreamerInfo()
TStreamerInfo dtor.
virtual void ClassEnd(const TClass *)=0
Int_t GetVersion() const
Definition: TFile.h:205
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
Char_t * fArray
Definition: TArrayC.h:32
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
virtual void SetNewType(Int_t dtype)
static TStreamerBasicType * GetElementCounter(const char *countName, TClass *cl)
Get pointer to a TStreamerBasicType in TClass *cl static function.
virtual Bool_t HasCounter() const
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1834
ClassImp(TSlaveInfo) Int_t TSlaveInfo const TSlaveInfo * si
Used to sort slaveinfos by ordinal.
Definition: TProof.cxx:183
Int_t GetType() const
TVirtualStreamerInfo * GetBaseStreamerInfo() const
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2719
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:446
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
void * NewArray(Long_t nElements, void *ary=0)
An array of emulated objects is created at address ary, if ary is null, we allocate memory for the ar...
const Int_t kMaxLen
TCompInfo ** fCompOpt
![fNdata]
#define gDirectory
Definition: TDirectory.h:221
double result[121]
TDataMember * GetDataMember() const
Definition: TRealData.h:57
void ResetBit(UInt_t f)
Definition: TObject.h:172
unsigned char UChar_t
Definition: RtypesCore.h:34
Bool_t HasDataMemberInfo() const
Definition: TClass.h:370
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual void Init(TObject *obj=0)
Setup the element.
const Bool_t kIterBackward
Definition: TCollection.h:44
TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:309
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Abstract Interface class describing Streamer information for one class.
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:99
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:56
Long_t GetThisOffset() const
Definition: TRealData.h:59
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:459
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
TObject * obj
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:379
void PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
static UInt_t GenerateClassPrefix(FILE *fp, const char *clname, Bool_t top, TString &protoname, UInt_t *numberOfClasses, Int_t implementEmptyClass=kFALSE, Bool_t needGenericTemplate=kFALSE)
Write the start of the class (forward) declaration.
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition: TClass.cxx:2319
void SetReadRawFunc(ROOT::TSchemaRule::ReadRawFuncPtr_t val)
gr SetName("gr")
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5243
const char * cnt
Definition: TXMLSetup.cxx:75
Bool_t CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete, TFile *file)
Return True if the current StreamerInfo in cl or info is equivalent to this TStreamerInfo.
std::atomic< ULong_t > fLiveCount
! Number of outstanding pointer to this StreamerInfo.
TArrayC * GetClassIndex() const
Definition: TFile.h:186
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1045
static TClassStreamer * GenExplicitClassStreamer(const ::ROOT::TCollectionProxyInfo &info, TClass *cl)
Generate class streamer from static functions.
TStreamerInfo()
Default ctor.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:39
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4339
Int_t GetArrayLength() const
static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *oldobj)
Array of chars or bytes (8 bits per element).
Definition: TArrayC.h:29
EReadWrite
EReadWrite Enumerator Enum Constant Description kBase Base class element kOffsetL Fixed size array k...
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904