Logo ROOT   6.12/07
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 "TMemberStreamer.h"
22 #include "TError.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 {
47  template <typename From>
48  struct WithFactorMarker {
49  typedef From Value_t;
50  };
51 
52  template <typename From>
53  struct NoFactorMarker {
54  typedef From Value_t;
55  };
56 
57  struct BitsMarker {
58  typedef UInt_t Value_t;
59  };
60 
62  {
63  // Add the (potentially negative) delta to all the configuration's offset. This is used by
64  // TBranchElement in the case of split sub-object.
65 
66  fOffset += delta;
67  }
68 
69  void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
70  {
71  // Inform the user what we are about to stream.
72 
73  // Idea, we should find a way to print the name of the function
74  if (fConfiguration) fConfiguration->PrintDebug(buf,addr);
75  }
76 
77  void TConfiguration::Print() const
78  {
79  // Inform the user what we are about to stream.
80 
81  TStreamerInfo *info = (TStreamerInfo*)fInfo;
82  TStreamerElement *aElement = fCompInfo->fElem;
83  TString sequenceType;
84  aElement->GetSequenceType(sequenceType);
85 
86  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
87  " %s, offset=%d (%s)\n",
88  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
89  aElement->ClassName(), fOffset, sequenceType.Data());
90  }
91 
92  void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
93  {
94  // Inform the user what we are about to stream.
95 
96  if (gDebug > 1) {
97  // Idea: We should print the name of the action function.
98  TStreamerInfo *info = (TStreamerInfo*)fInfo;
99  TStreamerElement *aElement = fCompInfo->fElem;
100  TString sequenceType;
101  aElement->GetSequenceType(sequenceType);
102 
103  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
104  " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
105  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
106  aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
107  }
108  }
109 
111  {
112  // Inform the user what we are about to stream.
113 
114  printf("TLoopConfiguration: unconfigured\n");
115  }
116 
117 
118  struct TGenericConfiguration : TConfiguration {
119  // Configuration of action using the legacy code.
120  // Mostly to cancel out the PrintDebug.
121  public:
122  TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset) {};
123  void PrintDebug(TBuffer &, void *) const {
124  // Since we call the old code, it will print the debug statement.
125  }
126 
127  virtual TConfiguration *Copy() { return new TGenericConfiguration(*this); }
128  };
129 
130  struct TBitsConfiguration : TConfiguration {
131  // Configuration of action handling kBits.
132  // In this case we need to know both the location
133  // of the member (fBits) and the start of the object
134  // (its TObject part to be exact).
135 
136  Int_t fObjectOffset; // Offset of the TObject part within the object
137 
138  TBitsConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset),fObjectOffset(0) {};
139  void PrintDebug(TBuffer &, void *) const {
140  TStreamerInfo *info = (TStreamerInfo*)fInfo;
141  TStreamerElement *aElement = fCompInfo->fElem;
142  TString sequenceType;
143  aElement->GetSequenceType(sequenceType);
144 
145  printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
146  " %s, offset=%d (%s)\n",
147  info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
148  aElement->ClassName(), fOffset, sequenceType.Data());
149  }
150 
151  void AddToOffset(Int_t delta)
152  {
153  // Add the (potentially negative) delta to all the configuration's offset. This is used by
154  // TBranchElement in the case of split sub-object.
155 
156  fOffset += delta;
157  fObjectOffset = 0;
158  }
159 
160  virtual TConfiguration *Copy() { return new TBitsConfiguration(*this); }
161 
162  };
163 
164  Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
165  {
166  char *obj = (char*)addr;
167  TGenericConfiguration *conf = (TGenericConfiguration*)config;
168  return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
169  }
170 
171  Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
172  {
173  char *obj = (char*)addr;
174  TGenericConfiguration *conf = (TGenericConfiguration*)config;
175  return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
176  }
177 
178  template <typename T>
180  {
181  T *x = (T*)( ((char*)addr) + config->fOffset );
182  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
183  buf >> *x;
184  return 0;
185  }
186 
187  void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
188  TBitsConfiguration *conf = (TBitsConfiguration*)config;
189  UShort_t pidf;
190  buf >> pidf;
191  pidf += buf.GetPidOffset();
192  TProcessID *pid = buf.ReadProcessID(pidf);
193  if (pid!=0) {
194  TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
195  UInt_t gpid = pid->GetUniqueID();
196  UInt_t uid;
197  if (gpid>=0xff) {
198  uid = obj->GetUniqueID() | 0xff000000;
199  } else {
200  uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
201  }
202  obj->SetUniqueID(uid);
203  pid->PutObjectWithID(obj);
204  }
205  }
206 
207  template <>
209  {
210  UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
211  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
212  // Idea: This code really belongs inside TBuffer[File]
213  buf >> *x;
214 
215  if ((*x & kIsReferenced) != 0) {
216  HandleReferencedTObject(buf,addr,config);
217  }
218  return 0;
219  }
220 
221  template <typename T>
223  {
224  T *x = (T*)( ((char*)addr) + config->fOffset );
225  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
226  buf << *x;
227  return 0;
228  }
229 
231  {
232  void *x = (void*)( ((char*)addr) + config->fOffset );
233  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
235  return 0;
236  }
237 
239  {
240  void *x = (void*)( ((char*)addr) + config->fOffset );
241  // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
243  return 0;
244  }
245 
246  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
247  * potentially can be used later for non-text streaming */
248  template<bool kIsTextT>
249  INLINE_TEMPLATE_ARGS Int_t WriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
250  {
251  TClass *cl = config->fCompInfo->fClass;
252  TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
254  TClass* vClass = proxy ? proxy->GetValueClass() : 0;
255  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
256  UInt_t ioffset = eoffset + config->fOffset;
257 
259  && proxy && vClass
260  && config->fInfo->GetStreamMemberWise()
261  && cl->CanSplit()
262  && !(strspn(config->fCompInfo->fElem->GetTitle(),"||") == 2)
263  && !(vClass->TestBit(TClass::kHasCustomStreamerMember)) ) {
264  // Let's save the collection member-wise.
265 
266  UInt_t pos = buf.WriteVersionMemberWise(config->fInfo->IsA(),kTRUE);
267  buf.WriteVersion( vClass, kFALSE );
268 
269  // TODO: subinfo used for WriteBufferSTL call, which is private for the moment
270  //TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
271 
272  //for (int k = 0; k < narr; ++k) {
273  char **contp = (char **)((char *)addr + ioffset);
274  for(int j=0;j<config->fCompInfo->fLength;++j) {
275  char *cont = contp[j];
276  TVirtualCollectionProxy::TPushPop helper( proxy, cont );
277  Int_t nobjects = cont ? proxy->Size() : 0;
278  buf << nobjects;
279 
280  // TODO: method is private, should be made accesible from here
281  // subinfo->WriteBufferSTL(buf,proxy,nobjects);
282  }
283  //}
284  buf.SetByteCount(pos,kTRUE);
285  return 0;
286  }
287  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(),kTRUE);
288  if (kIsTextT) {
289  // use same method which is used in kSTL
290  buf.WriteFastArray((void **)((char *) addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, 0);
291  } else
292  if (pstreamer == 0) {
293  //for (int k = 0; k < narr; ++k) {
294  char **contp = (char**)((char *) addr + ioffset);
295  for(int j=0; j<config->fCompInfo->fLength; ++j) {
296  char *cont = contp[j];
297  cl->Streamer( cont, buf );
298  }
299  // }
300  } else {
301  //for (int k = 0; k < narr; ++k) {
302  (*pstreamer)(buf,(char *) addr + ioffset, config->fCompInfo->fLength);
303  //}
304  }
305  buf.SetByteCount(pos,kTRUE);
306  return 0;
307  }
308 
309 
310  /** Direct copy of code from TStreamerInfo::WriteBufferAux,
311  * potentially can be used later for non-text streaming */
312  template<bool kIsTextT>
314  {
315  UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
316  UInt_t ioffset = eoffset + config->fOffset;
317 
318  if (!kIsTextT && config->fCompInfo->fStreamer) {
319  // Get any private streamer which was set for the data member.
320  TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
321  // -- We have a private streamer.
322  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
323  // Loop over the entries in the clones array or the STL container.
324  //for (int k = 0; k < narr; ++k) {
325  // Get a pointer to the counter for the varying length array.
326  Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
327 
328  // And call the private streamer, passing it the buffer, the object, and the counter.
329  (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
330  //} for k
331  buf.SetByteCount(pos, kTRUE);
332  // We are done, next streamer element.
333  return 0;
334  }
335 
336  // Get the class of the data member.
337  TClass* cl = config->fCompInfo->fClass;
338  // Which are we, an array of objects or an array of pointers to objects?
339  Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
340 
341  // By default assume the file version is the newest.
342  Int_t fileVersion = kMaxInt;
343 
344  if (!kIsTextT) {
345  // At this point we do *not* have a private streamer.
346  // Get the version of the file we are writing to.
347  TFile* file = (TFile*) buf.GetParent();
348  if (file) {
349  fileVersion = file->GetVersion();
350  }
351  }
352  // Write the class version to the buffer.
353  UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
354  if (fileVersion > 51508) {
355  // -- Newer versions allow polymorphic pointers to objects.
356  // Loop over the entries in the clones array or the STL container.
357  //for (int k = 0; k < narr; ++k) {
358  // Get the counter for the varying length array.
359  Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
360 
361  //b << vlen;
362  if (vlen) {
363  // Get a pointer to the array of pointers.
364  char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
365  // Loop over each element of the array of pointers to varying-length arrays.
366  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
367  if (!pp[ndx]) {
368  // -- We do not have a pointer to a varying-length array.
369  // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
370  // ::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()));
371  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());
372  continue;
373  }
374  if (!isPtrPtr) {
375  // -- We are a varying-length array of objects.
376  // Write the entire array of objects to the buffer.
377  // Note: Polymorphism is not allowed here.
378  buf.WriteFastArray(pp[ndx], cl, vlen, 0);
379  }
380  else {
381  // -- We are a varying-length array of pointers to objects.
382  // Write the entire array of object pointers to the buffer.
383  // Note: The object pointers are allowed to be polymorphic.
384  buf.WriteFastArray((void**) pp[ndx], cl, vlen, kFALSE, 0);
385  } // isPtrPtr
386  } // ndx
387  } else // vlen
388  if (kIsTextT) {
389  // special handling for the text-based streamers
390  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
391  buf.WriteFastArray((void *) 0, cl, -1, 0);
392  }
393  //} // k
394  }
395  else {
396  // -- Older versions do *not* allow polymorphic pointers to objects.
397  // Loop over the entries in the clones array or the STL container.
398  //for (int k = 0; k < narr; ++k) {
399  // Get the counter for the varying length array.
400  Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
401  //b << vlen;
402  if (vlen) {
403  // Get a pointer to the array of pointers.
404  char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
405  // -- Older versions do *not* allow polymorphic pointers to objects.
406  // Loop over each element of the array of pointers to varying-length arrays.
407  for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
408  if (!pp[ndx]) {
409  // -- We do not have a pointer to a varying-length array.
410  //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
411  // ::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()));
412  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());
413  continue;
414  }
415  if (!isPtrPtr) {
416  // -- We are a varying-length array of objects.
417  // Loop over the elements of the varying length array.
418  for (Int_t v = 0; v < vlen; ++v) {
419  // Write the object to the buffer.
420  cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
421  } // v
422  }
423  else {
424  // -- We are a varying-length array of pointers to objects.
425  // Loop over the elements of the varying length array.
426  for (Int_t v = 0; v < vlen; ++v) {
427  // Get a pointer to the object pointer.
428  char** r = (char**) pp[ndx];
429  // Write the object to the buffer.
430  cl->Streamer(r[v], buf);
431  } // v
432  } // isPtrPtr
433  } // ndx
434  } // vlen
435  //} // k
436  } // fileVersion
437  // Backpatch the byte count into the buffer.
438  buf.SetByteCount(pos, kTRUE);
439 
440  return 0;
441  }
442 
443 
444  class TConfWithFactor : public TConfiguration {
445  // Configuration object for the Float16/Double32 where a factor has been specified.
446  public:
447  Double_t fFactor;
448  Double_t fXmin;
449  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) {};
450  virtual TConfiguration *Copy() { return new TConfWithFactor(*this); }
451  };
452 
453  template <typename T>
455  {
456  // Stream a Float16 or Double32 where a factor has been specified.
457  //a range was specified. We read an integer and convert it back to a double.
458 
459  TConfWithFactor *conf = (TConfWithFactor *)config;
460  buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
461  return 0;
462  }
463 
464  class TConfNoFactor : public TConfiguration {
465  // Configuration object for the Float16/Double32 where a factor has been specified.
466  public:
467  Int_t fNbits;
468  TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
469  virtual TConfiguration *Copy() { return new TConfNoFactor(*this); }
470  };
471 
472  template <typename T>
474  {
475  // Stream a Float16 or Double32 where a factor has not been specified.
476 
477  TConfNoFactor *conf = (TConfNoFactor *)config;
478  Int_t nbits = conf->fNbits;
479 
480  buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
481  return 0;
482  }
483 
485  {
486  // Read in a TString object.
487 
488  // Idea: We could separate the TString Streamer in its two parts and
489  // avoid the if (buf.IsReading()) and try having it inlined.
490  ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
491  return 0;
492  }
493 
495  {
496  // Read in a TObject object part.
497 
498  // Idea: We could separate the TObject Streamer in its two parts and
499  // avoid the if (buf.IsReading()).
500  ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
501  return 0;
502  }
503 
504  INLINE_TEMPLATE_ARGS Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
505  {
506  // Read in a TNamed object part.
507  // Since the TNamed streamer is solely delegating back to the StreamerInfo we
508  // can skip the streamer.
509 
510  // Idea: We could extract the code from ReadClassBuffer and avoid one function
511  // code.
512  static const TClass *TNamed_cl = TNamed::Class();
513  return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
514  }
515 
516  class TConfigSTL : public TConfiguration {
517  // Configuration object for the kSTL case
518  private:
519  void Init() {
520  TVirtualCollectionProxy *proxy = fNewClass->GetCollectionProxy();
521  if (proxy) {
522  fCreateIterators = proxy->GetFunctionCreateIterators();
523  fCopyIterator = proxy->GetFunctionCopyIterator();
524  fDeleteIterator = proxy->GetFunctionDeleteIterator();
525  fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
526  }
527  }
528 
529  public:
530  TClass *fOldClass; // Class of the content on file
531  TClass *fNewClass; // Class of the content in memory.
532  TMemberStreamer *fStreamer;
533  const char *fTypeName; // Type name of the member as typed by ther user.
534  Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
535 
540 
541  TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
542  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
543  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
544 
545  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) :
546  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
547  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
548 
549  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) :
550  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
551  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
552 
553  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) :
554  TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
555  fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
556 
557  virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
558  };
559 
560  class TConfSTLWithFactor : public TConfigSTL {
561  // Configuration object for the Float16/Double32 where a factor has been specified.
562  public:
563  Double_t fFactor;
564  Double_t fXmin;
565  TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin) : TConfigSTL(*orig),fFactor(factor),fXmin(xmin) {};
566  virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
567  };
568 
569  class TConfSTLNoFactor : public TConfigSTL {
570  // Configuration object for the Float16/Double32 where a factor has been specified.
571  public:
572  Int_t fNbits;
573  TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
574  virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
575  };
576 
577  class TVectorLoopConfig : public TLoopConfiguration {
578  // Base class of the Configurations used in member wise streaming.
579  protected:
580  public:
581  Long_t fIncrement; // Either a value to increase the cursor by and
582  public:
583  TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
584  //virtual void PrintDebug(TBuffer &buffer, void *);
585  virtual ~TVectorLoopConfig() {};
586  void Print() const
587  {
588  printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
589  }
590 
591  void* GetFirstAddress(void *start, const void * /* end */) const
592  {
593  // Return the address of the first element of the collection.
594 
595  return start;
596  }
597 
598  virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
599  };
600 
601  class TAssocLoopConfig : public TLoopConfiguration {
602  // Base class of the Configurations used in member wise streaming.
603  public:
604  TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : TLoopConfiguration(proxy) {};
605  //virtual void PrintDebug(TBuffer &buffer, void *);
606  virtual ~TAssocLoopConfig() {};
607  void Print() const
608  {
609  printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
610  }
611  virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
612 
613  void* GetFirstAddress(void *start, const void * /* end */) const
614  {
615  // Return the address of the first element of the collection.
616 
617  R__ASSERT(0);
618 // char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
619 // void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
620 // arr0 = genloopconfig->fNext(iter,end_collection);
621 // if (iter != &iterator[0]) {
622 // genloopconfig->fDeleteIterator(iter);
623 // }
624  return start;
625  }
626  };
627 
628  class TGenericLoopConfig : public TLoopConfiguration {
629  // Configuration object for the generic case of member wise streaming looping.
630  private:
631  void Init(Bool_t read) {
632  if (fProxy) {
633  if (fProxy->HasPointers()) {
637  } else {
638  fNext = fProxy->GetFunctionNext(read);
639  fCopyIterator = fProxy->GetFunctionCopyIterator(read);
640  fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
641  }
642  }
643  }
644  public:
648 
649  TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : TLoopConfiguration(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
650  {
651  Init(read);
652  }
653  virtual ~TGenericLoopConfig() {};
654  void Print() const
655  {
656  printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
657  }
658  virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
659 
660  void* GetFirstAddress(void *start_collection, const void *end_collection) const
661  {
662  // Return the address of the first element of the collection.
663 
665  void *iter = fCopyIterator(&iterator,start_collection);
666  void *arr0 = fNext(iter,end_collection);
667  if (iter != &iterator[0]) {
668  fDeleteIterator(iter);
669  }
670  return arr0;
671  }
672  };
673 
675  {
676  // Collection was saved member-wise
677 
678  TConfigSTL *config = (TConfigSTL*)conf;
680 
681  if( vers >= 8 ) {
682 
683  TClass *oldClass = config->fOldClass;
684 
685  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
686  if (!oldProxy) {
687  // Missing information, broken file ... give up
688  return;
689  }
690  TClass *valueClass = oldProxy->GetValueClass();
691  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
692 
693  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
694  Int_t nobjects;
695  buf.ReadInt(nobjects);
696  void* alternative = oldProxy->Allocate(nobjects,true);
697  if (nobjects) {
698  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
699 
702  void *begin = &(startbuf[0]);
703  void *end = &(endbuf[0]);
704  config->fCreateIterators(alternative, &begin, &end, oldProxy);
705  // We can not get here with a split vector of pointer, so we can indeed assume
706  // that actions->fConfiguration != null.
707  buf.ApplySequence(*actions, begin, end);
708  if (begin != &(startbuf[0])) {
709  // assert(end != endbuf);
710  config->fDeleteTwoIterators(begin,end);
711  }
712  }
713  oldProxy->Commit(alternative);
714 
715  } else {
716 
717  TClass *oldClass = config->fOldClass;
718 
719  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
720  if (!oldProxy) {
721  // Missing information, broken file ... give up
722  return;
723  }
724 
725  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
726  Int_t nobjects;
727  buf.ReadInt(nobjects);
728  void* env = oldProxy->Allocate(nobjects,true);
729 
730  if (nobjects || vers < 7 ) {
731  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
732  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
733 
734  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
735  }
736  oldProxy->Commit(env);
737  }
738  }
739 
741  {
742  // Collection was saved member-wise
743 
744  TConfigSTL *config = (TConfigSTL*)conf;
746 
747  if( vers >= 8 ) {
748 
749  TClass *oldClass = config->fOldClass;
750 
751  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
752  if (!oldProxy) {
753  // Missing information, broken file ... give up
754  return;
755  }
756  TClass *valueClass = oldProxy->GetValueClass();
757  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
758 
759  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
760 
761  int objectSize = oldClass->Size();
762  char *obj = (char*)addr;
763  char *endobj = obj + conf->fLength*objectSize;
764 
765  for(; obj<endobj; obj+=objectSize) {
766  Int_t nobjects;
767  buf.ReadInt(nobjects);
768  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
769  void* alternative = oldProxy->Allocate(nobjects,true);
770  if (nobjects) {
773  void *begin = &(startbuf[0]);
774  void *end = &(endbuf[0]);
775  config->fCreateIterators(alternative, &begin, &end, oldProxy);
776  // We can not get here with a split vector of pointer, so we can indeed assume
777  // that actions->fConfiguration != null.
778  buf.ApplySequence(*actions, begin, end);
779  if (begin != &(startbuf[0])) {
780  // assert(end != endbuf);
781  config->fDeleteTwoIterators(begin,end);
782  }
783  }
784  oldProxy->Commit(alternative);
785  }
786 
787  } else {
788 
789  TClass *oldClass = config->fOldClass;
790 
791  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
792  if (!oldProxy) {
793  // Missing information, broken file ... give up
794  return;
795  }
796 
797  int objectSize = oldClass->Size();
798  char *obj = (char*)addr;
799  char *endobj = obj + conf->fLength*objectSize;
800 
801  for(; obj<endobj; obj+=objectSize) {
802  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
803  Int_t nobjects;
804  buf.ReadInt(nobjects);
805  void* env = oldProxy->Allocate(nobjects,true);
806 
807  if (nobjects || vers < 7 ) {
808  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
809  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
810 
811  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
812  }
813  oldProxy->Commit(env);
814  }
815  }
816  }
817 
819  {
820  // Collection was saved member-wise
821 
822  TConfigSTL *config = (TConfigSTL*)conf;
823 
825 
826  TClass *newClass = config->fNewClass;
827  TClass *oldClass = config->fOldClass;
828 
829  if( vers < 8 ) {
830  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
831  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
832  } else {
833 
834  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
835 
836  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
837  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
838 
839  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
840  Int_t nobjects;
841  buf.ReadInt(nobjects);
842  void* alternative = newProxy->Allocate(nobjects,true);
843  if (nobjects) {
844  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
847  void *begin = &(startbuf[0]);
848  void *end = &(endbuf[0]);
849  config->fCreateIterators( alternative, &begin, &end, newProxy);
850  // We can not get here with a split vector of pointer, so we can indeed assume
851  // that actions->fConfiguration != null.
852  buf.ApplySequence(*actions, begin, end);
853  if (begin != &(startbuf[0])) {
854  // assert(end != endbuf);
855  config->fDeleteTwoIterators(begin,end);
856  }
857  }
858  newProxy->Commit(alternative);
859  }
860  }
861 
863  {
864  // Collection was saved member-wise
865 
866  TConfigSTL *config = (TConfigSTL*)conf;
867 
869 
870  TClass *newClass = config->fNewClass;
871  TClass *oldClass = config->fOldClass;
872 
873  if( vers < 8 ) {
874  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
875  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
876  } else {
877 
878  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
879 
880  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
881  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
882 
883  int objectSize = newClass->Size();
884  char *obj = (char*)addr;
885  char *endobj = obj + conf->fLength*objectSize;
886 
887  for(; obj<endobj; obj+=objectSize) {
888  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
889  Int_t nobjects;
890  buf.ReadInt(nobjects);
891  void* alternative = newProxy->Allocate(nobjects,true);
892  if (nobjects) {
893  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
896  void *begin = &(startbuf[0]);
897  void *end = &(endbuf[0]);
898  config->fCreateIterators( alternative, &begin, &end, newProxy);
899  // We can not get here with a split vector of pointer, so we can indeed assume
900  // that actions->fConfiguration != null.
901  buf.ApplySequence(*actions, begin, end);
902  if (begin != &(startbuf[0])) {
903  // assert(end != endbuf);
904  config->fDeleteTwoIterators(begin,end);
905  }
906  }
907  newProxy->Commit(alternative);
908  }
909  }
910  }
911 
912 
913  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
914  {
915  TConfigSTL *config = (TConfigSTL*)conf;
916  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
917  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
918  }
919  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
920  {
921  TConfigSTL *config = (TConfigSTL*)conf;
922  (*config->fStreamer)(buf,addr,conf->fLength);
923  }
925  {
926  // case of old TStreamerInfo
927 
928  TConfigSTL *config = (TConfigSTL*)conf;
929  // Backward compatibility. Some TStreamerElement's where without
930  // Streamer but were not removed from element list
931  if (config->fIsSTLBase || vers == 0) {
932  buf.SetBufferOffset(start); //there is no byte count
933  }
934  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
935  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
936  }
938  {
939  // case of old TStreamerInfo
940 
941  TConfigSTL *config = (TConfigSTL*)conf;
942  // Backward compatibility. Some TStreamerElement's where without
943  // Streamer but were not removed from element list
944  if (config->fIsSTLBase || vers == 0) {
945  buf.SetBufferOffset(start); //there is no byte count
946  }
947  (*config->fStreamer)(buf,addr,conf->fLength);
948  }
949 
950  template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
951  void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
952  INLINE_TEMPLATE_ARGS Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
953  {
954  TConfigSTL *config = (TConfigSTL*)conf;
955  UInt_t start, count;
956  Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
957  if ( vers & TBufferFile::kStreamedMemberWise ) {
958  memberwise(buf,((char*)addr)+config->fOffset,config, vers);
959  } else {
960  objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
961  }
962  buf.CheckByteCount(start,count,config->fTypeName);
963  return 0;
964  }
965 
966  template <typename From, typename To>
967  struct ConvertBasicType {
968  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
969  {
970  // Simple conversion from a 'From' on disk to a 'To' in memory.
971  From temp;
972  buf >> temp;
973  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
974  return 0;
975  }
976  };
977 
978  template <typename To>
979  struct ConvertBasicType<BitsMarker,To> {
980  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
981  {
982  // Simple conversion from a 'From' on disk to a 'To' in memory
983  UInt_t temp;
984  buf >> temp;
985 
986  if ((temp & kIsReferenced) != 0) {
987  HandleReferencedTObject(buf,addr,config);
988  }
989 
990  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
991  return 0;
992  }
993  };
994 
995  template <typename From, typename To>
996  struct ConvertBasicType<WithFactorMarker<From>,To> {
997  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
998  {
999  // Simple conversion from a 'From' on disk to a 'To' in memory.
1000  TConfWithFactor *conf = (TConfWithFactor *)config;
1001  From temp;
1002  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1003  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1004  return 0;
1005  }
1006  };
1007 
1008  template <typename From, typename To>
1009  struct ConvertBasicType<NoFactorMarker<From>,To> {
1010  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1011  {
1012  // Simple conversion from a 'From' on disk to a 'To' in memory.
1013  TConfNoFactor *conf = (TConfNoFactor *)config;
1014  From temp;
1015  buf.ReadWithNbits(&temp, conf->fNbits);
1016  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1017  return 0;
1018  }
1019  };
1020 
1021  class TConfigurationPushDataCache : public TConfiguration {
1022  // Configuration object for the PushDataCache case.
1023  public:
1024  TVirtualArray *fOnfileObject;
1025 
1026  TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset) :
1027  TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1028  {}
1029 
1030  virtual void Print() const {
1031  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1032  if (fOnfileObject)
1033  printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1034  info->GetClass()->GetName(), fOffset);
1035  else
1036  printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1037  info->GetClass()->GetName(), fOffset);
1038  }
1039  virtual void PrintDebug(TBuffer &buffer, void *object) const {
1040  if (gDebug > 1) {
1041  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1042  printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1043  info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1044 
1045  }
1046  }
1047  };
1048 
1049  Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
1050  {
1051  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1052  auto onfileObject = config->fOnfileObject;
1053 
1054  // onfileObject->SetSize(1);
1055  b.PushDataCache( onfileObject );
1056 
1057  return 0;
1058  }
1059 
1060  Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1061  {
1062  TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1063  auto onfileObject = config->fOnfileObject;
1064 
1065  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1066  UInt_t n = proxy->Size();
1067 
1068  onfileObject->SetSize(n);
1069  b.PushDataCache( onfileObject );
1070 
1071  return 0;
1072  }
1073 
1074  Int_t PopDataCache(TBuffer &b, void *, const TConfiguration *)
1075  {
1076  b.PopDataCache();
1077  return 0;
1078  }
1079 
1080  Int_t PopDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *, const TConfiguration *)
1081  {
1082  b.PopDataCache();
1083  return 0;
1084  }
1085 
1086  class TConfigurationUseCache : public TConfiguration {
1087  // Configuration object for the UseCache case.
1088  public:
1089  TConfiguredAction fAction;
1090  Bool_t fNeedRepeat;
1091 
1092  TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1093  TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1094  virtual void PrintDebug(TBuffer &b, void *addr) const
1095  {
1096  if (gDebug > 1) {
1097  // Idea: We should print the name of the action function.
1098  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1099  TStreamerElement *aElement = fCompInfo->fElem;
1100  fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1101  " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1102  info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1103  aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1104  }
1105 
1106  }
1107  virtual ~TConfigurationUseCache() {};
1108  virtual TConfiguration *Copy() {
1109  TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1110  fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1111  return copy;
1112  }
1113  };
1114 
1115  INLINE_TEMPLATE_ARGS Int_t UseCache(TBuffer &b, void *addr, const TConfiguration *conf)
1116  {
1117  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1118 
1119  Int_t bufpos = b.Length();
1120  TVirtualArray *cached = b.PeekDataCache();
1121  if (cached==0) {
1122  TStreamerElement *aElement = conf->fCompInfo->fElem;
1123  TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1124  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1125  char *ptr = (char*)addr;
1126  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1127  } else {
1128  config->fAction(b, (*cached)[0]);
1129  }
1130  // Idea: Factor out this 'if' to a UseCacheRepeat function
1131  if (config->fNeedRepeat) {
1132  b.SetBufferOffset(bufpos);
1133  }
1134  return 0;
1135  }
1136 
1137  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1138  {
1139  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1140  Int_t bufpos = b.Length();
1141 
1142  TVirtualArray *cached = b.PeekDataCache();
1143  if (cached==0) {
1144  TStreamerElement *aElement = config->fCompInfo->fElem;
1145  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1146  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1147  char *ptr = (char*)start;
1148  UInt_t n = (((void**)end)-((void**)start));
1149  info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1150  } else {
1151  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1152  void *cached_start = (*cached)[0];
1153  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1154  config->fAction(b,cached_start,cached_end,&cached_config);
1155  }
1156  // Idea: Factor out this 'if' to a UseCacheRepeat function
1157  if (config->fNeedRepeat) {
1158  b.SetBufferOffset(bufpos);
1159  }
1160  return 0;
1161  }
1162 
1163  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1164  {
1165  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1166 
1167  Int_t bufpos = b.Length();
1168  TVirtualArray *cached = b.PeekDataCache();
1169  if (cached==0) {
1170  TStreamerElement *aElement = config->fCompInfo->fElem;
1171  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1172  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1173  char *ptr = (char*)start;
1174  UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1175  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1176  } else {
1177  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1178  void *cached_start = (*cached)[0];
1179  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1180  config->fAction(b,cached_start,cached_end,&cached_config);
1181  }
1182  // Idea: Factor out this 'if' to a UseCacheRepeat function
1183  if (config->fNeedRepeat) {
1184  b.SetBufferOffset(bufpos);
1185  }
1186  return 0;
1187  }
1188 
1189  INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1190  {
1191  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1192 
1193  Int_t bufpos = b.Length();
1194  TVirtualArray *cached = b.PeekDataCache();
1195  if (cached==0) {
1196  TStreamerElement *aElement = config->fCompInfo->fElem;
1197  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1198 
1199  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1200  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1201  UInt_t n = proxy->Size();
1202  info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1203  } else {
1204  TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1205  void *cached_start = (*cached)[0];
1206  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1207  config->fAction(b,cached_start,cached_end,&cached_config);
1208  }
1209  // Idea: Factor out this 'if' to a UseCacheRepeat function
1210  if (config->fNeedRepeat) {
1211  b.SetBufferOffset(bufpos);
1212  }
1213  return 0;
1214  }
1215 
1216  // Support for collections.
1217 
1218  Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1219  {
1220  Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1221  return 0;
1222  }
1223 
1224  Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1225  {
1226  Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1227  return 0;
1228  }
1229 
1231 
1233  {
1235  return kVectorLooper;
1236  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1240  || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1241  return kAssociativeLooper;
1242  } else {
1243  return kGenericLooper;
1244  }
1245  }
1246 
1247  struct VectorLooper {
1248 
1249  template <typename T>
1250  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1251  {
1252  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1253  iter = (char*)iter + config->fOffset;
1254  end = (char*)end + config->fOffset;
1255  for(; iter != end; iter = (char*)iter + incr ) {
1256  T *x = (T*) ((char*) iter);
1257  buf >> *x;
1258  }
1259  return 0;
1260  }
1261 
1262  template <typename From, typename To>
1263  struct ConvertBasicType {
1264  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1265  {
1266  // Simple conversion from a 'From' on disk to a 'To' in memory.
1267  From temp;
1268  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1269  iter = (char*)iter + config->fOffset;
1270  end = (char*)end + config->fOffset;
1271  for(; iter != end; iter = (char*)iter + incr ) {
1272  buf >> temp;
1273  *(To*)( ((char*)iter) ) = (To)temp;
1274  }
1275  return 0;
1276  }
1277  };
1278 
1279  template <typename To>
1280  struct ConvertBasicType<BitsMarker,To> {
1281  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1282  {
1283  // Simple conversion from a 'From' on disk to a 'To' in memory.
1284  UInt_t temp;
1285  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1286  iter = (char*)iter + config->fOffset;
1287  end = (char*)end + config->fOffset;
1288  for(; iter != end; iter = (char*)iter + incr ) {
1289  buf >> temp;
1290 
1291  if ((temp & kIsReferenced) != 0) {
1292  HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1293  }
1294 
1295  *(To*)( ((char*)iter) ) = (To)temp;
1296  }
1297  return 0;
1298  }
1299  };
1300 
1301  template <typename From, typename To>
1302  struct ConvertBasicType<WithFactorMarker<From>,To> {
1303  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1304  {
1305  // Simple conversion from a 'From' on disk to a 'To' in memory.
1306  TConfWithFactor *conf = (TConfWithFactor *)config;
1307  From temp;
1308  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1309  iter = (char*)iter + config->fOffset;
1310  end = (char*)end + config->fOffset;
1311  for(; iter != end; iter = (char*)iter + incr ) {
1312  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1313  *(To*)( ((char*)iter) ) = (To)temp;
1314  }
1315  return 0;
1316  }
1317  };
1318 
1319  template <typename From, typename To>
1320  struct ConvertBasicType<NoFactorMarker<From>,To> {
1321  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1322  {
1323  // Simple conversion from a 'From' on disk to a 'To' in memory.
1324  TConfNoFactor *conf = (TConfNoFactor *)config;
1325  From temp;
1326  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1327  iter = (char*)iter + config->fOffset;
1328  end = (char*)end + config->fOffset;
1329  for(; iter != end; iter = (char*)iter + incr ) {
1330  buf.ReadWithNbits(&temp, conf->fNbits);
1331  *(To*)( ((char*)iter) ) = (To)temp;
1332  }
1333  return 0;
1334  }
1335  };
1336 
1337  template <typename T>
1338  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1339  {
1340  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1341  iter = (char*)iter + config->fOffset;
1342  end = (char*)end + config->fOffset;
1343  for(; iter != end; iter = (char*)iter + incr ) {
1344  T *x = (T*) ((char*) iter);
1345  buf << *x;
1346  }
1347  return 0;
1348  }
1349 
1350  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1351  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1352  {
1353  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1354  //Idea: can we factor out the addition of fOffset
1355  // iter = (char*)iter + config->fOffset;
1356  for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1357  iter_action(buf, iter, config);
1358  }
1359  return 0;
1360  }
1361 
1362  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1363  {
1364  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1365  // punt.
1366 
1367  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1368  UInt_t n = (((char*)end)-((char*)start))/incr;
1369  char **arrptr = new char*[n];
1370  UInt_t i = 0;
1371  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1372  arrptr[i] = (char*)iter;
1373  }
1374  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1375  delete [] arrptr;
1376 
1377  // // Idea: need to cache this result!
1378  // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1379  // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1380  //
1381  // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1382  // *TClass *cle = aElement->GetNewBaseClass();
1383  // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1384  //
1385  // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1386  //
1387  // actions->ReadBuffer(b,start,end);
1388  // delete actions;
1389 
1390  // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1391  // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1392  // {
1393  // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1394  //
1395  // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1396  // }
1397  return 0;
1398  }
1399 
1400  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1401  {
1402  // Well the implementation is non trivial. For now punt.
1403 
1404  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1405  UInt_t n = (((char*)end)-((char*)start))/incr;
1406  char **arrptr = new char*[n];
1407  UInt_t i = 0;
1408  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1409  arrptr[i] = (char*)iter;
1410  }
1411  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1412  delete [] arrptr;
1413  return 0;
1414  }
1415 
1416  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1417  {
1418  // Well the implementation is non trivial. For now punt.
1419 
1420  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1421  UInt_t n = (((char*)end)-((char*)start))/incr;
1422  char **arrptr = new char*[n];
1423  UInt_t i = 0;
1424  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1425  arrptr[i] = (char*)iter;
1426  }
1427  ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1428  delete [] arrptr;
1429  return 0;
1430  }
1431 
1432  template <typename T>
1433  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1434  {
1435  // Collection of numbers. Memberwise or not, it is all the same.
1436 
1437  TConfigSTL *config = (TConfigSTL*)conf;
1438  UInt_t start, count;
1439  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1440 
1441  std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1442  Int_t nvalues;
1443  buf.ReadInt(nvalues);
1444  vec->resize(nvalues);
1445 
1446 #ifdef R__VISUAL_CPLUSPLUS
1447  if (nvalues <= 0) {
1448  buf.CheckByteCount(start,count,config->fTypeName);
1449  return 0;
1450  }
1451 #endif
1452  T *begin = &(*vec->begin());
1453  buf.ReadFastArray(begin, nvalues);
1454 
1455  buf.CheckByteCount(start,count,config->fTypeName);
1456  return 0;
1457  }
1458 
1459  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1460  {
1461  // Collection of numbers. Memberwise or not, it is all the same.
1462 
1463  TConfigSTL *config = (TConfigSTL*)conf;
1464  UInt_t start, count;
1465  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1466 
1467  std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1468  Int_t nvalues;
1469  buf.ReadInt(nvalues);
1470  vec->resize(nvalues);
1471 
1472  bool *items = new bool[nvalues];
1473  buf.ReadFastArray(items, nvalues);
1474  for(Int_t i = 0 ; i < nvalues; ++i) {
1475  (*vec)[i] = items[i];
1476  }
1477  delete [] items;
1478 
1479  // We could avoid the call to ReadFastArray, and we could
1480  // the following, however this breaks TBufferXML ...
1481  // for(Int_t i = 0 ; i < nvalues; ++i) {
1482  // bool tmp; buf >> tmp;
1483  // (*vec)[i] = tmp;
1484  // }
1485 
1486  buf.CheckByteCount(start,count,config->fTypeName);
1487  return 0;
1488  }
1489 
1490  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1491  {
1492  // Collection of numbers. Memberwise or not, it is all the same.
1493 
1494  TConfigSTL *config = (TConfigSTL*)conf;
1495  UInt_t start, count;
1496  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1497 
1498  std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1499  Int_t nvalues;
1500  buf.ReadInt(nvalues);
1501  vec->resize(nvalues);
1502 
1503 #ifdef R__VISUAL_CPLUSPLUS
1504  if (nvalues <= 0) {
1505  buf.CheckByteCount(start,count,config->fTypeName);
1506  return 0;
1507  }
1508 #endif
1509  float *begin = &(*vec->begin());
1510  buf.ReadFastArrayFloat16(begin, nvalues);
1511 
1512  buf.CheckByteCount(start,count,config->fTypeName);
1513  return 0;
1514  }
1515 
1516  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1517  {
1518  // Collection of numbers. Memberwise or not, it is all the same.
1519 
1520  TConfigSTL *config = (TConfigSTL*)conf;
1521  UInt_t start, count;
1522  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1523 
1524  std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1525  Int_t nvalues;
1526  buf.ReadInt(nvalues);
1527  vec->resize(nvalues);
1528 
1529 #ifdef R__VISUAL_CPLUSPLUS
1530  if (nvalues <= 0) {
1531  buf.CheckByteCount(start,count,config->fTypeName);
1532  return 0;
1533  }
1534 #endif
1535  double *begin = &(*vec->begin());
1536  buf.ReadFastArrayDouble32(begin, nvalues);
1537 
1538  buf.CheckByteCount(start,count,config->fTypeName);
1539  return 0;
1540  }
1541 
1542  template <typename From, typename To>
1543  struct ConvertCollectionBasicType {
1544  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1545  {
1546  // Collection of numbers. Memberwise or not, it is all the same.
1547 
1548  TConfigSTL *config = (TConfigSTL*)conf;
1549  UInt_t start, count;
1550  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1551 
1552  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1553  Int_t nvalues;
1554  buf.ReadInt(nvalues);
1555  vec->resize(nvalues);
1556 
1557  From *temp = new From[nvalues];
1558  buf.ReadFastArray(temp, nvalues);
1559  for(Int_t ind = 0; ind < nvalues; ++ind) {
1560  (*vec)[ind] = (To)temp[ind];
1561  }
1562  delete [] temp;
1563 
1564  buf.CheckByteCount(start,count,config->fTypeName);
1565  return 0;
1566  }
1567  };
1568 
1569  template <typename From, typename To>
1570  struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
1571  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1572  {
1573  // Collection of numbers. Memberwise or not, it is all the same.
1574 
1575  TConfigSTL *config = (TConfigSTL*)conf;
1576  UInt_t start, count;
1577  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1578 
1579  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1580  Int_t nvalues;
1581  buf.ReadInt(nvalues);
1582  vec->resize(nvalues);
1583 
1584  From *temp = new From[nvalues];
1585  buf.ReadFastArrayWithNbits(temp, nvalues, 0);
1586  for(Int_t ind = 0; ind < nvalues; ++ind) {
1587  (*vec)[ind] = (To)temp[ind];
1588  }
1589  delete [] temp;
1590 
1591  buf.CheckByteCount(start,count,config->fTypeName);
1592  return 0;
1593  }
1594  };
1595 
1596  template <typename To>
1597  static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1598  {
1599  // Collection of numbers. Memberwise or not, it is all the same.
1600 
1601  TConfigSTL *config = (TConfigSTL*)conf;
1602  UInt_t start, count;
1603  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1604 
1605  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1606  Int_t nvalues;
1607  buf.ReadInt(nvalues);
1608  vec->resize(nvalues);
1609 
1610  Double32_t *temp = new Double32_t[nvalues];
1611  buf.ReadFastArrayDouble32(temp, nvalues);
1612  for(Int_t ind = 0; ind < nvalues; ++ind) {
1613  (*vec)[ind] = (To)temp[ind];
1614  }
1615  delete [] temp;
1616 
1617  buf.CheckByteCount(start,count,config->fTypeName);
1618  return 0;
1619  }
1620 
1621  };
1622 
1623  struct VectorPtrLooper {
1624 
1625  template <typename T>
1626  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1627  {
1628  const Int_t offset = config->fOffset;
1629 
1630  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1631  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
1632  buf >> *x;
1633  }
1634  return 0;
1635  }
1636 
1637  template <typename From, typename To>
1638  struct ConvertBasicType {
1639  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1640  {
1641  // Simple conversion from a 'From' on disk to a 'To' in memory.
1642  From temp;
1643  const Int_t offset = config->fOffset;
1644  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1645  buf >> temp;
1646  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1647  *x = (To)temp;
1648  }
1649  return 0;
1650  }
1651  };
1652 
1653  template <typename To>
1654  struct ConvertBasicType<BitsMarker,To> {
1655  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1656  {
1657  // Simple conversion from a 'From' on disk to a 'To' in memory.
1658  UInt_t temp;
1659  const Int_t offset = config->fOffset;
1660  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1661  buf >> temp;
1662 
1663  if ((temp & kIsReferenced) != 0) {
1664  HandleReferencedTObject(buf,*(void**)iter,config);
1665  }
1666 
1667  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1668  *x = (To)temp;
1669  }
1670  return 0;
1671  }
1672  };
1673 
1674  template <typename From, typename To>
1675  struct ConvertBasicType<WithFactorMarker<From>,To> {
1676  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1677  {
1678  // Simple conversion from a 'From' on disk to a 'To' in memory.
1679  TConfWithFactor *conf = (TConfWithFactor *)config;
1680  From temp;
1681  const Int_t offset = config->fOffset;
1682  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1683  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1684  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1685  *x = (To)temp;
1686  }
1687  return 0;
1688  }
1689  };
1690 
1691  template <typename From, typename To>
1692  struct ConvertBasicType<NoFactorMarker<From>,To> {
1693  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1694  {
1695  // Simple conversion from a 'From' on disk to a 'To' in memory.
1696  TConfNoFactor *conf = (TConfNoFactor *)config;
1697  From temp;
1698  const Int_t offset = config->fOffset;
1699  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1700  buf.ReadWithNbits(&temp, conf->fNbits);
1701  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1702  *x = (To)temp;
1703  }
1704  return 0;
1705  }
1706  };
1707 
1708  template <typename T>
1709  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1710  {
1711  const Int_t offset = config->fOffset;
1712 
1713  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1714  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
1715  buf << *x;
1716  }
1717  return 0;
1718  }
1719 
1720  template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
1721  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
1722  {
1723  for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
1724  action(buf, *(void**)iter, config);
1725  }
1726  return 0;
1727  }
1728 
1729  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
1730  {
1731  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1732  // punt.
1733 
1734  return GenericRead(buf,start,end,config);
1735  }
1736 
1737  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1738  {
1739  Int_t n = ( ((void**)end) - ((void**)iter) );
1740  char **arr = (char**)iter;
1741  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1742  }
1743 
1744  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1745  {
1746  Int_t n = ( ((void**)end) - ((void**)iter) );
1747  char **arr = (char**)iter;
1748  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1749  }
1750 
1751  };
1752 
1753  struct AssociativeLooper {
1754 
1755  template <typename T>
1756  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
1757  {
1758  buf.ReadFastArray((T*)addr, nvalues);
1759  }
1760 
1761  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
1762  {
1763  buf.ReadFastArrayFloat16((float*)addr, nvalues);
1764  }
1765 
1766  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
1767  {
1768  buf.ReadFastArrayDouble32((double*)addr, nvalues);
1769  }
1770 
1771  template <typename T,void (*action)(TBuffer&,void *,Int_t)>
1772  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
1773  {
1774  // Collection of numbers. Memberwise or not, it is all the same.
1775 
1776  TConfigSTL *config = (TConfigSTL*)conf;
1777  UInt_t start, count;
1778  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1779 
1780  TClass *newClass = config->fNewClass;
1781  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1782  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
1783 
1784  Int_t nvalues;
1785  buf.ReadInt(nvalues);
1786  void* alternative = newProxy->Allocate(nvalues,true);
1787  if (nvalues) {
1790  void *begin = &(startbuf[0]);
1791  void *end = &(endbuf[0]);
1792  config->fCreateIterators(alternative, &begin, &end, newProxy);
1793  // We can not get here with a split vector of pointer, so we can indeed assume
1794  // that actions->fConfiguration != null.
1795 
1796  action(buf,begin,nvalues);
1797 
1798  if (begin != &(startbuf[0])) {
1799  // assert(end != endbuf);
1800  config->fDeleteTwoIterators(begin,end);
1801  }
1802  }
1803  newProxy->Commit(alternative);
1804 
1805  buf.CheckByteCount(start,count,config->fTypeName);
1806  return 0;
1807  }
1808 
1809  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1810  {
1811  return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
1812  }
1813 
1814  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1815  {
1816  return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
1817  }
1818 
1819  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1820  {
1821  return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
1822  }
1823 
1824  template <typename T>
1825  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1826  {
1827  return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
1828  }
1829 
1830  template <typename From, typename To>
1831  struct ConvertRead {
1832  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1833  {
1834  From *temp = new From[nvalues];
1835  buf.ReadFastArray(temp, nvalues);
1836  To *vec = (To*)addr;
1837  for(Int_t ind = 0; ind < nvalues; ++ind) {
1838  vec[ind] = (To)temp[ind];
1839  }
1840  delete [] temp;
1841  }
1842  };
1843 
1844  template <typename From, typename To>
1845  struct ConvertRead<NoFactorMarker<From>,To> {
1846  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1847  {
1848  From *temp = new From[nvalues];
1849  buf.ReadFastArrayWithNbits(temp, nvalues,0);
1850  To *vec = (To*)addr;
1851  for(Int_t ind = 0; ind < nvalues; ++ind) {
1852  vec[ind] = (To)temp[ind];
1853  }
1854  delete [] temp;
1855  }
1856  };
1857 
1858  template <typename From, typename To>
1859  struct ConvertRead<WithFactorMarker<From>,To> {
1860  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1861  {
1862  From *temp = new From[nvalues];
1863  double factor,min; // needs to be initialized.
1864  buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
1865  To *vec = (To*)addr;
1866  for(Int_t ind = 0; ind < nvalues; ++ind) {
1867  vec[ind] = (To)temp[ind];
1868  }
1869  delete [] temp;
1870  }
1871  };
1872 
1873  template <typename From, typename To>
1874  struct ConvertCollectionBasicType {
1875  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1876  {
1877  return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
1878  }
1879  };
1880 
1881  };
1882 
1883  struct GenericLooper {
1884 
1885  template <typename T>
1886  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1887  {
1888  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1889 
1890  Next_t next = loopconfig->fNext;
1891  const Int_t offset = config->fOffset;
1892 
1894  void *iter = loopconfig->fCopyIterator(iterator,start);
1895  void *addr;
1896  while( (addr = next(iter,end)) ) {
1897  T *x = (T*)( ((char*)addr) + offset );
1898  buf >> *x;
1899  }
1900  if (iter != &iterator[0]) {
1901  loopconfig->fDeleteIterator(iter);
1902  }
1903  return 0;
1904  }
1905 
1906  template <typename T>
1907  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1908  {
1909  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1910 
1911  Next_t next = loopconfig->fNext;
1912  const Int_t offset = config->fOffset;
1913 
1915  void *iter = loopconfig->fCopyIterator(iterator,start);
1916  void *addr;
1917  while( (addr = next(iter,end)) ) {
1918  T *x = (T*)( ((char*)addr) + offset );
1919  buf << *x;
1920  }
1921  if (iter != &iterator[0]) {
1922  loopconfig->fDeleteIterator(iter);
1923  }
1924  return 0;
1925  }
1926 
1927  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1928  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1929  {
1930  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1931 
1932  // const Int_t offset = config->fOffset;
1933  Next_t next = loopconfig->fNext;
1934 
1936  void *iter = loopconfig->fCopyIterator(&iterator,start);
1937  void *addr;
1938  while( (addr = next(iter,end)) ) {
1939  iter_action(buf, addr, config);
1940  }
1941  if (iter != &iterator[0]) {
1942  loopconfig->fDeleteIterator(iter);
1943  }
1944  return 0;
1945  }
1946 
1947  template <typename From, typename To>
1948  struct Generic {
1949  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1950  {
1951  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1952 
1953  const Int_t offset = config->fOffset;
1954  Next_t next = loopconfig->fNext;
1955 
1957  void *iter = loopconfig->fCopyIterator(&iterator,start);
1958  void *addr;
1959  while( (addr = next(iter,end)) ) {
1960  To *x = (To*)( ((char*)addr) + offset );
1961  *x = (To)(*items);
1962  ++items;
1963  }
1964  if (iter != &iterator[0]) {
1965  loopconfig->fDeleteIterator(iter);
1966  }
1967  }
1968  };
1969 
1970  template <typename From, typename To>
1971  struct Numeric {
1972  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
1973  {
1974  // The difference with ConvertAction is that we can modify the start
1975  // iterator and skip the copy. We also never have an offset.
1976 
1977  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1978  Next_t next = loopconfig->fNext;
1979 
1980  void *iter = start;
1981  void *addr;
1982  while( (addr = next(iter,end)) ) {
1983  To *x = (To*)(addr);
1984  *x = (To)(*items);
1985  ++items;
1986  }
1987  }
1988  };
1989 
1990  template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
1991  struct ConvertBasicType {
1992  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1993  {
1994  // Simple conversion from a 'From' on disk to a 'To' in memory.
1995 
1996  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1997  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
1998  Int_t nvalues = proxy->Size();
1999 
2000  From *items = new From[nvalues];
2001  buf.ReadFastArray(items, nvalues);
2002  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2003  delete [] items;
2004  return 0;
2005  }
2006  };
2007 
2008  template <typename To>
2009  struct ConvertBasicType<BitsMarker, To, Generic> {
2010  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2011  {
2012  // Simple conversion from a 'From' on disk to a 'To' in memory.
2013 
2014  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2015  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2016  Int_t nvalues = proxy->Size();
2017 
2018  UInt_t *items_storage = new UInt_t[nvalues];
2019  UInt_t *items = items_storage;
2020 
2021  const Int_t offset = config->fOffset;
2022  Next_t next = loopconfig->fNext;
2023 
2025  void *iter = loopconfig->fCopyIterator(&iterator,start);
2026  void *addr;
2027  while( (addr = next(iter,end)) ) {
2028  buf >> (*items);
2029  if (((*items) & kIsReferenced) != 0) {
2030  HandleReferencedTObject(buf, addr, config);
2031  }
2032  To *x = (To*)( ((char*)addr) + offset );
2033  *x = (To)(*items);
2034  ++items;
2035  }
2036  if (iter != &iterator[0]) {
2037  loopconfig->fDeleteIterator(iter);
2038  }
2039 
2040  delete [] items_storage;
2041  return 0;
2042  }
2043  };
2044 
2045  template <typename From, typename To, template <typename F, typename T> class Converter >
2046  struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2047  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2048  {
2049  // Simple conversion from a 'From' on disk to a 'To' in memory.
2050 
2051  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2052  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2053  Int_t nvalues = proxy->Size();
2054 
2055  TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2056 
2057  From *items = new From[nvalues];
2058  buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2059  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2060  delete [] items;
2061  return 0;
2062  }
2063  };
2064 
2065  template <typename From, typename To, template <typename F, typename T> class Converter >
2066  struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2067  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2068  {
2069  // Simple conversion from a 'From' on disk to a 'To' in memory.
2070 
2071  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2072  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2073  Int_t nvalues = proxy->Size();
2074 
2075  TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2076 
2077  From *items = new From[nvalues];
2078  buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2079  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2080  delete [] items;
2081  return 0;
2082  }
2083  };
2084 
2085  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2086  {
2087  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2088  // punt.
2089 
2090  return GenericRead(buf,start,end,loopconfig, config);
2091  }
2092 
2093  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2094  {
2095  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2096  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2097  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2098  }
2099 
2100  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2101  {
2102  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2103  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2104  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2105  }
2106 
2107  template <typename T>
2108  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2109  {
2110  buf >> *(T*)addr;
2111  }
2112 
2113  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2114  {
2115  buf.ReadWithNbits((float*)addr,12);
2116  }
2117 
2118  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2119  {
2120  //we read a float and convert it to double
2121  Float_t afloat;
2122  buf >> afloat;
2123  *(double*)addr = (Double_t)afloat;
2124  }
2125 
2126  template <typename ActionHolder>
2127  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2128  {
2129  // Collection of numbers. Memberwise or not, it is all the same.
2130 
2131  TConfigSTL *config = (TConfigSTL*)conf;
2132  UInt_t start, count;
2133  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2134 
2135  TClass *newClass = config->fNewClass;
2136  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2137  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2138 
2139  Int_t nvalues;
2140  buf.ReadInt(nvalues);
2141  void* alternative = newProxy->Allocate(nvalues,true);
2142  if (nvalues) {
2145  void *begin = &(startbuf[0]);
2146  void *end = &(endbuf[0]);
2147  config->fCreateIterators(alternative, &begin, &end, newProxy);
2148  // We can not get here with a split vector of pointer, so we can indeed assume
2149  // that actions->fConfiguration != null.
2150 
2151  TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2152  ActionHolder::Action(buf,begin,end,&loopconf,config);
2153 
2154  if (begin != &(startbuf[0])) {
2155  // assert(end != endbuf);
2156  config->fDeleteTwoIterators(begin,end);
2157  }
2158  }
2159  newProxy->Commit(alternative);
2160 
2161  buf.CheckByteCount(start,count,config->fTypeName);
2162  return 0;
2163  }
2164 
2165  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2166  {
2167  return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2168  }
2169 
2170  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2171  {
2172  return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2173  }
2174 
2175  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2176  {
2177  return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2178  // Could also use:
2179  // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2180  }
2181 
2182  template <typename T>
2183  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2184  {
2185  return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2186  }
2187 
2188  template <typename From, typename To>
2189  struct ConvertCollectionBasicType {
2190  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2191  {
2192  // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2193  return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2194  }
2195  };
2196 
2197  };
2198 }
2199 
2200 template <typename Looper, typename From>
2201 static TConfiguredAction GetCollectionReadConvertAction(Int_t newtype, TConfiguration *conf)
2202 {
2203  switch (newtype) {
2204  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2205  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2206  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2207  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2208  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2209  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2210  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2211  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2212  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2213  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2214  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2215  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2216  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2217  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2218  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2219  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2220  default:
2221  return TConfiguredAction( Looper::GenericRead, conf );
2222  break;
2223  }
2224  R__ASSERT(0); // We should never be here
2225  return TConfiguredAction();
2226 }
2227 
2228 template <class Looper>
2230 {
2231  // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2232 
2233  switch (type) {
2234  // Read basic types.
2235  case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2236  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2237  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2238  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2239  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2240  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2241  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2242  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2243  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2244  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2245  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2246  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2247  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2248  case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2249  case TStreamerInfo::kFloat16: {
2250  TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2251  delete conf;
2252  return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2253  // if (element->GetFactor() != 0) {
2254  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2255  // } else {
2256  // Int_t nbits = (Int_t)element->GetXmin();
2257  // if (!nbits) nbits = 12;
2258  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2259  // }
2260  break;
2261  }
2262  case TStreamerInfo::kDouble32: {
2263  TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2264  delete conf;
2265  return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2266  // if (element->GetFactor() != 0) {
2267  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2268  // } else {
2269  // Int_t nbits = (Int_t)element->GetXmin();
2270  // if (!nbits) {
2271  // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2272  // } else {
2273  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2274  // }
2275  // }
2276  break;
2277  }
2278  }
2279  Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2280  R__ASSERT(0); // We should never be here
2281  return TConfiguredAction();
2282 }
2283 
2284 template <typename Looper, typename From>
2285 static TConfiguredAction GetConvertCollectionReadActionFrom(Int_t newtype, TConfiguration *conf)
2286 {
2287  switch (newtype) {
2288  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2289  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2290  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2291  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2292  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2293  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2294  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2295  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2296  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2297  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2298  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2299  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2300  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2301  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2302  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2303  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2304  default:
2305  break;
2306  }
2307  R__ASSERT(0); // We should never be here
2308  return TConfiguredAction();
2309 }
2310 
2311 template <typename Looper>
2312 static TConfiguredAction GetConvertCollectionReadAction(Int_t oldtype, Int_t newtype, TConfiguration *conf)
2313 {
2314  switch (oldtype) {
2315  case TStreamerInfo::kBool:
2316  return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2317  break;
2318  case TStreamerInfo::kChar:
2319  return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2320  break;
2321  case TStreamerInfo::kShort:
2322  return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2323  break;
2324  case TStreamerInfo::kInt:
2325  return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2326  break;
2327  case TStreamerInfo::kLong:
2328  return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2329  break;
2331  return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2332  break;
2333  case TStreamerInfo::kFloat:
2334  return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2335  break;
2337  return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2338  break;
2339  case TStreamerInfo::kUChar:
2340  return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2341  break;
2343  return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2344  break;
2345  case TStreamerInfo::kUInt:
2346  return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2347  break;
2348  case TStreamerInfo::kULong:
2349  return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2350  break;
2352  return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2353  break;
2355  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2356  break;
2358  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2359  break;
2360  case TStreamerInfo::kBits:
2361  Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2362  break;
2363  default:
2364  break;
2365  }
2366  R__ASSERT(0); // We should never be here
2367  return TConfiguredAction();
2368 }
2369 
2370 template <class Looper>
2372 {
2373  switch (type) {
2374  // Read basic types.
2375  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2376  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2377  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2378  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2379  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2380  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2381  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2382  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2383  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2384  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2385  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2386  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2387  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2388  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2389  case TStreamerInfo::kFloat16: {
2390  if (element->GetFactor() != 0) {
2391  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2392  } else {
2393  Int_t nbits = (Int_t)element->GetXmin();
2394  if (!nbits) nbits = 12;
2395  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2396  }
2397  break;
2398  }
2399  case TStreamerInfo::kDouble32: {
2400  if (element->GetFactor() != 0) {
2401  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2402  } else {
2403  Int_t nbits = (Int_t)element->GetXmin();
2404  if (!nbits) {
2405  return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2406  } else {
2407  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2408  }
2409  }
2410  break;
2411  }
2412  case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2413  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2414  // Streamer alltogether.
2415  case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2416  case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2420  case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2421  case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2422 
2423  // Conversions.
2425  return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2426  break;
2428  return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2429  break;
2431  return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2432  break;
2434  return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2435  break;
2437  return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2438  break;
2440  return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2441  break;
2443  return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2444  break;
2446  return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2447  break;
2449  return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2450  break;
2452  return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2453  break;
2455  return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2456  break;
2458  return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2459  break;
2461  return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2462  break;
2464  return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2465  break;
2467  if (element->GetFactor() != 0) {
2468  return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2469  } else {
2470  Int_t nbits = (Int_t)element->GetXmin();
2471  if (!nbits) nbits = 12;
2472  return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2473  }
2474  break;
2475  }
2477  if (element->GetFactor() != 0) {
2478  return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2479  } else {
2480  Int_t nbits = (Int_t)element->GetXmin();
2481  if (!nbits) {
2482  return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2483  } else {
2484  return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2485  }
2486  }
2487  break;
2488  }
2489  default:
2490  return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2491  break;
2492  }
2493  R__ASSERT(0); // We should never be here
2494  return TConfiguredAction();
2495 }
2496 
2497 template <class Looper>
2499  switch (type) {
2500  // read basic types
2501  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2502  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2503  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2504  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2505  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2506  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2507  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2508  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2509  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2510  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2511  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2512  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2513  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2514  // the simple type missing are kBits and kCounter.
2515  default:
2516  return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2517  }
2518  R__ASSERT(0); // We should never be here
2519  return TConfiguredAction();
2520 }
2521 
2522 
2523 ////////////////////////////////////////////////////////////////////////////////
2524 /// loop on the TStreamerElement list
2525 /// regroup members with same type
2526 /// Store predigested information into local arrays. This saves a huge amount
2527 /// of time compared to an explicit iteration on all elements.
2528 
2530 {
2531  if (IsCompiled()) {
2532  //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
2533  return;
2534  }
2536 
2537  // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
2538 
2539  // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
2540  fOptimized = kFALSE;
2541  fNdata = 0;
2542  fNfulldata = 0;
2543 
2544  TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
2545  if (fNumber >= infos->GetSize()) {
2546  infos->AddAtAndExpand(this, fNumber);
2547  } else {
2548  if (!infos->At(fNumber)) {
2549  infos->AddAt(this, fNumber);
2550  }
2551  }
2552 
2553  assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
2554 
2555 
2556  Int_t ndata = fElements->GetEntries();
2557 
2558 
2559  if (fReadObjectWise) fReadObjectWise->fActions.clear();
2560  else fReadObjectWise = new TStreamerInfoActions::TActionSequence(this,ndata);
2561 
2562  if (fWriteObjectWise) fWriteObjectWise->fActions.clear();
2563  else fWriteObjectWise = new TStreamerInfoActions::TActionSequence(this,ndata);
2564 
2565  if (fReadMemberWise) fReadMemberWise->fActions.clear();
2566  else fReadMemberWise = new TStreamerInfoActions::TActionSequence(this,ndata);
2567 
2568  if (fWriteMemberWise) fWriteMemberWise->fActions.clear();
2569  else fWriteMemberWise = new TStreamerInfoActions::TActionSequence(this,ndata);
2570 
2571  if (fReadMemberWiseVecPtr) fReadMemberWiseVecPtr->fActions.clear();
2572  else fReadMemberWiseVecPtr = new TStreamerInfoActions::TActionSequence(this,ndata);
2573 
2574  if (fWriteMemberWiseVecPtr) fWriteMemberWiseVecPtr->fActions.clear();
2575  else fWriteMemberWiseVecPtr = new TStreamerInfoActions::TActionSequence(this,ndata);
2576 
2577  if (fWriteText) fWriteText->fActions.clear();
2578  else fWriteText = new TStreamerInfoActions::TActionSequence(this,ndata);
2579 
2580  if (!ndata) {
2581  // This may be the case for empty classes (e.g., TAtt3D).
2582  // We still need to properly set the size of emulated classes (i.e. add the virtual table)
2583  if (fClass->TestBit(TClass::kIsEmulation) && fNVirtualInfoLoc!=0) {
2584  fSize = sizeof(TStreamerInfo*);
2585  }
2586  fComp = new TCompInfo[1];
2587  fCompFull = new TCompInfo*[1];
2588  fCompOpt = new TCompInfo*[1];
2589  fCompOpt[0] = fCompFull[0] = &(fComp[0]);
2590  SetIsCompiled();
2591  return;
2592  }
2593 
2594  // At most half of the elements can be used to hold optimized versions.
2595  // We use the bottom to hold the optimized-into elements and the non-optimized elements
2596  // and the top to hold the original copy of the optimized out elements.
2597  fNslots = ndata + ndata/2 + 1;
2598  Int_t optiOut = 0;
2599 
2600  fComp = new TCompInfo[fNslots];
2601  fCompFull = new TCompInfo*[ndata];
2602  fCompOpt = new TCompInfo*[ndata];
2603 
2604  TStreamerElement* element;
2605  TStreamerElement* previous = 0;
2606  Int_t keep = -1;
2607  Int_t i;
2608 
2609  if (!CanOptimize()) {
2610  SetBit(kCannotOptimize);
2611  }
2612 
2613  Bool_t isOptimized = kFALSE;
2614  Bool_t previousOptimized = kFALSE;
2615 
2616  for (i = 0; i < ndata; ++i) {
2617  element = (TStreamerElement*) fElements->At(i);
2618  if (!element) {
2619  break;
2620  }
2621 
2622  Int_t asize = element->GetSize();
2623  if (element->GetArrayLength()) {
2624  asize /= element->GetArrayLength();
2625  }
2626  fComp[fNdata].fType = element->GetType();
2627  fComp[fNdata].fNewType = element->GetNewType();
2628  fComp[fNdata].fOffset = element->GetOffset();
2629  fComp[fNdata].fLength = element->GetArrayLength();
2630  fComp[fNdata].fElem = element;
2631  fComp[fNdata].fMethod = element->GetMethod();
2632  fComp[fNdata].fClass = element->GetClassPointer();
2633  fComp[fNdata].fNewClass = element->GetNewClass();
2634  fComp[fNdata].fClassName = TString(element->GetTypeName()).Strip(TString::kTrailing, '*');
2635  fComp[fNdata].fStreamer = element->GetStreamer();
2636 
2637  // try to group consecutive members of the same type
2638  if (!TestBit(kCannotOptimize)
2639  && (keep >= 0)
2640  && (element->GetType() >=0)
2641  && (element->GetType() < 10)
2642  && (fComp[fNdata].fType == fComp[fNdata].fNewType)
2643  && (fComp[keep].fMethod == 0)
2644  && (element->GetType() > 0)
2645  && (element->GetArrayDim() == 0)
2646  && (fComp[keep].fType < kObject)
2647  && (fComp[keep].fType != kCharStar) /* do not optimize char* */
2648  && (element->GetType() == (fComp[keep].fType%kRegrouped))
2649  && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
2650  && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
2651  ((element->GetFactor() == previous->GetFactor())
2652  && (element->GetXmin() == previous->GetXmin())
2653  && (element->GetXmax() == previous->GetXmax())
2654  )
2655  )
2658  // kWholeObject and kDoNotDelete do not apply to numerical elements.
2659  )
2660  {
2661  if (!previousOptimized) {
2662  // The element was not yet optimized we first need to copy it into
2663  // the set of original copies.
2664  fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
2665  fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
2666  }
2667  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
2668  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
2669 
2670  R__ASSERT( keep < (fNslots - optiOut) );
2671 
2672  if (fComp[keep].fLength == 0) {
2673  fComp[keep].fLength++;
2674  }
2675  fComp[keep].fLength++;
2676  fComp[keep].fType = element->GetType() + kRegrouped;
2677  isOptimized = kTRUE;
2678  previousOptimized = kTRUE;
2679  } else if (element->GetType() < 0) {
2680 
2681  // -- Deal with an ignored TObject base class.
2682  // Note: The only allowed negative value here is -1,
2683  // and signifies that Build() has found a TObject
2684  // base class and TClass::IgnoreTObjectStreamer() was
2685  // called. In this case the compiled version of the
2686  // elements omits the TObject base class element,
2687  // which has to be compensated for by TTree::Bronch()
2688  // when it is making branches for a split object.
2689  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
2690  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
2691  keep = -1;
2692  previousOptimized = kFALSE;
2693 
2694  } else {
2695  if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
2696  if (fComp[fNdata].fNewType > 0) {
2697  if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
2698  || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
2699  || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
2700  && (fComp[fNdata].fType == kObjectp || fComp[fNdata].fType == kAnyp
2701  || fComp[fNdata].fType == kObject || fComp[fNdata].fType == kAny
2702  || fComp[fNdata].fType == kTObject || fComp[fNdata].fType == kTNamed || fComp[fNdata].fType == kTString )
2703  ) {
2704  fComp[fNdata].fType = fComp[fNdata].fNewType;
2705  } else if (fComp[fNdata].fType != kCounter) {
2706  fComp[fNdata].fType += kConv;
2707  }
2708  } else {
2709  if (fComp[fNdata].fType == kCounter) {
2710  Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
2711  }
2712  fComp[fNdata].fType += kSkip;
2713  }
2714  }
2715  fCompOpt[fNdata] = &(fComp[fNdata]);
2716  fCompFull[fNfulldata] = &(fComp[fNdata]);
2717 
2718  R__ASSERT( fNdata < (fNslots - optiOut) );
2719 
2720  keep = fNdata;
2721  if (fComp[keep].fLength == 0) {
2722  fComp[keep].fLength = 1;
2723  }
2724  fNdata++;
2725  previousOptimized = kFALSE;
2726  }
2727  // The test 'fMethod[keep] == 0' fails to detect a variable size array
2728  // if the counter happens to have an offset of zero, so let's explicitly
2729  // prevent for here.
2730  if (element->HasCounter()) keep = -1;
2731  ++fNfulldata;
2732  previous = element;
2733  }
2734 
2735  for (i = 0; i < fNdata; ++i) {
2736  if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
2737  continue;
2738  }
2739  AddReadAction(fReadObjectWise, i, fCompOpt[i]);
2740  AddWriteAction(fWriteObjectWise, i, fCompOpt[i]);
2741  }
2742  for (i = 0; i < fNfulldata; ++i) {
2743  if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
2744  continue;
2745  }
2746  AddReadAction(fReadMemberWise, i, fCompFull[i]);
2747  AddWriteAction(fWriteMemberWise, i, fCompFull[i]);
2748  AddReadMemberWiseVecPtrAction(fReadMemberWiseVecPtr, i, fCompFull[i]);
2749  AddWriteMemberWiseVecPtrAction(fWriteMemberWiseVecPtr, i, fCompFull[i]);
2750 
2751  AddWriteTextAction(fWriteText, i, fCompFull[i]);
2752  }
2753  ComputeSize();
2754 
2755  fOptimized = isOptimized;
2756  SetIsCompiled();
2757 
2758  if (gDebug > 0) {
2759  ls();
2760  }
2761 }
2762 
2763 template <typename From>
2764 static void AddReadConvertAction(TStreamerInfoActions::TActionSequence *sequence, Int_t newtype, TConfiguration *conf)
2765 {
2766  switch (newtype) {
2767  case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
2768  case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
2769  case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
2770  case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
2771  case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
2772  case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
2773  case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
2774  case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
2775  case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
2776  case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
2777  case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
2778  case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
2779  case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
2780  case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
2781  case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
2782  case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
2783  }
2784 }
2785 
2786 ////////////////////////////////////////////////////////////////////////////////
2787 /// Add a read action for the given element.
2788 
2790 {
2791  TStreamerElement *element = compinfo->fElem;
2792 
2793  if (element->TestBit(TStreamerElement::kWrite)) return;
2794 
2795  switch (compinfo->fType) {
2796  // read basic types
2797  case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2798  case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2799  case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2800  case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2801  case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2802  case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2803  case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2804  case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2805  case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2806  case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2807  case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2808  case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2809  case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2810  case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2811  case TStreamerInfo::kFloat16: {
2812  if (element->GetFactor() != 0) {
2813  readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2814  } else {
2815  Int_t nbits = (Int_t)element->GetXmin();
2816  if (!nbits) nbits = 12;
2817  readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2818  }
2819  break;
2820  }
2821  case TStreamerInfo::kDouble32: {
2822  if (element->GetFactor() != 0) {
2823  readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2824  } else {
2825  Int_t nbits = (Int_t)element->GetXmin();
2826  if (!nbits) {
2827  readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2828  } else {
2829  readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2830  }
2831  }
2832  break;
2833  }
2834  case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2835  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2836  // Streamer alltogether.
2837  case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2838  case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2839  case TStreamerInfo::kSTL: {
2840  TClass *newClass = element->GetNewClass();
2841  TClass *oldClass = element->GetClassPointer();
2842  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
2843 
2844  if (element->GetArrayLength() <= 1) {
2845  if (fOldVersion<3){ // case of old TStreamerInfo
2846  if (newClass && newClass != oldClass) {
2847  if (element->GetStreamer()) {
2848  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2849  } else {
2850  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
2851  }
2852  } else {
2853  if (element->GetStreamer()) {
2854  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2855  } else {
2856  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
2857  }
2858  }
2859  } else {
2860  if (newClass && newClass != oldClass) {
2861  if (element->GetStreamer()) {
2862  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2863  } else {
2864  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
2865  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
2866  } else {
2867  switch (SelectLooper(*newClass->GetCollectionProxy())) {
2868  case kVectorLooper:
2869  readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2870  break;
2871  case kAssociativeLooper:
2872  readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2873  break;
2874  case kVectorPtrLooper:
2875  case kGenericLooper:
2876  default:
2877  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
2878  readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2879  break;
2880  }
2881  }
2882  }
2883  } else {
2884  if (element->GetStreamer()) {
2885  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2886  } else {
2887  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
2888  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
2889  } else {
2890  switch (SelectLooper(*oldClass->GetCollectionProxy())) {
2891  case kVectorLooper:
2892  readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2893  break;
2894  case kAssociativeLooper:
2895  readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2896  break;
2897  case kVectorPtrLooper:
2898  case kGenericLooper:
2899  default:
2900  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
2901  readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2902  break;
2903  }
2904  }
2905  }
2906  }
2907  }
2908  } else {
2909  if (fOldVersion<3){ // case of old TStreamerInfo
2910  if (newClass && newClass != oldClass) {
2911  if (element->GetStreamer()) {
2912  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2913  } else {
2914  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
2915  }
2916  } else {
2917  if (element->GetStreamer()) {
2918  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2919  } else {
2920  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
2921  }
2922  }
2923  } else {
2924  if (newClass && newClass != oldClass) {
2925  if (element->GetStreamer()) {
2926  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2927  } else {
2928  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
2929  }
2930  } else {
2931  if (element->GetStreamer()) {
2932  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2933  } else {
2934  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
2935  }
2936  }
2937  }
2938  }
2939  break;
2940  }
2941 
2943  AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2944  break;
2946  AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2947  break;
2949  AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2950  break;
2952  AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2953  break;
2955  AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2956  break;
2958  AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2959  break;
2961  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2962  break;
2964  AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2965  break;
2967  AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2968  break;
2970  AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2971  break;
2973  AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2974  break;
2976  AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2977  break;
2979  AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2980  break;
2982  AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
2983  break;
2985  if (element->GetFactor() != 0) {
2986  AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2987  } else {
2988  Int_t nbits = (Int_t)element->GetXmin();
2989  if (!nbits) nbits = 12;
2990  AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2991  }
2992  break;
2993  }
2995  if (element->GetFactor() != 0) {
2996  AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2997  } else {
2998  Int_t nbits = (Int_t)element->GetXmin();
2999  if (!nbits) {
3000  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3001  } else {
3002  AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3003  }
3004  }
3005  break;
3006  }
3007  default:
3008  readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3009  break;
3010  }
3011  if (element->TestBit(TStreamerElement::kCache)) {
3012  TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3013  readSequence->fActions.pop_back();
3014  readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3015  }
3016 }
3017 
3018 ////////////////////////////////////////////////////////////////////////////////
3019 /// Add a read action for the given element.
3020 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3021 
3023 {
3024  TStreamerElement *element = compinfo->fElem;
3025 
3026  if (element->TestBit(TStreamerElement::kWrite)) return;
3027 
3028  if (element->TestBit(TStreamerElement::kCache)) {
3029  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3030  readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3031  } else {
3032  readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3033  }
3034 }
3035 
3036 ////////////////////////////////////////////////////////////////////////////////
3037 
3039 {
3040  TStreamerElement *element = compinfo->fElem;
3041  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3042  // Skip element cached for reading purposes.
3043  return;
3044  }
3045  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3046  // Skip artificial element used for reading purposes.
3047  return;
3048  }
3049  switch (compinfo->fType) {
3050  // write basic types
3051  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3052  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3053  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3054  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3055  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3056  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3057  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3058  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3059  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3060  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3061  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3062  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3063  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3064  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3065  /*case TStreamerInfo::kFloat16: {
3066  if (element->GetFactor() != 0) {
3067  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3068  } else {
3069  Int_t nbits = (Int_t)element->GetXmin();
3070  if (!nbits) nbits = 12;
3071  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3072  }
3073  break;
3074  } */
3075  /*case TStreamerInfo::kDouble32: {
3076  if (element->GetFactor() != 0) {
3077  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3078  } else {
3079  Int_t nbits = (Int_t)element->GetXmin();
3080  if (!nbits) {
3081  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3082  } else {
3083  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3084  }
3085  }
3086  break;
3087  } */
3088  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3089  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3090  // Streamer alltogether.
3091  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3092  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3093  /*case TStreamerInfo::kSTL: {
3094  TClass *newClass = element->GetNewClass();
3095  TClass *oldClass = element->GetClassPointer();
3096  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3097 
3098  if (element->GetArrayLength() <= 1) {
3099  if (newClass && newClass != oldClass) {
3100  if (element->GetStreamer()) {
3101  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3102  } else {
3103  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3104  }
3105  } else {
3106  if (element->GetStreamer()) {
3107  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3108  } else {
3109  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3110  }
3111  }
3112  } else {
3113  if (newClass && newClass != oldClass) {
3114  if (element->GetStreamer()) {
3115  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3116  } else {
3117  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3118  }
3119  } else {
3120  if (element->GetStreamer()) {
3121  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3122  } else {
3123  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3124  }
3125  }
3126  }
3127  break;
3128  } */
3129  default:
3130  writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3131  break;
3132  }
3133 #if defined(CDJ_NO_COMPILE)
3134  if (element->TestBit(TStreamerElement::kCache)) {
3135  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3136  writeSequence->fActions.pop_back();
3137  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3138  }
3139 #endif
3140 }
3141 
3142 ////////////////////////////////////////////////////////////////////////////////
3143 
3145 {
3146  TStreamerElement *element = compinfo->fElem;
3147  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3148  // Skip element cached for reading purposes.
3149  return;
3150  }
3151  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3152  // Skip artificial element used for reading purposes.
3153  return;
3154  }
3155 
3156  Bool_t generic = kFALSE;
3157 
3158  switch (compinfo->fType) {
3159  // write basic types
3160  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3161  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3162  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3163  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3164  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3165  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3166  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3167  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3168  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3169  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3170  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3171  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3172  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3173 
3175  if (element->IsBase())
3176  generic = kTRUE;
3177  else
3178  writeSequence->AddAction( WriteTextTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3179  break;
3180 
3182  if (element->IsBase())
3183  generic = kTRUE;
3184  else
3185  writeSequence->AddAction( WriteTextTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3186  break;
3187 
3188  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3189  case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3190  writeSequence->AddAction( WriteSTLp<true>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3191  break;
3192 
3195  writeSequence->AddAction( WriteStreamerLoop<true>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3196  break;
3197 
3198 
3199  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3200  /*case TStreamerInfo::kFloat16: {
3201  if (element->GetFactor() != 0) {
3202  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3203  } else {
3204  Int_t nbits = (Int_t)element->GetXmin();
3205  if (!nbits) nbits = 12;
3206  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3207  }
3208  break;
3209  } */
3210  /*case TStreamerInfo::kDouble32: {
3211  if (element->GetFactor() != 0) {
3212  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3213  } else {
3214  Int_t nbits = (Int_t)element->GetXmin();
3215  if (!nbits) {
3216  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3217  } else {
3218  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3219  }
3220  }
3221  break;
3222  } */
3223  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3224  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3225  // Streamer alltogether.
3226  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3227  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3228  /*case TStreamerInfo::kSTL: {
3229  TClass *newClass = element->GetNewClass();
3230  TClass *oldClass = element->GetClassPointer();
3231  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3232 
3233  if (element->GetArrayLength() <= 1) {
3234  if (newClass && newClass != oldClass) {
3235  if (element->GetStreamer()) {
3236  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3237  } else {
3238  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3239  }
3240  } else {
3241  if (element->GetStreamer()) {
3242  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3243  } else {
3244  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3245  }
3246  }
3247  } else {
3248  if (newClass && newClass != oldClass) {
3249  if (element->GetStreamer()) {
3250  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3251  } else {
3252  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3253  }
3254  } else {
3255  if (element->GetStreamer()) {
3256  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3257  } else {
3258  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3259  }
3260  }
3261  }
3262  break;
3263  } */
3264  default:
3265  generic = kTRUE;
3266  break;
3267  }
3268 
3269  // use generic write action when special handling is not provided
3270  if (generic) writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3271 
3272 #if defined(CDJ_NO_COMPILE)
3273  if (element->TestBit(TStreamerElement::kCache)) {
3274  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3275  writeSequence->fActions.pop_back();
3276  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3277  }
3278 #endif
3279 }
3280 
3281 ////////////////////////////////////////////////////////////////////////////////
3282 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3283 
3285 {
3286  TStreamerElement *element = compinfo->fElem;
3287  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3288  // Skip element cached for reading purposes.
3289  return;
3290  }
3291  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3292  // Skip artificial element used for reading purposes.
3293  return;
3294  }
3295 
3296 #if defined(CDJ_NO_COMPILE)
3297  if (element->TestBit(TStreamerElement::kCache)) {
3298  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3299  writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3300  } else {
3301  writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3302  }
3303 #else
3304  writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3305 #endif
3306 
3307 }
3308 
3309 ////////////////////////////////////////////////////////////////////////////////
3310 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3311 
3313 {
3314  if (info == 0) {
3315  return new TStreamerInfoActions::TActionSequence(0,0);
3316  }
3317 
3318  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3319 
3320  UInt_t ndata = info->GetElements()->GetEntries();
3323  {
3324  if (proxy.HasPointers()) {
3325  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3326  delete sequence;
3327 
3328  sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3329 
3330  return sequence;
3331  }
3332 
3333  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3334  Long_t increment = proxy.GetIncrement();
3335  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3336  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
3340  {
3341  Long_t increment = proxy.GetIncrement();
3342  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3343  // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3344  } else {
3345  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3346  }
3347  for (UInt_t i = 0; i < ndata; ++i) {
3348  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3349  if (!element) {
3350  break;
3351  }
3352  if (element->GetType() < 0) {
3353  // -- Skip an ignored TObject base class.
3354  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3355  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3356  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3357  // when it is making branches for a split object.
3358  continue;
3359  }
3360  if (element->TestBit(TStreamerElement::kWrite)) {
3361  // Skip element that only for writing.
3362  continue;
3363  }
3364  TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3365  if (baseEl) {
3366  if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3367  // There was a problem with the checksum, the user likely did not
3368  // increment the version number of the derived class when the
3369  // base class changed. Since we will be member wise streaming
3370  // this class, let's warn the user that something is wrong.
3371  ::Warning("CreateReadMemberWiseActions","%s",
3372  baseEl->GetErrorMessage());
3374  }
3375  }
3376 
3377  TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3378 
3379  Int_t asize = element->GetSize();
3380  if (element->GetArrayLength()) {
3381  asize /= element->GetArrayLength();
3382  }
3383  Int_t oldType = element->GetType();
3384  Int_t newType = element->GetNewType();
3385 
3386  Int_t offset = element->GetOffset();
3387  if (newType != oldType) {
3388  if (newType > 0) {
3389  if (oldType != TVirtualStreamerInfo::kCounter) {
3390  oldType += TVirtualStreamerInfo::kConv;
3391  }
3392  } else {
3393  oldType += TVirtualStreamerInfo::kSkip;
3394  }
3395  }
3396  switch (SelectLooper(proxy)) {
3397  case kAssociativeLooper:
3398 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3399 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3400 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3401  case kVectorLooper:
3402  case kVectorPtrLooper:
3403  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3404  if (element->TestBit(TStreamerElement::kCache)) {
3405  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3406  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3407  } else {
3408  sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3409  }
3410  break;
3411  case kGenericLooper:
3412  default:
3413  // The usual collection case.
3414  if (element->TestBit(TStreamerElement::kCache)) {
3415  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3416  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3417  } else {
3418  sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3419  }
3420  break;
3421  }
3422  }
3423  return sequence;
3424 }
3425 
3426 ////////////////////////////////////////////////////////////////////////////////
3427 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3428 
3430 {
3431  if (info == 0) {
3432  return new TStreamerInfoActions::TActionSequence(0,0);
3433  }
3434 
3435  UInt_t ndata = info->GetElements()->GetEntries();
3436  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3438 
3440  {
3441  if (proxy.HasPointers()) {
3442  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3443  delete sequence;
3444 
3445  sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
3446 
3447  return sequence;
3448  }
3449 
3450  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3451  Long_t increment = proxy.GetIncrement();
3452  sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
3453  /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3454  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
3455  {
3456  Long_t increment = proxy.GetIncrement();
3457  sequence->fLoopConfig = new TVectorLoopConfig(increment);
3458  // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
3459  } else {
3460  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
3461  }
3462  for (UInt_t i = 0; i < ndata; ++i) {
3463  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3464  if (!element) {
3465  break;
3466  }
3467  if (element->GetType() < 0) {
3468  // -- Skip an ignored TObject base class.
3469  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3470  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3471  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3472  // when it is making branches for a split object.
3473  continue;
3474  }
3475  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3476  // Skip element cached for reading purposes.
3477  continue;
3478  }
3480  // Skip artificial element used for reading purposes.
3481  continue;
3482  }
3483  TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
3484  Int_t asize = element->GetSize();
3485  if (element->GetArrayLength()) {
3486  asize /= element->GetArrayLength();
3487  }
3488  Int_t oldType = element->GetType();
3489  Int_t offset = element->GetOffset();
3490 #if defined(CDJ_NO_COMPILE)
3491  Int_t newType = element->GetNewType();
3492 
3493  if (newType != oldType) {
3494  if (newType > 0) {
3495  if (oldType != TVirtualStreamerInfo::kCounter) {
3496  oldType += TVirtualStreamerInfo::kConv;
3497  }
3498  } else {
3499  oldType += TVirtualStreamerInfo::kSkip;
3500  }
3501  }
3503  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3504  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
3505  {
3506 
3507  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3508  if (element->TestBit(TStreamerElement::kCache)) {
3509  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3510  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3511  } else {
3512  sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3513  }
3514 
3515  // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3516  // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3517  // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3518  } else {
3519  // The usual collection case.
3520  if (element->TestBit(TStreamerElement::kCache)) {
3521  TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3522  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3523  } else {
3524  switch (oldType) {
3525  // read basic types
3526  case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3527  case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3528  case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3529  case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3530  case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3531  case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3532  case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3533  case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3534  case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3535  case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3536  case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3537  case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3538  case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3539  // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
3541  if (element->GetFactor() != 0) {
3542  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3543  } else {
3544  Int_t nbits = (Int_t)element->GetXmin();
3545  if (!nbits) nbits = 12;
3546  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3547  }
3548  break;
3549  }
3551  if (element->GetFactor() != 0) {
3552  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3553  } else {
3554  Int_t nbits = (Int_t)element->GetXmin();
3555  if (!nbits) {
3556  sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
3557  } else {
3558  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3559  }
3560  }
3561  break;
3562  }
3563  case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
3564  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3565  // Streamer alltogether.
3566  case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
3567  case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
3568  default:
3569  sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
3570  break;
3571  }
3572  }
3573  }
3574 #else
3576  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3577  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
3578  {
3579  sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3580  } else {
3581  // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
3582  // as it does not create/use a TStaging as expected ... but then again it might
3583  // not be the right things to expect ...
3584  // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3585  sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
3586  }
3587 #endif
3588  }
3589  return sequence;
3590 }
3592 {
3593  // Add the (potentially negative) delta to all the configuration's offset. This is used by
3594  // TBranchElement in the case of split sub-object.
3595 
3596  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3597  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3598  iter != end;
3599  ++iter)
3600  {
3601  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3602  iter->fConfiguration->AddToOffset(delta);
3603  }
3604 }
3605 
3607 {
3608  // Create a copy of this sequence.
3609 
3610  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,fActions.size());
3611 
3612  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
3613 
3614  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3615  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3616  iter != end;
3617  ++iter)
3618  {
3619  TConfiguration *conf = iter->fConfiguration->Copy();
3620  sequence->AddAction( iter->fAction, conf );
3621  }
3622  return sequence;
3623 }
3624 
3626  const TStreamerInfoActions::TIDs &element_ids,
3627  Int_t offset,
3629 {
3630  for(UInt_t id = 0; id < element_ids.size(); ++id) {
3631  if ( element_ids[id].fElemID < 0 ) {
3632  if (element_ids[id].fNestedIDs) {
3633  auto original = create(element_ids[id].fNestedIDs->fInfo,
3634  sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
3635  nullptr);
3636  if (element_ids[id].fNestedIDs->fOnfileObject) {
3637  auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
3638  if ( sequence->fLoopConfig )
3639  sequence->AddAction( PushDataCacheGenericCollection, conf );
3640  else
3641  sequence->AddAction( PushDataCache, conf );
3642  }
3643 
3644  original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
3645 
3646  if (element_ids[id].fNestedIDs->fOnfileObject)
3647  sequence->AddAction( PopDataCache,
3648  new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset) );
3649  } else {
3650  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3651  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3652  iter != end;
3653  ++iter)
3654  {
3655  TConfiguration *conf = iter->fConfiguration->Copy();
3656  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3657  conf->AddToOffset(offset);
3658  sequence->AddAction( iter->fAction, conf );
3659  }
3660  }
3661  } else {
3662  int localIndex = 0;
3663  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3664  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3665  iter != end;
3666  ++iter) {
3667  // fprintf(stderr, "With element_ids[%d] For %s comparing act[%d/%zu] %d to %d for %p vs %p %s\n",
3668  // id,
3669  // iter->fConfiguration->fInfo->GetName(),
3670  // localIndex, fActions.size(),
3671  // iter->fConfiguration->fElemId,
3672  // (UInt_t)element_ids[id].fElemID, iter->fConfiguration->fInfo,
3673  // element_ids[id].fInfo,
3674  // element_ids[id].fInfo ? element_ids[id].fInfo->GetName() : "nullptr" );
3675  ++localIndex;
3676  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
3677  TConfiguration *conf = iter->fConfiguration->Copy();
3678  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3679  conf->AddToOffset(offset);
3680  sequence->AddAction( iter->fAction, conf );
3681  }
3682  }
3683  }
3684  }
3685 }
3686 
3689 {
3690  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
3691  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
3692 
3693  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
3694 
3695  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
3696 
3697  AddToSubSequence(sequence, element_ids, offset, create);
3698 
3699  return sequence;
3700 }
3701 
3703 {
3704  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
3705  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
3706 
3707  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
3708 
3709  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
3710 
3711  for(UInt_t id = 0; id < element_ids.size(); ++id) {
3712  if ( element_ids[id] < 0 ) {
3713  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3714  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3715  iter != end;
3716  ++iter)
3717  {
3718  TConfiguration *conf = iter->fConfiguration->Copy();
3719  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3720  conf->AddToOffset(offset);
3721  sequence->AddAction( iter->fAction, conf );
3722  }
3723  } else {
3724  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3725  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3726  iter != end;
3727  ++iter) {
3728  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
3729  TConfiguration *conf = iter->fConfiguration->Copy();
3730  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3731  conf->AddToOffset(offset);
3732  sequence->AddAction( iter->fAction, conf );
3733  }
3734  }
3735  }
3736  }
3737  return sequence;
3738 }
3739 
3740 #if !defined(R__WIN32) && !defined(_AIX)
3741 
3742 #include <dlfcn.h>
3743 
3744 #endif
3745 
3746 typedef void (*voidfunc)();
3747 static const char *R__GetSymbolName(voidfunc func)
3748 {
3749 #if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
3750  return "not available on this platform";
3751 #if 0
3752  MEMORY_BASIC_INFORMATION mbi;
3753  if (!VirtualQuery (func, &mbi, sizeof (mbi)))
3754  {
3755  return 0;
3756  }
3757 
3758  HMODULE hMod = (HMODULE) mbi.AllocationBase;
3759  static char moduleName[MAX_PATH];
3760 
3761  if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
3762  {
3763  return 0;
3764  }
3765  return moduleName;
3766 #endif
3767 #else
3768  Dl_info info;
3769  if (dladdr((void*)func,&info)==0) {
3770  // Not in a known share library, let's give up
3771  return "name not found";
3772  } else {
3773  //fprintf(stdout,"Found address in %s\n",info.dli_fname);
3774  return info.dli_sname;
3775  }
3776 #endif
3777 }
3778 
3780 {
3781  // Add the (potentially negative) delta to all the configuration's offset. This is used by
3782  // TTBranchElement in the case of split sub-object.
3783  // If opt contains 'func', also print the (mangled) name of the function that will be executed.
3784 
3785  if (fLoopConfig) {
3786  fLoopConfig->Print();
3787  }
3788  TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
3789  for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
3790  iter != end;
3791  ++iter)
3792  {
3793  iter->fConfiguration->Print();
3794  if (strstr(opt,"func")) {
3795  printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
3796  }
3797  }
3798 }
3799 
3800 
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
virtual Int_t GetCollectionType() const =0
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
INLINE_TEMPLATE_ARGS Int_t ReadBasicType_WithFactor(TBuffer &buf, void *addr, const TConfiguration *config)
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:344
Int_t ReadBufferSkip(TBuffer &b, const T &arrptr, const TCompInfo *compinfo, Int_t kase, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Skip an element.
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2231
An array of TObjects.
Definition: TObjArray.h:37
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible...
float xmin
Definition: THbookFile.cxx:93
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
static void AddReadConvertAction(TStreamerInfoActions::TActionSequence *sequence, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetConvertCollectionReadActionFrom(Int_t newtype, TConfiguration *conf)
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
virtual Int_t GetProperties() const
void AddReadMemberWiseVecPtrAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
short Version_t
Definition: RtypesCore.h:61
void Fatal(const char *location, const char *msgfmt,...)
INLINE_TEMPLATE_ARGS Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
std::vector< TIDNode > TIDs
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
void AddReadAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
float Float_t
Definition: RtypesCore.h:53
Equal to TDataType&#39;s kchar.
static void * CopyIterator(void *dest, const void *source)
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)=0
const char Option_t
Definition: RtypesCore.h:62
virtual TClass * GetValueClass() const =0
void AddAction(action_t action, TConfiguration *conf)
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:241
static void * Next(void *iter, const void *end)
double T(double x)
Definition: ChebyshevPol.h:34
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition: MPSendRecv.h:157
virtual void PrintDebug(TBuffer &buffer, void *object) const
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
static TConfiguredAction GetNumericCollectionReadAction(Int_t type, TConfigSTL *conf)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType< BitsMarker >(TBuffer &buf, void *addr, const TConfiguration *config)
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4420
INLINE_TEMPLATE_ARGS Int_t ReadBasicType_NoFactor(TBuffer &buf, void *addr, const TConfiguration *config)
TMemberStreamer * GetStreamer() const
Return the local streamer object.
virtual void Commit(void *)=0
INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
INLINE_TEMPLATE_ARGS Int_t ReadTObject(TBuffer &buf, void *addr, const TConfiguration *config)
virtual TClass * GetCollectionClass() const
#define R__ASSERT(e)
Definition: TError.h:96
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:402
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual UInt_t WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt=kFALSE)=0
void AddWriteAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
UInt_t fElemId
Identifier of the TStreamerElement.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2816
Int_t GetArrayLength() const
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Cache the value in memory than is not part of the object but is accessible via a SchemaRule.
virtual UShort_t GetPidOffset() const =0
void AddWriteMemberWiseVecPtrAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
This is for streaming via a TClonesArray (or a vector of pointers of this type).
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)=0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Int_t GetArrayDim() const
INLINE_TEMPLATE_ARGS Int_t ReadTString(TBuffer &buf, void *addr, const TConfiguration *config)
virtual EDataType GetType() const =0
void GetSequenceType(TString &type) const
Fill type with the string representation of sequence information including &#39;cached&#39;,&#39;repeat&#39;,&#39;write&#39; or &#39;nodelete&#39;.
void *(* CopyIterator_t)(void *dest, const void *source)
Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS void ReadArraySTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
TCompInfo ** fCompFull
![fElements->GetEntries()]
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
virtual void ReadInt(Int_t &i)=0
TVirtualCollectionProxy::Next_t Next_t
void AddToSubSequence(TActionSequence *sequence, const TIDs &element_ids, Int_t offset, SequenceGetter_t create)
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
Int_t Length() const
Definition: TBuffer.h:96
void(* DeleteIterator_t)(void *iter)
INLINE_TEMPLATE_ARGS void ReadSTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
static TConfiguredAction GetCollectionReadAction(TVirtualStreamerInfo *info, TStreamerElement *element, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
INLINE_TEMPLATE_ARGS Int_t WriteStreamerLoop(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
virtual void ReadWithNbits(Float_t *ptr, Int_t nbits)=0
virtual Int_t GetClassVersion() const =0
INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
char * GetObjectAt(UInt_t ind) const
Definition: TVirtualArray.h:38
Double_t x[n]
Definition: legend1.C:17
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:323
void Class()
Definition: Class.C:29
void AddWriteTextAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
void(* voidfunc)()
virtual void Copy(TObject &object) const
Copy this to obj.
Definition: TObject.cxx:61
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:119
Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
TMemberStreamer * fStreamer
Not Owned.
Definition: TStreamerInfo.h:60
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
XFontStruct * id
Definition: TGX11.cxx:108
double Double32_t
Definition: RtypesCore.h:56
Base class of the Configurations for the member wise looping routines.
Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
void Error(const char *location, const char *msgfmt,...)
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
ESelectLooper SelectLooper(TVirtualCollectionProxy &proxy)
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
virtual Version_t ReadVersionForMemberWise(const TClass *cl=0)=0
static TConfiguredAction GetCollectionReadConvertAction(Int_t newtype, TConfiguration *conf)
virtual TVirtualCollectionProxy * GetCollectionProxy() const
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
TClass * GetClass() const
ROOT::R::TRInterface & r
Definition: Object.C:4
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:26
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0)=0
static TConfiguredAction GetCollectionWriteAction(TVirtualStreamerInfo *info, TStreamerElement *, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
SVector< double, 2 > v
Definition: Dict.h:5
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)=0
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
Int_t fOffset
Offset within the object.
virtual void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue)=0
virtual TLoopConfiguration * Copy() const =0
virtual Bool_t HasPointers() const =0
Double_t GetXmin() const
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=0)=0
unsigned int UInt_t
Definition: RtypesCore.h:42
INLINE_TEMPLATE_ARGS Int_t WriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5434
INLINE_TEMPLATE_ARGS Int_t WriteTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
virtual TVirtualArray * PeekDataCache() const
Return the &#39;current&#39; data cache area from the list of area to be used for temporarily store &#39;missing&#39;...
Definition: TBuffer.cxx:350
virtual void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue)=0
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
char * Strip(const char *str, char c=' ')
Strip leading and trailing c (blanks by default) from a string.
Definition: TString.cxx:2508
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Bool_t forCollection)
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
void Warning(const char *location, const char *msgfmt,...)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
TClass * fClass
Not Owned.
Definition: TStreamerInfo.h:57
static const Int_t fgIteratorArenaSize
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:561
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:253
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamerV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=0)=0
const Bool_t kFALSE
Definition: RtypesCore.h:88
PyObject * fType
TStreamerElement * fElem
Not Owned.
Definition: TStreamerInfo.h:55
virtual ULong_t GetIncrement() const =0
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Double_t GetXmax() const
void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config)
void Copy(void *source, void *dest)
virtual TVirtualArray * PopDataCache()
Pop and Return the &#39;current&#39; data cache area from the list of area to be used for temporarily store &#39;...
Definition: TBuffer.cxx:360
void Print(Option_t *="") const
This method must be overridden when a class wants to print itself.
#define INLINE_TEMPLATE_ARGS
void Print(std::ostream &os, const OptionType &opt)
virtual void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits)=0
double Double_t
Definition: RtypesCore.h:55
virtual TObjArray * GetElements() const =0
INLINE_TEMPLATE_ARGS Int_t WriteTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
INLINE_TEMPLATE_ARGS Int_t UseCache(TBuffer &b, void *addr, const TConfiguration *conf)
Double_t GetFactor() const
int type
Definition: TGX11.cxx:120
virtual Int_t GetSize() const
Returns size of this element in bytes.
static const Int_t kRegrouped
virtual Bool_t HasCounter() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
void PrintDebug(TBuffer &buffer, void *object) const
#define R__LOCKGUARD(mutex)
static TConfiguredAction GetConvertCollectionReadAction(Int_t oldtype, Int_t newtype, TConfiguration *conf)
virtual void PushDataCache(TVirtualArray *)
Push a new data cache area onto the list of area to be used for temporarily store &#39;missing&#39; data memb...
Definition: TBuffer.cxx:341
Int_t PopDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *, const TConfiguration *)
void Compile()
loop on the TStreamerElement list regroup members with same type Store predigested information into l...
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)=0
TClassRef fClass
Definition: TVirtualArray.h:28
Mother of all ROOT objects.
Definition: TObject.h:37
SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) SequenceGetter_t
Int_t GetNewType() const
virtual UInt_t Size() const =0
typedef void((*Func_t)())
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArrayV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
const char * GetTypeName() const
INLINE_TEMPLATE_ARGS Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
Definition: file.py:1
TClass * GetNewClass() const
INLINE_TEMPLATE_ARGS void ReadArraySTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
static const char * R__GetSymbolName(voidfunc func)
const Int_t kMaxInt
Definition: RtypesCore.h:99
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
void *(* Next_t)(void *iter, const void *end)
virtual ULong_t GetMethod() const
Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
const char * GetErrorMessage() const
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t GetSize() const
Definition: TCollection.h:180
Abstract Interface class describing Streamer information for one class.
Int_t ReadBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t eoffset, Bool_t v7=kTRUE)
The STL vector/list is deserialized from the buffer b.
Int_t GetOffset() const
void(* DeleteTwoIterators_t)(void *begin, void *end)
Base class of the Configurations.
const Bool_t kTRUE
Definition: RtypesCore.h:87
UInt_t fLength
Number of element in a fixed length array.
Int_t GetType() const
const Int_t n
Definition: legend1.C:16
INLINE_TEMPLATE_ARGS void ReadSTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions(Bool_t forCollection)
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
Int_t PopDataCache(TBuffer &b, void *, const TConfiguration *)
TCompInfo_t * fCompInfo
Access to compiled information (for legacy code)