Logo ROOT  
Reference Guide
TStreamerInfoActions.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Philippe Canal 05/2010
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TStreamerInfo.h"
14#include "TROOT.h"
15#include "TStreamerElement.h"
16#include "TVirtualMutex.h"
17#include "TInterpreter.h"
18#include "TError.h"
19#include "TVirtualArray.h"
20#include "TBufferFile.h"
21#include "TBufferText.h"
22#include "TMemberStreamer.h"
23#include "TClassEdit.h"
25#include "TProcessID.h"
26#include "TFile.h"
27
29
30// More possible optimizations:
31// Avoid call the virtual version of TBuffer::ReadInt and co.
32// Merge the Reading of the version and the looking up or the StreamerInfo
33// Avoid if (bytecnt) inside the CheckByteCount routines and avoid multiple (mostly useless nested calls)
34// Try to avoid if statement on onfile class being set (TBufferFile::ReadClassBuffer).
35
36using namespace TStreamerInfoActions;
37
38#ifdef _AIX
39# define INLINE_TEMPLATE_ARGS
40#else
41# define INLINE_TEMPLATE_ARGS inline
42#endif
43
44
46{
48 {
49 const auto props = proxy.GetProperties();
50 const bool isVector = proxy.GetCollectionType() == ROOT::kSTLvector;
51 const bool hasDefaultAlloc = !(props & TVirtualCollectionProxy::kCustomAlloc);
52 const bool isEmulated = props & TVirtualCollectionProxy::kIsEmulated;
53
54 return isEmulated || (isVector && hasDefaultAlloc);
55 }
56
57 template <typename From>
59 typedef From Value_t;
60 };
61
62 template <typename From>
64 typedef From Value_t;
65 };
66
67 struct BitsMarker {
68 typedef UInt_t Value_t;
69 };
70
72 {
73 // Add the (potentially negative) delta to all the configuration's offset. This is used by
74 // TBranchElement in the case of split sub-object.
75
77 fOffset += delta;
78 }
79
81 {
82 // Add the (potentially negative) delta to all the configuration's offset. This is used by
83 // TBranchElement in the case of split sub-object.
84
86 }
87
88 void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
89 {
90 // Inform the user what we are about to stream.
91
92 // Idea, we should find a way to print the name of the function
94 }
95
97 {
98 // Inform the user what we are about to stream.
99
101 TStreamerElement *aElement = fCompInfo->fElem;
102 TString sequenceType;
103 aElement->GetSequenceType(sequenceType);
104
105 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
106 " %s, offset=%d (%s), elemnId=%d \n",
107 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
108 aElement->ClassName(), fOffset, sequenceType.Data(), fElemId);
109 }
110
111 void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
112 {
113 // Inform the user what we are about to stream.
114
115 if (gDebug > 1) {
116 // Idea: We should print the name of the action function.
118 TStreamerElement *aElement = fCompInfo->fElem;
119 TString sequenceType;
120 aElement->GetSequenceType(sequenceType);
121
122 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
123 " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
124 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
125 aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
126 }
127 }
128
130 {
131 // Inform the user what we are about to stream.
132
133 printf("TLoopConfiguration: unconfigured\n");
134 }
135
136
138 // Configuration of action using the legacy code.
139 // Mostly to cancel out the PrintDebug.
140 public:
142 void PrintDebug(TBuffer &, void *) const override {
143 // Since we call the old code, it will print the debug statement.
144 }
145
146 TConfiguration *Copy() override { return new TGenericConfiguration(*this); }
147 };
148
150 // Configuration of action handling kBits.
151 // In this case we need to know both the location
152 // of the member (fBits) and the start of the object
153 // (its TObject part to be exact).
154
155 Int_t fObjectOffset; // Offset of the TObject part within the object
156
158 void PrintDebug(TBuffer &, void *) const override
159 {
161 TStreamerElement *aElement = fCompInfo->fElem;
162 TString sequenceType;
163 aElement->GetSequenceType(sequenceType);
164
165 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
166 " %s, offset=%d (%s)\n",
167 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
168 aElement->ClassName(), fOffset, sequenceType.Data());
169 }
170
171 void AddToOffset(Int_t delta) override
172 {
173 // Add the (potentially negative) delta to all the configuration's offset. This is used by
174 // TBranchElement in the case of split sub-object.
175
177 fOffset += delta;
178 fObjectOffset = 0;
179 }
180
181 void SetMissing() override
182 {
184 fObjectOffset = 0;
185 }
186
187 TConfiguration *Copy() override { return new TBitsConfiguration(*this); }
188
189 };
190
191 Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
192 {
193 char *obj = (char*)addr;
195 return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
196 }
197
198 Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
199 {
200 char *obj = (char*)addr;
202 return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
203 }
204
205 template <typename T>
207 {
208 T *x = (T*)( ((char*)addr) + config->fOffset );
209 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
210 buf >> *x;
211 return 0;
212 }
213
214 void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
215 TBitsConfiguration *conf = (TBitsConfiguration*)config;
216 UShort_t pidf;
217 buf >> pidf;
218 pidf += buf.GetPidOffset();
219 TProcessID *pid = buf.ReadProcessID(pidf);
220 if (pid!=0) {
221 TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
222 UInt_t gpid = pid->GetUniqueID();
223 UInt_t uid;
224 if (gpid>=0xff) {
225 uid = obj->GetUniqueID() | 0xff000000;
226 } else {
227 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
228 }
229 obj->SetUniqueID(uid);
230 pid->PutObjectWithID(obj);
231 }
232 }
233
234 template <>
236 {
237 UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
238 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
239 // Idea: This code really belongs inside TBuffer[File]
240 buf >> *x;
241
242 if ((*x & kIsReferenced) != 0) {
243 HandleReferencedTObject(buf,addr,config);
244 }
245 return 0;
246 }
247
248 template <typename T>
250 {
251 T *x = (T *)(((char *)addr) + config->fOffset);
252 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
253 buf << *x;
254 return 0;
255 }
256
258 {
259 void *x = (void *)(((char *)addr) + config->fOffset);
260 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
262 return 0;
263 }
264
266 {
267 void *x = (void *)(((char *)addr) + config->fOffset);
268 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
270 return 0;
271 }
272
274 {
275 void *x = (void *)(((char *)addr) + config->fOffset);
276 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
277 ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
278 return 0;
279 }
280
282 {
283 void *x = (void *)(((char *)addr) + config->fOffset);
284 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
285 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
286 (*pstreamer)(buf, x, config->fCompInfo->fLength);
287 buf.SetByteCount(pos, kTRUE);
288 return 0;
289 }
290
292 {
293 void *x = (void *)(((char *)addr) + config->fOffset);
294 buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
295 return 0;
296 }
297
299 {
300 void *x = (void *)(((char *)addr) + config->fOffset);
302 return 0;
303 }
304
306 {
307 void *x = (void *)(((char *)addr) + config->fOffset);
308 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
309 ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
310 return 0;
311 }
312
314 {
315 void *x = (void *)(((char *)addr) + config->fOffset);
316 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
317
318 UInt_t start, count;
319 /* Version_t v = */ buf.ReadVersion(&start, &count, config->fCompInfo->fClass);
320 (*pstreamer)(buf, x, config->fCompInfo->fLength);
321 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
322 return 0;
323 }
324
326 {
327 // action required to call custom code for TObject as base class
328 void *x = (void *)(((char *)addr) + config->fOffset);
330 return 0;
331 }
332
334 {
335 void *x = (void *)(((char *)addr) + config->fOffset);
337 return 0;
338 }
339
340 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
341 * potentially can be used later for non-text streaming */
342 template<bool kIsTextT>
344 {
345 TClass *cl = config->fCompInfo->fClass;
346 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
348 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
349 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
350 UInt_t ioffset = eoffset + config->fOffset;
351
353 && proxy && vClass
354 && config->fInfo->GetStreamMemberWise()
355 && cl->CanSplit()
356 && !(strspn(config->fCompInfo->fElem->GetTitle(),"||") == 2)
358 // Let's save the collection member-wise.
359
360 UInt_t pos = buf.WriteVersionMemberWise(config->fInfo->IsA(),kTRUE);
361 buf.WriteVersion( vClass, kFALSE );
362
363 // TODO: subinfo used for WriteBufferSTL call, which is private for the moment
364 //TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
365
366 //for (int k = 0; k < narr; ++k) {
367 char **contp = (char **)((char *)addr + ioffset);
368 for(int j=0;j<config->fCompInfo->fLength;++j) {
369 char *cont = contp[j];
370 TVirtualCollectionProxy::TPushPop helper( proxy, cont );
371 Int_t nobjects = cont ? proxy->Size() : 0;
372 buf << nobjects;
373
374 // TODO: method is private, should be made accesible from here
375 // subinfo->WriteBufferSTL(buf,proxy,nobjects);
376 }
377 //}
378 buf.SetByteCount(pos,kTRUE);
379 return 0;
380 }
381 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
382 if (kIsTextT) {
383 // use same method which is used in kSTL
384 buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
385 } else if (pstreamer == nullptr) {
386 // for (int k = 0; k < narr; ++k) {
387 char **contp = (char **)((char *)addr + ioffset);
388 for (int j = 0; j < config->fCompInfo->fLength; ++j) {
389 char *cont = contp[j];
390 cl->Streamer(cont, buf);
391 }
392 // }
393 } else {
394 // for (int k = 0; k < narr; ++k) {
395 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
396 //}
397 }
398 buf.SetByteCount(pos, kTRUE);
399 return 0;
400 }
401
402
403 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
404 * potentially can be used later for non-text streaming */
405 template<bool kIsTextT>
407 {
408 TClass *cle = config->fCompInfo->fClass;
409 TStreamerElement * aElement = (TStreamerElement*) config->fCompInfo->fElem;
410 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
411 //TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
412 //TClass* vClass = proxy ? proxy->GetValueClass() : 0;
413
414 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
415 UInt_t ioffset = eoffset + config->fOffset;
416
417
418 UInt_t start,count;
419 Version_t vers = buf.ReadVersion(&start, &count, cle);
420
421 if (!kIsTextT && (vers & TBufferFile::kStreamedMemberWise) ) {
422 // Collection was saved member-wise
423
425
426 TClass *newClass = aElement->GetNewClass();
427 TClass *oldClass = aElement->GetClassPointer();
428 if( vers < 9 && newClass && newClass!=oldClass ) {
429 Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
430 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
431 return 0;
432 }
433
434 Version_t vClVersion = 0; // For vers less than 9, we have to use the current version.
435 if( vers >= 9 ) {
436 vClVersion = buf.ReadVersionForMemberWise( cle->GetCollectionProxy()->GetValueClass() );
437 }
438
439 TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : nullptr);
440 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
441 TStreamerInfo *subinfo = nullptr;
442
443 if( newProxy ) {
444 // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
445 subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
446 } else {
447 subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( vClVersion );
448 newProxy = oldProxy;
449 }
450 if (subinfo) {
451 // DOLOOP {
452 void* env;
453 void **contp = (void**)((char *) addr + ioffset);
454 for(int j=0;j<config->fCompInfo->fLength;j++) {
455 void *cont = contp[j];
456 if (cont==nullptr) {
457 contp[j] = cle->New();
458 cont = contp[j];
459 }
460 TVirtualCollectionProxy::TPushPop helper( newProxy, cont );
461 Int_t nobjects;
462 buf >> nobjects;
463 env = newProxy->Allocate(nobjects,true);
464 subinfo->ReadBufferSTL(buf,newProxy,nobjects,/* offset */ 0, vers>=7 );
465 newProxy->Commit(env);
466 }
467 // } // DOLOOP
468 }
469 buf.CheckByteCount(start,count,aElement->GetFullName());
470 return 0;
471 }
472
473 if (kIsTextT) {
474 // use same method which is used in kSTL
475 buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
476 } else if (pstreamer == nullptr) {
477 // DOLOOP {
478 void **contp = (void **)((char *)addr + ioffset);
479 for (int j = 0; j < config->fCompInfo->fLength; j++) {
480 void *cont = contp[j];
481 if (cont == nullptr) {
482 // int R__n;
483 // b >> R__n;
484 // b.SetOffset(b.GetOffset()-4); // rewind to the start of the int
485 // if (R__n) continue;
486 contp[j] = cle->New();
487 cont = contp[j];
488 }
489 cle->Streamer(cont, buf);
490 }
491 // }
492 } else {
493 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
494 }
495 buf.CheckByteCount(start, count, aElement->GetFullName());
496
497 return 0;
498 }
499
500 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
501 * potentially can be used later for non-text streaming */
502 template<bool kIsTextT>
504 {
505 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
506 UInt_t ioffset = eoffset + config->fOffset;
507
508 if (!kIsTextT && config->fCompInfo->fStreamer) {
509 // Get any private streamer which was set for the data member.
510 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
511 // -- We have a private streamer.
512 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
513 // Loop over the entries in the clones array or the STL container.
514 //for (int k = 0; k < narr; ++k) {
515 // Get a pointer to the counter for the varying length array.
516 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
517
518 // And call the private streamer, passing it the buffer, the object, and the counter.
519 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
520 //} for k
521 buf.SetByteCount(pos, kTRUE);
522 // We are done, next streamer element.
523 return 0;
524 }
525
526 // Get the class of the data member.
527 TClass* cl = config->fCompInfo->fClass;
528 // Which are we, an array of objects or an array of pointers to objects?
529 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
530
531 // By default assume the file version is the newest.
532 Int_t fileVersion = kMaxInt;
533
534 if (!kIsTextT) {
535 // At this point we do *not* have a private streamer.
536 // Get the version of the file we are writing to.
537 TFile* file = (TFile*) buf.GetParent();
538 if (file) {
539 fileVersion = file->GetVersion();
540 }
541 }
542 // Write the class version to the buffer.
543 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
544 if (fileVersion > 51508) {
545 // -- Newer versions allow polymorphic pointers to objects.
546 // Loop over the entries in the clones array or the STL container.
547 //for (int k = 0; k < narr; ++k) {
548 // Get the counter for the varying length array.
549 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
550
551 //b << vlen;
552 if (vlen) {
553 // Get a pointer to the array of pointers.
554 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
555 // Loop over each element of the array of pointers to varying-length arrays.
556 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
557 if (!pp[ndx]) {
558 // -- We do not have a pointer to a varying-length array.
559 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
560 // ::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()));
561 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());
562 continue;
563 }
564 if (!isPtrPtr) {
565 // -- We are a varying-length array of objects.
566 // Write the entire array of objects to the buffer.
567 // Note: Polymorphism is not allowed here.
568 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
569 } else {
570 // -- We are a varying-length array of pointers to objects.
571 // Write the entire array of object pointers to the buffer.
572 // Note: The object pointers are allowed to be polymorphic.
573 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
574 } // isPtrPtr
575 } // ndx
576 } else // vlen
577 if (kIsTextT) {
578 // special handling for the text-based streamers
579 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
580 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
581 }
582 //} // k
583 }
584 else {
585 // -- Older versions do *not* allow polymorphic pointers to objects.
586 // Loop over the entries in the clones array or the STL container.
587 //for (int k = 0; k < narr; ++k) {
588 // Get the counter for the varying length array.
589 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
590 //b << vlen;
591 if (vlen) {
592 // Get a pointer to the array of pointers.
593 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
594 // -- Older versions do *not* allow polymorphic pointers to objects.
595 // Loop over each element of the array of pointers to varying-length arrays.
596 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
597 if (!pp[ndx]) {
598 // -- We do not have a pointer to a varying-length array.
599 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
600 // ::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()));
601 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());
602 continue;
603 }
604 if (!isPtrPtr) {
605 // -- We are a varying-length array of objects.
606 // Loop over the elements of the varying length array.
607 for (Int_t v = 0; v < vlen; ++v) {
608 // Write the object to the buffer.
609 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
610 } // v
611 }
612 else {
613 // -- We are a varying-length array of pointers to objects.
614 // Loop over the elements of the varying length array.
615 for (Int_t v = 0; v < vlen; ++v) {
616 // Get a pointer to the object pointer.
617 char** r = (char**) pp[ndx];
618 // Write the object to the buffer.
619 cl->Streamer(r[v], buf);
620 } // v
621 } // isPtrPtr
622 } // ndx
623 } // vlen
624 //} // k
625 } // fileVersion
626 // Backpatch the byte count into the buffer.
627 buf.SetByteCount(pos, kTRUE);
628
629 return 0;
630 }
631
632
633 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
634 * potentially can be used later for non-text streaming */
635 template<bool kIsTextT>
637 {
638 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
639 UInt_t ioffset = eoffset + config->fOffset;
640
641 // Get the class of the data member.
642 TClass* cl = config->fCompInfo->fClass;
643
644 // Check for a private streamer.
645 if (!kIsTextT && config->fCompInfo->fStreamer) {
646 // Get any private streamer which was set for the data member.
647 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
648 // -- We have a private streamer.
649 // Read the class version and byte count from the buffer.
650 UInt_t start = 0;
651 UInt_t count = 0;
652 buf.ReadVersion(&start, &count, cl);
653 // Loop over the entries in the clones array or the STL container.
654 //for (Int_t k = 0; k < narr; ++k) {
655
656 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
657 // And call the private streamer, passing it the buffer, the object, and the counter.
658 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
659
660 // } // for k
661 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
662 // We are done, next streamer element.
663 return 0;
664 }
665
666 // Which are we, an array of objects or an array of pointers to objects?
667 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
668
669 // By default assume the file version is the newest.
670 Int_t fileVersion = kMaxInt;
671 if (!kIsTextT) {
672 // At this point we do *not* have a private streamer.
673 // Get the version of the file we are reading from.
674 TFile* file = (TFile*) buf.GetParent();
675 if (file) {
676 fileVersion = file->GetVersion();
677 }
678 }
679 // Read the class version and byte count from the buffer.
680 UInt_t start = 0;
681 UInt_t count = 0;
682 buf.ReadVersion(&start, &count, cl);
683 if (fileVersion > 51508) {
684 // -- Newer versions allow polymorphic pointers.
685 // Loop over the entries in the clones array or the STL container.
686 // for (Int_t k = 0; k < narr; ++k) {
687 // Get the counter for the varying length array.
688 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
689 config->fCompInfo->fMethod /*counter offset*/));
690 // Int_t realLen;
691 // b >> realLen;
692 // if (realLen != vlen) {
693 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
694 //}
695 // Get a pointer to the array of pointers.
696 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
697 // Loop over each element of the array of pointers to varying-length arrays.
698 // if (!pp) {
699 // continue;
700 // }
701
702 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
703 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
704 // if (!pp[ndx]) {
705 // -- We do not have a pointer to a varying-length array.
706 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
707 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
708 // continue;
709 //}
710 // Delete any memory at pp[ndx].
711 if (!isPtrPtr) {
712 cl->DeleteArray(pp[ndx]);
713 pp[ndx] = 0;
714 } else {
715 // Using vlen is wrong here because it has already
716 // been overwritten with the value needed to read
717 // the current record. Fixing this will require
718 // doing a pass over the object at the beginning
719 // of the I/O and releasing all the buffer memory
720 // for varying length arrays before we overwrite
721 // the counter values.
722 //
723 // For now we will just leak memory, just as we
724 // have always done in the past. Fix this.
725 //
726 // char** r = (char**) pp[ndx];
727 // if (r) {
728 // for (Int_t v = 0; v < vlen; ++v) {
729 // cl->Destructor(r[v]);
730 // r[v] = 0;
731 // }
732 //}
733 delete[] pp[ndx];
734 pp[ndx] = 0;
735 }
736 if (!vlen) {
737 if (kIsTextT) {
738 // special handling for the text-based streamers - keep calling to shift array index
739 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
740 }
741 continue;
742 }
743 // Note: We now have pp[ndx] is null.
744 // Allocate memory to read into.
745 if (!isPtrPtr) {
746 // -- We are a varying-length array of objects.
747 // Note: Polymorphism is not allowed here.
748 // Allocate a new array of objects to read into.
749 pp[ndx] = (char *)cl->NewArray(vlen);
750 if (!pp[ndx]) {
751 Error("ReadBuffer", "Memory allocation failed!\n");
752 continue;
753 }
754 } else {
755 // -- We are a varying-length array of pointers to objects.
756 // Note: The object pointers are allowed to be polymorphic.
757 // Allocate a new array of pointers to objects to read into.
758 pp[ndx] = (char *)new char *[vlen];
759 if (!pp[ndx]) {
760 Error("ReadBuffer", "Memory allocation failed!\n");
761 continue;
762 }
763 // And set each pointer to null.
764 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
765 // = (char*) new char*[vlen];
766 }
767 if (!isPtrPtr) {
768 // -- We are a varying-length array of objects.
769 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
770 } else {
771 // -- We are a varying-length array of object pointers.
772 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
773 } // isPtrPtr
774 } // ndx
775 // } // k
776 } else {
777 // -- Older versions do *not* allow polymorphic pointers.
778 // Loop over the entries in the clones array or the STL container.
779 // for (Int_t k = 0; k < narr; ++k) {
780 // Get the counter for the varying length array.
781 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
782 config->fCompInfo->fMethod /*counter offset*/));
783 // Int_t realLen;
784 // b >> realLen;
785 // if (realLen != vlen) {
786 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
787 //}
788 // Get a pointer to the array of pointers.
789 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
790 // if (!pp) {
791 // continue;
792 //}
793
794 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
795
796 // Loop over each element of the array of pointers to varying-length arrays.
797 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
798 // if (!pp[ndx]) {
799 // -- We do not have a pointer to a varying-length array.
800 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
801 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
802 // continue;
803 //}
804 // Delete any memory at pp[ndx].
805 if (!isPtrPtr) {
806 cl->DeleteArray(pp[ndx]);
807 pp[ndx] = 0;
808 } else {
809 // Using vlen is wrong here because it has already
810 // been overwritten with the value needed to read
811 // the current record. Fixing this will require
812 // doing a pass over the object at the beginning
813 // of the I/O and releasing all the buffer memory
814 // for varying length arrays before we overwrite
815 // the counter values.
816 //
817 // For now we will just leak memory, just as we
818 // have always done in the past. Fix this.
819 //
820 // char** r = (char**) pp[ndx];
821 // if (r) {
822 // for (Int_t v = 0; v < vlen; ++v) {
823 // cl->Destructor(r[v]);
824 // r[v] = 0;
825 // }
826 //}
827 delete[] pp[ndx];
828 pp[ndx] = 0;
829 }
830 if (!vlen) {
831 continue;
832 }
833 // Note: We now have pp[ndx] is null.
834 // Allocate memory to read into.
835 if (!isPtrPtr) {
836 // -- We are a varying-length array of objects.
837 // Note: Polymorphism is not allowed here.
838 // Allocate a new array of objects to read into.
839 pp[ndx] = (char *)cl->NewArray(vlen);
840 if (!pp[ndx]) {
841 Error("ReadBuffer", "Memory allocation failed!\n");
842 continue;
843 }
844 } else {
845 // -- We are a varying-length array of pointers to objects.
846 // Note: The object pointers are allowed to be polymorphic.
847 // Allocate a new array of pointers to objects to read into.
848 pp[ndx] = (char *)new char *[vlen];
849 if (!pp[ndx]) {
850 Error("ReadBuffer", "Memory allocation failed!\n");
851 continue;
852 }
853 // And set each pointer to null.
854 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
855 // = (char*) new char*[vlen];
856 }
857 if (!isPtrPtr) {
858 // -- We are a varying-length array of objects.
859 // Loop over the elements of the varying length array.
860 for (Int_t v = 0; v < vlen; ++v) {
861 // Read the object from the buffer.
862 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
863 } // v
864 } else {
865 // -- We are a varying-length array of object pointers.
866 // Get a pointer to the object pointer array.
867 char **r = (char **)pp[ndx];
868 // Loop over the elements of the varying length array.
869 for (Int_t v = 0; v < vlen; ++v) {
870 // Allocate an object to read into.
871 r[v] = (char *)cl->New();
872 if (!r[v]) {
873 // Do not print a second error message here.
874 // Error("ReadBuffer", "Memory allocation failed!\n");
875 continue;
876 }
877 // Read the object from the buffer.
878 cl->Streamer(r[v], buf);
879 } // v
880 } // isPtrPtr
881 } // ndx
882 // } // k
883 } // fileVersion
884 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
885 return 0;
886 }
887
889 // Configuration object for the Float16/Double32 where a factor has been specified.
890 public:
894 TConfiguration *Copy() override { return new TConfWithFactor(*this); }
895 };
896
897 template <typename T>
899 {
900 // Stream a Float16 or Double32 where a factor has been specified.
901 //a range was specified. We read an integer and convert it back to a double.
902
903 TConfWithFactor *conf = (TConfWithFactor *)config;
904 buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
905 return 0;
906 }
907
909 // Configuration object for the Float16/Double32 where a factor has been specified.
910 public:
912 TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
913 TConfiguration *Copy() override { return new TConfNoFactor(*this); }
914 };
915
916 template <typename T>
918 {
919 // Stream a Float16 or Double32 where a factor has not been specified.
920
921 TConfNoFactor *conf = (TConfNoFactor *)config;
922 Int_t nbits = conf->fNbits;
923
924 buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
925 return 0;
926 }
927
929 {
930 // Read in a TString object.
931
932 // Idea: We could separate the TString Streamer in its two parts and
933 // avoid the if (buf.IsReading()) and try having it inlined.
934 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
935 return 0;
936 }
937
939 {
940 // Read in a TObject object part.
941
942 // Idea: We could separate the TObject Streamer in its two parts and
943 // avoid the if (buf.IsReading()).
944 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
945 return 0;
946 }
947
949 {
950 // Read in a TNamed object part.
951 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
952 // can skip the streamer.
953
954 // Idea: We could extract the code from ReadClassBuffer and avoid one function
955 // code.
956 static const TClass *TNamed_cl = TNamed::Class();
957 return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
958 }
959
960 class TConfigSTL : public TConfiguration {
961 // Configuration object for the kSTL case
962 private:
963 void Init() {
965 if (proxy) {
971 }
972 }
973
974 public:
975 TClass *fOldClass; // Class of the content on file
976 TClass *fNewClass; // Class of the content in memory.
978 const char *fTypeName; // Type name of the member as typed by ther user.
979 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
980
986
987 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
988 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
990
991 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, const char *type_name, Bool_t isbase) :
992 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
994
995 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) :
996 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
998
999 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) :
1000 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
1002
1003 TConfiguration *Copy() override { return new TConfigSTL(*this); }
1004 };
1005
1007 // Configuration object for the Float16/Double32 where a factor has been specified.
1008 public:
1012 TConfiguration *Copy() override { return new TConfSTLWithFactor(*this); }
1013 };
1014
1016 // Configuration object for the Float16/Double32 where a factor has been specified.
1017 public:
1019 TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1020 TConfiguration *Copy() override { return new TConfSTLNoFactor(*this); }
1021 };
1022
1024 // Base class of the Configurations used in member wise streaming.
1025 protected:
1026 public:
1027 Long_t fIncrement; // Either a value to increase the cursor by and
1028 public:
1029 TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1030 //virtual void PrintDebug(TBuffer &buffer, void *);
1032 void Print() const override
1033 {
1034 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1035 }
1036
1037 void* GetFirstAddress(void *start, const void * /* end */) const override
1038 {
1039 // Return the address of the first element of the collection.
1040
1041 return start;
1042 }
1043
1044 TLoopConfiguration* Copy() const override { return new TVectorLoopConfig(*this); }
1045 };
1046
1048 // Base class of the Configurations used in member wise streaming.
1049 public:
1051 //virtual void PrintDebug(TBuffer &buffer, void *);
1052 virtual ~TAssocLoopConfig() {};
1053 void Print() const override
1054 {
1055 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1056 }
1057 TLoopConfiguration* Copy() const override { return new TAssocLoopConfig(*this); }
1058
1059 void* GetFirstAddress(void *start, const void * /* end */) const override
1060 {
1061 // Return the address of the first element of the collection.
1062
1063 R__ASSERT(0);
1064// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1065// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1066// arr0 = genloopconfig->fNext(iter,end_collection);
1067// if (iter != &iterator[0]) {
1068// genloopconfig->fDeleteIterator(iter);
1069// }
1070 return start;
1071 }
1072 };
1073
1075 // Configuration object for the generic case of member wise streaming looping.
1076 private:
1077 void Init(Bool_t read) {
1078 if (fProxy) {
1079 if (fProxy->HasPointers()) {
1083 } else {
1084 fNext = fProxy->GetFunctionNext(read);
1087 }
1088 }
1089 }
1090 public:
1094
1096 {
1097 Init(read);
1098 }
1100 void Print() const override
1101 {
1102 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1103 }
1104 TLoopConfiguration* Copy() const override { return new TGenericLoopConfig(*this); }
1105
1106 void* GetFirstAddress(void *start_collection, const void *end_collection) const override
1107 {
1108 // Return the address of the first element of the collection.
1109
1111 void *iter = fCopyIterator(&iterator,start_collection);
1112 void *arr0 = fNext(iter,end_collection);
1113 if (iter != &iterator[0]) {
1114 fDeleteIterator(iter);
1115 }
1116 return arr0;
1117 }
1118 };
1119
1121 {
1122 // Collection was saved member-wise
1123
1124 TConfigSTL *config = (TConfigSTL*)conf;
1126
1127 if( vers >= 8 ) {
1128
1129 TClass *oldClass = config->fOldClass;
1130
1131 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1132 if (!oldProxy) {
1133 // Missing information, broken file ... give up
1134 return;
1135 }
1136 TClass *valueClass = oldProxy->GetValueClass();
1137 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1138
1139 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1140 Int_t nobjects;
1141 buf.ReadInt(nobjects);
1142 void* alternative = oldProxy->Allocate(nobjects,true);
1143 if (nobjects) {
1144 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1145
1148 void *begin = &(startbuf[0]);
1149 void *end = &(endbuf[0]);
1150 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1151 // We can not get here with a split vector of pointer, so we can indeed assume
1152 // that actions->fConfiguration != null.
1153 buf.ApplySequence(*actions, begin, end);
1154 if (begin != &(startbuf[0])) {
1155 // assert(end != endbuf);
1156 config->fDeleteTwoIterators(begin,end);
1157 }
1158 }
1159 oldProxy->Commit(alternative);
1160
1161 } else {
1162
1163 TClass *oldClass = config->fOldClass;
1164
1165 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1166 if (!oldProxy) {
1167 // Missing information, broken file ... give up
1168 return;
1169 }
1170
1171 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1172 Int_t nobjects;
1173 buf.ReadInt(nobjects);
1174 void* env = oldProxy->Allocate(nobjects,true);
1175
1176 if (nobjects || vers < 7 ) {
1177 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1178 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1179
1180 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1181 }
1182 oldProxy->Commit(env);
1183 }
1184 }
1185
1187 {
1188 // Collection was saved member-wise
1189
1190 TConfigSTL *config = (TConfigSTL*)conf;
1192
1193 if( vers >= 8 ) {
1194
1195 TClass *oldClass = config->fOldClass;
1196
1197 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1198 if (!oldProxy) {
1199 // Missing information, broken file ... give up
1200 return;
1201 }
1202 TClass *valueClass = oldProxy->GetValueClass();
1203 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1204
1205 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1206
1207 int objectSize = oldClass->Size();
1208 char *obj = (char*)addr;
1209 char *endobj = obj + conf->fLength*objectSize;
1210
1211 for(; obj<endobj; obj+=objectSize) {
1212 Int_t nobjects;
1213 buf.ReadInt(nobjects);
1214 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1215 void* alternative = oldProxy->Allocate(nobjects,true);
1216 if (nobjects) {
1219 void *begin = &(startbuf[0]);
1220 void *end = &(endbuf[0]);
1221 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1222 // We can not get here with a split vector of pointer, so we can indeed assume
1223 // that actions->fConfiguration != null.
1224 buf.ApplySequence(*actions, begin, end);
1225 if (begin != &(startbuf[0])) {
1226 // assert(end != endbuf);
1227 config->fDeleteTwoIterators(begin,end);
1228 }
1229 }
1230 oldProxy->Commit(alternative);
1231 }
1232
1233 } else {
1234
1235 TClass *oldClass = config->fOldClass;
1236
1237 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1238 if (!oldProxy) {
1239 // Missing information, broken file ... give up
1240 return;
1241 }
1242
1243 int objectSize = oldClass->Size();
1244 char *obj = (char*)addr;
1245 char *endobj = obj + conf->fLength*objectSize;
1246
1247 for(; obj<endobj; obj+=objectSize) {
1248 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1249 Int_t nobjects;
1250 buf.ReadInt(nobjects);
1251 void* env = oldProxy->Allocate(nobjects,true);
1252
1253 if (nobjects || vers < 7 ) {
1254 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1255 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1256
1257 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1258 }
1259 oldProxy->Commit(env);
1260 }
1261 }
1262 }
1263
1265 {
1266 // Collection was saved member-wise
1267
1268 TConfigSTL *config = (TConfigSTL*)conf;
1269
1271
1272 TClass *newClass = config->fNewClass;
1273 TClass *oldClass = config->fOldClass;
1274
1275 if( vers < 8 ) {
1276 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1277 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1278 } else {
1279
1280 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1281
1282 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1283 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1284
1285 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1286 Int_t nobjects;
1287 buf.ReadInt(nobjects);
1288 void* alternative = newProxy->Allocate(nobjects,true);
1289 if (nobjects) {
1290 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1293 void *begin = &(startbuf[0]);
1294 void *end = &(endbuf[0]);
1295 config->fCreateIterators( alternative, &begin, &end, newProxy);
1296 // We can not get here with a split vector of pointer, so we can indeed assume
1297 // that actions->fConfiguration != null.
1298 buf.ApplySequence(*actions, begin, end);
1299 if (begin != &(startbuf[0])) {
1300 // assert(end != endbuf);
1301 config->fDeleteTwoIterators(begin,end);
1302 }
1303 }
1304 newProxy->Commit(alternative);
1305 }
1306 }
1307
1309 {
1310 // Collection was saved member-wise
1311
1312 TConfigSTL *config = (TConfigSTL*)conf;
1313
1315
1316 TClass *newClass = config->fNewClass;
1317 TClass *oldClass = config->fOldClass;
1318
1319 if( vers < 8 ) {
1320 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1321 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1322 } else {
1323
1324 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1325
1326 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1327 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1328
1329 int objectSize = newClass->Size();
1330 char *obj = (char*)addr;
1331 char *endobj = obj + conf->fLength*objectSize;
1332
1333 for(; obj<endobj; obj+=objectSize) {
1334 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1335 Int_t nobjects;
1336 buf.ReadInt(nobjects);
1337 void* alternative = newProxy->Allocate(nobjects,true);
1338 if (nobjects) {
1339 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1342 void *begin = &(startbuf[0]);
1343 void *end = &(endbuf[0]);
1344 config->fCreateIterators( alternative, &begin, &end, newProxy);
1345 // We can not get here with a split vector of pointer, so we can indeed assume
1346 // that actions->fConfiguration != null.
1347 buf.ApplySequence(*actions, begin, end);
1348 if (begin != &(startbuf[0])) {
1349 // assert(end != endbuf);
1350 config->fDeleteTwoIterators(begin,end);
1351 }
1352 }
1353 newProxy->Commit(alternative);
1354 }
1355 }
1356 }
1357
1358 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1359 {
1360 TConfigSTL *config = (TConfigSTL*)conf;
1361 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1362 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1363 }
1364 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1365 {
1366 TConfigSTL *config = (TConfigSTL*)conf;
1367 (*config->fStreamer)(buf,addr,conf->fLength);
1368 }
1370 {
1371 // case of old TStreamerInfo
1372
1373 TConfigSTL *config = (TConfigSTL*)conf;
1374 // Backward compatibility. Some TStreamerElement's where without
1375 // Streamer but were not removed from element list
1376 if (config->fIsSTLBase || vers == 0) {
1377 buf.SetBufferOffset(start); //there is no byte count
1378 }
1379 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1380 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1381 }
1383 {
1384 // case of old TStreamerInfo
1385
1386 TConfigSTL *config = (TConfigSTL*)conf;
1387 // Backward compatibility. Some TStreamerElement's where without
1388 // Streamer but were not removed from element list
1389 if (config->fIsSTLBase || vers == 0) {
1390 buf.SetBufferOffset(start); //there is no byte count
1391 }
1392 (*config->fStreamer)(buf,addr,conf->fLength);
1393 }
1394
1395 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1396 void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1398 {
1399 TConfigSTL *config = (TConfigSTL*)conf;
1400 UInt_t start, count;
1401 Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1402 if ( vers & TBufferFile::kStreamedMemberWise ) {
1403 memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1404 } else {
1405 objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1406 }
1407 buf.CheckByteCount(start,count,config->fTypeName);
1408 return 0;
1409 }
1410
1411 template <typename From, typename To>
1413 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1414 {
1415 // Simple conversion from a 'From' on disk to a 'To' in memory.
1416 From temp;
1417 buf >> temp;
1418 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1419 return 0;
1420 }
1421 };
1422
1423 template <typename To>
1425 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1426 {
1427 // Simple conversion from a 'From' on disk to a 'To' in memory
1428 UInt_t temp;
1429 buf >> temp;
1430
1431 if ((temp & kIsReferenced) != 0) {
1432 HandleReferencedTObject(buf,addr,config);
1433 }
1434
1435 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1436 return 0;
1437 }
1438 };
1439
1440 template <typename From, typename To>
1442 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1443 {
1444 // Simple conversion from a 'From' on disk to a 'To' in memory.
1445 TConfWithFactor *conf = (TConfWithFactor *)config;
1446 From temp;
1447 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1448 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1449 return 0;
1450 }
1451 };
1452
1453 template <typename From, typename To>
1455 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1456 {
1457 // Simple conversion from a 'From' on disk to a 'To' in memory.
1458 TConfNoFactor *conf = (TConfNoFactor *)config;
1459 From temp;
1460 buf.ReadWithNbits(&temp, conf->fNbits);
1461 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1462 return 0;
1463 }
1464 };
1465
1467 // Configuration object for the PushDataCache case.
1468 public:
1470
1472 TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1473 {}
1474
1475 void Print() const override
1476 {
1478 if (fOnfileObject)
1479 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1480 info->GetClass()->GetName(), fOffset);
1481 else
1482 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1483 info->GetClass()->GetName(), fOffset);
1484 }
1485 void PrintDebug(TBuffer &buffer, void *object) const override
1486 {
1487 if (gDebug > 1) {
1489 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1490 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1491
1492 }
1493 }
1494 };
1495
1497 {
1499 auto onfileObject = config->fOnfileObject;
1500
1501 // onfileObject->SetSize(1);
1502 b.PushDataCache( onfileObject );
1503
1504 return 0;
1505 }
1506
1507 Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1508 {
1510 auto onfileObject = config->fOnfileObject;
1511
1512 // onfileObject->SetSize(n);
1513 b.PushDataCache( onfileObject );
1514
1515 return 0;
1516 }
1517
1518 Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1519 {
1521 auto onfileObject = config->fOnfileObject;
1522
1523 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1524 UInt_t n = proxy->Size();
1525
1526 onfileObject->SetSize(n);
1527 b.PushDataCache( onfileObject );
1528
1529 return 0;
1530 }
1531
1533 {
1534 b.PopDataCache();
1535 return 0;
1536 }
1537
1538 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1539 {
1540 b.PopDataCache();
1541 return 0;
1542 }
1543
1545 {
1546 b.PopDataCache();
1547 return 0;
1548 }
1549
1551 // Configuration object for the UseCache case.
1552 public:
1555
1557 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1558 void PrintDebug(TBuffer &b, void *addr) const override
1559 {
1560 if (gDebug > 1) {
1561 // Idea: We should print the name of the action function.
1563 TStreamerElement *aElement = fCompInfo->fElem;
1564 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1565 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1566 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1567 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1568 }
1569
1570 }
1573 {
1575 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1576 return copy;
1577 }
1578 };
1579
1581 {
1583
1584 Int_t bufpos = b.Length();
1585 TVirtualArray *cached = b.PeekDataCache();
1586 if (cached==0) {
1587 TStreamerElement *aElement = conf->fCompInfo->fElem;
1588 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1589 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1590 char *ptr = (char*)addr;
1591 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1592 } else {
1593 config->fAction(b, (*cached)[0]);
1594 }
1595 // Idea: Factor out this 'if' to a UseCacheRepeat function
1596 if (config->fNeedRepeat) {
1597 b.SetBufferOffset(bufpos);
1598 }
1599 return 0;
1600 }
1601
1602 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1603 {
1605 Int_t bufpos = b.Length();
1606
1607 TVirtualArray *cached = b.PeekDataCache();
1608 if (cached==0) {
1609 TStreamerElement *aElement = config->fCompInfo->fElem;
1610 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1611 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1612 char *ptr = (char*)start;
1613 UInt_t n = (((void**)end)-((void**)start));
1614 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1615 } else {
1616 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1617 void *cached_start = (*cached)[0];
1618 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1619 config->fAction(b,cached_start,cached_end,&cached_config);
1620 }
1621 // Idea: Factor out this 'if' to a UseCacheRepeat function
1622 if (config->fNeedRepeat) {
1623 b.SetBufferOffset(bufpos);
1624 }
1625 return 0;
1626 }
1627
1628 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1629 {
1631
1632 Int_t bufpos = b.Length();
1633 TVirtualArray *cached = b.PeekDataCache();
1634 if (cached==0) {
1635 TStreamerElement *aElement = config->fCompInfo->fElem;
1636 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1637 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1638 char *ptr = (char*)start;
1639 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1640 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1641 } else {
1642 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1643 void *cached_start = (*cached)[0];
1644 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1645 config->fAction(b,cached_start,cached_end,&cached_config);
1646 }
1647 // Idea: Factor out this 'if' to a UseCacheRepeat function
1648 if (config->fNeedRepeat) {
1649 b.SetBufferOffset(bufpos);
1650 }
1651 return 0;
1652 }
1653
1655 {
1657
1658 Int_t bufpos = b.Length();
1659 TVirtualArray *cached = b.PeekDataCache();
1660 if (cached==0) {
1661 TStreamerElement *aElement = config->fCompInfo->fElem;
1662 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1663
1664 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1665 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1666 UInt_t n = proxy->Size();
1667 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1668 } else {
1669 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1670 void *cached_start = (*cached)[0];
1671 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1672 config->fAction(b,cached_start,cached_end,&cached_config);
1673 }
1674 // Idea: Factor out this 'if' to a UseCacheRepeat function
1675 if (config->fNeedRepeat) {
1676 b.SetBufferOffset(bufpos);
1677 }
1678 return 0;
1679 }
1680
1681 // Support for collections.
1682
1683 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1684 {
1685 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1686 return 0;
1687 }
1688
1689 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1690 {
1691 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1692 return 0;
1693 }
1694
1696
1698 {
1700 return kVectorLooper;
1701 } else if ( (proxy.GetCollectionType() == ROOT::kSTLvector)) {
1703 return kGenericLooper;
1704 else
1705 return kVectorLooper;
1710 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1711 return kAssociativeLooper;
1712 } else {
1713 return kGenericLooper;
1714 }
1715 }
1716
1718
1719 template <typename T>
1720 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1721 {
1722 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1723 iter = (char*)iter + config->fOffset;
1724 end = (char*)end + config->fOffset;
1725 for(; iter != end; iter = (char*)iter + incr ) {
1726 T *x = (T*) ((char*) iter);
1727 buf >> *x;
1728 }
1729 return 0;
1730 }
1731
1732 template <typename From, typename To>
1734 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1735 {
1736 // Simple conversion from a 'From' on disk to a 'To' in memory.
1737 From temp;
1738 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1739 iter = (char*)iter + config->fOffset;
1740 end = (char*)end + config->fOffset;
1741 for(; iter != end; iter = (char*)iter + incr ) {
1742 buf >> temp;
1743 *(To*)( ((char*)iter) ) = (To)temp;
1744 }
1745 return 0;
1746 }
1747 };
1748
1749 template <typename To>
1751 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1752 {
1753 // Simple conversion from a 'From' on disk to a 'To' in memory.
1754 UInt_t temp;
1755 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1756 iter = (char*)iter + config->fOffset;
1757 end = (char*)end + config->fOffset;
1758 for(; iter != end; iter = (char*)iter + incr ) {
1759 buf >> temp;
1760
1761 if ((temp & kIsReferenced) != 0) {
1762 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1763 }
1764
1765 *(To*)( ((char*)iter) ) = (To)temp;
1766 }
1767 return 0;
1768 }
1769 };
1770
1771 template <typename From, typename To>
1773 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1774 {
1775 // Simple conversion from a 'From' on disk to a 'To' in memory.
1776 TConfWithFactor *conf = (TConfWithFactor *)config;
1777 From temp;
1778 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1779 iter = (char*)iter + config->fOffset;
1780 end = (char*)end + config->fOffset;
1781 for(; iter != end; iter = (char*)iter + incr ) {
1782 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1783 *(To*)( ((char*)iter) ) = (To)temp;
1784 }
1785 return 0;
1786 }
1787 };
1788
1789 template <typename From, typename To>
1791 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1792 {
1793 // Simple conversion from a 'From' on disk to a 'To' in memory.
1794 TConfNoFactor *conf = (TConfNoFactor *)config;
1795 From temp;
1796 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1797 iter = (char*)iter + config->fOffset;
1798 end = (char*)end + config->fOffset;
1799 for(; iter != end; iter = (char*)iter + incr ) {
1800 buf.ReadWithNbits(&temp, conf->fNbits);
1801 *(To*)( ((char*)iter) ) = (To)temp;
1802 }
1803 return 0;
1804 }
1805 };
1806
1807 template <typename T>
1808 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1809 {
1810 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1811 iter = (char*)iter + config->fOffset;
1812 end = (char*)end + config->fOffset;
1813 for(; iter != end; iter = (char*)iter + incr ) {
1814 T *x = (T*) ((char*) iter);
1815 buf << *x;
1816 }
1817 return 0;
1818 }
1819
1820 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1821 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1822 {
1823 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1824 //Idea: can we factor out the addition of fOffset
1825 // iter = (char*)iter + config->fOffset;
1826 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1827 iter_action(buf, iter, config);
1828 }
1829 return 0;
1830 }
1831
1832 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1833 {
1834 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1835 // punt.
1836
1837 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1838 UInt_t n = (((char*)end)-((char*)start))/incr;
1839 char **arrptr = new char*[n];
1840 UInt_t i = 0;
1841 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1842 arrptr[i] = (char*)iter;
1843 }
1844 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1845 delete [] arrptr;
1846
1847 // // Idea: need to cache this result!
1848 // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1849 // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1850 //
1851 // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1852 // *TClass *cle = aElement->GetNewBaseClass();
1853 // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1854 //
1855 // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1856 //
1857 // actions->ReadBuffer(b,start,end);
1858 // delete actions;
1859
1860 // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1861 // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1862 // {
1863 // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1864 //
1865 // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1866 // }
1867 return 0;
1868 }
1869
1870 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1871 {
1872 // Well the implementation is non trivial. For now punt.
1873
1874 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1875 UInt_t n = (((char*)end)-((char*)start))/incr;
1876 char **arrptr = new char*[n];
1877 UInt_t i = 0;
1878 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1879 arrptr[i] = (char*)iter;
1880 }
1881 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1882 delete [] arrptr;
1883 return 0;
1884 }
1885
1886 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1887 {
1888 // Well the implementation is non trivial. For now punt.
1889
1890 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1891 UInt_t n = (((char*)end)-((char*)start))/incr;
1892 char **arrptr = new char*[n];
1893 UInt_t i = 0;
1894 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1895 arrptr[i] = (char*)iter;
1896 }
1897 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1898 delete [] arrptr;
1899 return 0;
1900 }
1901
1902 template <typename T>
1904 {
1905 // Collection of numbers. Memberwise or not, it is all the same.
1906
1907 TConfigSTL *config = (TConfigSTL*)conf;
1908 UInt_t start, count;
1909 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1910
1911 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1912 Int_t nvalues;
1913 buf.ReadInt(nvalues);
1914 vec->resize(nvalues);
1915
1916#ifdef R__VISUAL_CPLUSPLUS
1917 if (nvalues <= 0) {
1918 buf.CheckByteCount(start,count,config->fTypeName);
1919 return 0;
1920 }
1921#endif
1922 T *begin = &(*vec->begin());
1923 buf.ReadFastArray(begin, nvalues);
1924
1925 buf.CheckByteCount(start,count,config->fTypeName);
1926 return 0;
1927 }
1928
1930 {
1931 // Collection of numbers. Memberwise or not, it is all the same.
1932
1933 TConfigSTL *config = (TConfigSTL*)conf;
1934 UInt_t start, count;
1935 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1936
1937 std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1938 Int_t nvalues;
1939 buf.ReadInt(nvalues);
1940 vec->resize(nvalues);
1941
1942 bool *items = new bool[nvalues];
1943 buf.ReadFastArray(items, nvalues);
1944 for(Int_t i = 0 ; i < nvalues; ++i) {
1945 (*vec)[i] = items[i];
1946 }
1947 delete [] items;
1948
1949 // We could avoid the call to ReadFastArray, and we could
1950 // the following, however this breaks TBufferXML ...
1951 // for(Int_t i = 0 ; i < nvalues; ++i) {
1952 // bool tmp; buf >> tmp;
1953 // (*vec)[i] = tmp;
1954 // }
1955
1956 buf.CheckByteCount(start,count,config->fTypeName);
1957 return 0;
1958 }
1959
1961 {
1962 // Collection of numbers. Memberwise or not, it is all the same.
1963
1964 TConfigSTL *config = (TConfigSTL*)conf;
1965 UInt_t start, count;
1966 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1967
1968 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1969 Int_t nvalues;
1970 buf.ReadInt(nvalues);
1971 vec->resize(nvalues);
1972
1973#ifdef R__VISUAL_CPLUSPLUS
1974 if (nvalues <= 0) {
1975 buf.CheckByteCount(start,count,config->fTypeName);
1976 return 0;
1977 }
1978#endif
1979 float *begin = &(*vec->begin());
1980 buf.ReadFastArrayFloat16(begin, nvalues);
1981
1982 buf.CheckByteCount(start,count,config->fTypeName);
1983 return 0;
1984 }
1985
1987 {
1988 // Collection of numbers. Memberwise or not, it is all the same.
1989
1990 TConfigSTL *config = (TConfigSTL*)conf;
1991 UInt_t start, count;
1992 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1993
1994 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1995 Int_t nvalues;
1996 buf.ReadInt(nvalues);
1997 vec->resize(nvalues);
1998
1999#ifdef R__VISUAL_CPLUSPLUS
2000 if (nvalues <= 0) {
2001 buf.CheckByteCount(start,count,config->fTypeName);
2002 return 0;
2003 }
2004#endif
2005 double *begin = &(*vec->begin());
2006 buf.ReadFastArrayDouble32(begin, nvalues);
2007
2008 buf.CheckByteCount(start,count,config->fTypeName);
2009 return 0;
2010 }
2011
2012 template <typename From, typename To>
2014 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2015 {
2016 // Collection of numbers. Memberwise or not, it is all the same.
2017
2018 TConfigSTL *config = (TConfigSTL*)conf;
2019 UInt_t start, count;
2020 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2021
2022 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2023 Int_t nvalues;
2024 buf.ReadInt(nvalues);
2025 vec->resize(nvalues);
2026
2027 From *temp = new From[nvalues];
2028 buf.ReadFastArray(temp, nvalues);
2029 for(Int_t ind = 0; ind < nvalues; ++ind) {
2030 (*vec)[ind] = (To)temp[ind];
2031 }
2032 delete [] temp;
2033
2034 buf.CheckByteCount(start,count,config->fTypeName);
2035 return 0;
2036 }
2037 };
2038
2039 template <typename From, typename To>
2041 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2042 {
2043 // Collection of numbers. Memberwise or not, it is all the same.
2044
2045 TConfigSTL *config = (TConfigSTL*)conf;
2046 UInt_t start, count;
2047 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2048
2049 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2050 Int_t nvalues;
2051 buf.ReadInt(nvalues);
2052 vec->resize(nvalues);
2053
2054 From *temp = new From[nvalues];
2055 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2056 for(Int_t ind = 0; ind < nvalues; ++ind) {
2057 (*vec)[ind] = (To)temp[ind];
2058 }
2059 delete [] temp;
2060
2061 buf.CheckByteCount(start,count,config->fTypeName);
2062 return 0;
2063 }
2064 };
2065
2066 template <typename To>
2068 {
2069 // Collection of numbers. Memberwise or not, it is all the same.
2070
2071 TConfigSTL *config = (TConfigSTL*)conf;
2072 UInt_t start, count;
2073 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2074
2075 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2076 Int_t nvalues;
2077 buf.ReadInt(nvalues);
2078 vec->resize(nvalues);
2079
2080 Double32_t *temp = new Double32_t[nvalues];
2081 buf.ReadFastArrayDouble32(temp, nvalues);
2082 for(Int_t ind = 0; ind < nvalues; ++ind) {
2083 (*vec)[ind] = (To)temp[ind];
2084 }
2085 delete [] temp;
2086
2087 buf.CheckByteCount(start,count,config->fTypeName);
2088 return 0;
2089 }
2090
2091 };
2092
2094
2095 template <typename T>
2096 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2097 {
2098 const Int_t offset = config->fOffset;
2099
2100 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2101 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2102 buf >> *x;
2103 }
2104 return 0;
2105 }
2106
2107 template <typename From, typename To>
2109 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2110 {
2111 // Simple conversion from a 'From' on disk to a 'To' in memory.
2112 From temp;
2113 const Int_t offset = config->fOffset;
2114 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2115 buf >> temp;
2116 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2117 *x = (To)temp;
2118 }
2119 return 0;
2120 }
2121 };
2122
2123 template <typename To>
2125 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2126 {
2127 // Simple conversion from a 'From' on disk to a 'To' in memory.
2128 UInt_t temp;
2129 const Int_t offset = config->fOffset;
2130 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2131 buf >> temp;
2132
2133 if ((temp & kIsReferenced) != 0) {
2134 HandleReferencedTObject(buf,*(void**)iter,config);
2135 }
2136
2137 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2138 *x = (To)temp;
2139 }
2140 return 0;
2141 }
2142 };
2143
2144 template <typename From, typename To>
2146 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2147 {
2148 // Simple conversion from a 'From' on disk to a 'To' in memory.
2149 TConfWithFactor *conf = (TConfWithFactor *)config;
2150 From temp;
2151 const Int_t offset = config->fOffset;
2152 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2153 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2154 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2155 *x = (To)temp;
2156 }
2157 return 0;
2158 }
2159 };
2160
2161 template <typename From, typename To>
2163 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2164 {
2165 // Simple conversion from a 'From' on disk to a 'To' in memory.
2166 TConfNoFactor *conf = (TConfNoFactor *)config;
2167 From temp;
2168 const Int_t offset = config->fOffset;
2169 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2170 buf.ReadWithNbits(&temp, conf->fNbits);
2171 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2172 *x = (To)temp;
2173 }
2174 return 0;
2175 }
2176 };
2177
2178 template <typename T>
2179 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2180 {
2181 const Int_t offset = config->fOffset;
2182
2183 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2184 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2185 buf << *x;
2186 }
2187 return 0;
2188 }
2189
2190 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2191 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2192 {
2193 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2194 action(buf, *(void**)iter, config);
2195 }
2196 return 0;
2197 }
2198
2199 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2200 {
2201 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2202 // punt.
2203
2204 return GenericRead(buf,start,end,config);
2205 }
2206
2207 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2208 {
2209 Int_t n = ( ((void**)end) - ((void**)iter) );
2210 char **arr = (char**)iter;
2211 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2212 }
2213
2214 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2215 {
2216 Int_t n = ( ((void**)end) - ((void**)iter) );
2217 char **arr = (char**)iter;
2218 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2219 }
2220
2221 };
2222
2224
2225 template <typename T>
2226 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2227 {
2228 buf.ReadFastArray((T*)addr, nvalues);
2229 }
2230
2231 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2232 {
2233 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2234 }
2235
2236 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2237 {
2238 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2239 }
2240
2241 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2243 {
2244 // Collection of numbers. Memberwise or not, it is all the same.
2245
2246 TConfigSTL *config = (TConfigSTL*)conf;
2247 UInt_t start, count;
2248 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2249
2250 TClass *newClass = config->fNewClass;
2251 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2252 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2253
2254 Int_t nvalues;
2255 buf.ReadInt(nvalues);
2256 void* alternative = newProxy->Allocate(nvalues,true);
2257 if (nvalues) {
2260 void *begin = &(startbuf[0]);
2261 void *end = &(endbuf[0]);
2262 config->fCreateIterators(alternative, &begin, &end, newProxy);
2263 // We can not get here with a split vector of pointer, so we can indeed assume
2264 // that actions->fConfiguration != null.
2265
2266 action(buf,begin,nvalues);
2267
2268 if (begin != &(startbuf[0])) {
2269 // assert(end != endbuf);
2270 config->fDeleteTwoIterators(begin,end);
2271 }
2272 }
2273 newProxy->Commit(alternative);
2274
2275 buf.CheckByteCount(start,count,config->fTypeName);
2276 return 0;
2277 }
2278
2280 {
2281 return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2282 }
2283
2285 {
2286 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2287 }
2288
2290 {
2291 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2292 }
2293
2294 template <typename T>
2296 {
2297 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2298 }
2299
2300 template <typename From, typename To>
2302 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2303 {
2304 From *temp = new From[nvalues];
2305 buf.ReadFastArray(temp, nvalues);
2306 To *vec = (To*)addr;
2307 for(Int_t ind = 0; ind < nvalues; ++ind) {
2308 vec[ind] = (To)temp[ind];
2309 }
2310 delete [] temp;
2311 }
2312 };
2313
2314 template <typename From, typename To>
2315 struct ConvertRead<NoFactorMarker<From>,To> {
2316 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2317 {
2318 From *temp = new From[nvalues];
2319 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2320 To *vec = (To*)addr;
2321 for(Int_t ind = 0; ind < nvalues; ++ind) {
2322 vec[ind] = (To)temp[ind];
2323 }
2324 delete [] temp;
2325 }
2326 };
2327
2328 template <typename From, typename To>
2330 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2331 {
2332 From *temp = new From[nvalues];
2333 double factor,min; // needs to be initialized.
2334 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2335 To *vec = (To*)addr;
2336 for(Int_t ind = 0; ind < nvalues; ++ind) {
2337 vec[ind] = (To)temp[ind];
2338 }
2339 delete [] temp;
2340 }
2341 };
2342
2343 template <typename From, typename To>
2345 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2346 {
2347 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2348 }
2349 };
2350
2351 };
2352
2354
2355 template <typename T>
2356 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2357 {
2358 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2359
2360 Next_t next = loopconfig->fNext;
2361 const Int_t offset = config->fOffset;
2362
2364 void *iter = loopconfig->fCopyIterator(iterator,start);
2365 void *addr;
2366 while( (addr = next(iter,end)) ) {
2367 T *x = (T*)( ((char*)addr) + offset );
2368 buf >> *x;
2369 }
2370 if (iter != &iterator[0]) {
2371 loopconfig->fDeleteIterator(iter);
2372 }
2373 return 0;
2374 }
2375
2376 template <typename T>
2377 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2378 {
2379 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2380
2381 Next_t next = loopconfig->fNext;
2382 const Int_t offset = config->fOffset;
2383
2385 void *iter = loopconfig->fCopyIterator(iterator,start);
2386 void *addr;
2387 while( (addr = next(iter,end)) ) {
2388 T *x = (T*)( ((char*)addr) + offset );
2389 buf << *x;
2390 }
2391 if (iter != &iterator[0]) {
2392 loopconfig->fDeleteIterator(iter);
2393 }
2394 return 0;
2395 }
2396
2397 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2398 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2399 {
2400 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2401
2402 // const Int_t offset = config->fOffset;
2403 Next_t next = loopconfig->fNext;
2404
2406 void *iter = loopconfig->fCopyIterator(&iterator,start);
2407 void *addr;
2408 while( (addr = next(iter,end)) ) {
2409 iter_action(buf, addr, config);
2410 }
2411 if (iter != &iterator[0]) {
2412 loopconfig->fDeleteIterator(iter);
2413 }
2414 return 0;
2415 }
2416
2417 template <typename From, typename To>
2418 struct Generic {
2419 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2420 {
2421 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2422
2423 const Int_t offset = config->fOffset;
2424 Next_t next = loopconfig->fNext;
2425
2427 void *iter = loopconfig->fCopyIterator(&iterator,start);
2428 void *addr;
2429 while( (addr = next(iter,end)) ) {
2430 To *x = (To*)( ((char*)addr) + offset );
2431 *x = (To)(*items);
2432 ++items;
2433 }
2434 if (iter != &iterator[0]) {
2435 loopconfig->fDeleteIterator(iter);
2436 }
2437 }
2438 };
2439
2440 template <typename From, typename To>
2441 struct Numeric {
2442 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2443 {
2444 // The difference with ConvertAction is that we can modify the start
2445 // iterator and skip the copy. We also never have an offset.
2446
2447 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2448 Next_t next = loopconfig->fNext;
2449
2450 void *iter = start;
2451 void *addr;
2452 while( (addr = next(iter,end)) ) {
2453 To *x = (To*)(addr);
2454 *x = (To)(*items);
2455 ++items;
2456 }
2457 }
2458 };
2459
2460 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2462 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2463 {
2464 // Simple conversion from a 'From' on disk to a 'To' in memory.
2465
2466 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2467 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2468 Int_t nvalues = proxy->Size();
2469
2470 From *items = new From[nvalues];
2471 buf.ReadFastArray(items, nvalues);
2472 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2473 delete [] items;
2474 return 0;
2475 }
2476 };
2477
2478 template <typename To>
2480 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2481 {
2482 // Simple conversion from a 'From' on disk to a 'To' in memory.
2483
2484 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2485 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2486 Int_t nvalues = proxy->Size();
2487
2488 UInt_t *items_storage = new UInt_t[nvalues];
2489 UInt_t *items = items_storage;
2490
2491 const Int_t offset = config->fOffset;
2492 Next_t next = loopconfig->fNext;
2493
2495 void *iter = loopconfig->fCopyIterator(&iterator,start);
2496 void *addr;
2497 while( (addr = next(iter,end)) ) {
2498 buf >> (*items);
2499 if (((*items) & kIsReferenced) != 0) {
2500 HandleReferencedTObject(buf, addr, config);
2501 }
2502 To *x = (To*)( ((char*)addr) + offset );
2503 *x = (To)(*items);
2504 ++items;
2505 }
2506 if (iter != &iterator[0]) {
2507 loopconfig->fDeleteIterator(iter);
2508 }
2509
2510 delete [] items_storage;
2511 return 0;
2512 }
2513 };
2514
2515 template <typename From, typename To, template <typename F, typename T> class Converter >
2516 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2517 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2518 {
2519 // Simple conversion from a 'From' on disk to a 'To' in memory.
2520
2521 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2522 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2523 Int_t nvalues = proxy->Size();
2524
2525 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2526
2527 From *items = new From[nvalues];
2528 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2529 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2530 delete [] items;
2531 return 0;
2532 }
2533 };
2534
2535 template <typename From, typename To, template <typename F, typename T> class Converter >
2536 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2537 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2538 {
2539 // Simple conversion from a 'From' on disk to a 'To' in memory.
2540
2541 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2542 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2543 Int_t nvalues = proxy->Size();
2544
2545 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2546
2547 From *items = new From[nvalues];
2548 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2549 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2550 delete [] items;
2551 return 0;
2552 }
2553 };
2554
2555 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2556 {
2557 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2558 // punt.
2559
2560 return GenericRead(buf,start,end,loopconfig, config);
2561 }
2562
2563 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2564 {
2565 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2566 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2567 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2568 }
2569
2570 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2571 {
2572 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2573 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2574 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2575 }
2576
2577 template <typename T>
2578 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2579 {
2580 buf >> *(T*)addr;
2581 }
2582
2583 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2584 {
2585 buf.ReadWithNbits((float*)addr,12);
2586 }
2587
2589 {
2590 //we read a float and convert it to double
2591 Float_t afloat;
2592 buf >> afloat;
2593 *(double*)addr = (Double_t)afloat;
2594 }
2595
2596 template <typename ActionHolder>
2598 {
2599 // Collection of numbers. Memberwise or not, it is all the same.
2600
2601 TConfigSTL *config = (TConfigSTL*)conf;
2602 UInt_t start, count;
2603 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2604
2605 TClass *newClass = config->fNewClass;
2606 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2607 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2608
2609 Int_t nvalues;
2610 buf.ReadInt(nvalues);
2611 void* alternative = newProxy->Allocate(nvalues,true);
2612 if (nvalues) {
2615 void *begin = &(startbuf[0]);
2616 void *end = &(endbuf[0]);
2617 config->fCreateIterators(alternative, &begin, &end, newProxy);
2618 // We can not get here with a split vector of pointer, so we can indeed assume
2619 // that actions->fConfiguration != null.
2620
2621 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2622 ActionHolder::Action(buf,begin,end,&loopconf,config);
2623
2624 if (begin != &(startbuf[0])) {
2625 // assert(end != endbuf);
2626 config->fDeleteTwoIterators(begin,end);
2627 }
2628 }
2629 newProxy->Commit(alternative);
2630
2631 buf.CheckByteCount(start,count,config->fTypeName);
2632 return 0;
2633 }
2634
2636 {
2637 return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2638 }
2639
2641 {
2642 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2643 }
2644
2646 {
2647 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2648 // Could also use:
2649 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2650 }
2651
2652 template <typename T>
2654 {
2655 //TODO: Check whether we can implement this without loading the data in
2656 // a temporary variable and whether this is noticeably faster.
2657 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2658 }
2659
2660 template <typename From, typename To>
2662 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2663 {
2664 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2665 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2666 }
2667 };
2668
2669 };
2670}
2671
2672template <typename Looper, typename From>
2674{
2675 switch (newtype) {
2676 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2677 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2678 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2679 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2680 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2681 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2682 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2683 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2684 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2685 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2686 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2687 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2688 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2689 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2690 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2691 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2692 default:
2693 return TConfiguredAction( Looper::GenericRead, conf );
2694 break;
2695 }
2696 R__ASSERT(0); // We should never be here
2697 return TConfiguredAction();
2698}
2699
2700template <class Looper>
2702{
2703 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2704
2705 switch (type) {
2706 // Read basic types.
2707 case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2708 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2709 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2710 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2711 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2712 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2713 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2714 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2715 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2716 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2717 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2718 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2719 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2720 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2722 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2723 delete conf;
2724 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2725 // if (element->GetFactor() != 0) {
2726 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2727 // } else {
2728 // Int_t nbits = (Int_t)element->GetXmin();
2729 // if (!nbits) nbits = 12;
2730 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2731 // }
2732 break;
2733 }
2735 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2736 delete conf;
2737 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2738 // if (element->GetFactor() != 0) {
2739 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2740 // } else {
2741 // Int_t nbits = (Int_t)element->GetXmin();
2742 // if (!nbits) {
2743 // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2744 // } else {
2745 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2746 // }
2747 // }
2748 break;
2749 }
2750 }
2751 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2752 R__ASSERT(0); // We should never be here
2753 return TConfiguredAction();
2754}
2755
2756template <typename Looper, typename From>
2758{
2759 switch (newtype) {
2760 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2761 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2762 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2763 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2764 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2765 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2766 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2767 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2768 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2769 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2770 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2771 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2772 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2773 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2774 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2775 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2776 default:
2777 break;
2778 }
2779 Error("GetConvertCollectionReadActionFrom", "UNEXPECTED: newtype == %d", newtype);
2780 R__ASSERT(0); // We should never be here
2781 return TConfiguredAction();
2782}
2783
2784template <typename Looper>
2786{
2787 switch (oldtype) {
2789 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2790 break;
2792 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2793 break;
2795 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2796 break;
2798 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2799 break;
2801 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2802 break;
2804 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2805 break;
2807 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2808 break;
2810 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2811 break;
2813 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2814 break;
2816 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2817 break;
2819 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2820 break;
2822 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2823 break;
2825 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2826 break;
2828 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2829 break;
2831 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2832 break;
2834 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2835 break;
2836 default:
2837 break;
2838 }
2839 Error("GetConvertCollectionReadAction", "UNEXPECTED: oldtype == %d", oldtype);
2840 R__ASSERT(0); // We should never be here
2841 return TConfiguredAction();
2842}
2843
2844template <class Looper>
2846{
2847 switch (type) {
2848 // Read basic types.
2849 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2850 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2851 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2852 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2853 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2854 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2855 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2856 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2857 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2858 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2859 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2860 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2861 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2862 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2864 if (element->GetFactor() != 0) {
2865 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2866 } else {
2867 Int_t nbits = (Int_t)element->GetXmin();
2868 if (!nbits) nbits = 12;
2869 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2870 }
2871 break;
2872 }
2874 if (element->GetFactor() != 0) {
2875 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2876 } else {
2877 Int_t nbits = (Int_t)element->GetXmin();
2878 if (!nbits) {
2879 return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2880 } else {
2881 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2882 }
2883 }
2884 break;
2885 }
2886 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2887 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2888 // Streamer alltogether.
2889 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2890 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2894 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2895 case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2896
2897 // Conversions.
2899 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2900 break;
2902 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2903 break;
2905 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2906 break;
2908 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2909 break;
2911 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2912 break;
2914 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2915 break;
2917 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2918 break;
2920 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2921 break;
2923 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2924 break;
2926 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2927 break;
2929 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2930 break;
2932 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2933 break;
2935 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2936 break;
2938 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2939 break;
2941 if (element->GetFactor() != 0) {
2942 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2943 } else {
2944 Int_t nbits = (Int_t)element->GetXmin();
2945 if (!nbits) nbits = 12;
2946 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2947 }
2948 break;
2949 }
2951 if (element->GetFactor() != 0) {
2952 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2953 } else {
2954 Int_t nbits = (Int_t)element->GetXmin();
2955 if (!nbits) {
2956 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2957 } else {
2958 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2959 }
2960 }
2961 break;
2962 }
2963 default:
2964 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2965 break;
2966 }
2967 R__ASSERT(0); // We should never be here
2968 return TConfiguredAction();
2969}
2970
2971template <class Looper>
2973 switch (type) {
2974 // read basic types
2975 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2976 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2977 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2978 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2979 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2980 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2981 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2982 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2983 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2984 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2985 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2986 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2987 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2988 // the simple type missing are kBits and kCounter.
2989 default:
2990 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2991 }
2992 R__ASSERT(0); // We should never be here
2993 return TConfiguredAction();
2994}
2995
2996
2997////////////////////////////////////////////////////////////////////////////////
2998/// loop on the TStreamerElement list
2999/// regroup members with same type
3000/// Store predigested information into local arrays. This saves a huge amount
3001/// of time compared to an explicit iteration on all elements.
3002
3004{
3005 if (IsCompiled()) {
3006 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
3007 return;
3008 }
3010
3011 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
3012
3013 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
3015 fNdata = 0;
3016 fNfulldata = 0;
3017
3018 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
3019 if (fNumber < 0) {
3020 ++fgCount;
3021 fNumber = fgCount;
3022 }
3023 if (fNumber >= infos->GetSize()) {
3024 infos->AddAtAndExpand(this, fNumber);
3025 } else {
3026 if (!infos->At(fNumber)) {
3027 infos->AddAt(this, fNumber);
3028 }
3029 }
3030
3031 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3032
3033
3034 Int_t ndata = fElements->GetEntriesFast();
3035
3036
3039
3042
3045
3046 if (fReadText) fReadText->fActions.clear();
3047 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3048
3051
3054
3057
3058 if (fWriteText) fWriteText->fActions.clear();
3060
3061 if (!ndata) {
3062 // This may be the case for empty classes (e.g., TAtt3D).
3063 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3065 fSize = sizeof(TStreamerInfo*);
3066 }
3067 fComp = new TCompInfo[1];
3068 fCompFull = new TCompInfo*[1];
3069 fCompOpt = new TCompInfo*[1];
3070 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3071 SetIsCompiled();
3072 return;
3073 }
3074
3075 // At most half of the elements can be used to hold optimized versions.
3076 // We use the bottom to hold the optimized-into elements and the non-optimized elements
3077 // and the top to hold the original copy of the optimized out elements.
3078 fNslots = ndata + ndata/2 + 1;
3079 Int_t optiOut = 0;
3080
3081 fComp = new TCompInfo[fNslots];
3082 fCompFull = new TCompInfo*[ndata];
3083 fCompOpt = new TCompInfo*[ndata];
3084
3085 TStreamerElement* element;
3086 TStreamerElement* previous = 0;
3087 Int_t keep = -1;
3088 Int_t i;
3089
3090 if (!CanOptimize()) {
3092 }
3093
3094 Bool_t isOptimized = kFALSE;
3095 Bool_t previousOptimized = kFALSE;
3096
3097 for (i = 0; i < ndata; ++i) {
3098 element = (TStreamerElement*) fElements->At(i);
3099 if (!element) {
3100 break;
3101 }
3102
3103 Int_t asize = element->GetSize();
3104 if (element->GetArrayLength()) {
3105 asize /= element->GetArrayLength();
3106 }
3107 fComp[fNdata].fType = element->GetType();
3108 fComp[fNdata].fNewType = element->GetNewType();
3109 fComp[fNdata].fOffset = element->GetOffset();
3110 fComp[fNdata].fLength = element->GetArrayLength();
3111 fComp[fNdata].fElem = element;
3112 fComp[fNdata].fMethod = element->GetMethod();
3113 fComp[fNdata].fClass = element->GetClassPointer();
3114 fComp[fNdata].fNewClass = element->GetNewClass();
3116 fComp[fNdata].fStreamer = element->GetStreamer();
3117
3118 // try to group consecutive members of the same type
3120 && (keep >= 0)
3121 && (element->GetType() > 0)
3122 && (element->GetType() < 10)
3124 && (fComp[keep].fMethod == 0)
3125 && (element->GetArrayDim() == 0)
3126 && (fComp[keep].fType < kObject)
3127 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3128 && (element->GetType() == (fComp[keep].fType%kRegrouped))
3129 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3130 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3131 ((element->GetFactor() == previous->GetFactor())
3132 && (element->GetXmin() == previous->GetXmin())
3133 && (element->GetXmax() == previous->GetXmax())
3134 )
3135 )
3138 // kWholeObject and kDoNotDelete do not apply to numerical elements.
3139 )
3140 {
3141 if (!previousOptimized) {
3142 // The element was not yet optimized we first need to copy it into
3143 // the set of original copies.
3144 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3145 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3146 }
3147 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3148 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3149
3150 R__ASSERT( keep < (fNslots - optiOut) );
3151
3152 if (fComp[keep].fLength == 0) {
3153 fComp[keep].fLength++;
3154 }
3155 fComp[keep].fLength++;
3156 fComp[keep].fType = element->GetType() + kRegrouped;
3157 isOptimized = kTRUE;
3158 previousOptimized = kTRUE;
3159 } else if (element->GetType() < 0) {
3160
3161 // -- Deal with an ignored TObject base class.
3162 // Note: The only allowed negative value here is -1,
3163 // and signifies that Build() has found a TObject
3164 // base class and TClass::IgnoreTObjectStreamer() was
3165 // called. In this case the compiled version of the
3166 // elements omits the TObject base class element,
3167 // which has to be compensated for by TTree::Bronch()
3168 // when it is making branches for a split object.
3169 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3170 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3171 keep = -1;
3172 previousOptimized = kFALSE;
3173
3174 } else {
3175 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3176 if (fComp[fNdata].fNewType > 0) {
3177 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3178 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3179 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3183 ) {
3185 } else if (fComp[fNdata].fType != kCounter) {
3186 fComp[fNdata].fType += kConv;
3187 }
3188 } else {
3189 if (fComp[fNdata].fType == kCounter) {
3190 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3191 }
3192 fComp[fNdata].fType += kSkip;
3193 }
3194 }
3195 fCompOpt[fNdata] = &(fComp[fNdata]);
3197
3198 R__ASSERT( fNdata < (fNslots - optiOut) );
3199
3200 keep = fNdata;
3201 if (fComp[keep].fLength == 0) {
3202 fComp[keep].fLength = 1;
3203 }
3204 fNdata++;
3205 previousOptimized = kFALSE;
3206 }
3207 // The test 'fMethod[keep] == 0' fails to detect a variable size array
3208 // if the counter happens to have an offset of zero, so let's explicitly
3209 // prevent for here.
3210 if (element->HasCounter()) keep = -1;
3211 ++fNfulldata;
3212 previous = element;
3213 }
3214
3215 for (i = 0; i < fNdata; ++i) {
3216 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3217 continue;
3218 }
3221 }
3222 for (i = 0; i < fNfulldata; ++i) {
3223 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3224 continue;
3225 }
3230
3233 }
3234 ComputeSize();
3235
3236 fOptimized = isOptimized;
3237 SetIsCompiled();
3238
3239 if (gDebug > 0) {
3240 ls();
3241 }
3242}
3243
3244template <typename From>
3246{
3247 switch (newtype) {
3264 }
3265}
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Add a read action for the given element.
3269
3271{
3272 TStreamerElement *element = compinfo->fElem;
3273
3274 if (element->TestBit(TStreamerElement::kWrite)) return;
3275
3276 switch (compinfo->fType) {
3277 // read basic types
3278 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3279 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3280 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3281 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3282 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3283 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3284 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3285 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3286 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3287 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3288 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3289 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3290 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3291 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3293 if (element->GetFactor() != 0) {
3294 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3295 } else {
3296 Int_t nbits = (Int_t)element->GetXmin();
3297 if (!nbits) nbits = 12;
3298 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3299 }
3300 break;
3301 }
3303 if (element->GetFactor() != 0) {
3304 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3305 } else {
3306 Int_t nbits = (Int_t)element->GetXmin();
3307 if (!nbits) {
3308 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3309 } else {
3310 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3311 }
3312 }
3313 break;
3314 }
3315 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3316 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3317 // Streamer alltogether.
3318 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3319 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3320 case TStreamerInfo::kSTL: {
3321 TClass *newClass = element->GetNewClass();
3322 TClass *oldClass = element->GetClassPointer();
3323 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3324
3325 if (element->GetArrayLength() <= 1) {
3326 if (fOldVersion<3){ // case of old TStreamerInfo
3327 if (newClass && newClass != oldClass) {
3328 if (element->GetStreamer()) {
3329 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3330 } else {
3331 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3332 }
3333 } else {
3334 if (element->GetStreamer()) {
3335 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3336 } else {
3337 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3338 }
3339 }
3340 } else {
3341 if (newClass && newClass != oldClass) {
3342 if (element->GetStreamer()) {
3343 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3344 } else {
3345 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3346 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3347 } else {
3348 switch (SelectLooper(*newClass->GetCollectionProxy())) {
3349 case kVectorLooper:
3350 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3351 break;
3352 case kAssociativeLooper:
3353 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3354 break;
3355 case kVectorPtrLooper:
3356 case kGenericLooper:
3357 default:
3358 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3359 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3360 break;
3361 }
3362 }
3363 }
3364 } else {
3365 if (element->GetStreamer()) {
3366 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3367 } else {
3368 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3369 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3370 } else {
3371 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3372 case kVectorLooper:
3373 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3374 break;
3375 case kAssociativeLooper:
3376 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3377 break;
3378 case kVectorPtrLooper:
3379 case kGenericLooper:
3380 default:
3381 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3382 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3383 break;
3384 }
3385 }
3386 }
3387 }
3388 }
3389 } else {
3390 if (fOldVersion<3){ // case of old TStreamerInfo
3391 if (newClass && newClass != oldClass) {
3392 if (element->GetStreamer()) {
3393 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3394 } else {
3395 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3396 }
3397 } else {
3398 if (element->GetStreamer()) {
3399 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3400 } else {
3401 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3402 }
3403 }
3404 } else {
3405 if (newClass && newClass != oldClass) {
3406 if (element->GetStreamer()) {
3407 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3408 } else {
3409 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3410 }
3411 } else {
3412 if (element->GetStreamer()) {
3413 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3414 } else {
3415 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3416 }
3417 }
3418 }
3419 }
3420 break;
3421 }
3422
3424 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3425 break;
3427 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3428 break;
3430 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3431 break;
3433 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3434 break;
3436 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3437 break;
3439 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3440 break;
3442 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3443 break;
3445 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3446 break;
3448 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3449 break;
3451 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3452 break;
3454 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3455 break;
3457 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3458 break;
3460 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3461 break;
3463 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3464 break;
3466 if (element->GetFactor() != 0) {
3467 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3468 } else {
3469 Int_t nbits = (Int_t)element->GetXmin();
3470 if (!nbits) nbits = 12;
3471 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3472 }
3473 break;
3474 }
3476 if (element->GetFactor() != 0) {
3477 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3478 } else {
3479 Int_t nbits = (Int_t)element->GetXmin();
3480 if (!nbits) {
3481 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3482 } else {
3483 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3484 }
3485 }
3486 break;
3487 }
3488 default:
3489 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3490 break;
3491 }
3492 if (element->TestBit(TStreamerElement::kCache)) {
3493 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3494 readSequence->fActions.pop_back();
3495 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3496 }
3497}
3498
3499////////////////////////////////////////////////////////////////////////////////
3500/// Add a read text action for the given element.
3501
3503{
3504 TStreamerElement *element = compinfo->fElem;
3505
3506 if (element->TestBit(TStreamerElement::kWrite))
3507 return;
3508
3509 Bool_t generic = kFALSE, isBase = kFALSE;
3510
3511 switch (compinfo->fType) {
3513 if (element->IsBase())
3514 isBase = kTRUE;
3515 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3516 else
3517 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3518 break;
3519
3521 if (element->IsBase())
3522 isBase = kTRUE;
3523 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3524 else
3525 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3526 break;
3527
3528 case TStreamerInfo::kObject: // Class derived from TObject
3529 case TStreamerInfo::kAny: // Class NOT derived from TObject
3532 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3533 break;
3534
3535 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3537 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3538 readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3539 break;
3540
3543 readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3544 break;
3545
3546 case TStreamerInfo::kBase: isBase = kTRUE; break;
3547
3549 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3550 break;
3551
3552 default: generic = kTRUE; break;
3553 }
3554
3555 if (isBase) {
3556 if (compinfo->fStreamer) {
3557 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3558 } else {
3559 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3560 }
3561 } else if (generic)
3562 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3563}
3564
3565////////////////////////////////////////////////////////////////////////////////
3566/// Add a read action for the given element.
3567/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3568
3570{
3571 TStreamerElement *element = compinfo->fElem;
3572
3573 if (element->TestBit(TStreamerElement::kWrite)) return;
3574
3575 if (element->TestBit(TStreamerElement::kCache)) {
3576 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3577 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3578 } else {
3579 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3580 }
3581}
3582
3583////////////////////////////////////////////////////////////////////////////////
3584
3586{
3587 TStreamerElement *element = compinfo->fElem;
3589 // Skip element cached for reading purposes.
3590 return;
3591 }
3592 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3593 // Skip artificial element used for reading purposes.
3594 return;
3595 }
3596 switch (compinfo->fType) {
3597 // write basic types
3598 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3599 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3600 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3601 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3602 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3603 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3604 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3605 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3606 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3607 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3608 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3609 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3610 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3611 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3612 /*case TStreamerInfo::kFloat16: {
3613 if (element->GetFactor() != 0) {
3614 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3615 } else {
3616 Int_t nbits = (Int_t)element->GetXmin();
3617 if (!nbits) nbits = 12;
3618 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3619 }
3620 break;
3621 } */
3622 /*case TStreamerInfo::kDouble32: {
3623 if (element->GetFactor() != 0) {
3624 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3625 } else {
3626 Int_t nbits = (Int_t)element->GetXmin();
3627 if (!nbits) {
3628 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3629 } else {
3630 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3631 }
3632 }
3633 break;
3634 } */
3635 //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3636 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3637 // Streamer alltogether.
3638 //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3639 //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3640 /*case TStreamerInfo::kSTL: {
3641 TClass *newClass = element->GetNewClass();
3642 TClass *oldClass = element->GetClassPointer();
3643 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3644
3645 if (element->GetArrayLength() <= 1) {
3646 if (newClass && newClass != oldClass) {
3647 if (element->GetStreamer()) {
3648 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3649 } else {
3650 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3651 }
3652 } else {
3653 if (element->GetStreamer()) {
3654 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3655 } else {
3656 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3657 }
3658 }
3659 } else {
3660 if (newClass && newClass != oldClass) {
3661 if (element->GetStreamer()) {
3662 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3663 } else {
3664 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3665 }
3666 } else {
3667 if (element->GetStreamer()) {
3668 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3669 } else {
3670 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3671 }
3672 }
3673 }
3674 break;
3675 } */
3676 default:
3677 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3678 break;
3679 }
3680#if defined(CDJ_NO_COMPILE)
3681 if (element->TestBit(TStreamerElement::kCache)) {
3682 TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3683 writeSequence->fActions.pop_back();
3684 writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3685 }
3686#endif
3687}
3688
3689////////////////////////////////////////////////////////////////////////////////
3690
3692{
3693 TStreamerElement *element = compinfo->fElem;
3695 // Skip element cached for reading purposes.
3696 return;
3697 }
3698 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3699 // Skip artificial element used for reading purposes.
3700 return;
3701 }
3702
3703 Bool_t generic = kFALSE, isBase = kFALSE;
3704
3705 switch (compinfo->fType) {
3706 // write basic types
3708 writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3709 break;
3711 writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3712 break;
3714 writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3715 break;
3717 writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3718 break;
3720 writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3721 break;
3723 writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3724 break;
3726 writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3727 break;
3729 writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3730 break;
3732 writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3733 break;
3735 writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3736 break;
3738 writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3739 break;
3741 writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3742 break;