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
39{
40 enum class EMode
41 {
42 kRead,
43 kWrite
44 };
45
47 {
48 const auto props = proxy.GetProperties();
49 const bool isVector = proxy.GetCollectionType() == ROOT::kSTLvector;
52
53 return isEmulated || (isVector && hasDefaultAlloc);
54 }
55
56 template <typename From>
58 typedef From Value_t;
59 };
60
61 template <typename From>
63 typedef From Value_t;
64 };
65
66 struct BitsMarker {
67 typedef UInt_t Value_t;
68 };
69
71 {
72 // Add the (potentially negative) delta to all the configuration's offset. This is used by
73 // TBranchElement in the case of split sub-object.
74
76 fOffset += delta;
77 }
78
80 {
81 // Add the (potentially negative) delta to all the configuration's offset. This is used by
82 // TBranchElement in the case of split sub-object.
83
85 }
86
88 {
89 // Inform the user what we are about to stream.
90
91 // Idea, we should find a way to print the name of the function
93 }
94
96 {
97 // Inform the user what we are about to stream.
98
102 aElement->GetSequenceType(sequenceType);
103
104 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
105 " %s, offset=%d (%s), elemnId=%d \n",
106 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
107 aElement->ClassName(), fOffset, sequenceType.Data(), fElemId);
108 }
109
111 {
112 // Inform the user what we are about to stream.
113
114 if (gDebug > 1) {
115 // Idea: We should print the name of the action function.
119 aElement->GetSequenceType(sequenceType);
120
121 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
122 " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
123 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
124 aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
125 }
126 }
127
129 {
130 // Inform the user what we are about to stream.
131
132 printf("TLoopConfiguration: unconfigured\n");
133 }
134
135
137 // Configuration of action using the legacy code.
138 // Mostly to cancel out the PrintDebug.
139 public:
141 void PrintDebug(TBuffer &, void *) const override {
142 // Since we call the old code, it will print the debug statement.
143 }
144
145 TConfiguration *Copy() override { return new TGenericConfiguration(*this); }
146 };
147
149 // Configuration of action handling kBits.
150 // In this case we need to know both the location
151 // of the member (fBits) and the start of the object
152 // (its TObject part to be exact).
153
154 Int_t fObjectOffset; // Offset of the TObject part within the object
155
157 void PrintDebug(TBuffer &, void *) const override
158 {
162 aElement->GetSequenceType(sequenceType);
163
164 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
165 " %s, offset=%d (%s)\n",
166 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
167 aElement->ClassName(), fOffset, sequenceType.Data());
168 }
169
170 void AddToOffset(Int_t delta) override
171 {
172 // Add the (potentially negative) delta to all the configuration's offset. This is used by
173 // TBranchElement in the case of split sub-object.
174
176 fOffset += delta;
177 fObjectOffset = 0;
178 }
179
180 void SetMissing() override
181 {
183 fObjectOffset = 0;
184 }
185
186 TConfiguration *Copy() override { return new TBitsConfiguration(*this); }
187
188 };
189
202
204 {
205 std::unique_ptr<TStreamerInfoActions::TActionSequence> fActions;
206
208 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions) :
210 fActions(std::move(actions))
211 {}
212
216
217 void AddToOffset(Int_t delta) override
218 {
219 // Add the (potentially negative) delta to all the configuration's offset. This is used by
220 // TBranchElement in the case of split sub-object.
221
223 fOffset += delta;
224 if (fActions)
225 fActions->AddToOffset(delta);
226 }
227 }
228
229 TConfiguration *Copy() override { return new TConfSubSequence(*this); };
230 };
231
233 bool fIsPtrPtr = false; // Which are we, an array of objects or an array of pointers to objects?
234
239
240 TConfiguration *Copy() override { return new TConfStreamerLoop(*this); };
241 };
242
244 {
245 char *obj = (char*)addr;
247 return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
248 }
249
251 {
252 char *obj = (char*)addr;
254 return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
255 }
256
257 template <typename T>
258 inline Int_t ReadBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
259 {
260 T *x = (T*)( ((char*)addr) + config->fOffset );
261 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
262 buf >> *x;
263 return 0;
264 }
265
269 buf >> pidf;
270 pidf += buf.GetPidOffset();
271 TProcessID *pid = buf.ReadProcessID(pidf);
272 if (pid!=0) {
273 TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
274 UInt_t gpid = pid->GetUniqueID();
275 UInt_t uid;
276 if (gpid>=0xff) {
277 uid = obj->GetUniqueID() | 0xff000000;
278 } else {
279 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
280 }
281 obj->SetUniqueID(uid);
282 pid->PutObjectWithID(obj);
283 }
284 }
285
286 inline Int_t ReadViaExtStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
287 {
288 void *x = (void *)(((char *)addr) + config->fOffset);
290 (*pstreamer)(buf, x, config->fCompInfo->fLength);
291 return 0;
292 }
293
295 {
296 void *x = (void *)(((char *)addr) + config->fOffset);
298 (*pstreamer)(buf, x, config->fCompInfo->fLength);
299 return 0;
300 }
301
303 {
304 UInt_t start, count;
305 /* Version_t v = */ buf.ReadVersion(&start, &count, config->fInfo->IsA());
306
307 ReadViaExtStreamer(buf, addr, config);
308
309 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
310 return 0;
311 }
312
314 {
315 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
316
317 WriteViaExtStreamer(buf, addr, config);
318
319 buf.SetByteCount(pos, kTRUE);
320 return 0;
321 }
322
323 // Read a full object objectwise including reading the version and
324 // selecting any conversion.
326 {
327 auto conf = (TConfObject*)config;
328 auto memoryClass = conf->fInMemoryClass;
329 auto onfileClass = conf->fOnfileClass;
330
331 char * const where = (((char*)addr)+config->fOffset);
332 buf.ReadClassBuffer( memoryClass, where, onfileClass );
333 return 0;
334 }
335
336 // Write a full object objectwise including reading the version and
337 // selecting any conversion.
339 {
340 auto conf = (TConfObject*)config;
341 [[maybe_unused]] auto memoryClass = conf->fInMemoryClass;
342 auto onfileClass = conf->fOnfileClass;
343 assert((memoryClass == nullptr || memoryClass == onfileClass)
344 && "Need to new TBufferFile::WriteClassBuffer overload to support this case");
345
346 char * const where = (((char*)addr)+config->fOffset);
347 buf.WriteClassBuffer( onfileClass, where);
348 return 0;
349 }
350
351 template <>
353 {
354 UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
355 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
356 // Idea: This code really belongs inside TBuffer[File]
357 const UInt_t isonheap = *x & TObject::kIsOnHeap; // Record how this instance was actually allocated.
358 buf >> *x;
359 *x |= isonheap | TObject::kNotDeleted; // by definition de-serialized object are not yet deleted.
360
361 if ((*x & kIsReferenced) != 0) {
363 }
364 return 0;
365 }
366
367 template <typename T>
368 static inline Int_t WriteBasicZero(TBuffer &buf, void *, const TConfiguration *)
369 {
370 buf << T{0};
371 return 0;
372 }
373
374 template <typename T>
375 inline Int_t WriteBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
376 {
377 T *x = (T *)(((char *)addr) + config->fOffset);
378 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
379 buf << *x;
380 return 0;
381 }
382
383 template <typename Onfile, typename Memory>
385 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
386 {
387 // Simple conversion from a 'From' on disk to a 'To' in memory.
388 Onfile temp;
389 temp = (Onfile)(*(Memory*)( ((char*)addr) + config->fOffset ));
390 buf << temp;
391 return 0;
392 }
393 };
394
395 inline Int_t WriteTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
396 {
397 void *x = (void *)(((char *)addr) + config->fOffset);
398 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
399 buf.StreamObject(x, TNamed::Class(), TNamed::Class());
400 return 0;
401 }
402
403 inline Int_t WriteTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
404 {
405 void *x = (void *)(((char *)addr) + config->fOffset);
406 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
407 buf.StreamObject(x, TObject::Class(), TObject::Class());
408 return 0;
409 }
410
411 inline Int_t WriteTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
412 {
413 void *x = (void *)(((char *)addr) + config->fOffset);
414 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
415 ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
416 return 0;
417 }
418
419 inline Int_t ReadTextObject(TBuffer &buf, void *addr, const TConfiguration *config)
420 {
421 void *x = (void *)(((char *)addr) + config->fOffset);
422 buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
423 return 0;
424 }
425
426 inline Int_t ReadTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
427 {
428 void *x = (void *)(((char *)addr) + config->fOffset);
429 buf.StreamObject(x, TObject::Class(), TObject::Class());
430 return 0;
431 }
432
433 inline Int_t ReadTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
434 {
435 void *x = (void *)(((char *)addr) + config->fOffset);
436 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
437 ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
438 return 0;
439 }
440
442 {
443 // action required to call custom code for TObject as base class
444 void *x = (void *)(((char *)addr) + config->fOffset);
445 buf.ReadClassBuffer(TObject::Class(), x, TObject::Class());
446 return 0;
447 }
448
449 inline Int_t ReadTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
450 {
451 void *x = (void *)(((char *)addr) + config->fOffset);
452 buf.StreamObject(x, TNamed::Class(), TNamed::Class());
453 return 0;
454 }
455
456 static inline void WriteCompressed(TBuffer &buf, float *addr, const TStreamerElement *elem)
457 {
458 buf.WriteFloat16(addr, const_cast<TStreamerElement*>(elem));
459 }
460
461 static inline void WriteCompressed(TBuffer &buf, double *addr, const TStreamerElement *elem)
462 {
463 buf.WriteDouble32(addr, const_cast<TStreamerElement*>(elem));
464 }
465
466 inline Int_t TextWriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
467 {
468 TClass *cl = config->fCompInfo->fClass;
470 UInt_t ioffset = config->fOffset;
471
472 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
473
474 // use same method which is used in kSTL
475 buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
476
477 buf.SetByteCount(pos, kTRUE);
478 return 0;
479 }
480
481 inline Int_t TextReadSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
482 {
483 TClass *cle = config->fCompInfo->fClass;
486 UInt_t ioffset = config->fOffset;
487 UInt_t start, count;
488 /* Version_t vers = */ buf.ReadVersion(&start, &count, cle);
489
490 // use same method which is used in kSTL
491 buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
492 buf.CheckByteCount(start, count, aElement->GetFullName());
493 return 0;
494 }
495
497 // Configuration object for the Float16/Double32 where a factor has been specified.
498 public:
502 TConfiguration *Copy() override { return new TConfWithFactor(*this); }
503 };
504
505 template <typename T>
507 {
508 // Stream a Float16 or Double32 where a factor has been specified.
509 //a range was specified. We read an integer and convert it back to a double.
510
512 buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
513 return 0;
514 }
515
517 // Configuration object for the Float16/Double32 where a factor has been specified.
518 public:
521 TConfiguration *Copy() override { return new TConfNoFactor(*this); }
522 };
523
524 template <typename T>
526 {
527 // Stream a Float16 or Double32 where a factor has not been specified.
528
529 TConfNoFactor *conf = (TConfNoFactor *)config;
530 Int_t nbits = conf->fNbits;
531
532 buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
533 return 0;
534 }
535
536 inline Int_t ReadTString(TBuffer &buf, void *addr, const TConfiguration *config)
537 {
538 // Read in a TString object.
539
540 // Idea: We could separate the TString Streamer in its two parts and
541 // avoid the if (buf.IsReading()) and try having it inlined.
542 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
543 return 0;
544 }
545
546 inline Int_t WriteTString(TBuffer &buf, void *addr, const TConfiguration *config)
547 {
548 // Read in a TString object.
549
550 // Idea: We could separate the TString Streamer in its two parts and
551 // avoid the if (buf.IsReading()) and try having it inlined.
552 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
553 return 0;
554 }
555
556 inline Int_t ReadTObject(TBuffer &buf, void *addr, const TConfiguration *config)
557 {
558 // Read in a TObject object part.
559
560 // Idea: We could separate the TObject Streamer in its two parts and
561 // avoid the if (buf.IsReading()).
562 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
563 return 0;
564 }
565
566 inline Int_t WriteTObject(TBuffer &buf, void *addr, const TConfiguration *config)
567 {
568 // Read in a TObject object part.
569
570 // Idea: We could separate the TObject Streamer in its two parts and
571 // avoid the if (buf.IsReading()).
572 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
573 return 0;
574 }
575
576 inline Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
577 {
578 // Read in a TNamed object part.
579 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
580 // can skip the streamer.
581
582 // Idea: We could extract the code from ReadClassBuffer and avoid one function
583 // code.
584 static const TClass *TNamed_cl = TNamed::Class();
585 return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
586 }
587
588 inline Int_t WriteTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
589 {
590 // Read in a TNamed object part.
591 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
592 // can skip the streamer.
593
594 // Idea: We could extract the code from ReadClassBuffer and avoid one function
595 // code.
596 static const TClass *TNamed_cl = TNamed::Class();
597 return buf.WriteClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
598 }
599
600 class TConfigSTL : public TConfiguration {
601 // Configuration object for the kSTL case
602 private:
603 void Init(bool read) {
605 if (proxy) {
606 fCreateIterators = proxy->GetFunctionCreateIterators(read);
607 fCopyIterator = proxy->GetFunctionCopyIterator();
608 fDeleteIterator = proxy->GetFunctionDeleteIterator();
609 fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
610 if (proxy->HasPointers()) {
612 } else {
613 fNext = proxy->GetFunctionNext(read);
614 }
615 }
616 }
617
618 public:
619 TClass *fOldClass; // Class of the content on file
620 TClass *fNewClass; // Class of the content in memory.
622 const char *fTypeName; // Type name of the member as typed by ther user.
623 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
624
630
631
635
639
643
647
648 TConfiguration *Copy() override { return new TConfigSTL(*this); }
649 };
650
652 // Configuration object for the Float16/Double32 where a factor has been specified.
653 public:
657 TConfiguration *Copy() override { return new TConfSTLWithFactor(*this); }
658 };
659
661 // Configuration object for the Float16/Double32 where a factor has been specified.
662 public:
665 TConfiguration *Copy() override { return new TConfSTLNoFactor(*this); }
666 };
667
669 // Base class of the Configurations used in member wise streaming.
670 protected:
671 public:
672 Long_t fIncrement; // Either a value to increase the cursor by and
673 public:
675 //virtual void PrintDebug(TBuffer &buffer, void *);
676 ~TVectorLoopConfig() override {};
677 void Print() const override
678 {
679 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
680 }
681
682 void* GetFirstAddress(void *start, const void * /* end */) const override
683 {
684 // Return the address of the first element of the collection.
685
686 return start;
687 }
688
689 TLoopConfiguration* Copy() const override { return new TVectorLoopConfig(*this); }
690 };
691
693 // Base class of the Configurations used in member wise streaming.
694 public:
696 //virtual void PrintDebug(TBuffer &buffer, void *);
697 ~TAssocLoopConfig() override {};
698 void Print() const override
699 {
700 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
701 }
702 TLoopConfiguration* Copy() const override { return new TAssocLoopConfig(*this); }
703
704 void* GetFirstAddress(void *start, const void * /* end */) const override
705 {
706 // Return the address of the first element of the collection.
707
708 R__ASSERT(0);
709// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
710// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
711// arr0 = genloopconfig->fNext(iter,end_collection);
712// if (iter != &iterator[0]) {
713// genloopconfig->fDeleteIterator(iter);
714// }
715 return start;
716 }
717 };
718
720 // Configuration object for the generic case of member wise streaming looping.
721 private:
735 public:
739
744 ~TGenericLoopConfig() override {};
745 void Print() const override
746 {
747 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
748 }
749 TLoopConfiguration* Copy() const override { return new TGenericLoopConfig(*this); }
750
751 void* GetFirstAddress(void *start_collection, const void *end_collection) const override
752 {
753 // Return the address of the first element of the collection.
754
756 void *iter = fCopyIterator(&iterator,start_collection);
757 void *arr0 = fNext(iter,end_collection);
758 if (iter != &iterator[0]) {
759 fDeleteIterator(iter);
760 }
761 return arr0;
762 }
763 };
764
766 {
767 // Collection was saved member-wise
768
769 TConfigSTL *config = (TConfigSTL*)conf;
771
772 if( vers >= 8 ) {
773
774 TClass *oldClass = config->fOldClass;
775
776 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
777 if (!oldProxy) {
778 // Missing information, broken file ... give up
779 return;
780 }
781 TClass *valueClass = oldProxy->GetValueClass();
782 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
783
786 buf.ReadInt(nobjects);
787 void* alternative = oldProxy->Allocate(nobjects,true);
788 if (nobjects) {
789 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
790
793 void *begin = &(startbuf[0]);
794 void *end = &(endbuf[0]);
795 config->fCreateIterators(alternative, &begin, &end, oldProxy);
796 // We can not get here with a split vector of pointer, so we can indeed assume
797 // that actions->fConfiguration != null.
798 buf.ApplySequence(*actions, begin, end);
799 if (begin != &(startbuf[0])) {
800 // assert(end != endbuf);
801 config->fDeleteTwoIterators(begin,end);
802 }
803 }
804 oldProxy->Commit(alternative);
805
806 } else {
807
808 TClass *oldClass = config->fOldClass;
809
810 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
811 if (!oldProxy) {
812 // Missing information, broken file ... give up
813 return;
814 }
815
818 buf.ReadInt(nobjects);
819 void* env = oldProxy->Allocate(nobjects,true);
820
821 if (nobjects || vers < 7 ) {
822 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
823 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
824
825 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
826 }
827 oldProxy->Commit(env);
828 }
829 }
830
832 {
833 // Collection was saved member-wise
834
835 TConfigSTL *config = (TConfigSTL*)conf;
837
838 if( vers >= 8 ) {
839
840 TClass *oldClass = config->fOldClass;
841
842 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
843 if (!oldProxy) {
844 // Missing information, broken file ... give up
845 return;
846 }
847 TClass *valueClass = oldProxy->GetValueClass();
848 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
849
850 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
851
852 int objectSize = oldClass->Size();
853 char *obj = (char*)addr;
854 char *endobj = obj + conf->fLength*objectSize;
855
856 for(; obj<endobj; obj+=objectSize) {
858 buf.ReadInt(nobjects);
860 void* alternative = oldProxy->Allocate(nobjects,true);
861 if (nobjects) {
864 void *begin = &(startbuf[0]);
865 void *end = &(endbuf[0]);
866 config->fCreateIterators(alternative, &begin, &end, oldProxy);
867 // We can not get here with a split vector of pointer, so we can indeed assume
868 // that actions->fConfiguration != null.
869 buf.ApplySequence(*actions, begin, end);
870 if (begin != &(startbuf[0])) {
871 // assert(end != endbuf);
872 config->fDeleteTwoIterators(begin,end);
873 }
874 }
875 oldProxy->Commit(alternative);
876 }
877
878 } else {
879
880 TClass *oldClass = config->fOldClass;
881
882 TVirtualCollectionProxy *oldProxy = oldClass ? oldClass->GetCollectionProxy() : nullptr;
883 if (!oldProxy) {
884 // Missing information, broken file ... give up
885 return;
886 }
887
888 int objectSize = oldClass->Size();
889 char *obj = (char*)addr;
890 char *endobj = obj + conf->fLength*objectSize;
891
892 for(; obj<endobj; obj+=objectSize) {
895 buf.ReadInt(nobjects);
896 void* env = oldProxy->Allocate(nobjects,true);
897
898 if (nobjects || vers < 7 ) {
899 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
900 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
901
902 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
903 }
904 oldProxy->Commit(env);
905 }
906 }
907 }
908
910 {
911 // Collection was saved member-wise
912
913 TConfigSTL *config = (TConfigSTL*)conf;
914
916
917 TClass *newClass = config->fNewClass;
918 TClass *oldClass = config->fOldClass;
919
920 if( vers < 8 ) {
921 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
922 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)" );
923 } else if (newClass && oldClass){
924
925 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
926
927 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
928 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
929
932 buf.ReadInt(nobjects);
933 void* alternative = newProxy->Allocate(nobjects,true);
934 if (nobjects) {
935 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
938 void *begin = &(startbuf[0]);
939 void *end = &(endbuf[0]);
940 config->fCreateIterators( alternative, &begin, &end, newProxy);
941 // We can not get here with a split vector of pointer, so we can indeed assume
942 // that actions->fConfiguration != null.
943 buf.ApplySequence(*actions, begin, end);
944 if (begin != &(startbuf[0])) {
945 // assert(end != endbuf);
946 config->fDeleteTwoIterators(begin,end);
947 }
948 }
949 newProxy->Commit(alternative);
950 }
951 }
952
954 {
955 // Collection was saved member-wise
956
957 TConfigSTL *config = (TConfigSTL*)conf;
958
960
961 TClass *newClass = config->fNewClass;
962 TClass *oldClass = config->fOldClass;
963
964 if( vers < 8 ) {
965 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
966 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)" );
967 } else if (newClass && oldClass) {
968
969 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
970
971 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
972 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
973
974 int objectSize = newClass->Size();
975 char *obj = (char*)addr;
976 char *endobj = obj + conf->fLength*objectSize;
977
978 for(; obj<endobj; obj+=objectSize) {
981 buf.ReadInt(nobjects);
982 void* alternative = newProxy->Allocate(nobjects,true);
983 if (nobjects) {
984 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
987 void *begin = &(startbuf[0]);
988 void *end = &(endbuf[0]);
989 config->fCreateIterators( alternative, &begin, &end, newProxy);
990 // We can not get here with a split vector of pointer, so we can indeed assume
991 // that actions->fConfiguration != null.
992 buf.ApplySequence(*actions, begin, end);
993 if (begin != &(startbuf[0])) {
994 // assert(end != endbuf);
995 config->fDeleteTwoIterators(begin,end);
996 }
997 }
998 newProxy->Commit(alternative);
999 }
1000 }
1001 }
1002
1003 inline void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1004 {
1005 TConfigSTL *config = (TConfigSTL*)conf;
1006 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1007 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1008 }
1009 inline void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1010 {
1011 TConfigSTL *config = (TConfigSTL*)conf;
1012 (*config->fStreamer)(buf,addr,conf->fLength);
1013 }
1015 {
1016 // case of old TStreamerInfo
1017
1018 TConfigSTL *config = (TConfigSTL*)conf;
1019 // Backward compatibility. Some TStreamerElement's where without
1020 // Streamer but were not removed from element list
1021 if (config->fIsSTLBase || vers == 0) {
1022 buf.SetBufferOffset(start); //there is no byte count
1023 }
1024 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1025 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1026 }
1028 {
1029 // case of old TStreamerInfo
1030
1031 TConfigSTL *config = (TConfigSTL*)conf;
1032 // Backward compatibility. Some TStreamerElement's where without
1033 // Streamer but were not removed from element list
1034 if (config->fIsSTLBase || vers == 0) {
1035 buf.SetBufferOffset(start); //there is no byte count
1036 }
1037 (*config->fStreamer)(buf,addr,conf->fLength);
1038 }
1039
1040 // To Upgrade this to WriteSTLMemberWiseChangedClass (see ReadSTLMemberWiseChangedClass)
1041 // we would need to a TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1043 {
1044 // Collection was saved member-wise
1045 // newClass -> in memory representation
1046 // oldClass -> onfile representation
1047
1048 TConfigSTL *config = (TConfigSTL*)conf;
1049 TClass *newClass = config->fNewClass;
1050 TClass *onfileClass = config->fOldClass;
1051
1052 // Until the writing of TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1054 "Class level transformation while writing is not yet supported");
1055
1056 if (newClass && onfileClass) {
1057
1058 buf.WriteVersion( onfileClass->GetCollectionProxy()->GetValueClass(), kFALSE );
1059
1060 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1061 TVirtualCollectionProxy *onfileProxy = onfileClass->GetCollectionProxy();
1062
1064 Int_t nobjects = newProxy->Size();
1065 buf.WriteInt(nobjects);
1066 if (nobjects) {
1067 TActionSequence *actions = onfileProxy->GetWriteMemberWiseActions();
1070 void *begin = &(startbuf[0]);
1071 void *end = &(endbuf[0]);
1072 config->fCreateIterators( addr, &begin, &end, newProxy);
1073 // We can not get here with a split vector of pointer, so we can indeed assume
1074 // that actions->fConfiguration != null.
1075 buf.ApplySequence(*actions, begin, end);
1076 if (begin != &(startbuf[0])) {
1077 // assert(end != endbuf);
1078 config->fDeleteTwoIterators(begin,end);
1079 }
1080 }
1081 }
1082 }
1083
1084 // This routine could/should be merge with WriteSTLMemberWise, the only difference
1085 // is the for loop over the objects. We are not using this version for the case
1086 // where `conf->fLength is 1` as we know this information at StreamerInfo build time
1087 // and thus we can avoid the 'waste' of CPU cycles involved in doing a loop of length 1
1089 {
1090 // Collection was saved member-wise
1091 // newClass -> in memory representation
1092 // oldClass -> onfile representation
1093
1094 TConfigSTL *config = (TConfigSTL*)conf;
1095 TClass *newClass = config->fNewClass;
1096 TClass *onfileClass = config->fOldClass;
1097
1098 // Until the writing of TVirtualCollectionProxy::GetConversionWriteMemberWiseActions
1100 "Class level transformation while writing is not yet supported");
1101
1102 if (newClass && onfileClass) {
1103
1104 buf.WriteVersion( onfileClass->GetCollectionProxy()->GetValueClass(), kFALSE );
1105
1106 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1107 TVirtualCollectionProxy *onfileProxy = onfileClass->GetCollectionProxy();
1108
1109 int objectSize = newClass->Size();
1110 char *obj = (char*)addr;
1111 char *endobj = obj + conf->fLength * objectSize;
1112
1113 for (; obj < endobj; obj += objectSize) {
1115 Int_t nobjects = newProxy->Size();
1116 buf.WriteInt(nobjects);
1117 if (nobjects) {
1118 TActionSequence *actions = onfileProxy->GetWriteMemberWiseActions();
1121 void *begin = &(startbuf[0]);
1122 void *end = &(endbuf[0]);
1123 config->fCreateIterators( addr, &begin, &end, newProxy);
1124 // We can not get here with a split vector of pointer, so we can indeed assume
1125 // that actions->fConfiguration != null.
1126 buf.ApplySequence(*actions, begin, end);
1127 if (begin != &(startbuf[0])) {
1128 // assert(end != endbuf);
1129 config->fDeleteTwoIterators(begin,end);
1130 }
1131 }
1132 }
1133 }
1134 }
1135
1137 {
1138 TConfigSTL *config = (TConfigSTL*)conf;
1139 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1140 buf.WriteFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0);
1141 }
1143 {
1144 TConfigSTL *config = (TConfigSTL*)conf;
1145 (*config->fStreamer)(buf,addr,conf->fLength);
1146 }
1147
1148 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1149 void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1151 {
1152 TConfigSTL *config = (TConfigSTL*)conf;
1153 UInt_t start, count;
1154 Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1156 memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1157 } else {
1158 objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1159 }
1160 buf.CheckByteCount(start,count,config->fTypeName);
1161 return 0;
1162 }
1163
1164 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*),
1165 void (*objectwise)(TBuffer&,void *,const TConfiguration*)>
1167 {
1168 TConfigSTL *config = (TConfigSTL*)conf;
1169 UInt_t start;
1170 TClass *onfileClass = config->fOldClass;
1172 TVirtualCollectionProxy *proxy = onfileClass->GetCollectionProxy();
1173 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
1174
1175 // See test in TStreamerInfo::kSTL case in TStreamerInfoWriteBuffer.cxx
1177 && proxy && vClass
1178 && config->fInfo->GetStreamMemberWise() && onfileClass->CanSplit()
1179 && !(strspn(aElement->GetTitle(),"||") == 2)
1180 && !(vClass->HasCustomStreamerMember()) )
1181 {
1182 start = buf.WriteVersionMemberWise(config->fInfo->IsA(), kTRUE);
1183 memberwise(buf, ((char *)addr) + config->fOffset, config);
1184 } else {
1185 start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1186 objectwise(buf, ((char *)addr) + config->fOffset, config);
1187 }
1188 buf.SetByteCount(start);
1189 return 0;
1190 }
1191
1192 template <typename From, typename To>
1194 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1195 {
1196 // Simple conversion from a 'From' on disk to a 'To' in memory.
1197 From temp;
1198 buf >> temp;
1199 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1200 return 0;
1201 }
1202 };
1203
1204 template <typename To>
1206 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1207 {
1208 // Simple conversion from a 'From' on disk to a 'To' in memory
1209 UInt_t temp;
1210 buf >> temp;
1211
1212 if ((temp & kIsReferenced) != 0) {
1214 }
1215
1216 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1217 return 0;
1218 }
1219 };
1220
1221 template <typename From, typename To>
1223 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1224 {
1225 // Simple conversion from a 'From' on disk to a 'To' in memory.
1227 From temp;
1228 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1229 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1230 return 0;
1231 }
1232 };
1233
1234 template <typename From, typename To>
1236 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1237 {
1238 // Simple conversion from a 'From' on disk to a 'To' in memory.
1239 TConfNoFactor *conf = (TConfNoFactor *)config;
1240 From temp;
1241 buf.ReadWithNbits(&temp, conf->fNbits);
1242 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1243 return 0;
1244 }
1245 };
1246
1248 // Configuration object for the PushDataCache case.
1249 public:
1251
1255
1256 void Print() const override
1257 {
1259 if (fOnfileObject)
1260 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1261 info->GetClass()->GetName(), fOffset);
1262 else
1263 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1264 info->GetClass()->GetName(), fOffset);
1265 }
1266 void PrintDebug(TBuffer &buffer, void *object) const override
1267 {
1268 if (gDebug > 1) {
1270 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1271 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1272
1273 }
1274 }
1275 };
1276
1278 {
1280 auto onfileObject = config->fOnfileObject;
1281
1282 // onfileObject->SetSize(1);
1283 b.PushDataCache( onfileObject );
1284
1285 return 0;
1286 }
1287
1289 {
1291 auto onfileObject = config->fOnfileObject;
1292
1293 // onfileObject->SetSize(n);
1294 b.PushDataCache( onfileObject );
1295
1296 return 0;
1297 }
1298
1300 {
1302 auto onfileObject = config->fOnfileObject;
1303
1305 UInt_t n = proxy->Size();
1306
1307 onfileObject->SetSize(n);
1308 b.PushDataCache( onfileObject );
1309
1310 return 0;
1311 }
1312
1314 {
1315 b.PopDataCache();
1316 return 0;
1317 }
1318
1319 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1320 {
1321 b.PopDataCache();
1322 return 0;
1323 }
1324
1326 {
1327 b.PopDataCache();
1328 return 0;
1329 }
1330
1332 // Configuration object for the UseCache case.
1333 public:
1336
1339 void PrintDebug(TBuffer &b, void *addr) const override
1340 {
1341 if (gDebug > 1) {
1342 // Idea: We should print the name of the action function.
1345 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1346 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1347 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1348 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1349 }
1350
1351 }
1354 {
1356 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1357 return copy;
1358 }
1359 };
1360
1362 {
1364
1365 Int_t bufpos = b.Length();
1366 TVirtualArray *cached = b.PeekDataCache();
1367 if (cached==0) {
1368 TStreamerElement *aElement = conf->fCompInfo->fElem;
1370 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1371 char *ptr = (char*)addr;
1372 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1373 } else {
1374 config->fAction(b, (*cached)[0]);
1375 }
1376 // Idea: Factor out this 'if' to a UseCacheRepeat function
1377 if (config->fNeedRepeat) {
1378 b.SetBufferOffset(bufpos);
1379 }
1380 return 0;
1381 }
1382
1383 inline Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1384 {
1386 Int_t bufpos = b.Length();
1387
1388 TVirtualArray *cached = b.PeekDataCache();
1389 if (cached==0) {
1392 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1393 char *ptr = (char*)start;
1394 UInt_t n = (((void**)end)-((void**)start));
1395 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1396 } else {
1397 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1398 void *cached_start = (*cached)[0];
1399 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1401 }
1402 // Idea: Factor out this 'if' to a UseCacheRepeat function
1403 if (config->fNeedRepeat) {
1404 b.SetBufferOffset(bufpos);
1405 }
1406 return 0;
1407 }
1408
1409 inline Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1410 {
1412
1413 Int_t bufpos = b.Length();
1414 TVirtualArray *cached = b.PeekDataCache();
1415 if (cached==0) {
1418 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1419 char *ptr = (char*)start;
1420 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1421 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1422 } else {
1423 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1424 void *cached_start = (*cached)[0];
1425 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1427 }
1428 // Idea: Factor out this 'if' to a UseCacheRepeat function
1429 if (config->fNeedRepeat) {
1430 b.SetBufferOffset(bufpos);
1431 }
1432 return 0;
1433 }
1434
1436 {
1438
1439 Int_t bufpos = b.Length();
1440 TVirtualArray *cached = b.PeekDataCache();
1441 if (cached==0) {
1444
1446 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1447 UInt_t n = proxy->Size();
1448 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1449 } else {
1450 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1451 void *cached_start = (*cached)[0];
1452 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1454 }
1455 // Idea: Factor out this 'if' to a UseCacheRepeat function
1456 if (config->fNeedRepeat) {
1457 b.SetBufferOffset(bufpos);
1458 }
1459 return 0;
1460 }
1461
1462 // Support for collections.
1463
1464 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1465 {
1466 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1467 return 0;
1468 }
1469
1470 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1471 {
1472 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1473 return 0;
1474 }
1475
1477
1479 {
1480 if ( (proxy.GetProperties() & TVirtualCollectionProxy::kIsEmulated) ) {
1481 return kVectorLooper;
1482 } else if ( (proxy.GetCollectionType() == ROOT::kSTLvector)) {
1483 if (proxy.GetProperties() & TVirtualCollectionProxy::kCustomAlloc)
1484 return kGenericLooper;
1485 else
1486 return kVectorLooper;
1487 } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
1488 || proxy.GetCollectionType() == ROOT::kSTLmultiset || proxy.GetCollectionType() == ROOT::kSTLunorderedmultiset
1489 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap
1490 || proxy.GetCollectionType() == ROOT::kSTLunorderedmap || proxy.GetCollectionType() == ROOT::kSTLunorderedmultimap
1491 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1492 return kAssociativeLooper;
1493 } else {
1494 return kGenericLooper;
1495 }
1496 }
1497
1499 {
1500 if (proxy)
1501 return SelectLooper(*proxy);
1502 else
1503 return kVectorPtrLooper;
1504 }
1505
1506
1507 template<typename Looper>
1509
1510 /// \param loopConfig pointer ownership stays at the caller, a copy is performed and transferred to the
1511 /// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return unique
1512 /// pointer of type TActionSequence
1513 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1515 {
1516 std::unique_ptr<TLoopConfiguration> localLoopConfig{ loopConfig ? loopConfig->Copy() : nullptr };
1517 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1519 return actions;
1520 }
1521
1522 /// \param loopConfig pointer ownership stays at the caller, a copy is performed and transferred to the
1523 /// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return unique
1524 /// pointer of type TActionSequence
1525 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
1527 {
1528 std::unique_ptr<TLoopConfiguration> localLoopConfig{ loopConfig ? loopConfig->Copy() : nullptr };
1529 std::unique_ptr<TStreamerInfoActions::TActionSequence> actions(
1531 return actions;
1532 }
1533
1534 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * /* loopconfig */, const TConfiguration *config)
1535 {
1536 auto conf = (TConfSubSequence*)config;
1537 auto actions = conf->fActions.get();
1538 // FIXME: need to update the signature of ApplySequence.
1539 buf.ApplySequence(*actions, start, const_cast<void*>(end));
1540 return 0;
1541 }
1542
1543 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1544 {
1545 UInt_t pos, count;
1546 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1547
1548 Looper::template LoopOverCollection< ReadViaExtStreamer >(buf, start, end, loopconfig, config);
1549
1550 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1551 return 0;
1552 }
1553
1554 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1555 {
1556 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1557
1558 Looper::template LoopOverCollection< WriteViaExtStreamer >(buf, start, end, loopconfig, config);
1559
1560 buf.SetByteCount(pos, kTRUE);
1561 return 0;
1562 }
1563
1565 UInt_t ioffset = actionConfig->fOffset;
1566 // Get any private streamer which was set for the data member.
1567 TMemberStreamer* pstreamer = actionConfig->fCompInfo->fStreamer;
1568 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + actionConfig->fCompInfo->fMethod /*counter offset*/);
1569 // And call the private streamer, passing it the buffer, the object, and the counter.
1570 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
1571 return 0;
1572 };
1573
1574 template<bool kIsTextT>
1576 // Get the class of the data member.
1577 TClass* cl = config->fCompInfo->fClass;
1578 UInt_t ioffset = config->fOffset;
1579 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1580
1581 // Get the counter for the varying length array.
1582 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1583
1584 //b << vlen;
1585 if (vlen) {
1586 // Get a pointer to the array of pointers.
1587 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1588 // Loop over each element of the array of pointers to varying-length arrays.
1589 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1590 if (!pp[ndx]) {
1591 // -- We do not have a pointer to a varying-length array.
1592 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1593 // ::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()));
1594 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());
1595 continue;
1596 }
1597 if (!isPtrPtr) {
1598 // -- We are a varying-length array of objects.
1599 // Write the entire array of objects to the buffer.
1600 // Note: Polymorphism is not allowed here.
1601 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
1602 } else {
1603 // -- We are a varying-length array of pointers to objects.
1604 // Write the entire array of object pointers to the buffer.
1605 // Note: The object pointers are allowed to be polymorphic.
1606 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1607 } // isPtrPtr
1608 } // ndx
1609 } else // vlen
1610 if (kIsTextT) {
1611 // special handling for the text-based streamers
1612 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
1613 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
1614 }
1615 return 0;
1616 }
1617
1619 // Get the class of the data member.
1620 TClass* cl = config->fCompInfo->fClass;
1621 UInt_t ioffset = config->fOffset;
1622 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1623
1624 // Get the counter for the varying length array.
1625 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + config->fCompInfo->fMethod /*counter offset*/));
1626 //b << vlen;
1627 if (vlen) {
1628 // Get a pointer to the array of pointers.
1629 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
1630 // -- Older versions do *not* allow polymorphic pointers to objects.
1631 // Loop over each element of the array of pointers to varying-length arrays.
1632 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1633 if (!pp[ndx]) {
1634 // -- We do not have a pointer to a varying-length array.
1635 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1636 // ::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()));
1637 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());
1638 continue;
1639 }
1640 if (!isPtrPtr) {
1641 // -- We are a varying-length array of objects.
1642 // Loop over the elements of the varying length array.
1643 for (Int_t v = 0; v < vlen; ++v) {
1644 // Write the object to the buffer.
1645 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1646 } // v
1647 }
1648 else {
1649 // -- We are a varying-length array of pointers to objects.
1650 // Loop over the elements of the varying length array.
1651 for (Int_t v = 0; v < vlen; ++v) {
1652 // Get a pointer to the object pointer.
1653 char** r = (char**) pp[ndx];
1654 // Write the object to the buffer.
1655 cl->Streamer(r[v], buf);
1656 } // v
1657 } // isPtrPtr
1658 } // ndx
1659 } // vlen
1660 return 0;
1661 }
1662
1663 template<bool kIsTextT, typename... Ts>
1665 static inline Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1666 {
1667 if (!kIsTextT && config->fCompInfo->fStreamer) {
1668 // -- We have a private streamer.
1669 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1670
1671 // Loop over the entries in the clones array or the STL container.
1672 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1673
1674 buf.SetByteCount(pos, kTRUE);
1675 // We are done, next streamer element.
1676 return 0;
1677 }
1678
1679 // By default assume the file version is the newest.
1681
1682 if (!kIsTextT) {
1683 // At this point we do *not* have a private streamer.
1684 // Get the version of the file we are writing to.
1685 TFile* file = (TFile*) buf.GetParent();
1686 if (file) {
1687 fileVersion = file->GetVersion();
1688 }
1689 }
1690 // Write the class version to the buffer.
1691 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
1692 if (fileVersion > 51508) {
1693 // -- Newer versions allow polymorphic pointers to objects.
1694 // Loop over the entries in the clones array or the STL container.
1695 Looper::template LoopOverCollection< WriteStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1696 }
1697 else {
1698 // -- Older versions do *not* allow polymorphic pointers to objects.
1699 // Loop over the entries in the clones array or the STL container.
1700 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1701 } // fileVersion
1702 // Backpatch the byte count into the buffer.
1703 buf.SetByteCount(pos, kTRUE);
1704
1705 return 0;
1706 }
1707 };
1708
1709 template<bool kIsTextT>
1710 static Int_t ReadStreamerLoopPoly(TBuffer &buf, void *addr, const TConfiguration *config) {
1711 // Get the class of the data member.
1712 TClass* cl = config->fCompInfo->fClass;
1713 UInt_t ioffset = config->fOffset;
1714 // Which are we, an array of objects or an array of pointers to objects?
1715 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1716
1717 // Get the counter for the varying length array.
1718 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1719 config->fCompInfo->fMethod /*counter offset*/));
1720 // Int_t realLen;
1721 // b >> realLen;
1722 // if (realLen != vlen) {
1723 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1724 //}
1725 // Get a pointer to the array of pointers.
1726 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1727 // Loop over each element of the array of pointers to varying-length arrays.
1728 // if (!pp) {
1729 // continue;
1730 // }
1731
1732 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1733 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1734 // if (!pp[ndx]) {
1735 // -- We do not have a pointer to a varying-length array.
1736 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1737 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1738 // continue;
1739 //}
1740 // Delete any memory at pp[ndx].
1741 if (!isPtrPtr) {
1742 cl->DeleteArray(pp[ndx]);
1743 pp[ndx] = 0;
1744 } else {
1745 // Using vlen is wrong here because it has already
1746 // been overwritten with the value needed to read
1747 // the current record. Fixing this will require
1748 // doing a pass over the object at the beginning
1749 // of the I/O and releasing all the buffer memory
1750 // for varying length arrays before we overwrite
1751 // the counter values.
1752 //
1753 // For now we will just leak memory, just as we
1754 // have always done in the past. Fix this.
1755 //
1756 // char** r = (char**) pp[ndx];
1757 // if (r) {
1758 // for (Int_t v = 0; v < vlen; ++v) {
1759 // cl->Destructor(r[v]);
1760 // r[v] = 0;
1761 // }
1762 //}
1763 delete[] pp[ndx];
1764 pp[ndx] = 0;
1765 }
1766 if (!vlen) {
1767 if (kIsTextT) {
1768 // special handling for the text-based streamers - keep calling to shift array index
1769 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
1770 }
1771 continue;
1772 }
1773 // Note: We now have pp[ndx] is null.
1774 // Allocate memory to read into.
1775 if (!isPtrPtr) {
1776 // -- We are a varying-length array of objects.
1777 // Note: Polymorphism is not allowed here.
1778 // Allocate a new array of objects to read into.
1779 pp[ndx] = (char *)cl->NewArray(vlen);
1780 if (!pp[ndx]) {
1781 Error("ReadBuffer", "Memory allocation failed!\n");
1782 continue;
1783 }
1784 } else {
1785 // -- We are a varying-length array of pointers to objects.
1786 // Note: The object pointers are allowed to be polymorphic.
1787 // Allocate a new array of pointers to objects to read into.
1788 pp[ndx] = (char *)new char *[vlen];
1789 if (!pp[ndx]) {
1790 Error("ReadBuffer", "Memory allocation failed!\n");
1791 continue;
1792 }
1793 // And set each pointer to null.
1794 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1795 // = (char*) new char*[vlen];
1796 }
1797 if (!isPtrPtr) {
1798 // -- We are a varying-length array of objects.
1799 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
1800 } else {
1801 // -- We are a varying-length array of object pointers.
1802 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
1803 } // isPtrPtr
1804 } // ndx
1805 return 0;
1806 }; // StreamerLoopPoly
1807
1809 // Get the class of the data member.
1810 TClass* cl = config->fCompInfo->fClass;
1811 UInt_t ioffset = config->fOffset;
1812 // Which are we, an array of objects or an array of pointers to objects?
1813 bool isPtrPtr = ((TConfStreamerLoop*)config)->fIsPtrPtr;
1814
1815 // Get the counter for the varying length array.
1816 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ +
1817 config->fCompInfo->fMethod /*counter offset*/));
1818 // Int_t realLen;
1819 // b >> realLen;
1820 // if (realLen != vlen) {
1821 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
1822 //}
1823 // Get a pointer to the array of pointers.
1824 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
1825 // if (!pp) {
1826 // continue;
1827 //}
1828
1829 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
1830
1831 // Loop over each element of the array of pointers to varying-length arrays.
1832 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
1833 // if (!pp[ndx]) {
1834 // -- We do not have a pointer to a varying-length array.
1835 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
1836 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
1837 // continue;
1838 //}
1839 // Delete any memory at pp[ndx].
1840 if (!isPtrPtr) {
1841 cl->DeleteArray(pp[ndx]);
1842 pp[ndx] = 0;
1843 } else {
1844 // Using vlen is wrong here because it has already
1845 // been overwritten with the value needed to read
1846 // the current record. Fixing this will require
1847 // doing a pass over the object at the beginning
1848 // of the I/O and releasing all the buffer memory
1849 // for varying length arrays before we overwrite
1850 // the counter values.
1851 //
1852 // For now we will just leak memory, just as we
1853 // have always done in the past. Fix this.
1854 //
1855 // char** r = (char**) pp[ndx];
1856 // if (r) {
1857 // for (Int_t v = 0; v < vlen; ++v) {
1858 // cl->Destructor(r[v]);
1859 // r[v] = 0;
1860 // }
1861 //}
1862 delete[] pp[ndx];
1863 pp[ndx] = 0;
1864 }
1865 if (!vlen) {
1866 continue;
1867 }
1868 // Note: We now have pp[ndx] is null.
1869 // Allocate memory to read into.
1870 if (!isPtrPtr) {
1871 // -- We are a varying-length array of objects.
1872 // Note: Polymorphism is not allowed here.
1873 // Allocate a new array of objects to read into.
1874 pp[ndx] = (char *)cl->NewArray(vlen);
1875 if (!pp[ndx]) {
1876 Error("ReadBuffer", "Memory allocation failed!\n");
1877 continue;
1878 }
1879 } else {
1880 // -- We are a varying-length array of pointers to objects.
1881 // Note: The object pointers are allowed to be polymorphic.
1882 // Allocate a new array of pointers to objects to read into.
1883 pp[ndx] = (char *)new char *[vlen];
1884 if (!pp[ndx]) {
1885 Error("ReadBuffer", "Memory allocation failed!\n");
1886 continue;
1887 }
1888 // And set each pointer to null.
1889 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
1890 // = (char*) new char*[vlen];
1891 }
1892 if (!isPtrPtr) {
1893 // -- We are a varying-length array of objects.
1894 // Loop over the elements of the varying length array.
1895 for (Int_t v = 0; v < vlen; ++v) {
1896 // Read the object from the buffer.
1897 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
1898 } // v
1899 } else {
1900 // -- We are a varying-length array of object pointers.
1901 // Get a pointer to the object pointer array.
1902 char **r = (char **)pp[ndx];
1903 // Loop over the elements of the varying length array.
1904 for (Int_t v = 0; v < vlen; ++v) {
1905 // Allocate an object to read into.
1906 r[v] = (char *)cl->New();
1907 if (!r[v]) {
1908 // Do not print a second error message here.
1909 // Error("ReadBuffer", "Memory allocation failed!\n");
1910 continue;
1911 }
1912 // Read the object from the buffer.
1913 cl->Streamer(r[v], buf);
1914 } // v
1915 } // isPtrPtr
1916 } // ndx
1917 return 0;
1918 }; // action
1919
1920 template<bool kIsTextT, typename... Ts>
1922 static inline Int_t Action(TBuffer &buf, void *start, Ts... args, const TConfiguration *config)
1923 {
1924 // Check for a private streamer.
1925 if (!kIsTextT && config->fCompInfo->fStreamer) {
1926 // -- We have a private streamer.
1927 // Read the class version and byte count from the buffer.
1928 UInt_t pos = 0;
1929 UInt_t count = 0;
1930 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1931
1932 // Loop over the entries in the clones array or the STL container.
1933 Looper::template LoopOverCollection< StreamerLoopExternal > (buf, start, args..., config);
1934
1935 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1936 // We are done, next streamer element.
1937 return 0;
1938 }
1939
1940 // By default assume the file version is the newest.
1942 if (!kIsTextT) {
1943 // At this point we do *not* have a private streamer.
1944 // Get the version of the file we are reading from.
1945 TFile* file = (TFile*) buf.GetParent();
1946 if (file) {
1947 fileVersion = file->GetVersion();
1948 }
1949 }
1950 // Read the class version and byte count from the buffer.
1951 UInt_t pos = 0;
1952 UInt_t count = 0;
1953 buf.ReadVersion(&pos, &count, config->fInfo->IsA());
1954 if (fileVersion > 51508) {
1955 // -- Newer versions allow polymorphic pointers.
1956
1957 // Loop over the entries in the clones array or the STL container.
1958 Looper::template LoopOverCollection< ReadStreamerLoopPoly<kIsTextT> > (buf, start, args..., config);
1959 } else {
1960 // -- Older versions do *not* allow polymorphic pointers.
1961
1962 // Loop over the entries in the clones array or the STL container.
1963 Looper::template LoopOverCollection< ReadStreamerLoopStatic > (buf, start, args..., config);
1964 } // fileVersion
1965 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
1966 return 0;
1967 }
1968 };
1969
1970 };
1971
1972 // The Scalar 'looper' only process one element.
1973 struct ScalarLooper : public CollectionLooper<ScalarLooper>
1974 {
1975 using LoopAction_t = Int_t (*)(TBuffer &, void*, const TConfiguration*);
1976
1977 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1978 static inline Int_t LoopOverCollection(TBuffer &buf, void *start, const TConfiguration *config)
1979 {
1980 iter_action(buf, start, config);
1981 return 0;
1982 }
1983 };
1984
1985 struct VectorLooper : public CollectionLooper<VectorLooper>
1986 {
1987 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
1988
1989 template <bool kIsText>
1991 template <bool kIsText>
1993
1994 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1995 static inline Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1996 {
1997 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1998 //Idea: can we factor out the addition of fOffset
1999 // iter = (char*)iter + config->fOffset;
2000 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
2001 iter_action(buf, iter, config);
2002 }
2003 return 0;
2004 }
2005
2006 template <typename T>
2007 static inline Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2008 {
2009 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2010 iter = (char*)iter + config->fOffset;
2011 end = (char*)end + config->fOffset;
2012 for(; iter != end; iter = (char*)iter + incr ) {
2013 T *x = (T*) ((char*) iter);
2014 buf >> *x;
2015 }
2016 return 0;
2017 }
2018
2019 template <typename From, typename To>
2021 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2022 {
2023 // Simple conversion from a 'From' on disk to a 'To' in memory.
2024 From temp;
2025 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2026 iter = (char*)iter + config->fOffset;
2027 end = (char*)end + config->fOffset;
2028 for(; iter != end; iter = (char*)iter + incr ) {
2029 buf >> temp;
2030 *(To*)( ((char*)iter) ) = (To)temp;
2031 }
2032 return 0;
2033 }
2034 };
2035
2036 template <typename To>
2038 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2039 {
2040 // Simple conversion from a 'From' on disk to a 'To' in memory.
2041 UInt_t temp;
2042 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2043 iter = (char*)iter + config->fOffset;
2044 end = (char*)end + config->fOffset;
2045 for(; iter != end; iter = (char*)iter + incr ) {
2046 buf >> temp;
2047
2048 if ((temp & kIsReferenced) != 0) {
2049 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
2050 }
2051
2052 *(To*)( ((char*)iter) ) = (To)temp;
2053 }
2054 return 0;
2055 }
2056 };
2057
2058 template <typename From, typename To>
2060 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2061 {
2062 // Simple conversion from a 'From' on disk to a 'To' in memory.
2064 From temp;
2065 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2066 iter = (char*)iter + config->fOffset;
2067 end = (char*)end + config->fOffset;
2068 for(; iter != end; iter = (char*)iter + incr ) {
2069 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2070 *(To*)( ((char*)iter) ) = (To)temp;
2071 }
2072 return 0;
2073 }
2074 };
2075
2076 template <typename From, typename To>
2078 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2079 {
2080 // Simple conversion from a 'From' on disk to a 'To' in memory.
2081 TConfNoFactor *conf = (TConfNoFactor *)config;
2082 From temp;
2083 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2084 iter = (char*)iter + config->fOffset;
2085 end = (char*)end + config->fOffset;
2086 for(; iter != end; iter = (char*)iter + incr ) {
2087 buf.ReadWithNbits(&temp, conf->fNbits);
2088 *(To*)( ((char*)iter) ) = (To)temp;
2089 }
2090 return 0;
2091 }
2092 };
2093
2094 template <typename T>
2095 static inline Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2096 {
2097 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2098 iter = (char*)iter + config->fOffset;
2099 end = (char*)end + config->fOffset;
2100 for(; iter != end; iter = (char*)iter + incr ) {
2101 T *x = (T*) ((char*) iter);
2102 buf << *x;
2103 }
2104 return 0;
2105 }
2106
2107 template <typename Onfile, typename Memory>
2109 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2110 {
2111 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2112 iter = (char*)iter + config->fOffset;
2113 end = (char*)end + config->fOffset;
2114 for(; iter != end; iter = (char*)iter + incr ) {
2115 // Simple conversion from a 'From' on disk to a 'To' in memory.
2116 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2117 buf << temp;
2118 }
2119 return 0;
2120 }
2121 };
2122
2123 template <typename Onfile, typename Memory>
2125 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2126 {
2127 const TStreamerElement *elem = config->fCompInfo->fElem;
2128 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2129 iter = (char*)iter + config->fOffset;
2130 end = (char*)end + config->fOffset;
2131 for(; iter != end; iter = (char*)iter + incr ) {
2132 // Simple conversion from a 'From' on disk to a 'To' in memory.
2133 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2134 WriteCompressed(buf, &temp, elem);
2135 }
2136 return 0;
2137 }
2138 };
2139
2140 template <typename Onfile, typename Memory>
2142 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
2143 {
2144 const TStreamerElement *elem = config->fCompInfo->fElem;
2145 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2146 iter = (char*)iter + config->fOffset;
2147 end = (char*)end + config->fOffset;
2148 for(; iter != end; iter = (char*)iter + incr ) {
2149 // Simple conversion from a 'From' on disk to a 'To' in memory.
2150 Onfile temp = (Onfile)(*(Memory*)((char*) iter));
2151 WriteCompressed(buf, &temp, elem);
2152 }
2153 return 0;
2154 }
2155 };
2156
2157 static inline Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2158 {
2159 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2160 // punt.
2161
2162 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2163 UInt_t n = (((char*)end)-((char*)start))/incr;
2164 char **arrptr = new char*[n];
2165 UInt_t i = 0;
2166 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2167 arrptr[i] = (char*)iter;
2168 }
2169 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2170 delete [] arrptr;
2171 return 0;
2172 }
2173
2174 static inline Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2175 {
2176 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2177 // punt.
2178
2179 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2180 UInt_t n = (((char*)end)-((char*)start))/incr;
2181 char **arrptr = new char*[n];
2182 UInt_t i = 0;
2183 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2184 arrptr[i] = (char*)iter;
2185 }
2186 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2187 delete [] arrptr;
2188 return 0;
2189 }
2190
2191 static inline Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2192 {
2193 // Well the implementation is non trivial. For now punt.
2194
2195 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2196 UInt_t n = (((char*)end)-((char*)start))/incr;
2197 char **arrptr = new char*[n];
2198 UInt_t i = 0;
2199 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2200 arrptr[i] = (char*)iter;
2201 }
2202 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2203 delete [] arrptr;
2204 return 0;
2205 }
2206
2207 static inline Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2208 {
2209 // Well the implementation is non trivial. For now punt.
2210
2211 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
2212 UInt_t n = (((char*)end)-((char*)start))/incr;
2213 char **arrptr = new char*[n];
2214 UInt_t i = 0;
2215 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
2216 arrptr[i] = (char*)iter;
2217 }
2218 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2219 delete [] arrptr;
2220 return 0;
2221 }
2222
2223 template <typename T>
2225 {
2226 // Collection of numbers. Memberwise or not, it is all the same.
2227
2228 TConfigSTL *config = (TConfigSTL*)conf;
2229 UInt_t start, count;
2230 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2231
2232 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2233 Int_t nvalues;
2234 buf.ReadInt(nvalues);
2235 vec->resize(nvalues);
2236
2237#ifdef R__VISUAL_CPLUSPLUS
2238 if (nvalues <= 0) {
2239 buf.CheckByteCount(start,count,config->fTypeName);
2240 return 0;
2241 }
2242#endif
2243 T *begin = vec->data();
2244 buf.ReadFastArray(begin, nvalues);
2245
2246 buf.CheckByteCount(start,count,config->fTypeName);
2247 return 0;
2248 }
2249
2250 template <typename T>
2252 {
2253 // Collection of numbers. Memberwise or not, it is all the same.
2254
2255 TConfigSTL *config = (TConfigSTL*)conf;
2256 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2257
2258 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
2259 Int_t nvalues = vec->size();
2260 buf.WriteInt(nvalues);
2261
2262 T *begin = vec->data();
2263 buf.WriteFastArray(begin, nvalues);
2264
2265 buf.SetByteCount(start);
2266 return 0;
2267 }
2268
2270 {
2271 // Collection of numbers. Memberwise or not, it is all the same.
2272
2273 TConfigSTL *config = (TConfigSTL*)conf;
2274 UInt_t start, count;
2275 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2276
2277 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2278 Int_t nvalues;
2279 buf.ReadInt(nvalues);
2280 vec->resize(nvalues);
2281
2282#ifdef R__VISUAL_CPLUSPLUS
2283 if (nvalues <= 0) {
2284 buf.CheckByteCount(start,count,config->fTypeName);
2285 return 0;
2286 }
2287#endif
2288 float *begin = vec->data();
2289 buf.ReadFastArrayFloat16(begin, nvalues);
2290
2291 buf.CheckByteCount(start,count,config->fTypeName);
2292 return 0;
2293 }
2294
2296 {
2297 // Collection of numbers. Memberwise or not, it is all the same.
2298
2299 TConfigSTL *config = (TConfigSTL*)conf;
2300 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2301
2302 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
2303 Int_t nvalues = vec->size();
2304 buf.WriteInt(nvalues);
2305
2306 float *begin = vec->data();
2307 buf.WriteFastArrayFloat16(begin, nvalues);
2308
2309 buf.SetByteCount(start);
2310 return 0;
2311 }
2312
2314 {
2315 // Collection of numbers. Memberwise or not, it is all the same.
2316
2317 TConfigSTL *config = (TConfigSTL*)conf;
2318 UInt_t start, count;
2319 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2320
2321 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2322 Int_t nvalues;
2323 buf.ReadInt(nvalues);
2324 vec->resize(nvalues);
2325
2326#ifdef R__VISUAL_CPLUSPLUS
2327 if (nvalues <= 0) {
2328 buf.CheckByteCount(start,count,config->fTypeName);
2329 return 0;
2330 }
2331#endif
2332 double *begin = vec->data();
2333 buf.ReadFastArrayDouble32(begin, nvalues);
2334
2335 buf.CheckByteCount(start,count,config->fTypeName);
2336 return 0;
2337 }
2338
2340 {
2341 // Collection of numbers. Memberwise or not, it is all the same.
2342
2343 TConfigSTL *config = (TConfigSTL*)conf;
2344 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2345
2346 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
2347 Int_t nvalues = vec->size();
2348 buf.WriteInt(nvalues);
2349
2350 double *begin = vec->data();
2351 buf.WriteFastArrayDouble32(begin, nvalues);
2352
2353 buf.SetByteCount(start);
2354 return 0;
2355 }
2356
2357 template <typename From, typename To>
2359 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2360 {
2361 // Collection of numbers. Memberwise or not, it is all the same.
2362
2363 TConfigSTL *config = (TConfigSTL*)conf;
2364 UInt_t start, count;
2365 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2366
2367 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2368 Int_t nvalues;
2369 buf.ReadInt(nvalues);
2370 vec->resize(nvalues);
2371
2372 From *temp = new From[nvalues];
2373 buf.ReadFastArray(temp, nvalues);
2374 for(Int_t ind = 0; ind < nvalues; ++ind) {
2375 (*vec)[ind] = (To)temp[ind];
2376 }
2377 delete [] temp;
2378
2379 buf.CheckByteCount(start,count,config->fTypeName);
2380 return 0;
2381 }
2382 };
2383
2384 template <typename From, typename To>
2386 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2387 {
2388 // Collection of numbers. Memberwise or not, it is all the same.
2389
2390 TConfigSTL *config = (TConfigSTL*)conf;
2391 UInt_t start, count;
2392 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2393
2394 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2395 Int_t nvalues;
2396 buf.ReadInt(nvalues);
2397 vec->resize(nvalues);
2398
2399 From *temp = new From[nvalues];
2400 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2401 for(Int_t ind = 0; ind < nvalues; ++ind) {
2402 (*vec)[ind] = (To)temp[ind];
2403 }
2404 delete [] temp;
2405
2406 buf.CheckByteCount(start,count,config->fTypeName);
2407 return 0;
2408 }
2409 };
2410
2411 template <typename To>
2413 {
2414 // Collection of numbers. Memberwise or not, it is all the same.
2415
2416 TConfigSTL *config = (TConfigSTL*)conf;
2417 UInt_t start, count;
2418 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2419
2420 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2421 Int_t nvalues;
2422 buf.ReadInt(nvalues);
2423 vec->resize(nvalues);
2424
2425 Double32_t *temp = new Double32_t[nvalues];
2426 buf.ReadFastArrayDouble32(temp, nvalues);
2427 for(Int_t ind = 0; ind < nvalues; ++ind) {
2428 (*vec)[ind] = (To)temp[ind];
2429 }
2430 delete [] temp;
2431
2432 buf.CheckByteCount(start,count,config->fTypeName);
2433 return 0;
2434 }
2435
2436 template <typename Memory, typename Onfile>
2438 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2439 {
2440 // Collection of numbers. Memberwise or not, it is all the same.
2441
2442 TConfigSTL *config = (TConfigSTL*)conf;
2443 UInt_t start = buf.WriteVersion( config->fInfo->IsA(), kTRUE );
2444
2445 std::vector<Memory> *const vec = (std::vector<Memory>*)(((char*)addr)+config->fOffset);
2446 Int_t nvalues = vec->size();
2447 buf.WriteInt(nvalues);
2448
2449 // We have to call WriteFastArray for proper JSON writing
2450 // So we need to convert before hand :(
2451 Onfile *temp = new Onfile[nvalues];
2452 for(Int_t ind = 0; ind < nvalues; ++ind) {
2453 temp[ind] = (Onfile)((*vec)[ind]);
2454 }
2455 buf.WriteFastArray(temp, nvalues);
2456 delete [] temp;
2457
2458 buf.SetByteCount(start, kTRUE);
2459 return 0;
2460 }
2461 };
2462 };
2463
2464 struct VectorPtrLooper : public CollectionLooper<VectorPtrLooper> {
2465 // Can not inherit/use CollectionLooper<VectorPtrLooper>, because this looper's
2466 // function do not take a `TLoopConfiguration`.
2467
2468 using LoopAction_t = Int_t (*)(TBuffer &, void *start, const void *end, const TConfiguration*);
2469
2470 template <bool kIsText>
2472 template <bool kIsText>
2474
2475 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2477 {
2478 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2479 return unique_ptr(info.GetReadMemberWiseActions(kTRUE)->CreateCopy());
2480 }
2481
2482 static std::unique_ptr<TStreamerInfoActions::TActionSequence>
2484 {
2485 using unique_ptr = std::unique_ptr<TStreamerInfoActions::TActionSequence>;
2486 return unique_ptr(info.GetWriteMemberWiseActions(kTRUE)->CreateCopy());
2487 }
2488
2489 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2490 static inline Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2491 {
2492 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2493 action(buf, *(void**)iter, config);
2494 }
2495 return 0;
2496 }
2497
2498 static inline Int_t SubSequenceAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2499 {
2500 auto conf = (TConfSubSequence*)config;
2501 auto actions = conf->fActions.get();
2502 // FIXME: need to update the signature of ApplySequence.
2503 buf.ApplySequenceVecPtr(*actions, start, const_cast<void*>(end));
2504 return 0;
2505 }
2506
2507 template <typename T>
2508 static inline Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2509 {
2510 const Int_t offset = config->fOffset;
2511
2512 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2513 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2514 buf >> *x;
2515 }
2516 return 0;
2517 }
2518
2519 template <typename From, typename To>
2521 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2522 {
2523 // Simple conversion from a 'From' on disk to a 'To' in memory.
2524 From temp;
2525 const Int_t offset = config->fOffset;
2526 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2527 buf >> temp;
2528 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2529 *x = (To)temp;
2530 }
2531 return 0;
2532 }
2533 };
2534
2535 template <typename To>
2537 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2538 {
2539 // Simple conversion from a 'From' on disk to a 'To' in memory.
2540 UInt_t temp;
2541 const Int_t offset = config->fOffset;
2542 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2543 buf >> temp;
2544
2545 if ((temp & kIsReferenced) != 0) {
2546 HandleReferencedTObject(buf,*(void**)iter,config);
2547 }
2548
2549 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2550 *x = (To)temp;
2551 }
2552 return 0;
2553 }
2554 };
2555
2556 template <typename From, typename To>
2558 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2559 {
2560 // Simple conversion from a 'From' on disk to a 'To' in memory.
2562 From temp;
2563 const Int_t offset = config->fOffset;
2564 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2565 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2566 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2567 *x = (To)temp;
2568 }
2569 return 0;
2570 }
2571 };
2572
2573 template <typename From, typename To>
2575 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2576 {
2577 // Simple conversion from a 'From' on disk to a 'To' in memory.
2578 TConfNoFactor *conf = (TConfNoFactor *)config;
2579 From temp;
2580 const Int_t offset = config->fOffset;
2581 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2582 buf.ReadWithNbits(&temp, conf->fNbits);
2583 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2584 *x = (To)temp;
2585 }
2586 return 0;
2587 }
2588 };
2589
2590 template <typename T>
2591 static inline Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2592 {
2593 const Int_t offset = config->fOffset;
2594
2595 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2596 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2597 buf << *x;
2598 }
2599 return 0;
2600 }
2601
2602 template <typename To, typename From>
2604 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2605 {
2606 const Int_t offset = config->fOffset;
2607
2608 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2609 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2610 To to = (To)(*from);
2611 buf << to;
2612 }
2613 return 0;
2614 }
2615 };
2616
2617 template <typename To, typename From>
2619 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2620 {
2621 const Int_t offset = config->fOffset;
2622 const TStreamerElement *elem = config->fCompInfo->fElem;
2623
2624 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2625 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2626 To to = (To)(*from);
2627 WriteCompressed(buf, &to, elem);
2628 }
2629 return 0;
2630 }
2631 };
2632 template <typename To, typename From>
2634 static inline Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2635 {
2636 const Int_t offset = config->fOffset;
2637 const TStreamerElement *elem = config->fCompInfo->fElem;
2638
2639 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2640 From *from = (From*)( ((char*) (*(void**)iter) ) + offset );
2641 To to = (To)(*from);
2642 WriteCompressed(buf, &to, elem);
2643 }
2644 return 0;
2645 }
2646 };
2647
2648 static inline Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2649 {
2650 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2651 // punt.
2652
2653 return GenericRead(buf,start,end,config);
2654 }
2655
2656 static inline Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2657 {
2658 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2659 // punt.
2660
2661 return GenericWrite(buf,start,end,config);
2662 }
2663
2664 static inline Int_t ReadStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2665 {
2666 UInt_t pos, count;
2667 /* Version_t v = */ buf.ReadVersion(&pos, &count, config->fInfo->IsA());
2668
2669 LoopOverCollection< ReadViaExtStreamer >(buf, start, end, config);
2670
2671 buf.CheckByteCount(pos, count, config->fCompInfo->fElem->GetFullName());
2672 return 0;
2673 }
2674
2675 static inline Int_t WriteStreamerCase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2676 {
2677 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2678
2680
2681 buf.SetByteCount(pos, kTRUE);
2682 return 0;
2683 }
2684
2685 static inline Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2686 {
2687 Int_t n = ( ((void**)end) - ((void**)iter) );
2688 char **arr = (char**)iter;
2689 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2690 }
2691
2692 static inline Int_t GenericWrite(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)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2697 }
2698
2699 };
2700
2702 using LoopAction_t = void (*)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem);
2703
2704protected:
2705
2706 template <typename T>
2707 static inline void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2708 {
2709 buf.ReadFastArray((T*)addr, nvalues);
2710 }
2711
2712 static inline void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2713 {
2714 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2715 }
2716
2717 static inline void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2718 {
2719 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2720 }
2721
2722 template <typename T>
2723 static inline void SimpleWrite(TBuffer &buf, void *addr, const TStreamerElement *)
2724 {
2725 buf << *(T*)addr;
2726 }
2727
2728 static inline void SimpleWriteFloat16(TBuffer &buf, void *addr, const TStreamerElement *elem)
2729 {
2730 buf.WriteFloat16((float*)addr, const_cast<TStreamerElement*>(elem));
2731 }
2732
2733 static inline void SimpleWriteDouble32(TBuffer &buf, void *addr, const TStreamerElement *elem)
2734 {
2735 buf.WriteDouble32((double*)addr, const_cast<TStreamerElement*>(elem));
2736 }
2737
2738 template <typename T>
2739 static inline void ArrayWrite(TBuffer &buf, void *addr, Int_t nvalues, const TStreamerElement *)
2740 {
2741 buf.WriteFastArray((T*)addr, nvalues);
2742 }
2743
2745 {
2746 buf.WriteFastArrayFloat16((float*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2747 }
2748
2750 {
2751 buf.WriteFastArrayDouble32((double*)addr, nvalues, const_cast<TStreamerElement*>(elem));
2752 }
2753
2754 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2756 {
2757 // Collection of numbers. Memberwise or not, it is all the same.
2758
2759 TConfigSTL *config = (TConfigSTL*)conf;
2760 UInt_t start, count;
2761 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2762
2763 TClass *newClass = config->fNewClass;
2764 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2766
2767 Int_t nvalues;
2768 buf.ReadInt(nvalues);
2769 void* alternative = newProxy->Allocate(nvalues,true);
2770 if (nvalues) {
2773 void *begin = &(startbuf[0]);
2774 void *end = &(endbuf[0]);
2775 config->fCreateIterators(alternative, &begin, &end, newProxy);
2776 // We can not get here with a split vector of pointer, so we can indeed assume
2777 // that actions->fConfiguration != null.
2778
2779 action(buf,begin,nvalues);
2780
2781 if (begin != &(startbuf[0])) {
2782 // assert(end != endbuf);
2783 config->fDeleteTwoIterators(begin,end);
2784 }
2785 }
2786 newProxy->Commit(alternative);
2787
2788 buf.CheckByteCount(start,count,config->fTypeName);
2789 return 0;
2790 }
2791
2792 template <void (*action)(TBuffer&, void*, const TStreamerElement*)>
2793 static inline void LoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t /* nvalues */, const TStreamerElement *elem)
2794 {
2795 void *addr;
2796 while( (addr = next(iter, end)) )
2797 {
2798 action(buf, addr, elem);
2799 }
2800 }
2801
2802 template <typename Memory, typename Onfile, void (*action)(TBuffer&, void*, Int_t, const TStreamerElement *elem)>
2803 static inline void ConvertLoopOverCollection(TBuffer &buf, void *iter, const void *end, Next_t next, Int_t nvalues, const TStreamerElement *elem)
2804 {
2805 Onfile *temp = new Onfile[nvalues];
2806 Int_t ind = 0;
2807 void *addr;
2808 while( (addr = next(iter, end)) )
2809 {
2810 temp[ind] = (Onfile)*(Memory*)addr;
2811 ++ind;
2812 }
2813 action(buf, temp, nvalues, elem);
2814 delete [] temp;
2815 }
2816
2817 template <typename T, void (*action)(TBuffer&, void *, const void *, Next_t, Int_t, const TStreamerElement *elem)>
2819 {
2820 // Collection of numbers. Memberwise or not, it is all the same.
2821
2822 TConfigSTL *config = (TConfigSTL*)conf;
2823 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
2824
2825 TClass *newClass = config->fNewClass;
2826 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2827 void *collection = ((char*)addr)+config->fOffset;
2829
2830 Int_t nvalues = newProxy->Size();
2831 buf.WriteInt(nvalues);
2832 if (nvalues) {
2835 void *begin = &(startbuf[0]);
2836 void *end = &(endbuf[0]);
2837 config->fCreateIterators(collection, &begin, &end, newProxy);
2838
2839 action(buf, begin, end, config->fNext, nvalues, config->fCompInfo->fElem);
2840
2841 if (begin != &(startbuf[0])) {
2842 // assert(end != endbuf);
2843 config->fDeleteTwoIterators(begin, end);
2844 }
2845 }
2846 buf.SetByteCount(start);
2847 return 0;
2848 }
2849
2850public:
2855
2860
2865
2870
2871 template <typename T>
2876
2877 template <typename T>
2882
2883 template <typename From, typename To>
2885 static inline void Action(TBuffer &buf, void *addr, Int_t nvalues)
2886 {
2887 From *temp = new From[nvalues];
2888 buf.ReadFastArray(temp, nvalues);
2889 To *vec = (To*)addr;
2890 for(Int_t ind = 0; ind < nvalues; ++ind) {
2891 vec[ind] = (To)temp[ind];
2892 }
2893 delete [] temp;
2894 }
2895 };
2896
2897 template <typename From, typename To>
2899 static inline void Action(TBuffer &buf, void *addr, Int_t nvalues)
2900 {
2901 From *temp = new From[nvalues];
2902 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2903 To *vec = (To*)addr;
2904 for(Int_t ind = 0; ind < nvalues; ++ind) {
2905 vec[ind] = (To)temp[ind];
2906 }
2907 delete [] temp;
2908 }
2909 };
2910
2911 template <typename From, typename To>
2913 static inline void Action(TBuffer &buf, void *addr, Int_t nvalues)
2914 {
2915 From *temp = new From[nvalues];
2916 double factor,min; // needs to be initialized.
2917 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2918 To *vec = (To*)addr;
2919 for(Int_t ind = 0; ind < nvalues; ++ind) {
2920 vec[ind] = (To)temp[ind];
2921 }
2922 delete [] temp;
2923 }
2924 };
2925 template <typename From, typename To>
2932
2933 template <typename Memory, typename Onfile>
2940 template <typename Memory, typename Onfile>
2947
2948 template <typename Memory, typename Onfile>
2955
2956 };
2957
2958 struct GenericLooper : public CollectionLooper<GenericLooper> {
2959 using LoopAction_t = Int_t (*)(TBuffer &, void*, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration*);
2960
2961 template <bool kIsText>
2963 template <bool kIsText>
2965
2966 template <typename T>
2967 static inline Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2968 {
2970
2971 Next_t next = loopconfig->fNext;
2972 const Int_t offset = config->fOffset;
2973
2975 void *iter = loopconfig->fCopyIterator(iterator,start);
2976 void *addr;
2977 while( (addr = next(iter,end)) ) {
2978 T *x = (T*)( ((char*)addr) + offset );
2979 buf >> *x;
2980 }
2981 if (iter != &iterator[0]) {
2982 loopconfig->fDeleteIterator(iter);
2983 }
2984 return 0;
2985 }
2986
2987 template <typename T>
2988 static inline Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2989 {
2991
2992 Next_t next = loopconfig->fNext;
2993 const Int_t offset = config->fOffset;
2994
2996 void *iter = loopconfig->fCopyIterator(iterator,start);
2997 void *addr;
2998 while( (addr = next(iter,end)) ) {
2999 T *x = (T*)( ((char*)addr) + offset );
3000 buf << *x;
3001 }
3002 if (iter != &iterator[0]) {
3003 loopconfig->fDeleteIterator(iter);
3004 }
3005 return 0;
3006 }
3007
3008 template <typename To, typename From>
3010 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3011 {
3013
3014 Next_t next = loopconfig->fNext;
3015 const Int_t offset = config->fOffset;
3016
3018 void *iter = loopconfig->fCopyIterator(iterator,start);
3019 void *addr;
3020 while( (addr = next(iter,end)) ) {
3021 From *x = (From*)( ((char*)addr) + offset );
3022 To t = (To)(*x);
3023 buf << t;
3024 }
3025 if (iter != &iterator[0]) {
3026 loopconfig->fDeleteIterator(iter);
3027 }
3028 return 0;
3029 }
3030 };
3031
3032 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
3033 static inline Int_t LoopOverCollection(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3034 {
3036
3037 // const Int_t offset = config->fOffset;
3038 Next_t next = loopconfig->fNext;
3039
3041 void *iter = loopconfig->fCopyIterator(&iterator,start);
3042 void *addr;
3043 while( (addr = next(iter,end)) ) {
3044 iter_action(buf, addr, config);
3045 }
3046 if (iter != &iterator[0]) {
3047 loopconfig->fDeleteIterator(iter);
3048 }
3049 return 0;
3050 }
3051
3052 template <typename From, typename To>
3053 struct Generic {
3054 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3055 {
3057
3058 const Int_t offset = config->fOffset;
3059 Next_t next = loopconfig->fNext;
3060
3062 void *iter = loopconfig->fCopyIterator(&iterator,start);
3063 void *addr;
3064 while( (addr = next(iter,end)) ) {
3065 To *x = (To*)( ((char*)addr) + offset );
3066 *x = (To)(*items);
3067 ++items;
3068 }
3069 if (iter != &iterator[0]) {
3070 loopconfig->fDeleteIterator(iter);
3071 }
3072 }
3073 // ConvertAction used for writing.
3074 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config, To *items)
3075 {
3077
3078 const Int_t offset = config->fOffset;
3079 Next_t next = loopconfig->fNext;
3080
3082 void *iter = loopconfig->fCopyIterator(&iterator,start);
3083 void *addr;
3084
3085 while( (addr = next(iter,end)) ) {
3086 From *x = (From*)( ((char*)addr) + offset );
3087 *items = (To)*x;
3088 ++items;
3089 }
3090 if (iter != &iterator[0]) {
3091 loopconfig->fDeleteIterator(iter);
3092 }
3093 }
3094 };
3095
3096 template <typename From, typename To>
3097 struct Numeric {
3098 // ConvertAction used for reading.
3099 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
3100 {
3101 // The difference with ConvertAction is that we can modify the start
3102 // iterator and skip the copy. We also never have an offset.
3103
3105 Next_t next = loopconfig->fNext;
3106
3107 void *iter = start;
3108 void *addr;
3109 while( (addr = next(iter,end)) ) {
3110 To *x = (To*)(addr);
3111 *x = (To)(*items);
3112 ++items;
3113 }
3114 }
3115 // ConvertAction used for writing.
3116 static void WriteConvertAction(void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */, To *items)
3117 {
3118 // The difference with ConvertAction is that we can modify the start
3119 // iterator and skip the copy. We also never have an offset.
3120
3122 Next_t next = loopconfig->fNext;
3123
3124 void *iter = start;
3125 void *addr;
3126 while( (addr = next(iter,end)) ) {
3127 From *x = (From*)(addr);
3128 *items = (To)*x;
3129 ++items;
3130 }
3131 }
3132 };
3133
3134 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
3136 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3137 {
3138 // Simple conversion from a 'From' on disk to a 'To' in memory.
3139
3142 Int_t nvalues = proxy->Size();
3143
3144 From *items = new From[nvalues];
3145 buf.ReadFastArray(items, nvalues);
3146 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3147 delete [] items;
3148 return 0;
3149 }
3150 };
3151
3152 template <typename To>
3154 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3155 {
3156 // Simple conversion from a 'From' on disk to a 'To' in memory.
3157
3160 Int_t nvalues = proxy->Size();
3161
3164
3165 const Int_t offset = config->fOffset;
3166 Next_t next = loopconfig->fNext;
3167
3169 void *iter = loopconfig->fCopyIterator(&iterator,start);
3170 void *addr;
3171 while( (addr = next(iter,end)) ) {
3172 buf >> (*items);
3173 if (((*items) & kIsReferenced) != 0) {
3175 }
3176 To *x = (To*)( ((char*)addr) + offset );
3177 *x = (To)(*items);
3178 ++items;
3179 }
3180 if (iter != &iterator[0]) {
3181 loopconfig->fDeleteIterator(iter);
3182 }
3183
3184 delete [] items_storage;
3185 return 0;
3186 }
3187 };
3188
3189 template <typename From, typename To, template <typename F, typename T> class Converter >
3191 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3192 {
3193 // Simple conversion from a 'From' on disk to a 'To' in memory.
3194
3197 Int_t nvalues = proxy->Size();
3198
3200
3201 From *items = new From[nvalues];
3202 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
3203 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3204 delete [] items;
3205 return 0;
3206 }
3207 };
3208
3209 template <typename From, typename To, template <typename F, typename T> class Converter >
3211 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3212 {
3213 // Simple conversion from a 'From' on disk to a 'To' in memory.
3214
3217 Int_t nvalues = proxy->Size();
3218
3220
3221 From *items = new From[nvalues];
3222 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
3223 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
3224 delete [] items;
3225 return 0;
3226 }
3227 };
3228
3229 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter = Generic >
3231 static inline Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3232 {
3233 // Simple conversion from a 'From' on disk to a 'To' in memory.
3234
3237 Int_t nvalues = proxy->Size();
3238
3239 Onfile *items = new Onfile[nvalues];
3240 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3241 buf.WriteFastArray(items, nvalues);
3242 delete [] items;
3243 return 0;
3244 }
3245 };
3246
3247 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3249 static inline Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3250 {
3251 // Simple conversion from a 'From' on disk to a 'To' in memory.
3252
3255 Int_t nvalues = proxy->Size();
3256
3258
3259 Onfile *items = new Onfile[nvalues];
3260 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3261 R__ASSERT(false && "Not yet implemented");
3262 (void)conf;
3263 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3264 delete [] items;
3265 return 0;
3266 }
3267 };
3268
3269 template <typename Onfile, typename Memory, template <typename F, typename T> class Converter >
3271 static inline Int_t Action(TBuffer & /* buf */, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
3272 {
3273 // Simple conversion from a 'From' on disk to a 'To' in memory.
3274
3277 Int_t nvalues = proxy->Size();
3278
3280
3281 Onfile *items = new Onfile[nvalues];
3282 Converter<Memory,Onfile>::WriteConvertAction(start, end, loopconfig, config, items);
3283 R__ASSERT(false && "Not yet implemented");
3284 (void)conf;
3285 // buf.WriteFastArrayWithNbits(items, nvalues, conf->fNbits);
3286 delete [] items;
3287 return 0;
3288 }
3289 };
3290
3291 static inline Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3292 {
3293 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3294 // punt.
3295
3296 return GenericRead(buf,start,end,loopconfig, config);
3297 }
3298
3299 static inline Int_t WriteBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
3300 {
3301 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
3302 // punt.
3303
3304 return GenericWrite(buf,start,end,loopconfig, config);
3305 }
3306
3307 static inline Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3308 {
3311 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
3312 }
3313
3314 static inline Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
3315 {
3318 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
3319 }
3320
3321 template <typename T>
3322 static inline void SimpleRead(TBuffer &buf, void *addr)
3323 {
3324 buf >> *(T*)addr;
3325 }
3326
3327 static inline void SimpleReadFloat16(TBuffer &buf, void *addr)
3328 {
3329 buf.ReadWithNbits((float*)addr,12);
3330 }
3331
3332 static inline void SimpleWriteFloat16(TBuffer &buf, void *addr)
3333 {
3334 buf.WriteFloat16((float*)addr, nullptr);
3335 }
3336
3337 static inline void SimpleReadDouble32(TBuffer &buf, void *addr)
3338 {
3339 //we read a float and convert it to double
3341 buf >> afloat;
3342 *(double*)addr = (Double_t)afloat;
3343 }
3344
3345 static inline void SimpleWriteDouble32(TBuffer &buf, void *addr)
3346 {
3347 //we read a float and convert it to double
3348 Float_t afloat = (Float_t)*(double*)addr;
3349 buf << afloat;
3350 }
3351
3352 template <typename ActionHolder>
3354 {
3355 // Collection of numbers. Memberwise or not, it is all the same.
3356
3357 TConfigSTL *config = (TConfigSTL*)conf;
3358 UInt_t start, count;
3359 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
3360
3361 TClass *newClass = config->fNewClass;
3362 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3364
3365 Int_t nvalues;
3366 buf.ReadInt(nvalues);
3367 void* alternative = newProxy->Allocate(nvalues,true);
3368 if (nvalues) {
3371 void *begin = &(startbuf[0]);
3372 void *end = &(endbuf[0]);
3373 config->fCreateIterators(alternative, &begin, &end, newProxy);
3374 // We can not get here with a split vector of pointer, so we can indeed assume
3375 // that actions->fConfiguration != null.
3376
3378 ActionHolder::Action(buf,begin,end,&loopconf,config);
3379
3380 if (begin != &(startbuf[0])) {
3381 // assert(end != endbuf);
3382 config->fDeleteTwoIterators(begin,end);
3383 }
3384 }
3385 newProxy->Commit(alternative);
3386
3387 buf.CheckByteCount(start,count,config->fTypeName);
3388 return 0;
3389 }
3390
3391 template <typename ActionHolder>
3393 {
3394 // Collection of numbers. Memberwise or not, it is all the same.
3395
3396 TConfigSTL *config = (TConfigSTL*)conf;
3397 UInt_t start = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
3398
3399 TClass *newClass = config->fNewClass;
3400 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
3401 void *collection = ((char*)addr)+config->fOffset;
3403
3404 Int_t nvalues = newProxy->Size();
3405 buf.WriteInt(nvalues);
3406 if (nvalues) {
3409 void *begin = &(startbuf[0]);
3410 void *end = &(endbuf[0]);
3411 config->fCreateIterators(collection, &begin, &end, newProxy);
3412 // We can not get here with a split vector of pointer, so we can indeed assume
3413 // that actions->fConfiguration != null.
3414
3416 ActionHolder::Action(buf,begin,end,&loopconf,config);
3417
3418 if (begin != &(startbuf[0])) {
3419 // assert(end != endbuf);
3420 config->fDeleteTwoIterators(begin,end);
3421 }
3422 }
3423
3424 buf.SetByteCount(start);
3425 return 0;
3426 }
3427
3432
3437
3439 {
3441 // Could also use:
3442 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
3443 }
3444
3446 {
3448 // Could also use:
3449 // return ReadNumericalCollection<WriteConvertBasicType<NoFactorMarker<double>, double, Numeric > >(buf,addr,conf);
3450 }
3451
3452 template <typename T>
3454 {
3455 //TODO: Check whether we can implement this without loading the data in
3456 // a temporary variable and whether this is noticeably faster.
3458 }
3459
3460 template <typename T>
3462 {
3463 //TODO: Check whether we can implement this without loading the data in
3464 // a temporary variable and whether this is noticeably faster.
3466 }
3467
3468 template <typename From, typename To>
3470 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
3471 {
3472 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3474 }
3475 };
3476
3477 template <typename Memory, typename Onfile>
3479 static inline Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
3480 {
3481 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
3483 }
3484 };
3485 };
3486}
3487
3488// Used in GetCollectionReadAction for the kConv cases within a collection
3489// Not to be confused with GetConvertCollectionReadAction
3490template <typename Looper, typename From>
3492{
3493 switch (newtype) {
3510 default:
3511 return TConfiguredAction( Looper::GenericRead, conf );
3512 }
3513 R__ASSERT(0); // We should never be here
3514 return TConfiguredAction();
3515}
3516
3517template <class Looper>
3519{
3520 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
3521
3522 switch (type) {
3523 // Read basic types.
3524
3525 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
3526 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<bool,bool>::Action, conf );
3539 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
3542 delete conf;
3543 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
3544 // if (element->GetFactor() != 0) {
3545 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3546 // } else {
3547 // Int_t nbits = (Int_t)element->GetXmin();
3548 // if (!nbits) nbits = 12;
3549 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3550 // }
3551 }
3554 delete conf;
3555 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
3556 // if (element->GetFactor() != 0) {
3557 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3558 // } else {
3559 // Int_t nbits = (Int_t)element->GetXmin();
3560 // if (!nbits) {
3561 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
3562 // } else {
3563 // return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3564 // }
3565 // }
3566 }
3567 }
3568 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
3569 R__ASSERT(0); // We should never be here
3570 return TConfiguredAction();
3571}
3572
3573template <typename Looper, typename From>
3575{
3576 switch (newtype) {
3577 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf );
3578 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf );
3579 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf );
3580 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf );
3581 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf );
3582 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf );
3583 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3584 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf );
3585 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3586 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf );
3587 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf );
3588 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf );
3589 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3590 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf );
3591 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3592 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf );
3593 default:
3594 break;
3595 }
3596 Error("GetConvertCollectionReadActionFrom", "UNEXPECTED: newtype == %d", newtype);
3597 R__ASSERT(0); // We should never be here
3598 return TConfiguredAction();
3599}
3600
3601// Used in AddReadAction to implement the kSTL cases
3602// Not to be confused with GetCollectionReadConvertAction
3603// nor with GetConvertCollectionReadActionFrom (used to implement this function)
3604template <typename Looper>
3606{
3607 switch (oldtype) {
3639 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
3640 break;
3641 default:
3642 break;
3643 }
3644 Error("GetConvertCollectionReadAction", "UNEXPECTED: oldtype == %d", oldtype);
3645 R__ASSERT(0); // We should never be here
3646 return TConfiguredAction();
3647}
3648
3649template <class Looper>
3650static TConfiguredAction
3653{
3654 switch (type) {
3655 // Read basic types.
3671 if (element->GetFactor() != 0) {
3672 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3673 } else {
3674 Int_t nbits = (Int_t)element->GetXmin();
3675 if (!nbits) nbits = 12;
3676 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3677 }
3678 }
3680 if (element->GetFactor() != 0) {
3681 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
3682 } else {
3683 Int_t nbits = (Int_t)element->GetXmin();
3684 if (!nbits) {
3685 return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
3686 } else {
3687 return TConfiguredAction( Looper::template LoopOverCollection<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
3688 }
3689 }
3690 }
3693 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3694 // Streamer alltogether.
3702 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3703 case TStreamerInfo::kBase: {
3704 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3705 if (baseEl) {
3706 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
3708 auto baseActions = Looper::CreateReadActionSequence(*baseinfo, loopConfig);
3709 baseActions->AddToOffset(baseEl->GetOffset());
3710 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
3711
3712 } else
3713 return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info, i, compinfo) );
3714 }
3717 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
3718 return TConfiguredAction(Looper::template ReadStreamerLoop<false>::Action,
3720 }
3722 if (info->GetOldVersion() >= 3)
3723 return TConfiguredAction( Looper::ReadStreamerCase, new TGenericConfiguration(info, i, compinfo) );
3724 else
3725 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3727 if (compinfo->fStreamer)
3729 else {
3730 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
3732 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
3733 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
3735 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
3736 else // Use the slower path for unusual cases
3737 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info, i, compinfo) );
3738 }
3739
3740 // Conversions.
3770 if (element->GetFactor() != 0) {
3772 } else {
3773 Int_t nbits = (Int_t)element->GetXmin();
3774 if (!nbits) nbits = 12;
3776 }
3777 }
3779 if (element->GetFactor() != 0) {
3781 } else {
3782 Int_t nbits = (Int_t)element->GetXmin();
3783 if (!nbits) {
3785 } else {
3787 }
3788 }
3789 }
3790 default:
3791 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
3792 }
3793 R__ASSERT(0); // We should never be here
3794 return TConfiguredAction();
3795}
3796
3797template <typename Looper, typename From>
3799{
3800 switch (onfileType) {
3801 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,bool>::Action, conf );
3802 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,char>::Action, conf );
3803 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,short>::Action, conf );
3804 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Int_t>::Action, conf );
3805 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long_t>::Action, conf );
3806 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,Long64_t>::Action, conf );
3807 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,float>::Action, conf );
3808 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,double>::Action, conf );
3809 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UChar_t>::Action, conf );
3810 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UShort_t>::Action, conf );
3811 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3812 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong_t>::Action, conf );
3813 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,ULong64_t>::Action, conf );
3814 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,UInt_t>::Action, conf );
3815
3816 // Supporting this requires adding TBuffer::WiteFastArrayWithNbits
3817 // and the proper struct WriteConvertCollectionBasicType<Memory, NoFactorMarker<Onfile>> here
3819 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Float16_t not yet supported");
3820 return TConfiguredAction();
3821 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Float16_t>>::Action, conf );
3823 Error("GetConvertCollectionWriteActionFrom", "Write Conversion to Double32_t not yet supported");
3824 return TConfiguredAction();
3825 // return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<From,NoFactorMarker<Double32_t>>::Action, conf );
3826 default:
3827 break;
3828 }
3829 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: onfileType/oldtype == %d", onfileType);
3830 R__ASSERT(0); // We should never be here
3831 return TConfiguredAction();
3832}
3833
3834// Used in to implement the kSTL case
3835// Not to be confused with GetCollectionWriteConvertAction
3836// nor with GetConvertCollectionWriteActionFrom (used to implement this function)
3837template <typename Looper>
3839{
3840 switch (memoryType) {
3872 Error("GetConvertCollectionWriteActionFrom","There is no support for kBits outside of a TObject.");
3873 break;
3874 default:
3875 break;
3876 }
3877 Error("GetConvertCollectionWriteActionFrom", "UNEXPECTED: memoryType/newype == %d", memoryType);
3878 R__ASSERT(0); // We should never be here
3879 return TConfiguredAction();
3880}
3881
3882// Used in GetCollectionWriteAction for the kConv cases within a collection
3883// Not to be confused with GetConvertCollectionWriteAction
3884// Note the read and write version could be merged (using yet another template parameter)
3885template <typename Looper, typename Onfile>
3887{
3888 switch (newtype) {
3905 default:
3906 return TConfiguredAction( Looper::GenericRead, conf );
3907 }
3908 R__ASSERT(0); // We should never be here
3909 return TConfiguredAction();
3910}
3911
3912template <class Looper>
3913static TConfiguredAction
3916{
3917 switch (type) {
3918 // write basic types
3932 // the simple type missing are kBits and kCounter.
3933
3934 // Handling of the error case where we are asked to write a missing data member.
3936 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Bool_t>>, new TConfiguration(info,i,compinfo,offset) );
3938 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Char_t>>, new TConfiguration(info,i,compinfo,offset) );
3940 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Short_t>>, new TConfiguration(info,i,compinfo,offset) );
3942 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Int_t>>, new TConfiguration(info,i,compinfo,offset) );
3944 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long_t>>, new TConfiguration(info,i,compinfo,offset) );
3946 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Long64_t>>, new TConfiguration(info,i,compinfo,offset) );
3948 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Float_t>>, new TConfiguration(info,i,compinfo,offset) );
3950 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<Double_t>>, new TConfiguration(info,i,compinfo,offset) );
3952 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UChar_t>>, new TConfiguration(info,i,compinfo,offset) );
3954 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UShort_t>>, new TConfiguration(info,i,compinfo,offset) );
3956 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<UInt_t>>, new TConfiguration(info,i,compinfo,offset) );
3958 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong_t>>, new TConfiguration(info,i,compinfo,offset) );
3960 return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicZero<ULong64_t>>, new TConfiguration(info,i,compinfo,offset) );
3961
3962 // Conversions.
3989#ifdef NOT_YET
3990 /* The conversion writing acceleration was not yet written for kBits */
3993#endif
3995 if (element->GetFactor() != 0) {
3997 } else {
3998 Int_t nbits = (Int_t)element->GetXmin();
3999 if (!nbits) nbits = 12;
4001 }
4002 break;
4003 }
4005 if (element->GetFactor() != 0) {
4007 } else {
4008 Int_t nbits = (Int_t)element->GetXmin();
4009 if (!nbits) {
4011 } else {
4013 }
4014 }
4015 break;
4016 }
4018 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4019 // Streamer alltogether.
4022 case TStreamerInfo::kBase: {
4023 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
4024 if (baseEl) {
4025 auto baseinfo = (TStreamerInfo *)baseEl->GetBaseStreamerInfo();
4027 auto baseActions = Looper::CreateWriteActionSequence(*baseinfo, loopConfig);
4028 baseActions->AddToOffset(baseEl->GetOffset());
4029 return TConfiguredAction( Looper::SubSequenceAction, new TConfSubSequence(info, i, compinfo, 0, std::move(baseActions)));
4030
4031 } else
4032 return TConfiguredAction( Looper::WriteBase, new TGenericConfiguration(info, i, compinfo) );
4033 }
4036 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4037 return TConfiguredAction(Looper::template WriteStreamerLoop<false>::Action,
4039 }
4041 if (info->GetOldVersion() >= 3)
4042 return TConfiguredAction( Looper::WriteStreamerCase, new TGenericConfiguration(info, i, compinfo) );
4043 else
4044 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4046 if (compinfo->fStreamer)
4048 else {
4049 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4051 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4052 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4054 new TConfObject(info, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4055 else // Use the slower path for unusual cases
4056 return TConfiguredAction( Looper::GenericWrite, new TGenericConfiguration(info, i, compinfo) );
4057 }
4058 default:
4059 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
4060 }
4061 R__ASSERT(0); // We should never be here
4062 return TConfiguredAction();
4063}
4064
4065template <class Looper>
4067{
4068 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
4069
4070 switch (type) {
4071 // Write basic types.
4072 // Because of std::vector of bool is not backed up by an array of bool we have to converted it first.
4073 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteConvertCollectionBasicType<bool,bool>::Action, conf );
4086 case TStreamerInfo::kBits: Error("GetNumericCollectionWriteAction","There is no support for kBits outside of a TObject."); break;
4089 delete conf;
4090 return TConfiguredAction( Looper::WriteCollectionFloat16, alternate );
4091 // if (element->GetFactor() != 0) {
4092 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4093 // } else {
4094 // Int_t nbits = (Int_t)element->GetXmin();
4095 // if (!nbits) nbits = 12;
4096 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4097 // }
4098 }
4101 delete conf;
4102 return TConfiguredAction( Looper::WriteCollectionDouble32, alternate );
4103 // if (element->GetFactor() != 0) {
4104 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4105 // } else {
4106 // Int_t nbits = (Int_t)element->GetXmin();
4107 // if (!nbits) {
4108 // return TConfiguredAction( Looper::template LoopOverCollection<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4109 // } else {
4110 // return TConfiguredAction( Looper::template LoopOverCollection<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4111 // }
4112 // }
4113 }
4114 }
4115 Fatal("GetNumericCollectionWriteAction","Is confused about %d",type);
4116 R__ASSERT(0); // We should never be here
4117 return TConfiguredAction();
4118}
4119
4120////////////////////////////////////////////////////////////////////////////////
4121/// loop on the TStreamerElement list
4122/// regroup members with same type
4123/// Store predigested information into local arrays. This saves a huge amount
4124/// of time compared to an explicit iteration on all elements.
4125
4127{
4128 if (IsCompiled()) {
4129 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
4130 return;
4131 }
4133
4134 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
4135
4136 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
4138 fNdata = 0;
4139 fNfulldata = 0;
4140
4141 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
4142 if (fNumber < 0) {
4143 ++fgCount;
4144 fNumber = fgCount;
4145 }
4146 if (fNumber >= infos->GetSize()) {
4147 infos->AddAtAndExpand(this, fNumber);
4148 } else {
4149 if (!infos->At(fNumber)) {
4150 infos->AddAt(this, fNumber);
4151 }
4152 }
4153
4154 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
4155
4156
4158
4159
4162
4165
4168
4169 if (fReadText) fReadText->fActions.clear();
4171
4174
4177
4180
4181 if (fWriteText) fWriteText->fActions.clear();
4183
4184 if (!ndata) {
4185 // This may be the case for empty classes (e.g., TAtt3D).
4186 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
4188 fSize = sizeof(TStreamerInfo*);
4189 }
4190 fComp = new TCompInfo[1];
4191 fCompFull = new TCompInfo*[1];
4192 fCompOpt = new TCompInfo*[1];
4193 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
4194 fAlignment = 1;
4195 SetIsCompiled();
4196 return;
4197 }
4198
4199 // At most half of the elements can be used to hold optimized versions.
4200 // We use the bottom to hold the optimized-into elements and the non-optimized elements
4201 // and the top to hold the original copy of the optimized out elements.
4202 fNslots = ndata + ndata/2 + 1;
4203 Int_t optiOut = 0;
4204
4205 fComp = new TCompInfo[fNslots];
4206 fCompFull = new TCompInfo*[ndata];
4207 fCompOpt = new TCompInfo*[ndata];
4208
4211 Int_t keep = -1;
4212 Int_t i;
4213
4214 if (!CanOptimize()) {
4216 }
4217
4220
4221 for (i = 0; i < ndata; ++i) {
4223 if (!element) {
4224 break;
4225 }
4226
4227 Int_t asize = element->GetSize();
4228 if (element->GetArrayLength()) {
4229 asize /= element->GetArrayLength();
4230 }
4231 fComp[fNdata].fType = element->GetType();
4232 fComp[fNdata].fNewType = element->GetNewType();
4233 fComp[fNdata].fOffset = element->GetOffset();
4234 fComp[fNdata].fLength = element->GetArrayLength();
4236 fComp[fNdata].fMethod = element->GetMethod();
4237 fComp[fNdata].fClass = element->GetClassPointer();
4238 fComp[fNdata].fNewClass = element->GetNewClass();
4240 fComp[fNdata].fStreamer = element->GetStreamer();
4241
4242 // try to group consecutive members of the same type
4244 && (keep >= 0)
4245 && (element->GetType() > 0)
4246 && (element->GetType() < 10)
4248 && (fComp[keep].fMethod == 0)
4249 && (element->GetArrayDim() == 0)
4250 && (fComp[keep].fType < kObject)
4251 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
4252 && (element->GetType() == (fComp[keep].fType%kRegrouped))
4253 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
4254 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
4255 ((element->GetFactor() == previous->GetFactor())
4256 && (element->GetXmin() == previous->GetXmin())
4257 && (element->GetXmax() == previous->GetXmax())
4258 )
4259 )
4262 // kWholeObject and kDoNotDelete do not apply to numerical elements.
4263 )
4264 {
4265 if (!previousOptimized) {
4266 // The element was not yet optimized we first need to copy it into
4267 // the set of original copies.
4268 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
4269 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
4270 }
4271 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
4273
4274 R__ASSERT( keep < (fNslots - optiOut) );
4275
4276 if (fComp[keep].fLength == 0) {
4277 fComp[keep].fLength++;
4278 }
4279 fComp[keep].fLength++;
4280 fComp[keep].fType = element->GetType() + kRegrouped;
4283 } else if (element->GetType() < 0) {
4284
4285 // -- Deal with an ignored TObject base class.
4286 // Note: The only allowed negative value here is -1,
4287 // and signifies that Build() has found a TObject
4288 // base class and TClass::IgnoreTObjectStreamer() was
4289 // called. In this case the compiled version of the
4290 // elements omits the TObject base class element,
4291 // which has to be compensated for by TTree::Bronch()
4292 // when it is making branches for a split object.
4293 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
4295 keep = -1;
4297
4298 } else {
4299 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
4300 if (fComp[fNdata].fNewType > 0) {
4301 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
4302 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
4303 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
4307 ) {
4309 } else if (fComp[fNdata].fType != kCounter) {
4310 fComp[fNdata].fType += kConv;
4311 }
4312 } else {
4313 if (fComp[fNdata].fType == kCounter) {
4314 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
4315 }
4316 fComp[fNdata].fType += kSkip;
4317 }
4318 }
4319 fCompOpt[fNdata] = &(fComp[fNdata]);
4321
4323
4324 keep = fNdata;
4325 if (fComp[keep].fLength == 0) {
4326 fComp[keep].fLength = 1;
4327 }
4328 fNdata++;
4330 }
4331 // The test 'fMethod[keep] == 0' fails to detect a variable size array
4332 // if the counter happens to have an offset of zero, so let's explicitly
4333 // prevent for here.
4334 if (element->HasCounter()) keep = -1;
4335 ++fNfulldata;
4336 previous = element;
4337 }
4338
4339 for (i = 0; i < fNdata; ++i) {
4340 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
4341 continue;
4342 }
4345 }
4346 for (i = 0; i < fNfulldata; ++i) {
4347 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
4348 continue;
4349 }
4354
4357 }
4358 ComputeSize();
4359
4361 SetIsCompiled();
4362
4363 if (gDebug > 0) {
4364 ls();
4365 }
4366}
4367
4368template <typename From>
4370{
4371 switch (newtype) {
4388 }
4389}
4390
4391template <typename Onfile>
4393{
4394 // When writing 'newtype' is the origin of the information (i.e. the in memory representation)
4395 // and the template parameter `To` is the representation on disk
4396 switch (newtype) {
4413 }
4414}
4415
4416////////////////////////////////////////////////////////////////////////////////
4417/// Add a read action for the given element.
4418
4420{
4422
4423 if (element->TestBit(TStreamerElement::kWrite)) return;
4424
4425 switch (compinfo->fType) {
4426 // read basic types
4427 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4428 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4429 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4430 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4431 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4432 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4433 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4434 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4435 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4436 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4437 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4438 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4439 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4440 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4442 if (element->GetFactor() != 0) {
4443 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4444 } else {
4445 Int_t nbits = (Int_t)element->GetXmin();
4446 if (!nbits) nbits = 12;
4448 }
4449 break;
4450 }
4452 if (element->GetFactor() != 0) {
4453 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4454 } else {
4455 Int_t nbits = (Int_t)element->GetXmin();
4456 if (!nbits) {
4458 } else {
4460 }
4461 }
4462 break;
4463 }
4464 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4465 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4466 // Streamer alltogether.
4467 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4468 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4469 case TStreamerInfo::kSTL: {
4470 TClass *newClass = element->GetNewClass();
4471 TClass *oldClass = element->GetClassPointer();
4472 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4473
4474 if (element->GetArrayLength() <= 1) {
4475 if (fOldVersion<3){ // case of old TStreamerInfo
4476 if (newClass && newClass != oldClass) {
4477 if (element->GetStreamer()) {
4478 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4479 } else {
4481 }
4482 } else {
4483 if (element->GetStreamer()) {
4484 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4485 } else {
4487 }
4488 }
4489 } else {
4490 if (newClass && newClass != oldClass) {
4491 if (element->GetStreamer()) {
4492 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4493 } else if (oldClass) {
4494 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4496 } else {
4497 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4498 case kVectorLooper:
4499 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)));
4500 break;
4501 case kAssociativeLooper:
4502 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)));
4503 break;
4504 case kVectorPtrLooper:
4505 case kGenericLooper:
4506 default:
4507 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4508 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)));
4509 break;
4510 }
4511 }
4512 }
4513 } else {
4514 if (element->GetStreamer()) {
4515 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4516 } else if (oldClass) {
4517 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
4518 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
4519 } else {
4520 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
4521 case kVectorLooper:
4522 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4523 break;
4524 case kAssociativeLooper:
4525 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4526 break;
4527 case kVectorPtrLooper:
4528 case kGenericLooper:
4529 default:
4530 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
4531 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
4532 break;
4533 }
4534 }
4535 }
4536 }
4537 }
4538 } else {
4539 if (fOldVersion<3){ // case of old TStreamerInfo
4540 if (newClass && newClass != oldClass) {
4541 if (element->GetStreamer()) {
4542 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4543 } else {
4544 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4545 }
4546 } else {
4547 if (element->GetStreamer()) {
4548 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4549 } else {
4550 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4551 }
4552 }
4553 } else {
4554 if (newClass && newClass != oldClass) {
4555 if (element->GetStreamer()) {
4556 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4557 } else {
4558 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
4559 }
4560 } else {
4561 if (element->GetStreamer()) {
4562 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
4563 } else {
4564 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(/*read = */ true, this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
4565 }
4566 }
4567 }
4568 }
4569 break;
4570 }
4571
4574 break;
4577 break;
4580 break;
4583 break;
4586 break;
4589 break;
4592 break;
4595 break;
4598 break;
4601 break;
4604 break;
4607 break;
4610 break;
4613 break;
4615 if (element->GetFactor() != 0) {
4616 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4617 } else {
4618 Int_t nbits = (Int_t)element->GetXmin();
4619 if (!nbits) nbits = 12;
4621 }
4622 break;
4623 }
4625 if (element->GetFactor() != 0) {
4626 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
4627 } else {
4628 Int_t nbits = (Int_t)element->GetXmin();
4629 if (!nbits) {
4631 } else {
4633 }
4634 }
4635 break;
4636 }
4639 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4640 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<false>::Action,
4641 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4642 break;
4643 }
4645 if (compinfo->fStreamer)
4646 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4647 else {
4648 auto base = dynamic_cast<TStreamerBase*>(element);
4649 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4650 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4651
4652 if(!base || !memoryBaseCl ||
4653 memoryBaseCl->GetStreamer() ||
4654 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4655 {
4656 // Unusual Case.
4658 }
4659 else
4660 readSequence->AddAction( ReadViaClassBuffer,
4661 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4662 }
4663 break;
4665 if (fOldVersion >= 3)
4666 readSequence->AddAction( ReadStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4667 else
4668 // Use the slower path for legacy files
4670 break;
4672 if (compinfo->fStreamer)
4673 readSequence->AddAction( ReadViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
4674 else {
4675 if (compinfo->fNewClass && compinfo->fNewClass->HasDirectStreamerInfoUse())
4676 readSequence->AddAction( ReadViaClassBuffer,
4677 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
4678 else if (compinfo->fClass && compinfo->fClass->HasDirectStreamerInfoUse())
4679 readSequence->AddAction( ReadViaClassBuffer,
4680 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
4681 else // Use the slower path for unusual cases
4682 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this, i, compinfo) );
4683 }
4684 break;
4685 default:
4687 break;
4688 }
4689 if (element->TestBit(TStreamerElement::kCache)) {
4690 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
4691 readSequence->fActions.pop_back();
4693 }
4694}
4695
4696////////////////////////////////////////////////////////////////////////////////
4697/// Add a read text action for the given element.
4698
4700{
4702
4703 if (element->TestBit(TStreamerElement::kWrite))
4704 return;
4705
4706 Bool_t generic = kFALSE, isBase = kFALSE;
4707
4708 switch (compinfo->fType) {
4710 if (element->IsBase())
4711 isBase = kTRUE;
4712 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
4713 else
4714 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4715 break;
4716
4718 if (element->IsBase())
4719 isBase = kTRUE;
4720 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
4721 else
4722 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4723 break;
4724
4725 case TStreamerInfo::kObject: // Class derived from TObject
4726 case TStreamerInfo::kAny: // Class NOT derived from TObject
4729 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4730 break;
4731
4732 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
4734 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
4735 readSequence->AddAction(TextReadSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
4736 break;
4737
4740 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4741 readSequence->AddAction(ScalarLooper::ReadStreamerLoop<true>::Action,
4742 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4743 break;
4744 }
4745 case TStreamerInfo::kBase: isBase = kTRUE; break;
4746
4749 break;
4750
4751 default: generic = kTRUE; break;
4752 }
4753
4754 if (isBase) {
4755 if (compinfo->fStreamer) {
4757 } else {
4759 }
4760 } else if (generic)
4762}
4763
4764////////////////////////////////////////////////////////////////////////////////
4765/// Add a read action for the given element.
4766/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
4767
4781
4782////////////////////////////////////////////////////////////////////////////////
4783
4785{
4788 // Skip element cached for reading purposes.
4789 return;
4790 }
4791 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
4792 // Skip artificial element used for reading purposes.
4793 return;
4794 }
4795 switch (compinfo->fType) {
4796 // write basic types
4797 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4798 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4799 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4800 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4801 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4802 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4803 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4804 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4805 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4806 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4807 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4808 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4809 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
4810
4813 break;
4816 break;
4819 break;
4822 break;
4825 break;
4828 break;
4831 break;
4834 break;
4837 break;
4840 break;
4841
4842 case kSTL:
4843 {
4844 TClass *newClass = element->GetNewClass();
4845 TClass *onfileClass = element->GetClassPointer();
4846 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
4847
4848 if (element->GetArrayLength() <= 1) {
4849 if (newClass && newClass != onfileClass) {
4850 if (element->GetStreamer()) {
4852 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4853 newClass, element->GetStreamer(), element->GetTypeName(),
4854 isSTLbase));
4855 } else if (onfileClass) {
4856 if (onfileClass->GetCollectionProxy() == 0 || onfileClass->GetCollectionProxy()->GetValueClass() ||
4857 onfileClass->GetCollectionProxy()->HasPointers()) {
4858 writeSequence->AddAction(
4860 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4861 element->GetTypeName(), isSTLbase));
4862 } else {
4863 switch (SelectLooper(*newClass->GetCollectionProxy())) {
4864 case kVectorLooper:
4866 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4867 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4868 element->GetTypeName(), isSTLbase)));
4869 break;
4870 case kAssociativeLooper:
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 kVectorPtrLooper:
4877 case kGenericLooper:
4878 default:
4879 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4880 // real thing.
4882 onfileClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(),
4883 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, newClass,
4884 element->GetTypeName(), isSTLbase)));
4885 break;
4886 }
4887 }
4888 }
4889 } else {
4890 if (element->GetStreamer()) {
4892 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4893 element->GetStreamer(), element->GetTypeName(),
4894 isSTLbase));
4895 } else if (onfileClass) {
4896 if (onfileClass->GetCollectionProxy() == 0 ||
4897 onfileClass->GetCollectionProxy()->GetValueClass() ||
4898 onfileClass->GetCollectionProxy()->HasPointers()) {
4900 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass,
4901 element->GetTypeName(), isSTLbase));
4902 } else {
4903 switch (SelectLooper(*onfileClass->GetCollectionProxy())) {
4904 case kVectorLooper:
4906 onfileClass->GetCollectionProxy()->GetType(),
4907 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4908 isSTLbase)));
4909 break;
4910 case kAssociativeLooper:
4912 onfileClass->GetCollectionProxy()->GetType(),
4913 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4914 isSTLbase)));
4915 break;
4916 case kVectorPtrLooper:
4917 case kGenericLooper:
4918 default:
4919 // For now TBufferXML would force use to allocate the data buffer each time and copy into the
4920 // real thing.
4922 onfileClass->GetCollectionProxy()->GetType(),
4923 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, 1, onfileClass, element->GetTypeName(),
4924 isSTLbase)));
4925 break;
4926 }
4927 }
4928 }
4929 }
4930 } else {
4931 if (newClass && newClass != onfileClass) {
4932 if (element->GetStreamer()) {
4933 writeSequence->AddAction(
4935 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4936 newClass, element->GetStreamer(), element->GetTypeName(), isSTLbase));
4937 } else {
4938 writeSequence->AddAction(
4940 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset, element->GetArrayLength(), onfileClass,
4941 newClass, element->GetTypeName(), isSTLbase));
4942 }
4943 } else {
4944 if (element->GetStreamer()) {
4946 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4947 element->GetArrayLength(), onfileClass,
4948 element->GetStreamer(), element->GetTypeName(), isSTLbase));
4949 } else {
4951 new TConfigSTL(/*read = */ false, this, i, compinfo, compinfo->fOffset,
4952 element->GetArrayLength(), onfileClass,
4953 element->GetTypeName(), isSTLbase));
4954 }
4955 }
4956 }
4957 break;
4958 }
4959
4960 case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4961 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4962 // Streamer alltogether.
4963 case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4964 case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this, i, compinfo, compinfo->fOffset) ); break;
4965
4968 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
4969 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<false>::Action,
4970 new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
4971 break;
4972 }
4974 if (compinfo->fStreamer)
4975 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4976 else {
4977 auto base = dynamic_cast<TStreamerBase*>(element);
4978 auto onfileBaseCl = base ? base->GetClassPointer() : nullptr;
4979 auto memoryBaseCl = base && base->GetNewBaseClass() ? base->GetNewBaseClass() : onfileBaseCl;
4980
4981 if(!base || !memoryBaseCl ||
4982 memoryBaseCl->GetStreamer() ||
4983 memoryBaseCl->GetStreamerFunc() || memoryBaseCl->GetConvStreamerFunc())
4984 {
4985 // Unusual Case.
4987 }
4988 else {
4990 new TConfObject(this, i, compinfo, compinfo->fOffset, onfileBaseCl, memoryBaseCl) );
4991 }
4992 }
4993 break;
4995 if (fOldVersion >= 3)
4996 writeSequence->AddAction( WriteStreamerCase, new TGenericConfiguration(this,i,compinfo, compinfo->fOffset) );
4997 else
4998 // Use the slower path for legacy files
5000 break;
5002 if (compinfo->fStreamer)
5003 writeSequence->AddAction( WriteViaExtStreamer, new TGenericConfiguration(this, i, compinfo, compinfo->fOffset) );
5004 else {
5005 if (compinfo->fNewClass && compinfo->fNewClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5007 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, compinfo->fNewClass) );
5008 else if (compinfo->fClass && compinfo->fClass->fStreamerImpl == &TClass::StreamerStreamerInfo)
5010 new TConfObject(this, i, compinfo, compinfo->fOffset, compinfo->fClass, nullptr) );
5011 else // Use the slower path for unusual cases
5013 }
5014 break;
5015
5016 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
5017 /*case TStreamerInfo::kFloat16: {
5018 if (element->GetFactor() != 0) {
5019 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5020 } else {
5021 Int_t nbits = (Int_t)element->GetXmin();
5022 if (!nbits) nbits = 12;
5023 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5024 }
5025 break;
5026 } */
5027 /*case TStreamerInfo::kDouble32: {
5028 if (element->GetFactor() != 0) {
5029 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
5030 } else {
5031 Int_t nbits = (Int_t)element->GetXmin();
5032 if (!nbits) {
5033 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
5034 } else {
5035 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
5036 }
5037 }
5038 break;
5039 } */
5040 default:
5042 break;
5043 }
5044}
5045
5046////////////////////////////////////////////////////////////////////////////////
5047
5049{
5052 // Skip element cached for reading purposes.
5053 return;
5054 }
5055 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5056 // Skip artificial element used for reading purposes.
5057 return;
5058 }
5059
5060 Bool_t generic = kFALSE, isBase = kFALSE;
5061
5062 switch (compinfo->fType) {
5063 // write basic types
5089 // Actually same action for this level
5091 break;
5092
5094 if (element->IsBase())
5095 isBase = kTRUE;
5096 else
5097 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5098 break;
5099
5101 if (element->IsBase())
5102 isBase = kTRUE;
5103 else
5104 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5105 break;
5106
5107 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
5109 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
5110 writeSequence->AddAction(TextWriteSTLp, new TConfiguration(this, i, compinfo, compinfo->fOffset));
5111 break;
5112
5115 bool isPtrPtr = (strstr(compinfo->fElem->GetTypeName(), "**") != 0);
5116 writeSequence->AddAction(ScalarLooper::WriteStreamerLoop<true>::Action, new TConfStreamerLoop(this, i, compinfo, compinfo->fOffset, isPtrPtr));
5117 break;
5118 }
5119 case TStreamerInfo::kBase: isBase = kTRUE; break;
5120
5123 break;
5124
5125 default: generic = kTRUE; break;
5126 }
5127
5128 if (isBase) {
5129 if (compinfo->fStreamer) {
5131 } else {
5133 }
5134
5135 } else
5136
5137 // use generic write action when special handling is not provided
5138 if (generic)
5140}
5141
5142////////////////////////////////////////////////////////////////////////////////
5143/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
5144
5146{
5149 // Skip element cached for reading purposes.
5150 return;
5151 }
5152 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
5153 // Skip artificial element used for reading purposes.
5154 return;
5155 }
5156 writeSequence->AddAction( GetCollectionWriteAction<VectorPtrLooper>(this,nullptr,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
5157}
5158
5159////////////////////////////////////////////////////////////////////////////////
5160/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5161
5163{
5164 if (info == 0) {
5166 }
5167
5168 std::unique_ptr<TLoopConfiguration> loopConfig;
5170 {
5171 if (proxy.HasPointers()) {
5172 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5173 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5174 return sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
5175 }
5176
5177 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5178 Long_t increment = proxy.GetIncrement();
5179 loopConfig = std::make_unique<TVectorLoopConfig>(&proxy, increment, /* read */ kTRUE);
5180 } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLunorderedset
5181 || proxy.GetCollectionType() == ROOT::kSTLmultiset || proxy.GetCollectionType() == ROOT::kSTLunorderedmultiset
5182 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap
5183 || proxy.GetCollectionType() == ROOT::kSTLunorderedmap || proxy.GetCollectionType() == ROOT::kSTLunorderedmultimap)
5184 {
5185 Long_t increment = proxy.GetIncrement();
5186 loopConfig = std::make_unique<TVectorLoopConfig>(&proxy, increment, /* read */ kTRUE);
5187 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
5188 } else {
5189 loopConfig = std::make_unique<TGenericLoopConfig>(&proxy, /* read */ kTRUE);
5190 }
5191
5192 return CreateReadMemberWiseActions(*info, std::move(loopConfig));
5193}
5194
5195////////////////////////////////////////////////////////////////////////////////
5196/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5197
5199{
5200 UInt_t ndata = info.GetElements()->GetEntriesFast();
5202 sequence->fLoopConfig = std::move(inLoopConfig);
5203 TLoopConfiguration *loopConfig = sequence->fLoopConfig.get();
5204
5205 for (UInt_t i = 0; i < ndata; ++i) {
5206 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5207 if (!element) {
5208 break;
5209 }
5210 if (element->GetType() < 0) {
5211 // -- Skip an ignored TObject base class.
5212 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5213 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5214 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5215 // when it is making branches for a split object.
5216 continue;
5217 }
5218 if (element->TestBit(TStreamerElement::kWrite)) {
5219 // Skip element that only for writing.
5220 continue;
5221 }
5222 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
5223 if (baseEl) {
5224 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
5225 // There was a problem with the checksum, the user likely did not
5226 // increment the version number of the derived class when the
5227 // base class changed. Since we will be member wise streaming
5228 // this class, let's warn the user that something is wrong.
5229 ::Warning("CreateReadMemberWiseActions","%s",
5230 baseEl->GetErrorMessage());
5232 }
5233 }
5234
5235 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5236 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
5237
5238 Int_t oldType = element->GetType();
5239 Int_t newType = element->GetNewType();
5240
5241 Int_t offset = element->GetOffset();
5242 if (newType != oldType) {
5243 // This 'prevents' the switch from base class (kBase (0)) to
5244 // anything else.
5245 if (newType > 0) {
5248 }
5249 } else {
5251 }
5252 }
5253 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5254 case kAssociativeLooper:
5255// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
5256// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
5257// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(true, info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
5258 case kVectorLooper:
5259 case kVectorPtrLooper:
5260 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5261 if (element->TestBit(TStreamerElement::kCache)) {
5264 } else {
5266 }
5267 break;
5268 case kGenericLooper:
5269 default:
5270 // The usual collection case.
5271 if (element->TestBit(TStreamerElement::kCache)) {
5274 } else {
5276 }
5277 break;
5278 }
5279 }
5280 return sequence;
5281}
5282
5283////////////////////////////////////////////////////////////////////////////////
5284/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
5285
5287{
5288 if (info == 0) {
5290 }
5291
5292 std::unique_ptr<TLoopConfiguration> loopConfig;
5294 {
5295 if (proxy.HasPointers()) {
5296 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
5297 // Instead of the creating a new one let's copy the one from the StreamerInfo.
5298 return sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
5299 }
5300
5301 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
5302 Long_t increment = proxy.GetIncrement();
5303 loopConfig = std::make_unique<TVectorLoopConfig>(&proxy, increment, /* read */ kFALSE);
5304 } else {
5305 loopConfig = std::make_unique<TGenericLoopConfig>(&proxy, /* read */ kFALSE);
5306 }
5307 return CreateWriteMemberWiseActions(*info, std::move(loopConfig));
5308}
5309
5310////////////////////////////////////////////////////////////////////////////////
5311/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the
5312/// collection described by 'proxy' \param loopConfig pointer ownership is taken from the caller and transferred to the
5313/// TActionSequence class (stored as public fLoopConfig internally, will be deleted in destructor) \return new
5314/// `sequence` pointer of type TActionSequence, the memory ownership is transferred to caller, must delete it later
5315
5317{
5318 UInt_t ndata = info.GetElements()->GetEntriesFast();
5320 sequence->fLoopConfig = std::move(inLoopConfig);
5321 TLoopConfiguration *loopConfig = sequence->fLoopConfig.get();
5322
5323 for (UInt_t i = 0; i < ndata; ++i) {
5324 TStreamerElement *element = (TStreamerElement*) info.GetElements()->At(i);
5325 if (!element) {
5326 break;
5327 }
5328 if (element->GetType() < 0) {
5329 // -- Skip an ignored TObject base class.
5330 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
5331 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
5332 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
5333 // when it is making branches for a split object.
5334 continue;
5335 }
5337 // Skip element cached for reading purposes.
5338 continue;
5339 }
5341 // Skip artificial element used for reading purposes.
5342 continue;
5343 }
5344 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(&info);
5345 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
5346 Int_t onfileType = element->GetType();
5347 Int_t memoryType = element->GetNewType();
5348 if (memoryType != onfileType) {
5349 // This 'prevents' the switch from base class (kBase (0)) to
5350 // anything else.
5351 if (memoryType > 0) {
5354 }
5355 } else {
5356 // When reading we need to consume the data in the onfile buffer,
5357 // so we do create a 'Skip' action for the missing elements.
5358 // When writing we should probably write a default value, for
5359 // now let's just ignore the request.
5360 // We could issue an error here but we might too often issue a
5361 // 'false positive' if the user only reads.
5362 // FIXME: The 'right' solution is to add a new action that first print
5363 // once the following error message:
5364 //
5365 // info.Error("TActionSequence::CreateWriteMemberWiseActions",
5366 // "Ignoring request to write the missing data member %s in %s version %d checksum 0x%x",
5367 // element->GetName(), info.GetName(), info.GetClassVersion(), info.GetCheckSum());
5368 continue;
5369 //
5370 // Instead of skipping the field we could write a zero there with:
5371 // onfileType += TVirtualStreamerInfo::kSkip;
5372 }
5373 }
5374
5375 Int_t offset = element->GetOffset();
5376 switch (SelectLooper(loopConfig ? loopConfig->fProxy : nullptr)) {
5377 case kAssociativeLooper:
5379 break;
5380 case kVectorLooper:
5382 break;
5383 case kVectorPtrLooper:
5385 break;
5386 case kGenericLooper:
5387 default:
5389 break;
5390 }
5391 }
5392 return sequence;
5393}
5394
5396{
5397 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5398 // TBranchElement in the case of split sub-object.
5399
5400 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5401 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5402 iter != end;
5403 ++iter)
5404 {
5405 // (fElemId == -1) indications that the action is a Push or Pop DataCache.
5406 if (iter->fConfiguration->fElemId != (UInt_t)-1 &&
5407 !iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5408 iter->fConfiguration->AddToOffset(delta);
5409 }
5410}
5411
5413{
5414 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5415 // TBranchElement in the case of split sub-object.
5416
5417 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5418 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5419 iter != end;
5420 ++iter)
5421 {
5422 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5423 iter->fConfiguration->SetMissing();
5424 }
5425}
5426
5428{
5429 // Create a copy of this sequence.
5430
5431 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, fActions.size(), IsForVectorPtrLooper());
5432
5433 sequence->fLoopConfig.reset(fLoopConfig ? fLoopConfig->Copy() : nullptr);
5434
5435 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5436 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5437 iter != end;
5438 ++iter)
5439 {
5440 TConfiguration *conf = iter->fConfiguration->Copy();
5441 sequence->AddAction( iter->fAction, conf );
5442 }
5443 return sequence;
5444}
5445
5448 Int_t offset,
5450{
5451 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5452 if ( element_ids[id].fElemID < 0 ) {
5453 if (element_ids[id].fNestedIDs) {
5454 auto original = create(element_ids[id].fNestedIDs->fInfo,
5455 sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
5456 nullptr);
5457 if (element_ids[id].fNestedIDs->fOnfileObject) {
5458 auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
5459 if ( sequence->fLoopConfig )
5461 else if ( sequence->IsForVectorPtrLooper() )
5462 sequence->AddAction( PushDataCacheVectorPtr, conf );
5463 else
5464 sequence->AddAction( PushDataCache, conf );
5465 }
5466
5467 original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
5468
5469 if (element_ids[id].fNestedIDs->fOnfileObject) {
5470 auto conf =
5471 new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset);
5472 if ( sequence->fLoopConfig )
5474 else if ( sequence->IsForVectorPtrLooper() )
5475 sequence->AddAction( PopDataCacheVectorPtr, conf );
5476 else
5477 sequence->AddAction( PopDataCache, conf );
5478 }
5479 } else {
5480 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5481 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5482 iter != end;
5483 ++iter)
5484 {
5485 TConfiguration *conf = iter->fConfiguration->Copy();
5486 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5487 conf->AddToOffset(offset);
5488 sequence->AddAction( iter->fAction, conf );
5489 }
5490 }
5491 } else {
5492 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5493 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5494 iter != end;
5495 ++iter) {
5496 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
5497 TConfiguration *conf = iter->fConfiguration->Copy();
5498 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5499 conf->AddToOffset(offset);
5500 sequence->AddAction( iter->fAction, conf );
5501 }
5502 }
5503 }
5504 }
5505}
5506
5509{
5510 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5511 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5512
5513 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5514
5515 sequence->fLoopConfig = std::unique_ptr<TLoopConfiguration>(fLoopConfig ? fLoopConfig->Copy() : 0);
5516
5517 AddToSubSequence(sequence, element_ids, offset, create);
5518
5519 return sequence;
5520}
5521
5523{
5524 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
5525 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
5526
5527 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
5528
5529 sequence->fLoopConfig.reset(fLoopConfig ? fLoopConfig->Copy() : 0);
5530
5531 for(UInt_t id = 0; id < element_ids.size(); ++id) {
5532 if ( element_ids[id] < 0 ) {
5533 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5534 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5535 iter != end;
5536 ++iter)
5537 {
5538 TConfiguration *conf = iter->fConfiguration->Copy();
5539 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5540 conf->AddToOffset(offset);
5541 sequence->AddAction( iter->fAction, conf );
5542 }
5543 } else {
5544 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
5545 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
5546 iter != end;
5547 ++iter) {
5548 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
5549 TConfiguration *conf = iter->fConfiguration->Copy();
5550 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
5551 conf->AddToOffset(offset);
5552 sequence->AddAction( iter->fAction, conf );
5553 }
5554 }
5555 }
5556 }
5557 return sequence;
5558}
5559
5560#if !defined(R__WIN32)
5561
5562#include <dlfcn.h>
5563
5564#endif
5565
5566typedef void (*voidfunc)();
5567static const char *R__GetSymbolName(voidfunc func)
5568{
5569#if defined(R__WIN32) || defined(__CYGWIN__)
5570 return "not available on this platform";
5571#if 0
5573 if (!VirtualQuery (func, &mbi, sizeof (mbi)))
5574 {
5575 return 0;
5576 }
5577
5578 HMODULE hMod = (HMODULE) mbi.AllocationBase;
5579 static char moduleName[MAX_PATH];
5580
5581 if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
5582 {
5583 return 0;
5584 }
5585 return moduleName;
5586#endif
5587#else
5588 Dl_info info;
5589 if (dladdr((void*)func,&info)==0) {
5590 // Not in a known share library, let's give up
5591 return "name not found";
5592 } else {
5593 //fprintf(stdout,"Found address in %s\n",info.dli_fname);
5594 return info.dli_sname;
5595 }
5596#endif
5597}
5598
5600{
5601 // Add the (potentially negative) delta to all the configuration's offset. This is used by
5602 // TTBranchElement in the case of split sub-object.
5603 // If opt contains 'func', also print the (mangled) name of the function that will be executed.
5604
5605 if (fLoopConfig) {
5606 fLoopConfig->Print();
5607 }
5608 TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
5609 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
5610 iter != end;
5611 ++iter)
5612 {
5613 iter->fConfiguration->Print();
5614 if (strstr(opt,"func")) {
5615 printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
5616 }
5617 }
5618}
5619
5620
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition MPSendRecv.h:158
#define b(i)
Definition RSha256.hxx:100
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
constexpr Int_t kMaxInt
Definition RtypesCore.h:120
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
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:130
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
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:267
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:378
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
#define gROOT
Definition TROOT.h:417
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
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)
#define R__LOCKGUARD(mutex)
const_iterator end() const
@ kStreamedMemberWise
Definition TBufferFile.h:70
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
@ kCannotHandleMemberWiseStreaming
Definition TBuffer.h:76
Int_t Length() const
Definition TBuffer.h:100
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:627
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:5326
EState GetState() const
Definition TClass.h:504
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5111
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5869
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:7036
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5662
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2923
@ kEmulated
Definition TClass.h:128
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
Int_t GetVersion() const
Definition TFile.h:333
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:170
Mother of all ROOT objects.
Definition TObject.h:42
@ kIsOnHeap
object is on heap
Definition TObject.h:90
@ kNotDeleted
object has not been deleted
Definition TObject.h:91
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:479
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
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:886
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:897
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
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.
size_t fAlignment
!alignment of the memory representation of the class
Basic string class.
Definition TString.h:137
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1171
@ kTrailing
Definition TString.h:283
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
Bool_t fOptimized
! true if the StreamerInfo has been optimized
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)