Logo ROOT   6.12/06
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
75  }
76 
77  void TConfiguration::Print() const
78  {
79  // Inform the user what we are about to stream.
80 
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.
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(Long_t increment, Bool_t /* read */) : 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() { return new TVectorLoopConfig(*this); }
599  };
600 
601  class TAssocLoopConfig : public TLoopConfiguration {
602  // Base class of the Configurations used in member wise streaming.
603  protected:
604  public:
605  TVirtualCollectionProxy *fProxy;
606  public:
607  TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : fProxy(proxy) {};
608  //virtual void PrintDebug(TBuffer &buffer, void *);
609  virtual ~TAssocLoopConfig() {};
610  void Print() const
611  {
612  printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
613  }
614  virtual TLoopConfiguration* Copy() { return new TAssocLoopConfig(*this); }
615 
616  void* GetFirstAddress(void *start, const void * /* end */) const
617  {
618  // Return the address of the first element of the collection.
619 
620  R__ASSERT(0);
621 // char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
622 // void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
623 // arr0 = genloopconfig->fNext(iter,end_collection);
624 // if (iter != &iterator[0]) {
625 // genloopconfig->fDeleteIterator(iter);
626 // }
627  return start;
628  }
629  };
630 
631  class TGenericLoopConfig : public TLoopConfiguration {
632  // Configuration object for the generic case of member wise streaming looping.
633  private:
634  void Init(Bool_t read) {
635  if (fProxy) {
636  if (fProxy->HasPointers()) {
640  } else {
641  fNext = fProxy->GetFunctionNext(read);
642  fCopyIterator = fProxy->GetFunctionCopyIterator(read);
643  fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
644  }
645  }
646  }
647  public:
648  TVirtualCollectionProxy *fProxy;
652 
653  TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : fProxy(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
654  {
655  Init(read);
656  }
657  virtual ~TGenericLoopConfig() {};
658  void Print() const
659  {
660  printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
661  }
662  virtual TLoopConfiguration* Copy() { return new TGenericLoopConfig(*this); }
663 
664  void* GetFirstAddress(void *start_collection, const void *end_collection) const
665  {
666  // Return the address of the first element of the collection.
667 
669  void *iter = fCopyIterator(&iterator,start_collection);
670  void *arr0 = fNext(iter,end_collection);
671  if (iter != &iterator[0]) {
672  fDeleteIterator(iter);
673  }
674  return arr0;
675  }
676  };
677 
679  {
680  // Collection was saved member-wise
681 
682  TConfigSTL *config = (TConfigSTL*)conf;
684 
685  if( vers >= 8 ) {
686 
687  TClass *oldClass = config->fOldClass;
688 
689  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
690  if (!oldProxy) {
691  // Missing information, broken file ... give up
692  return;
693  }
694  TClass *valueClass = oldProxy->GetValueClass();
695  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
696 
697  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
698  Int_t nobjects;
699  buf.ReadInt(nobjects);
700  void* alternative = oldProxy->Allocate(nobjects,true);
701  if (nobjects) {
702  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
703 
706  void *begin = &(startbuf[0]);
707  void *end = &(endbuf[0]);
708  config->fCreateIterators(alternative, &begin, &end, oldProxy);
709  // We can not get here with a split vector of pointer, so we can indeed assume
710  // that actions->fConfiguration != null.
711  buf.ApplySequence(*actions, begin, end);
712  if (begin != &(startbuf[0])) {
713  // assert(end != endbuf);
714  config->fDeleteTwoIterators(begin,end);
715  }
716  }
717  oldProxy->Commit(alternative);
718 
719  } else {
720 
721  TClass *oldClass = config->fOldClass;
722 
723  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
724  if (!oldProxy) {
725  // Missing information, broken file ... give up
726  return;
727  }
728 
729  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
730  Int_t nobjects;
731  buf.ReadInt(nobjects);
732  void* env = oldProxy->Allocate(nobjects,true);
733 
734  if (nobjects || vers < 7 ) {
735  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
736  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
737 
738  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
739  }
740  oldProxy->Commit(env);
741  }
742  }
743 
745  {
746  // Collection was saved member-wise
747 
748  TConfigSTL *config = (TConfigSTL*)conf;
750 
751  if( vers >= 8 ) {
752 
753  TClass *oldClass = config->fOldClass;
754 
755  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
756  if (!oldProxy) {
757  // Missing information, broken file ... give up
758  return;
759  }
760  TClass *valueClass = oldProxy->GetValueClass();
761  Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
762 
763  TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
764 
765  int objectSize = oldClass->Size();
766  char *obj = (char*)addr;
767  char *endobj = obj + conf->fLength*objectSize;
768 
769  for(; obj<endobj; obj+=objectSize) {
770  Int_t nobjects;
771  buf.ReadInt(nobjects);
772  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
773  void* alternative = oldProxy->Allocate(nobjects,true);
774  if (nobjects) {
777  void *begin = &(startbuf[0]);
778  void *end = &(endbuf[0]);
779  config->fCreateIterators(alternative, &begin, &end, oldProxy);
780  // We can not get here with a split vector of pointer, so we can indeed assume
781  // that actions->fConfiguration != null.
782  buf.ApplySequence(*actions, begin, end);
783  if (begin != &(startbuf[0])) {
784  // assert(end != endbuf);
785  config->fDeleteTwoIterators(begin,end);
786  }
787  }
788  oldProxy->Commit(alternative);
789  }
790 
791  } else {
792 
793  TClass *oldClass = config->fOldClass;
794 
795  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
796  if (!oldProxy) {
797  // Missing information, broken file ... give up
798  return;
799  }
800 
801  int objectSize = oldClass->Size();
802  char *obj = (char*)addr;
803  char *endobj = obj + conf->fLength*objectSize;
804 
805  for(; obj<endobj; obj+=objectSize) {
806  TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
807  Int_t nobjects;
808  buf.ReadInt(nobjects);
809  void* env = oldProxy->Allocate(nobjects,true);
810 
811  if (nobjects || vers < 7 ) {
812  // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
813  TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
814 
815  subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
816  }
817  oldProxy->Commit(env);
818  }
819  }
820  }
821 
823  {
824  // Collection was saved member-wise
825 
826  TConfigSTL *config = (TConfigSTL*)conf;
827 
829 
830  TClass *newClass = config->fNewClass;
831  TClass *oldClass = config->fOldClass;
832 
833  if( vers < 8 ) {
834  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
835  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
836  } else {
837 
838  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
839 
840  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
841  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
842 
843  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
844  Int_t nobjects;
845  buf.ReadInt(nobjects);
846  void* alternative = newProxy->Allocate(nobjects,true);
847  if (nobjects) {
848  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
851  void *begin = &(startbuf[0]);
852  void *end = &(endbuf[0]);
853  config->fCreateIterators( alternative, &begin, &end, newProxy);
854  // We can not get here with a split vector of pointer, so we can indeed assume
855  // that actions->fConfiguration != null.
856  buf.ApplySequence(*actions, begin, end);
857  if (begin != &(startbuf[0])) {
858  // assert(end != endbuf);
859  config->fDeleteTwoIterators(begin,end);
860  }
861  }
862  newProxy->Commit(alternative);
863  }
864  }
865 
867  {
868  // Collection was saved member-wise
869 
870  TConfigSTL *config = (TConfigSTL*)conf;
871 
873 
874  TClass *newClass = config->fNewClass;
875  TClass *oldClass = config->fOldClass;
876 
877  if( vers < 8 ) {
878  Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
879  vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
880  } else {
881 
882  Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
883 
884  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
885  TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
886 
887  int objectSize = newClass->Size();
888  char *obj = (char*)addr;
889  char *endobj = obj + conf->fLength*objectSize;
890 
891  for(; obj<endobj; obj+=objectSize) {
892  TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
893  Int_t nobjects;
894  buf.ReadInt(nobjects);
895  void* alternative = newProxy->Allocate(nobjects,true);
896  if (nobjects) {
897  TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
900  void *begin = &(startbuf[0]);
901  void *end = &(endbuf[0]);
902  config->fCreateIterators( alternative, &begin, &end, newProxy);
903  // We can not get here with a split vector of pointer, so we can indeed assume
904  // that actions->fConfiguration != null.
905  buf.ApplySequence(*actions, begin, end);
906  if (begin != &(startbuf[0])) {
907  // assert(end != endbuf);
908  config->fDeleteTwoIterators(begin,end);
909  }
910  }
911  newProxy->Commit(alternative);
912  }
913  }
914  }
915 
916 
917  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
918  {
919  TConfigSTL *config = (TConfigSTL*)conf;
920  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
921  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
922  }
923  INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
924  {
925  TConfigSTL *config = (TConfigSTL*)conf;
926  (*config->fStreamer)(buf,addr,conf->fLength);
927  }
929  {
930  // case of old TStreamerInfo
931 
932  TConfigSTL *config = (TConfigSTL*)conf;
933  // Backward compatibility. Some TStreamerElement's where without
934  // Streamer but were not removed from element list
935  if (config->fIsSTLBase || vers == 0) {
936  buf.SetBufferOffset(start); //there is no byte count
937  }
938  // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
939  buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
940  }
942  {
943  // case of old TStreamerInfo
944 
945  TConfigSTL *config = (TConfigSTL*)conf;
946  // Backward compatibility. Some TStreamerElement's where without
947  // Streamer but were not removed from element list
948  if (config->fIsSTLBase || vers == 0) {
949  buf.SetBufferOffset(start); //there is no byte count
950  }
951  (*config->fStreamer)(buf,addr,conf->fLength);
952  }
953 
954  template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
955  void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
956  INLINE_TEMPLATE_ARGS Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
957  {
958  TConfigSTL *config = (TConfigSTL*)conf;
959  UInt_t start, count;
960  Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
961  if ( vers & TBufferFile::kStreamedMemberWise ) {
962  memberwise(buf,((char*)addr)+config->fOffset,config, vers);
963  } else {
964  objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
965  }
966  buf.CheckByteCount(start,count,config->fTypeName);
967  return 0;
968  }
969 
970  template <typename From, typename To>
971  struct ConvertBasicType {
972  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
973  {
974  // Simple conversion from a 'From' on disk to a 'To' in memory.
975  From temp;
976  buf >> temp;
977  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
978  return 0;
979  }
980  };
981 
982  template <typename To>
983  struct ConvertBasicType<BitsMarker,To> {
984  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
985  {
986  // Simple conversion from a 'From' on disk to a 'To' in memory
987  UInt_t temp;
988  buf >> temp;
989 
990  if ((temp & kIsReferenced) != 0) {
991  HandleReferencedTObject(buf,addr,config);
992  }
993 
994  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
995  return 0;
996  }
997  };
998 
999  template <typename From, typename To>
1000  struct ConvertBasicType<WithFactorMarker<From>,To> {
1001  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1002  {
1003  // Simple conversion from a 'From' on disk to a 'To' in memory.
1004  TConfWithFactor *conf = (TConfWithFactor *)config;
1005  From temp;
1006  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1007  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1008  return 0;
1009  }
1010  };
1011 
1012  template <typename From, typename To>
1013  struct ConvertBasicType<NoFactorMarker<From>,To> {
1014  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1015  {
1016  // Simple conversion from a 'From' on disk to a 'To' in memory.
1017  TConfNoFactor *conf = (TConfNoFactor *)config;
1018  From temp;
1019  buf.ReadWithNbits(&temp, conf->fNbits);
1020  *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1021  return 0;
1022  }
1023  };
1024 
1025  class TConfigurationUseCache : public TConfiguration {
1026  // Configuration object for the UseCache case.
1027  public:
1028  TConfiguredAction fAction;
1029  Bool_t fNeedRepeat;
1030 
1031  TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1032  TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1033  virtual void PrintDebug(TBuffer &b, void *addr) const
1034  {
1035  if (gDebug > 1) {
1036  // Idea: We should print the name of the action function.
1037  TStreamerInfo *info = (TStreamerInfo*)fInfo;
1038  TStreamerElement *aElement = fCompInfo->fElem;
1039  fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1040  " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1041  info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1042  aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1043  }
1044 
1045  }
1046  virtual ~TConfigurationUseCache() {};
1047  virtual TConfiguration *Copy() {
1048  TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1049  fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1050  return copy;
1051  }
1052  };
1053 
1054 
1056  {
1057  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1058 
1059  Int_t bufpos = b.Length();
1060  TVirtualArray *cached = b.PeekDataCache();
1061  if (cached==0) {
1062  TStreamerElement *aElement = conf->fCompInfo->fElem;
1063  TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1064  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1065  char *ptr = (char*)addr;
1066  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1067  } else {
1068  config->fAction(b, (*cached)[0]);
1069  }
1070  // Idea: Factor out this 'if' to a UseCacheRepeat function
1071  if (config->fNeedRepeat) {
1072  b.SetBufferOffset(bufpos);
1073  }
1074  return 0;
1075  }
1076 
1077  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1078  {
1079  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1080  Int_t bufpos = b.Length();
1081 
1082  TVirtualArray *cached = b.PeekDataCache();
1083  if (cached==0) {
1084  TStreamerElement *aElement = config->fCompInfo->fElem;
1085  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1086  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1087  char *ptr = (char*)start;
1088  UInt_t n = (((void**)end)-((void**)start));
1089  info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1090  } else {
1091  TVectorLoopConfig cached_config( cached->fClass->Size(), /* read */ kTRUE );
1092  void *cached_start = (*cached)[0];
1093  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1094  config->fAction(b,cached_start,cached_end,&cached_config);
1095  }
1096  // Idea: Factor out this 'if' to a UseCacheRepeat function
1097  if (config->fNeedRepeat) {
1098  b.SetBufferOffset(bufpos);
1099  }
1100  return 0;
1101  }
1102 
1103  INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1104  {
1105  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1106 
1107  Int_t bufpos = b.Length();
1108  TVirtualArray *cached = b.PeekDataCache();
1109  if (cached==0) {
1110  TStreamerElement *aElement = config->fCompInfo->fElem;
1111  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1112  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1113  char *ptr = (char*)start;
1114  UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1115  info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1116  } else {
1117  TVectorLoopConfig cached_config( cached->fClass->Size(), /* read */ kTRUE );
1118  void *cached_start = (*cached)[0];
1119  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1120  config->fAction(b,cached_start,cached_end,&cached_config);
1121  }
1122  // Idea: Factor out this 'if' to a UseCacheRepeat function
1123  if (config->fNeedRepeat) {
1124  b.SetBufferOffset(bufpos);
1125  }
1126  return 0;
1127  }
1128 
1129  INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1130  {
1131  TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1132 
1133  Int_t bufpos = b.Length();
1134  TVirtualArray *cached = b.PeekDataCache();
1135  if (cached==0) {
1136  TStreamerElement *aElement = config->fCompInfo->fElem;
1137  TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1138 
1139  TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1140  Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1141  UInt_t n = proxy->Size();
1142  info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1143  } else {
1144  TVectorLoopConfig cached_config( cached->fClass->Size(), /* read */ kTRUE );
1145  void *cached_start = (*cached)[0];
1146  void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1147  config->fAction(b,cached_start,cached_end,&cached_config);
1148  }
1149  // Idea: Factor out this 'if' to a UseCacheRepeat function
1150  if (config->fNeedRepeat) {
1151  b.SetBufferOffset(bufpos);
1152  }
1153  return 0;
1154  }
1155 
1156  // Support for collections.
1157 
1158  Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1159  {
1160  Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1161  return 0;
1162  }
1163 
1164  Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1165  {
1166  Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1167  return 0;
1168  }
1169 
1171 
1173  {
1175  return kVectorLooper;
1176  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1180  || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1181  return kAssociativeLooper;
1182  } else {
1183  return kGenericLooper;
1184  }
1185  }
1186 
1187  struct VectorLooper {
1188 
1189  template <typename T>
1190  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1191  {
1192  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1193  iter = (char*)iter + config->fOffset;
1194  end = (char*)end + config->fOffset;
1195  for(; iter != end; iter = (char*)iter + incr ) {
1196  T *x = (T*) ((char*) iter);
1197  buf >> *x;
1198  }
1199  return 0;
1200  }
1201 
1202  template <typename From, typename To>
1203  struct ConvertBasicType {
1204  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1205  {
1206  // Simple conversion from a 'From' on disk to a 'To' in memory.
1207  From temp;
1208  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1209  iter = (char*)iter + config->fOffset;
1210  end = (char*)end + config->fOffset;
1211  for(; iter != end; iter = (char*)iter + incr ) {
1212  buf >> temp;
1213  *(To*)( ((char*)iter) ) = (To)temp;
1214  }
1215  return 0;
1216  }
1217  };
1218 
1219  template <typename To>
1220  struct ConvertBasicType<BitsMarker,To> {
1221  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1222  {
1223  // Simple conversion from a 'From' on disk to a 'To' in memory.
1224  UInt_t temp;
1225  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1226  iter = (char*)iter + config->fOffset;
1227  end = (char*)end + config->fOffset;
1228  for(; iter != end; iter = (char*)iter + incr ) {
1229  buf >> temp;
1230 
1231  if ((temp & kIsReferenced) != 0) {
1232  HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1233  }
1234 
1235  *(To*)( ((char*)iter) ) = (To)temp;
1236  }
1237  return 0;
1238  }
1239  };
1240 
1241  template <typename From, typename To>
1242  struct ConvertBasicType<WithFactorMarker<From>,To> {
1243  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1244  {
1245  // Simple conversion from a 'From' on disk to a 'To' in memory.
1246  TConfWithFactor *conf = (TConfWithFactor *)config;
1247  From temp;
1248  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1249  iter = (char*)iter + config->fOffset;
1250  end = (char*)end + config->fOffset;
1251  for(; iter != end; iter = (char*)iter + incr ) {
1252  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1253  *(To*)( ((char*)iter) ) = (To)temp;
1254  }
1255  return 0;
1256  }
1257  };
1258 
1259  template <typename From, typename To>
1260  struct ConvertBasicType<NoFactorMarker<From>,To> {
1261  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1262  {
1263  // Simple conversion from a 'From' on disk to a 'To' in memory.
1264  TConfNoFactor *conf = (TConfNoFactor *)config;
1265  From temp;
1266  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1267  iter = (char*)iter + config->fOffset;
1268  end = (char*)end + config->fOffset;
1269  for(; iter != end; iter = (char*)iter + incr ) {
1270  buf.ReadWithNbits(&temp, conf->fNbits);
1271  *(To*)( ((char*)iter) ) = (To)temp;
1272  }
1273  return 0;
1274  }
1275  };
1276 
1277  template <typename T>
1278  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1279  {
1280  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1281  iter = (char*)iter + config->fOffset;
1282  end = (char*)end + config->fOffset;
1283  for(; iter != end; iter = (char*)iter + incr ) {
1284  T *x = (T*) ((char*) iter);
1285  buf << *x;
1286  }
1287  return 0;
1288  }
1289 
1290  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1291  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1292  {
1293  const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1294  //Idea: can we factor out the addition of fOffset
1295  // iter = (char*)iter + config->fOffset;
1296  for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1297  iter_action(buf, iter, config);
1298  }
1299  return 0;
1300  }
1301 
1302  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1303  {
1304  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1305  // punt.
1306 
1307  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1308  UInt_t n = (((char*)end)-((char*)start))/incr;
1309  char **arrptr = new char*[n];
1310  UInt_t i = 0;
1311  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1312  arrptr[i] = (char*)iter;
1313  }
1314  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1315  delete [] arrptr;
1316 
1317  // // Idea: need to cache this result!
1318  // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1319  // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1320  //
1321  // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1322  // *TClass *cle = aElement->GetNewBaseClass();
1323  // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1324  //
1325  // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1326  //
1327  // actions->ReadBuffer(b,start,end);
1328  // delete actions;
1329 
1330  // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1331  // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1332  // {
1333  // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1334  //
1335  // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1336  // }
1337  return 0;
1338  }
1339 
1340  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1341  {
1342  // Well the implementation is non trivial. For now punt.
1343 
1344  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1345  UInt_t n = (((char*)end)-((char*)start))/incr;
1346  char **arrptr = new char*[n];
1347  UInt_t i = 0;
1348  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1349  arrptr[i] = (char*)iter;
1350  }
1351  ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1352  delete [] arrptr;
1353  return 0;
1354  }
1355 
1356  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1357  {
1358  // Well the implementation is non trivial. For now punt.
1359 
1360  UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1361  UInt_t n = (((char*)end)-((char*)start))/incr;
1362  char **arrptr = new char*[n];
1363  UInt_t i = 0;
1364  for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1365  arrptr[i] = (char*)iter;
1366  }
1367  ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1368  delete [] arrptr;
1369  return 0;
1370  }
1371 
1372  template <typename T>
1373  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1374  {
1375  // Collection of numbers. Memberwise or not, it is all the same.
1376 
1377  TConfigSTL *config = (TConfigSTL*)conf;
1378  UInt_t start, count;
1379  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1380 
1381  std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1382  Int_t nvalues;
1383  buf.ReadInt(nvalues);
1384  vec->resize(nvalues);
1385 
1386 #ifdef R__VISUAL_CPLUSPLUS
1387  if (nvalues <= 0) {
1388  buf.CheckByteCount(start,count,config->fTypeName);
1389  return 0;
1390  }
1391 #endif
1392  T *begin = &(*vec->begin());
1393  buf.ReadFastArray(begin, nvalues);
1394 
1395  buf.CheckByteCount(start,count,config->fTypeName);
1396  return 0;
1397  }
1398 
1399  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1400  {
1401  // Collection of numbers. Memberwise or not, it is all the same.
1402 
1403  TConfigSTL *config = (TConfigSTL*)conf;
1404  UInt_t start, count;
1405  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1406 
1407  std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1408  Int_t nvalues;
1409  buf.ReadInt(nvalues);
1410  vec->resize(nvalues);
1411 
1412  bool *items = new bool[nvalues];
1413  buf.ReadFastArray(items, nvalues);
1414  for(Int_t i = 0 ; i < nvalues; ++i) {
1415  (*vec)[i] = items[i];
1416  }
1417  delete [] items;
1418 
1419  // We could avoid the call to ReadFastArray, and we could
1420  // the following, however this breaks TBufferXML ...
1421  // for(Int_t i = 0 ; i < nvalues; ++i) {
1422  // bool tmp; buf >> tmp;
1423  // (*vec)[i] = tmp;
1424  // }
1425 
1426  buf.CheckByteCount(start,count,config->fTypeName);
1427  return 0;
1428  }
1429 
1430  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1431  {
1432  // Collection of numbers. Memberwise or not, it is all the same.
1433 
1434  TConfigSTL *config = (TConfigSTL*)conf;
1435  UInt_t start, count;
1436  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1437 
1438  std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1439  Int_t nvalues;
1440  buf.ReadInt(nvalues);
1441  vec->resize(nvalues);
1442 
1443 #ifdef R__VISUAL_CPLUSPLUS
1444  if (nvalues <= 0) {
1445  buf.CheckByteCount(start,count,config->fTypeName);
1446  return 0;
1447  }
1448 #endif
1449  float *begin = &(*vec->begin());
1450  buf.ReadFastArrayFloat16(begin, nvalues);
1451 
1452  buf.CheckByteCount(start,count,config->fTypeName);
1453  return 0;
1454  }
1455 
1456  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1457  {
1458  // Collection of numbers. Memberwise or not, it is all the same.
1459 
1460  TConfigSTL *config = (TConfigSTL*)conf;
1461  UInt_t start, count;
1462  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1463 
1464  std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1465  Int_t nvalues;
1466  buf.ReadInt(nvalues);
1467  vec->resize(nvalues);
1468 
1469 #ifdef R__VISUAL_CPLUSPLUS
1470  if (nvalues <= 0) {
1471  buf.CheckByteCount(start,count,config->fTypeName);
1472  return 0;
1473  }
1474 #endif
1475  double *begin = &(*vec->begin());
1476  buf.ReadFastArrayDouble32(begin, nvalues);
1477 
1478  buf.CheckByteCount(start,count,config->fTypeName);
1479  return 0;
1480  }
1481 
1482  template <typename From, typename To>
1483  struct ConvertCollectionBasicType {
1484  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1485  {
1486  // Collection of numbers. Memberwise or not, it is all the same.
1487 
1488  TConfigSTL *config = (TConfigSTL*)conf;
1489  UInt_t start, count;
1490  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1491 
1492  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1493  Int_t nvalues;
1494  buf.ReadInt(nvalues);
1495  vec->resize(nvalues);
1496 
1497  From *temp = new From[nvalues];
1498  buf.ReadFastArray(temp, nvalues);
1499  for(Int_t ind = 0; ind < nvalues; ++ind) {
1500  (*vec)[ind] = (To)temp[ind];
1501  }
1502  delete [] temp;
1503 
1504  buf.CheckByteCount(start,count,config->fTypeName);
1505  return 0;
1506  }
1507  };
1508 
1509  template <typename From, typename To>
1510  struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
1511  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1512  {
1513  // Collection of numbers. Memberwise or not, it is all the same.
1514 
1515  TConfigSTL *config = (TConfigSTL*)conf;
1516  UInt_t start, count;
1517  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1518 
1519  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1520  Int_t nvalues;
1521  buf.ReadInt(nvalues);
1522  vec->resize(nvalues);
1523 
1524  From *temp = new From[nvalues];
1525  buf.ReadFastArrayWithNbits(temp, nvalues, 0);
1526  for(Int_t ind = 0; ind < nvalues; ++ind) {
1527  (*vec)[ind] = (To)temp[ind];
1528  }
1529  delete [] temp;
1530 
1531  buf.CheckByteCount(start,count,config->fTypeName);
1532  return 0;
1533  }
1534  };
1535 
1536  template <typename To>
1537  static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1538  {
1539  // Collection of numbers. Memberwise or not, it is all the same.
1540 
1541  TConfigSTL *config = (TConfigSTL*)conf;
1542  UInt_t start, count;
1543  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1544 
1545  std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
1546  Int_t nvalues;
1547  buf.ReadInt(nvalues);
1548  vec->resize(nvalues);
1549 
1550  Double32_t *temp = new Double32_t[nvalues];
1551  buf.ReadFastArrayDouble32(temp, nvalues);
1552  for(Int_t ind = 0; ind < nvalues; ++ind) {
1553  (*vec)[ind] = (To)temp[ind];
1554  }
1555  delete [] temp;
1556 
1557  buf.CheckByteCount(start,count,config->fTypeName);
1558  return 0;
1559  }
1560 
1561  };
1562 
1563  struct VectorPtrLooper {
1564 
1565  template <typename T>
1566  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1567  {
1568  const Int_t offset = config->fOffset;
1569 
1570  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1571  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
1572  buf >> *x;
1573  }
1574  return 0;
1575  }
1576 
1577  template <typename From, typename To>
1578  struct ConvertBasicType {
1579  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1580  {
1581  // Simple conversion from a 'From' on disk to a 'To' in memory.
1582  From temp;
1583  const Int_t offset = config->fOffset;
1584  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1585  buf >> temp;
1586  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1587  *x = (To)temp;
1588  }
1589  return 0;
1590  }
1591  };
1592 
1593  template <typename To>
1594  struct ConvertBasicType<BitsMarker,To> {
1595  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1596  {
1597  // Simple conversion from a 'From' on disk to a 'To' in memory.
1598  UInt_t temp;
1599  const Int_t offset = config->fOffset;
1600  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1601  buf >> temp;
1602 
1603  if ((temp & kIsReferenced) != 0) {
1604  HandleReferencedTObject(buf,*(void**)iter,config);
1605  }
1606 
1607  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1608  *x = (To)temp;
1609  }
1610  return 0;
1611  }
1612  };
1613 
1614  template <typename From, typename To>
1615  struct ConvertBasicType<WithFactorMarker<From>,To> {
1616  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1617  {
1618  // Simple conversion from a 'From' on disk to a 'To' in memory.
1619  TConfWithFactor *conf = (TConfWithFactor *)config;
1620  From temp;
1621  const Int_t offset = config->fOffset;
1622  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1623  buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1624  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1625  *x = (To)temp;
1626  }
1627  return 0;
1628  }
1629  };
1630 
1631  template <typename From, typename To>
1632  struct ConvertBasicType<NoFactorMarker<From>,To> {
1633  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1634  {
1635  // Simple conversion from a 'From' on disk to a 'To' in memory.
1636  TConfNoFactor *conf = (TConfNoFactor *)config;
1637  From temp;
1638  const Int_t offset = config->fOffset;
1639  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1640  buf.ReadWithNbits(&temp, conf->fNbits);
1641  To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
1642  *x = (To)temp;
1643  }
1644  return 0;
1645  }
1646  };
1647 
1648  template <typename T>
1649  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1650  {
1651  const Int_t offset = config->fOffset;
1652 
1653  for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
1654  T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
1655  buf << *x;
1656  }
1657  return 0;
1658  }
1659 
1660  template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
1661  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
1662  {
1663  for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
1664  action(buf, *(void**)iter, config);
1665  }
1666  return 0;
1667  }
1668 
1669  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
1670  {
1671  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1672  // punt.
1673 
1674  return GenericRead(buf,start,end,config);
1675  }
1676 
1677  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1678  {
1679  Int_t n = ( ((void**)end) - ((void**)iter) );
1680  char **arr = (char**)iter;
1681  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1682  }
1683 
1684  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
1685  {
1686  Int_t n = ( ((void**)end) - ((void**)iter) );
1687  char **arr = (char**)iter;
1688  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1689  }
1690 
1691  };
1692 
1693  struct AssociativeLooper {
1694 
1695  template <typename T>
1696  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
1697  {
1698  buf.ReadFastArray((T*)addr, nvalues);
1699  }
1700 
1701  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
1702  {
1703  buf.ReadFastArrayFloat16((float*)addr, nvalues);
1704  }
1705 
1706  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
1707  {
1708  buf.ReadFastArrayDouble32((double*)addr, nvalues);
1709  }
1710 
1711  template <typename T,void (*action)(TBuffer&,void *,Int_t)>
1712  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
1713  {
1714  // Collection of numbers. Memberwise or not, it is all the same.
1715 
1716  TConfigSTL *config = (TConfigSTL*)conf;
1717  UInt_t start, count;
1718  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1719 
1720  TClass *newClass = config->fNewClass;
1721  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1722  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
1723 
1724  Int_t nvalues;
1725  buf.ReadInt(nvalues);
1726  void* alternative = newProxy->Allocate(nvalues,true);
1727  if (nvalues) {
1730  void *begin = &(startbuf[0]);
1731  void *end = &(endbuf[0]);
1732  config->fCreateIterators(alternative, &begin, &end, newProxy);
1733  // We can not get here with a split vector of pointer, so we can indeed assume
1734  // that actions->fConfiguration != null.
1735 
1736  action(buf,begin,nvalues);
1737 
1738  if (begin != &(startbuf[0])) {
1739  // assert(end != endbuf);
1740  config->fDeleteTwoIterators(begin,end);
1741  }
1742  }
1743  newProxy->Commit(alternative);
1744 
1745  buf.CheckByteCount(start,count,config->fTypeName);
1746  return 0;
1747  }
1748 
1749  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1750  {
1751  return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
1752  }
1753 
1754  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1755  {
1756  return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
1757  }
1758 
1759  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1760  {
1761  return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
1762  }
1763 
1764  template <typename T>
1765  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1766  {
1767  return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
1768  }
1769 
1770  template <typename From, typename To>
1771  struct ConvertRead {
1772  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1773  {
1774  From *temp = new From[nvalues];
1775  buf.ReadFastArray(temp, nvalues);
1776  To *vec = (To*)addr;
1777  for(Int_t ind = 0; ind < nvalues; ++ind) {
1778  vec[ind] = (To)temp[ind];
1779  }
1780  delete [] temp;
1781  }
1782  };
1783 
1784  template <typename From, typename To>
1785  struct ConvertRead<NoFactorMarker<From>,To> {
1786  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1787  {
1788  From *temp = new From[nvalues];
1789  buf.ReadFastArrayWithNbits(temp, nvalues,0);
1790  To *vec = (To*)addr;
1791  for(Int_t ind = 0; ind < nvalues; ++ind) {
1792  vec[ind] = (To)temp[ind];
1793  }
1794  delete [] temp;
1795  }
1796  };
1797 
1798  template <typename From, typename To>
1799  struct ConvertRead<WithFactorMarker<From>,To> {
1800  static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
1801  {
1802  From *temp = new From[nvalues];
1803  double factor,min; // needs to be initialized.
1804  buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
1805  To *vec = (To*)addr;
1806  for(Int_t ind = 0; ind < nvalues; ++ind) {
1807  vec[ind] = (To)temp[ind];
1808  }
1809  delete [] temp;
1810  }
1811  };
1812 
1813  template <typename From, typename To>
1814  struct ConvertCollectionBasicType {
1815  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1816  {
1817  return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
1818  }
1819  };
1820 
1821  };
1822 
1823  struct GenericLooper {
1824 
1825  template <typename T>
1826  static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1827  {
1828  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1829 
1830  Next_t next = loopconfig->fNext;
1831  const Int_t offset = config->fOffset;
1832 
1834  void *iter = loopconfig->fCopyIterator(iterator,start);
1835  void *addr;
1836  while( (addr = next(iter,end)) ) {
1837  T *x = (T*)( ((char*)addr) + offset );
1838  buf >> *x;
1839  }
1840  if (iter != &iterator[0]) {
1841  loopconfig->fDeleteIterator(iter);
1842  }
1843  return 0;
1844  }
1845 
1846  template <typename T>
1847  static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1848  {
1849  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1850 
1851  Next_t next = loopconfig->fNext;
1852  const Int_t offset = config->fOffset;
1853 
1855  void *iter = loopconfig->fCopyIterator(iterator,start);
1856  void *addr;
1857  while( (addr = next(iter,end)) ) {
1858  T *x = (T*)( ((char*)addr) + offset );
1859  buf << *x;
1860  }
1861  if (iter != &iterator[0]) {
1862  loopconfig->fDeleteIterator(iter);
1863  }
1864  return 0;
1865  }
1866 
1867  template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1868  static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1869  {
1870  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1871 
1872  // const Int_t offset = config->fOffset;
1873  Next_t next = loopconfig->fNext;
1874 
1876  void *iter = loopconfig->fCopyIterator(&iterator,start);
1877  void *addr;
1878  while( (addr = next(iter,end)) ) {
1879  iter_action(buf, addr, config);
1880  }
1881  if (iter != &iterator[0]) {
1882  loopconfig->fDeleteIterator(iter);
1883  }
1884  return 0;
1885  }
1886 
1887  template <typename From, typename To>
1888  struct Generic {
1889  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1890  {
1891  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1892 
1893  const Int_t offset = config->fOffset;
1894  Next_t next = loopconfig->fNext;
1895 
1897  void *iter = loopconfig->fCopyIterator(&iterator,start);
1898  void *addr;
1899  while( (addr = next(iter,end)) ) {
1900  To *x = (To*)( ((char*)addr) + offset );
1901  *x = (To)(*items);
1902  ++items;
1903  }
1904  if (iter != &iterator[0]) {
1905  loopconfig->fDeleteIterator(iter);
1906  }
1907  }
1908  };
1909 
1910  template <typename From, typename To>
1911  struct Numeric {
1912  static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
1913  {
1914  // The difference with ConvertAction is that we can modify the start
1915  // iterator and skip the copy. We also never have an offset.
1916 
1917  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1918  Next_t next = loopconfig->fNext;
1919 
1920  void *iter = start;
1921  void *addr;
1922  while( (addr = next(iter,end)) ) {
1923  To *x = (To*)(addr);
1924  *x = (To)(*items);
1925  ++items;
1926  }
1927  }
1928  };
1929 
1930  template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
1931  struct ConvertBasicType {
1932  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1933  {
1934  // Simple conversion from a 'From' on disk to a 'To' in memory.
1935 
1936  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1937  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
1938  Int_t nvalues = proxy->Size();
1939 
1940  From *items = new From[nvalues];
1941  buf.ReadFastArray(items, nvalues);
1942  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
1943  delete [] items;
1944  return 0;
1945  }
1946  };
1947 
1948  template <typename To>
1949  struct ConvertBasicType<BitsMarker, To, Generic> {
1950  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1951  {
1952  // Simple conversion from a 'From' on disk to a 'To' in memory.
1953 
1954  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1955  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
1956  Int_t nvalues = proxy->Size();
1957 
1958  UInt_t *items_storage = new UInt_t[nvalues];
1959  UInt_t *items = items_storage;
1960 
1961  const Int_t offset = config->fOffset;
1962  Next_t next = loopconfig->fNext;
1963 
1965  void *iter = loopconfig->fCopyIterator(&iterator,start);
1966  void *addr;
1967  while( (addr = next(iter,end)) ) {
1968  buf >> (*items);
1969  if (((*items) & kIsReferenced) != 0) {
1970  HandleReferencedTObject(buf, addr, config);
1971  }
1972  To *x = (To*)( ((char*)addr) + offset );
1973  *x = (To)(*items);
1974  ++items;
1975  }
1976  if (iter != &iterator[0]) {
1977  loopconfig->fDeleteIterator(iter);
1978  }
1979 
1980  delete [] items_storage;
1981  return 0;
1982  }
1983  };
1984 
1985  template <typename From, typename To, template <typename F, typename T> class Converter >
1986  struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
1987  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
1988  {
1989  // Simple conversion from a 'From' on disk to a 'To' in memory.
1990 
1991  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
1992  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
1993  Int_t nvalues = proxy->Size();
1994 
1995  TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
1996 
1997  From *items = new From[nvalues];
1998  buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
1999  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2000  delete [] items;
2001  return 0;
2002  }
2003  };
2004 
2005  template <typename From, typename To, template <typename F, typename T> class Converter >
2006  struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2007  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2008  {
2009  // Simple conversion from a 'From' on disk to a 'To' in memory.
2010 
2011  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2012  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2013  Int_t nvalues = proxy->Size();
2014 
2015  TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2016 
2017  From *items = new From[nvalues];
2018  buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2019  Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2020  delete [] items;
2021  return 0;
2022  }
2023  };
2024 
2025  static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2026  {
2027  // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2028  // punt.
2029 
2030  return GenericRead(buf,start,end,loopconfig, config);
2031  }
2032 
2033  static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2034  {
2035  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2036  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2037  return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2038  }
2039 
2040  static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2041  {
2042  TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2043  TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2044  return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2045  }
2046 
2047  template <typename T>
2048  static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2049  {
2050  buf >> *(T*)addr;
2051  }
2052 
2053  static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2054  {
2055  buf.ReadWithNbits((float*)addr,12);
2056  }
2057 
2058  static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2059  {
2060  //we read a float and convert it to double
2061  Float_t afloat;
2062  buf >> afloat;
2063  *(double*)addr = (Double_t)afloat;
2064  }
2065 
2066  template <typename ActionHolder>
2067  static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2068  {
2069  // Collection of numbers. Memberwise or not, it is all the same.
2070 
2071  TConfigSTL *config = (TConfigSTL*)conf;
2072  UInt_t start, count;
2073  /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2074 
2075  TClass *newClass = config->fNewClass;
2076  TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2077  TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2078 
2079  Int_t nvalues;
2080  buf.ReadInt(nvalues);
2081  void* alternative = newProxy->Allocate(nvalues,true);
2082  if (nvalues) {
2085  void *begin = &(startbuf[0]);
2086  void *end = &(endbuf[0]);
2087  config->fCreateIterators(alternative, &begin, &end, newProxy);
2088  // We can not get here with a split vector of pointer, so we can indeed assume
2089  // that actions->fConfiguration != null.
2090 
2091  TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2092  ActionHolder::Action(buf,begin,end,&loopconf,config);
2093 
2094  if (begin != &(startbuf[0])) {
2095  // assert(end != endbuf);
2096  config->fDeleteTwoIterators(begin,end);
2097  }
2098  }
2099  newProxy->Commit(alternative);
2100 
2101  buf.CheckByteCount(start,count,config->fTypeName);
2102  return 0;
2103  }
2104 
2105  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2106  {
2107  return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2108  }
2109 
2110  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2111  {
2112  return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2113  }
2114 
2115  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2116  {
2117  return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2118  // Could also use:
2119  // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2120  }
2121 
2122  template <typename T>
2123  static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2124  {
2125  return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2126  }
2127 
2128  template <typename From, typename To>
2129  struct ConvertCollectionBasicType {
2130  static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2131  {
2132  // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2133  return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2134  }
2135  };
2136 
2137  };
2138 }
2139 
2140 template <typename Looper, typename From>
2142 {
2143  switch (newtype) {
2144  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2145  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2146  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2147  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2148  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2149  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2150  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2151  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2152  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2153  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2154  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2155  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2156  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2157  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2158  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2159  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2160  default:
2161  return TConfiguredAction( Looper::GenericRead, conf );
2162  break;
2163  }
2164  R__ASSERT(0); // We should never be here
2165  return TConfiguredAction();
2166 }
2167 
2168 template <class Looper>
2170 {
2171  // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2172 
2173  switch (type) {
2174  // Read basic types.
2175  case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2176  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2177  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2178  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2179  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2180  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2181  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2182  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2183  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2184  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2185  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2186  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2187  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2188  case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2189  case TStreamerInfo::kFloat16: {
2190  TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2191  delete conf;
2192  return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2193  // if (element->GetFactor() != 0) {
2194  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2195  // } else {
2196  // Int_t nbits = (Int_t)element->GetXmin();
2197  // if (!nbits) nbits = 12;
2198  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2199  // }
2200  break;
2201  }
2202  case TStreamerInfo::kDouble32: {
2203  TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2204  delete conf;
2205  return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2206  // if (element->GetFactor() != 0) {
2207  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2208  // } else {
2209  // Int_t nbits = (Int_t)element->GetXmin();
2210  // if (!nbits) {
2211  // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2212  // } else {
2213  // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2214  // }
2215  // }
2216  break;
2217  }
2218  }
2219  Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2220  R__ASSERT(0); // We should never be here
2221  return TConfiguredAction();
2222 }
2223 
2224 template <typename Looper, typename From>
2226 {
2227  switch (newtype) {
2228  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2229  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2230  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2231  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2232  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2233  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2234  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2235  case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2236  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2237  case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2238  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2239  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2240  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2241  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2242  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2243  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2244  default:
2245  break;
2246  }
2247  R__ASSERT(0); // We should never be here
2248  return TConfiguredAction();
2249 }
2250 
2251 template <typename Looper>
2253 {
2254  switch (oldtype) {
2255  case TStreamerInfo::kBool:
2256  return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2257  break;
2258  case TStreamerInfo::kChar:
2259  return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2260  break;
2261  case TStreamerInfo::kShort:
2262  return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2263  break;
2264  case TStreamerInfo::kInt:
2265  return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2266  break;
2267  case TStreamerInfo::kLong:
2268  return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2269  break;
2271  return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2272  break;
2273  case TStreamerInfo::kFloat:
2274  return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2275  break;
2277  return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2278  break;
2279  case TStreamerInfo::kUChar:
2280  return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2281  break;
2283  return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2284  break;
2285  case TStreamerInfo::kUInt:
2286  return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2287  break;
2288  case TStreamerInfo::kULong:
2289  return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2290  break;
2292  return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2293  break;
2295  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2296  break;
2298  return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2299  break;
2300  case TStreamerInfo::kBits:
2301  Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2302  break;
2303  default:
2304  break;
2305  }
2306  R__ASSERT(0); // We should never be here
2307  return TConfiguredAction();
2308 }
2309 
2310 template <class Looper>
2312 {
2313  switch (type) {
2314  // Read basic types.
2315  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2316  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2317  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2318  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2319  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2320  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2321  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2322  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2323  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2324  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2325  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2326  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2327  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2328  case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2329  case TStreamerInfo::kFloat16: {
2330  if (element->GetFactor() != 0) {
2331  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2332  } else {
2333  Int_t nbits = (Int_t)element->GetXmin();
2334  if (!nbits) nbits = 12;
2335  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2336  }
2337  break;
2338  }
2339  case TStreamerInfo::kDouble32: {
2340  if (element->GetFactor() != 0) {
2341  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2342  } else {
2343  Int_t nbits = (Int_t)element->GetXmin();
2344  if (!nbits) {
2345  return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2346  } else {
2347  return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2348  }
2349  }
2350  break;
2351  }
2352  case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2353  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2354  // Streamer alltogether.
2355  case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2356  case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2360  case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2361  case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2362 
2363  // Conversions.
2365  return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2366  break;
2368  return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2369  break;
2371  return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2372  break;
2374  return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2375  break;
2377  return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2378  break;
2380  return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2381  break;
2383  return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2384  break;
2386  return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2387  break;
2389  return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2390  break;
2392  return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2393  break;
2395  return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2396  break;
2398  return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2399  break;
2401  return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2402  break;
2404  return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2405  break;
2407  if (element->GetFactor() != 0) {
2408  return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2409  } else {
2410  Int_t nbits = (Int_t)element->GetXmin();
2411  if (!nbits) nbits = 12;
2412  return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2413  }
2414  break;
2415  }
2417  if (element->GetFactor() != 0) {
2418  return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2419  } else {
2420  Int_t nbits = (Int_t)element->GetXmin();
2421  if (!nbits) {
2422  return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2423  } else {
2424  return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2425  }
2426  }
2427  break;
2428  }
2429  default:
2430  return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2431  break;
2432  }
2433  R__ASSERT(0); // We should never be here
2434  return TConfiguredAction();
2435 }
2436 
2437 template <class Looper>
2439  switch (type) {
2440  // read basic types
2441  case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2442  case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2443  case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2444  case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2445  case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2446  case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2447  case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2448  case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2449  case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2450  case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2451  case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2452  case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2453  case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2454  // the simple type missing are kBits and kCounter.
2455  default:
2456  return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2457  }
2458  R__ASSERT(0); // We should never be here
2459  return TConfiguredAction();
2460 }
2461 
2462 
2463 ////////////////////////////////////////////////////////////////////////////////
2464 /// loop on the TStreamerElement list
2465 /// regroup members with same type
2466 /// Store predigested information into local arrays. This saves a huge amount
2467 /// of time compared to an explicit iteration on all elements.
2468 
2470 {
2471  if (IsCompiled()) {
2472  //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
2473  return;
2474  }
2476 
2477  // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
2478 
2479  // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
2480  fOptimized = kFALSE;
2481  fNdata = 0;
2482  fNfulldata = 0;
2483 
2484  TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
2485  if (fNumber >= infos->GetSize()) {
2486  infos->AddAtAndExpand(this, fNumber);
2487  } else {
2488  if (!infos->At(fNumber)) {
2489  infos->AddAt(this, fNumber);
2490  }
2491  }
2492 
2493  assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
2494 
2495 
2496  Int_t ndata = fElements->GetEntries();
2497 
2498 
2501 
2504 
2507 
2510 
2513 
2516 
2517  if (fWriteText) fWriteText->fActions.clear();
2518  else fWriteText = new TStreamerInfoActions::TActionSequence(this,ndata);
2519 
2520  if (!ndata) {
2521  // This may be the case for empty classes (e.g., TAtt3D).
2522  // We still need to properly set the size of emulated classes (i.e. add the virtual table)
2524  fSize = sizeof(TStreamerInfo*);
2525  }
2526  fComp = new TCompInfo[1];
2527  fCompFull = new TCompInfo*[1];
2528  fCompOpt = new TCompInfo*[1];
2529  fCompOpt[0] = fCompFull[0] = &(fComp[0]);
2530  SetIsCompiled();
2531  return;
2532  }
2533 
2534  // At most half of the elements can be used to hold optimized versions.
2535  // We use the bottom to hold the optimized-into elements and the non-optimized elements
2536  // and the top to hold the original copy of the optimized out elements.
2537  fNslots = ndata + ndata/2 + 1;
2538  Int_t optiOut = 0;
2539 
2540  fComp = new TCompInfo[fNslots];
2541  fCompFull = new TCompInfo*[ndata];
2542  fCompOpt = new TCompInfo*[ndata];
2543 
2544  TStreamerElement* element;
2545  TStreamerElement* previous = 0;
2546  Int_t keep = -1;
2547  Int_t i;
2548 
2549  if (!CanOptimize()) {
2551  }
2552 
2553  Bool_t isOptimized = kFALSE;
2554  Bool_t previousOptimized = kFALSE;
2555 
2556  for (i = 0; i < ndata; ++i) {
2557  element = (TStreamerElement*) fElements->At(i);
2558  if (!element) {
2559  break;
2560  }
2561 
2562  Int_t asize = element->GetSize();
2563  if (element->GetArrayLength()) {
2564  asize /= element->GetArrayLength();
2565  }
2566  fComp[fNdata].fType = element->GetType();
2567  fComp[fNdata].fNewType = element->GetNewType();
2568  fComp[fNdata].fOffset = element->GetOffset();
2569  fComp[fNdata].fLength = element->GetArrayLength();
2570  fComp[fNdata].fElem = element;
2571  fComp[fNdata].fMethod = element->GetMethod();
2572  fComp[fNdata].fClass = element->GetClassPointer();
2573  fComp[fNdata].fNewClass = element->GetNewClass();
2574  fComp[fNdata].fClassName = TString(element->GetTypeName()).Strip(TString::kTrailing, '*');
2575  fComp[fNdata].fStreamer = element->GetStreamer();
2576 
2577  // try to group consecutive members of the same type
2578  if (!TestBit(kCannotOptimize)
2579  && (keep >= 0)
2580  && (element->GetType() >=0)
2581  && (element->GetType() < 10)
2582  && (fComp[fNdata].fType == fComp[fNdata].fNewType)
2583  && (fComp[keep].fMethod == 0)
2584  && (element->GetType() > 0)
2585  && (element->GetArrayDim() == 0)
2586  && (fComp[keep].fType < kObject)
2587  && (fComp[keep].fType != kCharStar) /* do not optimize char* */
2588  && (element->GetType() == (fComp[keep].fType%kRegrouped))
2589  && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
2590  && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
2591  ((element->GetFactor() == previous->GetFactor())
2592  && (element->GetXmin() == previous->GetXmin())
2593  && (element->GetXmax() == previous->GetXmax())
2594  )
2595  )
2598  // kWholeObject and kDoNotDelete do not apply to numerical elements.
2599  )
2600  {
2601  if (!previousOptimized) {
2602  // The element was not yet optimized we first need to copy it into
2603  // the set of original copies.
2604  fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
2605  fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
2606  }
2607  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
2608  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
2609 
2610  R__ASSERT( keep < (fNslots - optiOut) );
2611 
2612  if (fComp[keep].fLength == 0) {
2613  fComp[keep].fLength++;
2614  }
2615  fComp[keep].fLength++;
2616  fComp[keep].fType = element->GetType() + kRegrouped;
2617  isOptimized = kTRUE;
2618  previousOptimized = kTRUE;
2619  } else if (element->GetType() < 0) {
2620 
2621  // -- Deal with an ignored TObject base class.
2622  // Note: The only allowed negative value here is -1,
2623  // and signifies that Build() has found a TObject
2624  // base class and TClass::IgnoreTObjectStreamer() was
2625  // called. In this case the compiled version of the
2626  // elements omits the TObject base class element,
2627  // which has to be compensated for by TTree::Bronch()
2628  // when it is making branches for a split object.
2629  fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
2630  fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
2631  keep = -1;
2632  previousOptimized = kFALSE;
2633 
2634  } else {
2635  if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
2636  if (fComp[fNdata].fNewType > 0) {
2637  if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
2638  || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
2639  || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
2640  && (fComp[fNdata].fType == kObjectp || fComp[fNdata].fType == kAnyp
2641  || fComp[fNdata].fType == kObject || fComp[fNdata].fType == kAny
2643  ) {
2645  } else if (fComp[fNdata].fType != kCounter) {
2646  fComp[fNdata].fType += kConv;
2647  }
2648  } else {
2649  if (fComp[fNdata].fType == kCounter) {
2650  Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
2651  }
2652  fComp[fNdata].fType += kSkip;
2653  }
2654  }
2655  fCompOpt[fNdata] = &(fComp[fNdata]);
2657 
2658  R__ASSERT( fNdata < (fNslots - optiOut) );
2659 
2660  keep = fNdata;
2661  if (fComp[keep].fLength == 0) {
2662  fComp[keep].fLength = 1;
2663  }
2664  fNdata++;
2665  previousOptimized = kFALSE;
2666  }
2667  // The test 'fMethod[keep] == 0' fails to detect a variable size array
2668  // if the counter happens to have an offset of zero, so let's explicitly
2669  // prevent for here.
2670  if (element->HasCounter()) keep = -1;
2671  ++fNfulldata;
2672  previous = element;
2673  }
2674 
2675  for (i = 0; i < fNdata; ++i) {
2676  if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
2677  continue;
2678  }
2681  }
2682  for (i = 0; i < fNfulldata; ++i) {
2683  if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
2684  continue;
2685  }
2690 
2692  }
2693  ComputeSize();
2694 
2695  fOptimized = isOptimized;
2696  SetIsCompiled();
2697 
2698  if (gDebug > 0) {
2699  ls();
2700  }
2701 }
2702 
2703 template <typename From>
2705 {
2706  switch (newtype) {
2707  case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
2708  case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
2709  case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
2710  case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
2711  case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
2712  case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
2713  case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
2714  case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
2715  case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
2716  case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
2717  case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
2718  case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
2719  case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
2720  case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
2721  case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
2722  case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
2723  }
2724 }
2725 
2726 ////////////////////////////////////////////////////////////////////////////////
2727 /// Add a read action for the given element.
2728 
2730 {
2731  TStreamerElement *element = compinfo->fElem;
2732 
2733  if (element->TestBit(TStreamerElement::kWrite)) return;
2734 
2735  switch (compinfo->fType) {
2736  // read basic types
2737  case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2738  case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2739  case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2740  case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2741  case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2742  case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2743  case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2744  case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2745  case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2746  case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2747  case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2748  case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2749  case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2750  case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2751  case TStreamerInfo::kFloat16: {
2752  if (element->GetFactor() != 0) {
2753  readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2754  } else {
2755  Int_t nbits = (Int_t)element->GetXmin();
2756  if (!nbits) nbits = 12;
2757  readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2758  }
2759  break;
2760  }
2761  case TStreamerInfo::kDouble32: {
2762  if (element->GetFactor() != 0) {
2763  readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2764  } else {
2765  Int_t nbits = (Int_t)element->GetXmin();
2766  if (!nbits) {
2767  readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2768  } else {
2769  readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2770  }
2771  }
2772  break;
2773  }
2774  case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2775  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2776  // Streamer alltogether.
2777  case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2778  case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2779  case TStreamerInfo::kSTL: {
2780  TClass *newClass = element->GetNewClass();
2781  TClass *oldClass = element->GetClassPointer();
2782  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
2783 
2784  if (element->GetArrayLength() <= 1) {
2785  if (fOldVersion<3){ // case of old TStreamerInfo
2786  if (newClass && newClass != oldClass) {
2787  if (element->GetStreamer()) {
2788  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2789  } else {
2790  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
2791  }
2792  } else {
2793  if (element->GetStreamer()) {
2794  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2795  } else {
2796  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
2797  }
2798  }
2799  } else {
2800  if (newClass && newClass != oldClass) {
2801  if (element->GetStreamer()) {
2802  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2803  } else {
2804  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
2805  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
2806  } else {
2807  switch (SelectLooper(*newClass->GetCollectionProxy())) {
2808  case kVectorLooper:
2809  readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2810  break;
2811  case kAssociativeLooper:
2812  readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2813  break;
2814  case kVectorPtrLooper:
2815  case kGenericLooper:
2816  default:
2817  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
2818  readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
2819  break;
2820  }
2821  }
2822  }
2823  } else {
2824  if (element->GetStreamer()) {
2825  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2826  } else {
2827  if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
2828  readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
2829  } else {
2830  switch (SelectLooper(*oldClass->GetCollectionProxy())) {
2831  case kVectorLooper:
2832  readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2833  break;
2834  case kAssociativeLooper:
2835  readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2836  break;
2837  case kVectorPtrLooper:
2838  case kGenericLooper:
2839  default:
2840  // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
2841  readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
2842  break;
2843  }
2844  }
2845  }
2846  }
2847  }
2848  } else {
2849  if (fOldVersion<3){ // case of old TStreamerInfo
2850  if (newClass && newClass != oldClass) {
2851  if (element->GetStreamer()) {
2852  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2853  } else {
2854  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
2855  }
2856  } else {
2857  if (element->GetStreamer()) {
2858  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2859  } else {
2860  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
2861  }
2862  }
2863  } else {
2864  if (newClass && newClass != oldClass) {
2865  if (element->GetStreamer()) {
2866  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2867  } else {
2868  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
2869  }
2870  } else {
2871  if (element->GetStreamer()) {
2872  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
2873  } else {
2874  readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
2875  }
2876  }
2877  }
2878  }
2879  break;
2880  }
2881 
2883  AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2884  break;
2886  AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2887  break;
2889  AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2890  break;
2892  AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2893  break;
2895  AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2896  break;
2898  AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2899  break;
2901  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2902  break;
2904  AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2905  break;
2907  AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2908  break;
2910  AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2911  break;
2913  AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2914  break;
2916  AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2917  break;
2919  AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2920  break;
2922  AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
2923  break;
2925  if (element->GetFactor() != 0) {
2926  AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2927  } else {
2928  Int_t nbits = (Int_t)element->GetXmin();
2929  if (!nbits) nbits = 12;
2930  AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2931  }
2932  break;
2933  }
2935  if (element->GetFactor() != 0) {
2936  AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
2937  } else {
2938  Int_t nbits = (Int_t)element->GetXmin();
2939  if (!nbits) {
2940  AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
2941  } else {
2942  AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
2943  }
2944  }
2945  break;
2946  }
2947  default:
2948  readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
2949  break;
2950  }
2951  if (element->TestBit(TStreamerElement::kCache)) {
2952  TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
2953  readSequence->fActions.pop_back();
2954  readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
2955  }
2956 }
2957 
2958 ////////////////////////////////////////////////////////////////////////////////
2959 /// Add a read action for the given element.
2960 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
2961 
2963 {
2964  TStreamerElement *element = compinfo->fElem;
2965 
2966  if (element->TestBit(TStreamerElement::kWrite)) return;
2967 
2968  if (element->TestBit(TStreamerElement::kCache)) {
2969  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
2970  readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
2971  } else {
2972  readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
2973  }
2974 }
2975 
2976 ////////////////////////////////////////////////////////////////////////////////
2977 
2979 {
2980  TStreamerElement *element = compinfo->fElem;
2981  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2982  // Skip element cached for reading purposes.
2983  return;
2984  }
2985  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
2986  // Skip artificial element used for reading purposes.
2987  return;
2988  }
2989  switch (compinfo->fType) {
2990  // write basic types
2991  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2992  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2993  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2994  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2995  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2996  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2997  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2998  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
2999  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3000  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3001  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3002  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3003  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3004  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3005  /*case TStreamerInfo::kFloat16: {
3006  if (element->GetFactor() != 0) {
3007  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3008  } else {
3009  Int_t nbits = (Int_t)element->GetXmin();
3010  if (!nbits) nbits = 12;
3011  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3012  }
3013  break;
3014  } */
3015  /*case TStreamerInfo::kDouble32: {
3016  if (element->GetFactor() != 0) {
3017  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3018  } else {
3019  Int_t nbits = (Int_t)element->GetXmin();
3020  if (!nbits) {
3021  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3022  } else {
3023  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3024  }
3025  }
3026  break;
3027  } */
3028  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3029  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3030  // Streamer alltogether.
3031  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3032  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3033  /*case TStreamerInfo::kSTL: {
3034  TClass *newClass = element->GetNewClass();
3035  TClass *oldClass = element->GetClassPointer();
3036  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3037 
3038  if (element->GetArrayLength() <= 1) {
3039  if (newClass && newClass != oldClass) {
3040  if (element->GetStreamer()) {
3041  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3042  } else {
3043  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3044  }
3045  } else {
3046  if (element->GetStreamer()) {
3047  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3048  } else {
3049  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3050  }
3051  }
3052  } else {
3053  if (newClass && newClass != oldClass) {
3054  if (element->GetStreamer()) {
3055  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3056  } else {
3057  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3058  }
3059  } else {
3060  if (element->GetStreamer()) {
3061  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3062  } else {
3063  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3064  }
3065  }
3066  }
3067  break;
3068  } */
3069  default:
3070  writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3071  break;
3072  }
3073 #if defined(CDJ_NO_COMPILE)
3074  if (element->TestBit(TStreamerElement::kCache)) {
3075  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3076  writeSequence->fActions.pop_back();
3077  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3078  }
3079 #endif
3080 }
3081 
3082 ////////////////////////////////////////////////////////////////////////////////
3083 
3085 {
3086  TStreamerElement *element = compinfo->fElem;
3087  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3088  // Skip element cached for reading purposes.
3089  return;
3090  }
3091  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3092  // Skip artificial element used for reading purposes.
3093  return;
3094  }
3095 
3096  Bool_t generic = kFALSE;
3097 
3098  switch (compinfo->fType) {
3099  // write basic types
3100  case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3101  case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3102  case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3103  case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3104  case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3105  case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3106  case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3107  case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3108  case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3109  case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3110  case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3111  case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3112  case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3113 
3115  if (element->IsBase())
3116  generic = kTRUE;
3117  else
3118  writeSequence->AddAction( WriteTextTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3119  break;
3120 
3122  if (element->IsBase())
3123  generic = kTRUE;
3124  else
3125  writeSequence->AddAction( WriteTextTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3126  break;
3127 
3128  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3129  case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3130  writeSequence->AddAction( WriteSTLp<true>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3131  break;
3132 
3135  writeSequence->AddAction( WriteStreamerLoop<true>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3136  break;
3137 
3138 
3139  // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3140  /*case TStreamerInfo::kFloat16: {
3141  if (element->GetFactor() != 0) {
3142  writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3143  } else {
3144  Int_t nbits = (Int_t)element->GetXmin();
3145  if (!nbits) nbits = 12;
3146  writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3147  }
3148  break;
3149  } */
3150  /*case TStreamerInfo::kDouble32: {
3151  if (element->GetFactor() != 0) {
3152  writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3153  } else {
3154  Int_t nbits = (Int_t)element->GetXmin();
3155  if (!nbits) {
3156  writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3157  } else {
3158  writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3159  }
3160  }
3161  break;
3162  } */
3163  //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3164  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3165  // Streamer alltogether.
3166  //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3167  //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3168  /*case TStreamerInfo::kSTL: {
3169  TClass *newClass = element->GetNewClass();
3170  TClass *oldClass = element->GetClassPointer();
3171  Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3172 
3173  if (element->GetArrayLength() <= 1) {
3174  if (newClass && newClass != oldClass) {
3175  if (element->GetStreamer()) {
3176  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3177  } else {
3178  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3179  }
3180  } else {
3181  if (element->GetStreamer()) {
3182  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3183  } else {
3184  writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3185  }
3186  }
3187  } else {
3188  if (newClass && newClass != oldClass) {
3189  if (element->GetStreamer()) {
3190  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3191  } else {
3192  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3193  }
3194  } else {
3195  if (element->GetStreamer()) {
3196  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3197  } else {
3198  writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3199  }
3200  }
3201  }
3202  break;
3203  } */
3204  default:
3205  generic = kTRUE;
3206  break;
3207  }
3208 
3209  // use generic write action when special handling is not provided
3210  if (generic) writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3211 
3212 #if defined(CDJ_NO_COMPILE)
3213  if (element->TestBit(TStreamerElement::kCache)) {
3214  TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3215  writeSequence->fActions.pop_back();
3216  writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3217  }
3218 #endif
3219 }
3220 
3221 ////////////////////////////////////////////////////////////////////////////////
3222 /// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3223 
3225 {
3226  TStreamerElement *element = compinfo->fElem;
3227  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3228  // Skip element cached for reading purposes.
3229  return;
3230  }
3231  if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3232  // Skip artificial element used for reading purposes.
3233  return;
3234  }
3235 
3236 #if defined(CDJ_NO_COMPILE)
3237  if (element->TestBit(TStreamerElement::kCache)) {
3238  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3239  writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3240  } else {
3241  writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3242  }
3243 #else
3244  writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3245 #endif
3246 
3247 }
3248 
3249 ////////////////////////////////////////////////////////////////////////////////
3250 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3251 
3253 {
3254  if (info == 0) {
3255  return new TStreamerInfoActions::TActionSequence(0,0);
3256  }
3257 
3258  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3259 
3260  UInt_t ndata = info->GetElements()->GetEntries();
3263  {
3264  if (proxy.HasPointers()) {
3265  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3266  delete sequence;
3267 
3268  sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3269 
3270  return sequence;
3271  }
3272 
3273  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3274  Long_t increment = proxy.GetIncrement();
3275  sequence->fLoopConfig = new TVectorLoopConfig(increment, /* read */ kTRUE);
3276  } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
3280  {
3281  Long_t increment = proxy.GetIncrement();
3282  sequence->fLoopConfig = new TVectorLoopConfig(increment, /* read */ kTRUE);
3283  // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3284  } else {
3285  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3286  }
3287  for (UInt_t i = 0; i < ndata; ++i) {
3288  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3289  if (!element) {
3290  break;
3291  }
3292  if (element->GetType() < 0) {
3293  // -- Skip an ignored TObject base class.
3294  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3295  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3296  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3297  // when it is making branches for a split object.
3298  continue;
3299  }
3300  if (element->TestBit(TStreamerElement::kWrite)) {
3301  // Skip element that only for writing.
3302  continue;
3303  }
3304  TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3305  if (baseEl) {
3306  if (baseEl->GetErrorMessage()[0]) {
3307  // There was a problem with the checksum, the user likely did not
3308  // increment the version number of the derived class when the
3309  // base class changed. Since we will be member wise streaming
3310  // this class, let's warn the user that something is wrong.
3311  ::Warning("CreateReadMemberWiseActions","%s",
3312  baseEl->GetErrorMessage());
3313  }
3314  }
3315 
3316  TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3317 
3318  Int_t asize = element->GetSize();
3319  if (element->GetArrayLength()) {
3320  asize /= element->GetArrayLength();
3321  }
3322  Int_t oldType = element->GetType();
3323  Int_t newType = element->GetNewType();
3324 
3325  Int_t offset = element->GetOffset();
3326  if (newType != oldType) {
3327  if (newType > 0) {
3328  if (oldType != TVirtualStreamerInfo::kCounter) {
3329  oldType += TVirtualStreamerInfo::kConv;
3330  }
3331  } else {
3332  oldType += TVirtualStreamerInfo::kSkip;
3333  }
3334  }
3335  switch (SelectLooper(proxy)) {
3336  case kAssociativeLooper:
3337 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3338 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3339 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3340  case kVectorLooper:
3341  case kVectorPtrLooper:
3342  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3343  if (element->TestBit(TStreamerElement::kCache)) {
3344  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3345  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3346  } else {
3347  sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3348  }
3349  break;
3350  case kGenericLooper:
3351  default:
3352  // The usual collection case.
3353  if (element->TestBit(TStreamerElement::kCache)) {
3354  TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3355  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3356  } else {
3357  sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3358  }
3359  break;
3360  }
3361  }
3362  return sequence;
3363 }
3364 
3365 ////////////////////////////////////////////////////////////////////////////////
3366 /// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3367 
3369 {
3370  if (info == 0) {
3371  return new TStreamerInfoActions::TActionSequence(0,0);
3372  }
3373 
3374  UInt_t ndata = info->GetElements()->GetEntries();
3375  TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3377 
3379  {
3380  if (proxy.HasPointers()) {
3381  // Instead of the creating a new one let's copy the one from the StreamerInfo.
3382  delete sequence;
3383 
3384  sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
3385 
3386  return sequence;
3387  }
3388 
3389  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3390  Long_t increment = proxy.GetIncrement();
3391  sequence->fLoopConfig = new TVectorLoopConfig(increment, /* read */ kFALSE);
3392  /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3393  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
3394  {
3395  Long_t increment = proxy.GetIncrement();
3396  sequence->fLoopConfig = new TVectorLoopConfig(increment);
3397  // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
3398  } else {
3399  sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
3400  }
3401  for (UInt_t i = 0; i < ndata; ++i) {
3402  TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3403  if (!element) {
3404  break;
3405  }
3406  if (element->GetType() < 0) {
3407  // -- Skip an ignored TObject base class.
3408  // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3409  // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3410  // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3411  // when it is making branches for a split object.
3412  continue;
3413  }
3414  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
3415  // Skip element cached for reading purposes.
3416  continue;
3417  }
3419  // Skip artificial element used for reading purposes.
3420  continue;
3421  }
3422  TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
3423  Int_t asize = element->GetSize();
3424  if (element->GetArrayLength()) {
3425  asize /= element->GetArrayLength();
3426  }
3427  Int_t oldType = element->GetType();
3428  Int_t offset = element->GetOffset();
3429 #if defined(CDJ_NO_COMPILE)
3430  Int_t newType = element->GetNewType();
3431 
3432  if (newType != oldType) {
3433  if (newType > 0) {
3434  if (oldType != TVirtualStreamerInfo::kCounter) {
3435  oldType += TVirtualStreamerInfo::kConv;
3436  }
3437  } else {
3438  oldType += TVirtualStreamerInfo::kSkip;
3439  }
3440  }
3442  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3443  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
3444  {
3445 
3446  // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3447  if (element->TestBit(TStreamerElement::kCache)) {
3448  TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3449  sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3450  } else {
3451  sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3452  }
3453 
3454  // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3455  // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3456  // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3457  } else {
3458  // The usual collection case.
3459  if (element->TestBit(TStreamerElement::kCache)) {
3460  TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3461  sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3462  } else {
3463  switch (oldType) {
3464  // read basic types
3465  case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3466  case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3467  case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3468  case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3469  case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3470  case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3471  case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3472  case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3473  case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3474  case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3475  case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3476  case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3477  case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
3478  // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
3480  if (element->GetFactor() != 0) {
3481  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3482  } else {
3483  Int_t nbits = (Int_t)element->GetXmin();
3484  if (!nbits) nbits = 12;
3485  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3486  }
3487  break;
3488  }
3490  if (element->GetFactor() != 0) {
3491  sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3492  } else {
3493  Int_t nbits = (Int_t)element->GetXmin();
3494  if (!nbits) {
3495  sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
3496  } else {
3497  sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3498  }
3499  }
3500  break;
3501  }
3502  case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
3503  // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3504  // Streamer alltogether.
3505  case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
3506  case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
3507  default:
3508  sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
3509  break;
3510  }
3511  }
3512  }
3513 #else
3515  /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3516  || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
3517  {
3518  sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3519  } else {
3520  // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
3521  // as it does not create/use a TStaging as expected ... but then again it might
3522  // not be the right things to expect ...
3523  // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3524  sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
3525  }
3526 #endif
3527  }
3528  return sequence;
3529 }
3531 {
3532  // Add the (potentially negative) delta to all the configuration's offset. This is used by
3533  // TBranchElement in the case of split sub-object.
3534 
3535  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3536  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3537  iter != end;
3538  ++iter)
3539  {
3540  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3541  iter->fConfiguration->AddToOffset(delta);
3542  }
3543 }
3544 
3546 {
3547  // Create a copy of this sequence.
3548 
3549  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,fActions.size());
3550 
3551  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
3552 
3553  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3554  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3555  iter != end;
3556  ++iter)
3557  {
3558  TConfiguration *conf = iter->fConfiguration->Copy();
3559  sequence->AddAction( iter->fAction, conf );
3560  }
3561  return sequence;
3562 }
3563 
3565 {
3566  // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
3567  // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
3568 
3569  TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
3570 
3571  sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
3572 
3573  for(UInt_t id = 0; id < element_ids.size(); ++id) {
3574  if ( element_ids[id] < 0 ) {
3575  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3576  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3577  iter != end;
3578  ++iter)
3579  {
3580  TConfiguration *conf = iter->fConfiguration->Copy();
3581  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3582  conf->AddToOffset(offset);
3583  sequence->AddAction( iter->fAction, conf );
3584  }
3585  } else {
3586  TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
3587  for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
3588  iter != end;
3589  ++iter) {
3590  if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
3591  TConfiguration *conf = iter->fConfiguration->Copy();
3592  if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
3593  conf->AddToOffset(offset);
3594  sequence->AddAction( iter->fAction, conf );
3595  }
3596  }
3597  }
3598  }
3599  return sequence;
3600 }
3601 
3602 #if !defined(R__WIN32) && !defined(_AIX)
3603 
3604 #include <dlfcn.h>
3605 
3606 #endif
3607 
3608 typedef void (*voidfunc)();
3609 static const char *R__GetSymbolName(voidfunc func)
3610 {
3611 #if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
3612  return "not available on this platform";
3613 #if 0
3614  MEMORY_BASIC_INFORMATION mbi;
3615  if (!VirtualQuery (func, &mbi, sizeof (mbi)))
3616  {
3617  return 0;
3618  }
3619 
3620  HMODULE hMod = (HMODULE) mbi.AllocationBase;
3621  static char moduleName[MAX_PATH];
3622 
3623  if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
3624  {
3625  return 0;
3626  }
3627  return moduleName;
3628 #endif
3629 #else
3630  Dl_info info;
3631  if (dladdr((void*)func,&info)==0) {
3632  // Not in a known share library, let's give up
3633  return "name not found";
3634  } else {
3635  //fprintf(stdout,"Found address in %s\n",info.dli_fname);
3636  return info.dli_sname;
3637  }
3638 #endif
3639 }
3640 
3642 {
3643  // Add the (potentially negative) delta to all the configuration's offset. This is used by
3644  // TTBranchElement in the case of split sub-object.
3645  // If opt contains 'func', also print the (mangled) name of the function that will be executed.
3646 
3647  if (fLoopConfig) {
3648  fLoopConfig->Print();
3649  }
3650  TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
3651  for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
3652  iter != end;
3653  ++iter)
3654  {
3655  iter->fConfiguration->Print();
3656  if (strstr(opt,"func")) {
3657  printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
3658  }
3659  }
3660 }
3661 
3662 
Describe Streamer information for one class version
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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
TClass * fNewClass
Not Owned.
Definition: TStreamerInfo.h:58
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)
Version_t fOldVersion
! Version of the TStreamerInfo object read from the file
static TConfiguredAction GetConvertCollectionReadActionFrom(Int_t newtype, TConfiguration *conf)
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
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.
TStreamerInfoActions::TActionSequence * fWriteMemberWiseVecPtr
! List of write action resulting from the compilation for use in member wise streaming.
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)
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:4411
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:393
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.
Int_t fNdata
!number of optimized elements
Definition: TStreamerInfo.h:97
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)
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
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
void ComputeSize()
Compute total size of all persistent elements of the class.
Int_t Length() const
Definition: TBuffer.h:96
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
void(* DeleteIterator_t)(void *iter)
INLINE_TEMPLATE_ARGS void ReadSTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t fSize
!size of the persistent class
Definition: TStreamerInfo.h:96
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
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)()
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
Int_t fNfulldata
!number of elements
Definition: TStreamerInfo.h:98
TStreamerInfoActions::TActionSequence * fReadObjectWise
! List of read action resulting from the compilation.
virtual TLoopConfiguration * Copy()=0
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
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)
TClass * fClass
!pointer to class
TObjArray * fElements
Array of TStreamerElements.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
TStreamerInfoActions::TActionSequence * fWriteText
! List of write action resulting for text output like JSON or XML.
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 cl...
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 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:5425
INLINE_TEMPLATE_ARGS Int_t WriteTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
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)
static Bool_t CanOptimize()
static function returning true if optimization can be on
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)
TCompInfo * fComp
![fNslots with less than fElements->GetEntries()*1.5 used] Compiled info
TStreamerInfoActions::TActionSequence * fWriteMemberWise
! List of write action resulting from the compilation for use in member wise streaming.
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)
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)
Int_t fNslots
!total numbrer of slots in fComp.
Definition: TStreamerInfo.h:99
TStreamerInfoActions::TActionSequence * fReadMemberWiseVecPtr
! List of read action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fWriteObjectWise
! List of write action resulting from the compilation.
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
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.
Int_t fNVirtualInfoLoc
! Number of virtual info location to update.
void PrintDebug(TBuffer &buffer, void *object) const
#define R__LOCKGUARD(mutex)
static TConfiguredAction GetConvertCollectionReadAction(Int_t oldtype, Int_t newtype, TConfiguration *conf)
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
void ls(Option_t *option="") const
List the TStreamerElement list and also the precomputed tables if option contains the string "incOrig...
Int_t GetNewType() const
virtual UInt_t Size() const =0
typedef void((*Func_t)())
Int_t fNumber
!Unique identifier
Definition: TStreamerInfo.h:95
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)
TCompInfo ** fCompOpt
![fNdata]
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)
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
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
TCompInfo_t * fCompInfo
Access to compiled information (for legacy code)