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