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  fCreateWriteIterators = proxy->GetFunctionCreateIterators(kFALSE);
967  fCopyIterator = proxy->GetFunctionCopyIterator();
968  fDeleteIterator = proxy->GetFunctionDeleteIterator();
969  fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
970  }
971  }
972 
973  public:
974  TClass *fOldClass; // Class of the content on file
975  TClass *fNewClass; // Class of the content in memory.
976  TMemberStreamer *fStreamer;
977  const char *fTypeName; // Type name of the member as typed by ther user.
978  Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
979 
981  TVirtualCollectionProxy::CreateIterators_t fCreateWriteIterators;
985 
986  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
987  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
988  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
989 
990  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) :
991  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
992  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
993 
994  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) :
995  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
996  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
997 
998  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) :
999  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
1000  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
1001 
1002  virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
1003  };
1004 
1005  class TConfSTLWithFactor : public TConfigSTL {
1006  // Configuration object for the Float16/Double32 where a factor has been specified.
1007  public:
1008  Double_t fFactor;
1009  Double_t fXmin;
1010  TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin) : TConfigSTL(*orig),fFactor(factor),fXmin(xmin) {};
1011  virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
1012  };
1013 
1014  class TConfSTLNoFactor : public TConfigSTL {
1015  // Configuration object for the Float16/Double32 where a factor has been specified.
1016  public:
1017  Int_t fNbits;
1018  TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1019  virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
1020  };
1021 
1022  class TVectorLoopConfig : public TLoopConfiguration {
1023  // Base class of the Configurations used in member wise streaming.
1024  protected:
1025  public:
1026  Long_t fIncrement; // Either a value to increase the cursor by and
1027  public:
1028  TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1029  //virtual void PrintDebug(TBuffer &buffer, void *);
1030  virtual ~TVectorLoopConfig() {};
1031  void Print() const
1032  {
1033  printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1034  }
1035 
1036  void* GetFirstAddress(void *start, const void * /* end */) const
1037  {
1038  // Return the address of the first element of the collection.
1039 
1040  return start;
1041  }
1042 
1043  virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
1044  };
1045 
1046  class TAssocLoopConfig : public TLoopConfiguration {
1047  // Base class of the Configurations used in member wise streaming.
1048  public:
1049  TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : TLoopConfiguration(proxy) {};
1050  //virtual void PrintDebug(TBuffer &buffer, void *);
1051  virtual ~TAssocLoopConfig() {};
1052  void Print() const
1053  {
1054  printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1055  }
1056  virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
1057 
1058  void* GetFirstAddress(void *start, const void * /* end */) const
1059  {
1060  // Return the address of the first element of the collection.
1061 
1062  R__ASSERT(0);
1063 // char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1064 // void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1065 // arr0 = genloopconfig->fNext(iter,end_collection);
1066 // if (iter != &iterator[0]) {
1067 // genloopconfig->fDeleteIterator(iter);
1068 // }
1069  return start;
1070  }
1071  };
1072 
1073  class TGenericLoopConfig : public TLoopConfiguration {
1074  // Configuration object for the generic case of member wise streaming looping.
1075  private:
1076  void Init(Bool_t read) {
1077  if (fProxy) {
1078  if (fProxy->HasPointers()) {
1082  } else {
1083  fNext = fProxy->GetFunctionNext(read);
1084  fCopyIterator = fProxy->GetFunctionCopyIterator(read);
1085  fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
1086  }
1087  }
1088  }
1089  public:
1093 
1094  TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : TLoopConfiguration(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
1095  {
1096  Init(read);
1097  }
1098  virtual ~TGenericLoopConfig() {};
1099  void Print() const
1100  {
1101  printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1102  }
1103  virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
1104 
1105  void* GetFirstAddress(void *start_collection, const void *end_collection) const
1106  {
1107  // Return the address of the first element of the collection.
1108 
1110  void *iter = fCopyIterator(&iterator,start_collection);
1111  void *arr0 = fNext(iter,end_collection);
1112  if (iter != &iterator[0]) {
1113  fDeleteIterator(iter);
1114  }
1115  return arr0;
1116  }
1117  };
1118 
1120  {
1121  // Collection was saved member-wise
1122 
1123  TConfigSTL *config = (TConfigSTL*)conf;
1124  vers &= ~( TBufferFile::kStreamedMemberWise );
1125 
1126  if( vers >= 8 ) {
1127 
1128  TClass *oldClass = config->fOldClass;
1129 
1130  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1131  if (!oldProxy) {
1132  // Missing information, broken file ... give up
1133  return;
1134  }
1135  TClass *valueClass = oldProxy->GetValueClass();
1136  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1137 
1138  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1139  Int_t nobjects;
1140  buf.ReadInt(nobjects);
1141  void* alternative = oldProxy->Allocate(nobjects,true);
1142  if (nobjects) {
1143  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1144 
1147  void *begin = &(startbuf[0]);
1148  void *end = &(endbuf[0]);
1149  config->fCreateIterators(alternative, &begin, &end, oldProxy);
1150  // We can not get here with a split vector of pointer, so we can indeed assume
1151  // that actions->fConfiguration != null.
1152  buf.ApplySequence(*actions, begin, end);
1153  if (begin != &(startbuf[0])) {
1154  // assert(end != endbuf);
1155  config->fDeleteTwoIterators(begin,end);
1156  }
1157  }
1158  oldProxy->Commit(alternative);
1159 
1160  } else {
1161 
1162  TClass *oldClass = config->fOldClass;
1163 
1164  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1165  if (!oldProxy) {
1166  // Missing information, broken file ... give up
1167  return;
1168  }
1169 
1170  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1171  Int_t nobjects;
1172  buf.ReadInt(nobjects);
1173  void* env = oldProxy->Allocate(nobjects,true);
1174 
1175  if (nobjects || vers < 7 ) {
1176  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1177  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1178 
1179  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1180  }
1181  oldProxy->Commit(env);
1182  }
1183  }
1184 
1186  {
1187  // Collection was saved member-wise
1188 
1189  TConfigSTL *config = (TConfigSTL*)conf;
1190  vers &= ~( TBufferFile::kStreamedMemberWise );
1191 
1192  if( vers >= 8 ) {
1193 
1194  TClass *oldClass = config->fOldClass;
1195 
1196  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1197  if (!oldProxy) {
1198  // Missing information, broken file ... give up
1199  return;
1200  }
1201  TClass *valueClass = oldProxy->GetValueClass();
1202  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1203 
1204  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1205 
1206  int objectSize = oldClass->Size();
1207  char *obj = (char*)addr;
1208  char *endobj = obj + conf->fLength*objectSize;
1209 
1210  for(; obj<endobj; obj+=objectSize) {
1211  Int_t nobjects;
1212  buf.ReadInt(nobjects);
1213  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1214  void* alternative = oldProxy->Allocate(nobjects,true);
1215  if (nobjects) {
1218  void *begin = &(startbuf[0]);
1219  void *end = &(endbuf[0]);
1220  config->fCreateIterators(alternative, &begin, &end, oldProxy);
1221  // We can not get here with a split vector of pointer, so we can indeed assume
1222  // that actions->fConfiguration != null.
1223  buf.ApplySequence(*actions, begin, end);
1224  if (begin != &(startbuf[0])) {
1225  // assert(end != endbuf);
1226  config->fDeleteTwoIterators(begin,end);
1227  }
1228  }
1229  oldProxy->Commit(alternative);
1230  }
1231 
1232  } else {
1233 
1234  TClass *oldClass = config->fOldClass;
1235 
1236  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1237  if (!oldProxy) {
1238  // Missing information, broken file ... give up
1239  return;
1240  }
1241 
1242  int objectSize = oldClass->Size();
1243  char *obj = (char*)addr;
1244  char *endobj = obj + conf->fLength*objectSize;
1245 
1246  for(; obj<endobj; obj+=objectSize) {
1247  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1248  Int_t nobjects;
1249  buf.ReadInt(nobjects);
1250  void* env = oldProxy->Allocate(nobjects,true);
1251 
1252  if (nobjects || vers < 7 ) {
1253  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1254  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1255 
1256  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1257  }
1258  oldProxy->Commit(env);
1259  }
1260  }
1261  }
1262 
1264  {
1265  // Collection was saved member-wise
1266 
1267  TConfigSTL *config = (TConfigSTL*)conf;
1268 
1269  vers &= ~( TBufferFile::kStreamedMemberWise );
1270 
1271  TClass *newClass = config->fNewClass;
1272  TClass *oldClass = config->fOldClass;
1273 
1274  if( vers < 8 ) {
1275  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1276  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1277  } else {
1278 
1279  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1280 
1281  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1282  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1283 
1284  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1285  Int_t nobjects;
1286  buf.ReadInt(nobjects);
1287  void* alternative = newProxy->Allocate(nobjects,true);
1288  if (nobjects) {
1289  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1292  void *begin = &(startbuf[0]);
1293  void *end = &(endbuf[0]);
1294  config->fCreateIterators( alternative, &begin, &end, newProxy);
1295  // We can not get here with a split vector of pointer, so we can indeed assume
1296  // that actions->fConfiguration != null.
1297  buf.ApplySequence(*actions, begin, end);
1298  if (begin != &(startbuf[0])) {
1299  // assert(end != endbuf);
1300  config->fDeleteTwoIterators(begin,end);
1301  }
1302  }
1303  newProxy->Commit(alternative);
1304  }
1305  }
1306 
1308  {
1309  // Collection was saved member-wise
1310 
1311  TConfigSTL *config = (TConfigSTL*)conf;
1312 
1313  vers &= ~( TBufferFile::kStreamedMemberWise );
1314 
1315  TClass *newClass = config->fNewClass;
1316  TClass *oldClass = config->fOldClass;
1317 
1318  if( vers < 8 ) {
1319  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1320  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1321  } else {
1322 
1323  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1324 
1325  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1326  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1327 
1328  int objectSize = newClass->Size();
1329  char *obj = (char*)addr;
1330  char *endobj = obj + conf->fLength*objectSize;
1331 
1332  for(; obj<endobj; obj+=objectSize) {
1333  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1334  Int_t nobjects;
1335  buf.ReadInt(nobjects);
1336  void* alternative = newProxy->Allocate(nobjects,true);
1337  if (nobjects) {
1338  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1341  void *begin = &(startbuf[0]);
1342  void *end = &(endbuf[0]);
1343  config->fCreateIterators( alternative, &begin, &end, newProxy);
1344  // We can not get here with a split vector of pointer, so we can indeed assume
1345  // that actions->fConfiguration != null.
1346  buf.ApplySequence(*actions, begin, end);
1347  if (begin != &(startbuf[0])) {
1348  // assert(end != endbuf);
1349  config->fDeleteTwoIterators(begin,end);
1350  }
1351  }
1352  newProxy->Commit(alternative);
1353  }
1354  }
1355  }
1356 
1357 
1358  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1359  {
1360  TConfigSTL *config = (TConfigSTL*)conf;
1361  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1362  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1363  }
1364  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1365  {
1366  TConfigSTL *config = (TConfigSTL*)conf;
1367  (*config->fStreamer)(buf,addr,conf->fLength);
1368  }
1370  {
1371  // case of old TStreamerInfo
1372 
1373  TConfigSTL *config = (TConfigSTL*)conf;
1374  // Backward compatibility. Some TStreamerElement's where without
1375  // Streamer but were not removed from element list
1376  if (config->fIsSTLBase || vers == 0) {
1377  buf.SetBufferOffset(start); //there is no byte count
1378  }
1379  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1380  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1381  }
1383  {
1384  // case of old TStreamerInfo
1385 
1386  TConfigSTL *config = (TConfigSTL*)conf;
1387  // Backward compatibility. Some TStreamerElement's where without
1388  // Streamer but were not removed from element list
1389  if (config->fIsSTLBase || vers == 0) {
1390  buf.SetBufferOffset(start); //there is no byte count
1391  }
1392  (*config->fStreamer)(buf,addr,conf->fLength);
1393  }
1394 
1395  template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1396  void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1398  {
1399  TConfigSTL *config = (TConfigSTL*)conf;
1400  UInt_t start, count;
1401  Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1402  if ( vers & TBufferFile::kStreamedMemberWise ) {
1403  memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1404  } else {
1405  objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1406  }
1407  buf.CheckByteCount(start,count,config->fTypeName);
1408  return 0;
1409  }
1410 
1411  template <typename From, typename To>
1412  struct ConvertBasicType {
1413  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1414  {
1415  // Simple conversion from a 'From' on disk to a 'To' in memory.
1416  From temp;
1417  buf >> temp;
1418  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1419  return 0;
1420  }
1421  };
1422 
1423  template <typename To>
1424  struct ConvertBasicType<BitsMarker,To> {
1425  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1426  {
1427  // Simple conversion from a 'From' on disk to a 'To' in memory
1428  UInt_t temp;
1429  buf >> temp;
1430 
1431  if ((temp & kIsReferenced) != 0) {
1432  HandleReferencedTObject(buf,addr,config);
1433  }
1434 
1435  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1436  return 0;
1437  }
1438  };
1439 
1440  template <typename From, typename To>
1441  struct ConvertBasicType<WithFactorMarker<From>,To> {
1442  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1443  {
1444  // Simple conversion from a 'From' on disk to a 'To' in memory.
1445  TConfWithFactor *conf = (TConfWithFactor *)config;
1446  From temp;
1447  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1448  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1449  return 0;
1450  }
1451  };
1452 
1453  template <typename From, typename To>
1454  struct ConvertBasicType<NoFactorMarker<From>,To> {
1455  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1456  {
1457  // Simple conversion from a 'From' on disk to a 'To' in memory.
1458  TConfNoFactor *conf = (TConfNoFactor *)config;
1459  From temp;
1460  buf.ReadWithNbits(&temp, conf->fNbits);
1461  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1462  return 0;
1463  }
1464  };
1465 
1466  class TConfigurationPushDataCache : public TConfiguration {
1467  // Configuration object for the PushDataCache case.
1468  public:
1469  TVirtualArray *fOnfileObject;
1470 
1471  TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset) :
1472  TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1473  {}
1474 
1475  virtual void Print() const {
1476  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1477  if (fOnfileObject)
1478  printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1479  info->GetClass()->GetName(), fOffset);
1480  else
1481  printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1482  info->GetClass()->GetName(), fOffset);
1483  }
1484  virtual void PrintDebug(TBuffer &buffer, void *object) const {
1485  if (gDebug > 1) {
1486  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1487  printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1488  info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1489 
1490  }
1491  }
1492  };
1493 
1494  Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
1495  {
1496  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1497  auto onfileObject = config->fOnfileObject;
1498 
1499  // onfileObject->SetSize(1);
1500  b.PushDataCache( onfileObject );
1501 
1502  return 0;
1503  }
1504 
1505  Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1506  {
1507  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1508  auto onfileObject = config->fOnfileObject;
1509 
1510  // onfileObject->SetSize(n);
1511  b.PushDataCache( onfileObject );
1512 
1513  return 0;
1514  }
1515 
1516  Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1517  {
1518  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1519  auto onfileObject = config->fOnfileObject;
1520 
1521  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1522  UInt_t n = proxy->Size();
1523 
1524  onfileObject->SetSize(n);
1525  b.PushDataCache( onfileObject );
1526 
1527  return 0;
1528  }
1529 
1531  {
1532  b.PopDataCache();
1533  return 0;
1534  }
1535 
1536  Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1537  {
1538  b.PopDataCache();
1539  return 0;
1540  }
1541 
1543  {
1544  b.PopDataCache();
1545  return 0;
1546  }
1547 
1548  class TConfigurationUseCache : public TConfiguration {
1549  // Configuration object for the UseCache case.
1550  public:
1551  TConfiguredAction fAction;
1552  Bool_t fNeedRepeat;
1553 
1554  TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1555  TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1556  virtual void PrintDebug(TBuffer &b, void *addr) const
1557  {
1558  if (gDebug > 1) {
1559  // Idea: We should print the name of the action function.
1560  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1561  TStreamerElement *aElement = fCompInfo->fElem;
1562  fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1563  " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1564  info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1565  aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1566  }
1567 
1568  }
1569  virtual ~TConfigurationUseCache() {};
1570  virtual TConfiguration *Copy() {
1571  TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1572  fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1573  return copy;
1574  }
1575  };
1576 
1578  {
1579  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1580 
1581  Int_t bufpos = b.Length();
1582  TVirtualArray *cached = b.PeekDataCache();
1583  if (cached==0) {
1584  TStreamerElement *aElement = conf->fCompInfo->fElem;
1585  TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1586  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1587  char *ptr = (char*)addr;
1588  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1589  } else {
1590  config->fAction(b, (*cached)[0]);
1591  }
1592  // Idea: Factor out this 'if' to a UseCacheRepeat function
1593  if (config->fNeedRepeat) {
1594  b.SetBufferOffset(bufpos);
1595  }
1596  return 0;
1597  }
1598 
1599  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1600  {
1601  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1602  Int_t bufpos = b.Length();
1603 
1604  TVirtualArray *cached = b.PeekDataCache();
1605  if (cached==0) {
1606  TStreamerElement *aElement = config->fCompInfo->fElem;
1607  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1608  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1609  char *ptr = (char*)start;
1610  UInt_t n = (((void**)end)-((void**)start));
1611  info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1612  } else {
1613  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1614  void *cached_start = (*cached)[0];
1615  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1616  config->fAction(b,cached_start,cached_end,&cached_config);
1617  }
1618  // Idea: Factor out this 'if' to a UseCacheRepeat function
1619  if (config->fNeedRepeat) {
1620  b.SetBufferOffset(bufpos);
1621  }
1622  return 0;
1623  }
1624 
1625  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1626  {
1627  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1628 
1629  Int_t bufpos = b.Length();
1630  TVirtualArray *cached = b.PeekDataCache();
1631  if (cached==0) {
1632  TStreamerElement *aElement = config->fCompInfo->fElem;
1633  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1634  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1635  char *ptr = (char*)start;
1636  UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1637  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1638  } else {
1639  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1640  void *cached_start = (*cached)[0];
1641  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1642  config->fAction(b,cached_start,cached_end,&cached_config);
1643  }
1644  // Idea: Factor out this 'if' to a UseCacheRepeat function
1645  if (config->fNeedRepeat) {
1646  b.SetBufferOffset(bufpos);
1647  }
1648  return 0;
1649  }
1650 
1651  INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1652  {
1653  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1654 
1655  Int_t bufpos = b.Length();
1656  TVirtualArray *cached = b.PeekDataCache();
1657  if (cached==0) {
1658  TStreamerElement *aElement = config->fCompInfo->fElem;
1659  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1660 
1661  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1662  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1663  UInt_t n = proxy->Size();
1664  info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1665  } else {
1666  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1667  void *cached_start = (*cached)[0];
1668  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1669  config->fAction(b,cached_start,cached_end,&cached_config);
1670  }
1671  // Idea: Factor out this 'if' to a UseCacheRepeat function
1672  if (config->fNeedRepeat) {
1673  b.SetBufferOffset(bufpos);
1674  }
1675  return 0;
1676  }
1677 
1678  // Support for collections.
1679 
1680  Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1681  {
1682  Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1683  return 0;
1684  }
1685 
1686  Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1687  {
1688  Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1689  return 0;
1690  }
1691 
1693 
1695  {
1698  return kGenericLooper;
1699  else
1700  return kVectorLooper;
1701  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1705  || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1706  return kAssociativeLooper;
1707  } else if (proxy.GetCollectionType() == ROOT::kROOTRVec && proxy.GetType() == EDataType::kBool_t) {
1708  return kVectorLooper;
1709  } else {
1710  return kGenericLooper;
1711  }
1712  }
1713 
1714  struct VectorLooper {
1715 
1716  template <typename T>
1717  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1718  {
1719  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1720  iter = (char*)iter + config->fOffset;
1721  end = (char*)end + config->fOffset;
1722  for(; iter != end; iter = (char*)iter + incr ) {
1723  T *x = (T*) ((char*) iter);
1724  buf >> *x;
1725  }
1726  return 0;
1727  }
1728 
1729  template <typename From, typename To>
1730  struct ConvertBasicType {
1731  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1732  {
1733  // Simple conversion from a 'From' on disk to a 'To' in memory.
1734  From temp;
1735  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1736  iter = (char*)iter + config->fOffset;
1737  end = (char*)end + config->fOffset;
1738  for(; iter != end; iter = (char*)iter + incr ) {
1739  buf >> temp;
1740  *(To*)( ((char*)iter) ) = (To)temp;
1741  }
1742  return 0;
1743  }
1744  };
1745 
1746  template <typename To>
1747  struct ConvertBasicType<BitsMarker,To> {
1748  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1749  {
1750  // Simple conversion from a 'From' on disk to a 'To' in memory.
1751  UInt_t temp;
1752  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1753  iter = (char*)iter + config->fOffset;
1754  end = (char*)end + config->fOffset;
1755  for(; iter != end; iter = (char*)iter + incr ) {
1756  buf >> temp;
1757 
1758  if ((temp & kIsReferenced) != 0) {
1759  HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1760  }
1761 
1762  *(To*)( ((char*)iter) ) = (To)temp;
1763  }
1764  return 0;
1765  }
1766  };
1767 
1768  template <typename From, typename To>
1769  struct ConvertBasicType<WithFactorMarker<From>,To> {
1770  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1771  {
1772  // Simple conversion from a 'From' on disk to a 'To' in memory.
1773  TConfWithFactor *conf = (TConfWithFactor *)config;
1774  From temp;
1775  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1776  iter = (char*)iter + config->fOffset;
1777  end = (char*)end + config->fOffset;
1778  for(; iter != end; iter = (char*)iter + incr ) {
1779  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1780  *(To*)( ((char*)iter) ) = (To)temp;
1781  }
1782  return 0;
1783  }
1784  };
1785 
1786  template <typename From, typename To>
1787  struct ConvertBasicType<NoFactorMarker<From>,To> {
1788  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1789  {
1790  // Simple conversion from a 'From' on disk to a 'To' in memory.
1791  TConfNoFactor *conf = (TConfNoFactor *)config;
1792  From temp;
1793  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1794  iter = (char*)iter + config->fOffset;
1795  end = (char*)end + config->fOffset;
1796  for(; iter != end; iter = (char*)iter + incr ) {
1797  buf.ReadWithNbits(&temp, conf->fNbits);
1798  *(To*)( ((char*)iter) ) = (To)temp;
1799  }
1800  return 0;
1801  }
1802  };
1803 
1804  template <typename T>
1805  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1806  {
1807  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1808  iter = (char*)iter + config->fOffset;
1809  end = (char*)end + config->fOffset;
1810  for(; iter != end; iter = (char*)iter + incr ) {
1811  T *x = (T*) ((char*) iter);
1812  buf << *x;
1813  }
1814  return 0;
1815  }
1816 
1817  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1818  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1819  {
1820  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1821  //Idea: can we factor out the addition of fOffset
1822  // iter = (char*)iter + config->fOffset;
1823  for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1824  iter_action(buf, iter, config);
1825  }
1826  return 0;
1827  }
1828 
1829  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1830  {
1831  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1832  // punt.
1833 
1834  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1835  UInt_t n = (((char*)end)-((char*)start))/incr;
1836  char **arrptr = new char*[n];
1837  UInt_t i = 0;
1838  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1839  arrptr[i] = (char*)iter;
1840  }
1841  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1842  delete [] arrptr;
1843 
1844  // // Idea: need to cache this result!
1845  // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1846  // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1847  //
1848  // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1849  // *TClass *cle = aElement->GetNewBaseClass();
1850  // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1851  //
1852  // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1853  //
1854  // actions->ReadBuffer(b,start,end);
1855  // delete actions;
1856 
1857  // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1858  // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1859  // {
1860  // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1861  //
1862  // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1863  // }
1864  return 0;
1865  }
1866 
1867  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1868  {
1869  // Well the implementation is non trivial. For now punt.
1870 
1871  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1872  UInt_t n = (((char*)end)-((char*)start))/incr;
1873  char **arrptr = new char*[n];
1874  UInt_t i = 0;
1875  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1876  arrptr[i] = (char*)iter;
1877  }
1878  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1879  delete [] arrptr;
1880  return 0;
1881  }
1882 
1883  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1884  {
1885  // Well the implementation is non trivial. For now punt.
1886 
1887  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1888  UInt_t n = (((char*)end)-((char*)start))/incr;
1889  char **arrptr = new char*[n];
1890  UInt_t i = 0;
1891  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1892  arrptr[i] = (char*)iter;
1893  }
1894  ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1895  delete [] arrptr;
1896  return 0;
1897  }
1898 
1899  template <typename T>
1900  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1901  {
1902  // Collection of numbers. Memberwise or not, it is all the same.
1903 
1904  TConfigSTL *config = (TConfigSTL*)conf;
1905  UInt_t start, count;
1906  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1907 
1908  std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1909  Int_t nvalues;
1910  buf.ReadInt(nvalues);
1911  vec->resize(nvalues);
1912 
1913 #ifdef R__VISUAL_CPLUSPLUS
1914  if (nvalues <= 0) {
1915  buf.CheckByteCount(start,count,config->fTypeName);
1916  return 0;
1917  }
1918 #endif
1919  T *begin = &(*vec->begin());
1920  buf.ReadFastArray(begin, nvalues);
1921 
1922  buf.CheckByteCount(start,count,config->fTypeName);
1923  return 0;
1924  }
1925 
1926  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1927  {
1928  // Collection of numbers. Memberwise or not, it is all the same.
1929 
1930  TConfigSTL *config = (TConfigSTL*)conf;
1931  UInt_t start, count;
1932  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1933 
1934  std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1935  Int_t nvalues;
1936  buf.ReadInt(nvalues);
1937  vec->resize(nvalues);
1938 
1939  bool *items = new bool[nvalues];
1940  buf.ReadFastArray(items, nvalues);
1941  for(Int_t i = 0 ; i < nvalues; ++i) {
1942  (*vec)[i] = items[i];
1943  }
1944  delete [] items;
1945 
1946  // We could avoid the call to ReadFastArray, and we could
1947  // the following, however this breaks TBufferXML ...
1948  // for(Int_t i = 0 ; i < nvalues; ++i) {
1949  // bool tmp; buf >> tmp;
1950  // (*vec)[i] = tmp;
1951  // }
1952 
1953  buf.CheckByteCount(start,count,config->fTypeName);
1954  return 0;
1955  }
1956 
1957  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1958  {
1959  // Collection of numbers. Memberwise or not, it is all the same.
1960 
1961  TConfigSTL *config = (TConfigSTL*)conf;
1962  UInt_t start, count;
1963  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1964 
1965  std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1966  Int_t nvalues;
1967  buf.ReadInt(nvalues);
1968  vec->resize(nvalues);
1969 
1970 #ifdef R__VISUAL_CPLUSPLUS
1971  if (nvalues <= 0) {
1972  buf.CheckByteCount(start,count,config->fTypeName);
1973  return 0;
1974  }
1975 #endif
1976  float *begin = &(*vec->begin());
1977  buf.ReadFastArrayFloat16(begin, nvalues);
1978 
1979  buf.CheckByteCount(start,count,config->fTypeName);
1980  return 0;
1981  }
1982 
1983  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1984  {
1985  // Collection of numbers. Memberwise or not, it is all the same.
1986 
1987  TConfigSTL *config = (TConfigSTL*)conf;
1988  UInt_t start, count;
1989  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1990 
1991  std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1992  Int_t nvalues;
1993  buf.ReadInt(nvalues);
1994  vec->resize(nvalues);
1995 
1996 #ifdef R__VISUAL_CPLUSPLUS
1997  if (nvalues <= 0) {
1998  buf.CheckByteCount(start,count,config->fTypeName);
1999  return 0;
2000  }
2001 #endif
2002  double *begin = &(*vec->begin());
2003  buf.ReadFastArrayDouble32(begin, nvalues);
2004 
2005  buf.CheckByteCount(start,count,config->fTypeName);
2006  return 0;
2007  }
2008 
2009  template <typename From, typename To>
2010  struct ConvertCollectionBasicType {
2011  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2012  {
2013  // Collection of numbers. Memberwise or not, it is all the same.
2014 
2015  TConfigSTL *config = (TConfigSTL*)conf;
2016  UInt_t start, count;
2017  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2018 
2019  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2020  Int_t nvalues;
2021  buf.ReadInt(nvalues);
2022  vec->resize(nvalues);
2023 
2024  From *temp = new From[nvalues];
2025  buf.ReadFastArray(temp, nvalues);
2026  for(Int_t ind = 0; ind < nvalues; ++ind) {
2027  (*vec)[ind] = (To)temp[ind];
2028  }
2029  delete [] temp;
2030 
2031  buf.CheckByteCount(start,count,config->fTypeName);
2032  return 0;
2033  }
2034  };
2035 
2036  template <typename From, typename To>
2037  struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
2038  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2039  {
2040  // Collection of numbers. Memberwise or not, it is all the same.
2041 
2042  TConfigSTL *config = (TConfigSTL*)conf;
2043  UInt_t start, count;
2044  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2045 
2046  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2047  Int_t nvalues;
2048  buf.ReadInt(nvalues);
2049  vec->resize(nvalues);
2050 
2051  From *temp = new From[nvalues];
2052  buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2053  for(Int_t ind = 0; ind < nvalues; ++ind) {
2054  (*vec)[ind] = (To)temp[ind];
2055  }
2056  delete [] temp;
2057 
2058  buf.CheckByteCount(start,count,config->fTypeName);
2059  return 0;
2060  }
2061  };
2062 
2063  template <typename To>
2064  static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2065  {
2066  // Collection of numbers. Memberwise or not, it is all the same.
2067 
2068  TConfigSTL *config = (TConfigSTL*)conf;
2069  UInt_t start, count;
2070  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2071 
2072  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2073  Int_t nvalues;
2074  buf.ReadInt(nvalues);
2075  vec->resize(nvalues);
2076 
2077  Double32_t *temp = new Double32_t[nvalues];
2078  buf.ReadFastArrayDouble32(temp, nvalues);
2079  for(Int_t ind = 0; ind < nvalues; ++ind) {
2080  (*vec)[ind] = (To)temp[ind];
2081  }
2082  delete [] temp;
2083 
2084  buf.CheckByteCount(start,count,config->fTypeName);
2085  return 0;
2086  }
2087 
2088  };
2089 
2090  struct VectorPtrLooper {
2091 
2092  template <typename T>
2093  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2094  {
2095  const Int_t offset = config->fOffset;
2096 
2097  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2098  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2099  buf >> *x;
2100  }
2101  return 0;
2102  }
2103 
2104  template <typename From, typename To>
2105  struct ConvertBasicType {
2106  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2107  {
2108  // Simple conversion from a 'From' on disk to a 'To' in memory.
2109  From temp;
2110  const Int_t offset = config->fOffset;
2111  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2112  buf >> temp;
2113  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2114  *x = (To)temp;
2115  }
2116  return 0;
2117  }
2118  };
2119 
2120  template <typename To>
2121  struct ConvertBasicType<BitsMarker,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  UInt_t temp;
2126  const Int_t offset = config->fOffset;
2127  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2128  buf >> temp;
2129 
2130  if ((temp & kIsReferenced) != 0) {
2131  HandleReferencedTObject(buf,*(void**)iter,config);
2132  }
2133 
2134  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2135  *x = (To)temp;
2136  }
2137  return 0;
2138  }
2139  };
2140 
2141  template <typename From, typename To>
2142  struct ConvertBasicType<WithFactorMarker<From>,To> {
2143  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2144  {
2145  // Simple conversion from a 'From' on disk to a 'To' in memory.
2146  TConfWithFactor *conf = (TConfWithFactor *)config;
2147  From temp;
2148  const Int_t offset = config->fOffset;
2149  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2150  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2151  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2152  *x = (To)temp;
2153  }
2154  return 0;
2155  }
2156  };
2157 
2158  template <typename From, typename To>
2159  struct ConvertBasicType<NoFactorMarker<From>,To> {
2160  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2161  {
2162  // Simple conversion from a 'From' on disk to a 'To' in memory.
2163  TConfNoFactor *conf = (TConfNoFactor *)config;
2164  From temp;
2165  const Int_t offset = config->fOffset;
2166  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2167  buf.ReadWithNbits(&temp, conf->fNbits);
2168  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2169  *x = (To)temp;
2170  }
2171  return 0;
2172  }
2173  };
2174 
2175  template <typename T>
2176  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2177  {
2178  const Int_t offset = config->fOffset;
2179 
2180  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2181  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2182  buf << *x;
2183  }
2184  return 0;
2185  }
2186 
2187  template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2188  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2189  {
2190  for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2191  action(buf, *(void**)iter, config);
2192  }
2193  return 0;
2194  }
2195 
2196  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2197  {
2198  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2199  // punt.
2200 
2201  return GenericRead(buf,start,end,config);
2202  }
2203 
2204  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2205  {
2206  Int_t n = ( ((void**)end) - ((void**)iter) );
2207  char **arr = (char**)iter;
2208  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2209  }
2210 
2211  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2212  {
2213  Int_t n = ( ((void**)end) - ((void**)iter) );
2214  char **arr = (char**)iter;
2215  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2216  }
2217 
2218  };
2219 
2220  struct AssociativeLooper {
2221 
2222  template <typename T>
2223  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2224  {
2225  buf.ReadFastArray((T*)addr, nvalues);
2226  }
2227 
2228  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2229  {
2230  buf.ReadFastArrayFloat16((float*)addr, nvalues);
2231  }
2232 
2233  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2234  {
2235  buf.ReadFastArrayDouble32((double*)addr, nvalues);
2236  }
2237 
2238  template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2239  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2240  {
2241  // Collection of numbers. Memberwise or not, it is all the same.
2242 
2243  TConfigSTL *config = (TConfigSTL*)conf;
2244  UInt_t start, count;
2245  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2246 
2247  TClass *newClass = config->fNewClass;
2248  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2249  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2250 
2251  Int_t nvalues;
2252  buf.ReadInt(nvalues);
2253  void* alternative = newProxy->Allocate(nvalues,true);
2254  if (nvalues) {
2257  void *begin = &(startbuf[0]);
2258  void *end = &(endbuf[0]);
2259  config->fCreateIterators(alternative, &begin, &end, newProxy);
2260  // We can not get here with a split vector of pointer, so we can indeed assume
2261  // that actions->fConfiguration != null.
2262 
2263  action(buf,begin,nvalues);
2264 
2265  if (begin != &(startbuf[0])) {
2266  // assert(end != endbuf);
2267  config->fDeleteTwoIterators(begin,end);
2268  }
2269  }
2270  newProxy->Commit(alternative);
2271 
2272  buf.CheckByteCount(start,count,config->fTypeName);
2273  return 0;
2274  }
2275 
2276  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2277  {
2278  return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2279  }
2280 
2281  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2282  {
2283  return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2284  }
2285 
2286  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2287  {
2288  return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2289  }
2290 
2291  template <typename T>
2292  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2293  {
2294  return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2295  }
2296 
2297  template <typename From, typename To>
2298  struct ConvertRead {
2299  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2300  {
2301  From *temp = new From[nvalues];
2302  buf.ReadFastArray(temp, nvalues);
2303  To *vec = (To*)addr;
2304  for(Int_t ind = 0; ind < nvalues; ++ind) {
2305  vec[ind] = (To)temp[ind];
2306  }
2307  delete [] temp;
2308  }
2309  };
2310 
2311  template <typename From, typename To>
2312  struct ConvertRead<NoFactorMarker<From>,To> {
2313  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2314  {
2315  From *temp = new From[nvalues];
2316  buf.ReadFastArrayWithNbits(temp, nvalues,0);
2317  To *vec = (To*)addr;
2318  for(Int_t ind = 0; ind < nvalues; ++ind) {
2319  vec[ind] = (To)temp[ind];
2320  }
2321  delete [] temp;
2322  }
2323  };
2324 
2325  template <typename From, typename To>
2326  struct ConvertRead<WithFactorMarker<From>,To> {
2327  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2328  {
2329  From *temp = new From[nvalues];
2330  double factor,min; // needs to be initialized.
2331  buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2332  To *vec = (To*)addr;
2333  for(Int_t ind = 0; ind < nvalues; ++ind) {
2334  vec[ind] = (To)temp[ind];
2335  }
2336  delete [] temp;
2337  }
2338  };
2339 
2340  template <typename From, typename To>
2341  struct ConvertCollectionBasicType {
2342  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2343  {
2344  return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2345  }
2346  };
2347 
2348  };
2349 
2350  struct GenericLooper {
2351 
2352  template <typename T>
2353  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(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 <typename T>
2374  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2375  {
2376  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2377 
2378  Next_t next = loopconfig->fNext;
2379  const Int_t offset = config->fOffset;
2380 
2382  void *iter = loopconfig->fCopyIterator(iterator,start);
2383  void *addr;
2384  while( (addr = next(iter,end)) ) {
2385  T *x = (T*)( ((char*)addr) + offset );
2386  buf << *x;
2387  }
2388  if (iter != &iterator[0]) {
2389  loopconfig->fDeleteIterator(iter);
2390  }
2391  return 0;
2392  }
2393 
2394  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2395  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, 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  iter_action(buf, addr, config);
2407  }
2408  if (iter != &iterator[0]) {
2409  loopconfig->fDeleteIterator(iter);
2410  }
2411  return 0;
2412  }
2413 
2414  template <typename From, typename To>
2415  struct Generic {
2416  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2417  {
2418  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2419 
2420  const Int_t offset = config->fOffset;
2421  Next_t next = loopconfig->fNext;
2422 
2424  void *iter = loopconfig->fCopyIterator(&iterator,start);
2425  void *addr;
2426  while( (addr = next(iter,end)) ) {
2427  To *x = (To*)( ((char*)addr) + offset );
2428  *x = (To)(*items);
2429  ++items;
2430  }
2431  if (iter != &iterator[0]) {
2432  loopconfig->fDeleteIterator(iter);
2433  }
2434  }
2435  };
2436 
2437  template <typename From, typename To>
2438  struct Numeric {
2439  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2440  {
2441  // The difference with ConvertAction is that we can modify the start
2442  // iterator and skip the copy. We also never have an offset.
2443 
2444  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2445  Next_t next = loopconfig->fNext;
2446 
2447  void *iter = start;
2448  void *addr;
2449  while( (addr = next(iter,end)) ) {
2450  To *x = (To*)(addr);
2451  *x = (To)(*items);
2452  ++items;
2453  }
2454  }
2455  };
2456 
2457  template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2458  struct ConvertBasicType {
2459  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2460  {
2461  // Simple conversion from a 'From' on disk to a 'To' in memory.
2462 
2463  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2464  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2465  Int_t nvalues = proxy->Size();
2466 
2467  From *items = new From[nvalues];
2468  buf.ReadFastArray(items, nvalues);
2469  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2470  delete [] items;
2471  return 0;
2472  }
2473  };
2474 
2475  template <typename To>
2476  struct ConvertBasicType<BitsMarker, To, Generic> {
2477  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2478  {
2479  // Simple conversion from a 'From' on disk to a 'To' in memory.
2480 
2481  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2482  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2483  Int_t nvalues = proxy->Size();
2484 
2485  UInt_t *items_storage = new UInt_t[nvalues];
2486  UInt_t *items = items_storage;
2487 
2488  const Int_t offset = config->fOffset;
2489  Next_t next = loopconfig->fNext;
2490 
2492  void *iter = loopconfig->fCopyIterator(&iterator,start);
2493  void *addr;
2494  while( (addr = next(iter,end)) ) {
2495  buf >> (*items);
2496  if (((*items) & kIsReferenced) != 0) {
2497  HandleReferencedTObject(buf, addr, config);
2498  }
2499  To *x = (To*)( ((char*)addr) + offset );
2500  *x = (To)(*items);
2501  ++items;
2502  }
2503  if (iter != &iterator[0]) {
2504  loopconfig->fDeleteIterator(iter);
2505  }
2506 
2507  delete [] items_storage;
2508  return 0;
2509  }
2510  };
2511 
2512  template <typename From, typename To, template <typename F, typename T> class Converter >
2513  struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2514  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2515  {
2516  // Simple conversion from a 'From' on disk to a 'To' in memory.
2517 
2518  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2519  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2520  Int_t nvalues = proxy->Size();
2521 
2522  TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2523 
2524  From *items = new From[nvalues];
2525  buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2526  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2527  delete [] items;
2528  return 0;
2529  }
2530  };
2531 
2532  template <typename From, typename To, template <typename F, typename T> class Converter >
2533  struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2534  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2535  {
2536  // Simple conversion from a 'From' on disk to a 'To' in memory.
2537 
2538  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2539  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2540  Int_t nvalues = proxy->Size();
2541 
2542  TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2543 
2544  From *items = new From[nvalues];
2545  buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2546  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2547  delete [] items;
2548  return 0;
2549  }
2550  };
2551 
2552  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2553  {
2554  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2555  // punt.
2556 
2557  return GenericRead(buf,start,end,loopconfig, config);
2558  }
2559 
2560  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2561  {
2562  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2563  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2564  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2565  }
2566 
2567  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2568  {
2569  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2570  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2571  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2572  }
2573 
2574  template <typename T>
2575  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2576  {
2577  buf >> *(T*)addr;
2578  }
2579 
2580  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2581  {
2582  buf.ReadWithNbits((float*)addr,12);
2583  }
2584 
2585  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2586  {
2587  //we read a float and convert it to double
2588  Float_t afloat;
2589  buf >> afloat;
2590  *(double*)addr = (Double_t)afloat;
2591  }
2592 
2593  template <typename ActionHolder>
2594  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2595  {
2596  // Collection of numbers. Memberwise or not, it is all the same.
2597 
2598  TConfigSTL *config = (TConfigSTL*)conf;
2599  UInt_t start, count;
2600  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2601 
2602  TClass *newClass = config->fNewClass;
2603  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2604  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2605 
2606  Int_t nvalues;
2607  buf.ReadInt(nvalues);
2608  void* alternative = newProxy->Allocate(nvalues,true);
2609  if (nvalues) {
2612  void *begin = &(startbuf[0]);
2613  void *end = &(endbuf[0]);
2614  config->fCreateIterators(alternative, &begin, &end, newProxy);
2615  // We can not get here with a split vector of pointer, so we can indeed assume
2616  // that actions->fConfiguration != null.
2617 
2618  TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2619  ActionHolder::Action(buf,begin,end,&loopconf,config);
2620 
2621  if (begin != &(startbuf[0])) {
2622  // assert(end != endbuf);
2623  config->fDeleteTwoIterators(begin,end);
2624  }
2625  }
2626  newProxy->Commit(alternative);
2627 
2628  buf.CheckByteCount(start,count,config->fTypeName);
2629  return 0;
2630  }
2631 
2632  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2633  {
2634  return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2635  }
2636 
2637  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2638  {
2639  return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2640  }
2641 
2642  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2643  {
2644  return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2645  // Could also use:
2646  // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2647  }
2648 
2649  template <typename T>
2650  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2651  {
2652  return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2653  }
2654 
2655  template <typename From, typename To>
2656  struct ConvertCollectionBasicType {
2657  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2658  {
2659  // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2660  return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2661  }
2662  };
2663 
2664  };
2665 }
2666 
2667 template <typename Looper, typename From>
2669 {
2670  switch (newtype) {
2671  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2672  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2673  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2674  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2675  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2676  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2677  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2678  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2679  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2680  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2681  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2682  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2683  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2684  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2685  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2686  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2687  default:
2688  return TConfiguredAction( Looper::GenericRead, conf );
2689  break;
2690  }
2691  R__ASSERT(0); // We should never be here
2692  return TConfiguredAction();
2693 }
2694 
2695 template <class Looper>
2697 {
2698  // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2699 
2700  switch (type) {
2701  // Read basic types.
2702  case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2703  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2704  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2705  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2706  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2707  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2708  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2709  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2710  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2711  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2712  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2713  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2714  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2715  case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2716  case TStreamerInfo::kFloat16: {
2717  TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2718  delete conf;
2719  return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2720  // if (element->GetFactor() != 0) {
2721  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2722  // } else {
2723  // Int_t nbits = (Int_t)element->GetXmin();
2724  // if (!nbits) nbits = 12;
2725  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2726  // }
2727  break;
2728  }
2729  case TStreamerInfo::kDouble32: {
2730  TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2731  delete conf;
2732  return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2733  // if (element->GetFactor() != 0) {
2734  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2735  // } else {
2736  // Int_t nbits = (Int_t)element->GetXmin();
2737  // if (!nbits) {
2738  // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2739  // } else {
2740  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2741  // }
2742  // }
2743  break;
2744  }
2745  }
2746  Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2747  R__ASSERT(0); // We should never be here
2748  return TConfiguredAction();
2749 }
2750 
2751 template <typename Looper, typename From>
2753 {
2754  switch (newtype) {
2755  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2756  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2757  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2758  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2759  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2760  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2761  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2762  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2763  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2764  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2765  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2766  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2767  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2768  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2769  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2770  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2771  default:
2772  break;
2773  }
2774  R__ASSERT(0); // We should never be here
2775  return TConfiguredAction();
2776 }
2777 
2778 template <typename Looper>
2780 {
2781  switch (oldtype) {
2782  case TStreamerInfo::kBool:
2783  return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2784  break;
2785  case TStreamerInfo::kChar:
2786  return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2787  break;
2788  case TStreamerInfo::kShort:
2789  return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2790  break;
2791  case TStreamerInfo::kInt:
2792  return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2793  break;
2794  case TStreamerInfo::kLong:
2795  return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2796  break;
2798  return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2799  break;
2800  case TStreamerInfo::kFloat:
2801  return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2802  break;
2804  return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2805  break;
2806  case TStreamerInfo::kUChar:
2807  return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2808  break;
2810  return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2811  break;
2812  case TStreamerInfo::kUInt:
2813  return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2814  break;
2815  case TStreamerInfo::kULong:
2816  return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2817  break;
2819  return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2820  break;
2822  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2823  break;
2825  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2826  break;
2827  case TStreamerInfo::kBits:
2828  Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2829  break;
2830  default:
2831  break;
2832  }
2833  R__ASSERT(0); // We should never be here
2834  return TConfiguredAction();
2835 }
2836 
2837 template <class Looper>
2839 {
2840  switch (type) {
2841  // Read basic types.
2842  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2843  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2844  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2845  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2846  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2847  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2848  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2849  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2850  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2851  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2852  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2853  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2854  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2855  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2856  case TStreamerInfo::kFloat16: {
2857  if (element->GetFactor() != 0) {
2858  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2859  } else {
2860  Int_t nbits = (Int_t)element->GetXmin();
2861  if (!nbits) nbits = 12;
2862  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2863  }
2864  break;
2865  }
2866  case TStreamerInfo::kDouble32: {
2867  if (element->GetFactor() != 0) {
2868  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2869  } else {
2870  Int_t nbits = (Int_t)element->GetXmin();
2871  if (!nbits) {
2872  return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2873  } else {
2874  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2875  }
2876  }
2877  break;
2878  }
2879  case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2880  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2881  // Streamer alltogether.
2882  case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2883  case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2887  case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2888  case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2889 
2890  // Conversions.
2892  return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2893  break;
2895  return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2896  break;
2898  return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2899  break;
2901  return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2902  break;
2904  return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2905  break;
2907  return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2908  break;
2910  return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2911  break;
2913  return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2914  break;
2916  return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2917  break;
2919  return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2920  break;
2922  return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2923  break;
2925  return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2926  break;
2928  return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2929  break;
2931  return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2932  break;
2934  if (element->GetFactor() != 0) {
2935  return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2936  } else {
2937  Int_t nbits = (Int_t)element->GetXmin();
2938  if (!nbits) nbits = 12;
2939  return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2940  }
2941  break;
2942  }
2944  if (element->GetFactor() != 0) {
2945  return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2946  } else {
2947  Int_t nbits = (Int_t)element->GetXmin();
2948  if (!nbits) {
2949  return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2950  } else {
2951  return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2952  }
2953  }
2954  break;
2955  }
2956  default:
2957  return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2958  break;
2959  }
2960  R__ASSERT(0); // We should never be here
2961  return TConfiguredAction();
2962 }
2963 
2964 template <class Looper>
2966  switch (type) {
2967  // read basic types
2968  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2969  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2970  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2971  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2972  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2973  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2974  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2975  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2976  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2977  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2978  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2979  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2980  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2981  // the simple type missing are kBits and kCounter.
2982  default:
2983  return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2984  }
2985  R__ASSERT(0); // We should never be here
2986  return TConfiguredAction();
2987 }
2988 
2989 
2990 ////////////////////////////////////////////////////////////////////////////////
2991 /// loop on the TStreamerElement list
2992 /// regroup members with same type
2993 /// Store predigested information into local arrays. This saves a huge amount
2994 /// of time compared to an explicit iteration on all elements.
2995 
2997 {
2998  if (IsCompiled()) {
2999  //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
3000  return;
3001  }
3003 
3004  // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
3005 
3006  // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
3007  fOptimized = kFALSE;
3008  fNdata = 0;
3009  fNfulldata = 0;
3010 
3011  TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
3012  if (fNumber < 0) {
3013  ++fgCount;
3014  fNumber = fgCount;
3015  }
3016  if (fNumber >= infos->GetSize()) {
3017  infos->AddAtAndExpand(this, fNumber);
3018  } else {
3019  if (!infos->At(fNumber)) {
3020  infos->AddAt(this, fNumber);
3021  }
3022  }
3023 
3024  assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3025 
3026 
3027  Int_t ndata = fElements->GetEntriesFast();
3028 
3029 
3032 
3035 
3038 
3039  if (fReadText) fReadText->fActions.clear();
3040  else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3041 
3044 
3047 
3050 
3051  if (fWriteText) fWriteText->fActions.clear();
3052  else fWriteText = new TStreamerInfoActions::TActionSequence(this,ndata);
3053 
3054  if (!ndata) {
3055  // This may be the case for empty classes (e.g., TAtt3D).
3056  // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3058  fSize = sizeof(TStreamerInfo*);
3059  }
3060  fComp = new TCompInfo[1];
3061  fCompFull = new TCompInfo*[1];
3062  fCompOpt = new TCompInfo*[1];
3063  fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3064  SetIsCompiled();
3065  return;
3066  }
3067 
3068  // At most half of the elements can be used to hold optimized versions.
3069  // We use the bottom to hold the optimized-into elements and the non-optimized elements
3070  // and the top to hold the original copy of the optimized out elements.
3071  fNslots = ndata + ndata/2 + 1;
3072  Int_t optiOut = 0;
3073 
3074  fComp = new TCompInfo[fNslots];
3075  fCompFull = new TCompInfo*[ndata];
3076  fCompOpt = new TCompInfo*[ndata];
3077 
3078  TStreamerElement* element;
3079  TStreamerElement* previous = 0;
3080  Int_t keep = -1;
3081  Int_t i;
3082 
3083  if (!CanOptimize()) {
3085  }
3086 
3087  Bool_t isOptimized = kFALSE;
3088  Bool_t previousOptimized = kFALSE;
3089 
3090  for (i = 0; i < ndata; ++i) {
3091  element = (TStreamerElement*) fElements->At(i);
3092  if (!element) {
3093  break;
3094  }
3095 
3096  Int_t asize = element->GetSize();
3097  if (element->GetArrayLength()) {
3098  asize /= element->GetArrayLength();
3099  }
3100  fComp[fNdata].fType = element->GetType();
3101  fComp[fNdata].fNewType = element->GetNewType();
3102  fComp[fNdata].fOffset = element->GetOffset();
3103  fComp[fNdata].fLength = element->GetArrayLength();
3104  fComp[fNdata].fElem = element;
3105  fComp[fNdata].fMethod = element->GetMethod();
3106  fComp[fNdata].fClass = element->GetClassPointer();
3107  fComp[fNdata].fNewClass = element->GetNewClass();
3109  fComp[fNdata].fStreamer = element->GetStreamer();
3110 
3111  // try to group consecutive members of the same type
3112  if (!TestBit(kCannotOptimize)
3113  && (keep >= 0)
3114  && (element->GetType() > 0)
3115  && (element->GetType() < 10)
3117  && (fComp[keep].fMethod == 0)
3118  && (element->GetArrayDim() == 0)
3119  && (fComp[keep].fType < kObject)
3120  && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3121  && (element->GetType() == (fComp[keep].fType%kRegrouped))
3122  && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3123  && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3124  ((element->GetFactor() == previous->GetFactor())
3125  && (element->GetXmin() == previous->GetXmin())
3126  && (element->GetXmax() == previous->GetXmax())
3127  )
3128  )
3131  // kWholeObject and kDoNotDelete do not apply to numerical elements.
3132  )
3133  {
3134  if (!previousOptimized) {
3135  // The element was not yet optimized we first need to copy it into
3136  // the set of original copies.
3137  fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3138  fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3139  }
3140  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3141  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3142 
3143  R__ASSERT( keep < (fNslots - optiOut) );
3144 
3145  if (fComp[keep].fLength == 0) {
3146  fComp[keep].fLength++;
3147  }
3148  fComp[keep].fLength++;
3149  fComp[keep].fType = element->GetType() + kRegrouped;
3150  isOptimized = kTRUE;
3151  previousOptimized = kTRUE;
3152  } else if (element->GetType() < 0) {
3153 
3154  // -- Deal with an ignored TObject base class.
3155  // Note: The only allowed negative value here is -1,
3156  // and signifies that Build() has found a TObject
3157  // base class and TClass::IgnoreTObjectStreamer() was
3158  // called. In this case the compiled version of the
3159  // elements omits the TObject base class element,
3160  // which has to be compensated for by TTree::Bronch()
3161  // when it is making branches for a split object.
3162  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3163  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3164  keep = -1;
3165  previousOptimized = kFALSE;
3166 
3167  } else {
3168  if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3169  if (fComp[fNdata].fNewType > 0) {
3170  if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3171  || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3172  || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3173  && (fComp[fNdata].fType == kObjectp || fComp[fNdata].fType == kAnyp
3174  || fComp[fNdata].fType == kObject || fComp[fNdata].fType == kAny
3176  ) {
3178  } else if (fComp[fNdata].fType != kCounter) {
3179  fComp[fNdata].fType += kConv;
3180  }
3181  } else {
3182  if (fComp[fNdata].fType == kCounter) {
3183  Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3184  }
3185  fComp[fNdata].fType += kSkip;
3186  }
3187  }
3188  fCompOpt[fNdata] = &(fComp[fNdata]);
3190 
3191  R__ASSERT( fNdata < (fNslots - optiOut) );
3192 
3193  keep = fNdata;
3194  if (fComp[keep].fLength == 0) {
3195  fComp[keep].fLength = 1;
3196  }
3197  fNdata++;
3198  previousOptimized = kFALSE;
3199  }
3200  // The test 'fMethod[keep] == 0' fails to detect a variable size array
3201  // if the counter happens to have an offset of zero, so let's explicitly
3202  // prevent for here.
3203  if (element->HasCounter()) keep = -1;
3204  ++fNfulldata;
3205  previous = element;
3206  }
3207 
3208  for (i = 0; i < fNdata; ++i) {
3209  if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3210  continue;
3211  }
3214  }
3215  for (i = 0; i < fNfulldata; ++i) {
3216  if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3217  continue;
3218  }
3223 
3226  }
3227  ComputeSize();
3228 
3229  fOptimized = isOptimized;
3230  SetIsCompiled();
3231 
3232  if (gDebug > 0) {
3233  ls();
3234  }
3235 }
3236 
3237 template <typename From>
3239 {
3240  switch (newtype) {
3241  case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
3242  case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
3243  case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
3244  case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
3245  case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
3246  case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
3247  case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3248  case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3249  case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3250  case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3251  case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
3252  case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
3253  case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3254  case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
3255  case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
3256  case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3257  }
3258 }
3259 
3260 ////////////////////////////////////////////////////////////////////////////////
3261 /// Add a read action for the given element.
3262 
3264 {
3265  TStreamerElement *element = compinfo->fElem;
3266 
3267  if (element->TestBit(TStreamerElement::kWrite)) return;
3268 
3269  switch (compinfo->fType) {
3270  // read basic types
3271  case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3272  case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3273  case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3274  case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3275  case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3276  case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3277  case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3278  case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3279  case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3280  case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3281  case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3282  case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3283  case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3284  case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3285  case TStreamerInfo::kFloat16: {
3286  if (element->GetFactor() != 0) {
3287  readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3288  } else {
3289  Int_t nbits = (Int_t)element->GetXmin();
3290  if (!nbits) nbits = 12;
3291  readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3292  }
3293  break;
3294  }
3295  case TStreamerInfo::kDouble32: {
3296  if (element->GetFactor() != 0) {
3297  readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3298  } else {
3299  Int_t nbits = (Int_t)element->GetXmin();
3300  if (!nbits) {
3301  readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3302  } else {
3303  readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3304  }
3305  }
3306  break;
3307  }
3308  case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3309  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3310  // Streamer alltogether.
3311  case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3312  case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3313  case TStreamerInfo::kSTL: {
3314  TClass *newClass = element->GetNewClass();
3315  TClass *oldClass = element->GetClassPointer();
3316  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3317 
3318  if (element->GetArrayLength() <= 1) {
3319  if (fOldVersion<3){ // case of old TStreamerInfo
3320  if (newClass && newClass != oldClass) {
3321  if (element->GetStreamer()) {
3322  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3323  } else {
3324  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3325  }
3326  } else {
3327  if (element->GetStreamer()) {
3328  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3329  } else {
3330  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3331  }
3332  }
3333  } else {
3334  if (newClass && newClass != oldClass) {
3335  if (element->GetStreamer()) {
3336  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3337  } else {
3338  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3339  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3340  } else {
3341  switch (SelectLooper(*newClass->GetCollectionProxy())) {
3342  case kVectorLooper:
3343  readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3344  break;
3345  case kAssociativeLooper:
3346  readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3347  break;
3348  case kVectorPtrLooper:
3349  case kGenericLooper:
3350  default:
3351  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3352  readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3353  break;
3354  }
3355  }
3356  }
3357  } else {
3358  if (element->GetStreamer()) {
3359  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3360  } else {
3361  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3362  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3363  } else {
3364  switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3365  case kVectorLooper:
3366  readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3367  break;
3368  case kAssociativeLooper:
3369  readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3370  break;
3371  case kVectorPtrLooper:
3372  case kGenericLooper:
3373  default:
3374  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3375  readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3376  break;
3377  }
3378  }
3379  }
3380  }
3381  }
3382  } else {
3383  if (fOldVersion<3){ // case of old TStreamerInfo
3384  if (newClass && newClass != oldClass) {
3385  if (element->GetStreamer()) {
3386  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3387  } else {
3388  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3389  }
3390  } else {
3391  if (element->GetStreamer()) {
3392  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3393  } else {
3394  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3395  }
3396  }
3397  } else {
3398  if (newClass && newClass != oldClass) {
3399  if (element->GetStreamer()) {
3400  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3401  } else {
3402  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3403  }
3404  } else {
3405  if (element->GetStreamer()) {
3406  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3407  } else {
3408  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3409  }
3410  }
3411  }
3412  }
3413  break;
3414  }
3415 
3417  AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3418  break;
3420  AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3421  break;
3423  AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3424  break;
3426  AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3427  break;
3429  AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3430  break;
3432  AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3433  break;
3435  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3436  break;
3438  AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3439  break;
3441  AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3442  break;
3444  AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3445  break;
3447  AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3448  break;
3450  AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3451  break;
3453  AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3454  break;
3456  AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3457  break;
3459  if (element->GetFactor() != 0) {
3460  AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3461  } else {
3462  Int_t nbits = (Int_t)element->GetXmin();
3463  if (!nbits) nbits = 12;
3464  AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3465  }
3466  break;
3467  }
3469  if (element->GetFactor() != 0) {
3470  AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3471  } else {
3472  Int_t nbits = (Int_t)element->GetXmin();
3473  if (!nbits) {
3474  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3475  } else {
3476  AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3477  }
3478  }
3479  break;
3480  }
3481  default:
3482  readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3483  break;
3484  }
3485  if (element->TestBit(TStreamerElement::kCache)) {
3486  TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3487  readSequence->fActions.pop_back();
3488  readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3489  }
3490 }
3491 
3492 ////////////////////////////////////////////////////////////////////////////////
3493 /// Add a read text action for the given element.
3494 
3496 {
3497  TStreamerElement *element = compinfo->fElem;
3498 
3499  if (element->TestBit(TStreamerElement::kWrite))
3500  return;
3501 
3502  Bool_t generic = kFALSE, isBase = kFALSE;
3503 
3504  switch (compinfo->fType) {
3506  if (element->IsBase())
3507  isBase = kTRUE;
3508  // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3509  else
3510  readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3511  break;
3512 
3514  if (element->IsBase())
3515  isBase = kTRUE;
3516  // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3517  else
3518  readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3519  break;
3520 
3521  case TStreamerInfo::kObject: // Class derived from TObject
3522  case TStreamerInfo::kAny: // Class NOT derived from TObject
3525  readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3526  break;
3527 
3528  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3529  case TStreamerInfo::kSTLp +
3530  TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3531  readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3532  break;
3533 
3536  readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3537  break;
3538 
3539  case TStreamerInfo::kBase: isBase = kTRUE; break;
3540 
3542  readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3543  break;
3544 
3545  default: generic = kTRUE; break;
3546  }
3547 
3548  if (isBase) {
3549  if (compinfo->fStreamer) {
3550  readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3551  } else {
3552  readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3553  }
3554  } else if (generic)
3555  readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3556 }
3557 
3558 ////////////////////////////////////////////////////////////////////////////////
3559 /// Add a read action for the given element.
3560 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3561 
3563 {
3564  TStreamerElement *element = compinfo->fElem;
3565 
3566  if (element->TestBit(TStreamerElement::kWrite)) return;
3567 
3568  if (element->TestBit(TStreamerElement::kCache)) {
3569  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3570  readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3571  } else {
3572  readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3573  }
3574 }
3575 
3576 ////////////////////////////////////////////////////////////////////////////////
3577 
3579 {
3580  TStreamerElement *element = compinfo->fElem;
3581  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3582  // Skip element cached for reading purposes.
3583  return;
3584  }
3585  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3586  // Skip artificial element used for reading purposes.
3587  return;
3588  }
3589  switch (compinfo->fType) {
3590  // write basic types
3591  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3592  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3593  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3594  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3595  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3596  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3597  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3598  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3599  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3600  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3601  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3602  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3603  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3604  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3605  /*case TStreamerInfo::kFloat16: {
3606  if (element->GetFactor() != 0) {
3607  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3608  } else {
3609  Int_t nbits = (Int_t)element->GetXmin();
3610  if (!nbits) nbits = 12;
3611  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3612  }
3613  break;
3614  } */
3615  /*case TStreamerInfo::kDouble32: {
3616  if (element->GetFactor() != 0) {
3617  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3618  } else {
3619  Int_t nbits = (Int_t)element->GetXmin();
3620  if (!nbits) {
3621  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3622  } else {
3623  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3624  }
3625  }
3626  break;
3627  } */
3628  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3629  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3630  // Streamer alltogether.
3631  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3632  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3633  /*case TStreamerInfo::kSTL: {
3634  TClass *newClass = element->GetNewClass();
3635  TClass *oldClass = element->GetClassPointer();
3636  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3637 
3638  if (element->GetArrayLength() <= 1) {
3639  if (newClass && newClass != oldClass) {
3640  if (element->GetStreamer()) {
3641  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3642  } else {
3643  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3644  }
3645  } else {
3646  if (element->GetStreamer()) {
3647  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3648  } else {
3649  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3650  }
3651  }
3652  } else {
3653  if (newClass && newClass != oldClass) {
3654  if (element->GetStreamer()) {
3655  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3656  } else {
3657  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3658  }
3659  } else {
3660  if (element->GetStreamer()) {
3661  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3662  } else {
3663  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3664  }
3665  }
3666  }
3667  break;
3668  } */
3669  default:
3670  writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3671  break;
3672  }
3673 #if defined(CDJ_NO_COMPILE)
3674  if (element->TestBit(TStreamerElement::kCache)) {
3675  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3676  writeSequence->fActions.pop_back();
3677  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3678  }
3679 #endif
3680 }
3681 
3682 ////////////////////////////////////////////////////////////////////////////////
3683 
3685 {
3686  TStreamerElement *element = compinfo->fElem;
3687  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3688  // Skip element cached for reading purposes.
3689  return;
3690  }
3691  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3692  // Skip artificial element used for reading purposes.
3693  return;
3694  }
3695 
3696  Bool_t generic = kFALSE, isBase = kFALSE;
3697 
3698  switch (compinfo->fType) {
3699  // write basic types
3700  case TStreamerInfo::kBool:
3701  writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3702  break;
3703  case TStreamerInfo::kChar:
3704  writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3705  break;
3706  case TStreamerInfo::kShort:
3707  writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3708  break;
3709  case TStreamerInfo::kInt:
3710  writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3711  break;
3712  case TStreamerInfo::kLong:
3713  writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3714  break;
3716  writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3717  break;
3718  case TStreamerInfo::kFloat:
3719  writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3720  break;
3722  writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3723  break;
3724  case TStreamerInfo::kUChar:
3725  writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3726  break;
3728  writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3729  break;
3730  case TStreamerInfo::kUInt:
3731  writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3732  break;
3733  case TStreamerInfo::kULong:
3734  writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3735  break;
3737  writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3738  break;
3739 
3741  if (element->IsBase())
3742  isBase = kTRUE;
3743  else
3744  writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3745  break;
3746 
3748  if (element->IsBase())
3749  isBase = kTRUE;
3750  else
3751  writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3752  break;
3753 
3754  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3755  case TStreamerInfo::kSTLp +
3756  TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3757  writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3758  break;
3759 
3762  writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3763  break;
3764 
3765  case TStreamerInfo::kBase: isBase = kTRUE; break;
3766 
3768  writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3769  break;
3770 
3771  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3772  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3773  /*case TStreamerInfo::kFloat16: {
3774  if (element->GetFactor() != 0) {
3775  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3776  TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3777  } else {
3778  Int_t nbits = (Int_t)element->GetXmin();
3779  if (!nbits) nbits = 12;
3780  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3781  TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3782  }
3783  break;
3784  } */
3785  /*case TStreamerInfo::kDouble32: {
3786  if (element->GetFactor() != 0) {
3787  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3788  TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3789  } else {
3790  Int_t nbits = (Int_t)element->GetXmin();
3791  if (!nbits) {
3792  writeSequence->AddAction( ConvertBasicType<float,double>, new
3793  TConfiguration(this,i,compinfo,compinfo->fOffset) );
3794  } else {
3795  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3796  TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3797  }
3798  }
3799  break;
3800  } */
3801  // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3802  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3803  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3804  // Streamer alltogether.
3805  // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3806  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3807  // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3808  // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3809  /*case TStreamerInfo::kSTL: {
3810  TClass *newClass = element->GetNewClass();
3811  TClass *oldClass = element->GetClassPointer();
3812  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3813 
3814  if (element->GetArrayLength() <= 1) {
3815  if (newClass && newClass != oldClass) {
3816  if (element->GetStreamer()) {
3817  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3818  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3819  } else {
3820  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3821  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3822  }
3823  } else {
3824  if (element->GetStreamer()) {
3825  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3826  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3827  } else {
3828  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3829  TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3830  }
3831  }
3832  } else {
3833  if (newClass && newClass != oldClass) {
3834  if (element->GetStreamer()) {
3835  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3836  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3837  } else {
3838  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3839  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3840  }
3841  } else {
3842  if (element->GetStreamer()) {
3843  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3844  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3845  } else {
3846  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3847  TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3848  }
3849  }
3850  }
3851  break;
3852  } */
3853  default: generic = kTRUE; break;
3854  }
3855 
3856  if (isBase) {
3857  if (compinfo->fStreamer) {
3858  writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3859  } else {
3860  writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3861  }
3862 
3863  } else
3864 
3865  // use generic write action when special handling is not provided
3866  if (generic)
3867  writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3868 
3869 #if defined(CDJ_NO_COMPILE)
3870  if (element->TestBit(TStreamerElement::kCache)) {
3871  TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3872  writeSequence->fActions.pop_back();
3873  writeSequence->AddAction(UseCache,
3874  new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3875  }
3876 #endif
3877 }
3878 
3879 ////////////////////////////////////////////////////////////////////////////////
3880 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3881 
3883 {
3884  TStreamerElement *element = compinfo->fElem;
3885  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3886  // Skip element cached for reading purposes.
3887  return;
3888  }
3889  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3890  // Skip artificial element used for reading purposes.
3891  return;
3892  }
3893 
3894 #if defined(CDJ_NO_COMPILE)
3895  if (element->TestBit(TStreamerElement::kCache)) {
3896  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3897  writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3898  } else {
3899  writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3900  }
3901 #else
3902  writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3903 #endif
3904 
3905 }
3906 
3907 ////////////////////////////////////////////////////////////////////////////////
3908 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3909 
3911 {
3912  if (info == 0) {
3913  return new TStreamerInfoActions::TActionSequence(0,0);
3914  }
3915 
3916  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3917 
3918  UInt_t ndata = info->GetElements()->GetEntriesFast();
3920  if (IsDefaultVector(proxy))
3921  {
3922  if (proxy.HasPointers()) {
3923  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3924  delete sequence;
3925 
3926  sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3927 
3928  return sequence;
3929  }
3930 
3931  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3932  Long_t increment = proxy.GetIncrement();
3933  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3934  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
3938  {
3939  Long_t increment = proxy.GetIncrement();
3940  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3941  // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3942  } else {
3943  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3944  }
3945  for (UInt_t i = 0; i < ndata; ++i) {
3946  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3947  if (!element) {
3948  break;
3949  }
3950  if (element->GetType() < 0) {
3951  // -- Skip an ignored TObject base class.
3952  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3953  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3954  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3955  // when it is making branches for a split object.
3956  continue;
3957  }
3958  if (element->TestBit(TStreamerElement::kWrite)) {
3959  // Skip element that only for writing.
3960  continue;
3961  }
3962  TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3963  if (baseEl) {
3964  if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3965  // There was a problem with the checksum, the user likely did not
3966  // increment the version number of the derived class when the
3967  // base class changed. Since we will be member wise streaming
3968  // this class, let's warn the user that something is wrong.
3969  ::Warning("CreateReadMemberWiseActions","%s",
3970  baseEl->GetErrorMessage());
3972  }
3973  }
3974 
3975  TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3976 
3977  Int_t asize = element->GetSize();
3978  if (element->GetArrayLength()) {
3979  asize /= element->GetArrayLength();
3980  }
3981  Int_t oldType = element->GetType();
3982  Int_t newType = element->GetNewType();
3983 
3984  Int_t offset = element->GetOffset();
3985  if (newType != oldType) {
3986  if (newType > 0) {
3987  if (oldType != TVirtualStreamerInfo::kCounter) {
3988  oldType += TVirtualStreamerInfo::kConv;
3989  }
3990  } else {
3991  oldType += TVirtualStreamerInfo::kSkip;
3992  }
3993  }
3994  switch (SelectLooper(proxy)) {
3995  case kAssociativeLooper:
3996 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3997 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3998 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3999  case kVectorLooper:
4000  case kVectorPtrLooper:
4001  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4002  if (element->TestBit(TStreamerElement::kCache)) {
4003  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4004  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4005  } else {
4006  sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4007  }
4008  break;
4009  case kGenericLooper:
4010  default:
4011  // The usual collection case.
4012  if (element->TestBit(TStreamerElement::kCache)) {
4013  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4014  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4015  } else {
4016  sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4017  }
4018  break;
4019  }
4020  }
4021  return sequence;
4022 }
4023 
4024 ////////////////////////////////////////////////////////////////////////////////
4025 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
4026 
4028 {
4029  if (info == 0) {
4030  return new TStreamerInfoActions::TActionSequence(0,0);
4031  }
4032 
4033  UInt_t ndata = info->GetElements()->GetEntriesFast();
4034  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
4036 
4037  if (IsDefaultVector(proxy))
4038  {
4039  if (proxy.HasPointers()) {
4040  // Instead of the creating a new one let's copy the one from the StreamerInfo.
4041  delete sequence;
4042 
4043  sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
4044 
4045  return sequence;
4046  }
4047 
4048  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4049  Long_t increment = proxy.GetIncrement();
4050  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
4051  /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4052  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
4053  {
4054  Long_t increment = proxy.GetIncrement();
4055  sequence->fLoopConfig = new TVectorLoopConfig(increment);
4056  // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
4057  } else {
4058  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
4059  }
4060  for (UInt_t i = 0; i < ndata; ++i) {
4061  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
4062  if (!element) {
4063  break;
4064  }
4065  if (element->GetType() < 0) {
4066  // -- Skip an ignored TObject base class.
4067  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
4068  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
4069  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
4070  // when it is making branches for a split object.
4071  continue;
4072  }
4073  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
4074  // Skip element cached for reading purposes.
4075  continue;
4076  }
4078  // Skip artificial element used for reading purposes.
4079  continue;
4080  }
4081  TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
4082  Int_t asize = element->GetSize();
4083  if (element->GetArrayLength()) {
4084  asize /= element->GetArrayLength();
4085  }
4086  Int_t oldType = element->GetType();
4087  Int_t offset = element->GetOffset();
4088 #if defined(CDJ_NO_COMPILE)
4089  Int_t newType = element->GetNewType();
4090 
4091  if (newType != oldType) {
4092  if (newType > 0) {
4093  if (oldType != TVirtualStreamerInfo::kCounter) {
4094  oldType += TVirtualStreamerInfo::kConv;
4095  }
4096  } else {
4097  oldType += TVirtualStreamerInfo::kSkip;
4098  }
4099  }
4100  if ( IsDefaultVector(proxy)
4101  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4102  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
4103  {
4104 
4105  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4106  if (element->TestBit(TStreamerElement::kCache)) {
4107  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4108  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4109  } else {
4110  sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4111  }
4112 
4113  // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4114  // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
4115  // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4116  } else {
4117  // The usual collection case.
4118  if (element->TestBit(TStreamerElement::kCache)) {
4119  TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4120  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4121  } else {
4122  switch (oldType) {
4123  // read basic types
4124  case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4125  case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4126  case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4127  case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4128  case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4129  case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4130  case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4131  case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4132  case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4133  case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4134  case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4135  case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4136  case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4137  // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
4139  if (element->GetFactor() != 0) {
4140  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4141  } else {
4142  Int_t nbits = (Int_t)element->GetXmin();
4143  if (!nbits) nbits = 12;
4144  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4145  }
4146  break;
4147  }
4149  if (element->GetFactor() != 0) {
4150  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4151  } else {
4152  Int_t nbits = (Int_t)element->GetXmin();
4153  if (!nbits) {
4154  sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4155  } else {
4156  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4157  }
4158  }
4159  break;
4160  }
4161  case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
4162  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4163  // Streamer alltogether.
4164  case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
4165  case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
4166  default:
4167  sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4168  break;
4169  }
4170  }
4171  }
4172 #else
4173  if ( IsDefaultVector(proxy)
4174  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4175  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
4176  {
4177  sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4178  } else {
4179  // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
4180  // as it does not create/use a TStaging as expected ... but then again it might
4181  // not be the right things to expect ...
4182  // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4183  sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4184  }
4185 #endif
4186  }
4187  return sequence;
4188 }
4189 
4191 {
4192  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4193  // TBranchElement in the case of split sub-object.
4194 
4195  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4196  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4197  iter != end;
4198  ++iter)
4199  {
4200  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4201  iter->fConfiguration->AddToOffset(delta);
4202  }
4203 }
4204 
4206 {
4207  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4208  // TBranchElement in the case of split sub-object.
4209 
4210  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4211  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4212  iter != end;
4213  ++iter)
4214  {
4215  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4216  iter->fConfiguration->SetMissing();
4217  }
4218 }
4219 
4221 {
4222  // Create a copy of this sequence.
4223 
4224  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, fActions.size(), IsForVectorPtrLooper());
4225 
4226  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4227 
4228  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4229  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4230  iter != end;
4231  ++iter)
4232  {
4233  TConfiguration *conf = iter->fConfiguration->Copy();
4234  sequence->AddAction( iter->fAction, conf );
4235  }
4236  return sequence;
4237 }
4238 
4240  const TStreamerInfoActions::TIDs &element_ids,
4241  Int_t offset,
4243 {
4244  for(UInt_t id = 0; id < element_ids.size(); ++id) {
4245  if ( element_ids[id].fElemID < 0 ) {
4246  if (element_ids[id].fNestedIDs) {
4247  auto original = create(element_ids[id].fNestedIDs->fInfo,
4248  sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
4249  nullptr);
4250  if (element_ids[id].fNestedIDs->fOnfileObject) {
4251  auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
4252  if ( sequence->fLoopConfig )
4253  sequence->AddAction( PushDataCacheGenericCollection, conf );
4254  else if ( sequence->IsForVectorPtrLooper() )
4255  sequence->AddAction( PushDataCacheVectorPtr, conf );
4256  else
4257  sequence->AddAction( PushDataCache, conf );
4258  }
4259 
4260  original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
4261 
4262  if (element_ids[id].fNestedIDs->fOnfileObject) {
4263  auto conf =
4264  new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset);
4265  if ( sequence->fLoopConfig )
4266  sequence->AddAction( PopDataCacheGenericCollection, conf );
4267  else if ( sequence->IsForVectorPtrLooper() )
4268  sequence->AddAction( PopDataCacheVectorPtr, conf );
4269  else
4270  sequence->AddAction( PopDataCache, conf );
4271  }
4272  } else {
4273  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4274  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4275  iter != end;
4276  ++iter)
4277  {
4278  TConfiguration *conf = iter->fConfiguration->Copy();
4279  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4280  conf->AddToOffset(offset);
4281  sequence->AddAction( iter->fAction, conf );
4282  }
4283  }
4284  } else {
4285  int localIndex = 0;
4286  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4287  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4288  iter != end;
4289  ++iter) {
4290  // fprintf(stderr, "With element_ids[%d] For %s comparing act[%d/%zu] %d to %d for %p vs %p %s\n",
4291  // id,
4292  // iter->fConfiguration->fInfo->GetName(),
4293  // localIndex, fActions.size(),
4294  // iter->fConfiguration->fElemId,
4295  // (UInt_t)element_ids[id].fElemID, iter->fConfiguration->fInfo,
4296  // element_ids[id].fInfo,
4297  // element_ids[id].fInfo ? element_ids[id].fInfo->GetName() : "nullptr" );
4298  ++localIndex;
4299  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
4300  TConfiguration *conf = iter->fConfiguration->Copy();
4301  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4302  conf->AddToOffset(offset);
4303  sequence->AddAction( iter->fAction, conf );
4304  }
4305  }
4306  }
4307  }
4308 }
4309 
4312 {
4313  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4314  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4315 
4316  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
4317 
4318  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4319 
4320  AddToSubSequence(sequence, element_ids, offset, create);
4321 
4322  return sequence;
4323 }
4324 
4326 {
4327  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4328  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4329 
4330  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
4331 
4332  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4333 
4334  for(UInt_t id = 0; id < element_ids.size(); ++id) {
4335  if ( element_ids[id] < 0 ) {
4336  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4337  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4338  iter != end;
4339  ++iter)
4340  {
4341  TConfiguration *conf = iter->fConfiguration->Copy();
4342  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4343  conf->AddToOffset(offset);
4344  sequence->AddAction( iter->fAction, conf );
4345  }
4346  } else {
4347  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4348  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4349  iter != end;
4350  ++iter) {
4351  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
4352  TConfiguration *conf = iter->fConfiguration->Copy();
4353  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4354  conf->AddToOffset(offset);
4355  sequence->AddAction( iter->fAction, conf );
4356  }
4357  }
4358  }
4359  }
4360  return sequence;
4361 }
4362 
4363 #if !defined(R__WIN32) && !defined(_AIX)
4364 
4365 #include <dlfcn.h>
4366 
4367 #endif
4368 
4369 typedef void (*voidfunc)();
4370 static const char *R__GetSymbolName(voidfunc func)
4371 {
4372 #if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
4373  return "not available on this platform";
4374 #if 0
4375  MEMORY_BASIC_INFORMATION mbi;
4376  if (!VirtualQuery (func, &mbi, sizeof (mbi)))
4377  {
4378  return 0;
4379  }
4380 
4381  HMODULE hMod = (HMODULE) mbi.AllocationBase;
4382  static char moduleName[MAX_PATH];
4383 
4384  if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
4385  {
4386  return 0;
4387  }
4388  return moduleName;
4389 #endif
4390 #else
4391  Dl_info info;
4392  if (dladdr((void*)func,&info)==0) {
4393  // Not in a known share library, let's give up
4394  return "name not found";
4395  } else {
4396  //fprintf(stdout,"Found address in %s\n",info.dli_fname);
4397  return info.dli_sname;
4398  }
4399 #endif
4400 }
4401 
4403 {
4404  // Add the (potentially negative) delta to all the configuration's offset. This is used by
4405  // TTBranchElement in the case of split sub-object.
4406  // If opt contains 'func', also print the (mangled) name of the function that will be executed.
4407 
4408  if (fLoopConfig) {
4409  fLoopConfig->Print();
4410  }
4411  TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
4412  for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
4413  iter != end;
4414  ++iter)
4415  {
4416  iter->fConfiguration->Print();
4417  if (strstr(opt,"func")) {
4418  printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
4419  }
4420  }
4421 }
4422 
4423 
TStreamerInfoActions::TActionSequence::AddToSubSequence
void AddToSubSequence(TActionSequence *sequence, const TIDs &element_ids, Int_t offset, SequenceGetter_t create)
Definition: TStreamerInfoActions.cxx:4239
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:180
TStreamerInfoActions::TConfiguration::Print
virtual void Print() const
Definition: TStreamerInfoActions.cxx:96
R__GetSymbolName
static const char * R__GetSymbolName(voidfunc func)
Definition: TStreamerInfoActions.cxx:4370
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:3684
TStreamerInfoActions::ReadSTLObjectWiseFastArray
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
Definition: TStreamerInfoActions.cxx:1358
TStreamerInfo::kFloat16
@ kFloat16
Definition: TStreamerInfo.h:171
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:4325
GetCollectionWriteAction
static TConfiguredAction GetCollectionWriteAction(TVirtualStreamerInfo *info, TStreamerElement *, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
Definition: TStreamerInfoActions.cxx:2965
TStreamerInfo::fReadMemberWise
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
Definition: TStreamerInfo.h:110
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:2696