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;
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
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
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
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.
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 {
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
209
211 {
212 std::unique_ptr<TStreamerInfoActions::TActionSequence> fActions;
213
215 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions) :
217 fActions(std::move(actions))
218 {}
219
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
246
247 TConfiguration *Copy() override { return new TConfStreamerLoop(*this); };
248 };
249
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
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) {
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);
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);
305 (*pstreamer)(buf, x, config->fCompInfo->fLength);
306 return 0;
307 }
308
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
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.
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);
340 return 0;
341 }
342
343 // Write a full object objectwise including reading the version and
344 // selecting any conversion.
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);
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
464 {
465 buf.WriteFloat16(addr, const_cast<TStreamerElement*>(elem));
466 }
467
469 {
470 buf.WriteDouble32(addr, const_cast<TStreamerElement*>(elem));
471 }
472
474 {
475 TClass *cl = config->fCompInfo->fClass;
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;
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
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:
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) {
613 fCreateIterators = proxy->GetFunctionCreateIterators(read);
614 fCopyIterator = proxy->GetFunctionCopyIterator();
615 fDeleteIterator = proxy->GetFunctionDeleteIterator();
616 fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
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
642
646
650
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:
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:
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:
742 public:
746
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();
790
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
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();
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) {
865 buf.ReadInt(nobjects);
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) {
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
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) {
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
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 }
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
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
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
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) {
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);
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;
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.
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
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
1296 {
1298 auto onfileObject = config->fOnfileObject;
1299
1300 // onfileObject->SetSize(n);
1301 b.PushDataCache( onfileObject );
1302
1303 return 0;
1304 }
1305
1307 {
1309 auto onfileObject = config->fOnfileObject;
1310
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
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.
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;
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
1391 {
1393 Int_t bufpos = b.Length();
1394
1395 TVirtualArray *cached = b.PeekDataCache();
1396 if (cached==0) {
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;
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
1417 {
1419
1420 Int_t bufpos = b.Length();
1421 TVirtualArray *cached = b.PeekDataCache();
1422 if (cached==0) {
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;
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) {
1451
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;
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 {
1487 if ( (proxy.GetProperties() & TVirtualCollectionProxy::kIsEmulated) ) {
1488 return kVectorLooper;
1489 } else if ( (proxy.GetCollectionType() == ROOT::kSTLvector)) {
1490 if (proxy.GetProperties() & TVirtualCollectionProxy::kCustomAlloc)
1491 return kGenericLooper;
1492 else
1493 return kVectorLooper;
1494 } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1495 || proxy.GetCollectionType() == ROOT::kSTLmultiset || proxy.GetCollectionType() == ROOT::kSTLunorderedmultiset
1496 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap
1497 || proxy.GetCollectionType() == ROOT::kSTLunorderedmap || proxy.GetCollectionType() == ROOT::kSTLunorderedmultimap
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 /// \param loopConfig pointer ownership stays at the caller, a copy is performed and transferred to the
1518 /// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return unique
1519 /// pointer of type TActionSequence
1520 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1522 {
1524 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1526 return actions;
1527 }
1528
1529 /// \param loopConfig pointer ownership stays at the caller, a copy is performed and transferred to the
1530 /// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return unique
1531 /// pointer of type TActionSequence
1532 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1534 {
1536 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1538 return actions;
1539 }
1540
1541 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * /* loopconfig */, const TConfiguration *config)
1542 {
1543 auto conf = (TConfSubSequence*)config;
1544 auto actions = conf->fActions.get();
1545 // FIXME: need to update the signature of ApplySequence.
1546 buf.ApplySequence(*actions, start, const_cast<void*>(end));
1547 return 0;
1548 }
1549
1550 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1551 {
1552 UInt_t pos, count;
1553 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1554
1555 Looper::template LoopOverCollection< ReadViaExtStreamer >(buf, start, end, loopconfig, config);
1556
1557 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1558 return 0;
1559 }
1560
1561 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1562 {
1563 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1564
1565 Looper::template LoopOverCollection< WriteViaExtStreamer >(buf, start, end, loopconfig, config);
1566
1567 buf.SetByteCount(pos, kTRUE);
1568 return 0;
1569 }
1570
1572 UInt_t ioffset = actionConfig->fOffset;
1573 // Get any private streamer which was set for the data member.
1574 TMemberStreamer* pstreamer = actionConfig->fCompInfo->fStreamer;
1575 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + actionConfig->fCompInfo->fMethod /*counter offset*/);
1576 // And call the private streamer, passing it the buffer, the object, and the counter.
1577 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
1578 return 0;
1579 };
1580
1581 template<bool kIsTextT>
1582 static Int_t WriteStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config) {
1583 // Get the class of the data member.
1584 TClass* cl = config->fCompInfo->fClass;
1585 UInt_t ioffset = config->fOffset;
1586 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1587
1588 // Get the counter for the varying length array.
1589 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1590
1591 //b << vlen;
1592 if (vlen) {
1593 // Get a pointer to the array of pointers.
1594 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1595 // Loop over each element of the array of pointers to varying-length arrays.
1596 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1597 if (!pp[ndx]) {
1598 // -- We do not have a pointer to a varying-length array.
1599 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1600 // ::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()));
1601 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());
1602 continue;
1603 }
1604 if (!isPtrPtr) {
1605 // -- We are a varying-length array of objects.
1606 // Write the entire array of objects to the buffer.
1607 // Note: Polymorphism is not allowed here.
1608 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
1609 } else {
1610 // -- We are a varying-length array of pointers to objects.
1611 // Write the entire array of object pointers to the buffer.
1612 // Note: The object pointers are allowed to be polymorphic.
1613 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1614 } // isPtrPtr
1615 } // ndx
1616 } else // vlen
1617 if (kIsTextT) {
1618 // special handling for the text-based streamers
1619 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
1620 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
1621 }
1622 return 0;
1623 }
1624
1625 static Int_t WriteStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config) {
1626 // Get the class of the data member.
1627 TClass* cl = config->fCompInfo->fClass;
1628 UInt_t ioffset = config->fOffset;
1629 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1630
1631 // Get the counter for the varying length array.
1632 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1633 //b << vlen;
1634 if (vlen) {
1635 // Get a pointer to the array of pointers.
1636 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1637 // -- Older versions do *not* allow polymorphic pointers to objects.
1638 // Loop over each element of the array of pointers to varying-length arrays.
1639 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1640 if (!pp[ndx]) {
1641 // -- We do not have a pointer to a varying-length array.
1642 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1643 // ::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()));
1644 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());
1645 continue;
1646 }
1647 if (!isPtrPtr) {
1648 // -- We are a varying-length array of objects.
1649 // Loop over the elements of the varying length array.
1650 for (Int_t v = 0; v < vlen; ++v) {
1651 // Write the object to the buffer.
1652 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1653 } // v
1654 }
1655 else {
1656 // -- We are a varying-length array of pointers to objects.
1657 // Loop over the elements of the varying length array.
1658 for (Int_t v = 0; v < vlen; ++v) {
1659 // Get a pointer to the object pointer.
1660 char** r = (char**) pp[ndx];
1661 // Write the object to the buffer.
1662 cl->Streamer(r[v], buf);
1663 } // v
1664 } // isPtrPtr
1665 } // ndx
1666 } // vlen
1667 return 0;
1668 }
1669
1670 template<bool kIsTextT, typename... Ts>
1672 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1673 {
1674 if (!kIsTextT && config->fCompInfo->fStreamer) {
1675 // -- We have a private streamer.
1676 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1677
1678 // Loop over the entries in the clones array or the STL container.
1679 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1680
1681 buf.SetByteCount(pos, kTRUE);
1682 // We are done, next streamer element.
1683 return 0;
1684 }
1685
1686 // By default assume the file version is the newest.
1688
1689 if (!kIsTextT) {
1690 // At this point we do *not* have a private streamer.
1691 // Get the version of the file we are writing to.
1692 TFile* file = (TFile*) buf.GetParent();
1693 if (file) {
1694 fileVersion = file->GetVersion();
1695 }
1696 }
1697 // Write the class version to the buffer.
1698 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1699 if (fileVersion > 51508) {
1700 // -- Newer versions allow polymorphic pointers to objects.
1701 // Loop over the entries in the clones array or the STL container.
1702 Looper::template LoopOverCollection< WriteStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1703 }
1704 else {
1705 // -- Older versions do *not* allow polymorphic pointers to objects.
1706 // Loop over the entries in the clones array or the STL container.
1707 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1708 } // fileVersion
1709 // Backpatch the byte count into the buffer.
1710 buf.SetByteCount(pos, kTRUE);
1711
1712 return 0;
1713 }
1714 };
1715
1716 template<bool kIsTextT>
1717 static Int_t ReadStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config) {
1718 // Get the class of the data member.
1719 TClass* cl = config->fCompInfo->fClass;
1720 UInt_t ioffset = config->fOffset;
1721 // Which are we, an array of objects or an array of pointers to objects?
1722 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1723
1724 // Get the counter for the varying length array.
1725 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1726 config->fCompInfo->fMethod /*counter offset*/));
1727 // Int_t realLen;
1728 // b >> realLen;
1729 // if (realLen != vlen) {
1730 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1731 //}
1732 // Get a pointer to the array of pointers.
1733 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1734 // Loop over each element of the array of pointers to varying-length arrays.
1735 // if (!pp) {
1736 // continue;
1737 // }
1738
1739 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1740 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1741 // if (!pp[ndx]) {
1742 // -- We do not have a pointer to a varying-length array.
1743 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1744 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1745 // continue;
1746 //}
1747 // Delete any memory at pp[ndx].
1748 if (!isPtrPtr) {
1749 cl->DeleteArray(pp[ndx]);
1750 pp[ndx] = 0;
1751 } else {
1752 // Using vlen is wrong here because it has already
1753 // been overwritten with the value needed to read
1754 // the current record. Fixing this will require
1755 // doing a pass over the object at the beginning
1756 // of the I/O and releasing all the buffer memory
1757 // for varying length arrays before we overwrite
1758 // the counter values.
1759 //
1760 // For now we will just leak memory, just as we
1761 // have always done in the past. Fix this.
1762 //
1763 // char** r = (char**) pp[ndx];
1764 // if (r) {
1765 // for (Int_t v = 0; v < vlen; ++v) {
1766 // cl->Destructor(r[v]);
1767 // r[v] = 0;
1768 // }
1769 //}
1770 delete[] pp[ndx];
1771 pp[ndx] = 0;
1772 }
1773 if (!vlen) {
1774 if (kIsTextT) {
1775 // special handling for the text-based streamers - keep calling to shift array index
1776 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
1777 }
1778 continue;
1779 }
1780 // Note: We now have pp[ndx] is null.
1781 // Allocate memory to read into.
1782 if (!isPtrPtr) {
1783 // -- We are a varying-length array of objects.
1784 // Note: Polymorphism is not allowed here.
1785 // Allocate a new array of objects to read into.
1786 pp[ndx] = (char *)cl->NewArray(vlen);
1787 if (!pp[ndx]) {
1788 Error("ReadBuffer", "Memory allocation failed!\n");
1789 continue;
1790 }
1791 } else {
1792 // -- We are a varying-length array of pointers to objects.
1793 // Note: The object pointers are allowed to be polymorphic.
1794 // Allocate a new array of pointers to objects to read into.
1795 pp[ndx] = (char *)new char *[vlen];
1796 if (!pp[ndx]) {
1797 Error("ReadBuffer", "Memory allocation failed!\n");
1798 continue;
1799 }
1800 // And set each pointer to null.
1801 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1802 // = (char*) new char*[vlen];
1803 }
1804 if (!isPtrPtr) {
1805 // -- We are a varying-length array of objects.
1806 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
1807 } else {
1808 // -- We are a varying-length array of object pointers.
1809 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1810 } // isPtrPtr
1811 } // ndx
1812 return 0;
1813 }; // StreamerLoopPoly
1814
1815 static Int_t ReadStreamerLoopStatic(TBuffer &buf, void *addr, const TConfiguration *config) {
1816 // Get the class of the data member.
1817 TClass* cl = config->fCompInfo->fClass;
1818 UInt_t ioffset = config->fOffset;
1819 // Which are we, an array of objects or an array of pointers to objects?
1820 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1821
1822 // Get the counter for the varying length array.
1823 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1824 config->fCompInfo->fMethod /*counter offset*/));
1825 // Int_t realLen;
1826 // b >> realLen;
1827 // if (realLen != vlen) {
1828 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1829 //}
1830 // Get a pointer to the array of pointers.
1831 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1832 // if (!pp) {
1833 // continue;
1834 //}
1835
1836 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1837
1838 // Loop over each element of the array of pointers to varying-length arrays.
1839 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1840 // if (!pp[ndx]) {
1841 // -- We do not have a pointer to a varying-length array.
1842 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1843 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1844 // continue;
1845 //}
1846 // Delete any memory at pp[ndx].
1847 if (!isPtrPtr) {
1848 cl->DeleteArray(pp[ndx]);
1849 pp[ndx] = 0;
1850 } else {
1851 // Using vlen is wrong here because it has already
1852 // been overwritten with the value needed to read
1853 // the current record. Fixing this will require
1854 // doing a pass over the object at the beginning
1855 // of the I/O and releasing all the buffer memory
1856 // for varying length arrays before we overwrite
1857 // the counter values.
1858 //
1859 // For now we will just leak memory, just as we
1860 // have always done in the past. Fix this.
1861 //
1862 // char** r = (char**) pp[ndx];
1863 // if (r) {
1864 // for (Int_t v = 0; v < vlen; ++v) {
1865 // cl->Destructor(r[v]);
1866 // r[v] = 0;
1867 // }
1868 //}
1869 delete[] pp[ndx];
1870 pp[ndx] = 0;
1871 }
1872 if (!vlen) {
1873 continue;
1874 }
1875 // Note: We now have pp[ndx] is null.
1876 // Allocate memory to read into.
1877 if (!isPtrPtr) {
1878 // -- We are a varying-length array of objects.
1879 // Note: Polymorphism is not allowed here.
1880 // Allocate a new array of objects to read into.
1881 pp[ndx] = (char *)cl->NewArray(vlen);
1882 if (!pp[ndx]) {
1883 Error("ReadBuffer", "Memory allocation failed!\n");
1884 continue;
1885 }
1886 } else {
1887 // -- We are a varying-length array of pointers to objects.
1888 // Note: The object pointers are allowed to be polymorphic.
1889 // Allocate a new array of pointers to objects to read into.
1890 pp[ndx] = (char *)new char *[vlen];
1891 if (!pp[ndx]) {
1892 Error("ReadBuffer", "Memory allocation failed!\n");
1893 continue;
1894 }
1895 // And set each pointer to null.
1896 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1897 // = (char*) new char*[vlen];
1898 }
1899 if (!isPtrPtr) {
1900 // -- We are a varying-length array of objects.
1901 // Loop over the elements of the varying length array.
1902 for (Int_t v = 0; v < vlen; ++v) {
1903 // Read the object from the buffer.
1904 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1905 } // v
1906 } else {
1907 // -- We are a varying-length array of object pointers.
1908 // Get a pointer to the object pointer array.
1909 char **r = (char **)pp[ndx];
1910 // Loop over the elements of the varying length array.
1911 for (Int_t v = 0; v < vlen; ++v) {
1912 // Allocate an object to read into.
1913 r[v] = (char *)cl->New();
1914 if (!r[v]) {
1915 // Do not print a second error message here.
1916 // Error("ReadBuffer", "Memory allocation failed!\n");
1917 continue;
1918 }
1919 // Read the object from the buffer.
1920 cl->Streamer(r[v], buf);
1921 } // v
1922 } // isPtrPtr
1923 } // ndx
1924 return 0;
1925 }; // action
1926
1927 template<bool kIsTextT, typename... Ts>
1929 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1930 {
1931 // Check for a private streamer.
1932 if (!kIsTextT && config->fCompInfo->fStreamer) {
1933 // -- We have a private streamer.
1934 // Read the class version and byte count from the buffer.
1935 UInt_t pos = 0;
1936 UInt_t count = 0;
1937 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1938
1939 // Loop over the entries in the clones array or the STL container.
1940 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1941
1942 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1943 // We are done, next streamer element.
1944 return 0;
1945 }
1946
1947 // By default assume the file version is the newest.
1949 if (!kIsTextT) {
1950 // At this point we do *not* have a private streamer.
1951 // Get the version of the file we are reading from.
1952 TFile* file = (TFile*) buf.GetParent();
1953 if (file) {
1954 fileVersion = file->GetVersion();
1955 }
1956 }
1957 // Read the class version and byte count from the buffer.
1958 UInt_t pos = 0;
1959 UInt_t count = 0;
1960 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1961 if (fileVersion > 51508) {
1962 // -- Newer versions allow polymorphic pointers.
1963
1964 // Loop over the entries in the clones array or the STL container.
1965 Looper::template LoopOverCollection< ReadStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1966 } else {
1967 // -- Older versions do *not* allow polymorphic pointers.
1968
1969 // Loop over the entries in the clones array or the STL container.
1970 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1971 } // fileVersion
1972 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1973 return 0;
1974 }
1975 };
1976
1977 };
1978
1979 // The Scalar 'looper' only process one element.
1980 struct ScalarLooper : public CollectionLooper<ScalarLooper>
1981 {
1982 using LoopAction_t = Int_t (*)(TBuffer &, void*, const TConfiguration*);
1983
1984 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1985 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const TConfiguration *config)
1986 {
1987 iter_action(buf, start, config);
1988 return 0;
1989 }
1990 };
1991
1992 struct VectorLooper : public CollectionLooper<VectorLooper>
1993 {
1994 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
1995
1996 template <bool kIsText>
1998 template <bool kIsText>
2000
2001 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2002 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2003 {
2004 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2005 //Idea: can we factor out the addition of fOffset
2006 // iter = (char*)iter + config->fOffset;
2007 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
2008 iter_action(buf, iter, config);
2009 }
2010 return 0;
2011 }
2012
2013 template <typename T>
2014 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2015 {
2016 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2017 iter = (char*)iter + config->fOffset;
2018 end = (char*)end + config->fOffset;
2019 for(; iter != end; iter = (char*)iter + incr ) {
2020 T *x = (T*) ((char*) iter);
2021 buf >> *x;
2022 }
2023 return 0;
2024 }
2025
2026 template <typename From, typename To>
2028 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2029 {
2030 // Simple conversion from a 'From' on disk to a 'To' in memory.
2031 From temp;
2032 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2033 iter = (char*)iter + config->fOffset;
2034 end = (char*)end + config->fOffset;
2035 for(; iter != end; iter = (char*)iter + incr ) {
2036 buf >> temp;
2037 *(To*)( ((char*)iter) ) = (To)temp;
2038 }
2039 return 0;
2040 }
2041 };
2042
2043 template <typename To>
2045 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2046 {
2047 // Simple conversion from a 'From' on disk to a 'To' in memory.
2048 UInt_t temp;
2049 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2050 iter = (char*)iter + config->fOffset;
2051 end = (char*)end + config->fOffset;
2052 for(; iter != end; iter = (char*)iter + incr ) {
2053 buf >> temp;
2054
2055 if ((temp & kIsReferenced) != 0) {
2056 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
2057 }
2058
2059 *(To*)( ((char*)iter) ) = (To)temp;
2060 }
2061 return 0;
2062 }
2063 };
2064
2065 template <typename From, typename To>
2067 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2068 {
2069 // Simple conversion from a 'From' on disk to a 'To' in memory.
2071 From temp;
2072 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2073 iter = (char*)iter + config->fOffset;
2074 end = (char*)end + config->fOffset;
2075 for(; iter != end; iter = (char*)iter + incr ) {
2076 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2077 *(To*)( ((char*)iter) ) = (To)temp;
2078 }
2079 return 0;
2080 }
2081 };
2082
2083 template <typename From, typename To>
2085 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2086 {
2087 // Simple conversion from a 'From' on disk to a 'To' in memory.
2088 TConfNoFactor *conf = (TConfNoFactor *)config;
2089 From temp;
2090 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2091 iter = (char*)iter + config->fOffset;
2092 end = (char*)end + config->fOffset;
2093 for(; iter != end; iter = (char*)iter + incr ) {
2094 buf.ReadWithNbits(&temp, conf->fNbits);
2095 *(To*)( ((char*)iter) ) = (To)temp;
2096 }
2097 return 0;
2098 }
2099 };
2100
2101 template <typename T>
2102 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2103 {
2104 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2105 iter = (char*)iter + config->fOffset;
2106 end = (char*)end + config->fOffset;
2107 for(; iter != end; iter = (char*)iter + incr ) {
2108 T *x = (T*) ((char*) iter);
2109 buf << *x;
2110 }
2111 return 0;
2112 }
2113
2114 template <typename Onfile, typename Memory>
2116 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2117 {
2118 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2119 iter = (char*)iter + config->fOffset;
2120 end = (char*)end + config->fOffset;
2121 for(; iter != end; iter = (char*)iter + incr ) {
2122 // Simple conversion from a 'From' on disk to a 'To' in memory.
2123 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2124 buf << temp;
2125 }
2126 return 0;
2127 }
2128 };
2129
2130 template <typename Onfile, typename Memory>
2132 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2133 {
2134 const TStreamerElement *elem = config->fCompInfo->fElem;
2135 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2136 iter = (char*)iter + config->fOffset;
2137 end = (char*)end + config->fOffset;
2138 for(; iter != end; iter = (char*)iter + incr ) {
2139 // Simple conversion from a 'From' on disk to a 'To' in memory.
2140 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2141 WriteCompressed(buf, &temp, elem);
2142 }
2143 return 0;
2144 }
2145 };
2146
2147 template <typename Onfile, typename Memory>
2149 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2150 {
2151 const TStreamerElement *elem = config->fCompInfo->fElem;
2152 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2153 iter = (char*)iter + config->fOffset;
2154 end = (char*)end + config->fOffset;
2155 for(; iter != end; iter = (char*)iter + incr ) {
2156 // Simple conversion from a 'From' on disk to a 'To' in memory.
2157 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2158 WriteCompressed(buf, &temp, elem);
2159 }
2160 return 0;
2161 }
2162 };
2163
2164 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2165 {
2166 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2167 // punt.
2168
2169 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2170 UInt_t n = (((char*)end)-((char*)start))/incr;
2171 char **arrptr = new char*[n];
2172 UInt_t i = 0;
2173 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2174 arrptr[i] = (char*)iter;
2175 }
2176 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2177 delete [] arrptr;
2178 return 0;
2179 }
2180
2181 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2182 {
2183 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2184 // punt.
2185
2186 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2187 UInt_t n = (((char*)end)-((char*)start))/incr;
2188 char **arrptr = new char*[n];
2189 UInt_t i = 0;
2190 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2191 arrptr[i] = (char*)iter;
2192 }
2193 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2194 delete [] arrptr;
2195 return 0;
2196 }
2197
2198 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2199 {
2200 // Well the implementation is non trivial. For now punt.
2201
2202 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2203 UInt_t n = (((char*)end)-((char*)start))/incr;
2204 char **arrptr = new char*[n];
2205 UInt_t i = 0;
2206 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2207 arrptr[i] = (char*)iter;
2208 }
2209 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2210 delete [] arrptr;
2211 return 0;
2212 }
2213
2214 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2215 {
2216 // Well the implementation is non trivial. For now punt.
2217
2218 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2219 UInt_t n = (((char*)end)-((char*)start))/incr;
2220 char **arrptr = new char*[n];
2221 UInt_t i = 0;
2222 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2223 arrptr[i] = (char*)iter;
2224 }
2225 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2226 delete [] arrptr;
2227 return 0;
2228 }
2229
2230 template <typename T>
2232 {
2233 // Collection of numbers. Memberwise or not, it is all the same.
2234
2235 TConfigSTL *config = (TConfigSTL*)conf;
2236 UInt_t start, count;
2237 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2238
2239 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2240 Int_t nvalues;
2241 buf.ReadInt(nvalues);
2242 vec->resize(nvalues);
2243
2244#ifdef R__VISUAL_CPLUSPLUS
2245 if (nvalues <= 0) {
2246 buf.CheckByteCount(start,count,config->fTypeName);
2247 return 0;
2248 }
2249#endif
2250 T *begin = vec->data();
2251 buf.ReadFastArray(begin, nvalues);
2252
2253 buf.CheckByteCount(start,count,config->fTypeName);
2254 return 0;
2255 }
2256
2257 template <typename T>
2259 {
2260 // Collection of numbers. Memberwise or not, it is all the same.
2261
2262 TConfigSTL *config = (TConfigSTL*)conf;
2263 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2264
2265 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2266 Int_t nvalues = vec->size();
2267 buf.WriteInt(nvalues);
2268
2269 T *begin = vec->data();
2270 buf.WriteFastArray(begin, nvalues);
2271
2272 buf.SetByteCount(start);
2273 return 0;
2274 }
2275
2277 {
2278 // Collection of numbers. Memberwise or not, it is all the same.
2279
2280 TConfigSTL *config = (TConfigSTL*)conf;
2281 UInt_t start, count;
2282 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2283
2284 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2285 Int_t nvalues;
2286 buf.ReadInt(nvalues);
2287 vec->resize(nvalues);
2288
2289#ifdef R__VISUAL_CPLUSPLUS
2290 if (nvalues <= 0) {
2291 buf.CheckByteCount(start,count,config->fTypeName);
2292 return 0;
2293 }
2294#endif
2295 float *begin = vec->data();
2296 buf.ReadFastArrayFloat16(begin, nvalues);
2297
2298 buf.CheckByteCount(start,count,config->fTypeName);
2299 return 0;
2300 }
2301
2303 {
2304 // Collection of numbers. Memberwise or not, it is all the same.
2305
2306 TConfigSTL *config = (TConfigSTL*)conf;
2307 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2308
2309 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2310 Int_t nvalues = vec->size();
2311 buf.WriteInt(nvalues);
2312
2313 float *begin = vec->data();
2314 buf.WriteFastArrayFloat16(begin, nvalues);
2315
2316 buf.SetByteCount(start);
2317 return 0;
2318 }
2319
2321 {
2322 // Collection of numbers. Memberwise or not, it is all the same.
2323
2324 TConfigSTL *config = (TConfigSTL*)conf;
2325 UInt_t start, count;
2326 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2327
2328 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2329 Int_t nvalues;
2330 buf.ReadInt(nvalues);
2331 vec->resize(nvalues);
2332
2333#ifdef R__VISUAL_CPLUSPLUS
2334 if (nvalues <= 0) {
2335 buf.CheckByteCount(start,count,config->fTypeName);
2336 return 0;
2337 }
2338#endif
2339 double *begin = vec->data();
2340 buf.ReadFastArrayDouble32(begin, nvalues);
2341
2342 buf.CheckByteCount(start,count,config->fTypeName);
2343 return 0;
2344 }
2345
2347 {
2348 // Collection of numbers. Memberwise or not, it is all the same.
2349
2350 TConfigSTL *config = (TConfigSTL*)conf;
2351 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2352
2353 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2354 Int_t nvalues = vec->size();
2355 buf.WriteInt(nvalues);
2356
2357 double *begin = vec->data();
2358 buf.WriteFastArrayDouble32(begin, nvalues);
2359
2360 buf.SetByteCount(start);
2361 return 0;
2362 }
2363
2364 template <typename From, typename To>
2367 {
2368 // Collection of numbers. Memberwise or not, it is all the same.
2369
2370 TConfigSTL *config = (TConfigSTL*)conf;
2371 UInt_t start, count;
2372 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2373
2374 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2375 Int_t nvalues;
2376 buf.ReadInt(nvalues);
2377 vec->resize(nvalues);
2378
2379 From *temp = new From[nvalues];
2380 buf.ReadFastArray(temp, nvalues);
2381 for(Int_t ind = 0; ind < nvalues; ++ind) {
2382 (*vec)[ind] = (To)temp[ind];
2383 }
2384 delete [] temp;
2385
2386 buf.CheckByteCount(start,count,config->fTypeName);
2387 return 0;
2388 }
2389 };
2390
2391 template <typename From, typename To>
2394 {
2395 // Collection of numbers. Memberwise or not, it is all the same.
2396
2397 TConfigSTL *config = (TConfigSTL*)conf;
2398 UInt_t start, count;
2399 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2400
2401 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2402 Int_t nvalues;
2403 buf.ReadInt(nvalues);
2404 vec->resize(nvalues);
2405
2406 From *temp = new From[nvalues];
2407 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2408 for(Int_t ind = 0; ind < nvalues; ++ind) {
2409 (*vec)[ind] = (To)temp[ind];
2410 }
2411 delete [] temp;
2412
2413 buf.CheckByteCount(start,count,config->fTypeName);
2414 return 0;
2415 }
2416 };
2417
2418 template <typename To>
2420 {
2421 // Collection of numbers. Memberwise or not, it is all the same.
2422
2423 TConfigSTL *config = (TConfigSTL*)conf;
2424 UInt_t start, count;
2425 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2426
2427 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2428 Int_t nvalues;
2429 buf.ReadInt(nvalues);
2430 vec->resize(nvalues);
2431
2432 Double32_t *temp = new Double32_t[nvalues];
2433 buf.ReadFastArrayDouble32(temp, nvalues);
2434 for(Int_t ind = 0; ind < nvalues; ++ind) {
2435 (*vec)[ind] = (To)temp[ind];
2436 }
2437 delete [] temp;
2438
2439 buf.CheckByteCount(start,count,config->fTypeName);
2440 return 0;
2441 }
2442
2443 template <typename Memory, typename Onfile>
2446 {
2447 // Collection of numbers. Memberwise or not, it is all the same.
2448
2449 TConfigSTL *config = (TConfigSTL*)conf;
2450 UInt_t start = buf.WriteVersion( config->fInfo->IsA(), kTRUE );
2451
2452 std::vector<Memory> *const vec = (std::vector<Memory>*)(((char*)addr)+config->fOffset);
2453 Int_t nvalues = vec->size();
2454 buf.WriteInt(nvalues);
2455
2456 // We have to call WriteFastArray for proper JSON writing
2457 // So we need to convert before hand :(
2458 Onfile *temp = new Onfile[nvalues];
2459 for(Int_t ind = 0; ind < nvalues; ++ind) {
2460 temp[ind] = (Onfile)((*vec)[ind]);
2461 }
2462 buf.WriteFastArray(temp, nvalues);
2463 delete [] temp;
2464
2465 buf.SetByteCount(start, kTRUE);
2466 return 0;
2467 }
2468 };
2469 };
2470
2471 struct VectorPtrLooper : public CollectionLooper<VectorPtrLooper> {
2472 // Can not inherit/use CollectionLooper<VectorPtrLooper>, because this looper's
2473 // function do not take a `TLoopConfiguration`.
2474
2475 using LoopAction_t = Int_t (*)(TBuffer &, void *start, const void *end, const TConfiguration*);
2476
2477 template <bool kIsText>
2479 template <bool kIsText>
2481
2482 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2484 {
2485 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2486 return unique_ptr(info.GetReadMemberWiseActions(kTRUE)->CreateCopy());
2487 }
2488
2489 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2491 {
2492 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2493 return unique_ptr(info.GetWriteMemberWiseActions(kTRUE)->CreateCopy());
2494 }
2495
2496 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2497 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2498 {
2499 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2500 action(buf, *(void**)iter, config);
2501 }
2502 return 0;
2503 }
2504
2505 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2506 {
2507 auto conf = (TConfSubSequence*)config;
2508 auto actions = conf->fActions.get();
2509 // FIXME: need to update the signature of ApplySequence.
2510 buf.ApplySequenceVecPtr(*actions, start, const_cast<void*>(end));
2511 return 0;
2512 }
2513
2514 template <typename T>
2515 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2516 {
2517 const Int_t offset = config->fOffset;
2518
2519 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2520 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2521 buf >> *x;
2522 }
2523 return 0;
2524 }
2525
2526 template <typename From, typename To>
2528 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2529 {
2530 // Simple conversion from a 'From' on disk to a 'To' in memory.
2531 From temp;
2532 const Int_t offset = config->fOffset;
2533 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2534 buf >> temp;
2535 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2536 *x = (To)temp;
2537 }
2538 return 0;
2539 }
2540 };
2541
2542 template <typename To>
2544 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2545 {
2546 // Simple conversion from a 'From' on disk to a 'To' in memory.
2547 UInt_t temp;
2548 const Int_t offset = config->fOffset;
2549 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2550 buf >> temp;
2551
2552 if ((temp & kIsReferenced) != 0) {
2553 HandleReferencedTObject(buf,*(void**)iter,config);
2554 }
2555
2556 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2557 *x = (To)temp;
2558 }
2559 return 0;
2560 }
2561 };
2562
2563 template <typename From, typename To>
2565 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2566 {
2567 // Simple conversion from a 'From' on disk to a 'To' in memory.
2569 From temp;
2570 const Int_t offset = config->fOffset;
2571 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2572 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2573 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2574 *x = (To)temp;
2575 }
2576 return 0;
2577 }
2578 };
2579
2580 template <typename From, typename To>
2582 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2583 {
2584 // Simple conversion from a 'From' on disk to a 'To' in memory.
2585 TConfNoFactor *conf = (TConfNoFactor *)config;
2586 From temp;
2587 const Int_t offset = config->fOffset;
2588 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2589 buf.ReadWithNbits(&temp, conf->fNbits);
2590 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2591 *x = (To)temp;
2592 }
2593 return 0;
2594 }
2595 };
2596
2597 template <typename T>
2598 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2599 {
2600 const Int_t offset = config->fOffset;
2601
2602 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2603 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2604 buf << *x;
2605 }
2606 return 0;
2607 }
2608
2609 template <typename To, typename From>
2611 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2612 {
2613 const Int_t offset = config->fOffset;
2614
2615 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2616 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2617 To to = (To)(*from);
2618 buf << to;
2619 }
2620 return 0;
2621 }
2622 };
2623
2624 template <typename To, typename From>
2626 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2627 {
2628 const Int_t offset = config->fOffset;
2629 const TStreamerElement *elem = config->fCompInfo->fElem;
2630
2631 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2632 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2633 To to = (To)(*from);
2634 WriteCompressed(buf, &to, elem);
2635 }
2636 return 0;
2637 }
2638 };
2639 template <typename To, typename From>
2641 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2642 {
2643 const Int_t offset = config->fOffset;
2644 const TStreamerElement *elem = config->fCompInfo->fElem;
2645
2646 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2647 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2648 To to = (To)(*from);
2649 WriteCompressed(buf, &to, elem);
2650 }
2651 return 0;
2652 }
2653 };
2654
2655 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2656 {
2657 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2658 // punt.
2659
2660 return GenericRead(buf,start,end,config);
2661 }
2662
2663 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2664 {
2665 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2666 // punt.
2667
2668 return GenericWrite(buf,start,end,config);
2669 }
2670
2671 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2672 {
2673 UInt_t pos, count;
2674 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
2675
2676 LoopOverCollection< ReadViaExtStreamer >(buf, start, end, config);
2677
2678 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
2679 return 0;
2680 }
2681
2682 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2683 {
2684 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2685
2686 LoopOverCollection< WriteViaExtStreamer >(buf, start, end, config);
2687
2688 buf.SetByteCount(pos, kTRUE);
2689 return 0;
2690 }
2691
2692 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2693 {
2694 Int_t n = ( ((void**)end) - ((void**)iter) );
2695 char **arr = (char**)iter;
2696 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2697 }
2698
2699 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2700 {
2701 Int_t n = ( ((void**)end) - ((void**)iter) );
2702 char **arr = (char**)iter;
2703 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2704 }
2705
2706 };
2707
2709 using LoopAction_t = void (*)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem);
2710
2711protected:
2712
2713 template <typename T>
2715 {
2716 buf.ReadFastArray((T*)addr, nvalues);
2717 }
2718
2720 {
2721 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2722 }
2723
2725 {
2726 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2727 }
2728
2729 template <typename T>
2731 {
2732 buf << *(T*)addr;
2733 }
2734
2736 {
2737 buf.WriteFloat16((float*)addr, const_cast<TStreamerElement*>(elem));
2738 }
2739
2741 {
2742 buf.WriteDouble32((double*)addr, const_cast<TStreamerElement*>(elem));
2743 }
2744
2745 template <typename T>
2747 {
2748 buf.WriteFastArray((T*)addr, nvalues);
2749 }
2750
2752 {
2753 buf.WriteFastArrayFloat16((float*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2754 }
2755
2757 {
2758 buf.WriteFastArrayDouble32((double*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2759 }
2760
2761 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2763 {
2764 // Collection of numbers. Memberwise or not, it is all the same.
2765
2766 TConfigSTL *config = (TConfigSTL*)conf;
2767 UInt_t start, count;
2768 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2769
2770 TClass *newClass = config->fNewClass;
2771 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2773
2774 Int_t nvalues;
2775 buf.ReadInt(nvalues);
2776 void* alternative = newProxy->Allocate(nvalues,true);
2777 if (nvalues) {
2780 void *begin = &(startbuf[0]);
2781 void *end = &(endbuf[0]);
2782 config->fCreateIterators(alternative, &begin, &end, newProxy);
2783 // We can not get here with a split vector of pointer, so we can indeed assume
2784 // that actions->fConfiguration != null.
2785
2786 action(buf,begin,nvalues);
2787
2788 if (begin != &(startbuf[0])) {
2789 // assert(end != endbuf);
2790 config->fDeleteTwoIterators(begin,end);
2791 }
2792 }
2793 newProxy->Commit(alternative);
2794
2795 buf.CheckByteCount(start,count,config->fTypeName);
2796 return 0;
2797 }
2798
2799 template <void (*action)(TBuffer&, void*, const TStreamerElement*)>
2800 static INLINE_TEMPLATE_ARGS void LoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t /* nvalues */, const TStreamerElement *elem)
2801 {
2802 void *addr;
2803 while( (addr = next(iter, end)) )
2804 {
2805 action(buf, addr, elem);
2806 }
2807 }
2808
2809 template <typename Memory, typename Onfile, void (*action)(TBuffer&, void*, Int_t, const TStreamerElement *elem)>
2810 static INLINE_TEMPLATE_ARGS void ConvertLoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t nvalues, const TStreamerElement *elem)
2811 {
2812 Onfile *temp = new Onfile[nvalues];
2813 Int_t ind = 0;
2814 void *addr;
2815 while( (addr = next(iter, end)) )
2816 {
2817 temp[ind] = (Onfile)*(Memory*)addr;
2818 ++ind;
2819 }
2820 action(buf, temp, nvalues, elem);
2821 delete [] temp;
2822 }
2823
2824 template <typename T, void (*action)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem)>
2826 {
2827 // Collection of numbers. Memberwise or not, it is all the same.
2828
2829 TConfigSTL *config = (TConfigSTL*)conf;
2830 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2831
2832 TClass *newClass = config->fNewClass;
2833 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2834 void *collection = ((char*)addr)+config->fOffset;
2836
2837 Int_t nvalues = newProxy->Size();
2838 buf.WriteInt(nvalues);
2839 if (nvalues) {
2842 void *begin = &(startbuf[0]);
2843 void *end = &(endbuf[0]);
2844 config->fCreateIterators(collection, &begin, &end, newProxy);
2845
2846 action(buf, begin, end, config->fNext, nvalues, config->fCompInfo->fElem);
2847
2848 if (begin != &(startbuf[0])) {
2849 // assert(end != endbuf);
2850 config->fDeleteTwoIterators(begin, end);
2851 }
2852 }
2853 buf.SetByteCount(start);
2854 return 0;
2855 }
2856
2857public:
2862
2867
2872
2877
2878 template <typename T>
2883
2884 template <typename T>
2889
2890 template <typename From, typename To>
2893 {
2894 From *temp = new From[nvalues];
2895 buf.ReadFastArray(temp, nvalues);
2896 To *vec = (To*)addr;
2897 for(Int_t ind = 0; ind < nvalues; ++ind) {
2898 vec[ind] = (To)temp[ind];
2899 }
2900 delete [] temp;
2901 }
2902 };
2903
2904 template <typename From, typename To>
2907 {
2908 From *temp = new From[nvalues];
2909 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2910 To *vec = (To*)addr;
2911 for(Int_t ind = 0; ind < nvalues; ++ind) {
2912 vec[ind] = (To)temp[ind];
2913 }
2914 delete [] temp;
2915 }
2916 };
2917
2918 template <typename From, typename To>
2921 {
2922 From *temp = new From[nvalues];
2923 double factor,min; // needs to be initialized.
2924 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2925 To *vec = (To*)addr;
2926 for(Int_t ind = 0; ind < nvalues; ++ind) {
2927 vec[ind] = (To)temp[ind];
2928 }
2929 delete [] temp;
2930 }
2931 };
2932 template <typename From, typename To>
2939
2940 template <typename Memory, typename Onfile>
2947 template <typename Memory, typename Onfile>
2954
2955 template <typename Memory, typename Onfile>
2962
2963 };
2964
2965 struct GenericLooper : public CollectionLooper<GenericLooper> {
2966 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
2967
2968 template <bool kIsText>
2970 template <bool kIsText>
2972
2973 template <typename T>
2974 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2975 {
2977
2978 Next_t next = loopconfig->fNext;
2979 const Int_t offset = config->fOffset;
2980
2982 void *iter = loopconfig->fCopyIterator(iterator,start);
2983 void *addr;
2984 while( (addr = next(iter,end)) ) {
2985 T *x = (T*)( ((char*)addr) + offset );
2986 buf >> *x;
2987 }
2988 if (iter != &iterator[0]) {
2989 loopconfig->fDeleteIterator(iter);
2990 }
2991 return 0;
2992 }
2993
2994 template <typename T>
2995 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2996 {
2998
2999 Next_t next = loopconfig->fNext;
3000 const Int_t offset = config->fOffset;
3001
3003 void *iter = loopconfig->fCopyIterator(iterator,start);
3004 void *addr;
3005 while( (addr = next(iter,end)) ) {
3006 T *x = (T*)( ((char*)addr) + offset );
3007 buf << *x;
3008 }
3009 if (iter != &iterator[0]) {
3010 loopconfig->fDeleteIterator(iter);
3011 }
3012 return 0;
3013 }
3014
3015 template <typename To, typename From>
3017 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3018 {
3020
3021 Next_t next = loopconfig->fNext;
3022 const Int_t offset = config->fOffset;
3023
3025 void *iter = loopconfig->fCopyIterator(iterator,start);
3026 void *addr;
3027 while( (addr = next(iter,end)) ) {
3028 From *x = (From*)( ((char*)addr) + offset );
3029 To t = (To)(*x);
3030 buf << t;
3031 }
3032 if (iter != &iterator[0]) {
3033 loopconfig->fDeleteIterator(iter);
3034 }
3035 return 0;
3036 }
3037 };
3038
3039 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
3040 static INLINE_TEMPLATE_ARGS Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3041 {
3043
3044 // const Int_t offset = config->fOffset;
3045 Next_t next = loopconfig->fNext;
3046
3048 void *iter = loopconfig->fCopyIterator(&iterator,start);
3049 void *addr;
3050 while( (addr = next(iter,end)) ) {
3051 iter_action(buf, addr, config);
3052 }
3053 if (iter != &iterator[0]) {
3054 loopconfig->fDeleteIterator(iter);
3055 }
3056 return 0;
3057 }
3058
3059 template <typename From, typename To>
3060 struct Generic {
3061 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3062 {
3064
3065 const Int_t offset = config->fOffset;
3066 Next_t next = loopconfig->fNext;
3067
3069 void *iter = loopconfig->fCopyIterator(&iterator,start);
3070 void *addr;
3071 while( (addr = next(iter,end)) ) {
3072 To *x = (To*)( ((char*)addr) + offset );
3073 *x = (To)(*items);
3074 ++items;
3075 }
3076 if (iter != &iterator[0]) {
3077 loopconfig->fDeleteIterator(iter);
3078 }
3079 }
3080 // ConvertAction used for writing.
3081 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config, To *items)
3082 {
3084
3085 const Int_t offset = config->fOffset;
3086 Next_t next = loopconfig->fNext;
3087
3089 void *iter = loopconfig->fCopyIterator(&iterator,start);
3090 void *addr;
3091
3092 while( (addr = next(iter,end)) ) {
3093 From *x = (From*)( ((char*)addr) + offset );
3094 *items = (To)*x;
3095 ++items;
3096 }
3097 if (iter != &iterator[0]) {
3098 loopconfig->fDeleteIterator(iter);
3099 }
3100 }
3101 };
3102
3103 template <typename From, typename To>
3104 struct Numeric {
3105 // ConvertAction used for reading.
3106 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
3107 {
3108 // The difference with ConvertAction is that we can modify the start
3109 // iterator and skip the copy. We also never have an offset.
3110
3112 Next_t next = loopconfig->fNext;
3113
3114 void *iter = start;
3115 void *addr;
3116 while( (addr = next(iter,end)) ) {
3117 To *x = (To*)(addr);
3118 *x = (To)(*items);
3119 ++items;
3120 }
3121 }
3122 // ConvertAction used for writing.
3123 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */, To *items)
3124 {
3125 // The difference with ConvertAction is that we can modify the start
3126 // iterator and skip the copy. We also never have an offset.
3127
3129 Next_t next = loopconfig->fNext;
3130
3131 void *iter = start;
3132 void *addr;
3133 while( (addr = next(iter,end)) ) {
3134 From *x = (From*)(addr);
3135 *items = (To)*x;
3136 ++items;
3137 }
3138 }
3139 };
3140
3141 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
3143 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3144 {
3145 // Simple conversion from a 'From' on disk to a 'To' in memory.
3146
3149 Int_t nvalues = proxy->Size();
3150
3151 From *items = new From[nvalues];
3153 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3154 delete [] items;
3155 return 0;
3156 }
3157 };
3158
3159 template <typename To>
3161 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3162 {
3163 // Simple conversion from a 'From' on disk to a 'To' in memory.
3164
3167 Int_t nvalues = proxy->Size();
3168
3171
3172 const Int_t offset = config->fOffset;
3173 Next_t next = loopconfig->fNext;
3174
3176 void *iter = loopconfig->fCopyIterator(&iterator,start);
3177 void *addr;
3178 while( (addr = next(iter,end)) ) {
3179 buf >> (*items);
3180 if (((*items) & kIsReferenced) != 0) {
3181 HandleReferencedTObject(buf, addr, config);
3182 }
3183 To *x = (To*)( ((char*)addr) + offset );
3184 *x = (To)(*items);
3185 ++items;
3186 }
3187 if (iter != &iterator[0]) {
3188 loopconfig->fDeleteIterator(iter);
3189 }
3190
3191 delete [] items_storage;
3192 return 0;
3193 }
3194 };
3195
3196 template <typename From, typename To, template <typename F, typename T> class Converter >
3198 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3199 {
3200 // Simple conversion from a 'From' on disk to a 'To' in memory.
3201
3204 Int_t nvalues = proxy->Size();
3205
3207
3208 From *items = new From[nvalues];
3209 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
3210 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3211 delete [] items;
3212 return 0;
3213 }
3214 };
3215
3216 template <typename From, typename To, template <typename F, typename T> class Converter >
3218 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3219 {
3220 // Simple conversion from a 'From' on disk to a 'To' in memory.
3221
3224 Int_t nvalues = proxy->Size();
3225
3227
3228 From *items = new From[nvalues];
3230 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3231 delete [] items;
3232 return 0;
3233 }
3234 };
3235
3236 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter = Generic >
3238 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3239 {
3240 // Simple conversion from a 'From' on disk to a 'To' in memory.
3241
3244 Int_t nvalues = proxy->Size();
3245
3246 Onfile *items = new Onfile[nvalues];
3247 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3249 delete [] items;
3250 return 0;
3251 }
3252 };
3253
3254 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3256 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3257 {
3258 // Simple conversion from a 'From' on disk to a 'To' in memory.
3259
3262 Int_t nvalues = proxy->Size();
3263
3265
3266 Onfile *items = new Onfile[nvalues];
3267 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3268 R__ASSERT(false && "Not yet implemented");
3269 (void)conf;
3270 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3271 delete [] items;
3272 return 0;
3273 }
3274 };
3275
3276 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3278 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3279 {
3280 // Simple conversion from a 'From' on disk to a 'To' in memory.
3281
3284 Int_t nvalues = proxy->Size();
3285
3287
3288 Onfile *items = new Onfile[nvalues];
3289 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3290 R__ASSERT(false && "Not yet implemented");
3291 (void)conf;
3292 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3293 delete [] items;
3294 return 0;
3295 }
3296 };
3297
3298 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3299 {
3300 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3301 // punt.
3302
3303 return GenericRead(buf,start,end,loopconfig, config);
3304 }
3305
3306 static INLINE_TEMPLATE_ARGS Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3307 {
3308 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3309 // punt.
3310
3311 return GenericWrite(buf,start,end,loopconfig, config);
3312 }
3313
3314 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3315 {
3318 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
3319 }
3320
3321 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3322 {
3325 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
3326 }
3327
3328 template <typename T>
3330 {
3331 buf >> *(T*)addr;
3332 }
3333
3335 {
3336 buf.ReadWithNbits((float*)addr,12);
3337 }
3338
3340 {
3341 buf.WriteFloat16((float*)addr, nullptr);
3342 }
3343
3345 {
3346 //we read a float and convert it to double
3348 buf >> afloat;
3349 *(double*)addr = (Double_t)afloat;
3350 }
3351
3353 {
3354 //we read a float and convert it to double
3355 Float_t afloat = (Float_t)*(double*)addr;
3356 buf << afloat;
3357 }
3358
3359 template <typename ActionHolder>
3361 {
3362 // Collection of numbers. Memberwise or not, it is all the same.
3363
3364 TConfigSTL *config = (TConfigSTL*)conf;
3365 UInt_t start, count;
3366 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
3367
3368 TClass *newClass = config->fNewClass;
3369 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3371
3372 Int_t nvalues;
3373 buf.ReadInt(nvalues);
3374 void* alternative = newProxy->Allocate(nvalues,true);
3375 if (nvalues) {
3378 void *begin = &(startbuf[0]);
3379 void *end = &(endbuf[0]);
3380 config->fCreateIterators(alternative, &begin, &end, newProxy);
3381 // We can not get here with a split vector of pointer, so we can indeed assume
3382 // that actions->fConfiguration != null.
3383
3385 ActionHolder::Action(buf,begin,end,&loopconf,config);
3386
3387 if (begin != &(startbuf[0])) {
3388 // assert(end != endbuf);
3389 config->fDeleteTwoIterators(begin,end);
3390 }
3391 }
3392 newProxy->Commit(alternative);
3393
3394 buf.CheckByteCount(start,count,config->fTypeName);
3395 return 0;
3396 }
3397
3398 template <typename ActionHolder>
3400 {
3401 // Collection of numbers. Memberwise or not, it is all the same.
3402
3403 TConfigSTL *config = (TConfigSTL*)conf;
3404 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
3405
3406 TClass *newClass = config->fNewClass;
3407 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3408 void *collection = ((char*)addr)+config->fOffset;
3410
3411 Int_t nvalues = newProxy->Size();
3412 buf.WriteInt(nvalues);
3413 if (nvalues) {
3416 void *begin = &(startbuf[0]);
3417 void *end = &(endbuf[0]);
3418 config->fCreateIterators(collection, &begin, &end, newProxy);
3419 // We can not get here with a split vector of pointer, so we can indeed assume
3420 // that actions->fConfiguration != null.
3421
3423 ActionHolder::Action(buf,begin,end,&loopconf,config);
3424
3425 if (begin != &(startbuf[0])) {
3426 // assert(end != endbuf);
3427 config->fDeleteTwoIterators(begin,end);
3428 }
3429 }
3430
3431 buf.SetByteCount(start);
3432 return 0;
3433 }
3434
3439
3444
3446 {
3448 // Could also use:
3449 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
3450 }
3451
3453 {
3455 // Could also use:
3456 // return ReadNumericalCollection<WriteConvertBasicType<NoFactorMarker<double>, double, Numeric > >(buf,addr,conf);
3457 }
3458
3459 template <typename T>
3461 {
3462 //TODO: Check whether we can implement this without loading the data in
3463 // a temporary variable and whether this is noticeably faster.
3465 }
3466
3467 template <typename T>
3469 {
3470 //TODO: Check whether we can implement this without loading the data in
3471 // a temporary variable and whether this is noticeably faster.
3473 }
3474
3475 template <typename From, typename To>
3478 {
3479 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3481 }
3482 };
3483
3484 template <typename Memory, typename Onfile>
3487 {
3488 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3490 }
3491 };
3492 };
3493}
3494
3495// Used in GetCollectionReadAction for the kConv cases within a collection
3496// Not to be confused with GetConvertCollectionReadAction
3497template <typename Looper, typename From>
3499{
3500 switch (newtype) {
3517 default:
3518 return TConfiguredAction( Looper::GenericRead, conf );
3519 }
3520 R__ASSERT(0); // We should never be here
3521 return TConfiguredAction();
3522}
3523
3524template <class Looper>
3526{
3527 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
3528
3529 switch (type) {
3530 // Read basic types.
3531
3532 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
3533 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<bool,bool>::Action, conf );
3546 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
3549 delete conf;
3550 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
3551 // if (element->GetFactor() != 0) {
3552 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3553 // } else {
3554 // Int_t nbits = (Int_t)element->GetXmin();
3555 // if (!nbits) nbits = 12;
3556 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3557 // }
3558 }
3561 delete conf;
3562 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
3563 // if (element->GetFactor() != 0) {
3564 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3565 // } else {
3566 // Int_t nbits = (Int_t)element->GetXmin();
3567 // if (!nbits) {
3568 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
3569 // } else {
3570 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3571 // }
3572 // }
3573 }
3574 }
3575 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
3576 R__ASSERT(0); // We should never be here
3577 return TConfiguredAction();
3578}
3579
3580template <typename Looper, typename From>
3582{
3583 switch (newtype) {
3584 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf );
3585 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf );
3586 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf );
3587 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf );
3588 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf );
3589 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf );
3590 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3591 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3592 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3593 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3594 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf );
3595 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf );
3596 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3597 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf );
3598 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3599 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3600 default:
3601 break;
3602 }
3603 Error("GetConvertCollectionReadActionFrom", "UNEXPECTED: newtype == %d", newtype);
3604 R__ASSERT(0); // We should never be here
3605 return TConfiguredAction();
3606}
3607
3608// Used in AddReadAction to implement the kSTL cases
3609// Not to be confused with GetCollectionReadConvertAction
3610// nor with GetConvertCollectionReadActionFrom (used to implement this function)
3611template <typename Looper>
3613{
3614 switch (oldtype) {
3646 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
3647 break;
3648 default:
3649 break;
3650 }
3651 Error("GetConvertCollectionReadAction", "UNEXPECTED: oldtype == %d", oldtype);
3652 R__ASSERT(0); // We should never be here
3653 return TConfiguredAction();
3654}
3655
3656template <class Looper>
3657static TConfiguredAction
3660{
3661 switch (type) {
3662 // Read basic types.
3678 if (element->GetFactor() != 0) {
3679 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3680 } else {
3681 Int_t nbits = (Int_t)element->GetXmin();
3682 if (!nbits) nbits = 12;
3683 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3684 }
3685 }
3687 if (element->GetFactor() != 0) {
3688 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3689 } else {
3690 Int_t nbits = (Int_t)element->GetXmin();
3691 if (!nbits) {
3692 return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
3693 } else {
3694 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3695 }
3696 }
3697 }
3700 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3701 // Streamer alltogether.
3709 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3710 case TStreamerInfo::kBase: {
3711 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3712 if (baseEl) {
3713 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
3715 auto baseActions = Looper::CreateReadActionSequence(*baseinfo, loopConfig);
3716 baseActions->AddToOffset(baseEl->GetOffset());
3717 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
3718
3719 } else
3720 return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info, i, compinfo) );
3721 }
3724 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
3725 return TConfiguredAction(Looper::template ReadStreamerLoop<false>::Action,
3727 }
3729 if (info->GetOldVersion() >= 3)
3730 return TConfiguredAction( Looper::ReadStreamerCase, new TGenericConfiguration(info, i, compinfo) );
3731 else
3732 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3734 if (compinfo->fStreamer)
3736 else {
3737 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
3739 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
3740 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
3742 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
3743 else // Use the slower path for unusual cases
3744 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3745 }
3746
3747 // Conversions.
3777 if (element->GetFactor() != 0) {
3779 } else {
3780 Int_t nbits = (Int_t)element->GetXmin();
3781 if (!nbits) nbits = 12;
3783 }
3784 }
3786 if (element->GetFactor() != 0) {
3788 } else {
3789 Int_t nbits = (Int_t)element->GetXmin();
3790 if (!nbits) {
3792 } else {
3794 }
3795 }
3796 }
3797 default:
3798 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
3799 }
3800 R__ASSERT(0); // We should never be here
3801 return TConfiguredAction();
3802}
3803
3804template <typename Looper, typename From>
3806{
3807 switch (onfileType) {
3808 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,bool>::Action, conf );
3809 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,char>::Action, conf );
3810 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,short>::Action, conf );
3811 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Int_t>::Action, conf );
3812 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long_t>::Action, conf );
3813 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long64_t>::Action, conf );
3814 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,float>::Action, conf );
3815 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,double>::Action, conf );
3816 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UChar_t>::Action, conf );
3817 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UShort_t>::Action, conf );
3818 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3819 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong_t>::Action, conf );
3820 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3821 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3822
3823 // Supporting this requires adding TBuffer::WiteFastArrayWithNbits
3824 // and the proper struct WriteConvertCollectionBasicType<Memory, NoFactorMarker<Onfile>> here
3826 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Float16_t not yet supported");
3827 return TConfiguredAction();
3828 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Float16_t>>::Action, conf );
3830 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Double32_t not yet supported");
3831 return TConfiguredAction();
3832 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Double32_t>>::Action, conf );
3833 default:
3834 break;
3835 }
3836 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: onfileType/oldtype == %d", onfileType);
3837 R__ASSERT(0); // We should never be here
3838 return TConfiguredAction();
3839}
3840
3841// Used in to implement the kSTL case
3842// Not to be confused with GetCollectionWriteConvertAction
3843// nor with GetConvertCollectionWriteActionFrom (used to implement this function)
3844template <typename Looper>
3846{
3847 switch (memoryType) {
3879 Error("GetConvertCollectionWriteActionFrom","There is no support for kBits outside of a TObject.");
3880 break;
3881 default:
3882 break;
3883 }
3884 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: memoryType/newype == %d", memoryType);
3885 R__ASSERT(0); // We should never be here
3886 return TConfiguredAction();
3887}
3888
3889// Used in GetCollectionWriteAction for the kConv cases within a collection
3890// Not to be confused with GetConvertCollectionWriteAction
3891// Note the read and write version could be merged (using yet another template parameter)
3892template <typename Looper, typename Onfile>
3894{
3895 switch (newtype) {
3912 default:
3913 return TConfiguredAction( Looper::GenericRead, conf );
3914 }
3915 R__ASSERT(0); // We should never be here
3916 return TConfiguredAction();
3917}
3918
3919template <class Looper>
3920static TConfiguredAction
3923{
3924 switch (type) {
3925 // write basic types
3939 // the simple type missing are kBits and kCounter.
3940
3941 // Handling of the error case where we are asked to write a missing data member.
3943 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Bool_t>>, new TConfiguration(info,i,compinfo,offset) );
3945 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Char_t>>, new TConfiguration(info,i,compinfo,offset) );
3947 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Short_t>>, new TConfiguration(info,i,compinfo,offset) );
3949 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Int_t>>, new TConfiguration(info,i,compinfo,offset) );
3951 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long_t>>, new TConfiguration(info,i,compinfo,offset) );
3953 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long64_t>>, new TConfiguration(info,i,compinfo,offset) );
3955 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Float_t>>, new TConfiguration(info,i,compinfo,offset) );
3957 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Double_t>>, new TConfiguration(info,i,compinfo,offset) );
3959 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UChar_t>>, new TConfiguration(info,i,compinfo,offset) );
3961 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UShort_t>>, new TConfiguration(info,i,compinfo,offset) );
3963 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UInt_t>>, new TConfiguration(info,i,compinfo,offset) );
3965 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong_t>>, new TConfiguration(info,i,compinfo,offset) );
3967 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong64_t>>, new TConfiguration(info,i,compinfo,offset) );
3968
3969 // Conversions.
3996#ifdef NOT_YET
3997 /* The conversion writing acceleration was not yet written for kBits */
4000#endif
4002 if (element->GetFactor() != 0) {
4004 } else {
4005 Int_t nbits = (Int_t)element->GetXmin();
4006 if (!nbits) nbits = 12;
4008 }
4009 break;
4010 }
4012 if (element->GetFactor() != 0) {
4014 } else {
4015 Int_t nbits = (Int_t)element->GetXmin();
4016 if (!nbits) {
4018 } else {
4020 }
4021 }
4022 break;
4023 }
4025 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4026 // Streamer alltogether.
4029 case TStreamerInfo::kBase: {
4030 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
4031 if (baseEl) {
4032 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
4034 auto baseActions = Looper::CreateWriteActionSequence(*baseinfo, loopConfig);
4035 baseActions->AddToOffset(baseEl->GetOffset());
4036 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
4037
4038 } else
4039 return TConfiguredAction( Looper::WriteBase, new TGenericConfiguration(info, i, compinfo) );
4040 }
4043 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4044 return TConfiguredAction(Looper::template WriteStreamerLoop<false>::Action,
4046 }
4048 if (info->GetOldVersion() >= 3)
4049 return TConfiguredAction( Looper::WriteStreamerCase, new TGenericConfiguration(info, i, compinfo) );
4050 else
4051 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4053 if (compinfo->fStreamer)
4055 else {
4056 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4058 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4059 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4061 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4062 else // Use the slower path for unusual cases
4063 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4064 }
4065 default:
4066 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
4067 }
4068 R__ASSERT(0); // We should never be here
4069 return TConfiguredAction();
4070}
4071
4072template <class Looper>
4074{
4075 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
4076
4077 switch (type) {
4078 // Write basic types.
4079 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
4080 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<bool,bool>::Action, conf );
4093 case TStreamerInfo::kBits: Error("GetNumericCollectionWriteAction","There is no support for kBits outside of a TObject."); break;
4096 delete conf;
4097 return TConfiguredAction( Looper::WriteCollectionFloat16, alternate );
4098 // if (element->GetFactor() != 0) {
4099 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4100 // } else {
4101 // Int_t nbits = (Int_t)element->GetXmin();
4102 // if (!nbits) nbits = 12;
4103 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4104 // }
4105 }
4108 delete conf;
4109 return TConfiguredAction( Looper::WriteCollectionDouble32, alternate );
4110 // if (element->GetFactor() != 0) {
4111 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4112 // } else {
4113 // Int_t nbits = (Int_t)element->GetXmin();
4114 // if (!nbits) {
4115 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4116 // } else {
4117 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4118 // }
4119 // }
4120 }
4121 }
4122 Fatal("GetNumericCollectionWriteAction","Is confused about %d",type);
4123 R__ASSERT(0); // We should never be here
4124 return TConfiguredAction();
4125}
4126
4127////////////////////////////////////////////////////////////////////////////////
4128/// loop on the TStreamerElement list
4129/// regroup members with same type
4130/// Store predigested information into local arrays. This saves a huge amount
4131/// of time compared to an explicit iteration on all elements.
4132
4134{
4135 if (IsCompiled()) {
4136 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
4137 return;
4138 }
4140
4141 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
4142
4143 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
4145 fNdata = 0;
4146 fNfulldata = 0;
4147
4148 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
4149 if (fNumber < 0) {
4150 ++fgCount;
4151 fNumber = fgCount;
4152 }
4153 if (fNumber >= infos->GetSize()) {
4154 infos->AddAtAndExpand(this, fNumber);
4155 } else {
4156 if (!infos->At(fNumber)) {
4157 infos->AddAt(this, fNumber);
4158 }
4159 }
4160
4161 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
4162
4163
4165
4166
4169
4172
4175
4176 if (fReadText) fReadText->fActions.clear();
4178
4181
4184
4187
4188 if (fWriteText) fWriteText->fActions.clear();
4190
4191 if (!ndata) {
4192 // This may be the case for empty classes (e.g., TAtt3D).
4193 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
4195 fSize = sizeof(TStreamerInfo*);
4196 }
4197 fComp = new TCompInfo[1];
4198 fCompFull = new TCompInfo*[1];
4199 fCompOpt = new TCompInfo*[1];
4200 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
4201 SetIsCompiled();
4202 return;
4203 }
4204
4205 // At most half of the elements can be used to hold optimized versions.
4206 // We use the bottom to hold the optimized-into elements and the non-optimized elements
4207 // and the top to hold the original copy of the optimized out elements.
4208 fNslots = ndata + ndata/2 + 1;
4209 Int_t optiOut = 0;
4210
4211 fComp = new TCompInfo[fNslots];
4212 fCompFull = new TCompInfo*[ndata];
4213 fCompOpt = new TCompInfo*[ndata];
4214
4217 Int_t keep = -1;
4218 Int_t i;
4219
4220 if (!CanOptimize()) {
4222 }
4223
4226
4227 for (i = 0; i < ndata; ++i) {
4229 if (!element) {
4230 break;
4231 }
4232
4233 Int_t asize = element->GetSize();
4234 if (element->GetArrayLength()) {
4235 asize /= element->GetArrayLength();
4236 }
4237 fComp[fNdata].fType = element->GetType();
4238 fComp[fNdata].fNewType = element->GetNewType();
4239 fComp[fNdata].fOffset = element->GetOffset();
4240 fComp[fNdata].fLength = element->GetArrayLength();
4242 fComp[fNdata].fMethod = element->GetMethod();
4243 fComp[fNdata].fClass = element->GetClassPointer();
4244 fComp[fNdata].fNewClass = element->GetNewClass();
4246 fComp[fNdata].fStreamer = element->GetStreamer();
4247
4248 // try to group consecutive members of the same type
4250 && (keep >= 0)
4251 && (element->GetType() > 0)
4252 && (element->GetType() < 10)
4254 && (fComp[keep].fMethod == 0)
4255 && (element->GetArrayDim() == 0)
4256 && (fComp[keep].fType < kObject)
4257 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
4258 && (element->GetType() == (fComp[keep].fType%kRegrouped))
4259 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
4260 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
4261 ((element->GetFactor() == previous->GetFactor())
4262 && (element->GetXmin() == previous->GetXmin())
4263 && (element->GetXmax() == previous->GetXmax())
4264 )
4265 )
4268 // kWholeObject and kDoNotDelete do not apply to numerical elements.
4269 )
4270 {
4271 if (!previousOptimized) {
4272 // The element was not yet optimized we first need to copy it into
4273 // the set of original copies.
4274 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
4275 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
4276 }
4277 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
4279
4280 R__ASSERT( keep < (fNslots - optiOut) );
4281
4282 if (fComp[keep].fLength == 0) {
4283 fComp[keep].fLength++;
4284 }
4285 fComp[keep].fLength++;
4286 fComp[keep].fType = element->GetType() + kRegrouped;
4289 } else if (element->GetType() < 0) {
4290
4291 // -- Deal with an ignored TObject base class.
4292 // Note: The only allowed negative value here is -1,
4293 // and signifies that Build() has found a TObject
4294 // base class and TClass::IgnoreTObjectStreamer() was
4295 // called. In this case the compiled version of the
4296 // elements omits the TObject base class element,
4297 // which has to be compensated for by TTree::Bronch()
4298 // when it is making branches for a split object.
4299 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
4301 keep = -1;
4303
4304 } else {
4305 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
4306 if (fComp[fNdata].fNewType > 0) {
4307 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
4308 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
4309 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
4313 ) {
4315 } else if (fComp[fNdata].fType != kCounter) {
4316 fComp[fNdata].fType += kConv;
4317 }
4318 } else {
4319 if (fComp[fNdata].fType == kCounter) {
4320 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
4321 }
4322 fComp[fNdata].fType += kSkip;
4323 }
4324 }
4325 fCompOpt[fNdata] = &(fComp[fNdata]);
4327
4329
4330 keep = fNdata;
4331 if (fComp[keep].fLength == 0) {
4332 fComp[keep].fLength = 1;
4333 }
4334 fNdata++;
4336 }
4337 // The test 'fMethod[keep] == 0' fails to detect a variable size array
4338 // if the counter happens to have an offset of zero, so let's explicitly
4339 // prevent for here.
4340 if (element->HasCounter()) keep = -1;
4341 ++fNfulldata;
4342 previous = element;
4343 }
4344
4345 for (i = 0; i < fNdata; ++i) {
4346 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
4347 continue;
4348 }
4351 }
4352 for (i = 0; i < fNfulldata; ++i) {
4353 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
4354 continue;
4355 }
4360
4363 }
4364 ComputeSize();
4365
4367 SetIsCompiled();
4368
4369 if (gDebug > 0) {
4370 ls();
4371 }
4372}
4373
4374template <typename From>
4376{
4377 switch (newtype) {
4394 }
4395}
4396
4397template <typename Onfile>
4399{
4400 // When writing 'newtype' is the origin of the information (i.e. the in memory representation)
4401 // and the template parameter `To` is the representation on disk
4402 switch (newtype) {
4419 }
4420}
4421
4422////////////////////////////////////////////////////////////////////////////////
4423/// Add a read action for the given element.
4424
4426{
4428
4429 if (element->TestBit(TStreamerElement::kWrite)) return;
4430
4431 switch (compinfo->fType) {
4432 // read basic types
4433 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4434 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4435 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4436 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4437 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4438 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4439 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4440 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4441 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4442 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4443 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4444 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4445 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4446 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4448 if (element->GetFactor() != 0) {
4449 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4450 } else {
4451 Int_t nbits = (Int_t)element->GetXmin();
4452 if (!nbits) nbits = 12;
4454 }
4455 break;
4456 }
4458 if (element->GetFactor() != 0) {
4459 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4460 } else {
4461 Int_t nbits = (Int_t)element->GetXmin();
4462 if (!nbits) {
4464 } else {
4466 }
4467 }
4468 break;
4469 }
4470 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4471 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4472 // Streamer alltogether.
4473 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4474 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4475 case TStreamerInfo::kSTL: {
4476 TClass *newClass = element->GetNewClass();
4477 TClass *oldClass = element->GetClassPointer();
4478 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4479
4480 if (element->GetArrayLength() <= 1) {
4481 if (fOldVersion<3){ // case of old TStreamerInfo
4482 if (newClass && newClass != oldClass) {
4483 if (element->GetStreamer()) {
4484 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4485 } else {
4487 }
4488 } else {
4489 if (element->GetStreamer()) {
4490 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4491 } else {
4493 }
4494 }
4495 } else {
4496 if (newClass && newClass != oldClass) {
4497 if (element->GetStreamer()) {
4498 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4499 } else if (oldClass) {
4500 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4502 } else {
4503 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4504 case kVectorLooper:
4505 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)));
4506 break;
4507 case kAssociativeLooper:
4508 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)));
4509 break;
4510 case kVectorPtrLooper:
4511 case kGenericLooper:
4512 default:
4513 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4514 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)));
4515 break;
4516 }
4517 }
4518 }
4519 } else {
4520 if (element->GetStreamer()) {
4521 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4522 } else if (oldClass) {
4523 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4524 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
4525 } else {
4526 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
4527 case kVectorLooper:
4528 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4529 break;
4530 case kAssociativeLooper:
4531 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4532 break;
4533 case kVectorPtrLooper:
4534 case kGenericLooper:
4535 default:
4536 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4537 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4538 break;
4539 }
4540 }
4541 }
4542 }
4543 }
4544 } else {
4545 if (fOldVersion<3){ // case of old TStreamerInfo
4546 if (newClass && newClass != oldClass) {
4547 if (element->GetStreamer()) {
4548 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4549 } else {
4550 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4551 }
4552 } else {
4553 if (element->GetStreamer()) {
4554 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4555 } else {
4556 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4557 }
4558 }
4559 } else {
4560 if (newClass && newClass != oldClass) {
4561 if (element->GetStreamer()) {
4562 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4563 } else {
4564 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4565 }
4566 } else {
4567 if (element->GetStreamer()) {
4568 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4569 } else {
4570 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4571 }
4572 }
4573 }
4574 }
4575 break;
4576 }
4577
4580 break;
4583 break;
4586 break;
4589 break;
4592 break;
4595 break;
4598 break;
4601 break;
4604 break;
4607 break;
4610 break;
4613 break;
4616 break;
4619 break;
4621 if (element->GetFactor() != 0) {
4622 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4623 } else {
4624 Int_t nbits = (Int_t)element->GetXmin();
4625 if (!nbits) nbits = 12;
4627 }
4628 break;
4629 }
4631 if (element->GetFactor() != 0) {
4632 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4633 } else {
4634 Int_t nbits = (Int_t)element->GetXmin();
4635 if (!nbits) {
4637 } else {
4639 }
4640 }
4641 break;
4642 }
4645 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4646 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<false>::Action,
4647 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4648 break;
4649 }
4651 if (compinfo->fStreamer)
4652 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4653 else {
4654 auto base = dynamic_cast<TStreamerBase*>(element);
4655 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4656 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4657
4658 if(!base || !memoryBaseCl ||
4659 memoryBaseCl->GetStreamer() ||
4660 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4661 {
4662 // Unusual Case.
4664 }
4665 else
4666 readSequence->AddAction( ReadViaClassBuffer,
4667 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4668 }
4669 break;
4671 if (fOldVersion >= 3)
4672 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4673 else
4674 // Use the slower path for legacy files
4676 break;
4678 if (compinfo->fStreamer)
4679 readSequence->AddAction( ReadViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
4680 else {
4681 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4682 readSequence->AddAction( ReadViaClassBuffer,
4683 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4684 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4685 readSequence->AddAction( ReadViaClassBuffer,
4686 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4687 else // Use the slower path for unusual cases
4688 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this, i, compinfo) );
4689 }
4690 break;
4691 default:
4693 break;
4694 }
4695 if (element->TestBit(TStreamerElement::kCache)) {
4696 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
4697 readSequence->fActions.pop_back();
4699 }
4700}
4701
4702////////////////////////////////////////////////////////////////////////////////
4703/// Add a read text action for the given element.
4704
4706{
4708
4709 if (element->TestBit(TStreamerElement::kWrite))
4710 return;
4711
4712 Bool_t generic = kFALSE, isBase = kFALSE;
4713
4714 switch (compinfo->fType) {
4716 if (element->IsBase())
4717 isBase = kTRUE;
4718 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4719 else
4720 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4721 break;
4722
4724 if (element->IsBase())
4725 isBase = kTRUE;
4726 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
4727 else
4728 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4729 break;
4730
4731 case TStreamerInfo::kObject: // Class derived from TObject
4732 case TStreamerInfo::kAny: // Class NOT derived from TObject
4735 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4736 break;
4737
4738 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
4740 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
4741 readSequence->AddAction(TextReadSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4742 break;
4743
4746 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4747 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<true>::Action,
4748 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4749 break;
4750 }
4751 case TStreamerInfo::kBase: isBase = kTRUE; break;
4752
4755 break;
4756
4757 default: generic = kTRUE; break;
4758 }
4759
4760 if (isBase) {
4761 if (compinfo->fStreamer) {
4763 } else {
4765 }
4766 } else if (generic)
4768}
4769
4770////////////////////////////////////////////////////////////////////////////////
4771/// Add a read action for the given element.
4772/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
4773
4787
4788////////////////////////////////////////////////////////////////////////////////
4789
4791{
4794 // Skip element cached for reading purposes.
4795 return;
4796 }
4797 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
4798 // Skip artificial element used for reading purposes.
4799 return;
4800 }
4801 switch (compinfo->fType) {
4802 // write basic types
4803 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4804 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4805 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4806 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4807 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4808 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4809 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4810 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4811 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4812 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4813 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4814 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4815 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4816
4819 break;
4822 break;
4825 break;
4828 break;
4831 break;
4834 break;
4837 break;
4840 break;
4843 break;
4846 break;
4847
4848 case kSTL:
4849 {
4850 TClass *newClass = element->GetNewClass();
4851 TClass *onfileClass = element->GetClassPointer();
4852 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4853
4854 if (element->GetArrayLength() <= 1) {
4855 if (newClass && newClass != onfileClass) {
4856 if (element->GetStreamer()) {
4858 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4859 newClass, element->GetStreamer(), element->GetTypeName(),
4860 isSTLbase));
4861 } else if (onfileClass) {
4862 if (onfileClass->GetCollectionProxy() == 0 || onfileClass->GetCollectionProxy()->GetValueClass() ||
4863 onfileClass->GetCollectionProxy()->HasPointers()) {
4864 writeSequence->AddAction(
4866 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4867 element->GetTypeName(), isSTLbase));
4868 } else {
4869 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4870 case kVectorLooper:
4872 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4873 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4874 element->GetTypeName(), isSTLbase)));
4875 break;
4876 case kAssociativeLooper:
4878 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4879 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4880 element->GetTypeName(), isSTLbase)));
4881 break;
4882 case kVectorPtrLooper:
4883 case kGenericLooper:
4884 default:
4885 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4886 // real thing.
4888 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4889 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4890 element->GetTypeName(), isSTLbase)));
4891 break;
4892 }
4893 }
4894 }
4895 } else {
4896 if (element->GetStreamer()) {
4898 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4899 element->GetStreamer(), element->GetTypeName(),
4900 isSTLbase));
4901 } else if (onfileClass) {
4902 if (onfileClass->GetCollectionProxy() == 0 ||
4903 onfileClass->GetCollectionProxy()->GetValueClass() ||
4904 onfileClass->GetCollectionProxy()->HasPointers()) {
4906 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4907 element->GetTypeName(), isSTLbase));
4908 } else {
4909 switch (SelectLooper(*onfileClass->GetCollectionProxy())) {
4910 case kVectorLooper:
4912 onfileClass->GetCollectionProxy()->GetType(),
4913 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4914 isSTLbase)));
4915 break;
4916 case kAssociativeLooper:
4918 onfileClass->GetCollectionProxy()->GetType(),
4919 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4920 isSTLbase)));
4921 break;
4922 case kVectorPtrLooper:
4923 case kGenericLooper:
4924 default:
4925 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4926 // real thing.
4928 onfileClass->GetCollectionProxy()->GetType(),
4929 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4930 isSTLbase)));
4931 break;
4932 }
4933 }
4934 }
4935 }
4936 } else {
4937 if (newClass && newClass != onfileClass) {
4938 if (element->GetStreamer()) {
4939 writeSequence->AddAction(
4941 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4942 newClass, element->GetStreamer(), element->GetTypeName(), isSTLbase));
4943 } else {
4944 writeSequence->AddAction(
4946 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4947 newClass, element->GetTypeName(), isSTLbase));
4948 }
4949 } else {
4950 if (element->GetStreamer()) {
4952 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4953 element->GetArrayLength(), onfileClass,
4954 element->GetStreamer(), element->GetTypeName(), isSTLbase));
4955 } else {
4957 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4958 element->GetArrayLength(), onfileClass,
4959 element->GetTypeName(), isSTLbase));
4960 }
4961 }
4962 }
4963 break;
4964 }
4965
4966 case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4967 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4968 // Streamer alltogether.
4969 case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4970 case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4971
4974 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4975 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<false>::Action,
4976 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4977 break;
4978 }
4980 if (compinfo->fStreamer)
4981 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4982 else {
4983 auto base = dynamic_cast<TStreamerBase*>(element);
4984 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4985 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4986
4987 if(!base || !memoryBaseCl ||
4988 memoryBaseCl->GetStreamer() ||
4989 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4990 {
4991 // Unusual Case.
4993 }
4994 else {
4996 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4997 }
4998 }
4999 break;
5001 if (fOldVersion >= 3)
5002 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
5003 else
5004 // Use the slower path for legacy files
5006 break;
5008 if (compinfo->fStreamer)
5009 writeSequence->AddAction( WriteViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
5010 else {
5011 if (compinfo->fNewClass && compinfo->fNewClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5013 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
5014 else if (compinfo->fClass && compinfo->fClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5016 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
5017 else // Use the slower path for unusual cases
5019 }
5020 break;
5021
5022 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
5023 /*case TStreamerInfo::kFloat16: {
5024 if (element->GetFactor() != 0) {
5025 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5026 } else {
5027 Int_t nbits = (Int_t)element->GetXmin();
5028 if (!nbits) nbits = 12;
5029 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5030 }
5031 break;
5032 } */
5033 /*case TStreamerInfo::kDouble32: {
5034 if (element->GetFactor() != 0) {
5035 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5036 } else {
5037 Int_t nbits = (Int_t)element->GetXmin();
5038 if (!nbits) {
5039 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
5040 } else {
5041 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5042 }
5043 }
5044 break;
5045 } */
5046 default:
5048 break;
5049 }
5050}
5051
5052////////////////////////////////////////////////////////////////////////////////
5053
5055{
5058 // Skip element cached for reading purposes.
5059 return;
5060 }
5061 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5062 // Skip artificial element used for reading purposes.
5063 return;
5064 }
5065
5066 Bool_t generic = kFALSE, isBase = kFALSE;
5067
5068 switch (compinfo->fType) {
5069 // write basic types
5095 // Actually same action for this level
5097 break;
5098
5100 if (element->IsBase())
5101 isBase = kTRUE;
5102 else
5103 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5104 break;
5105
5107 if (element->IsBase())
5108 isBase = kTRUE;
5109 else
5110 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5111 break;
5112
5113 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
5115 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
5116 writeSequence->AddAction(TextWriteSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5117 break;
5118
5121 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
5122 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<true>::Action, new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
5123 break;
5124 }
5125 case TStreamerInfo::kBase: isBase = kTRUE; break;
5126
5129 break;
5130
5131 default: generic = kTRUE; break;
5132 }
5133
5134 if (isBase) {
5135 if (compinfo->fStreamer) {
5137 } else {
5139 }
5140
5141 } else
5142
5143 // use generic write action when special handling is not provided
5144 if (generic)
5146}
5147
5148////////////////////////////////////////////////////////////////////////////////
5149/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
5150
5152{
5155 // Skip element cached for reading purposes.
5156 return;
5157 }
5158 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5159 // Skip artificial element used for reading purposes.
5160 return;
5161 }
5162 writeSequence->AddAction( GetCollectionWriteAction<VectorPtrLooper>(this,nullptr,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
5163}
5164
5165////////////////////////////////////////////////////////////////////////////////
5166/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5167
5169{
5170 if (info == 0) {
5172 }
5173
5174 TLoopConfiguration *loopConfig = nullptr;
5176 {
5177 if (proxy.HasPointers()) {
5178 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5179 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5180 return sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
5181 }
5182
5183 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5184 Long_t increment = proxy.GetIncrement();
5185 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
5186 } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
5187 || proxy.GetCollectionType() == ROOT::kSTLmultiset || proxy.GetCollectionType() == ROOT::kSTLunorderedmultiset
5188 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap
5189 || proxy.GetCollectionType() == ROOT::kSTLunorderedmap || proxy.GetCollectionType() == ROOT::kSTLunorderedmultimap)
5190 {
5191 Long_t increment = proxy.GetIncrement();
5192 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
5193 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
5194 } else {
5195 loopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
5196 }
5197
5199}
5200
5201////////////////////////////////////////////////////////////////////////////////
5202/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5203
5205{
5206 UInt_t ndata = info.GetElements()->GetEntriesFast();
5208 sequence->fLoopConfig = loopConfig;
5209
5210 for (UInt_t i = 0; i < ndata; ++i) {
5211 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5212 if (!element) {
5213 break;
5214 }
5215 if (element->GetType() < 0) {
5216 // -- Skip an ignored TObject base class.
5217 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5218 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5219 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5220 // when it is making branches for a split object.
5221 continue;
5222 }
5223 if (element->TestBit(TStreamerElement::kWrite)) {
5224 // Skip element that only for writing.
5225 continue;
5226 }
5227 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
5228 if (baseEl) {
5229 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
5230 // There was a problem with the checksum, the user likely did not
5231 // increment the version number of the derived class when the
5232 // base class changed. Since we will be member wise streaming
5233 // this class, let's warn the user that something is wrong.
5234 ::Warning("CreateReadMemberWiseActions","%s",
5235 baseEl->GetErrorMessage());
5237 }
5238 }
5239
5240 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5241 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
5242
5243 Int_t oldType = element->GetType();
5244 Int_t newType = element->GetNewType();
5245
5246 Int_t offset = element->GetOffset();
5247 if (newType != oldType) {
5248 // This 'prevents' the switch from base class (kBase (0)) to
5249 // anything else.
5250 if (newType > 0) {
5253 }
5254 } else {
5256 }
5257 }
5258 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5259 case kAssociativeLooper:
5260// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
5261// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
5262// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(true, info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
5263 case kVectorLooper:
5264 case kVectorPtrLooper:
5265 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5266 if (element->TestBit(TStreamerElement::kCache)) {
5269 } else {
5271 }
5272 break;
5273 case kGenericLooper:
5274 default:
5275 // The usual collection case.
5276 if (element->TestBit(TStreamerElement::kCache)) {
5279 } else {
5281 }
5282 break;
5283 }
5284 }
5285 return sequence;
5286}
5287
5288////////////////////////////////////////////////////////////////////////////////
5289/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5290
5292{
5293 if (info == 0) {
5295 }
5296
5297 TLoopConfiguration *loopConfig = nullptr;
5299 {
5300 if (proxy.HasPointers()) {
5301 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5302 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5303 return sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
5304 }
5305
5306 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5307 Long_t increment = proxy.GetIncrement();
5308 loopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
5309 } else {
5310 loopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
5311 }
5312 return CreateWriteMemberWiseActions(*info, loopConfig);
5313}
5314
5315////////////////////////////////////////////////////////////////////////////////
5316/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the
5317/// collection described by 'proxy' \param loopConfig pointer ownership is taken from the caller and transferred to the
5318/// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return new
5319/// `sequence` pointer of type TActionSequence, the memory ownership is transferred to caller, must delete it later
5320
5322{
5323 UInt_t ndata = info.GetElements()->GetEntriesFast();
5325 sequence->fLoopConfig = loopConfig;
5326
5327 for (UInt_t i = 0; i < ndata; ++i) {
5328 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5329 if (!element) {
5330 break;
5331 }
5332 if (element->GetType() < 0) {
5333 // -- Skip an ignored TObject base class.
5334 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5335 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5336 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5337 // when it is making branches for a split object.
5338 continue;
5339 }
5341 // Skip element cached for reading purposes.
5342 continue;
5343 }
5345 // Skip artificial element used for reading purposes.
5346 continue;
5347 }
5348 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5349 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
5350 Int_t onfileType = element->GetType();
5351 Int_t memoryType = element->GetNewType();
5352 if (memoryType != onfileType) {
5353 // This 'prevents' the switch from base class (kBase (0)) to
5354 // anything else.
5355 if (memoryType > 0) {
5358 }
5359 } else {
5360 // When reading we need to consume the data in the onfile buffer,
5361 // so we do create a 'Skip' action for the missing elements.
5362 // When writing we should probably write a default value, for
5363 // now let's just ignore the request.
5364 // We could issue an error here but we might too often issue a
5365 // 'false positive' if the user only reads.
5366 // FIXME: The 'right' solution is to add a new action that first print
5367 // once the following error message:
5368 //
5369 // info.Error("TActionSequence::CreateWriteMemberWiseActions",
5370 // "Ignoring request to write the missing data member %s in %s version %d checksum 0x%x",
5371 // element->GetName(), info.GetName(), info.GetClassVersion(), info.GetCheckSum());
5372 continue;
5373 //
5374 // Instead of skipping the field we could write a zero there with:
5375 // onfileType += TVirtualStreamerInfo::kSkip;
5376 }
5377 }
5378
5379 Int_t offset = element->GetOffset();
5380 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5381 case kAssociativeLooper:
5383 break;
5384 case kVectorLooper:
5386 break;
5387 case kVectorPtrLooper:
5389 break;
5390 case kGenericLooper:
5391 default:
5393 break;
5394 }
5395 }
5396 return sequence;
5397}
5398
5400{
5401 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5402 // TBranchElement in the case of split sub-object.
5403
5404 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5405 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5406 iter != end;
5407 ++iter)
5408 {
5409 // (fElemId == -1) indications that the action is a Push or Pop DataCache.
5410 if (iter->fConfiguration->fElemId != (UInt_t)-1 &&
5411 !iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5412 iter->fConfiguration->AddToOffset(delta);
5413 }
5414}
5415
5417{
5418 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5419 // TBranchElement in the case of split sub-object.
5420
5421 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5422 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5423 iter != end;
5424 ++iter)
5425 {
5426 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5427 iter->fConfiguration->SetMissing();
5428 }
5429}
5430
5432{
5433 // Create a copy of this sequence.
5434
5435 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, fActions.size(), IsForVectorPtrLooper());
5436
5437 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5438
5439 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5440 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5441 iter != end;
5442 ++iter)
5443 {
5444 TConfiguration *conf = iter->fConfiguration->Copy();
5445 sequence->AddAction( iter->fAction, conf );
5446 }
5447 return sequence;
5448}
5449
5452 Int_t offset,
5454{
5455 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5456 if ( element_ids[id].fElemID < 0 ) {
5457 if (element_ids[id].fNestedIDs) {
5458 auto original = create(element_ids[id].fNestedIDs->fInfo,
5459 sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
5460 nullptr);
5461 if (element_ids[id].fNestedIDs->fOnfileObject) {
5462 auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
5463 if ( sequence->fLoopConfig )
5465 else if ( sequence->IsForVectorPtrLooper() )
5466 sequence->AddAction( PushDataCacheVectorPtr, conf );
5467 else
5468 sequence->AddAction( PushDataCache, conf );
5469 }
5470
5471 original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
5472
5473 if (element_ids[id].fNestedIDs->fOnfileObject) {
5474 auto conf =
5475 new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset);
5476 if ( sequence->fLoopConfig )
5478 else if ( sequence->IsForVectorPtrLooper() )
5479 sequence->AddAction( PopDataCacheVectorPtr, conf );
5480 else
5481 sequence->AddAction( PopDataCache, conf );
5482 }
5483 } else {
5484 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5485 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5486 iter != end;
5487 ++iter)
5488 {
5489 TConfiguration *conf = iter->fConfiguration->Copy();
5490 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5491 conf->AddToOffset(offset);
5492 sequence->AddAction( iter->fAction, conf );
5493 }
5494 }
5495 } else {
5496 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5497 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5498 iter != end;
5499 ++iter) {
5500 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
5501 TConfiguration *conf = iter->fConfiguration->Copy();
5502 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5503 conf->AddToOffset(offset);
5504 sequence->AddAction( iter->fAction, conf );
5505 }
5506 }
5507 }
5508 }
5509}
5510
5513{
5514 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5515 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5516
5517 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5518
5519 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5520
5521 AddToSubSequence(sequence, element_ids, offset, create);
5522
5523 return sequence;
5524}
5525
5527{
5528 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5529 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5530
5531 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5532
5533 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
5534
5535 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5536 if ( element_ids[id] < 0 ) {
5537 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5538 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5539 iter != end;
5540 ++iter)
5541 {
5542 TConfiguration *conf = iter->fConfiguration->Copy();
5543 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5544 conf->AddToOffset(offset);
5545 sequence->AddAction( iter->fAction, conf );
5546 }
5547 } else {
5548 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5549 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5550 iter != end;
5551 ++iter) {
5552 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
5553 TConfiguration *conf = iter->fConfiguration->Copy();
5554 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5555 conf->AddToOffset(offset);
5556 sequence->AddAction( iter->fAction, conf );
5557 }
5558 }
5559 }
5560 }
5561 return sequence;
5562}
5563
5564#if !defined(R__WIN32) && !defined(_AIX)
5565
5566#include <dlfcn.h>
5567
5568#endif
5569
5570typedef void (*voidfunc)();
5571static const char *R__GetSymbolName(voidfunc func)
5572{
5573#if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
5574 return "not available on this platform";
5575#if 0
5577 if (!VirtualQuery (func, &mbi, sizeof (mbi)))
5578 {
5579 return 0;
5580 }
5581
5582 HMODULE hMod = (HMODULE) mbi.AllocationBase;
5583 static char moduleName[MAX_PATH];
5584
5585 if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
5586 {
5587 return 0;
5588 }
5589 return moduleName;
5590#endif
5591#else
5592 Dl_info info;
5593 if (dladdr((void*)func,&info)==0) {
5594 // Not in a known share library, let's give up
5595 return "name not found";
5596 } else {
5597 //fprintf(stdout,"Found address in %s\n",info.dli_fname);
5598 return info.dli_sname;
5599 }
5600#endif
5601}
5602
5604{
5605 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5606 // TTBranchElement in the case of split sub-object.
5607 // If opt contains 'func', also print the (mangled) name of the function that will be executed.
5608
5609 if (fLoopConfig) {
5610 fLoopConfig->Print();
5611 }
5612 TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
5613 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
5614 iter != end;
5615 ++iter)
5616 {
5617 iter->fConfiguration->Print();
5618 if (strstr(opt,"func")) {
5619 printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
5620 }
5621 }
5622}
5623
5624
#define b(i)
Definition RSha256.hxx:100
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
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#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:376
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:29
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:616
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:5319
EState GetState() const
Definition TClass.h:495
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5104
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5830
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:6996
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5655
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:3002
@ kEmulated
Definition TClass.h:128
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
Int_t GetVersion() const
Definition TFile.h:328
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
static TClass * Class()
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
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:457
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:475
@ kIsOnHeap
object is on heap
Definition TObject.h:87
@ kNotDeleted
object has not been deleted
Definition TObject.h:88
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
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:864
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:875
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...
static TClass * Class()
Describe one element (data member) to be Streamed.
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
const char * GetTypeName() const
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
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)
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 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.
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.
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 * 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]
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...
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.
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
@ 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...
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.
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...
@ kCustomAlloc
The collection has a custom allocator.
void *(* CopyIterator_t)(void *dest, const void *source)
Copy the iterator source into dest.
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 Next_t GetFunctionNext(Bool_t read=kTRUE)=0
Return a pointer to a function that can advance an iterator (see Next_t).
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 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 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)
std::vector< TIDNode > TIDs
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)
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)
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 std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateWriteActionSequence(TStreamerInfo &info, TLoopConfiguration *loopConfig)
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 Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateReadActionSequence(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)
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)
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)
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)
static Int_t WriteCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
static Int_t WriteCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
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)
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)
static Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
static Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateWriteActionSequence(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)
static std::unique_ptr< TStreamerInfoActions::TActionSequence > CreateReadActionSequence(TStreamerInfo &info, TLoopConfiguration *)
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)