Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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"
14#include "TROOT.h"
15#include "TStreamerElement.h"
16#include "TVirtualMutex.h"
17#include "TInterpreter.h"
18#include "TError.h"
19#include "TVirtualArray.h"
20#include "TBufferFile.h"
21#include "TBufferText.h"
22#include "TMemberStreamer.h"
23#include "TClassEdit.h"
25#include "TProcessID.h"
26#include "TFile.h"
27
29
30// More possible optimizations:
31// Avoid call the virtual version of TBuffer::ReadInt and co.
32// Merge the Reading of the version and the looking up or the StreamerInfo
33// Avoid if (bytecnt) inside the CheckByteCount routines and avoid multiple (mostly useless nested calls)
34// Try to avoid if statement on onfile class being set (TBufferFile::ReadClassBuffer).
35
36using namespace TStreamerInfoActions;
37
38#ifdef _AIX
39# define INLINE_TEMPLATE_ARGS
40#else
41# define INLINE_TEMPLATE_ARGS inline
42#endif
43
44
46{
47 enum class EMode
48 {
49 kRead,
50 kWrite
51 };
52
54 {
55 const auto props = proxy.GetProperties();
56 const bool isVector = proxy.GetCollectionType() == ROOT::kSTLvector;
57 const bool hasDefaultAlloc = !(props & TVirtualCollectionProxy::kCustomAlloc);
58 const bool isEmulated = props & TVirtualCollectionProxy::kIsEmulated;
59
60 return isEmulated || (isVector && hasDefaultAlloc);
61 }
62
63 template <typename From>
65 typedef From Value_t;
66 };
67
68 template <typename From>
70 typedef From Value_t;
71 };
72
73 struct BitsMarker {
74 typedef UInt_t Value_t;
75 };
76
78 {
79 // Add the (potentially negative) delta to all the configuration's offset. This is used by
80 // TBranchElement in the case of split sub-object.
81
83 fOffset += delta;
84 }
85
87 {
88 // Add the (potentially negative) delta to all the configuration's offset. This is used by
89 // TBranchElement in the case of split sub-object.
90
92 }
93
94 void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
95 {
96 // Inform the user what we are about to stream.
97
98 // Idea, we should find a way to print the name of the function
100 }
101
103 {
104 // Inform the user what we are about to stream.
105
107 TStreamerElement *aElement = fCompInfo->fElem;
108 TString sequenceType;
109 aElement->GetSequenceType(sequenceType);
110
111 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
112 " %s, offset=%d (%s), elemnId=%d \n",
113 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
114 aElement->ClassName(), fOffset, sequenceType.Data(), fElemId);
115 }
116
117 void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
118 {
119 // Inform the user what we are about to stream.
120
121 if (gDebug > 1) {
122 // Idea: We should print the name of the action function.
124 TStreamerElement *aElement = fCompInfo->fElem;
125 TString sequenceType;
126 aElement->GetSequenceType(sequenceType);
127
128 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
129 " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
130 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
131 aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
132 }
133 }
134
136 {
137 // Inform the user what we are about to stream.
138
139 printf("TLoopConfiguration: unconfigured\n");
140 }
141
142
144 // Configuration of action using the legacy code.
145 // Mostly to cancel out the PrintDebug.
146 public:
148 void PrintDebug(TBuffer &, void *) const override {
149 // Since we call the old code, it will print the debug statement.
150 }
151
152 TConfiguration *Copy() override { return new TGenericConfiguration(*this); }
153 };
154
156 // Configuration of action handling kBits.
157 // In this case we need to know both the location
158 // of the member (fBits) and the start of the object
159 // (its TObject part to be exact).
160
161 Int_t fObjectOffset; // Offset of the TObject part within the object
162
164 void PrintDebug(TBuffer &, void *) const override
165 {
167 TStreamerElement *aElement = fCompInfo->fElem;
168 TString sequenceType;
169 aElement->GetSequenceType(sequenceType);
170
171 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
172 " %s, offset=%d (%s)\n",
173 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
174 aElement->ClassName(), fOffset, sequenceType.Data());
175 }
176
177 void AddToOffset(Int_t delta) override
178 {
179 // Add the (potentially negative) delta to all the configuration's offset. This is used by
180 // TBranchElement in the case of split sub-object.
181
183 fOffset += delta;
184 fObjectOffset = 0;
185 }
186
187 void SetMissing() override
188 {
190 fObjectOffset = 0;
191 }
192
193 TConfiguration *Copy() override { return new TBitsConfiguration(*this); }
194
195 };
196
198 {
201
203 TClass *onfileClass, TClass *inMemoryClass) :
204 TConfiguration(info, id, compinfo, offset),
205 fOnfileClass(onfileClass),
206 fInMemoryClass(inMemoryClass ? inMemoryClass : onfileClass) {}
207 TConfiguration *Copy() override { return new TConfObject(*this); }
208 };
209
211 {
212 std::unique_ptr<TStreamerInfoActions::TActionSequence> fActions;
213
215 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions) :
216 TConfiguration(info, id, compinfo, offset),
217 fActions(std::move(actions))
218 {}
219
221 fActions(input.fActions->CreateCopy())
222 {}
223
224 void AddToOffset(Int_t delta) override
225 {
226 // Add the (potentially negative) delta to all the configuration's offset. This is used by
227 // TBranchElement in the case of split sub-object.
228
230 fOffset += delta;
231 if (fActions)
232 fActions->AddToOffset(delta);
233 }
234 }
235
236 TConfiguration *Copy() override { return new TConfSubSequence(*this); };
237 };
238
240 bool fIsPtrPtr = false; // Which are we, an array of objects or an array of pointers to objects?
241
243 : TConfiguration(info, id, compinfo, offset), fIsPtrPtr(isPtrPtr)
244 {
245 }
246
247 TConfiguration *Copy() override { return new TConfStreamerLoop(*this); };
248 };
249
250 Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
251 {
252 char *obj = (char*)addr;
254 return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
255 }
256
257 Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
258 {
259 char *obj = (char*)addr;
261 return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
262 }
263
264 template <typename T>
266 {
267 T *x = (T*)( ((char*)addr) + config->fOffset );
268 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
269 buf >> *x;
270 return 0;
271 }
272
273 void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
274 TBitsConfiguration *conf = (TBitsConfiguration*)config;
275 UShort_t pidf;
276 buf >> pidf;
277 pidf += buf.GetPidOffset();
278 TProcessID *pid = buf.ReadProcessID(pidf);
279 if (pid!=0) {
280 TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
281 UInt_t gpid = pid->GetUniqueID();
282 UInt_t uid;
283 if (gpid>=0xff) {
284 uid = obj->GetUniqueID() | 0xff000000;
285 } else {
286 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
287 }
288 obj->SetUniqueID(uid);
289 pid->PutObjectWithID(obj);
290 }
291 }
292
293 inline Int_t ReadViaExtStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
294 {
295 void *x = (void *)(((char *)addr) + config->fOffset);
296 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
297 (*pstreamer)(buf, x, config->fCompInfo->fLength);
298 return 0;
299 }
300
301 inline Int_t WriteViaExtStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
302 {
303 void *x = (void *)(((char *)addr) + config->fOffset);
304 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
305 (*pstreamer)(buf, x, config->fCompInfo->fLength);
306 return 0;
307 }
308
309 Int_t ReadStreamerCase(TBuffer &buf, void *addr, const TConfiguration *config)
310 {
311 UInt_t start, count;
312 /* Version_t v = */ buf.ReadVersion(&start, &count, config->fInfo->IsA());
313
314 ReadViaExtStreamer(buf, addr, config);
315
316 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
317 return 0;
318 }
319
320 Int_t WriteStreamerCase(TBuffer &buf, void *addr, const TConfiguration *config)
321 {
322 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
323
324 WriteViaExtStreamer(buf, addr, config);
325
326 buf.SetByteCount(pos, kTRUE);
327 return 0;
328 }
329
330 // Read a full object objectwise including reading the version and
331 // selecting any conversion.
332 Int_t ReadViaClassBuffer(TBuffer &buf, void *addr, const TConfiguration *config)
333 {
334 auto conf = (TConfObject*)config;
335 auto memoryClass = conf->fInMemoryClass;
336 auto onfileClass = conf->fOnfileClass;
337
338 char * const where = (((char*)addr)+config->fOffset);
339 buf.ReadClassBuffer( memoryClass, where, onfileClass );
340 return 0;
341 }
342
343 // Write a full object objectwise including reading the version and
344 // selecting any conversion.
345 Int_t WriteViaClassBuffer(TBuffer &buf, void *addr, const TConfiguration *config)
346 {
347 auto conf = (TConfObject*)config;
348 [[maybe_unused]] auto memoryClass = conf->fInMemoryClass;
349 auto onfileClass = conf->fOnfileClass;
350 assert((memoryClass == nullptr || memoryClass == onfileClass)
351 && "Need to new TBufferFile::WriteClassBuffer overload to support this case");
352
353 char * const where = (((char*)addr)+config->fOffset);
354 buf.WriteClassBuffer( onfileClass, where);
355 return 0;
356 }
357
358 template <>
360 {
361 UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
362 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
363 // Idea: This code really belongs inside TBuffer[File]
364 const UInt_t isonheap = *x & TObject::kIsOnHeap; // Record how this instance was actually allocated.
365 buf >> *x;
366 *x |= isonheap | TObject::kNotDeleted; // by definition de-serialized object are not yet deleted.
367
368 if ((*x & kIsReferenced) != 0) {
369 HandleReferencedTObject(buf,addr,config);
370 }
371 return 0;
372 }
373
374 template <typename T>
376 {
377 buf << T{0};
378 return 0;
379 }
380
381 template <typename T>
383 {
384 T *x = (T *)(((char *)addr) + config->fOffset);
385 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
386 buf << *x;
387 return 0;
388 }
389
390 template <typename Onfile, typename Memory>
392 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
393 {
394 // Simple conversion from a 'From' on disk to a 'To' in memory.
395 Onfile temp;
396 temp = (Onfile)(*(Memory*)( ((char*)addr) + config->fOffset ));
397 buf << temp;
398 return 0;
399 }
400 };
401
403 {
404 void *x = (void *)(((char *)addr) + config->fOffset);
405 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
407 return 0;
408 }
409
411 {
412 void *x = (void *)(((char *)addr) + config->fOffset);
413 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
415 return 0;
416 }
417
419 {
420 void *x = (void *)(((char *)addr) + config->fOffset);
421 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
422 ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
423 return 0;
424 }
425
427 {
428 void *x = (void *)(((char *)addr) + config->fOffset);
429 buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
430 return 0;
431 }
432
434 {
435 void *x = (void *)(((char *)addr) + config->fOffset);
437 return 0;
438 }
439
441 {
442 void *x = (void *)(((char *)addr) + config->fOffset);
443 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
444 ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
445 return 0;
446 }
447
449 {
450 // action required to call custom code for TObject as base class
451 void *x = (void *)(((char *)addr) + config->fOffset);
453 return 0;
454 }
455
457 {
458 void *x = (void *)(((char *)addr) + config->fOffset);
460 return 0;
461 }
462
463 static INLINE_TEMPLATE_ARGS void WriteCompressed(TBuffer &buf, float *addr, const TStreamerElement *elem)
464 {
465 buf.WriteFloat16(addr, const_cast<TStreamerElement*>(elem));
466 }
467
468 static INLINE_TEMPLATE_ARGS void WriteCompressed(TBuffer &buf, double *addr, const TStreamerElement *elem)
469 {
470 buf.WriteDouble32(addr, const_cast<TStreamerElement*>(elem));
471 }
472
474 {
475 TClass *cl = config->fCompInfo->fClass;
476 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
477 UInt_t ioffset = config->fOffset;
478
479 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
480
481 // use same method which is used in kSTL
482 buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
483
484 buf.SetByteCount(pos, kTRUE);
485 return 0;
486 }
487
489 {
490 TClass *cle = config->fCompInfo->fClass;
491 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
492 TStreamerElement *aElement = (TStreamerElement *)config->fCompInfo->fElem;
493 UInt_t ioffset = config->fOffset;
494 UInt_t start, count;
495 /* Version_t vers = */ buf.ReadVersion(&start, &count, cle);
496
497 // use same method which is used in kSTL
498 buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
499 buf.CheckByteCount(start, count, aElement->GetFullName());
500 return 0;
501 }
502
504 // Configuration object for the Float16/Double32 where a factor has been specified.
505 public:
509 TConfiguration *Copy() override { return new TConfWithFactor(*this); }
510 };
511
512 template <typename T>
514 {
515 // Stream a Float16 or Double32 where a factor has been specified.
516 //a range was specified. We read an integer and convert it back to a double.
517
518 TConfWithFactor *conf = (TConfWithFactor *)config;
519 buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
520 return 0;
521 }
522
524 // Configuration object for the Float16/Double32 where a factor has been specified.
525 public:
527 TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
528 TConfiguration *Copy() override { return new TConfNoFactor(*this); }
529 };
530
531 template <typename T>
533 {
534 // Stream a Float16 or Double32 where a factor has not been specified.
535
536 TConfNoFactor *conf = (TConfNoFactor *)config;
537 Int_t nbits = conf->fNbits;
538
539 buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
540 return 0;
541 }
542
544 {
545 // Read in a TString object.
546
547 // Idea: We could separate the TString Streamer in its two parts and
548 // avoid the if (buf.IsReading()) and try having it inlined.
549 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
550 return 0;
551 }
552
553 inline Int_t WriteTString(TBuffer &buf, void *addr, const TConfiguration *config)
554 {
555 // Read in a TString object.
556
557 // Idea: We could separate the TString Streamer in its two parts and
558 // avoid the if (buf.IsReading()) and try having it inlined.
559 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
560 return 0;
561 }
562
564 {
565 // Read in a TObject object part.
566
567 // Idea: We could separate the TObject Streamer in its two parts and
568 // avoid the if (buf.IsReading()).
569 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
570 return 0;
571 }
572
573 inline Int_t WriteTObject(TBuffer &buf, void *addr, const TConfiguration *config)
574 {
575 // Read in a TObject object part.
576
577 // Idea: We could separate the TObject Streamer in its two parts and
578 // avoid the if (buf.IsReading()).
579 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
580 return 0;
581 }
582
584 {
585 // Read in a TNamed object part.
586 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
587 // can skip the streamer.
588
589 // Idea: We could extract the code from ReadClassBuffer and avoid one function
590 // code.
591 static const TClass *TNamed_cl = TNamed::Class();
592 return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
593 }
594
595 inline Int_t WriteTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
596 {
597 // Read in a TNamed object part.
598 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
599 // can skip the streamer.
600
601 // Idea: We could extract the code from ReadClassBuffer and avoid one function
602 // code.
603 static const TClass *TNamed_cl = TNamed::Class();
604 return buf.WriteClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
605 }
606
607 class TConfigSTL : public TConfiguration {
608 // Configuration object for the kSTL case
609 private:
610 void Init(bool read) {
612 if (proxy) {
617 if (proxy->HasPointers()) {
619 } else {
620 fNext = proxy->GetFunctionNext(read);
621 }
622 }
623 }
624
625 public:
626 TClass *fOldClass; // Class of the content on file
627 TClass *fNewClass; // Class of the content in memory.
629 const char *fTypeName; // Type name of the member as typed by ther user.
630 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
631
637
638
639 TConfigSTL(Bool_t read, TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
640 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
642
643 TConfigSTL(Bool_t read, 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) :
644 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
646
647 TConfigSTL(Bool_t read, 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) :
648 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
650
651 TConfigSTL(Bool_t read, 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) :
652 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
654
655 TConfiguration *Copy() override { return new TConfigSTL(*this); }
656 };
657
659 // Configuration object for the Float16/Double32 where a factor has been specified.
660 public:
664 TConfiguration *Copy() override { return new TConfSTLWithFactor(*this); }
665 };
666
668 // Configuration object for the Float16/Double32 where a factor has been specified.
669 public:
671 TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
672 TConfiguration *Copy() override { return new TConfSTLNoFactor(*this); }
673 };
674
676 // Base class of the Configurations used in member wise streaming.
677 protected:
678 public:
679 Long_t fIncrement; // Either a value to increase the cursor by and
680 public:
681 TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
682 //virtual void PrintDebug(TBuffer &buffer, void *);
683 ~TVectorLoopConfig() override {};
684 void Print() const override
685 {
686 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
687 }
688
689 void* GetFirstAddress(void *start, const void * /* end */) const override
690 {
691 // Return the address of the first element of the collection.
692
693 return start;
694 }
695
696 TLoopConfiguration* Copy() const override { return new TVectorLoopConfig(*this); }
697 };
698
700 // Base class of the Configurations used in member wise streaming.
701 public:
703 //virtual void PrintDebug(TBuffer &buffer, void *);
704 ~TAssocLoopConfig() override {};
705 void Print() const override
706 {
707 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
708 }
709 TLoopConfiguration* Copy() const override { return new TAssocLoopConfig(*this); }
710
711 void* GetFirstAddress(void *start, const void * /* end */) const override
712 {
713 // Return the address of the first element of the collection.
714
715 R__ASSERT(0);
716// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
717// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
718// arr0 = genloopconfig->fNext(iter,end_collection);
719// if (iter != &iterator[0]) {
720// genloopconfig->fDeleteIterator(iter);
721// }
722 return start;
723 }
724 };
725
727 // Configuration object for the generic case of member wise streaming looping.
728 private:
729 void Init(Bool_t read) {
730 if (fProxy) {
731 if (fProxy->HasPointers()) {
735 } else {
739 }
740 }
741 }
742 public:
746
748 {
749 Init(read);
750 }
751 ~TGenericLoopConfig() override {};
752 void Print() const override
753 {
754 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
755 }
756 TLoopConfiguration* Copy() const override { return new TGenericLoopConfig(*this); }
757
758 void* GetFirstAddress(void *start_collection, const void *end_collection) const override
759 {
760 // Return the address of the first element of the collection.
761
763 void *iter = fCopyIterator(&iterator,start_collection);
764 void *arr0 = fNext(iter,end_collection);
765 if (iter != &iterator[0]) {
766 fDeleteIterator(iter);
767 }
768 return arr0;
769 }
770 };
771
773 {
774 // Collection was saved member-wise
775
776 TConfigSTL *config = (TConfigSTL*)conf;
778
779 if( vers >= 8 ) {
780
781 TClass *oldClass = config->fOldClass;
782
783 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
784 if (!oldProxy) {
785 // Missing information, broken file ... give up
786 return;
787 }
788 TClass *valueClass = oldProxy->GetValueClass();
789 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
790
791 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
792 Int_t nobjects;
793 buf.ReadInt(nobjects);
794 void* alternative = oldProxy->Allocate(nobjects,true);
795 if (nobjects) {
796 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
797
800 void *begin = &(startbuf[0]);
801 void *end = &(endbuf[0]);
802 config->fCreateIterators(alternative, &begin, &end, oldProxy);
803 // We can not get here with a split vector of pointer, so we can indeed assume
804 // that actions->fConfiguration != null.
805 buf.ApplySequence(*actions, begin, end);
806 if (begin != &(startbuf[0])) {
807 // assert(end != endbuf);
808 config->fDeleteTwoIterators(begin,end);
809 }
810 }
811 oldProxy->Commit(alternative);
812
813 } else {
814
815 TClass *oldClass = config->fOldClass;
816
817 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
818 if (!oldProxy) {
819 // Missing information, broken file ... give up
820 return;
821 }
822
823 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
824 Int_t nobjects;
825 buf.ReadInt(nobjects);
826 void* env = oldProxy->Allocate(nobjects,true);
827
828 if (nobjects || vers < 7 ) {
829 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
830 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
831
832 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
833 }
834 oldProxy->Commit(env);
835 }
836 }
837
839 {
840 // Collection was saved member-wise
841
842 TConfigSTL *config = (TConfigSTL*)conf;
844
845 if( vers >= 8 ) {
846
847 TClass *oldClass = config->fOldClass;
848
849 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
850 if (!oldProxy) {
851 // Missing information, broken file ... give up
852 return;
853 }
854 TClass *valueClass = oldProxy->GetValueClass();
855 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
856
857 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
858
859 int objectSize = oldClass->Size();
860 char *obj = (char*)addr;
861 char *endobj = obj + conf->fLength*objectSize;
862
863 for(; obj<endobj; obj+=objectSize) {
864 Int_t nobjects;
865 buf.ReadInt(nobjects);
866 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
867 void* alternative = oldProxy->Allocate(nobjects,true);
868 if (nobjects) {
871 void *begin = &(startbuf[0]);
872 void *end = &(endbuf[0]);
873 config->fCreateIterators(alternative, &begin, &end, oldProxy);
874 // We can not get here with a split vector of pointer, so we can indeed assume
875 // that actions->fConfiguration != null.
876 buf.ApplySequence(*actions, begin, end);
877 if (begin != &(startbuf[0])) {
878 // assert(end != endbuf);
879 config->fDeleteTwoIterators(begin,end);
880 }
881 }
882 oldProxy->Commit(alternative);
883 }
884
885 } else {
886
887 TClass *oldClass = config->fOldClass;
888
889 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
890 if (!oldProxy) {
891 // Missing information, broken file ... give up
892 return;
893 }
894
895 int objectSize = oldClass->Size();
896 char *obj = (char*)addr;
897 char *endobj = obj + conf->fLength*objectSize;
898
899 for(; obj<endobj; obj+=objectSize) {
900 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
901 Int_t nobjects;
902 buf.ReadInt(nobjects);
903 void* env = oldProxy->Allocate(nobjects,true);
904
905 if (nobjects || vers < 7 ) {
906 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
907 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
908
909 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
910 }
911 oldProxy->Commit(env);
912 }
913 }
914 }
915
917 {
918 // Collection was saved member-wise
919
920 TConfigSTL *config = (TConfigSTL*)conf;
921
923
924 TClass *newClass = config->fNewClass;
925 TClass *oldClass = config->fOldClass;
926
927 if( vers < 8 ) {
928 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
929 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass ? oldClass->GetName() : "(could not find the origin TClass)", newClass ? newClass->GetName() : "(could not find the destination TClass)" );
930 } else if (newClass && oldClass){
931
932 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
933
934 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
935 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
936
937 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
938 Int_t nobjects;
939 buf.ReadInt(nobjects);
940 void* alternative = newProxy->Allocate(nobjects,true);
941 if (nobjects) {
942 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
945 void *begin = &(startbuf[0]);
946 void *end = &(endbuf[0]);
947 config->fCreateIterators( alternative, &begin, &end, newProxy);
948 // We can not get here with a split vector of pointer, so we can indeed assume
949 // that actions->fConfiguration != null.
950 buf.ApplySequence(*actions, begin, end);
951 if (begin != &(startbuf[0])) {
952 // assert(end != endbuf);
953 config->fDeleteTwoIterators(begin,end);
954 }
955 }
956 newProxy->Commit(alternative);
957 }
958 }
959
961 {
962 // Collection was saved member-wise
963
964 TConfigSTL *config = (TConfigSTL*)conf;
965
967
968 TClass *newClass = config->fNewClass;
969 TClass *oldClass = config->fOldClass;
970
971 if( vers < 8 ) {
972 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
973 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass ? oldClass->GetName() : "(could not find the origin TClass)", newClass ? newClass->GetName() : "(could not find the destination TClass)" );
974 } else if (newClass && oldClass) {
975
976 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
977
978 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
979 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
980
981 int objectSize = newClass->Size();
982 char *obj = (char*)addr;
983 char *endobj = obj + conf->fLength*objectSize;
984
985 for(; obj<endobj; obj+=objectSize) {
986 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
987 Int_t nobjects;
988 buf.ReadInt(nobjects);
989 void* alternative = newProxy->Allocate(nobjects,true);
990 if (nobjects) {
991 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
994 void *begin = &(startbuf[0]);
995 void *end = &(endbuf[0]);
996 config->fCreateIterators( alternative, &begin, &end, newProxy);
997 // We can not get here with a split vector of pointer, so we can indeed assume
998 // that actions->fConfiguration != null.
999 buf.ApplySequence(*actions, begin, end);
1000 if (begin != &(startbuf[0])) {
1001 // assert(end != endbuf);
1002 config->fDeleteTwoIterators(begin,end);
1003 }
1004 }
1005 newProxy->Commit(alternative);
1006 }
1007 }
1008 }
1009
1010 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1011 {
1012 TConfigSTL *config = (TConfigSTL*)conf;
1013 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1014 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1015 }
1016 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1017 {
1018 TConfigSTL *config = (TConfigSTL*)conf;
1019 (*config->fStreamer)(buf,addr,conf->fLength);
1020 }
1022 {
1023 // case of old TStreamerInfo
1024
1025 TConfigSTL *config = (TConfigSTL*)conf;
1026 // Backward compatibility. Some TStreamerElement's where without
1027 // Streamer but were not removed from element list
1028 if (config->fIsSTLBase || vers == 0) {
1029 buf.SetBufferOffset(start); //there is no byte count
1030 }
1031 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1032 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1033 }
1035 {
1036 // case of old TStreamerInfo
1037
1038 TConfigSTL *config = (TConfigSTL*)conf;
1039 // Backward compatibility. Some TStreamerElement's where without
1040 // Streamer but were not removed from element list
1041 if (config->fIsSTLBase || vers == 0) {
1042 buf.SetBufferOffset(start); //there is no byte count
1043 }
1044 (*config->fStreamer)(buf,addr,conf->fLength);
1045 }
1046
1047 // To Upgrade this to WriteSTLMemberWiseChangedClass (see ReadSTLMemberWiseChangedClass)
1048 // we would need to a TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1050 {
1051 // Collection was saved member-wise
1052 // newClass -> in memory representation
1053 // oldClass -> onfile representation
1054
1055 TConfigSTL *config = (TConfigSTL*)conf;
1056 TClass *newClass = config->fNewClass;
1057 TClass *onfileClass = config->fOldClass;
1058
1059 // Until the writing of TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1060 assert(newClass && onfileClass && newClass == onfileClass &&
1061 "Class level transformation while writing is not yet supported");
1062
1063 if (newClass && onfileClass) {
1064
1065 buf.WriteVersion( onfileClass->GetCollectionProxy()->GetValueClass(), kFALSE );
1066
1067 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1068 TVirtualCollectionProxy *onfileProxy = onfileClass->GetCollectionProxy();
1069
1070 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1071 Int_t nobjects = newProxy->Size();
1072 buf.WriteInt(nobjects);
1073 if (nobjects) {
1074 TActionSequence *actions = onfileProxy->GetWriteMemberWiseActions();
1077 void *begin = &(startbuf[0]);
1078 void *end = &(endbuf[0]);
1079 config->fCreateIterators( addr, &begin, &end, newProxy);
1080 // We can not get here with a split vector of pointer, so we can indeed assume
1081 // that actions->fConfiguration != null.
1082 buf.ApplySequence(*actions, begin, end);
1083 if (begin != &(startbuf[0])) {
1084 // assert(end != endbuf);
1085 config->fDeleteTwoIterators(begin,end);
1086 }
1087 }
1088 }
1089 }
1090
1091 // This routine could/should be merge with WriteSTLMemberWise, the only difference
1092 // is the for loop over the objects. We are not using this version for the case
1093 // where `conf->fLength is 1` as we know this information at StreamerInfo build time
1094 // and thus we can avoid the 'waste' of CPU cycles involved in doing a loop of length 1
1096 {
1097 // Collection was saved member-wise
1098 // newClass -> in memory representation
1099 // oldClass -> onfile representation
1100
1101 TConfigSTL *config = (TConfigSTL*)conf;
1102 TClass *newClass = config->fNewClass;
1103 TClass *onfileClass = config->fOldClass;
1104
1105 // Until the writing of TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1106 assert(newClass && onfileClass && newClass == onfileClass &&
1107 "Class level transformation while writing is not yet supported");
1108
1109 if (newClass && onfileClass) {
1110
1111 buf.WriteVersion( onfileClass->GetCollectionProxy()->GetValueClass(), kFALSE );
1112
1113 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1114 TVirtualCollectionProxy *onfileProxy = onfileClass->GetCollectionProxy();
1115
1116 int objectSize = newClass->Size();
1117 char *obj = (char*)addr;
1118 char *endobj = obj + conf->fLength * objectSize;
1119
1120 for (; obj < endobj; obj += objectSize) {
1121 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1122 Int_t nobjects = newProxy->Size();
1123 buf.WriteInt(nobjects);
1124 if (nobjects) {
1125 TActionSequence *actions = onfileProxy->GetWriteMemberWiseActions();
1128 void *begin = &(startbuf[0]);
1129 void *end = &(endbuf[0]);
1130 config->fCreateIterators( addr, &begin, &end, newProxy);
1131 // We can not get here with a split vector of pointer, so we can indeed assume
1132 // that actions->fConfiguration != null.
1133 buf.ApplySequence(*actions, begin, end);
1134 if (begin != &(startbuf[0])) {
1135 // assert(end != endbuf);
1136 config->fDeleteTwoIterators(begin,end);
1137 }
1138 }
1139 }
1140 }
1141 }
1142
1144 {
1145 TConfigSTL *config = (TConfigSTL*)conf;
1146 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1147 buf.WriteFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0);
1148 }
1150 {
1151 TConfigSTL *config = (TConfigSTL*)conf;
1152 (*config->fStreamer)(buf,addr,conf->fLength);
1153 }
1154
1155 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1156 void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1158 {
1159 TConfigSTL *config = (TConfigSTL*)conf;
1160 UInt_t start, count;
1161 Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1162 if ( vers & TBufferFile::kStreamedMemberWise ) {
1163 memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1164 } else {
1165 objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1166 }
1167 buf.CheckByteCount(start,count,config->fTypeName);
1168 return 0;
1169 }
1170
1171 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*),
1172 void (*objectwise)(TBuffer&,void *,const TConfiguration*)>
1174 {
1175 TConfigSTL *config = (TConfigSTL*)conf;
1176 UInt_t start;
1177 TClass *onfileClass = config->fOldClass;
1178 TStreamerElement *aElement = config->fCompInfo->fElem;
1179 TVirtualCollectionProxy *proxy = onfileClass->GetCollectionProxy();
1180 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
1181
1182 // See test in TStreamerInfo::kSTL case in TStreamerInfoWriteBuffer.cxx
1184 && proxy && vClass
1185 && config->fInfo->GetStreamMemberWise() && onfileClass->CanSplit()
1186 && !(strspn(aElement->GetTitle(),"||") == 2)
1187 && !(vClass->HasCustomStreamerMember()) )
1188 {
1189 start = buf.WriteVersionMemberWise(config->fInfo->IsA(), kTRUE);
1190 memberwise(buf, ((char *)addr) + config->fOffset, config);
1191 } else {
1192 start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1193 objectwise(buf, ((char *)addr) + config->fOffset, config);
1194 }
1195 buf.SetByteCount(start);
1196 return 0;
1197 }
1198
1199 template <typename From, typename To>
1201 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1202 {
1203 // Simple conversion from a 'From' on disk to a 'To' in memory.
1204 From temp;
1205 buf >> temp;
1206 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1207 return 0;
1208 }
1209 };
1210
1211 template <typename To>
1213 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1214 {
1215 // Simple conversion from a 'From' on disk to a 'To' in memory
1216 UInt_t temp;
1217 buf >> temp;
1218
1219 if ((temp & kIsReferenced) != 0) {
1220 HandleReferencedTObject(buf,addr,config);
1221 }
1222
1223 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1224 return 0;
1225 }
1226 };
1227
1228 template <typename From, typename To>
1230 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1231 {
1232 // Simple conversion from a 'From' on disk to a 'To' in memory.
1233 TConfWithFactor *conf = (TConfWithFactor *)config;
1234 From temp;
1235 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1236 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1237 return 0;
1238 }
1239 };
1240
1241 template <typename From, typename To>
1243 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1244 {
1245 // Simple conversion from a 'From' on disk to a 'To' in memory.
1246 TConfNoFactor *conf = (TConfNoFactor *)config;
1247 From temp;
1248 buf.ReadWithNbits(&temp, conf->fNbits);
1249 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1250 return 0;
1251 }
1252 };
1253
1255 // Configuration object for the PushDataCache case.
1256 public:
1258
1260 TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1261 {}
1262
1263 void Print() const override
1264 {
1266 if (fOnfileObject)
1267 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1268 info->GetClass()->GetName(), fOffset);
1269 else
1270 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1271 info->GetClass()->GetName(), fOffset);
1272 }
1273 void PrintDebug(TBuffer &buffer, void *object) const override
1274 {
1275 if (gDebug > 1) {
1277 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1278 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1279
1280 }
1281 }
1282 };
1283
1285 {
1287 auto onfileObject = config->fOnfileObject;
1288
1289 // onfileObject->SetSize(1);
1290 b.PushDataCache( onfileObject );
1291
1292 return 0;
1293 }
1294
1295 Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1296 {
1298 auto onfileObject = config->fOnfileObject;
1299
1300 // onfileObject->SetSize(n);
1301 b.PushDataCache( onfileObject );
1302
1303 return 0;
1304 }
1305
1306 Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1307 {
1309 auto onfileObject = config->fOnfileObject;
1310
1311 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1312 UInt_t n = proxy->Size();
1313
1314 onfileObject->SetSize(n);
1315 b.PushDataCache( onfileObject );
1316
1317 return 0;
1318 }
1319
1321 {
1322 b.PopDataCache();
1323 return 0;
1324 }
1325
1326 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1327 {
1328 b.PopDataCache();
1329 return 0;
1330 }
1331
1333 {
1334 b.PopDataCache();
1335 return 0;
1336 }
1337
1339 // Configuration object for the UseCache case.
1340 public:
1343
1345 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1346 void PrintDebug(TBuffer &b, void *addr) const override
1347 {
1348 if (gDebug > 1) {
1349 // Idea: We should print the name of the action function.
1351 TStreamerElement *aElement = fCompInfo->fElem;
1352 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1353 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1354 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1355 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1356 }
1357
1358 }
1361 {
1363 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1364 return copy;
1365 }
1366 };
1367
1369 {
1371
1372 Int_t bufpos = b.Length();
1373 TVirtualArray *cached = b.PeekDataCache();
1374 if (cached==0) {
1375 TStreamerElement *aElement = conf->fCompInfo->fElem;
1376 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1377 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1378 char *ptr = (char*)addr;
1379 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1380 } else {
1381 config->fAction(b, (*cached)[0]);
1382 }
1383 // Idea: Factor out this 'if' to a UseCacheRepeat function
1384 if (config->fNeedRepeat) {
1385 b.SetBufferOffset(bufpos);
1386 }
1387 return 0;
1388 }
1389
1390 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1391 {
1393 Int_t bufpos = b.Length();
1394
1395 TVirtualArray *cached = b.PeekDataCache();
1396 if (cached==0) {
1397 TStreamerElement *aElement = config->fCompInfo->fElem;
1398 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1399 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1400 char *ptr = (char*)start;
1401 UInt_t n = (((void**)end)-((void**)start));
1402 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1403 } else {
1404 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1405 void *cached_start = (*cached)[0];
1406 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1407 config->fAction(b,cached_start,cached_end,&cached_config);
1408 }
1409 // Idea: Factor out this 'if' to a UseCacheRepeat function
1410 if (config->fNeedRepeat) {
1411 b.SetBufferOffset(bufpos);
1412 }
1413 return 0;
1414 }
1415
1416 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1417 {
1419
1420 Int_t bufpos = b.Length();
1421 TVirtualArray *cached = b.PeekDataCache();
1422 if (cached==0) {
1423 TStreamerElement *aElement = config->fCompInfo->fElem;
1424 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1425 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1426 char *ptr = (char*)start;
1427 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1428 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1429 } else {
1430 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1431 void *cached_start = (*cached)[0];
1432 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1433 config->fAction(b,cached_start,cached_end,&cached_config);
1434 }
1435 // Idea: Factor out this 'if' to a UseCacheRepeat function
1436 if (config->fNeedRepeat) {
1437 b.SetBufferOffset(bufpos);
1438 }
1439 return 0;
1440 }
1441
1443 {
1445
1446 Int_t bufpos = b.Length();
1447 TVirtualArray *cached = b.PeekDataCache();
1448 if (cached==0) {
1449 TStreamerElement *aElement = config->fCompInfo->fElem;
1450 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1451
1452 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1453 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1454 UInt_t n = proxy->Size();
1455 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1456 } else {
1457 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1458 void *cached_start = (*cached)[0];
1459 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1460 config->fAction(b,cached_start,cached_end,&cached_config);
1461 }
1462 // Idea: Factor out this 'if' to a UseCacheRepeat function
1463 if (config->fNeedRepeat) {
1464 b.SetBufferOffset(bufpos);
1465 }
1466 return 0;
1467 }
1468
1469 // Support for collections.
1470
1471 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1472 {
1473 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1474 return 0;
1475 }
1476
1477 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1478 {
1479 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1480 return 0;
1481 }
1482
1484
1486 {
1488 return kVectorLooper;
1489 } else if ( (proxy.GetCollectionType() == ROOT::kSTLvector)) {
1491 return kGenericLooper;
1492 else
1493 return kVectorLooper;
1498 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1499 return kAssociativeLooper;
1500 } else {
1501 return kGenericLooper;
1502 }
1503 }
1504
1506 {
1507 if (proxy)
1508 return SelectLooper(*proxy);
1509 else
1510 return kVectorPtrLooper;
1511 }
1512
1513
1514 template<typename Looper>
1516
1517 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1519 {
1520 TLoopConfiguration *localLoopConfig = loopConfig ? loopConfig->Copy() : nullptr;
1521 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1522 TActionSequence::CreateReadMemberWiseActions(info, localLoopConfig));
1523 return actions;
1524 }
1525
1526 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1528 {
1529 TLoopConfiguration *localLoopConfig = loopConfig ? loopConfig->Copy() : nullptr;
1530 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1531 TActionSequence::CreateWriteMemberWiseActions(info, localLoopConfig));
1532 return actions;
1533 }
1534
1535 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * /* loopconfig */, const TConfiguration *config)
1536 {
1537 auto conf = (TConfSubSequence*)config;
1538 auto actions = conf->fActions.get();
1539 // FIXME: need to update the signature of ApplySequence.
1540 buf.ApplySequence(*actions, start, const_cast<void*>(end));
1541 return 0;
1542 }
1543
1544 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1545 {
1546 UInt_t pos, count;
1547 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1548
1549 Looper::template LoopOverCollection< ReadViaExtStreamer >(buf, start, end, loopconfig, config);
1550
1551 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1552 return 0;
1553 }
1554
1555 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1556 {
1557 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1558
1559 Looper::template LoopOverCollection< WriteViaExtStreamer >(buf, start, end, loopconfig, config);
1560
1561 buf.SetByteCount(pos, kTRUE);
1562 return 0;
1563 }
1564
1565 static inline Int_t StreamerLoopExternal(TBuffer &buf, void *addr, const TConfiguration *actionConfig) {
1566 UInt_t ioffset = actionConfig->fOffset;
1567 // Get any private streamer which was set for the data member.
1568 TMemberStreamer* pstreamer = actionConfig->fCompInfo->fStreamer;
1569 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + actionConfig->fCompInfo->fMethod /*counter offset*/);
1570 // And call the private streamer, passing it the buffer, the object, and the counter.
1571 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
1572 return 0;
1573 };
1574
1575 template<bool kIsTextT>
1576 static Int_t WriteStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config) {
1577 // Get the class of the data member.
1578 TClass* cl = config->fCompInfo->fClass;
1579 UInt_t ioffset = config->fOffset;
1580 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1581
1582 // Get the counter for the varying length array.
1583 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1584
1585 //b << vlen;
1586 if (vlen) {
1587 // Get a pointer to the array of pointers.
1588 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1589 // Loop over each element of the array of pointers to varying-length arrays.
1590 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1591 if (!pp[ndx]) {
1592 // -- We do not have a pointer to a varying-length array.
1593 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1594 // ::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()));
1595 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());
1596 continue;
1597 }
1598 if (!isPtrPtr) {
1599 // -- We are a varying-length array of objects.
1600 // Write the entire array of objects to the buffer.
1601 // Note: Polymorphism is not allowed here.
1602 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
1603 } else {
1604 // -- We are a varying-length array of pointers to objects.
1605 // Write the entire array of object pointers to the buffer.
1606 // Note: The object pointers are allowed to be polymorphic.
1607 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1608 } // isPtrPtr
1609 } // ndx
1610 } else // vlen
1611 if (kIsTextT) {
1612 // special handling for the text-based streamers
1613 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
1614 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
1615 }
1616 return 0;
1617 }
1618
1619 static Int_t WriteStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config) {
1620 // Get the class of the data member.
1621 TClass* cl = config->fCompInfo->fClass;
1622 UInt_t ioffset = config->fOffset;
1623 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1624
1625 // Get the counter for the varying length array.
1626 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1627 //b << vlen;
1628 if (vlen) {
1629 // Get a pointer to the array of pointers.
1630 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1631 // -- Older versions do *not* allow polymorphic pointers to objects.
1632 // Loop over each element of the array of pointers to varying-length arrays.
1633 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1634 if (!pp[ndx]) {
1635 // -- We do not have a pointer to a varying-length array.
1636 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1637 // ::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()));
1638 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());
1639 continue;
1640 }
1641 if (!isPtrPtr) {
1642 // -- We are a varying-length array of objects.
1643 // Loop over the elements of the varying length array.
1644 for (Int_t v = 0; v < vlen; ++v) {
1645 // Write the object to the buffer.
1646 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1647 } // v
1648 }
1649 else {
1650 // -- We are a varying-length array of pointers to objects.
1651 // Loop over the elements of the varying length array.
1652 for (Int_t v = 0; v < vlen; ++v) {
1653 // Get a pointer to the object pointer.
1654 char** r = (char**) pp[ndx];
1655 // Write the object to the buffer.
1656 cl->Streamer(r[v], buf);
1657 } // v
1658 } // isPtrPtr
1659 } // ndx
1660 } // vlen
1661 return 0;
1662 }
1663
1664 template<bool kIsTextT, typename... Ts>
1666 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1667 {
1668 if (!kIsTextT && config->fCompInfo->fStreamer) {
1669 // -- We have a private streamer.
1670 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1671
1672 // Loop over the entries in the clones array or the STL container.
1673 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1674
1675 buf.SetByteCount(pos, kTRUE);
1676 // We are done, next streamer element.
1677 return 0;
1678 }
1679
1680 // By default assume the file version is the newest.
1681 Int_t fileVersion = kMaxInt;
1682
1683 if (!kIsTextT) {
1684 // At this point we do *not* have a private streamer.
1685 // Get the version of the file we are writing to.
1686 TFile* file = (TFile*) buf.GetParent();
1687 if (file) {
1688 fileVersion = file->GetVersion();
1689 }
1690 }
1691 // Write the class version to the buffer.
1692 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1693 if (fileVersion > 51508) {
1694 // -- Newer versions allow polymorphic pointers to objects.
1695 // Loop over the entries in the clones array or the STL container.
1696 Looper::template LoopOverCollection< WriteStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1697 }
1698 else {
1699 // -- Older versions do *not* allow polymorphic pointers to objects.
1700 // Loop over the entries in the clones array or the STL container.
1701 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1702 } // fileVersion
1703 // Backpatch the byte count into the buffer.
1704 buf.SetByteCount(pos, kTRUE);
1705
1706 return 0;
1707 }
1708 };
1709
1710 template<bool kIsTextT>
1711 static Int_t ReadStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config) {
1712 // Get the class of the data member.
1713 TClass* cl = config->fCompInfo->fClass;
1714 UInt_t ioffset = config->fOffset;
1715 // Which are we, an array of objects or an array of pointers to objects?
1716 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1717
1718 // Get the counter for the varying length array.
1719 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1720 config->fCompInfo->fMethod /*counter offset*/));
1721 // Int_t realLen;
1722 // b >> realLen;
1723 // if (realLen != vlen) {
1724 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1725 //}
1726 // Get a pointer to the array of pointers.
1727 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1728 // Loop over each element of the array of pointers to varying-length arrays.
1729 // if (!pp) {
1730 // continue;
1731 // }
1732
1733 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1734 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1735 // if (!pp[ndx]) {
1736 // -- We do not have a pointer to a varying-length array.
1737 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1738 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1739 // continue;
1740 //}
1741 // Delete any memory at pp[ndx].
1742 if (!isPtrPtr) {
1743 cl->DeleteArray(pp[ndx]);
1744 pp[ndx] = 0;
1745 } else {
1746 // Using vlen is wrong here because it has already
1747 // been overwritten with the value needed to read
1748 // the current record. Fixing this will require
1749 // doing a pass over the object at the beginning
1750 // of the I/O and releasing all the buffer memory
1751 // for varying length arrays before we overwrite
1752 // the counter values.
1753 //
1754 // For now we will just leak memory, just as we
1755 // have always done in the past. Fix this.
1756 //
1757 // char** r = (char**) pp[ndx];
1758 // if (r) {
1759 // for (Int_t v = 0; v < vlen; ++v) {
1760 // cl->Destructor(r[v]);
1761 // r[v] = 0;
1762 // }
1763 //}
1764 delete[] pp[ndx];
1765 pp[ndx] = 0;
1766 }
1767 if (!vlen) {
1768 if (kIsTextT) {
1769 // special handling for the text-based streamers - keep calling to shift array index
1770 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
1771 }
1772 continue;
1773 }
1774 // Note: We now have pp[ndx] is null.
1775 // Allocate memory to read into.
1776 if (!isPtrPtr) {
1777 // -- We are a varying-length array of objects.
1778 // Note: Polymorphism is not allowed here.
1779 // Allocate a new array of objects to read into.
1780 pp[ndx] = (char *)cl->NewArray(vlen);
1781 if (!pp[ndx]) {
1782 Error("ReadBuffer", "Memory allocation failed!\n");
1783 continue;
1784 }
1785 } else {
1786 // -- We are a varying-length array of pointers to objects.
1787 // Note: The object pointers are allowed to be polymorphic.
1788 // Allocate a new array of pointers to objects to read into.
1789 pp[ndx] = (char *)new char *[vlen];
1790 if (!pp[ndx]) {
1791 Error("ReadBuffer", "Memory allocation failed!\n");
1792 continue;
1793 }
1794 // And set each pointer to null.
1795 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1796 // = (char*) new char*[vlen];
1797 }
1798 if (!isPtrPtr) {
1799 // -- We are a varying-length array of objects.
1800 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
1801 } else {
1802 // -- We are a varying-length array of object pointers.
1803 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1804 } // isPtrPtr
1805 } // ndx
1806 return 0;
1807 }; // StreamerLoopPoly
1808
1809 static Int_t ReadStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config) {
1810 // Get the class of the data member.
1811 TClass* cl = config->fCompInfo->fClass;
1812 UInt_t ioffset = config->fOffset;
1813 // Which are we, an array of objects or an array of pointers to objects?
1814 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1815
1816 // Get the counter for the varying length array.
1817 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1818 config->fCompInfo->fMethod /*counter offset*/));
1819 // Int_t realLen;
1820 // b >> realLen;
1821 // if (realLen != vlen) {
1822 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1823 //}
1824 // Get a pointer to the array of pointers.
1825 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1826 // if (!pp) {
1827 // continue;
1828 //}
1829
1830 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1831
1832 // Loop over each element of the array of pointers to varying-length arrays.
1833 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1834 // if (!pp[ndx]) {
1835 // -- We do not have a pointer to a varying-length array.
1836 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1837 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1838 // continue;
1839 //}
1840 // Delete any memory at pp[ndx].
1841 if (!isPtrPtr) {
1842 cl->DeleteArray(pp[ndx]);
1843 pp[ndx] = 0;
1844 } else {
1845 // Using vlen is wrong here because it has already
1846 // been overwritten with the value needed to read
1847 // the current record. Fixing this will require
1848 // doing a pass over the object at the beginning
1849 // of the I/O and releasing all the buffer memory
1850 // for varying length arrays before we overwrite
1851 // the counter values.
1852 //
1853 // For now we will just leak memory, just as we
1854 // have always done in the past. Fix this.
1855 //
1856 // char** r = (char**) pp[ndx];
1857 // if (r) {
1858 // for (Int_t v = 0; v < vlen; ++v) {
1859 // cl->Destructor(r[v]);
1860 // r[v] = 0;
1861 // }
1862 //}
1863 delete[] pp[ndx];
1864 pp[ndx] = 0;
1865 }
1866 if (!vlen) {
1867 continue;
1868 }
1869 // Note: We now have pp[ndx] is null.
1870 // Allocate memory to read into.
1871 if (!isPtrPtr) {
1872 // -- We are a varying-length array of objects.
1873 // Note: Polymorphism is not allowed here.
1874 // Allocate a new array of objects to read into.
1875 pp[ndx] = (char *)cl->NewArray(vlen);
1876 if (!pp[ndx]) {
1877 Error("ReadBuffer", "Memory allocation failed!\n");
1878 continue;
1879 }
1880 } else {
1881 // -- We are a varying-length array of pointers to objects.
1882 // Note: The object pointers are allowed to be polymorphic.
1883 // Allocate a new array of pointers to objects to read into.
1884 pp[ndx] = (char *)new char *[vlen];
1885 if (!pp[ndx]) {
1886 Error("ReadBuffer", "Memory allocation failed!\n");
1887 continue;
1888 }
1889 // And set each pointer to null.
1890 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1891 // = (char*) new char*[vlen];
1892 }
1893 if (!isPtrPtr) {
1894 // -- We are a varying-length array of objects.
1895 // Loop over the elements of the varying length array.
1896 for (Int_t v = 0; v < vlen; ++v) {
1897 // Read the object from the buffer.
1898 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1899 } // v
1900 } else {
1901 // -- We are a varying-length array of object pointers.
1902 // Get a pointer to the object pointer array.
1903 char **r = (char **)pp[ndx];
1904 // Loop over the elements of the varying length array.
1905 for (Int_t v = 0; v < vlen; ++v) {
1906 // Allocate an object to read into.
1907 r[v] = (char *)cl->New();
1908 if (!r[v]) {
1909 // Do not print a second error message here.
1910 // Error("ReadBuffer", "Memory allocation failed!\n");
1911 continue;
1912 }
1913 // Read the object from the buffer.
1914 cl->Streamer(r[v], buf);
1915 } // v
1916 } // isPtrPtr
1917 } // ndx
1918 return 0;
1919 }; // action
1920
1921 template<bool kIsTextT, typename... Ts>
1923 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1924 {
1925 // Check for a private streamer.
1926 if (!kIsTextT && config->fCompInfo->fStreamer) {
1927 // -- We have a private streamer.
1928 // Read the class version and byte count from the buffer.
1929 UInt_t pos = 0;
1930 UInt_t count = 0;
1931 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1932
1933 // Loop over the entries in the clones array or the STL container.
1934 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1935
1936 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1937 // We are done, next streamer element.
1938 return 0;
1939 }
1940
1941 // By default assume the file version is the newest.
1942 Int_t fileVersion = kMaxInt;
1943 if (!kIsTextT) {
1944 // At this point we do *not* have a private streamer.
1945 // Get the version of the file we are reading from.
1946 TFile* file = (TFile*) buf.GetParent();
1947 if (file) {
1948 fileVersion = file->GetVersion();
1949 }
1950 }
1951 // Read the class version and byte count from the buffer.
1952 UInt_t pos = 0;
1953 UInt_t count = 0;
1954 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1955 if (fileVersion > 51508) {
1956 // -- Newer versions allow polymorphic pointers.
1957
1958 // Loop over the entries in the clones array or the STL container.
1959 Looper::template LoopOverCollection< ReadStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1960 } else {
1961 // -- Older versions do *not* allow polymorphic pointers.
1962
1963 // Loop over the entries in the clones array or the STL container.
1964 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1965 } // fileVersion
1966 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1967 return 0;
1968 }
1969 };
1970
1971 };
1972
1973 // The Scalar 'looper' only process one element.
1974 struct ScalarLooper : public CollectionLooper<ScalarLooper>
1975 {
1976 using LoopAction_t = Int_t (*)(TBuffer &, void*, const TConfiguration*);
1977
1978 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1979 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const TConfiguration *config)
1980 {
1981 iter_action(buf, start, config);
1982 return 0;
1983 }
1984 };
1985
1986 struct VectorLooper : public CollectionLooper<VectorLooper>
1987 {
1988 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
1989
1990 template <bool kIsText>
1992 template <bool kIsText>
1994
1995 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1996 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1997 {
1998 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1999 //Idea: can we factor out the addition of fOffset
2000 // iter = (char*)iter + config->fOffset;
2001 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
2002 iter_action(buf, iter, config);
2003 }
2004 return 0;
2005 }
2006
2007 template <typename T>
2008 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2009 {
2010 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2011 iter = (char*)iter + config->fOffset;
2012 end = (char*)end + config->fOffset;
2013 for(; iter != end; iter = (char*)iter + incr ) {
2014 T *x = (T*) ((char*) iter);
2015 buf >> *x;
2016 }
2017 return 0;
2018 }
2019
2020 template <typename From, typename To>
2022 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2023 {
2024 // Simple conversion from a 'From' on disk to a 'To' in memory.
2025 From temp;
2026 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2027 iter = (char*)iter + config->fOffset;
2028 end = (char*)end + config->fOffset;
2029 for(; iter != end; iter = (char*)iter + incr ) {
2030 buf >> temp;
2031 *(To*)( ((char*)iter) ) = (To)temp;
2032 }
2033 return 0;
2034 }
2035 };
2036
2037 template <typename To>
2039 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2040 {
2041 // Simple conversion from a 'From' on disk to a 'To' in memory.
2042 UInt_t temp;
2043 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2044 iter = (char*)iter + config->fOffset;
2045 end = (char*)end + config->fOffset;
2046 for(; iter != end; iter = (char*)iter + incr ) {
2047 buf >> temp;
2048
2049 if ((temp & kIsReferenced) != 0) {
2050 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
2051 }
2052
2053 *(To*)( ((char*)iter) ) = (To)temp;
2054 }
2055 return 0;
2056 }
2057 };
2058
2059 template <typename From, typename To>
2061 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2062 {
2063 // Simple conversion from a 'From' on disk to a 'To' in memory.
2064 TConfWithFactor *conf = (TConfWithFactor *)config;
2065 From temp;
2066 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2067 iter = (char*)iter + config->fOffset;
2068 end = (char*)end + config->fOffset;
2069 for(; iter != end; iter = (char*)iter + incr ) {
2070 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2071 *(To*)( ((char*)iter) ) = (To)temp;
2072 }
2073 return 0;
2074 }
2075 };
2076
2077 template <typename From, typename To>
2079 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2080 {
2081 // Simple conversion from a 'From' on disk to a 'To' in memory.
2082 TConfNoFactor *conf = (TConfNoFactor *)config;
2083 From temp;
2084 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2085 iter = (char*)iter + config->fOffset;
2086 end = (char*)end + config->fOffset;
2087 for(; iter != end; iter = (char*)iter + incr ) {
2088 buf.ReadWithNbits(&temp, conf->fNbits);
2089 *(To*)( ((char*)iter) ) = (To)temp;
2090 }
2091 return 0;
2092 }
2093 };
2094
2095 template <typename T>
2096 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2097 {
2098 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2099 iter = (char*)iter + config->fOffset;
2100 end = (char*)end + config->fOffset;
2101 for(; iter != end; iter = (char*)iter + incr ) {
2102 T *x = (T*) ((char*) iter);
2103 buf << *x;
2104 }
2105 return 0;
2106 }
2107
2108 template <typename Onfile, typename Memory>
2110 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2111 {
2112 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2113 iter = (char*)iter + config->fOffset;
2114 end = (char*)end + config->fOffset;
2115 for(; iter != end; iter = (char*)iter + incr ) {
2116 // Simple conversion from a 'From' on disk to a 'To' in memory.
2117 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2118 buf << temp;
2119 }
2120 return 0;
2121 }
2122 };
2123
2124 template <typename Onfile, typename Memory>
2125 struct WriteConvertBasicType<WithFactorMarker<Onfile>, Memory> {
2126 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2127 {
2128 const TStreamerElement *elem = config->fCompInfo->fElem;
2129 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2130 iter = (char*)iter + config->fOffset;
2131 end = (char*)end + config->fOffset;
2132 for(; iter != end; iter = (char*)iter + incr ) {
2133 // Simple conversion from a 'From' on disk to a 'To' in memory.
2134 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2135 WriteCompressed(buf, &temp, elem);
2136 }
2137 return 0;
2138 }
2139 };
2140
2141 template <typename Onfile, typename Memory>
2142 struct WriteConvertBasicType<NoFactorMarker<Onfile>, Memory> {
2143 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2144 {
2145 const TStreamerElement *elem = config->fCompInfo->fElem;
2146 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2147 iter = (char*)iter + config->fOffset;
2148 end = (char*)end + config->fOffset;
2149 for(; iter != end; iter = (char*)iter + incr ) {
2150 // Simple conversion from a 'From' on disk to a 'To' in memory.
2151 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2152 WriteCompressed(buf, &temp, elem);
2153 }
2154 return 0;
2155 }
2156 };
2157
2158 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2159 {
2160 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2161 // punt.
2162
2163 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2164 UInt_t n = (((char*)end)-((char*)start))/incr;
2165 char **arrptr = new char*[n];
2166 UInt_t i = 0;
2167 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2168 arrptr[i] = (char*)iter;
2169 }
2170 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2171 delete [] arrptr;
2172 return 0;
2173 }
2174
2175 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2176 {
2177 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2178 // punt.
2179
2180 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2181 UInt_t n = (((char*)end)-((char*)start))/incr;
2182 char **arrptr = new char*[n];
2183 UInt_t i = 0;
2184 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2185 arrptr[i] = (char*)iter;
2186 }
2187 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2188 delete [] arrptr;
2189 return 0;
2190 }
2191
2192 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2193 {
2194 // Well the implementation is non trivial. For now punt.
2195
2196 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2197 UInt_t n = (((char*)end)-((char*)start))/incr;
2198 char **arrptr = new char*[n];
2199 UInt_t i = 0;
2200 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2201 arrptr[i] = (char*)iter;
2202 }
2203 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2204 delete [] arrptr;
2205 return 0;
2206 }
2207
2208 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2209 {
2210 // Well the implementation is non trivial. For now punt.
2211
2212 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2213 UInt_t n = (((char*)end)-((char*)start))/incr;
2214 char **arrptr = new char*[n];
2215 UInt_t i = 0;
2216 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2217 arrptr[i] = (char*)iter;
2218 }
2219 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2220 delete [] arrptr;
2221 return 0;
2222 }
2223
2224 template <typename T>
2226 {
2227 // Collection of numbers. Memberwise or not, it is all the same.
2228
2229 TConfigSTL *config = (TConfigSTL*)conf;
2230 UInt_t start, count;
2231 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2232
2233 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2234 Int_t nvalues;
2235 buf.ReadInt(nvalues);
2236 vec->resize(nvalues);
2237
2238#ifdef R__VISUAL_CPLUSPLUS
2239 if (nvalues <= 0) {
2240 buf.CheckByteCount(start,count,config->fTypeName);
2241 return 0;
2242 }
2243#endif
2244 T *begin = &(*vec->begin());
2245 buf.ReadFastArray(begin, nvalues);
2246
2247 buf.CheckByteCount(start,count,config->fTypeName);
2248 return 0;
2249 }
2250
2251 template <typename T>
2253 {
2254 // Collection of numbers. Memberwise or not, it is all the same.
2255
2256 TConfigSTL *config = (TConfigSTL*)conf;
2257 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2258
2259 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2260 Int_t nvalues = vec->size();
2261 buf.WriteInt(nvalues);
2262
2263 T *begin = &(*vec->begin());
2264 buf.WriteFastArray(begin, nvalues);
2265
2266 buf.SetByteCount(start);
2267 return 0;
2268 }
2269
2271 {
2272 // Collection of numbers. Memberwise or not, it is all the same.
2273
2274 TConfigSTL *config = (TConfigSTL*)conf;
2275 UInt_t start, count;
2276 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2277
2278 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2279 Int_t nvalues;
2280 buf.ReadInt(nvalues);
2281 vec->resize(nvalues);
2282
2283#ifdef R__VISUAL_CPLUSPLUS
2284 if (nvalues <= 0) {
2285 buf.CheckByteCount(start,count,config->fTypeName);
2286 return 0;
2287 }
2288#endif
2289 float *begin = &(*vec->begin());
2290 buf.ReadFastArrayFloat16(begin, nvalues);
2291
2292 buf.CheckByteCount(start,count,config->fTypeName);
2293 return 0;
2294 }
2295
2297 {
2298 // Collection of numbers. Memberwise or not, it is all the same.
2299
2300 TConfigSTL *config = (TConfigSTL*)conf;
2301 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2302
2303 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2304 Int_t nvalues = vec->size();
2305 buf.WriteInt(nvalues);
2306
2307 float *begin = &(*vec->begin());
2308 buf.WriteFastArrayFloat16(begin, nvalues);
2309
2310 buf.SetByteCount(start);
2311 return 0;
2312 }
2313
2315 {
2316 // Collection of numbers. Memberwise or not, it is all the same.
2317
2318 TConfigSTL *config = (TConfigSTL*)conf;
2319 UInt_t start, count;
2320 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2321
2322 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2323 Int_t nvalues;
2324 buf.ReadInt(nvalues);
2325 vec->resize(nvalues);
2326
2327#ifdef R__VISUAL_CPLUSPLUS
2328 if (nvalues <= 0) {
2329 buf.CheckByteCount(start,count,config->fTypeName);
2330 return 0;
2331 }
2332#endif
2333 double *begin = &(*vec->begin());
2334 buf.ReadFastArrayDouble32(begin, nvalues);
2335
2336 buf.CheckByteCount(start,count,config->fTypeName);
2337 return 0;
2338 }
2339
2341 {
2342 // Collection of numbers. Memberwise or not, it is all the same.
2343
2344 TConfigSTL *config = (TConfigSTL*)conf;
2345 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2346
2347 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2348 Int_t nvalues = vec->size();
2349 buf.WriteInt(nvalues);
2350
2351 double *begin = &(*vec->begin());
2352 buf.WriteFastArrayDouble32(begin, nvalues);
2353
2354 buf.SetByteCount(start);
2355 return 0;
2356 }
2357
2358 template <typename From, typename To>
2360 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2361 {
2362 // Collection of numbers. Memberwise or not, it is all the same.
2363
2364 TConfigSTL *config = (TConfigSTL*)conf;
2365 UInt_t start, count;
2366 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2367
2368 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2369 Int_t nvalues;
2370 buf.ReadInt(nvalues);
2371 vec->resize(nvalues);
2372
2373 From *temp = new From[nvalues];
2374 buf.ReadFastArray(temp, nvalues);
2375 for(Int_t ind = 0; ind < nvalues; ++ind) {
2376 (*vec)[ind] = (To)temp[ind];
2377 }
2378 delete [] temp;
2379
2380 buf.CheckByteCount(start,count,config->fTypeName);
2381 return 0;
2382 }
2383 };
2384
2385 template <typename From, typename To>
2387 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2388 {
2389 // Collection of numbers. Memberwise or not, it is all the same.
2390
2391 TConfigSTL *config = (TConfigSTL*)conf;
2392 UInt_t start, count;
2393 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2394
2395 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2396 Int_t nvalues;
2397 buf.ReadInt(nvalues);
2398 vec->resize(nvalues);
2399
2400 From *temp = new From[nvalues];
2401 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2402 for(Int_t ind = 0; ind < nvalues; ++ind) {
2403 (*vec)[ind] = (To)temp[ind];
2404 }
2405 delete [] temp;
2406
2407 buf.CheckByteCount(start,count,config->fTypeName);
2408 return 0;
2409 }
2410 };
2411
2412 template <typename To>
2414 {
2415 // Collection of numbers. Memberwise or not, it is all the same.
2416
2417 TConfigSTL *config = (TConfigSTL*)conf;
2418 UInt_t start, count;
2419 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2420
2421 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2422 Int_t nvalues;
2423 buf.ReadInt(nvalues);
2424 vec->resize(nvalues);
2425
2426 Double32_t *temp = new Double32_t[nvalues];
2427 buf.ReadFastArrayDouble32(temp, nvalues);
2428 for(Int_t ind = 0; ind < nvalues; ++ind) {
2429 (*vec)[ind] = (To)temp[ind];
2430 }
2431 delete [] temp;
2432
2433 buf.CheckByteCount(start,count,config->fTypeName);
2434 return 0;
2435 }
2436
2437 template <typename Memory, typename Onfile>
2439 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2440 {
2441 // Collection of numbers. Memberwise or not, it is all the same.
2442
2443 TConfigSTL *config = (TConfigSTL*)conf;
2444 UInt_t start = buf.WriteVersion( config->fInfo->IsA(), kTRUE );
2445
2446 std::vector<Memory> *const vec = (std::vector<Memory>*)(((char*)addr)+config->fOffset);
2447 Int_t nvalues = vec->size();
2448 buf.WriteInt(nvalues);
2449
2450 // We have to call WriteFastArray for proper JSON writing
2451 // So we need to convert before hand :(
2452 Onfile *temp = new Onfile[nvalues];
2453 for(Int_t ind = 0; ind < nvalues; ++ind) {
2454 temp[ind] = (Onfile)((*vec)[ind]);
2455 }
2456 buf.WriteFastArray(temp, nvalues);
2457 delete [] temp;
2458
2459 buf.SetByteCount(start, kTRUE);
2460 return 0;
2461 }
2462 };
2463 };
2464
2465 struct VectorPtrLooper : public CollectionLooper<VectorPtrLooper> {
2466 // Can not inherit/use CollectionLooper<VectorPtrLooper>, because this looper's
2467 // function do not take a `TLoopConfiguration`.
2468
2469 using LoopAction_t = Int_t (*)(TBuffer &, void *start, const void *end, const TConfiguration*);
2470
2471 template <bool kIsText>
2473 template <bool kIsText>
2475
2476 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2478 {
2479 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2480 return unique_ptr(info.GetReadMemberWiseActions(kTRUE)->CreateCopy());
2481 }
2482
2483 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2485 {
2486 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2487 return unique_ptr(info.GetWriteMemberWiseActions(kTRUE)->CreateCopy());
2488 }
2489
2490 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2491 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2492 {
2493 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2494 action(buf, *(void**)iter, config);
2495 }
2496 return 0;
2497 }
2498
2499 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2500 {
2501 auto conf = (TConfSubSequence*)config;
2502 auto actions = conf->fActions.get();
2503 // FIXME: need to update the signature of ApplySequence.
2504 buf.ApplySequenceVecPtr(*actions, start, const_cast<void*>(end));
2505 return 0;
2506 }
2507
2508 template <typename T>
2509 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2510 {
2511 const Int_t offset = config->fOffset;
2512
2513 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2514 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2515 buf >> *x;
2516 }
2517 return 0;
2518 }
2519
2520 template <typename From, typename To>
2522 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2523 {
2524 // Simple conversion from a 'From' on disk to a 'To' in memory.
2525 From temp;
2526 const Int_t offset = config->fOffset;
2527 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2528 buf >> temp;
2529 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2530 *x = (To)temp;
2531 }
2532 return 0;
2533 }
2534 };
2535
2536 template <typename To>
2538 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2539 {
2540 // Simple conversion from a 'From' on disk to a 'To' in memory.
2541 UInt_t temp;
2542 const Int_t offset = config->fOffset;
2543 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2544 buf >> temp;
2545
2546 if ((temp & kIsReferenced) != 0) {
2547 HandleReferencedTObject(buf,*(void**)iter,config);
2548 }
2549
2550 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2551 *x = (To)temp;
2552 }
2553 return 0;
2554 }
2555 };
2556
2557 template <typename From, typename To>
2559 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2560 {
2561 // Simple conversion from a 'From' on disk to a 'To' in memory.
2562 TConfWithFactor *conf = (TConfWithFactor *)config;
2563 From temp;
2564 const Int_t offset = config->fOffset;
2565 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2566 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2567 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2568 *x = (To)temp;
2569 }
2570 return 0;
2571 }
2572 };
2573
2574 template <typename From, typename To>
2576 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2577 {
2578 // Simple conversion from a 'From' on disk to a 'To' in memory.
2579 TConfNoFactor *conf = (TConfNoFactor *)config;
2580 From temp;
2581 const Int_t offset = config->fOffset;
2582 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2583 buf.ReadWithNbits(&temp, conf->fNbits);
2584 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2585 *x = (To)temp;
2586 }
2587 return 0;
2588 }
2589 };
2590
2591 template <typename T>
2592 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2593 {
2594 const Int_t offset = config->fOffset;
2595
2596 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2597 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2598 buf << *x;
2599 }
2600 return 0;
2601 }
2602
2603 template <typename To, typename From>
2605 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2606 {
2607 const Int_t offset = config->fOffset;
2608
2609 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2610 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2611 To to = (To)(*from);
2612 buf << to;
2613 }
2614 return 0;
2615 }
2616 };
2617
2618 template <typename To, typename From>
2620 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2621 {
2622 const Int_t offset = config->fOffset;
2623 const TStreamerElement *elem = config->fCompInfo->fElem;
2624
2625 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2626 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2627 To to = (To)(*from);
2628 WriteCompressed(buf, &to, elem);
2629 }
2630 return 0;
2631 }
2632 };
2633 template <typename To, typename From>
2635 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2636 {
2637 const Int_t offset = config->fOffset;
2638 const TStreamerElement *elem = config->fCompInfo->fElem;
2639
2640 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2641 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2642 To to = (To)(*from);
2643 WriteCompressed(buf, &to, elem);
2644 }
2645 return 0;
2646 }
2647 };
2648
2649 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2650 {
2651 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2652 // punt.
2653
2654 return GenericRead(buf,start,end,config);
2655 }
2656
2657 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2658 {
2659 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2660 // punt.
2661
2662 return GenericWrite(buf,start,end,config);
2663 }
2664
2665 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2666 {
2667 UInt_t pos, count;
2668 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
2669
2670 LoopOverCollection< ReadViaExtStreamer >(buf, start, end, config);
2671
2672 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
2673 return 0;
2674 }
2675
2676 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2677 {
2678 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2679
2680 LoopOverCollection< WriteViaExtStreamer >(buf, start, end, config);
2681
2682 buf.SetByteCount(pos, kTRUE);
2683 return 0;
2684 }
2685
2686 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2687 {
2688 Int_t n = ( ((void**)end) - ((void**)iter) );
2689 char **arr = (char**)iter;
2690 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2691 }
2692
2693 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2694 {
2695 Int_t n = ( ((void**)end) - ((void**)iter) );
2696 char **arr = (char**)iter;
2697 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2698 }
2699
2700 };
2701
2703 using LoopAction_t = void (*)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem);
2704
2705protected:
2706
2707 template <typename T>
2708 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2709 {
2710 buf.ReadFastArray((T*)addr, nvalues);
2711 }
2712
2713 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2714 {
2715 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2716 }
2717
2718 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2719 {
2720 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2721 }
2722
2723 template <typename T>
2724 static INLINE_TEMPLATE_ARGS void SimpleWrite(TBuffer &buf, void *addr, const TStreamerElement *)
2725 {
2726 buf << *(T*)addr;
2727 }
2728
2729 static INLINE_TEMPLATE_ARGS void SimpleWriteFloat16(TBuffer &buf, void *addr, const TStreamerElement *elem)
2730 {
2731 buf.WriteFloat16((float*)addr, const_cast<TStreamerElement*>(elem));
2732 }
2733
2734 static INLINE_TEMPLATE_ARGS void SimpleWriteDouble32(TBuffer &buf, void *addr, const TStreamerElement *elem)
2735 {
2736 buf.WriteDouble32((double*)addr, const_cast<TStreamerElement*>(elem));
2737 }
2738
2739 template <typename T>
2740 static INLINE_TEMPLATE_ARGS void ArrayWrite(TBuffer &buf, void *addr, Int_t nvalues, const TStreamerElement *)
2741 {
2742 buf.WriteFastArray((T*)addr, nvalues);
2743 }
2744
2745 static INLINE_TEMPLATE_ARGS void ArrayWriteCompressed(TBuffer &buf, float *addr, Int_t nvalues, const TStreamerElement *elem)
2746 {
2747 buf.WriteFastArrayFloat16((float*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2748 }
2749
2750 static INLINE_TEMPLATE_ARGS void ArrayWriteCompressed(TBuffer &buf, double *addr, Int_t nvalues, const TStreamerElement *elem)
2751 {
2752 buf.WriteFastArrayDouble32((double*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2753 }
2754
2755 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2757 {
2758 // Collection of numbers. Memberwise or not, it is all the same.
2759
2760 TConfigSTL *config = (TConfigSTL*)conf;
2761 UInt_t start, count;
2762 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2763
2764 TClass *newClass = config->fNewClass;
2765 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2766 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2767
2768 Int_t nvalues;
2769 buf.ReadInt(nvalues);
2770 void* alternative = newProxy->Allocate(nvalues,true);
2771 if (nvalues) {
2774 void *begin = &(startbuf[0]);
2775 void *end = &(endbuf[0]);
2776 config->fCreateIterators(alternative, &begin, &end, newProxy);
2777 // We can not get here with a split vector of pointer, so we can indeed assume
2778 // that actions->fConfiguration != null.
2779
2780 action(buf,begin,nvalues);
2781
2782 if (begin != &(startbuf[0])) {
2783 // assert(end != endbuf);
2784 config->fDeleteTwoIterators(begin,end);
2785 }
2786 }
2787 newProxy->Commit(alternative);
2788
2789 buf.CheckByteCount(start,count,config->fTypeName);
2790 return 0;
2791 }
2792
2793 template <void (*action)(TBuffer&, void*, const TStreamerElement*)>
2794 static INLINE_TEMPLATE_ARGS void LoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t /* nvalues */, const TStreamerElement *elem)
2795 {
2796 void *addr;
2797 while( (addr = next(iter, end)) )
2798 {
2799 action(buf, addr, elem);
2800 }
2801 }
2802
2803 template <typename Memory, typename Onfile, void (*action)(TBuffer&, void*, Int_t, const TStreamerElement *elem)>
2804 static INLINE_TEMPLATE_ARGS void ConvertLoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t nvalues, const TStreamerElement *elem)
2805 {
2806 Onfile *temp = new Onfile[nvalues];
2807 Int_t ind = 0;
2808 void *addr;
2809 while( (addr = next(iter, end)) )
2810 {
2811 temp[ind] = (Onfile)*(Memory*)addr;
2812 ++ind;
2813 }
2814 action(buf, temp, nvalues, elem);
2815 delete [] temp;
2816 }
2817
2818 template <typename T, void (*action)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem)>
2820 {
2821 // Collection of numbers. Memberwise or not, it is all the same.
2822
2823 TConfigSTL *config = (TConfigSTL*)conf;
2824 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2825
2826 TClass *newClass = config->fNewClass;
2827 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2828 void *collection = ((char*)addr)+config->fOffset;
2829 TVirtualCollectionProxy::TPushPop helper( newProxy, collection);
2830
2831 Int_t nvalues = newProxy->Size();
2832 buf.WriteInt(nvalues);
2833 if (nvalues) {
2836 void *begin = &(startbuf[0]);
2837 void *end = &(endbuf[0]);
2838 config->fCreateIterators(collection, &begin, &end, newProxy);
2839
2840 action(buf, begin, end, config->fNext, nvalues, config->fCompInfo->fElem);
2841
2842 if (begin != &(startbuf[0])) {
2843 // assert(end != endbuf);
2844 config->fDeleteTwoIterators(begin, end);
2845 }
2846 }
2847 buf.SetByteCount(start);
2848 return 0;
2849 }
2850
2851public:
2853 {
2854 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2855 }
2856
2858 {
2859 return WriteNumericalCollection<Float_t,LoopOverCollection<SimpleWriteFloat16> >(buf,addr,conf);
2860 }
2861
2863 {
2864 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2865 }
2866
2868 {
2869 return WriteNumericalCollection<Double_t,LoopOverCollection<SimpleWriteDouble32> >(buf,addr,conf);
2870 }
2871
2872 template <typename T>
2874 {
2875 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2876 }
2877
2878 template <typename T>
2880 {
2881 return WriteNumericalCollection<T, LoopOverCollection<SimpleWrite<T>> >(buf,addr,conf);
2882 }
2883
2884 template <typename From, typename To>
2886 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2887 {
2888 From *temp = new From[nvalues];
2889 buf.ReadFastArray(temp, nvalues);
2890 To *vec = (To*)addr;
2891 for(Int_t ind = 0; ind < nvalues; ++ind) {
2892 vec[ind] = (To)temp[ind];
2893 }
2894 delete [] temp;
2895 }
2896 };
2897
2898 template <typename From, typename To>
2899 struct ConvertRead<NoFactorMarker<From>,To> {
2900 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2901 {
2902 From *temp = new From[nvalues];
2903 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2904 To *vec = (To*)addr;
2905 for(Int_t ind = 0; ind < nvalues; ++ind) {
2906 vec[ind] = (To)temp[ind];
2907 }
2908 delete [] temp;
2909 }
2910 };
2911
2912 template <typename From, typename To>
2914 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2915 {
2916 From *temp = new From[nvalues];
2917 double factor,min; // needs to be initialized.
2918 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2919 To *vec = (To*)addr;
2920 for(Int_t ind = 0; ind < nvalues; ++ind) {
2921 vec[ind] = (To)temp[ind];
2922 }
2923 delete [] temp;
2924 }
2925 };
2926 template <typename From, typename To>
2928 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2929 {
2930 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2931 }
2932 };
2933
2934 template <typename Memory, typename Onfile>
2936 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2937 {
2938 return WriteNumericalCollection<Memory, ConvertLoopOverCollection<Memory, Onfile, ArrayWrite<Onfile>> >(buf,addr,conf);
2939 }
2940 };
2941 template <typename Memory, typename Onfile>
2943 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2944 {
2945 return WriteNumericalCollection<Memory, ConvertLoopOverCollection<Memory,Onfile, ArrayWriteCompressed> >(buf,addr,conf);
2946 }
2947 };
2948
2949 template <typename Memory, typename Onfile>
2951 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2952 {
2953 return WriteNumericalCollection<Memory, ConvertLoopOverCollection<Memory,Onfile, ArrayWriteCompressed> >(buf,addr,conf);
2954 }
2955 };
2956
2957 };
2958
2959 struct GenericLooper : public CollectionLooper<GenericLooper> {
2960 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
2961
2962 template <bool kIsText>
2964 template <bool kIsText>
2966
2967 template <typename T>
2968 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2969 {
2970 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2971
2972 Next_t next = loopconfig->fNext;
2973 const Int_t offset = config->fOffset;
2974
2976 void *iter = loopconfig->fCopyIterator(iterator,start);
2977 void *addr;
2978 while( (addr = next(iter,end)) ) {
2979 T *x = (T*)( ((char*)addr) + offset );
2980 buf >> *x;
2981 }
2982 if (iter != &iterator[0]) {
2983 loopconfig->fDeleteIterator(iter);
2984 }
2985 return 0;
2986 }
2987
2988 template <typename T>
2989 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2990 {
2991 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2992
2993 Next_t next = loopconfig->fNext;
2994 const Int_t offset = config->fOffset;
2995
2997 void *iter = loopconfig->fCopyIterator(iterator,start);
2998 void *addr;
2999 while( (addr = next(iter,end)) ) {
3000 T *x = (T*)( ((char*)addr) + offset );
3001 buf << *x;
3002 }
3003 if (iter != &iterator[0]) {
3004 loopconfig->fDeleteIterator(iter);
3005 }
3006 return 0;
3007 }
3008
3009 template <typename To, typename From>
3011 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3012 {
3013 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3014
3015 Next_t next = loopconfig->fNext;
3016 const Int_t offset = config->fOffset;
3017
3019 void *iter = loopconfig->fCopyIterator(iterator,start);
3020 void *addr;
3021 while( (addr = next(iter,end)) ) {
3022 From *x = (From*)( ((char*)addr) + offset );
3023 To t = (To)(*x);
3024 buf << t;
3025 }
3026 if (iter != &iterator[0]) {
3027 loopconfig->fDeleteIterator(iter);
3028 }
3029 return 0;
3030 }
3031 };
3032
3033 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
3034 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3035 {
3036 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3037
3038 // const Int_t offset = config->fOffset;
3039 Next_t next = loopconfig->fNext;
3040
3042 void *iter = loopconfig->fCopyIterator(&iterator,start);
3043 void *addr;
3044 while( (addr = next(iter,end)) ) {
3045 iter_action(buf, addr, config);
3046 }
3047 if (iter != &iterator[0]) {
3048 loopconfig->fDeleteIterator(iter);
3049 }
3050 return 0;
3051 }
3052
3053 template <typename From, typename To>
3054 struct Generic {
3055 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3056 {
3057 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3058
3059 const Int_t offset = config->fOffset;
3060 Next_t next = loopconfig->fNext;
3061
3063 void *iter = loopconfig->fCopyIterator(&iterator,start);
3064 void *addr;
3065 while( (addr = next(iter,end)) ) {
3066 To *x = (To*)( ((char*)addr) + offset );
3067 *x = (To)(*items);
3068 ++items;
3069 }
3070 if (iter != &iterator[0]) {
3071 loopconfig->fDeleteIterator(iter);
3072 }
3073 }
3074 // ConvertAction used for writing.
3075 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config, To *items)
3076 {
3077 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3078
3079 const Int_t offset = config->fOffset;
3080 Next_t next = loopconfig->fNext;
3081
3083 void *iter = loopconfig->fCopyIterator(&iterator,start);
3084 void *addr;
3085
3086 while( (addr = next(iter,end)) ) {
3087 From *x = (From*)( ((char*)addr) + offset );
3088 *items = (To)*x;
3089 ++items;
3090 }
3091 if (iter != &iterator[0]) {
3092 loopconfig->fDeleteIterator(iter);
3093 }
3094 }
3095 };
3096
3097 template <typename From, typename To>
3098 struct Numeric {
3099 // ConvertAction used for reading.
3100 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
3101 {
3102 // The difference with ConvertAction is that we can modify the start
3103 // iterator and skip the copy. We also never have an offset.
3104
3105 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3106 Next_t next = loopconfig->fNext;
3107
3108 void *iter = start;
3109 void *addr;
3110 while( (addr = next(iter,end)) ) {
3111 To *x = (To*)(addr);
3112 *x = (To)(*items);
3113 ++items;
3114 }
3115 }
3116 // ConvertAction used for writing.
3117 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */, To *items)
3118 {
3119 // The difference with ConvertAction is that we can modify the start
3120 // iterator and skip the copy. We also never have an offset.
3121
3122 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3123 Next_t next = loopconfig->fNext;
3124
3125 void *iter = start;
3126 void *addr;
3127 while( (addr = next(iter,end)) ) {
3128 From *x = (From*)(addr);
3129 *items = (To)*x;
3130 ++items;
3131 }
3132 }
3133 };
3134
3135 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
3137 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3138 {
3139 // Simple conversion from a 'From' on disk to a 'To' in memory.
3140
3141 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3142 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3143 Int_t nvalues = proxy->Size();
3144
3145 From *items = new From[nvalues];
3146 buf.ReadFastArray(items, nvalues);
3147 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3148 delete [] items;
3149 return 0;
3150 }
3151 };
3152
3153 template <typename To>
3155 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3156 {
3157 // Simple conversion from a 'From' on disk to a 'To' in memory.
3158
3159 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3160 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3161 Int_t nvalues = proxy->Size();
3162
3163 UInt_t *items_storage = new UInt_t[nvalues];
3164 UInt_t *items = items_storage;
3165
3166 const Int_t offset = config->fOffset;
3167 Next_t next = loopconfig->fNext;
3168
3170 void *iter = loopconfig->fCopyIterator(&iterator,start);
3171 void *addr;
3172 while( (addr = next(iter,end)) ) {
3173 buf >> (*items);
3174 if (((*items) & kIsReferenced) != 0) {
3175 HandleReferencedTObject(buf, addr, config);
3176 }
3177 To *x = (To*)( ((char*)addr) + offset );
3178 *x = (To)(*items);
3179 ++items;
3180 }
3181 if (iter != &iterator[0]) {
3182 loopconfig->fDeleteIterator(iter);
3183 }
3184
3185 delete [] items_storage;
3186 return 0;
3187 }
3188 };
3189
3190 template <typename From, typename To, template <typename F, typename T> class Converter >
3191 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
3192 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3193 {
3194 // Simple conversion from a 'From' on disk to a 'To' in memory.
3195
3196 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3197 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3198 Int_t nvalues = proxy->Size();
3199
3200 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
3201
3202 From *items = new From[nvalues];
3203 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
3204 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3205 delete [] items;
3206 return 0;
3207 }
3208 };
3209
3210 template <typename From, typename To, template <typename F, typename T> class Converter >
3211 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
3212 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3213 {
3214 // Simple conversion from a 'From' on disk to a 'To' in memory.
3215
3216 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3217 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3218 Int_t nvalues = proxy->Size();
3219
3220 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
3221
3222 From *items = new From[nvalues];
3223 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
3224 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3225 delete [] items;
3226 return 0;
3227 }
3228 };
3229
3230 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter = Generic >
3232 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3233 {
3234 // Simple conversion from a 'From' on disk to a 'To' in memory.
3235
3236 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3237 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3238 Int_t nvalues = proxy->Size();
3239
3240 Onfile *items = new Onfile[nvalues];
3241 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3242 buf.WriteFastArray(items, nvalues);
3243 delete [] items;
3244 return 0;
3245 }
3246 };
3247
3248 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3249 struct WriteConvertBasicType<WithFactorMarker<Onfile>, Memory, Converter > {
3250 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3251 {
3252 // Simple conversion from a 'From' on disk to a 'To' in memory.
3253
3254 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3255 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3256 Int_t nvalues = proxy->Size();
3257
3258 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
3259
3260 Onfile *items = new Onfile[nvalues];
3261 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3262 R__ASSERT(false && "Not yet implemented");
3263 (void)conf;
3264 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3265 delete [] items;
3266 return 0;
3267 }
3268 };
3269
3270 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3271 struct WriteConvertBasicType<NoFactorMarker<Onfile>, Memory, Converter > {
3272 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3273 {
3274 // Simple conversion from a 'From' on disk to a 'To' in memory.
3275
3276 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3277 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3278 Int_t nvalues = proxy->Size();
3279
3280 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
3281
3282 Onfile *items = new Onfile[nvalues];
3283 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3284 R__ASSERT(false && "Not yet implemented");
3285 (void)conf;
3286 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3287 delete [] items;
3288 return 0;
3289 }
3290 };
3291
3292 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3293 {
3294 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3295 // punt.
3296
3297 return GenericRead(buf,start,end,loopconfig, config);
3298 }
3299
3300 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3301 {
3302 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3303 // punt.
3304
3305 return GenericWrite(buf,start,end,loopconfig, config);
3306 }
3307
3308 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3309 {
3310 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3311 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3312 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
3313 }
3314
3315 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3316 {
3317 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
3318 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
3319 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
3320 }
3321
3322 template <typename T>
3323 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
3324 {
3325 buf >> *(T*)addr;
3326 }
3327
3328 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
3329 {
3330 buf.ReadWithNbits((float*)addr,12);
3331 }
3332
3334 {
3335 buf.WriteFloat16((float*)addr, nullptr);
3336 }
3337
3339 {
3340 //we read a float and convert it to double
3341 Float_t afloat;
3342 buf >> afloat;
3343 *(double*)addr = (Double_t)afloat;
3344 }
3345
3347 {
3348 //we read a float and convert it to double
3349 Float_t afloat = (Float_t)*(double*)addr;
3350 buf << afloat;
3351 }
3352
3353 template <typename ActionHolder>
3355 {
3356 // Collection of numbers. Memberwise or not, it is all the same.
3357
3358 TConfigSTL *config = (TConfigSTL*)conf;
3359 UInt_t start, count;
3360 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
3361
3362 TClass *newClass = config->fNewClass;
3363 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3364 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
3365
3366 Int_t nvalues;
3367 buf.ReadInt(nvalues);
3368 void* alternative = newProxy->Allocate(nvalues,true);
3369 if (nvalues) {
3372 void *begin = &(startbuf[0]);
3373 void *end = &(endbuf[0]);
3374 config->fCreateIterators(alternative, &begin, &end, newProxy);
3375 // We can not get here with a split vector of pointer, so we can indeed assume
3376 // that actions->fConfiguration != null.
3377
3378 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
3379 ActionHolder::Action(buf,begin,end,&loopconf,config);
3380
3381 if (begin != &(startbuf[0])) {
3382 // assert(end != endbuf);
3383 config->fDeleteTwoIterators(begin,end);
3384 }
3385 }
3386 newProxy->Commit(alternative);
3387
3388 buf.CheckByteCount(start,count,config->fTypeName);
3389 return 0;
3390 }
3391
3392 template <typename ActionHolder>
3394 {
3395 // Collection of numbers. Memberwise or not, it is all the same.
3396
3397 TConfigSTL *config = (TConfigSTL*)conf;
3398 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
3399
3400 TClass *newClass = config->fNewClass;
3401 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3402 void *collection = ((char*)addr)+config->fOffset;
3403 TVirtualCollectionProxy::TPushPop helper( newProxy, collection );
3404
3405 Int_t nvalues = newProxy->Size();
3406 buf.WriteInt(nvalues);
3407 if (nvalues) {
3410 void *begin = &(startbuf[0]);
3411 void *end = &(endbuf[0]);
3412 config->fCreateIterators(collection, &begin, &end, newProxy);
3413 // We can not get here with a split vector of pointer, so we can indeed assume
3414 // that actions->fConfiguration != null.
3415
3416 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
3417 ActionHolder::Action(buf,begin,end,&loopconf,config);
3418
3419 if (begin != &(startbuf[0])) {
3420 // assert(end != endbuf);
3421 config->fDeleteTwoIterators(begin,end);
3422 }
3423 }
3424
3425 buf.SetByteCount(start);
3426 return 0;
3427 }
3428
3430 {
3431 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>, float, Numeric > >(buf,addr,conf);
3432 }
3433
3435 {
3436 return WriteNumericalCollection<WriteConvertBasicType<NoFactorMarker<float>, float, Numeric > >(buf,addr,conf);
3437 }
3438
3440 {
3441 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
3442 // Could also use:
3443 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
3444 }
3445
3447 {
3448 return WriteNumericalCollection<WriteConvertBasicType<float, double ,Numeric > >(buf,addr,conf);
3449 // Could also use:
3450 // return ReadNumericalCollection<WriteConvertBasicType<NoFactorMarker<double>, double, Numeric > >(buf,addr,conf);
3451 }
3452
3453 template <typename T>
3455 {
3456 //TODO: Check whether we can implement this without loading the data in
3457 // a temporary variable and whether this is noticeably faster.
3458 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
3459 }
3460
3461 template <typename T>
3463 {
3464 //TODO: Check whether we can implement this without loading the data in
3465 // a temporary variable and whether this is noticeably faster.
3466 return WriteNumericalCollection<WriteConvertBasicType<T,T,Numeric > >(buf,addr,conf);
3467 }
3468
3469 template <typename From, typename To>
3471 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
3472 {
3473 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3474 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
3475 }
3476 };
3477
3478 template <typename Memory, typename Onfile>
3480 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
3481 {
3482 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3483 return WriteNumericalCollection<WriteConvertBasicType<Memory,Onfile,Numeric > >(buf,addr,conf);
3484 }
3485 };
3486 };
3487}
3488
3489// Used in GetCollectionReadAction for the kConv cases within a collection
3490// Not to be confused with GetConvertCollectionReadAction
3491template <typename Looper, typename From>
3493{
3494 switch (newtype) {
3495 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf );
3496 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf );
3498 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf );
3511 default:
3512 return TConfiguredAction( Looper::GenericRead, conf );
3513 }
3514 R__ASSERT(0); // We should never be here
3515 return TConfiguredAction();
3516}
3517
3518template <class Looper>
3520{
3521 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
3522
3523 switch (type) {
3524 // Read basic types.
3525
3526 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
3527 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<bool,bool>::Action, conf );
3528 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf );
3529 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf );
3530 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf );
3531 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf );
3532 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf );
3533 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf );
3534 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf );
3535 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf );
3536 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf );
3537 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf );
3538 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf );
3539 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf );
3540 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
3542 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
3543 delete conf;
3544 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
3545 // if (element->GetFactor() != 0) {
3546 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3547 // } else {
3548 // Int_t nbits = (Int_t)element->GetXmin();
3549 // if (!nbits) nbits = 12;
3550 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3551 // }
3552 }
3554 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
3555 delete conf;
3556 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
3557 // if (element->GetFactor() != 0) {
3558 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3559 // } else {
3560 // Int_t nbits = (Int_t)element->GetXmin();
3561 // if (!nbits) {
3562 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
3563 // } else {
3564 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3565 // }
3566 // }
3567 }
3568 }
3569 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
3570 R__ASSERT(0); // We should never be here
3571 return TConfiguredAction();
3572}
3573
3574template <typename Looper, typename From>
3576{
3577 switch (newtype) {
3578 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf );
3579 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf );
3580 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf );
3581 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf );
3582 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf );
3583 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf );
3584 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3585 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3586 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3587 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3588 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf );
3589 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf );
3590 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3591 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf );
3592 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3593 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3594 default:
3595 break;
3596 }
3597 Error("GetConvertCollectionReadActionFrom", "UNEXPECTED: newtype == %d", newtype);
3598 R__ASSERT(0); // We should never be here
3599 return TConfiguredAction();
3600}
3601
3602// Used in AddReadAction to implement the kSTL cases
3603// Not to be confused with GetCollectionReadConvertAction
3604// nor with GetConvertCollectionReadActionFrom (used to implement this function)
3605template <typename Looper>
3607{
3608 switch (oldtype) {
3610 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
3612 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
3614 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
3616 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
3618 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
3620 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
3622 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
3624 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
3626 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
3628 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
3630 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
3632 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
3634 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
3636 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
3638 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
3640 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
3641 break;
3642 default:
3643 break;
3644 }
3645 Error("GetConvertCollectionReadAction", "UNEXPECTED: oldtype == %d", oldtype);
3646 R__ASSERT(0); // We should never be here
3647 return TConfiguredAction();
3648}
3649
3650template <class Looper>
3651static TConfiguredAction
3654{
3655 switch (type) {
3656 // Read basic types.
3657 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) );
3658 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) );
3659 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) );
3660 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) );
3661 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) );
3662 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) );
3663 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) );
3664 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) );
3665 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) );
3666 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) );
3667 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) );
3668 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) );
3669 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) );
3670 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template LoopOverCollection<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) );
3672 if (element->GetFactor() != 0) {
3673 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3674 } else {
3675 Int_t nbits = (Int_t)element->GetXmin();
3676 if (!nbits) nbits = 12;
3677 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3678 }
3679 }
3681 if (element->GetFactor() != 0) {
3682 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3683 } else {
3684 Int_t nbits = (Int_t)element->GetXmin();
3685 if (!nbits) {
3686 return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
3687 } else {
3688 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3689 }
3690 }
3691 }
3693 return TConfiguredAction( Looper::template LoopOverCollection<ReadTNamed >, new TConfiguration(info, i, compinfo, offset) );
3694 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3695 // Streamer alltogether.
3697 return TConfiguredAction( Looper::template LoopOverCollection<ReadTObject >, new TConfiguration(info, i, compinfo,offset) );
3699 return TConfiguredAction( Looper::template LoopOverCollection<ReadTString >, new TConfiguration(info, i, compinfo,offset) );
3703 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3704 case TStreamerInfo::kBase: {
3705 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3706 if (baseEl) {
3707 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
3708 assert(baseinfo);
3709 TLoopConfiguration *baseLoopConfig = loopConfig ? loopConfig->Copy() : nullptr;
3710 auto baseActions = Looper::CreateReadActionSquence(*baseinfo, baseLoopConfig);
3711 baseActions->AddToOffset(baseEl->GetOffset());
3712 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
3713
3714 } else
3715 return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info, i, compinfo) );
3716 }
3719 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
3720 return TConfiguredAction(Looper::template ReadStreamerLoop<false>::Action,
3721 new TConfStreamerLoop(info, i, compinfo, offset, isPtrPtr));
3722 }
3724 if (info->GetOldVersion() >= 3)
3725 return TConfiguredAction( Looper::ReadStreamerCase, new TGenericConfiguration(info, i, compinfo) );
3726 else
3727 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3729 if (compinfo->fStreamer)
3730 return TConfiguredAction( Looper::template LoopOverCollection<ReadViaExtStreamer >, new TConfiguration(info, i, compinfo,offset) );
3731 else {
3732 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
3733 return TConfiguredAction( Looper::template LoopOverCollection<ReadViaClassBuffer>,
3734 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
3735 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
3736 return TConfiguredAction( Looper::template LoopOverCollection<ReadViaClassBuffer>,
3737 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
3738 else // Use the slower path for unusual cases
3739 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3740 }
3741
3742 // Conversions.
3744 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3746 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3748 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3750 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3752 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3754 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3756 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3758 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3760 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3762 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3764 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3766 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3768 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3770 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
3772 if (element->GetFactor() != 0) {
3773 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3774 } else {
3775 Int_t nbits = (Int_t)element->GetXmin();
3776 if (!nbits) nbits = 12;
3777 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
3778 }
3779 }
3781 if (element->GetFactor() != 0) {
3782 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3783 } else {
3784 Int_t nbits = (Int_t)element->GetXmin();
3785 if (!nbits) {
3786 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3787 } else {
3788 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
3789 }
3790 }
3791 }
3792 default:
3793 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
3794 }
3795 R__ASSERT(0); // We should never be here
3796 return TConfiguredAction();
3797}
3798
3799template <typename Looper, typename From>
3801{
3802 switch (onfileType) {
3803 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,bool>::Action, conf );
3804 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,char>::Action, conf );
3805 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,short>::Action, conf );
3806 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Int_t>::Action, conf );
3807 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long_t>::Action, conf );
3808 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long64_t>::Action, conf );
3809 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,float>::Action, conf );
3810 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,double>::Action, conf );
3811 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UChar_t>::Action, conf );
3812 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UShort_t>::Action, conf );
3813 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3814 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong_t>::Action, conf );
3815 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3816 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3817
3818 // Supporting this requires adding TBuffer::WiteFastArrayWithNbits
3819 // and the proper struct WriteConvertCollectionBasicType<Memory, NoFactorMarker<Onfile>> here
3821 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Float16_t not yet supported");
3822 return TConfiguredAction();
3823 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Float16_t>>::Action, conf );
3825 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Double32_t not yet supported");
3826 return TConfiguredAction();
3827 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Double32_t>>::Action, conf );
3828 default:
3829 break;
3830 }
3831 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: onfileType/oldtype == %d", onfileType);
3832 R__ASSERT(0); // We should never be here
3833 return TConfiguredAction();
3834}
3835
3836// Used in to implement the kSTL case
3837// Not to be confused with GetCollectionWriteConvertAction
3838// nor with GetConvertCollectionWriteActionFrom (used to implement this function)
3839template <typename Looper>
3841{
3842 switch (memoryType) {
3844 return GetConvertCollectionWriteActionFrom<Looper,Bool_t>(onfileType, conf );
3846 return GetConvertCollectionWriteActionFrom<Looper,Char_t>(onfileType, conf );
3848 return GetConvertCollectionWriteActionFrom<Looper,Short_t>(onfileType, conf );
3850 return GetConvertCollectionWriteActionFrom<Looper,Int_t>(onfileType, conf );
3852 return GetConvertCollectionWriteActionFrom<Looper,Long_t>(onfileType, conf );
3854 return GetConvertCollectionWriteActionFrom<Looper,Long64_t>(onfileType, conf );
3856 return GetConvertCollectionWriteActionFrom<Looper,Float_t>(onfileType, conf );
3858 return GetConvertCollectionWriteActionFrom<Looper,Double_t>(onfileType, conf );
3860 return GetConvertCollectionWriteActionFrom<Looper,UChar_t>(onfileType, conf );
3862 return GetConvertCollectionWriteActionFrom<Looper,UShort_t>(onfileType, conf );
3864 return GetConvertCollectionWriteActionFrom<Looper,UInt_t>(onfileType, conf );
3866 return GetConvertCollectionWriteActionFrom<Looper,ULong_t>(onfileType, conf );
3868 return GetConvertCollectionWriteActionFrom<Looper,ULong64_t>(onfileType, conf );
3870 return GetConvertCollectionWriteActionFrom<Looper,Float16_t>(onfileType, conf );
3872 return GetConvertCollectionWriteActionFrom<Looper,Double32_t>(onfileType, conf );
3874 Error("GetConvertCollectionWriteActionFrom","There is no support for kBits outside of a TObject.");
3875 break;
3876 default:
3877 break;
3878 }
3879 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: memoryType/newype == %d", memoryType);
3880 R__ASSERT(0); // We should never be here
3881 return TConfiguredAction();
3882}
3883
3884// Used in GetCollectionWriteAction for the kConv cases within a collection
3885// Not to be confused with GetConvertCollectionWriteAction
3886// Note the read and write version could be merged (using yet another template parameter)
3887template <typename Looper, typename Onfile>
3889{
3890 switch (newtype) {
3907 default:
3908 return TConfiguredAction( Looper::GenericRead, conf );
3909 }
3910 R__ASSERT(0); // We should never be here
3911 return TConfiguredAction();
3912}
3913
3914template <class Looper>
3915static TConfiguredAction
3918{
3919 switch (type) {
3920 // write basic types
3921 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) );
3922 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) );
3923 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) );
3924 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) );
3925 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) );
3926 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) );
3927 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) );
3928 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) );
3929 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) );
3930 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) );
3931 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) );
3932 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) );
3933 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) );
3934 // the simple type missing are kBits and kCounter.
3935
3936 // Handling of the error case where we are asked to write a missing data member.
3938 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Bool_t>>, new TConfiguration(info,i,compinfo,offset) );
3940 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Char_t>>, new TConfiguration(info,i,compinfo,offset) );
3942 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Short_t>>, new TConfiguration(info,i,compinfo,offset) );
3944 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Int_t>>, new TConfiguration(info,i,compinfo,offset) );
3946 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long_t>>, new TConfiguration(info,i,compinfo,offset) );
3948 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long64_t>>, new TConfiguration(info,i,compinfo,offset) );
3950 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Float_t>>, new TConfiguration(info,i,compinfo,offset) );
3952 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Double_t>>, new TConfiguration(info,i,compinfo,offset) );
3954 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UChar_t>>, new TConfiguration(info,i,compinfo,offset) );
3956 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UShort_t>>, new TConfiguration(info,i,compinfo,offset) );
3958 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UInt_t>>, new TConfiguration(info,i,compinfo,offset) );
3960 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong_t>>, new TConfiguration(info,i,compinfo,offset) );
3962 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong64_t>>, new TConfiguration(info,i,compinfo,offset) );
3963
3964 // Conversions.
3966 return GetCollectionWriteConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3968 return GetCollectionWriteConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3970 return GetCollectionWriteConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3972 return GetCollectionWriteConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3974 return GetCollectionWriteConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3976 return GetCollectionWriteConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3978 return GetCollectionWriteConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3980 return GetCollectionWriteConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3982 return GetCollectionWriteConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3984 return GetCollectionWriteConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3986 return GetCollectionWriteConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3988 return GetCollectionWriteConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3990 return GetCollectionWriteConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
3991#ifdef NOT_YET
3992 /* The conversion writing acceleration was not yet written for kBits */
3994 return GetCollectionWriteConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
3995#endif
3997 if (element->GetFactor() != 0) {
3998 return GetCollectionWriteConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3999 } else {
4000 Int_t nbits = (Int_t)element->GetXmin();
4001 if (!nbits) nbits = 12;
4002 return GetCollectionWriteConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
4003 }
4004 break;
4005 }
4007 if (element->GetFactor() != 0) {
4008 return GetCollectionWriteConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4009 } else {
4010 Int_t nbits = (Int_t)element->GetXmin();
4011 if (!nbits) {
4012 return GetCollectionWriteConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
4013 } else {
4014 return GetCollectionWriteConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
4015 }
4016 }
4017 break;
4018 }
4019 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template LoopOverCollection<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) );
4020 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4021 // Streamer alltogether.
4022 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template LoopOverCollection<WriteTObject >, new TConfiguration(info,i,compinfo,offset) );
4023 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template LoopOverCollection<WriteTString >, new TConfiguration(info,i,compinfo,offset) );
4024 case TStreamerInfo::kBase: {
4025 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
4026 if (baseEl) {
4027 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
4028 assert(baseinfo);
4029 TLoopConfiguration *baseLoopConfig = loopConfig ? loopConfig->Copy() : nullptr;
4030 auto baseActions = Looper::CreateWriteActionSquence(*baseinfo, baseLoopConfig);
4031 baseActions->AddToOffset(baseEl->GetOffset());
4032 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
4033
4034 } else
4035 return TConfiguredAction( Looper::WriteBase, new TGenericConfiguration(info, i, compinfo) );
4036 }
4039 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4040 return TConfiguredAction(Looper::template WriteStreamerLoop<false>::Action,
4041 new TConfStreamerLoop(info, i, compinfo, offset, isPtrPtr));
4042 }
4044 if (info->GetOldVersion() >= 3)
4045 return TConfiguredAction( Looper::WriteStreamerCase, new TGenericConfiguration(info, i, compinfo) );
4046 else
4047 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4049 if (compinfo->fStreamer)
4050 return TConfiguredAction( Looper::template LoopOverCollection<WriteViaExtStreamer >, new TConfiguration(info, i, compinfo,offset) );
4051 else {
4052 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4053 return TConfiguredAction( Looper::template LoopOverCollection<WriteViaClassBuffer>,
4054 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4055 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4056 return TConfiguredAction( Looper::template LoopOverCollection<WriteViaClassBuffer>,
4057 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4058 else // Use the slower path for unusual cases
4059 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4060 }
4061 default:
4062 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
4063 }
4064 R__ASSERT(0); // We should never be here
4065 return TConfiguredAction();
4066}
4067
4068template <class Looper>
4070{
4071 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
4072
4073 switch (type) {
4074 // Write basic types.
4075 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
4076 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<bool,bool>::Action, conf );
4077 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteCollectionBasicType<Char_t>, conf );
4078 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteCollectionBasicType<Short_t>,conf );
4079 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteCollectionBasicType<Int_t>, conf );
4080 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteCollectionBasicType<Long_t>, conf );
4081 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteCollectionBasicType<Long64_t>, conf );
4082 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteCollectionBasicType<Float_t>, conf );
4083 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteCollectionBasicType<Double_t>, conf );
4084 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteCollectionBasicType<UChar_t>, conf );
4085 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteCollectionBasicType<UShort_t>, conf );
4086 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteCollectionBasicType<UInt_t>, conf );
4087 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteCollectionBasicType<ULong_t>, conf );
4088 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteCollectionBasicType<ULong64_t>, conf );
4089 case TStreamerInfo::kBits: Error("GetNumericCollectionWriteAction","There is no support for kBits outside of a TObject."); break;
4091 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
4092 delete conf;
4093 return TConfiguredAction( Looper::WriteCollectionFloat16, alternate );
4094 // if (element->GetFactor() != 0) {
4095 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4096 // } else {
4097 // Int_t nbits = (Int_t)element->GetXmin();
4098 // if (!nbits) nbits = 12;
4099 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4100 // }
4101 }
4103 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
4104 delete conf;
4105 return TConfiguredAction( Looper::WriteCollectionDouble32, alternate );
4106 // if (element->GetFactor() != 0) {
4107 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4108 // } else {
4109 // Int_t nbits = (Int_t)element->GetXmin();
4110 // if (!nbits) {
4111 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4112 // } else {
4113 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4114 // }
4115 // }
4116 }
4117 }
4118 Fatal("GetNumericCollectionWriteAction","Is confused about %d",type);
4119 R__ASSERT(0); // We should never be here
4120 return TConfiguredAction();
4121}
4122
4123////////////////////////////////////////////////////////////////////////////////
4124/// loop on the TStreamerElement list
4125/// regroup members with same type
4126/// Store predigested information into local arrays. This saves a huge amount
4127/// of time compared to an explicit iteration on all elements.
4128
4130{
4131 if (IsCompiled()) {
4132 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
4133 return;
4134 }
4136
4137 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
4138
4139 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
4141 fNdata = 0;
4142 fNfulldata = 0;
4143
4144 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
4145 if (fNumber < 0) {
4146 ++fgCount;
4147 fNumber = fgCount;
4148 }
4149 if (fNumber >= infos->GetSize()) {
4150 infos->AddAtAndExpand(this, fNumber);
4151 } else {
4152 if (!infos->At(fNumber)) {
4153 infos->AddAt(this, fNumber);
4154 }
4155 }
4156
4157 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
4158
4159
4160 Int_t ndata = fElements->GetEntriesFast();
4161
4162
4165
4168
4171
4172 if (fReadText) fReadText->fActions.clear();
4173 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
4174
4177
4180
4183
4184 if (fWriteText) fWriteText->fActions.clear();
4186
4187 if (!ndata) {
4188 // This may be the case for empty classes (e.g., TAtt3D).
4189 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
4191 fSize = sizeof(TStreamerInfo*);
4192 }
4193 fComp = new TCompInfo[1];
4194 fCompFull = new TCompInfo*[1];
4195 fCompOpt = new TCompInfo*[1];
4196 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
4197 SetIsCompiled();
4198 return;
4199 }
4200
4201 // At most half of the elements can be used to hold optimized versions.
4202 // We use the bottom to hold the optimized-into elements and the non-optimized elements
4203 // and the top to hold the original copy of the optimized out elements.
4204 fNslots = ndata + ndata/2 + 1;
4205 Int_t optiOut = 0;
4206
4207 fComp = new TCompInfo[fNslots];
4208 fCompFull = new TCompInfo*[ndata];
4209 fCompOpt = new TCompInfo*[ndata];
4210
4211 TStreamerElement* element;
4212 TStreamerElement* previous = 0;
4213 Int_t keep = -1;
4214 Int_t i;
4215
4216 if (!CanOptimize()) {
4218 }
4219
4220 Bool_t isOptimized = kFALSE;
4221 Bool_t previousOptimized = kFALSE;
4222
4223 for (i = 0; i < ndata; ++i) {
4224 element = (TStreamerElement*) fElements->At(i);
4225 if (!element) {
4226 break;
4227 }
4228
4229 Int_t asize = element->GetSize();
4230 if (element->GetArrayLength()) {
4231 asize /= element->GetArrayLength();
4232 }
4233 fComp[fNdata].fType = element->GetType();
4234 fComp[fNdata].fNewType = element->GetNewType();
4235 fComp[fNdata].fOffset = element->GetOffset();
4236 fComp[fNdata].fLength = element->GetArrayLength();
4237 fComp[fNdata].fElem = element;
4238 fComp[fNdata].fMethod = element->GetMethod();
4239 fComp[fNdata].fClass = element->GetClassPointer();
4240 fComp[fNdata].fNewClass = element->GetNewClass();
4242 fComp[fNdata].fStreamer = element->GetStreamer();
4243
4244 // try to group consecutive members of the same type
4246 && (keep >= 0)
4247 && (element->GetType() > 0)
4248 && (element->GetType() < 10)
4250 && (fComp[keep].fMethod == 0)
4251 && (element->GetArrayDim() == 0)
4252 && (fComp[keep].fType < kObject)
4253 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
4254 && (element->GetType() == (fComp[keep].fType%kRegrouped))
4255 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
4256 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
4257 ((element->GetFactor() == previous->GetFactor())
4258 && (element->GetXmin() == previous->GetXmin())
4259 && (element->GetXmax() == previous->GetXmax())
4260 )
4261 )
4264 // kWholeObject and kDoNotDelete do not apply to numerical elements.
4265 )
4266 {
4267 if (!previousOptimized) {
4268 // The element was not yet optimized we first need to copy it into
4269 // the set of original copies.
4270 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
4271 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
4272 }
4273 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
4274 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
4275
4276 R__ASSERT( keep < (fNslots - optiOut) );
4277
4278 if (fComp[keep].fLength == 0) {
4279 fComp[keep].fLength++;
4280 }
4281 fComp[keep].fLength++;
4282 fComp[keep].fType = element->GetType() + kRegrouped;
4283 isOptimized = kTRUE;
4284 previousOptimized = kTRUE;
4285 } else if (element->GetType() < 0) {
4286
4287 // -- Deal with an ignored TObject base class.
4288 // Note: The only allowed negative value here is -1,
4289 // and signifies that Build() has found a TObject
4290 // base class and TClass::IgnoreTObjectStreamer() was
4291 // called. In this case the compiled version of the
4292 // elements omits the TObject base class element,
4293 // which has to be compensated for by TTree::Bronch()
4294 // when it is making branches for a split object.
4295 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
4296 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
4297 keep = -1;
4298 previousOptimized = kFALSE;
4299
4300 } else {
4301 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
4302 if (fComp[fNdata].fNewType > 0) {
4303 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
4304 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
4305 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
4309 ) {
4311 } else if (fComp[fNdata].fType != kCounter) {
4312 fComp[fNdata].fType += kConv;
4313 }
4314 } else {
4315 if (fComp[fNdata].fType == kCounter) {
4316 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
4317 }
4318 fComp[fNdata].fType += kSkip;
4319 }
4320 }
4321 fCompOpt[fNdata] = &(fComp[fNdata]);
4323
4324 R__ASSERT( fNdata < (fNslots - optiOut) );
4325
4326 keep = fNdata;
4327 if (fComp[keep].fLength == 0) {
4328 fComp[keep].fLength = 1;
4329 }
4330 fNdata++;
4331 previousOptimized = kFALSE;
4332 }
4333 // The test 'fMethod[keep] == 0' fails to detect a variable size array
4334 // if the counter happens to have an offset of zero, so let's explicitly
4335 // prevent for here.
4336 if (element->HasCounter()) keep = -1;
4337 ++fNfulldata;
4338 previous = element;
4339 }
4340
4341 for (i = 0; i < fNdata; ++i) {
4342 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
4343 continue;
4344 }
4347 }
4348 for (i = 0; i < fNfulldata; ++i) {
4349 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
4350 continue;
4351 }
4356
4359 }
4360 ComputeSize();
4361
4362 fOptimized = isOptimized;
4363 SetIsCompiled();
4364
4365 if (gDebug > 0) {
4366 ls();
4367 }
4368}
4369
4370template <typename From>
4372{
4373 switch (newtype) {
4390 }
4391}
4392
4393template <typename Onfile>
4395{
4396 // When writing 'newtype' is the origin of the information (i.e. the in memory representation)
4397 // and the template parameter `To` is the representation on disk
4398 switch (newtype) {
4415 }
4416}
4417
4418////////////////////////////////////////////////////////////////////////////////
4419/// Add a read action for the given element.
4420
4422{
4423 TStreamerElement *element = compinfo->fElem;
4424
4425 if (element->TestBit(TStreamerElement::kWrite)) return;
4426
4427 switch (compinfo->fType) {
4428 // read basic types
4429 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4430 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4431 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4432 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4433 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4434 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4435 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4436 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4437 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4438 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4439 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4440 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4441 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4442 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4444 if (element->GetFactor() != 0) {
4445 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4446 } else {
4447 Int_t nbits = (Int_t)element->GetXmin();
4448 if (!nbits) nbits = 12;
4449 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
4450 }
4451 break;
4452 }
4454 if (element->GetFactor() != 0) {
4455 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4456 } else {
4457 Int_t nbits = (Int_t)element->GetXmin();
4458 if (!nbits) {
4459 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4460 } else {
4461 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
4462 }
4463 }
4464 break;
4465 }
4466 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4467 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4468 // Streamer alltogether.
4469 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4470 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4471 case TStreamerInfo::kSTL: {
4472 TClass *newClass = element->GetNewClass();
4473 TClass *oldClass = element->GetClassPointer();
4474 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4475
4476 if (element->GetArrayLength() <= 1) {
4477 if (fOldVersion<3){ // case of old TStreamerInfo
4478 if (newClass && newClass != oldClass) {
4479 if (element->GetStreamer()) {
4480 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4481 } else {
4482 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
4483 }
4484 } else {
4485 if (element->GetStreamer()) {
4486 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4487 } else {
4488 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
4489 }
4490 }
4491 } else {
4492 if (newClass && newClass != oldClass) {
4493 if (element->GetStreamer()) {
4494 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4495 } else if (oldClass) {
4496 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4497 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
4498 } else {
4499 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4500 case kVectorLooper:
4501 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
4502 break;
4503 case kAssociativeLooper:
4504 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
4505 break;
4506 case kVectorPtrLooper:
4507 case kGenericLooper:
4508 default:
4509 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4510 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
4511 break;
4512 }
4513 }
4514 }
4515 } else {
4516 if (element->GetStreamer()) {
4517 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4518 } else if (oldClass) {
4519 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4520 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
4521 } else {
4522 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
4523 case kVectorLooper:
4524 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4525 break;
4526 case kAssociativeLooper:
4527 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4528 break;
4529 case kVectorPtrLooper:
4530 case kGenericLooper:
4531 default:
4532 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4533 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4534 break;
4535 }
4536 }
4537 }
4538 }
4539 }
4540 } else {
4541 if (fOldVersion<3){ // case of old TStreamerInfo
4542 if (newClass && newClass != oldClass) {
4543 if (element->GetStreamer()) {
4544 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4545 } else {
4546 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4547 }
4548 } else {
4549 if (element->GetStreamer()) {
4550 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4551 } else {
4552 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4553 }
4554 }
4555 } else {
4556 if (newClass && newClass != oldClass) {
4557 if (element->GetStreamer()) {
4558 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4559 } else {
4560 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4561 }
4562 } else {
4563 if (element->GetStreamer()) {
4564 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4565 } else {
4566 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4567 }
4568 }
4569 }
4570 }
4571 break;
4572 }
4573
4575 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4576 break;
4578 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4579 break;
4581 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4582 break;
4584 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4585 break;
4587 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4588 break;
4590 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4591 break;
4593 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4594 break;
4596 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4597 break;
4599 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4600 break;
4602 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4603 break;
4605 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4606 break;
4608 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4609 break;
4611 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4612 break;
4614 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
4615 break;
4617 if (element->GetFactor() != 0) {
4618 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4619 } else {
4620 Int_t nbits = (Int_t)element->GetXmin();
4621 if (!nbits) nbits = 12;
4622 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
4623 }
4624 break;
4625 }
4627 if (element->GetFactor() != 0) {
4628 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4629 } else {
4630 Int_t nbits = (Int_t)element->GetXmin();
4631 if (!nbits) {
4632 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4633 } else {
4634 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
4635 }
4636 }
4637 break;
4638 }
4641 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4642 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<false>::Action,
4643 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4644 break;
4645 }
4647 if (compinfo->fStreamer)
4648 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4649 else {
4650 auto base = dynamic_cast<TStreamerBase*>(element);
4651 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4652 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4653
4654 if(!base || !memoryBaseCl ||
4655 memoryBaseCl->GetStreamer() ||
4656 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4657 {
4658 // Unusual Case.
4659 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
4660 }
4661 else
4662 readSequence->AddAction( ReadViaClassBuffer,
4663 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4664 }
4665 break;
4667 if (fOldVersion >= 3)
4668 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4669 else
4670 // Use the slower path for legacy files
4671 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
4672 break;
4674 if (compinfo->fStreamer)
4675 readSequence->AddAction( ReadViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
4676 else {
4677 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4678 readSequence->AddAction( ReadViaClassBuffer,
4679 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4680 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4681 readSequence->AddAction( ReadViaClassBuffer,
4682 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4683 else // Use the slower path for unusual cases
4684 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this, i, compinfo) );
4685 }
4686 break;
4687 default:
4688 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
4689 break;
4690 }
4691 if (element->TestBit(TStreamerElement::kCache)) {
4692 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
4693 readSequence->fActions.pop_back();
4694 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
4695 }
4696}
4697
4698////////////////////////////////////////////////////////////////////////////////
4699/// Add a read text action for the given element.
4700
4702{
4703 TStreamerElement *element = compinfo->fElem;
4704
4705 if (element->TestBit(TStreamerElement::kWrite))
4706 return;
4707
4708 Bool_t generic = kFALSE, isBase = kFALSE;
4709
4710 switch (compinfo->fType) {
4712 if (element->IsBase())
4713 isBase = kTRUE;
4714 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4715 else
4716 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4717 break;
4718
4720 if (element->IsBase())
4721 isBase = kTRUE;
4722 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
4723 else
4724 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4725 break;
4726
4727 case TStreamerInfo::kObject: // Class derived from TObject
4728 case TStreamerInfo::kAny: // Class NOT derived from TObject
4731 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4732 break;
4733
4734 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
4736 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
4737 readSequence->AddAction(TextReadSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4738 break;
4739
4742 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4743 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<true>::Action,
4744 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4745 break;
4746 }
4747 case TStreamerInfo::kBase: isBase = kTRUE; break;
4748
4750 readSequence->AddAction(ReadStreamerCase, new TGenericConfiguration(this, i, compinfo));
4751 break;
4752
4753 default: generic = kTRUE; break;
4754 }
4755
4756 if (isBase) {
4757 if (compinfo->fStreamer) {
4758 readSequence->AddAction(ReadStreamerCase, new TGenericConfiguration(this, i, compinfo));
4759 } else {
4760 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
4761 }
4762 } else if (generic)
4763 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
4764}
4765
4766////////////////////////////////////////////////////////////////////////////////
4767/// Add a read action for the given element.
4768/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
4769
4771{
4772 TStreamerElement *element = compinfo->fElem;
4773
4774 if (element->TestBit(TStreamerElement::kWrite)) return;
4775
4776 if (element->TestBit(TStreamerElement::kCache)) {
4777 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,nullptr,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
4778 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
4779 } else {
4780 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,nullptr,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
4781 }
4782}
4783
4784////////////////////////////////////////////////////////////////////////////////
4785
4787{
4788 TStreamerElement *element = compinfo->fElem;
4790 // Skip element cached for reading purposes.
4791 return;
4792 }
4793 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
4794 // Skip artificial element used for reading purposes.
4795 return;
4796 }
4797 switch (compinfo->fType) {
4798 // write basic types
4799 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4800 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4801 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4802 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4803 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4804 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4805 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4806 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4807 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4808 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4809 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4810 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4811 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4812
4814 AddWriteConvertAction<Char_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4815 break;
4817 AddWriteConvertAction<Short_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4818 break;
4820 AddWriteConvertAction<Int_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4821 break;
4823 AddWriteConvertAction<Long_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4824 break;
4826 AddWriteConvertAction<Long64_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4827 break;
4829 AddWriteConvertAction<UChar_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4830 break;
4832 AddWriteConvertAction<UShort_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4833 break;
4835 AddWriteConvertAction<UInt_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4836 break;
4838 AddWriteConvertAction<ULong_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4839 break;
4841 AddWriteConvertAction<ULong64_t>(writeSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4842 break;
4843
4844 case kSTL:
4845 {
4846 TClass *newClass = element->GetNewClass();
4847 TClass *onfileClass = element->GetClassPointer();
4848 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4849
4850 if (element->GetArrayLength() <= 1) {
4851 if (newClass && newClass != onfileClass) {
4852 if (element->GetStreamer()) {
4853 writeSequence->AddAction(WriteSTL<WriteSTLMemberWise /* should be ChangedClass */, WriteSTLObjectWiseStreamer>,
4854 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4855 newClass, element->GetStreamer(), element->GetTypeName(),
4856 isSTLbase));
4857 } else if (onfileClass) {
4858 if (onfileClass->GetCollectionProxy() == 0 || onfileClass->GetCollectionProxy()->GetValueClass() ||
4859 onfileClass->GetCollectionProxy()->HasPointers()) {
4860 writeSequence->AddAction(
4861 WriteSTL<WriteSTLObjectWiseStreamer /* should be ChangedClass */, WriteSTLObjectWiseFastArray>,
4862 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4863 element->GetTypeName(), isSTLbase));
4864 } else {
4865 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4866 case kVectorLooper:
4867 writeSequence->AddAction(GetConvertCollectionWriteAction<VectorLooper>(
4868 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4869 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4870 element->GetTypeName(), isSTLbase)));
4871 break;
4872 case kAssociativeLooper:
4873 writeSequence->AddAction(GetConvertCollectionWriteAction<AssociativeLooper>(
4874 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4875 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4876 element->GetTypeName(), isSTLbase)));
4877 break;
4878 case kVectorPtrLooper:
4879 case kGenericLooper:
4880 default:
4881 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4882 // real thing.
4883 writeSequence->AddAction(GetConvertCollectionWriteAction<GenericLooper>(
4884 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4885 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4886 element->GetTypeName(), isSTLbase)));
4887 break;
4888 }
4889 }
4890 }
4891 } else {
4892 if (element->GetStreamer()) {
4893 writeSequence->AddAction(WriteSTL<WriteSTLMemberWise, WriteSTLObjectWiseStreamer>,
4894 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4895 element->GetStreamer(), element->GetTypeName(),
4896 isSTLbase));
4897 } else if (onfileClass) {
4898 if (onfileClass->GetCollectionProxy() == 0 ||
4899 onfileClass->GetCollectionProxy()->GetValueClass() ||
4900 onfileClass->GetCollectionProxy()->HasPointers()) {
4901 writeSequence->AddAction(WriteSTL<WriteSTLMemberWise, WriteSTLObjectWiseFastArray>,
4902 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4903 element->GetTypeName(), isSTLbase));
4904 } else {
4905 switch (SelectLooper(*onfileClass->GetCollectionProxy())) {
4906 case kVectorLooper:
4907 writeSequence->AddAction(GetNumericCollectionWriteAction<VectorLooper>(
4908 onfileClass->GetCollectionProxy()->GetType(),
4909 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4910 isSTLbase)));
4911 break;
4912 case kAssociativeLooper:
4913 writeSequence->AddAction(GetNumericCollectionWriteAction<AssociativeLooper>(
4914 onfileClass->GetCollectionProxy()->GetType(),
4915 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4916 isSTLbase)));
4917 break;
4918 case kVectorPtrLooper:
4919 case kGenericLooper:
4920 default:
4921 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4922 // real thing.
4923 writeSequence->AddAction(GetNumericCollectionWriteAction<GenericLooper>(
4924 onfileClass->GetCollectionProxy()->GetType(),
4925 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4926 isSTLbase)));
4927 break;
4928 }
4929 }
4930 }
4931 }
4932 } else {
4933 if (newClass && newClass != onfileClass) {
4934 if (element->GetStreamer()) {
4935 writeSequence->AddAction(
4936 WriteSTL<WriteArraySTLMemberWise /* should be ChangedClass */, WriteSTLObjectWiseStreamer>,
4937 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4938 newClass, element->GetStreamer(), element->GetTypeName(), isSTLbase));
4939 } else {
4940 writeSequence->AddAction(
4941 WriteSTL<WriteArraySTLMemberWise /* should be ChangedClass */, WriteSTLObjectWiseFastArray>,
4942 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4943 newClass, element->GetTypeName(), isSTLbase));
4944 }
4945 } else {
4946 if (element->GetStreamer()) {
4947 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWise, WriteSTLObjectWiseStreamer>,
4948 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4949 element->GetArrayLength(), onfileClass,
4950 element->GetStreamer(), element->GetTypeName(), isSTLbase));
4951 } else {
4952 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWise, WriteSTLObjectWiseFastArray>,
4953 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4954 element->GetArrayLength(), onfileClass,
4955 element->GetTypeName(), isSTLbase));
4956 }
4957 }
4958 }
4959 break;
4960 }
4961
4962 case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4963 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4964 // Streamer alltogether.
4965 case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4966 case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4967
4970 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4971 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<false>::Action,
4972 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4973 break;
4974 }
4976 if (compinfo->fStreamer)
4977 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4978 else {
4979 auto base = dynamic_cast<TStreamerBase*>(element);
4980 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4981 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4982
4983 if(!base || !memoryBaseCl ||
4984 memoryBaseCl->GetStreamer() ||
4985 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4986 {
4987 // Unusual Case.
4988 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
4989 }
4990 else {
4991 writeSequence->AddAction( WriteViaClassBuffer,
4992 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4993 }
4994 }
4995 break;
4997 if (fOldVersion >= 3)
4998 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4999 else
5000 // Use the slower path for legacy files
5001 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
5002 break;
5004 if (compinfo->fStreamer)
5005 writeSequence->AddAction( WriteViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
5006 else {
5007 if (compinfo->fNewClass && compinfo->fNewClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5008 writeSequence->AddAction( WriteViaClassBuffer,
5009 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
5010 else if (compinfo->fClass && compinfo->fClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5011 writeSequence->AddAction( WriteViaClassBuffer,
5012 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
5013 else // Use the slower path for unusual cases
5014 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this, i, compinfo) );
5015 }
5016 break;
5017
5018 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
5019 /*case TStreamerInfo::kFloat16: {
5020 if (element->GetFactor() != 0) {
5021 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5022 } else {
5023 Int_t nbits = (Int_t)element->GetXmin();
5024 if (!nbits) nbits = 12;
5025 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5026 }
5027 break;
5028 } */
5029 /*case TStreamerInfo::kDouble32: {
5030 if (element->GetFactor() != 0) {
5031 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5032 } else {
5033 Int_t nbits = (Int_t)element->GetXmin();
5034 if (!nbits) {
5035 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
5036 } else {
5037 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5038 }
5039 }
5040 break;
5041 } */
5042 default:
5043 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
5044 break;
5045 }
5046}
5047
5048////////////////////////////////////////////////////////////////////////////////
5049
5051{
5052 TStreamerElement *element = compinfo->fElem;
5054 // Skip element cached for reading purposes.
5055 return;
5056 }
5057 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5058 // Skip artificial element used for reading purposes.
5059 return;
5060 }
5061
5062 Bool_t generic = kFALSE, isBase = kFALSE;
5063
5064 switch (compinfo->fType) {
5065 // write basic types
5091 // Actually same action for this level
5092 AddWriteAction(writeSequence, i, compinfo);
5093 break;
5094
5096 if (element->IsBase())
5097 isBase = kTRUE;
5098 else
5099 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5100 break;
5101
5103 if (element->IsBase())
5104 isBase = kTRUE;
5105 else
5106 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5107 break;
5108
5109 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
5111 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
5112 writeSequence->AddAction(TextWriteSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5113 break;
5114
5117 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
5118 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<true>::Action, new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
5119 break;
5120 }
5121 case TStreamerInfo::kBase: isBase = kTRUE; break;
5122
5124 writeSequence->AddAction(WriteStreamerCase, new TGenericConfiguration(this, i, compinfo));
5125 break;
5126
5127 default: generic = kTRUE; break;
5128 }
5129
5130 if (isBase) {
5131 if (compinfo->fStreamer) {
5132 writeSequence->AddAction(WriteStreamerCase, new TGenericConfiguration(this, i, compinfo));
5133 } else {
5134 writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
5135 }
5136
5137 } else
5138
5139 // use generic write action when special handling is not provided
5140 if (generic)
5141 writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
5142}
5143
5144////////////////////////////////////////////////////////////////////////////////
5145/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
5146
5148{
5149 TStreamerElement *element = compinfo->fElem;
5151 // Skip element cached for reading purposes.
5152 return;
5153 }
5154 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5155 // Skip artificial element used for reading purposes.
5156 return;
5157 }
5158 writeSequence->AddAction( GetCollectionWriteAction<VectorPtrLooper>(this,nullptr,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
5159}
5160
5161////////////////////////////////////////////////////////////////////////////////
5162/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5163
5165{
5166 if (info == 0) {
5168 }
5169
5170 TLoopConfiguration *loopConfig = nullptr;
5171 if (IsDefaultVector(proxy))
5172 {
5173 if (proxy.HasPointers()) {
5174 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5175 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5176 return sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
5177 }
5178
5179 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5180 Long_t increment = proxy.GetIncrement();
5181 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
5186 {
5187 Long_t increment = proxy.GetIncrement();
5188 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
5189 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
5190 } else {
5191 loopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
5192 }
5193
5194 return CreateReadMemberWiseActions(*info, loopConfig);
5195}
5196
5197////////////////////////////////////////////////////////////////////////////////
5198/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5199
5201{
5202 UInt_t ndata = info.GetElements()->GetEntriesFast();
5204 sequence->fLoopConfig = loopConfig;
5205
5206 for (UInt_t i = 0; i < ndata; ++i) {
5207 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5208 if (!element) {
5209 break;
5210 }
5211 if (element->GetType() < 0) {
5212 // -- Skip an ignored TObject base class.
5213 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5214 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5215 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5216 // when it is making branches for a split object.
5217 continue;
5218 }
5219 if (element->TestBit(TStreamerElement::kWrite)) {
5220 // Skip element that only for writing.
5221 continue;
5222 }
5223 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
5224 if (baseEl) {
5225 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
5226 // There was a problem with the checksum, the user likely did not
5227 // increment the version number of the derived class when the
5228 // base class changed. Since we will be member wise streaming
5229 // this class, let's warn the user that something is wrong.
5230 ::Warning("CreateReadMemberWiseActions","%s",
5231 baseEl->GetErrorMessage());
5233 }
5234 }
5235
5236 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5237 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
5238
5239 Int_t oldType = element->GetType();
5240 Int_t newType = element->GetNewType();
5241
5242 Int_t offset = element->GetOffset();
5243 if (newType != oldType) {
5244 // This 'prevents' the switch from base class (kBase (0)) to
5245 // anything else.
5246 if (newType > 0) {
5247 if (oldType != TVirtualStreamerInfo::kCounter) {
5248 oldType += TVirtualStreamerInfo::kConv;
5249 }
5250 } else {
5251 oldType += TVirtualStreamerInfo::kSkip;
5252 }
5253 }
5254 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5255 case kAssociativeLooper:
5256// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
5257// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
5258// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(true, info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
5259 case kVectorLooper:
5260 case kVectorPtrLooper:
5261 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5262 if (element->TestBit(TStreamerElement::kCache)) {
5263 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(&info,loopConfig,element,oldType,i,compinfo,offset) );
5265 } else {
5266 sequence->AddAction( GetCollectionReadAction<VectorLooper>(&info,loopConfig,element,oldType,i,compinfo,offset));
5267 }
5268 break;
5269 case kGenericLooper:
5270 default:
5271 // The usual collection case.
5272 if (element->TestBit(TStreamerElement::kCache)) {
5273 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(&info,loopConfig,element,oldType,i,compinfo,offset) );
5275 } else {
5276 sequence->AddAction( GetCollectionReadAction<GenericLooper>(&info,loopConfig,element,oldType,i,compinfo,offset) );
5277 }
5278 break;
5279 }
5280 }
5281 return sequence;
5282}
5283
5284////////////////////////////////////////////////////////////////////////////////
5285/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5286
5288{
5289 if (info == 0) {
5291 }
5292
5293 TLoopConfiguration *loopConfig = nullptr;
5294 if (IsDefaultVector(proxy))
5295 {
5296 if (proxy.HasPointers()) {
5297 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5298 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5299 return sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
5300 }
5301
5302 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5303 Long_t increment = proxy.GetIncrement();
5304 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
5305 } else {
5306 loopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
5307 }
5308 return CreateWriteMemberWiseActions(*info, loopConfig);
5309}
5310
5311////////////////////////////////////////////////////////////////////////////////
5312/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5313
5315{
5316 UInt_t ndata = info.GetElements()->GetEntriesFast();
5318 sequence->fLoopConfig = loopConfig;
5319
5320 for (UInt_t i = 0; i < ndata; ++i) {
5321 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5322 if (!element) {
5323 break;
5324 }
5325 if (element->GetType() < 0) {
5326 // -- Skip an ignored TObject base class.
5327 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5328 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5329 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5330 // when it is making branches for a split object.
5331 continue;
5332 }
5334 // Skip element cached for reading purposes.
5335 continue;
5336 }
5338 // Skip artificial element used for reading purposes.
5339 continue;
5340 }
5341 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5342 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
5343 Int_t onfileType = element->GetType();
5344 Int_t memoryType = element->GetNewType();
5345 if (memoryType != onfileType) {
5346 // This 'prevents' the switch from base class (kBase (0)) to
5347 // anything else.
5348 if (memoryType > 0) {
5349 if (onfileType != TVirtualStreamerInfo::kCounter) {
5350 onfileType += TVirtualStreamerInfo::kConv;
5351 }
5352 } else {
5353 // When reading we need to consume the data in the onfile buffer,
5354 // so we do create a 'Skip' action for the missing elements.
5355 // When writing we should probably write a default value, for
5356 // now let's just ignore the request.
5357 // We could issue an error here but we might too often issue a
5358 // 'false positive' if the user only reads.
5359 // FIXME: The 'right' solution is to add a new action that first print
5360 // once the following error message:
5361 //
5362 // info.Error("TActionSequence::CreateWriteMemberWiseActions",
5363 // "Ignoring request to write the missing data member %s in %s version %d checksum 0x%x",
5364 // element->GetName(), info.GetName(), info.GetClassVersion(), info.GetCheckSum());
5365 continue;
5366 //
5367 // Instead of skipping the field we could write a zero there with:
5368 // onfileType += TVirtualStreamerInfo::kSkip;
5369 }
5370 }
5371
5372 Int_t offset = element->GetOffset();
5373 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5374 case kAssociativeLooper:
5375 sequence->AddAction( GetCollectionWriteAction<GenericLooper>(&info,loopConfig,element,onfileType,i,compinfo,offset) );
5376 break;
5377 case kVectorLooper:
5378 sequence->AddAction( GetCollectionWriteAction<VectorLooper>(&info,loopConfig,element,onfileType,i,compinfo,offset) );
5379 break;
5380 case kVectorPtrLooper:
5381 sequence->AddAction( GetCollectionWriteAction<VectorPtrLooper>(&info,loopConfig,element,onfileType,i,compinfo,offset) );
5382 break;
5383 case kGenericLooper:
5384 default:
5385 sequence->AddAction( GetCollectionWriteAction<GenericLooper>(&info,loopConfig,element,onfileType,i,compinfo,offset) );
5386 break;
5387 }
5388 }
5389 return sequence;
5390}
5391
5393{
5394 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5395 // TBranchElement in the case of split sub-object.
5396
5397 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5398 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5399 iter != end;
5400 ++iter)
5401 {
5402 // (fElemId == -1) indications that the action is a Push or Pop DataCache.
5403 if (iter->fConfiguration->fElemId != (UInt_t)-1 &&
5404 !iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5405 iter->fConfiguration->AddToOffset(delta);
5406 }
5407}
5408
5410{
5411 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5412 // TBranchElement in the case of split sub-object.
5413
5414 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5415 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5416 iter != end;
5417 ++iter)
5418 {
5419 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5420 iter->fConfiguration->SetMissing();
5421 }
5422}
5423
5425{
5426 // Create a copy of this sequence.
5427
5428 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, fActions.size(), IsForVectorPtrLooper());
5429
5430 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5431
5432 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5433 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5434 iter != end;
5435 ++iter)
5436 {
5437 TConfiguration *conf = iter->fConfiguration->Copy();
5438 sequence->AddAction( iter->fAction, conf );
5439 }
5440 return sequence;
5441}
5442
5444 const TStreamerInfoActions::TIDs &element_ids,
5445 Int_t offset,
5447{
5448 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5449 if ( element_ids[id].fElemID < 0 ) {
5450 if (element_ids[id].fNestedIDs) {
5451 auto original = create(element_ids[id].fNestedIDs->fInfo,
5452 sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
5453 nullptr);
5454 if (element_ids[id].fNestedIDs->fOnfileObject) {
5455 auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
5456 if ( sequence->fLoopConfig )
5457 sequence->AddAction( PushDataCacheGenericCollection, conf );
5458 else if ( sequence->IsForVectorPtrLooper() )
5459 sequence->AddAction( PushDataCacheVectorPtr, conf );
5460 else
5461 sequence->AddAction( PushDataCache, conf );
5462 }
5463
5464 original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
5465
5466 if (element_ids[id].fNestedIDs->fOnfileObject) {
5467 auto conf =
5468 new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset);
5469 if ( sequence->fLoopConfig )
5470 sequence->AddAction( PopDataCacheGenericCollection, conf );
5471 else if ( sequence->IsForVectorPtrLooper() )
5472 sequence->AddAction( PopDataCacheVectorPtr, conf );
5473 else
5474 sequence->AddAction( PopDataCache, conf );
5475 }
5476 } else {
5477 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5478 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5479 iter != end;
5480 ++iter)
5481 {
5482 TConfiguration *conf = iter->fConfiguration->Copy();
5483 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5484 conf->AddToOffset(offset);
5485 sequence->AddAction( iter->fAction, conf );
5486 }
5487 }
5488 } else {
5489 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5490 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5491 iter != end;
5492 ++iter) {
5493 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
5494 TConfiguration *conf = iter->fConfiguration->Copy();
5495 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5496 conf->AddToOffset(offset);
5497 sequence->AddAction( iter->fAction, conf );
5498 }
5499 }
5500 }
5501 }
5502}
5503
5506{
5507 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5508 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5509
5510 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5511
5512 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5513
5514 AddToSubSequence(sequence, element_ids, offset, create);
5515
5516 return sequence;
5517}
5518
5520{
5521 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5522 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5523
5524 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5525
5526 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5527
5528 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5529 if ( element_ids[id] < 0 ) {
5530 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5531 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5532 iter != end;
5533 ++iter)
5534 {
5535 TConfiguration *conf = iter->fConfiguration->Copy();
5536 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5537 conf->AddToOffset(offset);
5538 sequence->AddAction( iter->fAction, conf );
5539 }
5540 } else {
5541 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5542 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5543 iter != end;
5544 ++iter) {
5545 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
5546 TConfiguration *conf = iter->fConfiguration->Copy();
5547 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5548 conf->AddToOffset(offset);
5549 sequence->AddAction( iter->fAction, conf );
5550 }
5551 }
5552 }
5553 }
5554 return sequence;
5555}
5556
5557#if !defined(R__WIN32) && !defined(_AIX)
5558
5559#include <dlfcn.h>
5560
5561#endif
5562
5563typedef void (*voidfunc)();
5564static const char *R__GetSymbolName(voidfunc func)
5565{
5566#if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
5567 return "not available on this platform";
5568#if 0
5569 MEMORY_BASIC_INFORMATION mbi;
5570 if (!VirtualQuery (func, &mbi, sizeof (mbi)))
5571 {
5572 return 0;
5573 }
5574
5575 HMODULE hMod = (HMODULE) mbi.AllocationBase;
5576 static char moduleName[MAX_PATH];
5577
5578 if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
5579 {
5580 return 0;
5581 }
5582 return moduleName;
5583#endif
5584#else
5585 Dl_info info;
5586 if (dladdr((void*)func,&info)==0) {
5587 // Not in a known share library, let's give up
5588 return "name not found";
5589 } else {
5590 //fprintf(stdout,"Found address in %s\n",info.dli_fname);
5591 return info.dli_sname;
5592 }
5593#endif
5594}
5595
5597{
5598 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5599 // TTBranchElement in the case of split sub-object.
5600 // If opt contains 'func', also print the (mangled) name of the function that will be executed.
5601
5602 if (fLoopConfig) {
5603 fLoopConfig->Print();
5604 }
5605 TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
5606 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
5607 iter != end;
5608 ++iter)
5609 {
5610 iter->fConfiguration->Print();
5611 if (strstr(opt,"func")) {
5612 printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
5613 }
5614 }
5615}
5616
5617
#define b(i)
Definition RSha256.hxx:100
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
constexpr Int_t kMaxInt
Definition RtypesCore.h:105
short Version_t
Definition RtypesCore.h:65
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:244
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
float xmin
R__EXTERN TVirtualMutex * gInterpreterMutex
@ kIsReferenced
Definition TObject.h:370
Int_t gDebug
Definition TROOT.cxx:597
#define gROOT
Definition TROOT.h:406
static TConfiguredAction GetNumericCollectionReadAction(Int_t type, TConfigSTL *conf)
static TConfiguredAction GetNumericCollectionWriteAction(Int_t type, TConfigSTL *conf)
void(* voidfunc)()
static void AddWriteConvertAction(TStreamerInfoActions::TActionSequence *sequence, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionWriteConvertAction(Int_t newtype, TConfiguration *conf)
static void AddReadConvertAction(TStreamerInfoActions::TActionSequence *sequence, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionReadConvertAction(Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionReadAction(TVirtualStreamerInfo *info, TLoopConfiguration *loopConfig, TStreamerElement *element, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
static const Int_t kRegrouped
#define INLINE_TEMPLATE_ARGS
static const char * R__GetSymbolName(voidfunc func)
static TConfiguredAction GetCollectionWriteAction(TVirtualStreamerInfo *info, TLoopConfiguration *loopConfig, TStreamerElement *element, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
static TConfiguredAction GetConvertCollectionReadAction(Int_t oldtype, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetConvertCollectionWriteAction(Int_t onfileType, Int_t memoryType, TConfiguration *conf)
static TConfiguredAction GetConvertCollectionReadActionFrom(Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetConvertCollectionWriteActionFrom(Int_t onfileType, TConfiguration *conf)
#define ReadBasicType(name)
#define WriteBasicType(name)
void ReadBuffer(char *&buffer) override
#define R__LOCKGUARD(mutex)
@ kStreamedMemberWise
Definition TBufferFile.h:69
Base class for text-based streamers like TBufferJSON or TBufferXML Special actions list will use meth...
Definition TBufferText.h:20
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual void ReadWithNbits(Float_t *ptr, Int_t nbits)=0
virtual void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue)=0
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)=0
virtual Version_t ReadVersionForMemberWise(const TClass *cl=nullptr)=0
virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=nullptr)=0
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition TBuffer.cxx:344
virtual UInt_t WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual void ReadInt(Int_t &i)=0
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition TBuffer.cxx:262
virtual void WriteFloat16(Float_t *f, TStreamerElement *ele=nullptr)=0
virtual UShort_t GetPidOffset() const =0
@ kCannotHandleMemberWiseStreaming
Definition TBuffer.h:76
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=nullptr)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)=0
virtual void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits)=0
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
virtual void WriteFastArrayFloat16(const Float_t *f, Long64_t n, TStreamerElement *ele=nullptr)=0
virtual void WriteFastArray(const Bool_t *b, Long64_t n)=0
virtual void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue)=0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void WriteInt(Int_t i)=0
virtual void WriteFastArrayDouble32(const Double_t *d, Long64_t n, TStreamerElement *ele=nullptr)=0
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=nullptr)=0
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Int_t Length() const
Definition TBuffer.h:100
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=nullptr)=0
TClassRef is used to implement a permanent reference to a TClass object.
Definition TClassRef.h:28
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:608
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2388
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:5274
EState GetState() const
Definition TClass.h:489
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5059
Bool_t HasCustomStreamerMember() const
The class has a Streamer method and it is implemented by the user or an older (not StreamerInfo based...
Definition TClass.h:509
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5785
Bool_t HasDirectStreamerInfoUse() const
Definition TClass.h:409
static void StreamerStreamerInfo(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of where we should directly use the StreamerInfo.
Definition TClass.cxx:6939
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5610
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4668
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2966
std::atomic< StreamerImpl_t > fStreamerImpl
Definition TClass.h:287
@ kEmulated
Definition TClass.h:125
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
Int_t GetVersion() const
Definition TFile.h:245
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
static TClass * Class()
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:474
@ kIsOnHeap
object is on heap
Definition TObject.h:81
@ kNotDeleted
object has not been deleted
Definition TObject.h:82
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:991
static TClass * Class()
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:809
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
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...
TVirtualStreamerInfo * GetBaseStreamerInfo() const
TClass * GetClassPointer() const override
Returns a pointer to the TClass of this element.
const char * GetErrorMessage() const
static TClass * Class()
Int_t GetNewType() const
virtual Int_t GetSize() const
Returns size of this element in bytes.
Int_t GetType() const
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual ULongptr_t GetMethod() const
Int_t GetArrayDim() const
TMemberStreamer * GetStreamer() const
Return the local streamer object.
Double_t GetXmax() const
TClass * GetNewClass() const
Int_t GetArrayLength() const
Double_t GetFactor() const
const char * GetTypeName() const
TClass * IsA() const override
Double_t GetXmin() const
Int_t GetOffset() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
virtual Bool_t HasCounter() const
void GetSequenceType(TString &type) const
Fill type with the string representation of sequence information including 'cached',...
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
void Print(Option_t *="") const override
This method must be overridden when a class wants to print itself.
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) SequenceGetter_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)
void AddAction(action_t action, TConfiguration *conf)
TLoopConfiguration * Copy() const override
TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t)
void * GetFirstAddress(void *start, const void *) const override
TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits)
TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits)
TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin)
TConfWithFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Double_t factor, Double_t xmin)
TConfigSTL(Bool_t read, TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase)
TConfigSTL(Bool_t read, 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)
TConfigSTL(Bool_t read, 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)
TVirtualCollectionProxy::CreateIterators_t fCreateIterators
TVirtualCollectionProxy::DeleteIterator_t fDeleteIterator
TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators
TVirtualCollectionProxy::Next_t fNext
TConfigSTL(Bool_t read, 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)
TVirtualCollectionProxy::CopyIterator_t fCopyIterator
TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset)
void PrintDebug(TBuffer &buffer, void *object) const override
void PrintDebug(TBuffer &b, void *addr) const override
TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat)
Base class of the Configurations.
virtual void PrintDebug(TBuffer &buffer, void *object) const
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
Int_t fOffset
Offset within the object.
TCompInfo_t * fCompInfo
Access to compiled information (for legacy code)
UInt_t fLength
Number of element in a fixed length array.
UInt_t fElemId
Identifier of the TStreamerElement.
void PrintDebug(TBuffer &buffer, void *object) const
TLoopConfiguration * Copy() const override
void * GetFirstAddress(void *start_collection, const void *end_collection) const override
TVirtualCollectionProxy::CopyIterator_t fCopyIterator
TVirtualCollectionProxy::DeleteIterator_t fDeleteIterator
TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read)
Base class of the Configurations for the member wise looping routines.
virtual TVirtualCollectionProxy * GetCollectionProxy() const
virtual TLoopConfiguration * Copy() const =0
TLoopConfiguration * Copy() const override
void * GetFirstAddress(void *start, const void *) const override
TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t)
TClass * fClass
Not Owned.
TMemberStreamer * fStreamer
Not Owned.
TStreamerElement * fElem
Not Owned.
TClass * fNewClass
Not Owned.
Describes a persistent version of a class.
Int_t fNVirtualInfoLoc
! Number of virtual info location to update.
Int_t ReadBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t eoffset, Bool_t v7=kTRUE)
The STL vector/list is deserialized from the buffer b.
void AddWriteAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
Int_t fNfulldata
!number of elements
TCompInfo * fComp
![fNslots with less than fElements->GetEntries()*1.5 used] Compiled info
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions(Bool_t forCollection)
TStreamerInfoActions::TActionSequence * fWriteMemberWiseVecPtr
! List of write action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fReadText
! List of text read action resulting from the compilation, used for JSON.
void ls(Option_t *option="") const override
List the TStreamerElement list and also the precomputed tables if option contains the string "incOrig...
void AddReadTextAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read text action for the given element.
TCompInfo ** fCompFull
![fElements->GetEntries()]
TObjArray * fElements
Array of TStreamerElements.
void AddReadMemberWiseVecPtrAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
Int_t fNdata
!number of optimized elements
TStreamerInfoActions::TActionSequence * fReadMemberWiseVecPtr
! List of read action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fReadObjectWise
! List of read action resulting from the compilation.
TClass * fClass
!pointer to class
TCompInfo ** fCompOpt
![fNdata]
TClass * GetClass() const override
static std::atomic< Int_t > fgCount
Number of TStreamerInfo instances.
void AddWriteTextAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
void ComputeSize()
Compute total size of all persistent elements of the class.
void AddReadAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
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).
Int_t fNumber
!Unique identifier
TStreamerInfoActions::TActionSequence * fWriteObjectWise
! List of write action resulting from the compilation.
Int_t fSize
!size of the persistent class
void Compile() override
loop on the TStreamerElement list regroup members with same type Store predigested information into l...
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.
TStreamerInfoActions::TActionSequence * fWriteMemberWise
! List of write action resulting from the compilation for use in member wise streaming.
Int_t fNslots
!total number of slots in fComp.
Version_t fOldVersion
! Version of the TStreamerInfo object read from the file
TStreamerInfoActions::TActionSequence * fWriteText
! List of text write action resulting for the compilation, used for JSON.
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Bool_t forCollection)
Basic string class.
Definition TString.h:139
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:376
@ kTrailing
Definition TString.h:276
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
TClassRef fClass
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual Int_t GetProperties() const
Return miscallenous properties of the proxy (see TVirtualCollectionProxy::EProperty)
virtual ULong_t GetIncrement() const =0
Return the offset between two consecutive in-memory values (which depends on the sizeof() and alignme...
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
*begin_arena and *end_arena should contain the location of a memory arena of size fgIteratorArenaSize...
virtual EDataType GetType() const =0
If the value type is a fundamental data type, return its type (see enumeration EDataType).
@ kCustomAlloc
The collection has a custom allocator.
void *(* CopyIterator_t)(void *dest, const void *source)
Copy the iterator source into dest.
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()=0
void *(* Next_t)(void *iter, const void *end)
iter and end should be pointers to an iterator to be incremented and an iterator that points to the e...
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual void Commit(void *)=0
Commits pending elements in a staging area (see Allocate() for more information).
virtual Int_t GetCollectionType() const =0
Return the type of the proxied collection (see enumeration TClassEdit::ESTLType)
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
Return a pointer to a function that can advance an iterator (see Next_t).
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual UInt_t Size() const =0
Return the current number of elements in the container.
void(* DeleteTwoIterators_t)(void *begin, void *end)
void(* DeleteIterator_t)(void *iter)
If the size of the iterator is greater than fgIteratorArenaSize, call delete on the addresses; otherw...
static const Int_t fgIteratorArenaSize
The size of a small buffer that can be allocated on the stack to store iterator-specific information.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Return a pointer to a function that can create an iterator pair, where each iterator points to the be...
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
Allocates space for storing at least n elements.
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)=0
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)=0
Return a pointer to a function that can delete an iterator (pair) (see DeleteIterator_t).
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)=0
Return a pointer to a function that can copy an iterator (see CopyIterator_t).
virtual Bool_t HasPointers() const =0
Return true if the content is of type 'pointer to'.
virtual TClass * GetCollectionClass() const
Return a pointer to the TClass representing the proxied container class.
static void * Next(void *iter, const void *end)
static void * CopyIterator(void *dest, const void *source)
Abstract Interface class describing Streamer information for one class.
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible.
@ kUChar
Equal to TDataType's kchar.
TClass * IsA() const override
static Bool_t CanOptimize()
static function returning true if optimization can be on
virtual TObjArray * GetElements() const =0
virtual Version_t GetOldVersion() const =0
virtual Int_t GetClassVersion() const =0
struct void * fTypeName
Definition cppyy.h:9
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
@ kSTLbitset
Definition ESTLType.h:37
@ kSTLmap
Definition ESTLType.h:33
@ kSTLunorderedmultiset
Definition ESTLType.h:43
@ kSTLset
Definition ESTLType.h:35
@ kSTLmultiset
Definition ESTLType.h:36
@ kSTLvector
Definition ESTLType.h:30
@ kSTLunorderedmultimap
Definition ESTLType.h:45
@ kSTLunorderedset
Definition ESTLType.h:42
@ kSTLunorderedmap
Definition ESTLType.h:44
@ kSTLmultimap
Definition ESTLType.h:34
void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
Int_t WriteTString(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
Int_t PopDataCache(TBuffer &b, void *, const TConfiguration *)
void ReadSTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t TextReadSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
void ReadSTLObjectWiseFastArrayV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
Int_t ReadBasicType< BitsMarker >(TBuffer &buf, void *addr, const TConfiguration *config)
static void WriteCompressed(TBuffer &buf, float *addr, const TStreamerElement *elem)
Int_t WriteTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t WriteTObject(TBuffer &buf, void *addr, const TConfiguration *config)
void ReadArraySTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t WriteTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t WriteTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t ReadBasicType_WithFactor(TBuffer &buf, void *addr, const TConfiguration *config)
void WriteSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t ReadTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
void WriteSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t WriteSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t ReadTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
Int_t UseCache(TBuffer &b, void *addr, const TConfiguration *conf)
Int_t WriteViaClassBuffer(TBuffer &buf, void *addr, const TConfiguration *config)
std::vector< TIDNode > TIDs
Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
void ReadSTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t WriteTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t ReadTextObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t TextWriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
Int_t ReadViaExtStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t ReadTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
void WriteArraySTLMemberWise(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t WriteStreamerCase(TBuffer &buf, void *addr, const TConfiguration *config)
void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t ReadBasicType_NoFactor(TBuffer &buf, void *addr, const TConfiguration *config)
bool IsDefaultVector(TVirtualCollectionProxy &proxy)
Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
Int_t ReadTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t WriteViaExtStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
void ReadSTLObjectWiseStreamerV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
void ReadArraySTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PopDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *, const TConfiguration *)
Int_t ReadStreamerCase(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
Int_t ReadTextTObjectBase(TBuffer &buf, void *addr, const TConfiguration *config)
ESelectLooper SelectLooper(TVirtualCollectionProxy &proxy)
Int_t ReadTString(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
void WriteSTLMemberWise(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteBasicZero(TBuffer &buf, void *, const TConfiguration *)
Int_t ReadViaClassBuffer(TBuffer &buf, void *addr, const TConfiguration *config)
TVirtualCollectionProxy::Next_t Next_t
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
static void Action(TBuffer &buf, void *addr, Int_t nvalues)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
static void LoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t, const TStreamerElement *elem)
static void SimpleWriteFloat16(TBuffer &buf, void *addr, const TStreamerElement *elem)
static Int_t WriteCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
static void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
static void ArrayWrite(TBuffer &buf, void *addr, Int_t nvalues, const TStreamerElement *)
static Int_t WriteCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
static void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
static void SimpleWrite(TBuffer &buf, void *addr, const TStreamerElement *)
static void ConvertLoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t nvalues, const TStreamerElement *elem)
static void ArrayWriteCompressed(TBuffer &buf, double *addr, Int_t nvalues, const TStreamerElement *elem)
static void SimpleWriteDouble32(TBuffer &buf, void *addr, const TStreamerElement *elem)
static Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
void(*)(TBuffer &, void *, const void *, Next_t, Int_t, const TStreamerElement *elem) LoopAction_t
static Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static void ArrayWriteCompressed(TBuffer &buf, float *addr, Int_t nvalues, const TStreamerElement *elem)
static void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
static Int_t WriteNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
static Int_t ReadStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *, const TConfiguration *config)
static Int_t WriteStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t WriteStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t ReadStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateReadActionSquence(TStreamerInfo &info, TLoopConfiguration *loopConfig)
static Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateWriteActionSquence(TStreamerInfo &info, TLoopConfiguration *loopConfig)
static Int_t StreamerLoopExternal(TBuffer &buf, void *addr, const TConfiguration *actionConfig)
static Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config, To *items)
static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *, To *items)
static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *)
static Int_t Action(TBuffer &, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
CollectionLooper< GenericLooper >::ReadStreamerLoop< kIsText, const void *, const TLoopConfiguration * > ReadStreamerLoop
static Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t WriteNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t WriteCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static void SimpleWriteFloat16(TBuffer &buf, void *addr)
static void SimpleReadFloat16(TBuffer &buf, void *addr)
Int_t(*)(TBuffer &, void *, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *) LoopAction_t
static Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration *loopconf, const TConfiguration *config)
static Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
static void SimpleRead(TBuffer &buf, void *addr)
static void SimpleReadDouble32(TBuffer &buf, void *addr)
static void SimpleWriteDouble32(TBuffer &buf, void *addr)
static Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
CollectionLooper< GenericLooper >::WriteStreamerLoop< kIsText, const void *, const TLoopConfiguration * > WriteStreamerLoop
Int_t(*)(TBuffer &, void *, const TConfiguration *) LoopAction_t
static Int_t LoopOverCollection(TBuffer &buf, void *start, const TConfiguration *config)
TBitsConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset=0)
void PrintDebug(TBuffer &, void *) const override
TConfObject(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, TClass *onfileClass, TClass *inMemoryClass)
TConfStreamerLoop(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, bool isPtrPtr)
TConfSubSequence(const TConfSubSequence &input)
TConfSubSequence(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, std::unique_ptr< TStreamerInfoActions::TActionSequence > actions)
std::unique_ptr< TStreamerInfoActions::TActionSequence > fActions
TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset=0)
void PrintDebug(TBuffer &, void *) const override
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
CollectionLooper< VectorLooper >::ReadStreamerLoop< kIsText, const void *, const TLoopConfiguration * > ReadStreamerLoop
static Int_t WriteCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
Int_t(*)(TBuffer &, void *, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *) LoopAction_t
static Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t WriteCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
CollectionLooper< VectorLooper >::WriteStreamerLoop< kIsText, const void *, const TLoopConfiguration * > WriteStreamerLoop
static Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
Int_t(*)(TBuffer &, void *start, const void *end, const TConfiguration *) LoopAction_t
static Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateWriteActionSquence(TStreamerInfo &info, TLoopConfiguration *)
static Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateReadActionSquence(TStreamerInfo &info, TLoopConfiguration *)
static Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
CollectionLooper< VectorPtrLooper >::ReadStreamerLoop< kIsText, const void * > ReadStreamerLoop
CollectionLooper< VectorPtrLooper >::WriteStreamerLoop< kIsText, const void * > WriteStreamerLoop
static Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)