Logo ROOT  
Reference Guide
TStreamerInfoActions.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Philippe Canal 05/2010
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 #include "TStreamerInfo.h"
13 #include "TStreamerInfoActions.h"
14 #include "TROOT.h"
15 #include "TStreamerElement.h"
16 #include "TVirtualMutex.h"
17 #include "TInterpreter.h"
18 #include "TError.h"
19 #include "TVirtualArray.h"
20 #include "TBufferFile.h"
21 #include "TBufferText.h"
22 #include "TMemberStreamer.h"
23 #include "TClassEdit.h"
25 #include "TProcessID.h"
26 #include "TFile.h"
27 
29 
30 // More possible optimizations:
31 // Avoid call the virtual version of TBuffer::ReadInt and co.
32 // Merge the Reading of the version and the looking up or the StreamerInfo
33 // Avoid if (bytecnt) inside the CheckByteCount routines and avoid multiple (mostly useless nested calls)
34 // Try to avoid if statement on onfile class being set (TBufferFile::ReadClassBuffer).
35 
36 using namespace TStreamerInfoActions;
37 
38 #ifdef _AIX
39 # define INLINE_TEMPLATE_ARGS
40 #else
41 # define INLINE_TEMPLATE_ARGS inline
42 #endif
43 
44 
45 namespace TStreamerInfoActions
46 {
48  {
49  const auto props = proxy.GetProperties();
50  const bool isVector = proxy.GetCollectionType() == ROOT::kSTLvector;
51  const bool hasDefaultAlloc = !(props & TVirtualCollectionProxy::kCustomAlloc);
52  const bool isEmulated = props & TVirtualCollectionProxy::kIsEmulated;
53 
54  return isEmulated || (isVector && hasDefaultAlloc);
55  }
56 
57  template <typename From>
58  struct WithFactorMarker {
59  typedef From Value_t;
60  };
61 
62  template <typename From>
63  struct NoFactorMarker {
64  typedef From Value_t;
65  };
66 
67  struct BitsMarker {
68  typedef UInt_t Value_t;
69  };
70 
72  {
73  // Add the (potentially negative) delta to all the configuration's offset. This is used by
74  // TBranchElement in the case of split sub-object.
75 
77  fOffset += delta;
78  }
79 
81  {
82  // Add the (potentially negative) delta to all the configuration's offset. This is used by
83  // TBranchElement in the case of split sub-object.
84 
86  }
87 
88  void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
89  {
90  // Inform the user what we are about to stream.
91 
92  // Idea, we should find a way to print the name of the function
94  }
95 
96  void TConfiguration::Print() const
97  {
98  // Inform the user what we are about to stream.
99 
101  TStreamerElement *aElement = fCompInfo->fElem;
102  TString sequenceType;
103  aElement->GetSequenceType(sequenceType);
104 
105  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
106  " %s, offset=%d (%s)\n",
107  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
108  aElement->ClassName(), fOffset, sequenceType.Data());
109  }
110 
111  void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
112  {
113  // Inform the user what we are about to stream.
114 
115  if (gDebug > 1) {
116  // Idea: We should print the name of the action function.
118  TStreamerElement *aElement = fCompInfo->fElem;
119  TString sequenceType;
120  aElement->GetSequenceType(sequenceType);
121 
122  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
123  " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
124  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
125  aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
126  }
127  }
128 
130  {
131  // Inform the user what we are about to stream.
132 
133  printf("TLoopConfiguration: unconfigured\n");
134  }
135 
136 
137  struct TGenericConfiguration : TConfiguration {
138  // Configuration of action using the legacy code.
139  // Mostly to cancel out the PrintDebug.
140  public:
141  TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset) {};
142  void PrintDebug(TBuffer &, void *) const {
143  // Since we call the old code, it will print the debug statement.
144  }
145 
146  virtual TConfiguration *Copy() { return new TGenericConfiguration(*this); }
147  };
148 
149  struct TBitsConfiguration : TConfiguration {
150  // Configuration of action handling kBits.
151  // In this case we need to know both the location
152  // of the member (fBits) and the start of the object
153  // (its TObject part to be exact).
154 
155  Int_t fObjectOffset; // Offset of the TObject part within the object
156 
157  TBitsConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset),fObjectOffset(0) {};
158  void PrintDebug(TBuffer &, void *) const {
159  TStreamerInfo *info = (TStreamerInfo*)fInfo;
160  TStreamerElement *aElement = fCompInfo->fElem;
161  TString sequenceType;
162  aElement->GetSequenceType(sequenceType);
163 
164  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
165  " %s, offset=%d (%s)\n",
166  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
167  aElement->ClassName(), fOffset, sequenceType.Data());
168  }
169 
170  void AddToOffset(Int_t delta)
171  {
172  // Add the (potentially negative) delta to all the configuration's offset. This is used by
173  // TBranchElement in the case of split sub-object.
174 
175  if (fOffset != TVirtualStreamerInfo::kMissing)
176  fOffset += delta;
177  fObjectOffset = 0;
178  }
179 
180  void SetMissing()
181  {
183  fObjectOffset = 0;
184  }
185 
186  virtual TConfiguration *Copy() { return new TBitsConfiguration(*this); }
187 
188  };
189 
190  Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
191  {
192  char *obj = (char*)addr;
193  TGenericConfiguration *conf = (TGenericConfiguration*)config;
194  return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
195  }
196 
197  Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
198  {
199  char *obj = (char*)addr;
200  TGenericConfiguration *conf = (TGenericConfiguration*)config;
201  return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
202  }
203 
204  template <typename T>
206  {
207  T *x = (T*)( ((char*)addr) + config->fOffset );
208  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
209  buf >> *x;
210  return 0;
211  }
212 
213  void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
214  TBitsConfiguration *conf = (TBitsConfiguration*)config;
215  UShort_t pidf;
216  buf >> pidf;
217  pidf += buf.GetPidOffset();
218  TProcessID *pid = buf.ReadProcessID(pidf);
219  if (pid!=0) {
220  TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
221  UInt_t gpid = pid->GetUniqueID();
222  UInt_t uid;
223  if (gpid>=0xff) {
224  uid = obj->GetUniqueID() | 0xff000000;
225  } else {
226  uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
227  }
228  obj->SetUniqueID(uid);
229  pid->PutObjectWithID(obj);
230  }
231  }
232 
233  template <>
235  {
236  UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
237  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
238  // Idea: This code really belongs inside TBuffer[File]
239  buf >> *x;
240 
241  if ((*x & kIsReferenced) != 0) {
242  HandleReferencedTObject(buf,addr,config);
243  }
244  return 0;
245  }
246 
247  template <typename T>
249  {
250  T *x = (T *)(((char *)addr) + config->fOffset);
251  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
252  buf << *x;
253  return 0;
254  }
255 
257  {
258  void *x = (void *)(((char *)addr) + config->fOffset);
259  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
261  return 0;
262  }
263 
265  {
266  void *x = (void *)(((char *)addr) + config->fOffset);
267  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
269  return 0;
270  }
271 
273  {
274  void *x = (void *)(((char *)addr) + config->fOffset);
275  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
276  ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
277  return 0;
278  }
279 
281  {
282  void *x = (void *)(((char *)addr) + config->fOffset);
283  TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
284  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
285  (*pstreamer)(buf, x, config->fCompInfo->fLength);
286  buf.SetByteCount(pos, kTRUE);
287  return 0;
288  }
289 
291  {
292  void *x = (void *)(((char *)addr) + config->fOffset);
293  buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
294  return 0;
295  }
296 
298  {
299  void *x = (void *)(((char *)addr) + config->fOffset);
301  return 0;
302  }
303 
305  {
306  void *x = (void *)(((char *)addr) + config->fOffset);
307  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
308  ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
309  return 0;
310  }
311 
313  {
314  void *x = (void *)(((char *)addr) + config->fOffset);
315  TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
316 
317  UInt_t start, count;
318  /* Version_t v = */ buf.ReadVersion(&start, &count, config->fCompInfo->fClass);
319  (*pstreamer)(buf, x, config->fCompInfo->fLength);
320  buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
321  return 0;
322  }
323 
325  {
326  // action required to call custom code for TObject as base class
327  void *x = (void *)(((char *)addr) + config->fOffset);
329  return 0;
330  }
331 
333  {
334  void *x = (void *)(((char *)addr) + config->fOffset);
336  return 0;
337  }
338 
339  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
340  * potentially can be used later for non-text streaming */
341  template<bool kIsTextT>
342  INLINE_TEMPLATE_ARGS Int_t WriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
343  {
344  TClass *cl = config->fCompInfo->fClass;
345  TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
347  TClass* vClass = proxy ? proxy->GetValueClass() : 0;
348  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
349  UInt_t ioffset = eoffset + config->fOffset;
350 
352  && proxy && vClass
353  && config->fInfo->GetStreamMemberWise()
354  && cl->CanSplit()
355  && !(strspn(config->fCompInfo->fElem->GetTitle(),"||") == 2)
356  && !(vClass->TestBit(TClass::kHasCustomStreamerMember)) ) {
357  // Let's save the collection member-wise.
358 
359  UInt_t pos = buf.WriteVersionMemberWise(config->fInfo->IsA(),kTRUE);
360  buf.WriteVersion( vClass, kFALSE );
361 
362  // TODO: subinfo used for WriteBufferSTL call, which is private for the moment
363  //TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
364 
365  //for (int k = 0; k < narr; ++k) {
366  char **contp = (char **)((char *)addr + ioffset);
367  for(int j=0;j<config->fCompInfo->fLength;++j) {
368  char *cont = contp[j];
369  TVirtualCollectionProxy::TPushPop helper( proxy, cont );
370  Int_t nobjects = cont ? proxy->Size() : 0;
371  buf << nobjects;
372 
373  // TODO: method is private, should be made accesible from here
374  // subinfo->WriteBufferSTL(buf,proxy,nobjects);
375  }
376  //}
377  buf.SetByteCount(pos,kTRUE);
378  return 0;
379  }
380  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
381  if (kIsTextT) {
382  // use same method which is used in kSTL
383  buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
384  } else if (pstreamer == nullptr) {
385  // for (int k = 0; k < narr; ++k) {
386  char **contp = (char **)((char *)addr + ioffset);
387  for (int j = 0; j < config->fCompInfo->fLength; ++j) {
388  char *cont = contp[j];
389  cl->Streamer(cont, buf);
390  }
391  // }
392  } else {
393  // for (int k = 0; k < narr; ++k) {
394  (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
395  //}
396  }
397  buf.SetByteCount(pos, kTRUE);
398  return 0;
399  }
400 
401 
402  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
403  * potentially can be used later for non-text streaming */
404  template<bool kIsTextT>
405  INLINE_TEMPLATE_ARGS Int_t ReadSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
406  {
407  TClass *cle = config->fCompInfo->fClass;
408  TStreamerElement * aElement = (TStreamerElement*) config->fCompInfo->fElem;
409  TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
410  //TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
411  //TClass* vClass = proxy ? proxy->GetValueClass() : 0;
412 
413  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
414  UInt_t ioffset = eoffset + config->fOffset;
415 
416 
417  UInt_t start,count;
418  Version_t vers = buf.ReadVersion(&start, &count, cle);
419 
420  if (!kIsTextT && (vers & TBufferFile::kStreamedMemberWise) ) {
421  // Collection was saved member-wise
422 
424 
425  TClass *newClass = aElement->GetNewClass();
426  TClass *oldClass = aElement->GetClassPointer();
427  if( vers < 9 && newClass && newClass!=oldClass ) {
428  Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
429  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
430  return 0;
431  }
432 
433  Version_t vClVersion = 0; // For vers less than 9, we have to use the current version.
434  if( vers >= 9 ) {
435  vClVersion = buf.ReadVersionForMemberWise( cle->GetCollectionProxy()->GetValueClass() );
436  }
437 
438  TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : nullptr);
439  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
440  TStreamerInfo *subinfo = nullptr;
441 
442  if( newProxy ) {
443  // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
444  subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
445  } else {
446  subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( vClVersion );
447  newProxy = oldProxy;
448  }
449  if (subinfo) {
450  // DOLOOP {
451  void* env;
452  void **contp = (void**)((char *) addr + ioffset);
453  for(int j=0;j<config->fCompInfo->fLength;j++) {
454  void *cont = contp[j];
455  if (cont==nullptr) {
456  contp[j] = cle->New();
457  cont = contp[j];
458  }
459  TVirtualCollectionProxy::TPushPop helper( newProxy, cont );
460  Int_t nobjects;
461  buf >> nobjects;
462  env = newProxy->Allocate(nobjects,true);
463  subinfo->ReadBufferSTL(buf,newProxy,nobjects,/* offset */ 0, vers>=7 );
464  newProxy->Commit(env);
465  }
466  // } // DOLOOP
467  }
468  buf.CheckByteCount(start,count,aElement->GetFullName());
469  return 0;
470  }
471 
472  if (kIsTextT) {
473  // use same method which is used in kSTL
474  buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
475  } else if (pstreamer == nullptr) {
476  // DOLOOP {
477  void **contp = (void **)((char *)addr + ioffset);
478  for (int j = 0; j < config->fCompInfo->fLength; j++) {
479  void *cont = contp[j];
480  if (cont == nullptr) {
481  // int R__n;
482  // b >> R__n;
483  // b.SetOffset(b.GetOffset()-4); // rewind to the start of the int
484  // if (R__n) continue;
485  contp[j] = cle->New();
486  cont = contp[j];
487  }
488  cle->Streamer(cont, buf);
489  }
490  // }
491  } else {
492  (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
493  }
494  buf.CheckByteCount(start, count, aElement->GetFullName());
495 
496  return 0;
497  }
498 
499  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
500  * potentially can be used later for non-text streaming */
501  template<bool kIsTextT>
503  {
504  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
505  UInt_t ioffset = eoffset + config->fOffset;
506 
507  if (!kIsTextT && config->fCompInfo->fStreamer) {
508  // Get any private streamer which was set for the data member.
509  TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
510  // -- We have a private streamer.
511  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
512  // Loop over the entries in the clones array or the STL container.
513  //for (int k = 0; k < narr; ++k) {
514  // Get a pointer to the counter for the varying length array.
515  Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
516 
517  // And call the private streamer, passing it the buffer, the object, and the counter.
518  (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
519  //} for k
520  buf.SetByteCount(pos, kTRUE);
521  // We are done, next streamer element.
522  return 0;
523  }
524 
525  // Get the class of the data member.
526  TClass* cl = config->fCompInfo->fClass;
527  // Which are we, an array of objects or an array of pointers to objects?
528  Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
529 
530  // By default assume the file version is the newest.
531  Int_t fileVersion = kMaxInt;
532 
533  if (!kIsTextT) {
534  // At this point we do *not* have a private streamer.
535  // Get the version of the file we are writing to.
536  TFile* file = (TFile*) buf.GetParent();
537  if (file) {
538  fileVersion = file->GetVersion();
539  }
540  }
541  // Write the class version to the buffer.
542  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
543  if (fileVersion > 51508) {
544  // -- Newer versions allow polymorphic pointers to objects.
545  // Loop over the entries in the clones array or the STL container.
546  //for (int k = 0; k < narr; ++k) {
547  // Get the counter for the varying length array.
548  Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
549 
550  //b << vlen;
551  if (vlen) {
552  // Get a pointer to the array of pointers.
553  char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
554  // Loop over each element of the array of pointers to varying-length arrays.
555  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
556  if (!pp[ndx]) {
557  // -- We do not have a pointer to a varying-length array.
558  // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
559  // ::ErrorHandler(kError, "::WriteStreamerLoop", Form("The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName()));
560  printf("WriteStreamerLoop - The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName());
561  continue;
562  }
563  if (!isPtrPtr) {
564  // -- We are a varying-length array of objects.
565  // Write the entire array of objects to the buffer.
566  // Note: Polymorphism is not allowed here.
567  buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
568  } else {
569  // -- We are a varying-length array of pointers to objects.
570  // Write the entire array of object pointers to the buffer.
571  // Note: The object pointers are allowed to be polymorphic.
572  buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
573  } // isPtrPtr
574  } // ndx
575  } else // vlen
576  if (kIsTextT) {
577  // special handling for the text-based streamers
578  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
579  buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
580  }
581  //} // k
582  }
583  else {
584  // -- Older versions do *not* allow polymorphic pointers to objects.
585  // Loop over the entries in the clones array or the STL container.
586  //for (int k = 0; k < narr; ++k) {
587  // Get the counter for the varying length array.
588  Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
589  //b << vlen;
590  if (vlen) {
591  // Get a pointer to the array of pointers.
592  char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
593  // -- Older versions do *not* allow polymorphic pointers to objects.
594  // Loop over each element of the array of pointers to varying-length arrays.
595  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
596  if (!pp[ndx]) {
597  // -- We do not have a pointer to a varying-length array.
598  //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
599  // ::ErrorHandler(kError, "::WriteTextStreamerLoop", Form("The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName()));
600  printf("WriteStreamerLoop - The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName());
601  continue;
602  }
603  if (!isPtrPtr) {
604  // -- We are a varying-length array of objects.
605  // Loop over the elements of the varying length array.
606  for (Int_t v = 0; v < vlen; ++v) {
607  // Write the object to the buffer.
608  cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
609  } // v
610  }
611  else {
612  // -- We are a varying-length array of pointers to objects.
613  // Loop over the elements of the varying length array.
614  for (Int_t v = 0; v < vlen; ++v) {
615  // Get a pointer to the object pointer.
616  char** r = (char**) pp[ndx];
617  // Write the object to the buffer.
618  cl->Streamer(r[v], buf);
619  } // v
620  } // isPtrPtr
621  } // ndx
622  } // vlen
623  //} // k
624  } // fileVersion
625  // Backpatch the byte count into the buffer.
626  buf.SetByteCount(pos, kTRUE);
627 
628  return 0;
629  }
630 
631 
632  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
633  * potentially can be used later for non-text streaming */
634  template<bool kIsTextT>
636  {
637  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
638  UInt_t ioffset = eoffset + config->fOffset;
639 
640  // Get the class of the data member.
641  TClass* cl = config->fCompInfo->fClass;
642 
643  // Check for a private streamer.
644  if (!kIsTextT && config->fCompInfo->fStreamer) {
645  // Get any private streamer which was set for the data member.
646  TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
647  // -- We have a private streamer.
648  // Read the class version and byte count from the buffer.
649  UInt_t start = 0;
650  UInt_t count = 0;
651  buf.ReadVersion(&start, &count, cl);
652  // Loop over the entries in the clones array or the STL container.
653  //for (Int_t k = 0; k < narr; ++k) {
654 
655  Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
656  // And call the private streamer, passing it the buffer, the object, and the counter.
657  (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
658 
659  // } // for k
660  buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
661  // We are done, next streamer element.
662  return 0;
663  }
664 
665  // Which are we, an array of objects or an array of pointers to objects?
666  Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
667 
668  // By default assume the file version is the newest.
669  Int_t fileVersion = kMaxInt;
670  if (!kIsTextT) {
671  // At this point we do *not* have a private streamer.
672  // Get the version of the file we are reading from.
673  TFile* file = (TFile*) buf.GetParent();
674  if (file) {
675  fileVersion = file->GetVersion();
676  }
677  }
678  // Read the class version and byte count from the buffer.
679  UInt_t start = 0;
680  UInt_t count = 0;
681  buf.ReadVersion(&start, &count, cl);
682  if (fileVersion > 51508) {
683  // -- Newer versions allow polymorphic pointers.
684  // Loop over the entries in the clones array or the STL container.
685  // for (Int_t k = 0; k < narr; ++k) {
686  // Get the counter for the varying length array.
687  Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
688  config->fCompInfo->fMethod /*counter offset*/));
689  // Int_t realLen;
690  // b >> realLen;
691  // if (realLen != vlen) {
692  // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
693  //}
694  // Get a pointer to the array of pointers.
695  char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
696  // Loop over each element of the array of pointers to varying-length arrays.
697  // if (!pp) {
698  // continue;
699  // }
700 
701  if (pp) // SL: place it here instead of continue, which is related to for(k) loop
702  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
703  // if (!pp[ndx]) {
704  // -- We do not have a pointer to a varying-length array.
705  // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
706  // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
707  // continue;
708  //}
709  // Delete any memory at pp[ndx].
710  if (!isPtrPtr) {
711  cl->DeleteArray(pp[ndx]);
712  pp[ndx] = 0;
713  } else {
714  // Using vlen is wrong here because it has already
715  // been overwritten with the value needed to read
716  // the current record. Fixing this will require
717  // doing a pass over the object at the beginning
718  // of the I/O and releasing all the buffer memory
719  // for varying length arrays before we overwrite
720  // the counter values.
721  //
722  // For now we will just leak memory, just as we
723  // have always done in the past. Fix this.
724  //
725  // char** r = (char**) pp[ndx];
726  // if (r) {
727  // for (Int_t v = 0; v < vlen; ++v) {
728  // cl->Destructor(r[v]);
729  // r[v] = 0;
730  // }
731  //}
732  delete[] pp[ndx];
733  pp[ndx] = 0;
734  }
735  if (!vlen) {
736  if (kIsTextT) {
737  // special handling for the text-based streamers - keep calling to shift array index
738  buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
739  }
740  continue;
741  }
742  // Note: We now have pp[ndx] is null.
743  // Allocate memory to read into.
744  if (!isPtrPtr) {
745  // -- We are a varying-length array of objects.
746  // Note: Polymorphism is not allowed here.
747  // Allocate a new array of objects to read into.
748  pp[ndx] = (char *)cl->NewArray(vlen);
749  if (!pp[ndx]) {
750  Error("ReadBuffer", "Memory allocation failed!\n");
751  continue;
752  }
753  } else {
754  // -- We are a varying-length array of pointers to objects.
755  // Note: The object pointers are allowed to be polymorphic.
756  // Allocate a new array of pointers to objects to read into.
757  pp[ndx] = (char *)new char *[vlen];
758  if (!pp[ndx]) {
759  Error("ReadBuffer", "Memory allocation failed!\n");
760  continue;
761  }
762  // And set each pointer to null.
763  memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
764  // = (char*) new char*[vlen];
765  }
766  if (!isPtrPtr) {
767  // -- We are a varying-length array of objects.
768  buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
769  } else {
770  // -- We are a varying-length array of object pointers.
771  buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
772  } // isPtrPtr
773  } // ndx
774  // } // k
775  } else {
776  // -- Older versions do *not* allow polymorphic pointers.
777  // Loop over the entries in the clones array or the STL container.
778  // for (Int_t k = 0; k < narr; ++k) {
779  // Get the counter for the varying length array.
780  Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
781  config->fCompInfo->fMethod /*counter offset*/));
782  // Int_t realLen;
783  // b >> realLen;
784  // if (realLen != vlen) {
785  // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
786  //}
787  // Get a pointer to the array of pointers.
788  char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
789  // if (!pp) {
790  // continue;
791  //}
792 
793  if (pp) // SL: place it here instead of continue, which is related to for(k) loop
794 
795  // Loop over each element of the array of pointers to varying-length arrays.
796  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
797  // if (!pp[ndx]) {
798  // -- We do not have a pointer to a varying-length array.
799  // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
800  // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
801  // continue;
802  //}
803  // Delete any memory at pp[ndx].
804  if (!isPtrPtr) {
805  cl->DeleteArray(pp[ndx]);
806  pp[ndx] = 0;
807  } else {
808  // Using vlen is wrong here because it has already
809  // been overwritten with the value needed to read
810  // the current record. Fixing this will require
811  // doing a pass over the object at the beginning
812  // of the I/O and releasing all the buffer memory
813  // for varying length arrays before we overwrite
814  // the counter values.
815  //
816  // For now we will just leak memory, just as we
817  // have always done in the past. Fix this.
818  //
819  // char** r = (char**) pp[ndx];
820  // if (r) {
821  // for (Int_t v = 0; v < vlen; ++v) {
822  // cl->Destructor(r[v]);
823  // r[v] = 0;
824  // }
825  //}
826  delete[] pp[ndx];
827  pp[ndx] = 0;
828  }
829  if (!vlen) {
830  continue;
831  }
832  // Note: We now have pp[ndx] is null.
833  // Allocate memory to read into.
834  if (!isPtrPtr) {
835  // -- We are a varying-length array of objects.
836  // Note: Polymorphism is not allowed here.
837  // Allocate a new array of objects to read into.
838  pp[ndx] = (char *)cl->NewArray(vlen);
839  if (!pp[ndx]) {
840  Error("ReadBuffer", "Memory allocation failed!\n");
841  continue;
842  }
843  } else {
844  // -- We are a varying-length array of pointers to objects.
845  // Note: The object pointers are allowed to be polymorphic.
846  // Allocate a new array of pointers to objects to read into.
847  pp[ndx] = (char *)new char *[vlen];
848  if (!pp[ndx]) {
849  Error("ReadBuffer", "Memory allocation failed!\n");
850  continue;
851  }
852  // And set each pointer to null.
853  memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
854  // = (char*) new char*[vlen];
855  }
856  if (!isPtrPtr) {
857  // -- We are a varying-length array of objects.
858  // Loop over the elements of the varying length array.
859  for (Int_t v = 0; v < vlen; ++v) {
860  // Read the object from the buffer.
861  cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
862  } // v
863  } else {
864  // -- We are a varying-length array of object pointers.
865  // Get a pointer to the object pointer array.
866  char **r = (char **)pp[ndx];
867  // Loop over the elements of the varying length array.
868  for (Int_t v = 0; v < vlen; ++v) {
869  // Allocate an object to read into.
870  r[v] = (char *)cl->New();
871  if (!r[v]) {
872  // Do not print a second error message here.
873  // Error("ReadBuffer", "Memory allocation failed!\n");
874  continue;
875  }
876  // Read the object from the buffer.
877  cl->Streamer(r[v], buf);
878  } // v
879  } // isPtrPtr
880  } // ndx
881  // } // k
882  } // fileVersion
883  buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
884  return 0;
885  }
886 
887  class TConfWithFactor : public TConfiguration {
888  // Configuration object for the Float16/Double32 where a factor has been specified.
889  public:
890  Double_t fFactor;
891  Double_t fXmin;
892  TConfWithFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Double_t factor, Double_t xmin) : TConfiguration(info,id,compinfo,offset),fFactor(factor),fXmin(xmin) {};
893  virtual TConfiguration *Copy() { return new TConfWithFactor(*this); }
894  };
895 
896  template <typename T>
898  {
899  // Stream a Float16 or Double32 where a factor has been specified.
900  //a range was specified. We read an integer and convert it back to a double.
901 
902  TConfWithFactor *conf = (TConfWithFactor *)config;
903  buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
904  return 0;
905  }
906 
907  class TConfNoFactor : public TConfiguration {
908  // Configuration object for the Float16/Double32 where a factor has been specified.
909  public:
910  Int_t fNbits;
911  TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
912  virtual TConfiguration *Copy() { return new TConfNoFactor(*this); }
913  };
914 
915  template <typename T>
917  {
918  // Stream a Float16 or Double32 where a factor has not been specified.
919 
920  TConfNoFactor *conf = (TConfNoFactor *)config;
921  Int_t nbits = conf->fNbits;
922 
923  buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
924  return 0;
925  }
926 
928  {
929  // Read in a TString object.
930 
931  // Idea: We could separate the TString Streamer in its two parts and
932  // avoid the if (buf.IsReading()) and try having it inlined.
933  ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
934  return 0;
935  }
936 
938  {
939  // Read in a TObject object part.
940 
941  // Idea: We could separate the TObject Streamer in its two parts and
942  // avoid the if (buf.IsReading()).
943  ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
944  return 0;
945  }
946 
947  INLINE_TEMPLATE_ARGS Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
948  {
949  // Read in a TNamed object part.
950  // Since the TNamed streamer is solely delegating back to the StreamerInfo we
951  // can skip the streamer.
952 
953  // Idea: We could extract the code from ReadClassBuffer and avoid one function
954  // code.
955  static const TClass *TNamed_cl = TNamed::Class();
956  return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
957  }
958 
959  class TConfigSTL : public TConfiguration {
960  // Configuration object for the kSTL case
961  private:
962  void Init() {
963  TVirtualCollectionProxy *proxy = fNewClass->GetCollectionProxy();
964  if (proxy) {
965  fCreateIterators = proxy->GetFunctionCreateIterators();
966  fCopyIterator = proxy->GetFunctionCopyIterator();
967  fDeleteIterator = proxy->GetFunctionDeleteIterator();
968  fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
969  }
970  }
971 
972  public:
973  TClass *fOldClass; // Class of the content on file
974  TClass *fNewClass; // Class of the content in memory.
975  TMemberStreamer *fStreamer;
976  const char *fTypeName; // Type name of the member as typed by ther user.
977  Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
978 
983 
984  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
985  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
986  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
987 
988  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, const char *type_name, Bool_t isbase) :
989  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
990  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
991 
992  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) :
993  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
994  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
995 
996  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) :
997  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
998  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
999 
1000  virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
1001  };
1002 
1003  class TConfSTLWithFactor : public TConfigSTL {
1004  // Configuration object for the Float16/Double32 where a factor has been specified.
1005  public:
1006  Double_t fFactor;
1007  Double_t fXmin;
1008  TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin) : TConfigSTL(*orig),fFactor(factor),fXmin(xmin) {};
1009  virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
1010  };
1011 
1012  class TConfSTLNoFactor : public TConfigSTL {
1013  // Configuration object for the Float16/Double32 where a factor has been specified.
1014  public:
1015  Int_t fNbits;
1016  TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1017  virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
1018  };
1019 
1020  class TVectorLoopConfig : public TLoopConfiguration {
1021  // Base class of the Configurations used in member wise streaming.
1022  protected:
1023  public:
1024  Long_t fIncrement; // Either a value to increase the cursor by and
1025  public:
1026  TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1027  //virtual void PrintDebug(TBuffer &buffer, void *);
1028  virtual ~TVectorLoopConfig() {};
1029  void Print() const
1030  {
1031  printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1032  }
1033 
1034  void* GetFirstAddress(void *start, const void * /* end */) const
1035  {
1036  // Return the address of the first element of the collection.
1037 
1038  return start;
1039  }
1040 
1041  virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
1042  };
1043 
1044  class TAssocLoopConfig : public TLoopConfiguration {
1045  // Base class of the Configurations used in member wise streaming.
1046  public:
1047  TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : TLoopConfiguration(proxy) {};
1048  //virtual void PrintDebug(TBuffer &buffer, void *);
1049  virtual ~TAssocLoopConfig() {};
1050  void Print() const
1051  {
1052  printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1053  }
1054  virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
1055 
1056  void* GetFirstAddress(void *start, const void * /* end */) const
1057  {
1058  // Return the address of the first element of the collection.
1059 
1060  R__ASSERT(0);
1061 // char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1062 // void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1063 // arr0 = genloopconfig->fNext(iter,end_collection);
1064 // if (iter != &iterator[0]) {
1065 // genloopconfig->fDeleteIterator(iter);
1066 // }
1067  return start;
1068  }
1069  };
1070 
1071  class TGenericLoopConfig : public TLoopConfiguration {
1072  // Configuration object for the generic case of member wise streaming looping.
1073  private:
1074  void Init(Bool_t read) {
1075  if (fProxy) {
1076  if (fProxy->HasPointers()) {
1080  } else {
1081  fNext = fProxy->GetFunctionNext(read);
1082  fCopyIterator = fProxy->GetFunctionCopyIterator(read);
1083  fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
1084  }
1085  }
1086  }
1087  public:
1091 
1092  TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : TLoopConfiguration(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
1093  {
1094  Init(read);
1095  }
1096  virtual ~TGenericLoopConfig() {};
1097  void Print() const
1098  {
1099  printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1100  }
1101  virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
1102 
1103  void* GetFirstAddress(void *start_collection, const void *end_collection) const
1104  {
1105  // Return the address of the first element of the collection.
1106 
1108  void *iter = fCopyIterator(&iterator,start_collection);
1109  void *arr0 = fNext(iter,end_collection);
1110  if (iter != &iterator[0]) {
1111  fDeleteIterator(iter);
1112  }
1113  return arr0;
1114  }
1115  };
1116 
1118  {
1119  // Collection was saved member-wise
1120 
1121  TConfigSTL *config = (TConfigSTL*)conf;
1122  vers &= ~( TBufferFile::kStreamedMemberWise );
1123 
1124  if( vers >= 8 ) {
1125 
1126  TClass *oldClass = config->fOldClass;
1127 
1128  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1129  if (!oldProxy) {
1130  // Missing information, broken file ... give up
1131  return;
1132  }
1133  TClass *valueClass = oldProxy->GetValueClass();
1134  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1135 
1136  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1137  Int_t nobjects;
1138  buf.ReadInt(nobjects);
1139  void* alternative = oldProxy->Allocate(nobjects,true);
1140  if (nobjects) {
1141  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1142 
1145  void *begin = &(startbuf[0]);
1146  void *end = &(endbuf[0]);
1147  config->fCreateIterators(alternative, &begin, &end, oldProxy);
1148  // We can not get here with a split vector of pointer, so we can indeed assume
1149  // that actions->fConfiguration != null.
1150  buf.ApplySequence(*actions, begin, end);
1151  if (begin != &(startbuf[0])) {
1152  // assert(end != endbuf);
1153  config->fDeleteTwoIterators(begin,end);
1154  }
1155  }
1156  oldProxy->Commit(alternative);
1157 
1158  } else {
1159 
1160  TClass *oldClass = config->fOldClass;
1161 
1162  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1163  if (!oldProxy) {
1164  // Missing information, broken file ... give up
1165  return;
1166  }
1167 
1168  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1169  Int_t nobjects;
1170  buf.ReadInt(nobjects);
1171  void* env = oldProxy->Allocate(nobjects,true);
1172 
1173  if (nobjects || vers < 7 ) {
1174  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1175  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1176 
1177  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1178  }
1179  oldProxy->Commit(env);
1180  }
1181  }
1182 
1184  {
1185  // Collection was saved member-wise
1186 
1187  TConfigSTL *config = (TConfigSTL*)conf;
1188  vers &= ~( TBufferFile::kStreamedMemberWise );
1189 
1190  if( vers >= 8 ) {
1191 
1192  TClass *oldClass = config->fOldClass;
1193 
1194  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1195  if (!oldProxy) {
1196  // Missing information, broken file ... give up
1197  return;
1198  }
1199  TClass *valueClass = oldProxy->GetValueClass();
1200  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1201 
1202  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1203 
1204  int objectSize = oldClass->Size();
1205  char *obj = (char*)addr;
1206  char *endobj = obj + conf->fLength*objectSize;
1207 
1208  for(; obj<endobj; obj+=objectSize) {
1209  Int_t nobjects;
1210  buf.ReadInt(nobjects);
1211  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1212  void* alternative = oldProxy->Allocate(nobjects,true);
1213  if (nobjects) {
1216  void *begin = &(startbuf[0]);
1217  void *end = &(endbuf[0]);
1218  config->fCreateIterators(alternative, &begin, &end, oldProxy);
1219  // We can not get here with a split vector of pointer, so we can indeed assume
1220  // that actions->fConfiguration != null.
1221  buf.ApplySequence(*actions, begin, end);
1222  if (begin != &(startbuf[0])) {
1223  // assert(end != endbuf);
1224  config->fDeleteTwoIterators(begin,end);
1225  }
1226  }
1227  oldProxy->Commit(alternative);
1228  }
1229 
1230  } else {
1231 
1232  TClass *oldClass = config->fOldClass;
1233 
1234  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1235  if (!oldProxy) {
1236  // Missing information, broken file ... give up
1237  return;
1238  }
1239 
1240  int objectSize = oldClass->Size();
1241  char *obj = (char*)addr;
1242  char *endobj = obj + conf->fLength*objectSize;
1243 
1244  for(; obj<endobj; obj+=objectSize) {
1245  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1246  Int_t nobjects;
1247  buf.ReadInt(nobjects);
1248  void* env = oldProxy->Allocate(nobjects,true);
1249 
1250  if (nobjects || vers < 7 ) {
1251  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1252  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1253 
1254  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1255  }
1256  oldProxy->Commit(env);
1257  }
1258  }
1259  }
1260 
1262  {
1263  // Collection was saved member-wise
1264 
1265  TConfigSTL *config = (TConfigSTL*)conf;
1266 
1267  vers &= ~( TBufferFile::kStreamedMemberWise );
1268 
1269  TClass *newClass = config->fNewClass;
1270  TClass *oldClass = config->fOldClass;
1271 
1272  if( vers < 8 ) {
1273  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1274  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1275  } else {
1276 
1277  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1278 
1279  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1280  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1281 
1282  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1283  Int_t nobjects;
1284  buf.ReadInt(nobjects);
1285  void* alternative = newProxy->Allocate(nobjects,true);
1286  if (nobjects) {
1287  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1290  void *begin = &(startbuf[0]);
1291  void *end = &(endbuf[0]);
1292  config->fCreateIterators( alternative, &begin, &end, newProxy);
1293  // We can not get here with a split vector of pointer, so we can indeed assume
1294  // that actions->fConfiguration != null.
1295  buf.ApplySequence(*actions, begin, end);
1296  if (begin != &(startbuf[0])) {
1297  // assert(end != endbuf);
1298  config->fDeleteTwoIterators(begin,end);
1299  }
1300  }
1301  newProxy->Commit(alternative);
1302  }
1303  }
1304 
1306  {
1307  // Collection was saved member-wise
1308 
1309  TConfigSTL *config = (TConfigSTL*)conf;
1310 
1311  vers &= ~( TBufferFile::kStreamedMemberWise );
1312 
1313  TClass *newClass = config->fNewClass;
1314  TClass *oldClass = config->fOldClass;
1315 
1316  if( vers < 8 ) {
1317  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1318  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1319  } else {
1320 
1321  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1322 
1323  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1324  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1325 
1326  int objectSize = newClass->Size();
1327  char *obj = (char*)addr;
1328  char *endobj = obj + conf->fLength*objectSize;
1329 
1330  for(; obj<endobj; obj+=objectSize) {
1331  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1332  Int_t nobjects;
1333  buf.ReadInt(nobjects);
1334  void* alternative = newProxy->Allocate(nobjects,true);
1335  if (nobjects) {
1336  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1339  void *begin = &(startbuf[0]);
1340  void *end = &(endbuf[0]);
1341  config->fCreateIterators( alternative, &begin, &end, newProxy);
1342  // We can not get here with a split vector of pointer, so we can indeed assume
1343  // that actions->fConfiguration != null.
1344  buf.ApplySequence(*actions, begin, end);
1345  if (begin != &(startbuf[0])) {
1346  // assert(end != endbuf);
1347  config->fDeleteTwoIterators(begin,end);
1348  }
1349  }
1350  newProxy->Commit(alternative);
1351  }
1352  }
1353  }
1354 
1355 
1356  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1357  {
1358  TConfigSTL *config = (TConfigSTL*)conf;
1359  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1360  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1361  }
1362  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1363  {
1364  TConfigSTL *config = (TConfigSTL*)conf;
1365  (*config->fStreamer)(buf,addr,conf->fLength);
1366  }
1368  {
1369  // case of old TStreamerInfo
1370 
1371  TConfigSTL *config = (TConfigSTL*)conf;
1372  // Backward compatibility. Some TStreamerElement's where without
1373  // Streamer but were not removed from element list
1374  if (config->fIsSTLBase || vers == 0) {
1375  buf.SetBufferOffset(start); //there is no byte count
1376  }
1377  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1378  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1379  }
1381  {
1382  // case of old TStreamerInfo
1383 
1384  TConfigSTL *config = (TConfigSTL*)conf;
1385  // Backward compatibility. Some TStreamerElement's where without
1386  // Streamer but were not removed from element list
1387  if (config->fIsSTLBase || vers == 0) {
1388  buf.SetBufferOffset(start); //there is no byte count
1389  }
1390  (*config->fStreamer)(buf,addr,conf->fLength);
1391  }
1392 
1393  template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1394  void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1396  {
1397  TConfigSTL *config = (TConfigSTL*)conf;
1398  UInt_t start, count;
1399  Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1400  if ( vers & TBufferFile::kStreamedMemberWise ) {
1401  memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1402  } else {
1403  objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1404  }
1405  buf.CheckByteCount(start,count,config->fTypeName);
1406  return 0;
1407  }
1408 
1409  template <typename From, typename To>
1410  struct ConvertBasicType {
1411  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1412  {
1413  // Simple conversion from a 'From' on disk to a 'To' in memory.
1414  From temp;
1415  buf >> temp;
1416  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1417  return 0;
1418  }
1419  };
1420 
1421  template <typename To>
1422  struct ConvertBasicType<BitsMarker,To> {
1423  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1424  {
1425  // Simple conversion from a 'From' on disk to a 'To' in memory
1426  UInt_t temp;
1427  buf >> temp;
1428 
1429  if ((temp & kIsReferenced) != 0) {
1430  HandleReferencedTObject(buf,addr,config);
1431  }
1432 
1433  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1434  return 0;
1435  }
1436  };
1437 
1438  template <typename From, typename To>
1439  struct ConvertBasicType<WithFactorMarker<From>,To> {
1440  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1441  {
1442  // Simple conversion from a 'From' on disk to a 'To' in memory.
1443  TConfWithFactor *conf = (TConfWithFactor *)config;
1444  From temp;
1445  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1446  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1447  return 0;
1448  }
1449  };
1450 
1451  template <typename From, typename To>
1452  struct ConvertBasicType<NoFactorMarker<From>,To> {
1453  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1454  {
1455  // Simple conversion from a 'From' on disk to a 'To' in memory.
1456  TConfNoFactor *conf = (TConfNoFactor *)config;
1457  From temp;
1458  buf.ReadWithNbits(&temp, conf->fNbits);
1459  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1460  return 0;
1461  }
1462  };
1463 
1464  class TConfigurationPushDataCache : public TConfiguration {
1465  // Configuration object for the PushDataCache case.
1466  public:
1467  TVirtualArray *fOnfileObject;
1468 
1469  TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset) :
1470  TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1471  {}
1472 
1473  virtual void Print() const {
1474  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1475  if (fOnfileObject)
1476  printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1477  info->GetClass()->GetName(), fOffset);
1478  else
1479  printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1480  info->GetClass()->GetName(), fOffset);
1481  }
1482  virtual void PrintDebug(TBuffer &buffer, void *object) const {
1483  if (gDebug > 1) {
1484  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1485  printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1486  info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1487 
1488  }
1489  }
1490  };
1491 
1492  Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
1493  {
1494  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1495  auto onfileObject = config->fOnfileObject;
1496 
1497  // onfileObject->SetSize(1);
1498  b.PushDataCache( onfileObject );
1499 
1500  return 0;
1501  }
1502 
1503  Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1504  {
1505  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1506  auto onfileObject = config->fOnfileObject;
1507 
1508  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1509  UInt_t n = proxy->Size();
1510 
1511  onfileObject->SetSize(n);
1512  b.PushDataCache( onfileObject );
1513 
1514  return 0;
1515  }
1516 
1518  {
1519  b.PopDataCache();
1520  return 0;
1521  }
1522 
1524  {
1525  b.PopDataCache();
1526  return 0;
1527  }
1528 
1529  class TConfigurationUseCache : public TConfiguration {
1530  // Configuration object for the UseCache case.
1531  public:
1532  TConfiguredAction fAction;
1533  Bool_t fNeedRepeat;
1534 
1535  TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1536  TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1537  virtual void PrintDebug(TBuffer &b, void *addr) const
1538  {
1539  if (gDebug > 1) {
1540  // Idea: We should print the name of the action function.
1541  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1542  TStreamerElement *aElement = fCompInfo->fElem;
1543  fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1544  " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1545  info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1546  aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1547  }
1548 
1549  }
1550  virtual ~TConfigurationUseCache() {};
1551  virtual TConfiguration *Copy() {
1552  TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1553  fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1554  return copy;
1555  }
1556  };
1557 
1559  {
1560  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1561 
1562  Int_t bufpos = b.Length();
1563  TVirtualArray *cached = b.PeekDataCache();
1564  if (cached==0) {
1565  TStreamerElement *aElement = conf->fCompInfo->fElem;
1566  TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1567  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1568  char *ptr = (char*)addr;
1569  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1570  } else {
1571  config->fAction(b, (*cached)[0]);
1572  }
1573  // Idea: Factor out this 'if' to a UseCacheRepeat function
1574  if (config->fNeedRepeat) {
1575  b.SetBufferOffset(bufpos);
1576  }
1577  return 0;
1578  }
1579 
1580  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1581  {
1582  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1583  Int_t bufpos = b.Length();
1584 
1585  TVirtualArray *cached = b.PeekDataCache();
1586  if (cached==0) {
1587  TStreamerElement *aElement = config->fCompInfo->fElem;
1588  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1589  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1590  char *ptr = (char*)start;
1591  UInt_t n = (((void**)end)-((void**)start));
1592  info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1593  } else {
1594  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1595  void *cached_start = (*cached)[0];
1596  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1597  config->fAction(b,cached_start,cached_end,&cached_config);
1598  }
1599  // Idea: Factor out this 'if' to a UseCacheRepeat function
1600  if (config->fNeedRepeat) {
1601  b.SetBufferOffset(bufpos);
1602  }
1603  return 0;
1604  }
1605 
1606  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1607  {
1608  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1609 
1610  Int_t bufpos = b.Length();
1611  TVirtualArray *cached = b.PeekDataCache();
1612  if (cached==0) {
1613  TStreamerElement *aElement = config->fCompInfo->fElem;
1614  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1615  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1616  char *ptr = (char*)start;
1617  UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1618  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1619  } else {
1620  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1621  void *cached_start = (*cached)[0];
1622  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1623  config->fAction(b,cached_start,cached_end,&cached_config);
1624  }
1625  // Idea: Factor out this 'if' to a UseCacheRepeat function
1626  if (config->fNeedRepeat) {
1627  b.SetBufferOffset(bufpos);
1628  }
1629  return 0;
1630  }
1631 
1632  INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1633  {
1634  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1635 
1636  Int_t bufpos = b.Length();
1637  TVirtualArray *cached = b.PeekDataCache();
1638  if (cached==0) {
1639  TStreamerElement *aElement = config->fCompInfo->fElem;
1640  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1641 
1642  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1643  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1644  UInt_t n = proxy->Size();
1645  info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1646  } else {
1647  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1648  void *cached_start = (*cached)[0];
1649  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1650  config->fAction(b,cached_start,cached_end,&cached_config);
1651  }
1652  // Idea: Factor out this 'if' to a UseCacheRepeat function
1653  if (config->fNeedRepeat) {
1654  b.SetBufferOffset(bufpos);
1655  }
1656  return 0;
1657  }
1658 
1659  // Support for collections.
1660 
1661  Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1662  {
1663  Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1664  return 0;
1665  }
1666 
1667  Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1668  {
1669  Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1670  return 0;
1671  }
1672 
1674 
1676  {
1679  return kGenericLooper;
1680  else
1681  return kVectorLooper;
1682  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1686  || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1687  return kAssociativeLooper;
1688  } else {
1689  return kGenericLooper;
1690  }
1691  }
1692 
1693  struct VectorLooper {
1694 
1695  template <typename T>
1696  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1697  {
1698  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1699  iter = (char*)iter + config->fOffset;
1700  end = (char*)end + config->fOffset;
1701  for(; iter != end; iter = (char*)iter + incr ) {
1702  T *x = (T*) ((char*) iter);
1703  buf >> *x;
1704  }
1705  return 0;
1706  }
1707 
1708  template <typename From, typename To>
1709  struct ConvertBasicType {
1710  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1711  {
1712  // Simple conversion from a 'From' on disk to a 'To' in memory.
1713  From temp;
1714  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1715  iter = (char*)iter + config->fOffset;
1716  end = (char*)end + config->fOffset;
1717  for(; iter != end; iter = (char*)iter + incr ) {
1718  buf >> temp;
1719  *(To*)( ((char*)iter) ) = (To)temp;
1720  }
1721  return 0;
1722  }
1723  };
1724 
1725  template <typename To>
1726  struct ConvertBasicType<BitsMarker,To> {
1727  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1728  {
1729  // Simple conversion from a 'From' on disk to a 'To' in memory.
1730  UInt_t temp;
1731  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1732  iter = (char*)iter + config->fOffset;
1733  end = (char*)end + config->fOffset;
1734  for(; iter != end; iter = (char*)iter + incr ) {
1735  buf >> temp;
1736 
1737  if ((temp & kIsReferenced) != 0) {
1738  HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1739  }
1740 
1741  *(To*)( ((char*)iter) ) = (To)temp;
1742  }
1743  return 0;
1744  }
1745  };
1746 
1747  template <typename From, typename To>
1748  struct ConvertBasicType<WithFactorMarker<From>,To> {
1749  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1750  {
1751  // Simple conversion from a 'From' on disk to a 'To' in memory.
1752  TConfWithFactor *conf = (TConfWithFactor *)config;
1753  From temp;
1754  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1755  iter = (char*)iter + config->fOffset;
1756  end = (char*)end + config->fOffset;
1757  for(; iter != end; iter = (char*)iter + incr ) {
1758  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1759  *(To*)( ((char*)iter) ) = (To)temp;
1760  }
1761  return 0;
1762  }
1763  };
1764 
1765  template <typename From, typename To>
1766  struct ConvertBasicType<NoFactorMarker<From>,To> {
1767  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1768  {
1769  // Simple conversion from a 'From' on disk to a 'To' in memory.
1770  TConfNoFactor *conf = (TConfNoFactor *)config;
1771  From temp;
1772  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1773  iter = (char*)iter + config->fOffset;
1774  end = (char*)end + config->fOffset;
1775  for(; iter != end; iter = (char*)iter + incr ) {
1776  buf.ReadWithNbits(&temp, conf->fNbits);
1777  *(To*)( ((char*)iter) ) = (To)temp;
1778  }
1779  return 0;
1780  }
1781  };
1782 
1783  template <typename T>
1784  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1785  {
1786  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1787  iter = (char*)iter + config->fOffset;
1788  end = (char*)end + config->fOffset;
1789  for(; iter != end; iter = (char*)iter + incr ) {
1790  T *x = (T*) ((char*) iter);
1791  buf << *x;
1792  }
1793  return 0;
1794  }
1795 
1796  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1797  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1798  {
1799  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1800  //Idea: can we factor out the addition of fOffset
1801  // iter = (char*)iter + config->fOffset;
1802  for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1803  iter_action(buf, iter, config);
1804  }
1805  return 0;
1806  }
1807 
1808  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1809  {
1810  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1811  // punt.
1812 
1813  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1814  UInt_t n = (((char*)end)-((char*)start))/incr;
1815  char **arrptr = new char*[n];
1816  UInt_t i = 0;
1817  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1818  arrptr[i] = (char*)iter;
1819  }
1820  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1821  delete [] arrptr;
1822 
1823  // // Idea: need to cache this result!
1824  // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1825  // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1826  //
1827  // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1828  // *TClass *cle = aElement->GetNewBaseClass();
1829  // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1830  //
1831  // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1832  //
1833  // actions->ReadBuffer(b,start,end);
1834  // delete actions;
1835 
1836  // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1837  // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1838  // {
1839  // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1840  //
1841  // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1842  // }
1843  return 0;
1844  }
1845 
1846  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1847  {
1848  // Well the implementation is non trivial. For now punt.
1849 
1850  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1851  UInt_t n = (((char*)end)-((char*)start))/incr;
1852  char **arrptr = new char*[n];
1853  UInt_t i = 0;
1854  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1855  arrptr[i] = (char*)iter;
1856  }
1857  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1858  delete [] arrptr;
1859  return 0;
1860  }
1861 
1862  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1863  {
1864  // Well the implementation is non trivial. For now punt.
1865 
1866  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1867  UInt_t n = (((char*)end)-((char*)start))/incr;
1868  char **arrptr = new char*[n];
1869  UInt_t i = 0;
1870  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1871  arrptr[i] = (char*)iter;
1872  }
1873  ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1874  delete [] arrptr;
1875  return 0;
1876  }
1877 
1878  template <typename T>
1879  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1880  {
1881  // Collection of numbers. Memberwise or not, it is all the same.
1882 
1883  TConfigSTL *config = (TConfigSTL*)conf;
1884  UInt_t start, count;
1885  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1886 
1887  std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1888  Int_t nvalues;
1889  buf.ReadInt(nvalues);
1890  vec->resize(nvalues);
1891 
1892 #ifdef R__VISUAL_CPLUSPLUS
1893  if (nvalues <= 0) {
1894  buf.CheckByteCount(start,count,config->fTypeName);
1895  return 0;
1896  }
1897 #endif
1898  T *begin = &(*vec->begin());
1899  buf.ReadFastArray(begin, nvalues);
1900 
1901  buf.CheckByteCount(start,count,config->fTypeName);
1902  return 0;
1903  }
1904 
1905  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1906  {
1907  // Collection of numbers. Memberwise or not, it is all the same.
1908 
1909  TConfigSTL *config = (TConfigSTL*)conf;
1910  UInt_t start, count;
1911  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1912 
1913  std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1914  Int_t nvalues;
1915  buf.ReadInt(nvalues);
1916  vec->resize(nvalues);
1917 
1918  bool *items = new bool[nvalues];
1919  buf.ReadFastArray(items, nvalues);
1920  for(Int_t i = 0 ; i < nvalues; ++i) {
1921  (*vec)[i] = items[i];
1922  }
1923  delete [] items;
1924 
1925  // We could avoid the call to ReadFastArray, and we could
1926  // the following, however this breaks TBufferXML ...
1927  // for(Int_t i = 0 ; i < nvalues; ++i) {
1928  // bool tmp; buf >> tmp;
1929  // (*vec)[i] = tmp;
1930  // }
1931 
1932  buf.CheckByteCount(start,count,config->fTypeName);
1933  return 0;
1934  }
1935 
1936  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1937  {
1938  // Collection of numbers. Memberwise or not, it is all the same.
1939 
1940  TConfigSTL *config = (TConfigSTL*)conf;
1941  UInt_t start, count;
1942  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1943 
1944  std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1945  Int_t nvalues;
1946  buf.ReadInt(nvalues);
1947  vec->resize(nvalues);
1948 
1949 #ifdef R__VISUAL_CPLUSPLUS
1950  if (nvalues <= 0) {
1951  buf.CheckByteCount(start,count,config->fTypeName);
1952  return 0;
1953  }
1954 #endif
1955  float *begin = &(*vec->begin());
1956  buf.ReadFastArrayFloat16(begin, nvalues);
1957 
1958  buf.CheckByteCount(start,count,config->fTypeName);
1959  return 0;
1960  }
1961 
1962  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1963  {
1964  // Collection of numbers. Memberwise or not, it is all the same.
1965 
1966  TConfigSTL *config = (TConfigSTL*)conf;
1967  UInt_t start, count;
1968  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1969 
1970  std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1971  Int_t nvalues;
1972  buf.ReadInt(nvalues);
1973  vec->resize(nvalues);
1974 
1975 #ifdef R__VISUAL_CPLUSPLUS
1976  if (nvalues <= 0) {
1977  buf.CheckByteCount(start,count,config->fTypeName);
1978  return 0;
1979  }
1980 #endif
1981  double *begin = &(*vec->begin());
1982  buf.ReadFastArrayDouble32(begin, nvalues);
1983 
1984  buf.CheckByteCount(start,count,config->fTypeName);
1985  return 0;
1986  }
1987 
1988  template <typename From, typename To>
1989  struct ConvertCollectionBasicType {
1990  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1991  {
1992  // Collection of numbers. Memberwise or not, it is all the same.
1993 
1994  TConfigSTL *config = (TConfigSTL*)conf;
1995  UInt_t start, count;
1996  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1997 
1998  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1999  Int_t nvalues;
2000  buf.ReadInt(nvalues);
2001  vec->resize(nvalues);
2002 
2003  From *temp = new From[nvalues];
2004  buf.ReadFastArray(temp, nvalues);
2005  for(Int_t ind = 0; ind < nvalues; ++ind) {
2006  (*vec)[ind] = (To)temp[ind];
2007  }
2008  delete [] temp;
2009 
2010  buf.CheckByteCount(start,count,config->fTypeName);
2011  return 0;
2012  }
2013  };
2014 
2015  template <typename From, typename To>
2016  struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
2017  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2018  {
2019  // Collection of numbers. Memberwise or not, it is all the same.
2020 
2021  TConfigSTL *config = (TConfigSTL*)conf;
2022  UInt_t start, count;
2023  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2024 
2025  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2026  Int_t nvalues;
2027  buf.ReadInt(nvalues);
2028  vec->resize(nvalues);
2029 
2030  From *temp = new From[nvalues];
2031  buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2032  for(Int_t ind = 0; ind < nvalues; ++ind) {
2033  (*vec)[ind] = (To)temp[ind];
2034  }
2035  delete [] temp;
2036 
2037  buf.CheckByteCount(start,count,config->fTypeName);
2038  return 0;
2039  }
2040  };
2041 
2042  template <typename To>
2043  static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2044  {
2045  // Collection of numbers. Memberwise or not, it is all the same.
2046 
2047  TConfigSTL *config = (TConfigSTL*)conf;
2048  UInt_t start, count;
2049  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2050 
2051  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2052  Int_t nvalues;
2053  buf.ReadInt(nvalues);
2054  vec->resize(nvalues);
2055 
2056  Double32_t *temp = new Double32_t[nvalues];
2057  buf.ReadFastArrayDouble32(temp, nvalues);
2058  for(Int_t ind = 0; ind < nvalues; ++ind) {
2059  (*vec)[ind] = (To)temp[ind];
2060  }
2061  delete [] temp;
2062 
2063  buf.CheckByteCount(start,count,config->fTypeName);
2064  return 0;
2065  }
2066 
2067  };
2068 
2069  struct VectorPtrLooper {
2070 
2071  template <typename T>
2072  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2073  {
2074  const Int_t offset = config->fOffset;
2075 
2076  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2077  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2078  buf >> *x;
2079  }
2080  return 0;
2081  }
2082 
2083  template <typename From, typename To>
2084  struct ConvertBasicType {
2085  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2086  {
2087  // Simple conversion from a 'From' on disk to a 'To' in memory.
2088  From temp;
2089  const Int_t offset = config->fOffset;
2090  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2091  buf >> temp;
2092  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2093  *x = (To)temp;
2094  }
2095  return 0;
2096  }
2097  };
2098 
2099  template <typename To>
2100  struct ConvertBasicType<BitsMarker,To> {
2101  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2102  {
2103  // Simple conversion from a 'From' on disk to a 'To' in memory.
2104  UInt_t temp;
2105  const Int_t offset = config->fOffset;
2106  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2107  buf >> temp;
2108 
2109  if ((temp & kIsReferenced) != 0) {
2110  HandleReferencedTObject(buf,*(void**)iter,config);
2111  }
2112 
2113  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2114  *x = (To)temp;
2115  }
2116  return 0;
2117  }
2118  };
2119 
2120  template <typename From, typename To>
2121  struct ConvertBasicType<WithFactorMarker<From>,To> {
2122  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2123  {
2124  // Simple conversion from a 'From' on disk to a 'To' in memory.
2125  TConfWithFactor *conf = (TConfWithFactor *)config;
2126  From temp;
2127  const Int_t offset = config->fOffset;
2128  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2129  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2130  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2131  *x = (To)temp;
2132  }
2133  return 0;
2134  }
2135  };
2136 
2137  template <typename From, typename To>
2138  struct ConvertBasicType<NoFactorMarker<From>,To> {
2139  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2140  {
2141  // Simple conversion from a 'From' on disk to a 'To' in memory.
2142  TConfNoFactor *conf = (TConfNoFactor *)config;
2143  From temp;
2144  const Int_t offset = config->fOffset;
2145  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2146  buf.ReadWithNbits(&temp, conf->fNbits);
2147  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2148  *x = (To)temp;
2149  }
2150  return 0;
2151  }
2152  };
2153 
2154  template <typename T>
2155  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2156  {
2157  const Int_t offset = config->fOffset;
2158 
2159  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2160  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2161  buf << *x;
2162  }
2163  return 0;
2164  }
2165 
2166  template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2167  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2168  {
2169  for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2170  action(buf, *(void**)iter, config);
2171  }
2172  return 0;
2173  }
2174 
2175  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2176  {
2177  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2178  // punt.
2179 
2180  return GenericRead(buf,start,end,config);
2181  }
2182 
2183  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2184  {
2185  Int_t n = ( ((void**)end) - ((void**)iter) );
2186  char **arr = (char**)iter;
2187  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2188  }
2189 
2190  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2191  {
2192  Int_t n = ( ((void**)end) - ((void**)iter) );
2193  char **arr = (char**)iter;
2194  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2195  }
2196 
2197  };
2198 
2199  struct AssociativeLooper {
2200 
2201  template <typename T>
2202  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2203  {
2204  buf.ReadFastArray((T*)addr, nvalues);
2205  }
2206 
2207  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2208  {
2209  buf.ReadFastArrayFloat16((float*)addr, nvalues);
2210  }
2211 
2212  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2213  {
2214  buf.ReadFastArrayDouble32((double*)addr, nvalues);
2215  }
2216 
2217  template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2218  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2219  {
2220  // Collection of numbers. Memberwise or not, it is all the same.
2221 
2222  TConfigSTL *config = (TConfigSTL*)conf;
2223  UInt_t start, count;
2224  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2225 
2226  TClass *newClass = config->fNewClass;
2227  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2228  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2229 
2230  Int_t nvalues;
2231  buf.ReadInt(nvalues);
2232  void* alternative = newProxy->Allocate(nvalues,true);
2233  if (nvalues) {
2236  void *begin = &(startbuf[0]);
2237  void *end = &(endbuf[0]);
2238  config->fCreateIterators(alternative, &begin, &end, newProxy);
2239  // We can not get here with a split vector of pointer, so we can indeed assume
2240  // that actions->fConfiguration != null.
2241 
2242  action(buf,begin,nvalues);
2243 
2244  if (begin != &(startbuf[0])) {
2245  // assert(end != endbuf);
2246  config->fDeleteTwoIterators(begin,end);
2247  }
2248  }
2249  newProxy->Commit(alternative);
2250 
2251  buf.CheckByteCount(start,count,config->fTypeName);
2252  return 0;
2253  }
2254 
2255  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2256  {
2257  return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2258  }
2259 
2260  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2261  {
2262  return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2263  }
2264 
2265  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2266  {
2267  return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2268  }
2269 
2270  template <typename T>
2271  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2272  {
2273  return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2274  }
2275 
2276  template <typename From, typename To>
2277  struct ConvertRead {
2278  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2279  {
2280  From *temp = new From[nvalues];
2281  buf.ReadFastArray(temp, nvalues);
2282  To *vec = (To*)addr;
2283  for(Int_t ind = 0; ind < nvalues; ++ind) {
2284  vec[ind] = (To)temp[ind];
2285  }
2286  delete [] temp;
2287  }
2288  };
2289 
2290  template <typename From, typename To>
2291  struct ConvertRead<NoFactorMarker<From>,To> {
2292  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2293  {
2294  From *temp = new From[nvalues];
2295  buf.ReadFastArrayWithNbits(temp, nvalues,0);
2296  To *vec = (To*)addr;
2297  for(Int_t ind = 0; ind < nvalues; ++ind) {
2298  vec[ind] = (To)temp[ind];
2299  }
2300  delete [] temp;
2301  }
2302  };
2303 
2304  template <typename From, typename To>
2305  struct ConvertRead<WithFactorMarker<From>,To> {
2306  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2307  {
2308  From *temp = new From[nvalues];
2309  double factor,min; // needs to be initialized.
2310  buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2311  To *vec = (To*)addr;
2312  for(Int_t ind = 0; ind < nvalues; ++ind) {
2313  vec[ind] = (To)temp[ind];
2314  }
2315  delete [] temp;
2316  }
2317  };
2318 
2319  template <typename From, typename To>
2320  struct ConvertCollectionBasicType {
2321  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2322  {
2323  return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2324  }
2325  };
2326 
2327  };
2328 
2329  struct GenericLooper {
2330 
2331  template <typename T>
2332  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2333  {
2334  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2335 
2336  Next_t next = loopconfig->fNext;
2337  const Int_t offset = config->fOffset;
2338 
2340  void *iter = loopconfig->fCopyIterator(iterator,start);
2341  void *addr;
2342  while( (addr = next(iter,end)) ) {
2343  T *x = (T*)( ((char*)addr) + offset );
2344  buf >> *x;
2345  }
2346  if (iter != &iterator[0]) {
2347  loopconfig->fDeleteIterator(iter);
2348  }
2349  return 0;
2350  }
2351 
2352  template <typename T>
2353  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2354  {
2355  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2356 
2357  Next_t next = loopconfig->fNext;
2358  const Int_t offset = config->fOffset;
2359 
2361  void *iter = loopconfig->fCopyIterator(iterator,start);
2362  void *addr;
2363  while( (addr = next(iter,end)) ) {
2364  T *x = (T*)( ((char*)addr) + offset );
2365  buf << *x;
2366  }
2367  if (iter != &iterator[0]) {
2368  loopconfig->fDeleteIterator(iter);
2369  }
2370  return 0;
2371  }
2372 
2373  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2374  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2375  {
2376  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2377 
2378  // const Int_t offset = config->fOffset;
2379  Next_t next = loopconfig->fNext;
2380 
2382  void *iter = loopconfig->fCopyIterator(&iterator,start);
2383  void *addr;
2384  while( (addr = next(iter,end)) ) {
2385  iter_action(buf, addr, config);
2386  }
2387  if (iter != &iterator[0]) {
2388  loopconfig->fDeleteIterator(iter);
2389  }
2390  return 0;
2391  }
2392 
2393  template <typename From, typename To>
2394  struct Generic {
2395  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2396  {
2397  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2398 
2399  const Int_t offset = config->fOffset;
2400  Next_t next = loopconfig->fNext;
2401 
2403  void *iter = loopconfig->fCopyIterator(&iterator,start);
2404  void *addr;
2405  while( (addr = next(iter,end)) ) {
2406  To *x = (To*)( ((char*)addr) + offset );
2407  *x = (To)(*items);
2408  ++items;
2409  }
2410  if (iter != &iterator[0]) {
2411  loopconfig->fDeleteIterator(iter);
2412  }
2413  }
2414  };
2415 
2416  template <typename From, typename To>
2417  struct Numeric {
2418  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2419  {
2420  // The difference with ConvertAction is that we can modify the start
2421  // iterator and skip the copy. We also never have an offset.
2422 
2423  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2424  Next_t next = loopconfig->fNext;
2425 
2426  void *iter = start;
2427  void *addr;
2428  while( (addr = next(iter,end)) ) {
2429  To *x = (To*)(addr);
2430  *x = (To)(*items);
2431  ++items;
2432  }
2433  }
2434  };
2435 
2436  template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2437  struct ConvertBasicType {
2438  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2439  {
2440  // Simple conversion from a 'From' on disk to a 'To' in memory.
2441 
2442  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2443  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2444  Int_t nvalues = proxy->Size();
2445 
2446  From *items = new From[nvalues];
2447  buf.ReadFastArray(items, nvalues);
2448  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2449  delete [] items;
2450  return 0;
2451  }
2452  };
2453 
2454  template <typename To>
2455  struct ConvertBasicType<BitsMarker, To, Generic> {
2456  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2457  {
2458  // Simple conversion from a 'From' on disk to a 'To' in memory.
2459 
2460  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2461  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2462  Int_t nvalues = proxy->Size();
2463 
2464  UInt_t *items_storage = new UInt_t[nvalues];
2465  UInt_t *items = items_storage;
2466 
2467  const Int_t offset = config->fOffset;
2468  Next_t next = loopconfig->fNext;
2469 
2471  void *iter = loopconfig->fCopyIterator(&iterator,start);
2472  void *addr;
2473  while( (addr = next(iter,end)) ) {
2474  buf >> (*items);
2475  if (((*items) & kIsReferenced) != 0) {
2476  HandleReferencedTObject(buf, addr, config);
2477  }
2478  To *x = (To*)( ((char*)addr) + offset );
2479  *x = (To)(*items);
2480  ++items;
2481  }
2482  if (iter != &iterator[0]) {
2483  loopconfig->fDeleteIterator(iter);
2484  }
2485 
2486  delete [] items_storage;
2487  return 0;
2488  }
2489  };
2490 
2491  template <typename From, typename To, template <typename F, typename T> class Converter >
2492  struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2493  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2494  {
2495  // Simple conversion from a 'From' on disk to a 'To' in memory.
2496 
2497  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2498  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2499  Int_t nvalues = proxy->Size();
2500 
2501  TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2502 
2503  From *items = new From[nvalues];
2504  buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2505  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2506  delete [] items;
2507  return 0;
2508  }
2509  };
2510 
2511  template <typename From, typename To, template <typename F, typename T> class Converter >
2512  struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2513  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2514  {
2515  // Simple conversion from a 'From' on disk to a 'To' in memory.
2516 
2517  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2518  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2519  Int_t nvalues = proxy->Size();
2520 
2521  TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2522 
2523  From *items = new From[nvalues];
2524  buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2525  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2526  delete [] items;
2527  return 0;
2528  }
2529  };
2530 
2531  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2532  {
2533  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2534  // punt.
2535 
2536  return GenericRead(buf,start,end,loopconfig, config);
2537  }
2538 
2539  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2540  {
2541  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2542  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2543  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2544  }
2545 
2546  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2547  {
2548  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2549  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2550  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2551  }
2552 
2553  template <typename T>
2554  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2555  {
2556  buf >> *(T*)addr;
2557  }
2558 
2559  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2560  {
2561  buf.ReadWithNbits((float*)addr,12);
2562  }
2563 
2564  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2565  {
2566  //we read a float and convert it to double
2567  Float_t afloat;
2568  buf >> afloat;
2569  *(double*)addr = (Double_t)afloat;
2570  }
2571 
2572  template <typename ActionHolder>
2573  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2574  {
2575  // Collection of numbers. Memberwise or not, it is all the same.
2576 
2577  TConfigSTL *config = (TConfigSTL*)conf;
2578  UInt_t start, count;
2579  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2580 
2581  TClass *newClass = config->fNewClass;
2582  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2583  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2584 
2585  Int_t nvalues;
2586  buf.ReadInt(nvalues);
2587  void* alternative = newProxy->Allocate(nvalues,true);
2588  if (nvalues) {
2591  void *begin = &(startbuf[0]);
2592  void *end = &(endbuf[0]);
2593  config->fCreateIterators(alternative, &begin, &end, newProxy);
2594  // We can not get here with a split vector of pointer, so we can indeed assume
2595  // that actions->fConfiguration != null.
2596 
2597  TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2598  ActionHolder::Action(buf,begin,end,&loopconf,config);
2599 
2600  if (begin != &(startbuf[0])) {
2601  // assert(end != endbuf);
2602  config->fDeleteTwoIterators(begin,end);
2603  }
2604  }
2605  newProxy->Commit(alternative);
2606 
2607  buf.CheckByteCount(start,count,config->fTypeName);
2608  return 0;
2609  }
2610 
2611  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2612  {
2613  return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2614  }
2615 
2616  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2617  {
2618  return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2619  }
2620 
2621  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2622  {
2623  return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2624  // Could also use:
2625  // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2626  }
2627 
2628  template <typename T>
2629  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2630  {
2631  return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2632  }
2633 
2634  template <typename From, typename To>
2635  struct ConvertCollectionBasicType {
2636  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2637  {
2638  // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2639  return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2640  }
2641  };
2642 
2643  };
2644 }
2645 
2646 template <typename Looper, typename From>
2648 {
2649  switch (newtype) {
2650  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2651  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2652  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2653  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2654  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2655  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2656  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2657  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2658  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2659  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2660  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2661  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2662  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2663  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2664  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2665  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2666  default:
2667  return TConfiguredAction( Looper::GenericRead, conf );
2668  break;
2669  }
2670  R__ASSERT(0); // We should never be here
2671  return TConfiguredAction();
2672 }
2673 
2674 template <class Looper>
2676 {
2677  // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2678 
2679  switch (type) {
2680  // Read basic types.
2681  case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2682  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2683  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2684  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2685  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2686  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2687  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2688  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2689  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2690  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2691  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2692  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2693  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2694  case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2695  case TStreamerInfo::kFloat16: {
2696  TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2697  delete conf;
2698  return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2699  // if (element->GetFactor() != 0) {
2700  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2701  // } else {
2702  // Int_t nbits = (Int_t)element->GetXmin();
2703  // if (!nbits) nbits = 12;
2704  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2705  // }
2706  break;
2707  }
2708  case TStreamerInfo::kDouble32: {
2709  TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2710  delete conf;
2711  return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2712  // if (element->GetFactor() != 0) {
2713  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2714  // } else {
2715  // Int_t nbits = (Int_t)element->GetXmin();
2716  // if (!nbits) {
2717  // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2718  // } else {
2719  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2720  // }
2721  // }
2722  break;
2723  }
2724  }
2725  Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2726  R__ASSERT(0); // We should never be here
2727  return TConfiguredAction();
2728 }
2729 
2730 template <typename Looper, typename From>
2732 {
2733  switch (newtype) {
2734  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2735  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2736  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2737  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2738  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2739  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2740  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2741  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2742  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2743  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2744  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2745  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2746  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2747  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2748  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2749  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2750  default:
2751  break;
2752  }
2753  R__ASSERT(0); // We should never be here
2754  return TConfiguredAction();
2755 }
2756 
2757 template <typename Looper>
2759 {
2760  switch (oldtype) {
2761  case TStreamerInfo::kBool:
2762  return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2763  break;
2764  case TStreamerInfo::kChar:
2765  return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2766  break;
2767  case TStreamerInfo::kShort:
2768  return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2769  break;
2770  case TStreamerInfo::kInt:
2771  return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2772  break;
2773  case TStreamerInfo::kLong:
2774  return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2775  break;
2777  return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2778  break;
2779  case TStreamerInfo::kFloat:
2780  return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2781  break;
2783  return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2784  break;
2785  case TStreamerInfo::kUChar:
2786  return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2787  break;
2789  return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2790  break;
2791  case TStreamerInfo::kUInt:
2792  return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2793  break;
2794  case TStreamerInfo::kULong:
2795  return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2796  break;
2798  return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2799  break;
2801  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2802  break;
2804  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2805  break;
2806  case TStreamerInfo::kBits:
2807  Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2808  break;
2809  default:
2810  break;
2811  }
2812  R__ASSERT(0); // We should never be here
2813  return TConfiguredAction();
2814 }
2815 
2816 template <class Looper>
2818 {
2819  switch (type) {
2820  // Read basic types.
2821  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2822  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2823  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2824  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2825  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2826  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2827  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2828  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2829  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2830  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2831  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2832  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2833  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2834  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2835  case TStreamerInfo::kFloat16: {
2836  if (element->GetFactor() != 0) {
2837  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2838  } else {
2839  Int_t nbits = (Int_t)element->GetXmin();
2840  if (!nbits) nbits = 12;
2841  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2842  }
2843  break;
2844  }
2845  case TStreamerInfo::kDouble32: {
2846  if (element->GetFactor() != 0) {
2847  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2848  } else {
2849  Int_t nbits = (Int_t)element->GetXmin();
2850  if (!nbits) {
2851  return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2852  } else {
2853  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2854  }
2855  }
2856  break;
2857  }
2858  case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2859  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2860  // Streamer alltogether.
2861  case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2862  case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2866  case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2867  case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2868 
2869  // Conversions.
2871  return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2872  break;
2874  return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2875  break;
2877  return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2878  break;
2880  return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2881  break;
2883  return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2884  break;
2886  return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2887  break;
2889  return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2890  break;
2892  return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2893  break;
2895  return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2896  break;
2898  return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2899  break;
2901  return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2902  break;
2904  return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2905  break;
2907  return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2908  break;
2910  return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2911  break;
2913  if (element->GetFactor() != 0) {
2914  return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2915  } else {
2916  Int_t nbits = (Int_t)element->GetXmin();
2917  if (!nbits) nbits = 12;
2918  return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2919  }
2920  break;
2921  }
2923  if (element->GetFactor() != 0) {
2924  return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2925  } else {
2926  Int_t nbits = (Int_t)element->GetXmin();
2927  if (!nbits) {
2928  return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2929  } else {
2930  return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2931  }
2932  }
2933  break;
2934  }
2935  default:
2936  return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2937  break;
2938  }
2939  R__ASSERT(0); // We should never be here
2940  return TConfiguredAction();
2941 }
2942 
2943 template <class Looper>
2945  switch (type) {
2946  // read basic types
2947  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2948  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2949  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2950  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2951  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2952  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2953  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2954  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2955  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2956  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2957  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2958  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2959  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2960  // the simple type missing are kBits and kCounter.
2961  default:
2962  return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2963  }
2964  R__ASSERT(0); // We should never be here
2965  return TConfiguredAction();
2966 }
2967 
2968 
2969 ////////////////////////////////////////////////////////////////////////////////
2970 /// loop on the TStreamerElement list
2971 /// regroup members with same type
2972 /// Store predigested information into local arrays. This saves a huge amount
2973 /// of time compared to an explicit iteration on all elements.
2974 
2976 {
2977  if (IsCompiled()) {
2978  //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
2979  return;
2980  }
2982 
2983  // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
2984 
2985  // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
2986  fOptimized = kFALSE;
2987  fNdata = 0;
2988  fNfulldata = 0;
2989 
2990  TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
2991  if (fNumber < 0) {
2992  ++fgCount;
2993  fNumber = fgCount;
2994  }
2995  if (fNumber >= infos->GetSize()) {
2996  infos->AddAtAndExpand(this, fNumber);
2997  } else {
2998  if (!infos->At(fNumber)) {
2999  infos->AddAt(this, fNumber);
3000  }
3001  }
3002 
3003  assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3004 
3005 
3006  Int_t ndata = fElements->GetEntries();
3007 
3008 
3011 
3014 
3017 
3018  if (fReadText) fReadText->fActions.clear();
3019  else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3020 
3023 
3026 
3029 
3030  if (fWriteText) fWriteText->fActions.clear();
3031  else fWriteText = new TStreamerInfoActions::TActionSequence(this,ndata);
3032 
3033  if (!ndata) {
3034  // This may be the case for empty classes (e.g., TAtt3D).
3035  // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3037  fSize = sizeof(TStreamerInfo*);
3038  }
3039  fComp = new TCompInfo[1];
3040  fCompFull = new TCompInfo*[1];
3041  fCompOpt = new TCompInfo*[1];
3042  fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3043  SetIsCompiled();
3044  return;
3045  }
3046 
3047  // At most half of the elements can be used to hold optimized versions.
3048  // We use the bottom to hold the optimized-into elements and the non-optimized elements
3049  // and the top to hold the original copy of the optimized out elements.
3050  fNslots = ndata + ndata/2 + 1;
3051  Int_t optiOut = 0;
3052 
3053  fComp = new TCompInfo[fNslots];
3054  fCompFull = new TCompInfo*[ndata];
3055  fCompOpt = new TCompInfo*[ndata];
3056 
3057  TStreamerElement* element;
3058  TStreamerElement* previous = 0;
3059  Int_t keep = -1;
3060  Int_t i;
3061 
3062  if (!CanOptimize()) {
3064  }
3065 
3066  Bool_t isOptimized = kFALSE;
3067  Bool_t previousOptimized = kFALSE;
3068 
3069  for (i = 0; i < ndata; ++i) {
3070  element = (TStreamerElement*) fElements->At(i);
3071  if (!element) {
3072  break;
3073  }
3074 
3075  Int_t asize = element->GetSize();
3076  if (element->GetArrayLength()) {
3077  asize /= element->GetArrayLength();
3078  }
3079  fComp[fNdata].fType = element->GetType();
3080  fComp[fNdata].fNewType = element->GetNewType();
3081  fComp[fNdata].fOffset = element->GetOffset();
3082  fComp[fNdata].fLength = element->GetArrayLength();
3083  fComp[fNdata].fElem = element;
3084  fComp[fNdata].fMethod = element->GetMethod();
3085  fComp[fNdata].fClass = element->GetClassPointer();
3086  fComp[fNdata].fNewClass = element->GetNewClass();
3088  fComp[fNdata].fStreamer = element->GetStreamer();
3089 
3090  // try to group consecutive members of the same type
3091  if (!TestBit(kCannotOptimize)
3092  && (keep >= 0)
3093  && (element->GetType() > 0)
3094  && (element->GetType() < 10)
3096  && (fComp[keep].fMethod == 0)
3097  && (element->GetArrayDim() == 0)
3098  && (fComp[keep].fType < kObject)
3099  && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3100  && (element->GetType() == (fComp[keep].fType%kRegrouped))
3101  && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3102  && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3103  ((element->GetFactor() == previous->GetFactor())
3104  && (element->GetXmin() == previous->GetXmin())
3105  && (element->GetXmax() == previous->GetXmax())
3106  )
3107  )
3110  // kWholeObject and kDoNotDelete do not apply to numerical elements.
3111  )
3112  {
3113  if (!previousOptimized) {
3114  // The element was not yet optimized we first need to copy it into
3115  // the set of original copies.
3116  fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3117  fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3118  }
3119  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3120  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3121 
3122  R__ASSERT( keep < (fNslots - optiOut) );
3123 
3124  if (fComp[keep].fLength == 0) {
3125  fComp[keep].fLength++;
3126  }
3127  fComp[keep].fLength++;
3128  fComp[keep].fType = element->GetType() + kRegrouped;
3129  isOptimized = kTRUE;
3130  previousOptimized = kTRUE;
3131  } else if (element->GetType() < 0) {
3132 
3133  // -- Deal with an ignored TObject base class.
3134  // Note: The only allowed negative value here is -1,
3135  // and signifies that Build() has found a TObject
3136  // base class and TClass::IgnoreTObjectStreamer() was
3137  // called. In this case the compiled version of the
3138  // elements omits the TObject base class element,
3139  // which has to be compensated for by TTree::Bronch()
3140  // when it is making branches for a split object.
3141  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3142  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3143  keep = -1;
3144  previousOptimized = kFALSE;
3145 
3146  } else {
3147  if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3148  if (fComp[fNdata].fNewType > 0) {
3149  if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3150  || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3151  || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3152  && (fComp[fNdata].fType == kObjectp || fComp[fNdata].fType == kAnyp
3153  || fComp[fNdata].fType == kObject || fComp[fNdata].fType == kAny
3155  ) {
3157  } else if (fComp[fNdata].fType != kCounter) {
3158  fComp[fNdata].fType += kConv;
3159  }
3160  } else {
3161  if (fComp[fNdata].fType == kCounter) {
3162  Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3163  }
3164  fComp[fNdata].fType += kSkip;
3165  }
3166  }
3167  fCompOpt[fNdata] = &(fComp[fNdata]);
3169 
3170  R__ASSERT( fNdata < (fNslots - optiOut) );
3171 
3172  keep = fNdata;
3173  if (fComp[keep].fLength == 0) {
3174  fComp[keep].fLength = 1;
3175  }
3176  fNdata++;
3177  previousOptimized = kFALSE;
3178  }
3179  // The test 'fMethod[keep] == 0' fails to detect a variable size array
3180  // if the counter happens to have an offset of zero, so let's explicitly
3181  // prevent for here.
3182  if (element->HasCounter()) keep = -1;
3183  ++fNfulldata;
3184  previous = element;
3185  }
3186 
3187  for (i = 0; i < fNdata; ++i) {
3188  if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3189  continue;
3190  }
3193  }
3194  for (i = 0; i < fNfulldata; ++i) {
3195  if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3196  continue;
3197  }
3202 
3205  }
3206  ComputeSize();
3207 
3208  fOptimized = isOptimized;
3209  SetIsCompiled();
3210 
3211  if (gDebug > 0) {
3212  ls();
3213  }
3214 }
3215 
3216 template <typename From>
3218 {
3219  switch (newtype) {
3220  case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
3221  case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
3222  case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
3223  case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
3224  case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
3225  case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
3226  case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3227  case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3228  case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3229  case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3230  case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
3231  case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
3232  case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3233  case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
3234  case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
3235  case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3236  }
3237 }
3238 
3239 ////////////////////////////////////////////////////////////////////////////////
3240 /// Add a read action for the given element.
3241 
3243 {
3244  TStreamerElement *element = compinfo->fElem;
3245 
3246  if (element->TestBit(TStreamerElement::kWrite)) return;
3247 
3248  switch (compinfo->fType) {
3249  // read basic types
3250  case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3251  case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3252  case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3253  case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3254  case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3255  case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3256  case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3257  case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3258  case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3259  case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3260  case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3261  case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3262  case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3263  case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3264  case TStreamerInfo::kFloat16: {
3265  if (element->GetFactor() != 0) {
3266  readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3267  } else {
3268  Int_t nbits = (Int_t)element->GetXmin();
3269  if (!nbits) nbits = 12;
3270  readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3271  }
3272  break;
3273  }
3274  case TStreamerInfo::kDouble32: {
3275  if (element->GetFactor() != 0) {
3276  readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3277  } else {
3278  Int_t nbits = (Int_t)element->GetXmin();
3279  if (!nbits) {
3280  readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3281  } else {
3282  readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3283  }
3284  }
3285  break;
3286  }
3287  case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3288  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3289  // Streamer alltogether.
3290  case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3291  case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3292  case TStreamerInfo::kSTL: {
3293  TClass *newClass = element->GetNewClass();
3294  TClass *oldClass = element->GetClassPointer();
3295  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3296 
3297  if (element->GetArrayLength() <= 1) {
3298  if (fOldVersion<3){ // case of old TStreamerInfo
3299  if (newClass && newClass != oldClass) {
3300  if (element->GetStreamer()) {
3301  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3302  } else {
3303  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3304  }
3305  } else {
3306  if (element->GetStreamer()) {
3307  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3308  } else {
3309  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3310  }
3311  }
3312  } else {
3313  if (newClass && newClass != oldClass) {
3314  if (element->GetStreamer()) {
3315  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3316  } else {
3317  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3318  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3319  } else {
3320  switch (SelectLooper(*newClass->GetCollectionProxy())) {
3321  case kVectorLooper:
3322  readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3323  break;
3324  case kAssociativeLooper:
3325  readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3326  break;
3327  case kVectorPtrLooper:
3328  case kGenericLooper:
3329  default:
3330  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3331  readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3332  break;
3333  }
3334  }
3335  }
3336  } else {
3337  if (element->GetStreamer()) {
3338  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3339  } else {
3340  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3341  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3342  } else {
3343  switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3344  case kVectorLooper:
3345  readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3346  break;
3347  case kAssociativeLooper:
3348  readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3349  break;
3350  case kVectorPtrLooper:
3351  case kGenericLooper:
3352  default:
3353  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3354  readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3355  break;
3356  }
3357  }
3358  }
3359  }
3360  }
3361  } else {
3362  if (fOldVersion<3){ // case of old TStreamerInfo
3363  if (newClass && newClass != oldClass) {
3364  if (element->GetStreamer()) {
3365  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3366  } else {
3367  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3368  }
3369  } else {
3370  if (element->GetStreamer()) {
3371  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3372  } else {
3373  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3374  }
3375  }
3376  } else {
3377  if (newClass && newClass != oldClass) {
3378  if (element->GetStreamer()) {
3379  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3380  } else {
3381  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3382  }
3383  } else {
3384  if (element->GetStreamer()) {
3385  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3386  } else {
3387  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3388  }
3389  }
3390  }
3391  }
3392  break;
3393  }
3394 
3396  AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3397  break;
3399  AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3400  break;
3402  AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3403  break;
3405  AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3406  break;
3408  AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3409  break;
3411  AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3412  break;
3414  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3415  break;
3417  AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3418  break;
3420  AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3421  break;
3423  AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3424  break;
3426  AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3427  break;
3429  AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3430  break;
3432  AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3433  break;
3435  AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3436  break;
3438  if (element->GetFactor() != 0) {
3439  AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3440  } else {
3441  Int_t nbits = (Int_t)element->GetXmin();
3442  if (!nbits) nbits = 12;
3443  AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3444  }
3445  break;
3446  }
3448  if (element->GetFactor() != 0) {
3449  AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3450  } else {
3451  Int_t nbits = (Int_t)element->GetXmin();
3452  if (!nbits) {
3453  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3454  } else {
3455  AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3456  }
3457  }
3458  break;
3459  }
3460  default:
3461  readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3462  break;
3463  }
3464  if (element->TestBit(TStreamerElement::kCache)) {
3465  TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3466  readSequence->fActions.pop_back();
3467  readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3468  }
3469 }
3470 
3471 ////////////////////////////////////////////////////////////////////////////////
3472 /// Add a read text action for the given element.
3473 
3475 {
3476  TStreamerElement *element = compinfo->fElem;
3477 
3478  if (element->TestBit(TStreamerElement::kWrite))
3479  return;
3480 
3481  Bool_t generic = kFALSE, isBase = kFALSE;
3482 
3483  switch (compinfo->fType) {
3485  if (element->IsBase())
3486  isBase = kTRUE;
3487  // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3488  else
3489  readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3490  break;
3491 
3493  if (element->IsBase())
3494  isBase = kTRUE;
3495  // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3496  else
3497  readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3498  break;
3499 
3500  case TStreamerInfo::kObject: // Class derived from TObject
3501  case TStreamerInfo::kAny: // Class NOT derived from TObject
3504  readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3505  break;
3506 
3507  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3508  case TStreamerInfo::kSTLp +
3509  TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3510  readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3511  break;
3512 
3515  readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3516  break;
3517 
3518  case TStreamerInfo::kBase: isBase = kTRUE; break;
3519 
3521  readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3522  break;
3523 
3524  default: generic = kTRUE; break;
3525  }
3526 
3527  if (isBase) {
3528  if (compinfo->fStreamer) {
3529  readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3530  } else {
3531  readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3532  }
3533  } else if (generic)
3534  readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3535 }
3536 
3537 ////////////////////////////////////////////////////////////////////////////////
3538 /// Add a read action for the given element.
3539 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3540 
3542 {
3543  TStreamerElement *element = compinfo->fElem;
3544 
3545  if (element->TestBit(TStreamerElement::kWrite)) return;
3546 
3547  if (element->TestBit(TStreamerElement::kCache)) {
3548  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3549  readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3550  } else {
3551  readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3552  }
3553 }
3554 
3555 ////////////////////////////////////////////////////////////////////////////////
3556 
3558 {
3559  TStreamerElement *element = compinfo->fElem;
3560  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3561  // Skip element cached for reading purposes.
3562  return;
3563  }
3564  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3565  // Skip artificial element used for reading purposes.
3566  return;
3567  }
3568  switch (compinfo->fType) {
3569  // write basic types
3570  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3571  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3572  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3573  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3574  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3575  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3576  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3577  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3578  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3579  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3580  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3581  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3582  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3583  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3584  /*case TStreamerInfo::kFloat16: {
3585  if (element->GetFactor() != 0) {
3586  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3587  } else {
3588  Int_t nbits = (Int_t)element->GetXmin();
3589  if (!nbits) nbits = 12;
3590  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3591  }
3592  break;
3593  } */
3594  /*case TStreamerInfo::kDouble32: {
3595  if (element->GetFactor() != 0) {
3596  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3597  } else {
3598  Int_t nbits = (Int_t)element->GetXmin();
3599  if (!nbits) {
3600  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3601  } else {
3602  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3603  }
3604  }
3605  break;
3606  } */
3607  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3608  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3609  // Streamer alltogether.
3610  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3611  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3612  /*case TStreamerInfo::kSTL: {
3613  TClass *newClass = element->GetNewClass();
3614  TClass *oldClass = element->GetClassPointer();
3615  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3616 
3617  if (element->GetArrayLength() <= 1) {
3618  if (newClass && newClass != oldClass) {
3619  if (element->GetStreamer()) {
3620  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3621  } else {
3622  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3623  }
3624  } else {
3625  if (element->GetStreamer()) {
3626  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3627  } else {
3628  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3629  }
3630  }
3631  } else {
3632  if (newClass && newClass != oldClass) {
3633  if (element->GetStreamer()) {
3634  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3635  } else {
3636  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3637  }
3638  } else {
3639  if (element->GetStreamer()) {
3640  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3641  } else {
3642  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3643  }
3644  }
3645  }
3646  break;
3647  } */
3648  default:
3649  writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3650  break;
3651  }
3652 #if defined(CDJ_NO_COMPILE)
3653  if (element->TestBit(TStreamerElement::kCache)) {
3654  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3655  writeSequence->fActions.pop_back();
3656  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3657  }
3658 #endif
3659 }
3660 
3661 ////////////////////////////////////////////////////////////////////////////////
3662 
3664 {
3665  TStreamerElement *element = compinfo->fElem;
3666  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3667  // Skip element cached for reading purposes.
3668  return;
3669  }
3670  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3671  // Skip artificial element used for reading purposes.
3672  return;
3673  }
3674 
3675  Bool_t generic = kFALSE, isBase = kFALSE;
3676 
3677  switch (compinfo->fType) {
3678  // write basic types
3679  case TStreamerInfo::kBool:
3680  writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3681  break;
3682  case TStreamerInfo::kChar:
3683  writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3684  break;
3685  case TStreamerInfo::kShort:
3686  writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3687  break;
3688  case TStreamerInfo::kInt:
3689  writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3690  break;
3691  case TStreamerInfo::kLong:
3692  writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3693  break;
3695  writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3696  break;
3697  case TStreamerInfo::kFloat:
3698  writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3699  break;
3701  writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3702  break;
3703  case TStreamerInfo::kUChar:
3704  writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3705  break;
3707  writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3708  break;
3709  case TStreamerInfo::kUInt:
3710  writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3711  break;
3712  case TStreamerInfo::kULong:
3713  writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3714  break;
3716  writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3717  break;
3718 
3720  if (element->IsBase())
3721  isBase = kTRUE;
3722  else
3723  writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3724  break;
3725 
3727  if (element->IsBase())
3728  isBase = kTRUE;
3729  else
3730  writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3731  break;
3732 
3733  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3734  case TStreamerInfo::kSTLp +
3735  TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3736  writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3737  break;
3738 
3741  writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3742  break;
3743 
3744  case TStreamerInfo::kBase: isBase = kTRUE; break;
3745 
3747  writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3748  break;
3749 
3750  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3751  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3752  /*case TStreamerInfo::kFloat16: {
3753  if (element->GetFactor() != 0) {
3754  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3755  TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3756  } else {
3757  Int_t nbits = (Int_t)element->GetXmin();
3758  if (!nbits) nbits = 12;
3759  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3760  TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3761  }
3762  break;
3763  } */
3764  /*case TStreamerInfo::kDouble32: {
3765  if (element->GetFactor() != 0) {
3766  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3767  TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3768  } else {
3769  Int_t nbits = (Int_t)element->GetXmin();
3770  if (!nbits) {
3771  writeSequence->AddAction( ConvertBasicType<float,double>, new
3772  TConfiguration(this,i,compinfo,compinfo->fOffset) );
3773  } else {
3774  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3775  TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3776  }
3777  }
3778  break;
3779  } */
3780  // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3781  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3782  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3783  // Streamer alltogether.
3784  // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3785  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3786  // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3787  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3788  /*case TStreamerInfo::kSTL: {
3789  TClass *newClass = element->GetNewClass();
3790  TClass *oldClass = element->GetClassPointer();
3791  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3792 
3793  if (element->GetArrayLength() <= 1) {
3794  if (newClass && newClass != oldClass) {
3795  if (element->GetStreamer()) {
3796  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3797  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3798  } else {
3799  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3800  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3801  }
3802  } else {
3803  if (element->GetStreamer()) {
3804  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3805  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3806  } else {
3807  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3808  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3809  }
3810  }
3811  } else {
3812  if (newClass && newClass != oldClass) {
3813  if (element->GetStreamer()) {
3814  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3815  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3816  } else {
3817  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3818  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3819  }
3820  } else {
3821  if (element->GetStreamer()) {
3822  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3823  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3824  } else {
3825  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3826  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3827  }
3828  }
3829  }
3830  break;
3831  } */
3832  default: generic = kTRUE; break;
3833  }
3834 
3835  if (isBase) {
3836  if (compinfo->fStreamer) {
3837  writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3838  } else {
3839  writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3840  }
3841 
3842  } else
3843 
3844  // use generic write action when special handling is not provided
3845  if (generic)
3846  writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3847 
3848 #if defined(CDJ_NO_COMPILE)
3849  if (element->TestBit(TStreamerElement::kCache)) {
3850  TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3851  writeSequence->fActions.pop_back();
3852  writeSequence->AddAction(UseCache,
3853  new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3854  }
3855 #endif
3856 }
3857 
3858 ////////////////////////////////////////////////////////////////////////////////
3859 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3860 
3862 {
3863  TStreamerElement *element = compinfo->fElem;
3864  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3865  // Skip element cached for reading purposes.
3866  return;
3867  }
3868  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3869  // Skip artificial element used for reading purposes.
3870  return;
3871  }
3872 
3873 #if defined(CDJ_NO_COMPILE)
3874  if (element->TestBit(TStreamerElement::kCache)) {
3875  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3876  writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3877  } else {
3878  writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3879  }
3880 #else
3881  writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3882 #endif
3883 
3884 }
3885 
3886 ////////////////////////////////////////////////////////////////////////////////
3887 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3888 
3890 {
3891  if (info == 0) {
3892  return new TStreamerInfoActions::TActionSequence(0,0);
3893  }
3894 
3895  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3896 
3897  UInt_t ndata = info->GetElements()->GetEntries();
3899  if (IsDefaultVector(proxy))
3900  {
3901  if (proxy.HasPointers()) {
3902  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3903  delete sequence;
3904 
3905  sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3906 
3907  return sequence;
3908  }
3909 
3910  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3911  Long_t increment = proxy.GetIncrement();
3912  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3913  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
3917  {
3918  Long_t increment = proxy.GetIncrement();
3919  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3920  // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3921  } else {
3922  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3923  }
3924  for (UInt_t i = 0; i < ndata; ++i) {
3925  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3926  if (!element) {
3927  break;
3928  }
3929  if (element->GetType() < 0) {
3930  // -- Skip an ignored TObject base class.
3931  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3932  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3933  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3934  // when it is making branches for a split object.
3935  continue;
3936  }
3937  if (element->TestBit(TStreamerElement::kWrite)) {
3938  // Skip element that only for writing.
3939  continue;
3940  }
3941  TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3942  if (baseEl) {
3943  if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3944  // There was a problem with the checksum, the user likely did not
3945  // increment the version number of the derived class when the
3946  // base class changed. Since we will be member wise streaming
3947  // this class, let's warn the user that something is wrong.
3948  ::Warning("CreateReadMemberWiseActions","%s",
3949  baseEl->GetErrorMessage());
3951  }
3952  }
3953 
3954  TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3955 
3956  Int_t asize = element->GetSize();
3957  if (element->GetArrayLength()) {
3958  asize /= element->GetArrayLength();
3959  }
3960  Int_t oldType = element->GetType();
3961  Int_t newType = element->GetNewType();
3962 
3963  Int_t offset = element->GetOffset();
3964  if (newType != oldType) {
3965  if (newType > 0) {
3966  if (oldType != TVirtualStreamerInfo::kCounter) {
3967  oldType += TVirtualStreamerInfo::kConv;
3968  }
3969  } else {
3970  oldType += TVirtualStreamerInfo::kSkip;
3971  }
3972  }
3973  switch (SelectLooper(proxy)) {
3974  case kAssociativeLooper:
3975 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3976 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3977 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3978  case kVectorLooper:
3979  case kVectorPtrLooper:
3980  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3981  if (element->TestBit(TStreamerElement::kCache)) {
3982  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3983  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3984  } else {
3985  sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3986  }
3987  break;
3988  case kGenericLooper:
3989  default:
3990  // The usual collection case.
3991  if (element->TestBit(TStreamerElement::kCache)) {
3992  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3993  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3994  } else {
3995  sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3996  }
3997  break;
3998  }
3999  }
4000  return sequence;
4001 }
4002 
4003 ////////////////////////////////////////////////////////////////////////////////
4004 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
4005 
4007 {
4008  if (info == 0) {
4009  return new TStreamerInfoActions::TActionSequence(0,0);
4010  }
4011 
4012  UInt_t ndata = info->GetElements()->GetEntries();
4013  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
4015 
4016  if (IsDefaultVector(proxy))
4017  {
4018  if (proxy.HasPointers()) {
4019  // Instead of the creating a new one let's copy the one from the StreamerInfo.
4020  delete sequence;
4021 
4022  sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
4023 
4024  return sequence;
4025  }
4026 
4027  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4028  Long_t increment = proxy.GetIncrement();
4029  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
4030  /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4031  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
4032  {
4033  Long_t increment = proxy.GetIncrement();
4034  sequence->fLoopConfig = new TVectorLoopConfig(increment);
4035  // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
4036  } else {
4037  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
4038  }
4039  for (UInt_t i = 0; i < ndata; ++i) {
4040  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
4041  if (!element) {
4042  break;
4043  }
4044  if (element->GetType() < 0) {
4045  // -- Skip an ignored TObject base class.
4046  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
4047  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
4048  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
4049  // when it is making branches for a split object.
4050  continue;
4051  }
4052  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
4053  // Skip element cached for reading purposes.
4054  continue;
4055  }
4057  // Skip artificial element used for reading purposes.
4058  continue;
4059  }
4060  TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
4061  Int_t asize = element->GetSize();
4062  if (element->GetArrayLength()) {
4063  asize /= element->GetArrayLength();
4064  }
4065  Int_t oldType = element->GetType();
4066  Int_t offset = element->GetOffset();
4067 #if defined(CDJ_NO_COMPILE)
4068  Int_t newType = element->GetNewType();
4069 
4070  if (newType != oldType) {
4071  if (newType > 0) {
4072  if (oldType != TVirtualStreamerInfo::kCounter) {
4073  oldType += TVirtualStreamerInfo::kConv;
4074  }
4075  } else {
4076  oldType += TVirtualStreamerInfo::kSkip;
4077  }
4078  }
4079  if ( IsDefaultVector(proxy)
4080  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4081  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
4082  {
4083 
4084  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4085  if (element->TestBit(TStreamerElement::kCache)) {
4086  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4087  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4088  } else {
4089  sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4090  }
4091 
4092  // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4093  // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
4094  // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4095  } else {
4096  // The usual collection case.
4097  if (element->TestBit(TStreamerElement::kCache)) {
4098  TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4099  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4100  } else {
4101  switch (oldType) {
4102  // read basic types
4103  case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4104  case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4105  case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4106  case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4107  case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4108  case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4109  case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4110  case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4111  case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4112  case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4113  case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4114  case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4115  case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4116  // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
4118  if (element->GetFactor() != 0) {
4119  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4120  } else {
4121  Int_t nbits = (Int_t)element->GetXmin();
4122  if (!nbits) nbits = 12;
4123  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4124  }
4125  break;
4126  }
4128  if (element->GetFactor() != 0) {
4129  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4130  } else {
4131  Int_t nbits = (Int_t)element->GetXmin();
4132  if (!nbits) {
4133  sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4134  } else {
4135  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4136  }
4137  }
4138  break;
4139  }
4140  case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
4141  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4142  // Streamer alltogether.
4143  case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
4144  case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
4145  default:
4146  sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4147  break;
4148  }
4149  }
4150  }
4151 #else
4152  if ( IsDefaultVector(proxy)
4153  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4154  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
4155  {
4156  sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4157  } else {
4158  // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
4159  // as it does not create/use a TStaging as expected ... but then again it might
4160  // not be the right things to expect ...
4161  // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4162  sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4163  }
4164 #endif
4165  }
4166  return sequence;
4167 }
4168 
4170 {
4171  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4172  // TBranchElement in the case of split sub-object.
4173 
4174  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4175  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4176  iter != end;
4177  ++iter)
4178  {
4179  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4180  iter->fConfiguration->AddToOffset(delta);
4181  }
4182 }
4183 
4185 {
4186  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4187  // TBranchElement in the case of split sub-object.
4188 
4189  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4190  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4191  iter != end;
4192  ++iter)
4193  {
4194  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4195  iter->fConfiguration->SetMissing();
4196  }
4197 }
4198 
4200 {
4201  // Create a copy of this sequence.
4202 
4203  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,fActions.size());
4204 
4205  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4206 
4207  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4208  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4209  iter != end;
4210  ++iter)
4211  {
4212  TConfiguration *conf = iter->fConfiguration->Copy();
4213  sequence->AddAction( iter->fAction, conf );
4214  }
4215  return sequence;
4216 }
4217 
4219  const TStreamerInfoActions::TIDs &element_ids,
4220  Int_t offset,
4222 {
4223  for(UInt_t id = 0; id < element_ids.size(); ++id) {
4224  if ( element_ids[id].fElemID < 0 ) {
4225  if (element_ids[id].fNestedIDs) {
4226  auto original = create(element_ids[id].fNestedIDs->fInfo,
4227  sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
4228  nullptr);
4229  if (element_ids[id].fNestedIDs->fOnfileObject) {
4230  auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
4231  if ( sequence->fLoopConfig )
4232  sequence->AddAction( PushDataCacheGenericCollection, conf );
4233  else
4234  sequence->AddAction( PushDataCache, conf );
4235  }
4236 
4237  original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
4238 
4239  if (element_ids[id].fNestedIDs->fOnfileObject)
4240  sequence->AddAction( PopDataCache,
4241  new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset) );
4242  } else {
4243  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4244  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4245  iter != end;
4246  ++iter)
4247  {
4248  TConfiguration *conf = iter->fConfiguration->Copy();
4249  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4250  conf->AddToOffset(offset);
4251  sequence->AddAction( iter->fAction, conf );
4252  }
4253  }
4254  } else {
4255  int localIndex = 0;
4256  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4257  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4258  iter != end;
4259  ++iter) {
4260  // fprintf(stderr, "With element_ids[%d] For %s comparing act[%d/%zu] %d to %d for %p vs %p %s\n",
4261  // id,
4262  // iter->fConfiguration->fInfo->GetName(),
4263  // localIndex, fActions.size(),
4264  // iter->fConfiguration->fElemId,
4265  // (UInt_t)element_ids[id].fElemID, iter->fConfiguration->fInfo,
4266  // element_ids[id].fInfo,
4267  // element_ids[id].fInfo ? element_ids[id].fInfo->GetName() : "nullptr" );
4268  ++localIndex;
4269  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
4270  TConfiguration *conf = iter->fConfiguration->Copy();
4271  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4272  conf->AddToOffset(offset);
4273  sequence->AddAction( iter->fAction, conf );
4274  }
4275  }
4276  }
4277  }
4278 }
4279 
4282 {
4283  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4284  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4285 
4286  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
4287 
4288  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4289 
4290  AddToSubSequence(sequence, element_ids, offset, create);
4291 
4292  return sequence;
4293 }
4294 
4296 {
4297  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4298  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4299 
4300  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
4301 
4302  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4303 
4304  for(UInt_t id = 0; id < element_ids.size(); ++id) {
4305  if ( element_ids[id] < 0 ) {
4306  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4307  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4308  iter != end;
4309  ++iter)
4310  {
4311  TConfiguration *conf = iter->fConfiguration->Copy();
4312  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4313  conf->AddToOffset(offset);
4314  sequence->AddAction( iter->fAction, conf );
4315  }
4316  } else {
4317  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4318  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4319  iter != end;
4320  ++iter) {
4321  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
4322  TConfiguration *conf = iter->fConfiguration->Copy();
4323  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4324  conf->AddToOffset(offset);
4325  sequence->AddAction( iter->fAction, conf );
4326  }
4327  }
4328  }
4329  }
4330  return sequence;
4331 }
4332 
4333 #if !defined(R__WIN32) && !defined(_AIX)
4334 
4335 #include <dlfcn.h>
4336 
4337 #endif
4338 
4339 typedef void (*voidfunc)();
4340 static const char *R__GetSymbolName(voidfunc func)
4341 {
4342 #if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
4343  return "not available on this platform";
4344 #if 0
4345  MEMORY_BASIC_INFORMATION mbi;
4346  if (!VirtualQuery (func, &mbi, sizeof (mbi)))
4347  {
4348  return 0;
4349  }
4350 
4351  HMODULE hMod = (HMODULE) mbi.AllocationBase;
4352  static char moduleName[MAX_PATH];
4353 
4354  if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
4355  {
4356  return 0;
4357  }
4358  return moduleName;
4359 #endif
4360 #else
4361  Dl_info info;
4362  if (dladdr((void*)func,&info)==0) {
4363  // Not in a known share library, let's give up
4364  return "name not found";
4365  } else {
4366  //fprintf(stdout,"Found address in %s\n",info.dli_fname);
4367  return info.dli_sname;
4368  }
4369 #endif
4370 }
4371 
4373 {
4374  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4375  // TTBranchElement in the case of split sub-object.
4376  // If opt contains 'func', also print the (mangled) name of the function that will be executed.
4377 
4378  if (fLoopConfig) {
4379  fLoopConfig->Print();
4380  }
4381  TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
4382  for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
4383  iter != end;
4384  ++iter)
4385  {
4386  iter->fConfiguration->Print();
4387  if (strstr(opt,"func")) {
4388  printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
4389  }
4390  }
4391 }
4392 
4393 
TStreamerInfoActions::TActionSequence::AddToSubSequence
void AddToSubSequence(TActionSequence *sequence, const TIDs &element_ids, Int_t offset, SequenceGetter_t create)
Definition: TStreamerInfoActions.cxx:4218
TClass::GetStreamerInfo
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:4504
TProcessID::PutObjectWithID
void PutObjectWithID(TObject *obj, UInt_t uid=0)
stores the object at the uid th slot in the table of objects The object uniqued is set as well as its...
Definition: TProcessID.cxx:383
TStreamerInfoActions::TLoopConfiguration::GetCollectionProxy
virtual TVirtualCollectionProxy * GetCollectionProxy() const
Definition: TStreamerInfoActions.h:65
TVirtualStreamerInfo::GetStreamMemberWise
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible.
Definition: TVirtualStreamerInfo.cxx:155
TStreamerInfoActions::TActionSequence::SequenceGetter_t
SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) SequenceGetter_t
Definition: TStreamerInfoActions.h:176
TStreamerInfoActions::TConfiguration::Print
virtual void Print() const
Definition: TStreamerInfoActions.cxx:96
R__GetSymbolName
static const char * R__GetSymbolName(voidfunc func)
Definition: TStreamerInfoActions.cxx:4340
TVirtualStreamerInfo::kLong64
@ kLong64
Definition: TVirtualStreamerInfo.h:88
TVirtualCollectionProxy::GetReadMemberWiseActions
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
TVirtualCollectionProxy::GetProperties
virtual Int_t GetProperties() const
Definition: TVirtualCollectionProxy.h:86
TStreamerInfo::AddWriteTextAction
void AddWriteTextAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
Definition: TStreamerInfoActions.cxx:3663
TStreamerInfoActions::ReadSTLObjectWiseFastArray
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
Definition: TStreamerInfoActions.cxx:1356
TStreamerInfo::kFloat16
@ kFloat16
Definition: TStreamerInfo.h:172
n
const Int_t n
Definition: legend1.C:16
TStreamerInfo::fNVirtualInfoLoc
Int_t fNVirtualInfoLoc
! Number of virtual info location to update.
Definition: TStreamerInfo.h:107
TStreamerInfoActions::TActionSequence::CreateSubSequence
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
Definition: TStreamerInfoActions.cxx:4295
GetCollectionWriteAction
static TConfiguredAction GetCollectionWriteAction(TVirtualStreamerInfo *info, TStreamerElement *, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
Definition: TStreamerInfoActions.cxx:2944
TStreamerInfo::fReadMemberWise
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
Definition: TStreamerInfo.h:111
TStreamerInfoActions::TConfiguredAction
Definition: TStreamerInfoActions.h:74
TVirtualCollectionProxy::GetCollectionClass
virtual TClass * GetCollectionClass() const
Definition: TVirtualCollectionProxy.h:77
TVirtualStreamerInfo::kUInt
@ kUInt
Definition: TVirtualStreamerInfo.h:87
TStreamerInfoActions::TConfiguration::Copy
virtual TConfiguration * Copy()
Definition: TStreamerInfoActions.h:46
ROOT::Math::IntegOptionsUtil::Print
void Print(std::ostream &os, const OptionType &opt)
Definition: IntegratorOptions.cxx:91
TBuffer::ReadFastArrayDouble32
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0)=0
GetNumericCollectionReadAction
static TConfiguredAction GetNumericCollectionReadAction(Int_t type, TConfigSTL *conf)
Definition: TStreamerInfoActions.cxx:2675
TClass::kIsEmulation
@ kIsEmulation
Definition: TClass.h:100
ROOT::kSTLvector
@ kSTLvector
Definition: ESTLType.h:30
TClass::GetCollectionProxy
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2854
TStreamerInfoActions::ESelectLooper
ESelectLooper
Definition: TStreamerInfoActions.cxx:1673
TVirtualStreamerInfo::SetIsCompiled
void SetIsCompiled()
Definition: TVirtualStreamerInfo.h:57
ROOT::kSTLset
@ kSTLset
Definition: ESTLType.h:35
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TStreamerInfo::TCompInfo::fElem
TStreamerElement * fElem
Not Owned.
Definition: TStreamerInfo.h:56
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
ROOT::kSTLunorderedmultimap
@ kSTLunorderedmultimap
Definition: ESTLType.h:45
ROOT::kSTLbitset
@ kSTLbitset
Definition: ESTLType.h:37
Version_t
short Version_t
Definition: RtypesCore.h:65
TVirtualStreamerInfo::fOptimized
Bool_t fOptimized
Definition: TVirtualStreamerInfo.h:40
TClass::Streamer
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:554
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
TStreamerInfoActions::UseCacheGenericCollection
INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
Definition: TStreamerInfoActions.cxx:1632
TBuffer::ReadFastArrayFloat16
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=0)=0
TStreamerInfo::ReadBufferSkip
Int_t ReadBufferSkip(TBuffer &b, const T &arrptr, const TCompInfo *compinfo, Int_t kase, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Skip an element.
Definition: TStreamerInfoReadBuffer.cxx:182