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)\n",
107 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
108 aElement->ClassName(), fOffset, sequenceType.Data());
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:
141 TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset) {};
142 void PrintDebug(TBuffer &, void *) const {
143 // Since we call the old code, it will print the debug statement.
144 }
145
146 virtual TConfiguration *Copy() { 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
157 TBitsConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset),fObjectOffset(0) {};
158 void PrintDebug(TBuffer &, void *) const {
160 TStreamerElement *aElement = fCompInfo->fElem;
161 TString sequenceType;
162 aElement->GetSequenceType(sequenceType);
163
164 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
165 " %s, offset=%d (%s)\n",
166 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
167 aElement->ClassName(), fOffset, sequenceType.Data());
168 }
169
170 void AddToOffset(Int_t delta)
171 {
172 // Add the (potentially negative) delta to all the configuration's offset. This is used by
173 // TBranchElement in the case of split sub-object.
174
176 fOffset += delta;
177 fObjectOffset = 0;
178 }
179
181 {
183 fObjectOffset = 0;
184 }
185
186 virtual TConfiguration *Copy() { return new TBitsConfiguration(*this); }
187
188 };
189
190 Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
191 {
192 char *obj = (char*)addr;
194 return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
195 }
196
197 Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
198 {
199 char *obj = (char*)addr;
201 return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
202 }
203
204 template <typename T>
206 {
207 T *x = (T*)( ((char*)addr) + config->fOffset );
208 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
209 buf >> *x;
210 return 0;
211 }
212
213 void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
214 TBitsConfiguration *conf = (TBitsConfiguration*)config;
215 UShort_t pidf;
216 buf >> pidf;
217 pidf += buf.GetPidOffset();
218 TProcessID *pid = buf.ReadProcessID(pidf);
219 if (pid!=0) {
220 TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
221 UInt_t gpid = pid->GetUniqueID();
222 UInt_t uid;
223 if (gpid>=0xff) {
224 uid = obj->GetUniqueID() | 0xff000000;
225 } else {
226 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
227 }
228 obj->SetUniqueID(uid);
229 pid->PutObjectWithID(obj);
230 }
231 }
232
233 template <>
235 {
236 UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
237 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
238 // Idea: This code really belongs inside TBuffer[File]
239 buf >> *x;
240
241 if ((*x & kIsReferenced) != 0) {
242 HandleReferencedTObject(buf,addr,config);
243 }
244 return 0;
245 }
246
247 template <typename T>
249 {
250 T *x = (T *)(((char *)addr) + config->fOffset);
251 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
252 buf << *x;
253 return 0;
254 }
255
257 {
258 void *x = (void *)(((char *)addr) + config->fOffset);
259 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
261 return 0;
262 }
263
265 {
266 void *x = (void *)(((char *)addr) + config->fOffset);
267 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
269 return 0;
270 }
271
273 {
274 void *x = (void *)(((char *)addr) + config->fOffset);
275 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
276 ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
277 return 0;
278 }
279
281 {
282 void *x = (void *)(((char *)addr) + config->fOffset);
283 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
284 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
285 (*pstreamer)(buf, x, config->fCompInfo->fLength);
286 buf.SetByteCount(pos, kTRUE);
287 return 0;
288 }
289
291 {
292 void *x = (void *)(((char *)addr) + config->fOffset);
293 buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
294 return 0;
295 }
296
298 {
299 void *x = (void *)(((char *)addr) + config->fOffset);
301 return 0;
302 }
303
305 {
306 void *x = (void *)(((char *)addr) + config->fOffset);
307 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
308 ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
309 return 0;
310 }
311
313 {
314 void *x = (void *)(((char *)addr) + config->fOffset);
315 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
316
317 UInt_t start, count;
318 /* Version_t v = */ buf.ReadVersion(&start, &count, config->fCompInfo->fClass);
319 (*pstreamer)(buf, x, config->fCompInfo->fLength);
320 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
321 return 0;
322 }
323
325 {
326 // action required to call custom code for TObject as base class
327 void *x = (void *)(((char *)addr) + config->fOffset);
329 return 0;
330 }
331
333 {
334 void *x = (void *)(((char *)addr) + config->fOffset);
336 return 0;
337 }
338
339 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
340 * potentially can be used later for non-text streaming */
341 template<bool kIsTextT>
343 {
344 TClass *cl = config->fCompInfo->fClass;
345 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
347 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
348 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
349 UInt_t ioffset = eoffset + config->fOffset;
350
352 && proxy && vClass
353 && config->fInfo->GetStreamMemberWise()
354 && cl->CanSplit()
355 && !(strspn(config->fCompInfo->fElem->GetTitle(),"||") == 2)
357 // Let's save the collection member-wise.
358
359 UInt_t pos = buf.WriteVersionMemberWise(config->fInfo->IsA(),kTRUE);
360 buf.WriteVersion( vClass, kFALSE );
361
362 // TODO: subinfo used for WriteBufferSTL call, which is private for the moment
363 //TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
364
365 //for (int k = 0; k < narr; ++k) {
366 char **contp = (char **)((char *)addr + ioffset);
367 for(int j=0;j<config->fCompInfo->fLength;++j) {
368 char *cont = contp[j];
369 TVirtualCollectionProxy::TPushPop helper( proxy, cont );
370 Int_t nobjects = cont ? proxy->Size() : 0;
371 buf << nobjects;
372
373 // TODO: method is private, should be made accesible from here
374 // subinfo->WriteBufferSTL(buf,proxy,nobjects);
375 }
376 //}
377 buf.SetByteCount(pos,kTRUE);
378 return 0;
379 }
380 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
381 if (kIsTextT) {
382 // use same method which is used in kSTL
383 buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
384 } else if (pstreamer == nullptr) {
385 // for (int k = 0; k < narr; ++k) {
386 char **contp = (char **)((char *)addr + ioffset);
387 for (int j = 0; j < config->fCompInfo->fLength; ++j) {
388 char *cont = contp[j];
389 cl->Streamer(cont, buf);
390 }
391 // }
392 } else {
393 // for (int k = 0; k < narr; ++k) {
394 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
395 //}
396 }
397 buf.SetByteCount(pos, kTRUE);
398 return 0;
399 }
400
401
402 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
403 * potentially can be used later for non-text streaming */
404 template<bool kIsTextT>
406 {
407 TClass *cle = config->fCompInfo->fClass;
408 TStreamerElement * aElement = (TStreamerElement*) config->fCompInfo->fElem;
409 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
410 //TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
411 //TClass* vClass = proxy ? proxy->GetValueClass() : 0;
412
413 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
414 UInt_t ioffset = eoffset + config->fOffset;
415
416
417 UInt_t start,count;
418 Version_t vers = buf.ReadVersion(&start, &count, cle);
419
420 if (!kIsTextT && (vers & TBufferFile::kStreamedMemberWise) ) {
421 // Collection was saved member-wise
422
424
425 TClass *newClass = aElement->GetNewClass();
426 TClass *oldClass = aElement->GetClassPointer();
427 if( vers < 9 && newClass && newClass!=oldClass ) {
428 Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
429 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
430 return 0;
431 }
432
433 Version_t vClVersion = 0; // For vers less than 9, we have to use the current version.
434 if( vers >= 9 ) {
435 vClVersion = buf.ReadVersionForMemberWise( cle->GetCollectionProxy()->GetValueClass() );
436 }
437
438 TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : nullptr);
439 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
440 TStreamerInfo *subinfo = nullptr;
441
442 if( newProxy ) {
443 // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
444 subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
445 } else {
446 subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( vClVersion );
447 newProxy = oldProxy;
448 }
449 if (subinfo) {
450 // DOLOOP {
451 void* env;
452 void **contp = (void**)((char *) addr + ioffset);
453 for(int j=0;j<config->fCompInfo->fLength;j++) {
454 void *cont = contp[j];
455 if (cont==nullptr) {
456 contp[j] = cle->New();
457 cont = contp[j];
458 }
459 TVirtualCollectionProxy::TPushPop helper( newProxy, cont );
460 Int_t nobjects;
461 buf >> nobjects;
462 env = newProxy->Allocate(nobjects,true);
463 subinfo->ReadBufferSTL(buf,newProxy,nobjects,/* offset */ 0, vers>=7 );
464 newProxy->Commit(env);
465 }
466 // } // DOLOOP
467 }
468 buf.CheckByteCount(start,count,aElement->GetFullName());
469 return 0;
470 }
471
472 if (kIsTextT) {
473 // use same method which is used in kSTL
474 buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
475 } else if (pstreamer == nullptr) {
476 // DOLOOP {
477 void **contp = (void **)((char *)addr + ioffset);
478 for (int j = 0; j < config->fCompInfo->fLength; j++) {
479 void *cont = contp[j];
480 if (cont == nullptr) {
481 // int R__n;
482 // b >> R__n;
483 // b.SetOffset(b.GetOffset()-4); // rewind to the start of the int
484 // if (R__n) continue;
485 contp[j] = cle->New();
486 cont = contp[j];
487 }
488 cle->Streamer(cont, buf);
489 }
490 // }
491 } else {
492 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
493 }
494 buf.CheckByteCount(start, count, aElement->GetFullName());
495
496 return 0;
497 }
498
499 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
500 * potentially can be used later for non-text streaming */
501 template<bool kIsTextT>
503 {
504 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
505 UInt_t ioffset = eoffset + config->fOffset;
506
507 if (!kIsTextT && config->fCompInfo->fStreamer) {
508 // Get any private streamer which was set for the data member.
509 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
510 // -- We have a private streamer.
511 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
512 // Loop over the entries in the clones array or the STL container.
513 //for (int k = 0; k < narr; ++k) {
514 // Get a pointer to the counter for the varying length array.
515 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
516
517 // And call the private streamer, passing it the buffer, the object, and the counter.
518 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
519 //} for k
520 buf.SetByteCount(pos, kTRUE);
521 // We are done, next streamer element.
522 return 0;
523 }
524
525 // Get the class of the data member.
526 TClass* cl = config->fCompInfo->fClass;
527 // Which are we, an array of objects or an array of pointers to objects?
528 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
529
530 // By default assume the file version is the newest.
531 Int_t fileVersion = kMaxInt;
532
533 if (!kIsTextT) {
534 // At this point we do *not* have a private streamer.
535 // Get the version of the file we are writing to.
536 TFile* file = (TFile*) buf.GetParent();
537 if (file) {
538 fileVersion = file->GetVersion();
539 }
540 }
541 // Write the class version to the buffer.
542 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
543 if (fileVersion > 51508) {
544 // -- Newer versions allow polymorphic pointers to objects.
545 // Loop over the entries in the clones array or the STL container.
546 //for (int k = 0; k < narr; ++k) {
547 // Get the counter for the varying length array.
548 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
549
550 //b << vlen;
551 if (vlen) {
552 // Get a pointer to the array of pointers.
553 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
554 // Loop over each element of the array of pointers to varying-length arrays.
555 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
556 if (!pp[ndx]) {
557 // -- We do not have a pointer to a varying-length array.
558 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
559 // ::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()));
560 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());
561 continue;
562 }
563 if (!isPtrPtr) {
564 // -- We are a varying-length array of objects.
565 // Write the entire array of objects to the buffer.
566 // Note: Polymorphism is not allowed here.
567 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
568 } else {
569 // -- We are a varying-length array of pointers to objects.
570 // Write the entire array of object pointers to the buffer.
571 // Note: The object pointers are allowed to be polymorphic.
572 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
573 } // isPtrPtr
574 } // ndx
575 } else // vlen
576 if (kIsTextT) {
577 // special handling for the text-based streamers
578 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
579 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
580 }
581 //} // k
582 }
583 else {
584 // -- Older versions do *not* allow polymorphic pointers to objects.
585 // Loop over the entries in the clones array or the STL container.
586 //for (int k = 0; k < narr; ++k) {
587 // Get the counter for the varying length array.
588 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
589 //b << vlen;
590 if (vlen) {
591 // Get a pointer to the array of pointers.
592 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
593 // -- Older versions do *not* allow polymorphic pointers to objects.
594 // Loop over each element of the array of pointers to varying-length arrays.
595 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
596 if (!pp[ndx]) {
597 // -- We do not have a pointer to a varying-length array.
598 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
599 // ::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()));
600 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());
601 continue;
602 }
603 if (!isPtrPtr) {
604 // -- We are a varying-length array of objects.
605 // Loop over the elements of the varying length array.
606 for (Int_t v = 0; v < vlen; ++v) {
607 // Write the object to the buffer.
608 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
609 } // v
610 }
611 else {
612 // -- We are a varying-length array of pointers to objects.
613 // Loop over the elements of the varying length array.
614 for (Int_t v = 0; v < vlen; ++v) {
615 // Get a pointer to the object pointer.
616 char** r = (char**) pp[ndx];
617 // Write the object to the buffer.
618 cl->Streamer(r[v], buf);
619 } // v
620 } // isPtrPtr
621 } // ndx
622 } // vlen
623 //} // k
624 } // fileVersion
625 // Backpatch the byte count into the buffer.
626 buf.SetByteCount(pos, kTRUE);
627
628 return 0;
629 }
630
631
632 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
633 * potentially can be used later for non-text streaming */
634 template<bool kIsTextT>
636 {
637 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
638 UInt_t ioffset = eoffset + config->fOffset;
639
640 // Get the class of the data member.
641 TClass* cl = config->fCompInfo->fClass;
642
643 // Check for a private streamer.
644 if (!kIsTextT && config->fCompInfo->fStreamer) {
645 // Get any private streamer which was set for the data member.
646 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
647 // -- We have a private streamer.
648 // Read the class version and byte count from the buffer.
649 UInt_t start = 0;
650 UInt_t count = 0;
651 buf.ReadVersion(&start, &count, cl);
652 // Loop over the entries in the clones array or the STL container.
653 //for (Int_t k = 0; k < narr; ++k) {
654
655 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
656 // And call the private streamer, passing it the buffer, the object, and the counter.
657 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
658
659 // } // for k
660 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
661 // We are done, next streamer element.
662 return 0;
663 }
664
665 // Which are we, an array of objects or an array of pointers to objects?
666 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
667
668 // By default assume the file version is the newest.
669 Int_t fileVersion = kMaxInt;
670 if (!kIsTextT) {
671 // At this point we do *not* have a private streamer.
672 // Get the version of the file we are reading from.
673 TFile* file = (TFile*) buf.GetParent();
674 if (file) {
675 fileVersion = file->GetVersion();
676 }
677 }
678 // Read the class version and byte count from the buffer.
679 UInt_t start = 0;
680 UInt_t count = 0;
681 buf.ReadVersion(&start, &count, cl);
682 if (fileVersion > 51508) {
683 // -- Newer versions allow polymorphic pointers.
684 // Loop over the entries in the clones array or the STL container.
685 // for (Int_t k = 0; k < narr; ++k) {
686 // Get the counter for the varying length array.
687 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
688 config->fCompInfo->fMethod /*counter offset*/));
689 // Int_t realLen;
690 // b >> realLen;
691 // if (realLen != vlen) {
692 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
693 //}
694 // Get a pointer to the array of pointers.
695 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
696 // Loop over each element of the array of pointers to varying-length arrays.
697 // if (!pp) {
698 // continue;
699 // }
700
701 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
702 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
703 // if (!pp[ndx]) {
704 // -- We do not have a pointer to a varying-length array.
705 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
706 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
707 // continue;
708 //}
709 // Delete any memory at pp[ndx].
710 if (!isPtrPtr) {
711 cl->DeleteArray(pp[ndx]);
712 pp[ndx] = 0;
713 } else {
714 // Using vlen is wrong here because it has already
715 // been overwritten with the value needed to read
716 // the current record. Fixing this will require
717 // doing a pass over the object at the beginning
718 // of the I/O and releasing all the buffer memory
719 // for varying length arrays before we overwrite
720 // the counter values.
721 //
722 // For now we will just leak memory, just as we
723 // have always done in the past. Fix this.
724 //
725 // char** r = (char**) pp[ndx];
726 // if (r) {
727 // for (Int_t v = 0; v < vlen; ++v) {
728 // cl->Destructor(r[v]);
729 // r[v] = 0;
730 // }
731 //}
732 delete[] pp[ndx];
733 pp[ndx] = 0;
734 }
735 if (!vlen) {
736 if (kIsTextT) {
737 // special handling for the text-based streamers - keep calling to shift array index
738 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
739 }
740 continue;
741 }
742 // Note: We now have pp[ndx] is null.
743 // Allocate memory to read into.
744 if (!isPtrPtr) {
745 // -- We are a varying-length array of objects.
746 // Note: Polymorphism is not allowed here.
747 // Allocate a new array of objects to read into.
748 pp[ndx] = (char *)cl->NewArray(vlen);
749 if (!pp[ndx]) {
750 Error("ReadBuffer", "Memory allocation failed!\n");
751 continue;
752 }
753 } else {
754 // -- We are a varying-length array of pointers to objects.
755 // Note: The object pointers are allowed to be polymorphic.
756 // Allocate a new array of pointers to objects to read into.
757 pp[ndx] = (char *)new char *[vlen];
758 if (!pp[ndx]) {
759 Error("ReadBuffer", "Memory allocation failed!\n");
760 continue;
761 }
762 // And set each pointer to null.
763 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
764 // = (char*) new char*[vlen];
765 }
766 if (!isPtrPtr) {
767 // -- We are a varying-length array of objects.
768 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
769 } else {
770 // -- We are a varying-length array of object pointers.
771 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
772 } // isPtrPtr
773 } // ndx
774 // } // k
775 } else {
776 // -- Older versions do *not* allow polymorphic pointers.
777 // Loop over the entries in the clones array or the STL container.
778 // for (Int_t k = 0; k < narr; ++k) {
779 // Get the counter for the varying length array.
780 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
781 config->fCompInfo->fMethod /*counter offset*/));
782 // Int_t realLen;
783 // b >> realLen;
784 // if (realLen != vlen) {
785 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
786 //}
787 // Get a pointer to the array of pointers.
788 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
789 // if (!pp) {
790 // continue;
791 //}
792
793 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
794
795 // Loop over each element of the array of pointers to varying-length arrays.
796 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
797 // if (!pp[ndx]) {
798 // -- We do not have a pointer to a varying-length array.
799 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
800 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
801 // continue;
802 //}
803 // Delete any memory at pp[ndx].
804 if (!isPtrPtr) {
805 cl->DeleteArray(pp[ndx]);
806 pp[ndx] = 0;
807 } else {
808 // Using vlen is wrong here because it has already
809 // been overwritten with the value needed to read
810 // the current record. Fixing this will require
811 // doing a pass over the object at the beginning
812 // of the I/O and releasing all the buffer memory
813 // for varying length arrays before we overwrite
814 // the counter values.
815 //
816 // For now we will just leak memory, just as we
817 // have always done in the past. Fix this.
818 //
819 // char** r = (char**) pp[ndx];
820 // if (r) {
821 // for (Int_t v = 0; v < vlen; ++v) {
822 // cl->Destructor(r[v]);
823 // r[v] = 0;
824 // }
825 //}
826 delete[] pp[ndx];
827 pp[ndx] = 0;
828 }
829 if (!vlen) {
830 continue;
831 }
832 // Note: We now have pp[ndx] is null.
833 // Allocate memory to read into.
834 if (!isPtrPtr) {
835 // -- We are a varying-length array of objects.
836 // Note: Polymorphism is not allowed here.
837 // Allocate a new array of objects to read into.
838 pp[ndx] = (char *)cl->NewArray(vlen);
839 if (!pp[ndx]) {
840 Error("ReadBuffer", "Memory allocation failed!\n");
841 continue;
842 }
843 } else {
844 // -- We are a varying-length array of pointers to objects.
845 // Note: The object pointers are allowed to be polymorphic.
846 // Allocate a new array of pointers to objects to read into.
847 pp[ndx] = (char *)new char *[vlen];
848 if (!pp[ndx]) {
849 Error("ReadBuffer", "Memory allocation failed!\n");
850 continue;
851 }
852 // And set each pointer to null.
853 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
854 // = (char*) new char*[vlen];
855 }
856 if (!isPtrPtr) {
857 // -- We are a varying-length array of objects.
858 // Loop over the elements of the varying length array.
859 for (Int_t v = 0; v < vlen; ++v) {
860 // Read the object from the buffer.
861 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
862 } // v
863 } else {
864 // -- We are a varying-length array of object pointers.
865 // Get a pointer to the object pointer array.
866 char **r = (char **)pp[ndx];
867 // Loop over the elements of the varying length array.
868 for (Int_t v = 0; v < vlen; ++v) {
869 // Allocate an object to read into.
870 r[v] = (char *)cl->New();
871 if (!r[v]) {
872 // Do not print a second error message here.
873 // Error("ReadBuffer", "Memory allocation failed!\n");
874 continue;
875 }
876 // Read the object from the buffer.
877 cl->Streamer(r[v], buf);
878 } // v
879 } // isPtrPtr
880 } // ndx
881 // } // k
882 } // fileVersion
883 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
884 return 0;
885 }
886
888 // Configuration object for the Float16/Double32 where a factor has been specified.
889 public:
892 TConfWithFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Double_t factor, Double_t xmin) : TConfiguration(info,id,compinfo,offset),fFactor(factor),fXmin(xmin) {};
893 virtual TConfiguration *Copy() { return new TConfWithFactor(*this); }
894 };
895
896 template <typename T>
898 {
899 // Stream a Float16 or Double32 where a factor has been specified.
900 //a range was specified. We read an integer and convert it back to a double.
901
902 TConfWithFactor *conf = (TConfWithFactor *)config;
903 buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
904 return 0;
905 }
906
908 // Configuration object for the Float16/Double32 where a factor has been specified.
909 public:
911 TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
912 virtual TConfiguration *Copy() { return new TConfNoFactor(*this); }
913 };
914
915 template <typename T>
917 {
918 // Stream a Float16 or Double32 where a factor has not been specified.
919
920 TConfNoFactor *conf = (TConfNoFactor *)config;
921 Int_t nbits = conf->fNbits;
922
923 buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
924 return 0;
925 }
926
928 {
929 // Read in a TString object.
930
931 // Idea: We could separate the TString Streamer in its two parts and
932 // avoid the if (buf.IsReading()) and try having it inlined.
933 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
934 return 0;
935 }
936
938 {
939 // Read in a TObject object part.
940
941 // Idea: We could separate the TObject Streamer in its two parts and
942 // avoid the if (buf.IsReading()).
943 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
944 return 0;
945 }
946
948 {
949 // Read in a TNamed object part.
950 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
951 // can skip the streamer.
952
953 // Idea: We could extract the code from ReadClassBuffer and avoid one function
954 // code.
955 static const TClass *TNamed_cl = TNamed::Class();
956 return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
957 }
958
959 class TConfigSTL : public TConfiguration {
960 // Configuration object for the kSTL case
961 private:
962 void Init() {
964 if (proxy) {
970 }
971 }
972
973 public:
974 TClass *fOldClass; // Class of the content on file
975 TClass *fNewClass; // Class of the content in memory.
977 const char *fTypeName; // Type name of the member as typed by ther user.
978 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
979
985
986 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
987 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
989
990 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) :
991 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
993
994 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) :
995 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
997
998 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) :
999 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
1001
1002 virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
1003 };
1004
1006 // Configuration object for the Float16/Double32 where a factor has been specified.
1007 public:
1011 virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
1012 };
1013
1015 // Configuration object for the Float16/Double32 where a factor has been specified.
1016 public:
1018 TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1019 virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
1020 };
1021
1023 // Base class of the Configurations used in member wise streaming.
1024 protected:
1025 public:
1026 Long_t fIncrement; // Either a value to increase the cursor by and
1027 public:
1028 TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1029 //virtual void PrintDebug(TBuffer &buffer, void *);
1031 void Print() const
1032 {
1033 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1034 }
1035
1036 void* GetFirstAddress(void *start, const void * /* end */) const
1037 {
1038 // Return the address of the first element of the collection.
1039
1040 return start;
1041 }
1042
1043 virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
1044 };
1045
1047 // Base class of the Configurations used in member wise streaming.
1048 public:
1050 //virtual void PrintDebug(TBuffer &buffer, void *);
1051 virtual ~TAssocLoopConfig() {};
1052 void Print() const
1053 {
1054 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1055 }
1056 virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
1057
1058 void* GetFirstAddress(void *start, const void * /* end */) const
1059 {
1060 // Return the address of the first element of the collection.
1061
1062 R__ASSERT(0);
1063// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1064// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1065// arr0 = genloopconfig->fNext(iter,end_collection);
1066// if (iter != &iterator[0]) {
1067// genloopconfig->fDeleteIterator(iter);
1068// }
1069 return start;
1070 }
1071 };
1072
1074 // Configuration object for the generic case of member wise streaming looping.
1075 private:
1076 void Init(Bool_t read) {
1077 if (fProxy) {
1078 if (fProxy->HasPointers()) {
1082 } else {
1083 fNext = fProxy->GetFunctionNext(read);
1086 }
1087 }
1088 }
1089 public:
1093
1095 {
1096 Init(read);
1097 }
1099 void Print() const
1100 {
1101 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1102 }
1103 virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
1104
1105 void* GetFirstAddress(void *start_collection, const void *end_collection) const
1106 {
1107 // Return the address of the first element of the collection.
1108
1110 void *iter = fCopyIterator(&iterator,start_collection);
1111 void *arr0 = fNext(iter,end_collection);
1112 if (iter != &iterator[0]) {
1113 fDeleteIterator(iter);
1114 }
1115 return arr0;
1116 }
1117 };
1118
1120 {
1121 // Collection was saved member-wise
1122
1123 TConfigSTL *config = (TConfigSTL*)conf;
1125
1126 if( vers >= 8 ) {
1127
1128 TClass *oldClass = config->fOldClass;
1129
1130 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1131 if (!oldProxy) {
1132 // Missing information, broken file ... give up
1133 return;
1134 }
1135 TClass *valueClass = oldProxy->GetValueClass();
1136 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1137
1138 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1139 Int_t nobjects;
1140 buf.ReadInt(nobjects);
1141 void* alternative = oldProxy->Allocate(nobjects,true);
1142 if (nobjects) {
1143 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1144
1147 void *begin = &(startbuf[0]);
1148 void *end = &(endbuf[0]);
1149 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1150 // We can not get here with a split vector of pointer, so we can indeed assume
1151 // that actions->fConfiguration != null.
1152 buf.ApplySequence(*actions, begin, end);
1153 if (begin != &(startbuf[0])) {
1154 // assert(end != endbuf);
1155 config->fDeleteTwoIterators(begin,end);
1156 }
1157 }
1158 oldProxy->Commit(alternative);
1159
1160 } else {
1161
1162 TClass *oldClass = config->fOldClass;
1163
1164 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1165 if (!oldProxy) {
1166 // Missing information, broken file ... give up
1167 return;
1168 }
1169
1170 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1171 Int_t nobjects;
1172 buf.ReadInt(nobjects);
1173 void* env = oldProxy->Allocate(nobjects,true);
1174
1175 if (nobjects || vers < 7 ) {
1176 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1177 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1178
1179 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1180 }
1181 oldProxy->Commit(env);
1182 }
1183 }
1184
1186 {
1187 // Collection was saved member-wise
1188
1189 TConfigSTL *config = (TConfigSTL*)conf;
1191
1192 if( vers >= 8 ) {
1193
1194 TClass *oldClass = config->fOldClass;
1195
1196 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1197 if (!oldProxy) {
1198 // Missing information, broken file ... give up
1199 return;
1200 }
1201 TClass *valueClass = oldProxy->GetValueClass();
1202 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1203
1204 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1205
1206 int objectSize = oldClass->Size();
1207 char *obj = (char*)addr;
1208 char *endobj = obj + conf->fLength*objectSize;
1209
1210 for(; obj<endobj; obj+=objectSize) {
1211 Int_t nobjects;
1212 buf.ReadInt(nobjects);
1213 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1214 void* alternative = oldProxy->Allocate(nobjects,true);
1215 if (nobjects) {
1218 void *begin = &(startbuf[0]);
1219 void *end = &(endbuf[0]);
1220 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1221 // We can not get here with a split vector of pointer, so we can indeed assume
1222 // that actions->fConfiguration != null.
1223 buf.ApplySequence(*actions, begin, end);
1224 if (begin != &(startbuf[0])) {
1225 // assert(end != endbuf);
1226 config->fDeleteTwoIterators(begin,end);
1227 }
1228 }
1229 oldProxy->Commit(alternative);
1230 }
1231
1232 } else {
1233
1234 TClass *oldClass = config->fOldClass;
1235
1236 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1237 if (!oldProxy) {
1238 // Missing information, broken file ... give up
1239 return;
1240 }
1241
1242 int objectSize = oldClass->Size();
1243 char *obj = (char*)addr;
1244 char *endobj = obj + conf->fLength*objectSize;
1245
1246 for(; obj<endobj; obj+=objectSize) {
1247 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1248 Int_t nobjects;
1249 buf.ReadInt(nobjects);
1250 void* env = oldProxy->Allocate(nobjects,true);
1251
1252 if (nobjects || vers < 7 ) {
1253 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1254 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1255
1256 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1257 }
1258 oldProxy->Commit(env);
1259 }
1260 }
1261 }
1262
1264 {
1265 // Collection was saved member-wise
1266
1267 TConfigSTL *config = (TConfigSTL*)conf;
1268
1270
1271 TClass *newClass = config->fNewClass;
1272 TClass *oldClass = config->fOldClass;
1273
1274 if( vers < 8 ) {
1275 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1276 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1277 } else {
1278
1279 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1280
1281 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1282 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1283
1284 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1285 Int_t nobjects;
1286 buf.ReadInt(nobjects);
1287 void* alternative = newProxy->Allocate(nobjects,true);
1288 if (nobjects) {
1289 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1292 void *begin = &(startbuf[0]);
1293 void *end = &(endbuf[0]);
1294 config->fCreateIterators( alternative, &begin, &end, newProxy);
1295 // We can not get here with a split vector of pointer, so we can indeed assume
1296 // that actions->fConfiguration != null.
1297 buf.ApplySequence(*actions, begin, end);
1298 if (begin != &(startbuf[0])) {
1299 // assert(end != endbuf);
1300 config->fDeleteTwoIterators(begin,end);
1301 }
1302 }
1303 newProxy->Commit(alternative);
1304 }
1305 }
1306
1308 {
1309 // Collection was saved member-wise
1310
1311 TConfigSTL *config = (TConfigSTL*)conf;
1312
1314
1315 TClass *newClass = config->fNewClass;
1316 TClass *oldClass = config->fOldClass;
1317
1318 if( vers < 8 ) {
1319 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1320 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1321 } else {
1322
1323 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1324
1325 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1326 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1327
1328 int objectSize = newClass->Size();
1329 char *obj = (char*)addr;
1330 char *endobj = obj + conf->fLength*objectSize;
1331
1332 for(; obj<endobj; obj+=objectSize) {
1333 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1334 Int_t nobjects;
1335 buf.ReadInt(nobjects);
1336 void* alternative = newProxy->Allocate(nobjects,true);
1337 if (nobjects) {
1338 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1341 void *begin = &(startbuf[0]);
1342 void *end = &(endbuf[0]);
1343 config->fCreateIterators( alternative, &begin, &end, newProxy);
1344 // We can not get here with a split vector of pointer, so we can indeed assume
1345 // that actions->fConfiguration != null.
1346 buf.ApplySequence(*actions, begin, end);
1347 if (begin != &(startbuf[0])) {
1348 // assert(end != endbuf);
1349 config->fDeleteTwoIterators(begin,end);
1350 }
1351 }
1352 newProxy->Commit(alternative);
1353 }
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 virtual void Print() const {
1477 if (fOnfileObject)
1478 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1479 info->GetClass()->GetName(), fOffset);
1480 else
1481 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1482 info->GetClass()->GetName(), fOffset);
1483 }
1484 virtual void PrintDebug(TBuffer &buffer, void *object) const {
1485 if (gDebug > 1) {
1487 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1488 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1489
1490 }
1491 }
1492 };
1493
1495 {
1497 auto onfileObject = config->fOnfileObject;
1498
1499 // onfileObject->SetSize(1);
1500 b.PushDataCache( onfileObject );
1501
1502 return 0;
1503 }
1504
1505 Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1506 {
1508 auto onfileObject = config->fOnfileObject;
1509
1510 // onfileObject->SetSize(n);
1511 b.PushDataCache( onfileObject );
1512
1513 return 0;
1514 }
1515
1516 Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1517 {
1519 auto onfileObject = config->fOnfileObject;
1520
1521 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1522 UInt_t n = proxy->Size();
1523
1524 onfileObject->SetSize(n);
1525 b.PushDataCache( onfileObject );
1526
1527 return 0;
1528 }
1529
1531 {
1532 b.PopDataCache();
1533 return 0;
1534 }
1535
1536 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1537 {
1538 b.PopDataCache();
1539 return 0;
1540 }
1541
1543 {
1544 b.PopDataCache();
1545 return 0;
1546 }
1547
1549 // Configuration object for the UseCache case.
1550 public:
1553
1555 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1556 virtual void PrintDebug(TBuffer &b, void *addr) const
1557 {
1558 if (gDebug > 1) {
1559 // Idea: We should print the name of the action function.
1561 TStreamerElement *aElement = fCompInfo->fElem;
1562 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1563 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1564 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1565 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1566 }
1567
1568 }
1572 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1573 return copy;
1574 }
1575 };
1576
1578 {
1580
1581 Int_t bufpos = b.Length();
1582 TVirtualArray *cached = b.PeekDataCache();
1583 if (cached==0) {
1584 TStreamerElement *aElement = conf->fCompInfo->fElem;
1585 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1586 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1587 char *ptr = (char*)addr;
1588 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1589 } else {
1590 config->fAction(b, (*cached)[0]);
1591 }
1592 // Idea: Factor out this 'if' to a UseCacheRepeat function
1593 if (config->fNeedRepeat) {
1594 b.SetBufferOffset(bufpos);
1595 }
1596 return 0;
1597 }
1598
1599 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1600 {
1602 Int_t bufpos = b.Length();
1603
1604 TVirtualArray *cached = b.PeekDataCache();
1605 if (cached==0) {
1606 TStreamerElement *aElement = config->fCompInfo->fElem;
1607 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1608 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1609 char *ptr = (char*)start;
1610 UInt_t n = (((void**)end)-((void**)start));
1611 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1612 } else {
1613 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1614 void *cached_start = (*cached)[0];
1615 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1616 config->fAction(b,cached_start,cached_end,&cached_config);
1617 }
1618 // Idea: Factor out this 'if' to a UseCacheRepeat function
1619 if (config->fNeedRepeat) {
1620 b.SetBufferOffset(bufpos);
1621 }
1622 return 0;
1623 }
1624
1625 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1626 {
1628
1629 Int_t bufpos = b.Length();
1630 TVirtualArray *cached = b.PeekDataCache();
1631 if (cached==0) {
1632 TStreamerElement *aElement = config->fCompInfo->fElem;
1633 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1634 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1635 char *ptr = (char*)start;
1636 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1637 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1638 } else {
1639 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1640 void *cached_start = (*cached)[0];
1641 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1642 config->fAction(b,cached_start,cached_end,&cached_config);
1643 }
1644 // Idea: Factor out this 'if' to a UseCacheRepeat function
1645 if (config->fNeedRepeat) {
1646 b.SetBufferOffset(bufpos);
1647 }
1648 return 0;
1649 }
1650
1652 {
1654
1655 Int_t bufpos = b.Length();
1656 TVirtualArray *cached = b.PeekDataCache();
1657 if (cached==0) {
1658 TStreamerElement *aElement = config->fCompInfo->fElem;
1659 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1660
1661 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1662 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1663 UInt_t n = proxy->Size();
1664 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1665 } else {
1666 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1667 void *cached_start = (*cached)[0];
1668 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1669 config->fAction(b,cached_start,cached_end,&cached_config);
1670 }
1671 // Idea: Factor out this 'if' to a UseCacheRepeat function
1672 if (config->fNeedRepeat) {
1673 b.SetBufferOffset(bufpos);
1674 }
1675 return 0;
1676 }
1677
1678 // Support for collections.
1679
1680 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1681 {
1682 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1683 return 0;
1684 }
1685
1686 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1687 {
1688 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1689 return 0;
1690 }
1691
1693
1695 {
1698 return kGenericLooper;
1699 else
1700 return kVectorLooper;
1705 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1706 return kAssociativeLooper;
1707 } else if (proxy.GetCollectionType() == ROOT::kROOTRVec && proxy.GetType() == EDataType::kBool_t) {
1708 return kVectorLooper;
1709 } else {
1710 return kGenericLooper;
1711 }
1712 }
1713
1715
1716 template <typename T>
1717 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1718 {
1719 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1720 iter = (char*)iter + config->fOffset;
1721 end = (char*)end + config->fOffset;
1722 for(; iter != end; iter = (char*)iter + incr ) {
1723 T *x = (T*) ((char*) iter);
1724 buf >> *x;
1725 }
1726 return 0;
1727 }
1728
1729 template <typename From, typename To>
1731 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1732 {
1733 // Simple conversion from a 'From' on disk to a 'To' in memory.
1734 From temp;
1735 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1736 iter = (char*)iter + config->fOffset;
1737 end = (char*)end + config->fOffset;
1738 for(; iter != end; iter = (char*)iter + incr ) {
1739 buf >> temp;
1740 *(To*)( ((char*)iter) ) = (To)temp;
1741 }
1742 return 0;
1743 }
1744 };
1745
1746 template <typename To>
1748 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1749 {
1750 // Simple conversion from a 'From' on disk to a 'To' in memory.
1751 UInt_t temp;
1752 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1753 iter = (char*)iter + config->fOffset;
1754 end = (char*)end + config->fOffset;
1755 for(; iter != end; iter = (char*)iter + incr ) {
1756 buf >> temp;
1757
1758 if ((temp & kIsReferenced) != 0) {
1759 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1760 }
1761
1762 *(To*)( ((char*)iter) ) = (To)temp;
1763 }
1764 return 0;
1765 }
1766 };
1767
1768 template <typename From, typename To>
1770 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1771 {
1772 // Simple conversion from a 'From' on disk to a 'To' in memory.
1773 TConfWithFactor *conf = (TConfWithFactor *)config;
1774 From temp;
1775 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1776 iter = (char*)iter + config->fOffset;
1777 end = (char*)end + config->fOffset;
1778 for(; iter != end; iter = (char*)iter + incr ) {
1779 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1780 *(To*)( ((char*)iter) ) = (To)temp;
1781 }
1782 return 0;
1783 }
1784 };
1785
1786 template <typename From, typename To>
1788 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1789 {
1790 // Simple conversion from a 'From' on disk to a 'To' in memory.
1791 TConfNoFactor *conf = (TConfNoFactor *)config;
1792 From temp;
1793 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1794 iter = (char*)iter + config->fOffset;
1795 end = (char*)end + config->fOffset;
1796 for(; iter != end; iter = (char*)iter + incr ) {
1797 buf.ReadWithNbits(&temp, conf->fNbits);
1798 *(To*)( ((char*)iter) ) = (To)temp;
1799 }
1800 return 0;
1801 }
1802 };
1803
1804 template <typename T>
1805 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1806 {
1807 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1808 iter = (char*)iter + config->fOffset;
1809 end = (char*)end + config->fOffset;
1810 for(; iter != end; iter = (char*)iter + incr ) {
1811 T *x = (T*) ((char*) iter);
1812 buf << *x;
1813 }
1814 return 0;
1815 }
1816
1817 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1818 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1819 {
1820 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1821 //Idea: can we factor out the addition of fOffset
1822 // iter = (char*)iter + config->fOffset;
1823 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1824 iter_action(buf, iter, config);
1825 }
1826 return 0;
1827 }
1828
1829 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1830 {
1831 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1832 // punt.
1833
1834 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1835 UInt_t n = (((char*)end)-((char*)start))/incr;
1836 char **arrptr = new char*[n];
1837 UInt_t i = 0;
1838 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1839 arrptr[i] = (char*)iter;
1840 }
1841 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1842 delete [] arrptr;
1843
1844 // // Idea: need to cache this result!
1845 // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1846 // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1847 //
1848 // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1849 // *TClass *cle = aElement->GetNewBaseClass();
1850 // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1851 //
1852 // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1853 //
1854 // actions->ReadBuffer(b,start,end);
1855 // delete actions;
1856
1857 // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1858 // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1859 // {
1860 // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1861 //
1862 // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1863 // }
1864 return 0;
1865 }
1866
1867 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1868 {
1869 // Well the implementation is non trivial. For now punt.
1870
1871 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1872 UInt_t n = (((char*)end)-((char*)start))/incr;
1873 char **arrptr = new char*[n];
1874 UInt_t i = 0;
1875 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1876 arrptr[i] = (char*)iter;
1877 }
1878 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1879 delete [] arrptr;
1880 return 0;
1881 }
1882
1883 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1884 {
1885 // Well the implementation is non trivial. For now punt.
1886
1887 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1888 UInt_t n = (((char*)end)-((char*)start))/incr;
1889 char **arrptr = new char*[n];
1890 UInt_t i = 0;
1891 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1892 arrptr[i] = (char*)iter;
1893 }
1894 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1895 delete [] arrptr;
1896 return 0;
1897 }
1898
1899 template <typename T>
1901 {
1902 // Collection of numbers. Memberwise or not, it is all the same.
1903
1904 TConfigSTL *config = (TConfigSTL*)conf;
1905 UInt_t start, count;
1906 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1907
1908 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1909 Int_t nvalues;
1910 buf.ReadInt(nvalues);
1911 vec->resize(nvalues);
1912
1913#ifdef R__VISUAL_CPLUSPLUS
1914 if (nvalues <= 0) {
1915 buf.CheckByteCount(start,count,config->fTypeName);
1916 return 0;
1917 }
1918#endif
1919 T *begin = &(*vec->begin());
1920 buf.ReadFastArray(begin, nvalues);
1921
1922 buf.CheckByteCount(start,count,config->fTypeName);
1923 return 0;
1924 }
1925
1927 {
1928 // Collection of numbers. Memberwise or not, it is all the same.
1929
1930 TConfigSTL *config = (TConfigSTL*)conf;
1931 UInt_t start, count;
1932 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1933
1934 std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1935 Int_t nvalues;
1936 buf.ReadInt(nvalues);
1937 vec->resize(nvalues);
1938
1939 bool *items = new bool[nvalues];
1940 buf.ReadFastArray(items, nvalues);
1941 for(Int_t i = 0 ; i < nvalues; ++i) {
1942 (*vec)[i] = items[i];
1943 }
1944 delete [] items;
1945
1946 // We could avoid the call to ReadFastArray, and we could
1947 // the following, however this breaks TBufferXML ...
1948 // for(Int_t i = 0 ; i < nvalues; ++i) {
1949 // bool tmp; buf >> tmp;
1950 // (*vec)[i] = tmp;
1951 // }
1952
1953 buf.CheckByteCount(start,count,config->fTypeName);
1954 return 0;
1955 }
1956
1958 {
1959 // Collection of numbers. Memberwise or not, it is all the same.
1960
1961 TConfigSTL *config = (TConfigSTL*)conf;
1962 UInt_t start, count;
1963 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1964
1965 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1966 Int_t nvalues;
1967 buf.ReadInt(nvalues);
1968 vec->resize(nvalues);
1969
1970#ifdef R__VISUAL_CPLUSPLUS
1971 if (nvalues <= 0) {
1972 buf.CheckByteCount(start,count,config->fTypeName);
1973 return 0;
1974 }
1975#endif
1976 float *begin = &(*vec->begin());
1977 buf.ReadFastArrayFloat16(begin, nvalues);
1978
1979 buf.CheckByteCount(start,count,config->fTypeName);
1980 return 0;
1981 }
1982
1984 {
1985 // Collection of numbers. Memberwise or not, it is all the same.
1986
1987 TConfigSTL *config = (TConfigSTL*)conf;
1988 UInt_t start, count;
1989 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1990
1991 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1992 Int_t nvalues;
1993 buf.ReadInt(nvalues);
1994 vec->resize(nvalues);
1995
1996#ifdef R__VISUAL_CPLUSPLUS
1997 if (nvalues <= 0) {
1998 buf.CheckByteCount(start,count,config->fTypeName);
1999 return 0;
2000 }
2001#endif
2002 double *begin = &(*vec->begin());
2003 buf.ReadFastArrayDouble32(begin, nvalues);
2004
2005 buf.CheckByteCount(start,count,config->fTypeName);
2006 return 0;
2007 }
2008
2009 template <typename From, typename To>
2011 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2012 {
2013 // Collection of numbers. Memberwise or not, it is all the same.
2014
2015 TConfigSTL *config = (TConfigSTL*)conf;
2016 UInt_t start, count;
2017 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2018
2019 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2020 Int_t nvalues;
2021 buf.ReadInt(nvalues);
2022 vec->resize(nvalues);
2023
2024 From *temp = new From[nvalues];
2025 buf.ReadFastArray(temp, nvalues);
2026 for(Int_t ind = 0; ind < nvalues; ++ind) {
2027 (*vec)[ind] = (To)temp[ind];
2028 }
2029 delete [] temp;
2030
2031 buf.CheckByteCount(start,count,config->fTypeName);
2032 return 0;
2033 }
2034 };
2035
2036 template <typename From, typename To>
2038 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2039 {
2040 // Collection of numbers. Memberwise or not, it is all the same.
2041
2042 TConfigSTL *config = (TConfigSTL*)conf;
2043 UInt_t start, count;
2044 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2045
2046 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2047 Int_t nvalues;
2048 buf.ReadInt(nvalues);
2049 vec->resize(nvalues);
2050
2051 From *temp = new From[nvalues];
2052 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2053 for(Int_t ind = 0; ind < nvalues; ++ind) {
2054 (*vec)[ind] = (To)temp[ind];
2055 }
2056 delete [] temp;
2057
2058 buf.CheckByteCount(start,count,config->fTypeName);
2059 return 0;
2060 }
2061 };
2062
2063 template <typename To>
2065 {
2066 // Collection of numbers. Memberwise or not, it is all the same.
2067
2068 TConfigSTL *config = (TConfigSTL*)conf;
2069 UInt_t start, count;
2070 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2071
2072 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2073 Int_t nvalues;
2074 buf.ReadInt(nvalues);
2075 vec->resize(nvalues);
2076
2077 Double32_t *temp = new Double32_t[nvalues];
2078 buf.ReadFastArrayDouble32(temp, nvalues);
2079 for(Int_t ind = 0; ind < nvalues; ++ind) {
2080 (*vec)[ind] = (To)temp[ind];
2081 }
2082 delete [] temp;
2083
2084 buf.CheckByteCount(start,count,config->fTypeName);
2085 return 0;
2086 }
2087
2088 };
2089
2091
2092 template <typename T>
2093 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2094 {
2095 const Int_t offset = config->fOffset;
2096
2097 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2098 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2099 buf >> *x;
2100 }
2101 return 0;
2102 }
2103
2104 template <typename From, typename To>
2106 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2107 {
2108 // Simple conversion from a 'From' on disk to a 'To' in memory.
2109 From temp;
2110 const Int_t offset = config->fOffset;
2111 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2112 buf >> temp;
2113 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2114 *x = (To)temp;
2115 }
2116 return 0;
2117 }
2118 };
2119
2120 template <typename To>
2122 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2123 {
2124 // Simple conversion from a 'From' on disk to a 'To' in memory.
2125 UInt_t temp;
2126 const Int_t offset = config->fOffset;
2127 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2128 buf >> temp;
2129
2130 if ((temp & kIsReferenced) != 0) {
2131 HandleReferencedTObject(buf,*(void**)iter,config);
2132 }
2133
2134 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2135 *x = (To)temp;
2136 }
2137 return 0;
2138 }
2139 };
2140
2141 template <typename From, typename To>
2143 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2144 {
2145 // Simple conversion from a 'From' on disk to a 'To' in memory.
2146 TConfWithFactor *conf = (TConfWithFactor *)config;
2147 From temp;
2148 const Int_t offset = config->fOffset;
2149 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2150 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2151 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2152 *x = (To)temp;
2153 }
2154 return 0;
2155 }
2156 };
2157
2158 template <typename From, typename To>
2160 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2161 {
2162 // Simple conversion from a 'From' on disk to a 'To' in memory.
2163 TConfNoFactor *conf = (TConfNoFactor *)config;
2164 From temp;
2165 const Int_t offset = config->fOffset;
2166 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2167 buf.ReadWithNbits(&temp, conf->fNbits);
2168 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2169 *x = (To)temp;
2170 }
2171 return 0;
2172 }
2173 };
2174
2175 template <typename T>
2176 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2177 {
2178 const Int_t offset = config->fOffset;
2179
2180 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2181 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2182 buf << *x;
2183 }
2184 return 0;
2185 }
2186
2187 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2188 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2189 {
2190 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2191 action(buf, *(void**)iter, config);
2192 }
2193 return 0;
2194 }
2195
2196 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2197 {
2198 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2199 // punt.
2200
2201 return GenericRead(buf,start,end,config);
2202 }
2203
2204 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2205 {
2206 Int_t n = ( ((void**)end) - ((void**)iter) );
2207 char **arr = (char**)iter;
2208 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2209 }
2210
2211 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2212 {
2213 Int_t n = ( ((void**)end) - ((void**)iter) );
2214 char **arr = (char**)iter;
2215 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2216 }
2217
2218 };
2219
2221
2222 template <typename T>
2223 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2224 {
2225 buf.ReadFastArray((T*)addr, nvalues);
2226 }
2227
2228 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2229 {
2230 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2231 }
2232
2233 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2234 {
2235 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2236 }
2237
2238 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2240 {
2241 // Collection of numbers. Memberwise or not, it is all the same.
2242
2243 TConfigSTL *config = (TConfigSTL*)conf;
2244 UInt_t start, count;
2245 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2246
2247 TClass *newClass = config->fNewClass;
2248 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2249 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2250
2251 Int_t nvalues;
2252 buf.ReadInt(nvalues);
2253 void* alternative = newProxy->Allocate(nvalues,true);
2254 if (nvalues) {
2257 void *begin = &(startbuf[0]);
2258 void *end = &(endbuf[0]);
2259 config->fCreateIterators(alternative, &begin, &end, newProxy);
2260 // We can not get here with a split vector of pointer, so we can indeed assume
2261 // that actions->fConfiguration != null.
2262
2263 action(buf,begin,nvalues);
2264
2265 if (begin != &(startbuf[0])) {
2266 // assert(end != endbuf);
2267 config->fDeleteTwoIterators(begin,end);
2268 }
2269 }
2270 newProxy->Commit(alternative);
2271
2272 buf.CheckByteCount(start,count,config->fTypeName);
2273 return 0;
2274 }
2275
2277 {
2278 return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2279 }
2280
2282 {
2283 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2284 }
2285
2287 {
2288 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2289 }
2290
2291 template <typename T>
2293 {
2294 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2295 }
2296
2297 template <typename From, typename To>
2299 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2300 {
2301 From *temp = new From[nvalues];
2302 buf.ReadFastArray(temp, nvalues);
2303 To *vec = (To*)addr;
2304 for(Int_t ind = 0; ind < nvalues; ++ind) {
2305 vec[ind] = (To)temp[ind];
2306 }
2307 delete [] temp;
2308 }
2309 };
2310
2311 template <typename From, typename To>
2312 struct ConvertRead<NoFactorMarker<From>,To> {
2313 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2314 {
2315 From *temp = new From[nvalues];
2316 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2317 To *vec = (To*)addr;
2318 for(Int_t ind = 0; ind < nvalues; ++ind) {
2319 vec[ind] = (To)temp[ind];
2320 }
2321 delete [] temp;
2322 }
2323 };
2324
2325 template <typename From, typename To>
2327 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2328 {
2329 From *temp = new From[nvalues];
2330 double factor,min; // needs to be initialized.
2331 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2332 To *vec = (To*)addr;
2333 for(Int_t ind = 0; ind < nvalues; ++ind) {
2334 vec[ind] = (To)temp[ind];
2335 }
2336 delete [] temp;
2337 }
2338 };
2339
2340 template <typename From, typename To>
2342 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2343 {
2344 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2345 }
2346 };
2347
2348 };
2349
2351
2352 template <typename T>
2353 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2354 {
2355 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2356
2357 Next_t next = loopconfig->fNext;
2358 const Int_t offset = config->fOffset;
2359
2361 void *iter = loopconfig->fCopyIterator(iterator,start);
2362 void *addr;
2363 while( (addr = next(iter,end)) ) {
2364 T *x = (T*)( ((char*)addr) + offset );
2365 buf >> *x;
2366 }
2367 if (iter != &iterator[0]) {
2368 loopconfig->fDeleteIterator(iter);
2369 }
2370 return 0;
2371 }
2372
2373 template <typename T>
2374 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2375 {
2376 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2377
2378 Next_t next = loopconfig->fNext;
2379 const Int_t offset = config->fOffset;
2380
2382 void *iter = loopconfig->fCopyIterator(iterator,start);
2383 void *addr;
2384 while( (addr = next(iter,end)) ) {
2385 T *x = (T*)( ((char*)addr) + offset );
2386 buf << *x;
2387 }
2388 if (iter != &iterator[0]) {
2389 loopconfig->fDeleteIterator(iter);
2390 }
2391 return 0;
2392 }
2393
2394 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2395 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2396 {
2397 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2398
2399 // const Int_t offset = config->fOffset;
2400 Next_t next = loopconfig->fNext;
2401
2403 void *iter = loopconfig->fCopyIterator(&iterator,start);
2404 void *addr;
2405 while( (addr = next(iter,end)) ) {
2406 iter_action(buf, addr, config);
2407 }
2408 if (iter != &iterator[0]) {
2409 loopconfig->fDeleteIterator(iter);
2410 }
2411 return 0;
2412 }
2413
2414 template <typename From, typename To>
2415 struct Generic {
2416 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2417 {
2418 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2419
2420 const Int_t offset = config->fOffset;
2421 Next_t next = loopconfig->fNext;
2422
2424 void *iter = loopconfig->fCopyIterator(&iterator,start);
2425 void *addr;
2426 while( (addr = next(iter,end)) ) {
2427 To *x = (To*)( ((char*)addr) + offset );
2428 *x = (To)(*items);
2429 ++items;
2430 }
2431 if (iter != &iterator[0]) {
2432 loopconfig->fDeleteIterator(iter);
2433 }
2434 }
2435 };
2436
2437 template <typename From, typename To>
2438 struct Numeric {
2439 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2440 {
2441 // The difference with ConvertAction is that we can modify the start
2442 // iterator and skip the copy. We also never have an offset.
2443
2444 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2445 Next_t next = loopconfig->fNext;
2446
2447 void *iter = start;
2448 void *addr;
2449 while( (addr = next(iter,end)) ) {
2450 To *x = (To*)(addr);
2451 *x = (To)(*items);
2452 ++items;
2453 }
2454 }
2455 };
2456
2457 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2459 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2460 {
2461 // Simple conversion from a 'From' on disk to a 'To' in memory.
2462
2463 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2464 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2465 Int_t nvalues = proxy->Size();
2466
2467 From *items = new From[nvalues];
2468 buf.ReadFastArray(items, nvalues);
2469 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2470 delete [] items;
2471 return 0;
2472 }
2473 };
2474
2475 template <typename To>
2477 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2478 {
2479 // Simple conversion from a 'From' on disk to a 'To' in memory.
2480
2481 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2482 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2483 Int_t nvalues = proxy->Size();
2484
2485 UInt_t *items_storage = new UInt_t[nvalues];
2486 UInt_t *items = items_storage;
2487
2488 const Int_t offset = config->fOffset;
2489 Next_t next = loopconfig->fNext;
2490
2492 void *iter = loopconfig->fCopyIterator(&iterator,start);
2493 void *addr;
2494 while( (addr = next(iter,end)) ) {
2495 buf >> (*items);
2496 if (((*items) & kIsReferenced) != 0) {
2497 HandleReferencedTObject(buf, addr, config);
2498 }
2499 To *x = (To*)( ((char*)addr) + offset );
2500 *x = (To)(*items);
2501 ++items;
2502 }
2503 if (iter != &iterator[0]) {
2504 loopconfig->fDeleteIterator(iter);
2505 }
2506
2507 delete [] items_storage;
2508 return 0;
2509 }
2510 };
2511
2512 template <typename From, typename To, template <typename F, typename T> class Converter >
2513 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2514 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2515 {
2516 // Simple conversion from a 'From' on disk to a 'To' in memory.
2517
2518 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2519 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2520 Int_t nvalues = proxy->Size();
2521
2522 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2523
2524 From *items = new From[nvalues];
2525 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2526 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2527 delete [] items;
2528 return 0;
2529 }
2530 };
2531
2532 template <typename From, typename To, template <typename F, typename T> class Converter >
2533 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2534 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2535 {
2536 // Simple conversion from a 'From' on disk to a 'To' in memory.
2537
2538 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2539 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2540 Int_t nvalues = proxy->Size();
2541
2542 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2543
2544 From *items = new From[nvalues];
2545 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2546 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2547 delete [] items;
2548 return 0;
2549 }
2550 };
2551
2552 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2553 {
2554 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2555 // punt.
2556
2557 return GenericRead(buf,start,end,loopconfig, config);
2558 }
2559
2560 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2561 {
2562 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2563 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2564 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2565 }
2566
2567 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2568 {
2569 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2570 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2571 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2572 }
2573
2574 template <typename T>
2575 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2576 {
2577 buf >> *(T*)addr;
2578 }
2579
2580 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2581 {
2582 buf.ReadWithNbits((float*)addr,12);
2583 }
2584
2586 {
2587 //we read a float and convert it to double
2588 Float_t afloat;
2589 buf >> afloat;
2590 *(double*)addr = (Double_t)afloat;
2591 }
2592
2593 template <typename ActionHolder>
2595 {
2596 // Collection of numbers. Memberwise or not, it is all the same.
2597
2598 TConfigSTL *config = (TConfigSTL*)conf;
2599 UInt_t start, count;
2600 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2601
2602 TClass *newClass = config->fNewClass;
2603 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2604 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2605
2606 Int_t nvalues;
2607 buf.ReadInt(nvalues);
2608 void* alternative = newProxy->Allocate(nvalues,true);
2609 if (nvalues) {
2612 void *begin = &(startbuf[0]);
2613 void *end = &(endbuf[0]);
2614 config->fCreateIterators(alternative, &begin, &end, newProxy);
2615 // We can not get here with a split vector of pointer, so we can indeed assume
2616 // that actions->fConfiguration != null.
2617
2618 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2619 ActionHolder::Action(buf,begin,end,&loopconf,config);
2620
2621 if (begin != &(startbuf[0])) {
2622 // assert(end != endbuf);
2623 config->fDeleteTwoIterators(begin,end);
2624 }
2625 }
2626 newProxy->Commit(alternative);
2627
2628 buf.CheckByteCount(start,count,config->fTypeName);
2629 return 0;
2630 }
2631
2633 {
2634 return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2635 }
2636
2638 {
2639 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2640 }
2641
2643 {
2644 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2645 // Could also use:
2646 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2647 }
2648
2649 template <typename T>
2651 {
2652 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2653 }
2654
2655 template <typename From, typename To>
2657 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2658 {
2659 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2660 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2661 }
2662 };
2663
2664 };
2665}
2666
2667template <typename Looper, typename From>
2669{
2670 switch (newtype) {
2671 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2672 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2673 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2674 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2675 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2676 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2677 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2678 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2679 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2680 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2681 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2682 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2683 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2684 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2685 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2686 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2687 default:
2688 return TConfiguredAction( Looper::GenericRead, conf );
2689 break;
2690 }
2691 R__ASSERT(0); // We should never be here
2692 return TConfiguredAction();
2693}
2694
2695template <class Looper>
2697{
2698 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2699
2700 switch (type) {
2701 // Read basic types.
2702 case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2703 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2704 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2705 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2706 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2707 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2708 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2709 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2710 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2711 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2712 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2713 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2714 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2715 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2717 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2718 delete conf;
2719 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2720 // if (element->GetFactor() != 0) {
2721 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2722 // } else {
2723 // Int_t nbits = (Int_t)element->GetXmin();
2724 // if (!nbits) nbits = 12;
2725 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2726 // }
2727 break;
2728 }
2730 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2731 delete conf;
2732 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2733 // if (element->GetFactor() != 0) {
2734 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2735 // } else {
2736 // Int_t nbits = (Int_t)element->GetXmin();
2737 // if (!nbits) {
2738 // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2739 // } else {
2740 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2741 // }
2742 // }
2743 break;
2744 }
2745 }
2746 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2747 R__ASSERT(0); // We should never be here
2748 return TConfiguredAction();
2749}
2750
2751template <typename Looper, typename From>
2753{
2754 switch (newtype) {
2755 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2756 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2757 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2758 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2759 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2760 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2761 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2762 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2763 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2764 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2765 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2766 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2767 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2768 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2769 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2770 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2771 default:
2772 break;
2773 }
2774 R__ASSERT(0); // We should never be here
2775 return TConfiguredAction();
2776}
2777
2778template <typename Looper>
2780{
2781 switch (oldtype) {
2783 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2784 break;
2786 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2787 break;
2789 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2790 break;
2792 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2793 break;
2795 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2796 break;
2798 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2799 break;
2801 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2802 break;
2804 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2805 break;
2807 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2808 break;
2810 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2811 break;
2813 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2814 break;
2816 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2817 break;
2819 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2820 break;
2822 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2823 break;
2825 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2826 break;
2828 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2829 break;
2830 default:
2831 break;
2832 }
2833 R__ASSERT(0); // We should never be here
2834 return TConfiguredAction();
2835}
2836
2837template <class Looper>
2839{
2840 switch (type) {
2841 // Read basic types.
2842 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2843 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2844 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2845 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2846 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2847 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2848 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2849 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2850 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2851 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2852 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2853 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2854 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2855 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2857 if (element->GetFactor() != 0) {
2858 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2859 } else {
2860 Int_t nbits = (Int_t)element->GetXmin();
2861 if (!nbits) nbits = 12;
2862 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2863 }
2864 break;
2865 }
2867 if (element->GetFactor() != 0) {
2868 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2869 } else {
2870 Int_t nbits = (Int_t)element->GetXmin();
2871 if (!nbits) {
2872 return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2873 } else {
2874 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2875 }
2876 }
2877 break;
2878 }
2879 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2880 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2881 // Streamer alltogether.
2882 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2883 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2887 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2888 case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2889
2890 // Conversions.
2892 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2893 break;
2895 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2896 break;
2898 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2899 break;
2901 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2902 break;
2904 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2905 break;
2907 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2908 break;
2910 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2911 break;
2913 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2914 break;
2916 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2917 break;
2919 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2920 break;
2922 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2923 break;
2925 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2926 break;
2928 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2929 break;
2931 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2932 break;
2934 if (element->GetFactor() != 0) {
2935 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2936 } else {
2937 Int_t nbits = (Int_t)element->GetXmin();
2938 if (!nbits) nbits = 12;
2939 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2940 }
2941 break;
2942 }
2944 if (element->GetFactor() != 0) {
2945 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2946 } else {
2947 Int_t nbits = (Int_t)element->GetXmin();
2948 if (!nbits) {
2949 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2950 } else {
2951 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2952 }
2953 }
2954 break;
2955 }
2956 default:
2957 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2958 break;
2959 }
2960 R__ASSERT(0); // We should never be here
2961 return TConfiguredAction();
2962}
2963
2964template <class Looper>
2966 switch (type) {
2967 // read basic types
2968 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2969 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2970 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2971 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2972 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2973 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2974 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2975 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2976 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2977 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2978 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2979 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2980 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2981 // the simple type missing are kBits and kCounter.
2982 default:
2983 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2984 }
2985 R__ASSERT(0); // We should never be here
2986 return TConfiguredAction();
2987}
2988
2989
2990////////////////////////////////////////////////////////////////////////////////
2991/// loop on the TStreamerElement list
2992/// regroup members with same type
2993/// Store predigested information into local arrays. This saves a huge amount
2994/// of time compared to an explicit iteration on all elements.
2995
2997{
2998 if (IsCompiled()) {
2999 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
3000 return;
3001 }
3003
3004 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
3005
3006 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
3008 fNdata = 0;
3009 fNfulldata = 0;
3010
3011 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
3012 if (fNumber < 0) {
3013 ++fgCount;
3014 fNumber = fgCount;
3015 }
3016 if (fNumber >= infos->GetSize()) {
3017 infos->AddAtAndExpand(this, fNumber);
3018 } else {
3019 if (!infos->At(fNumber)) {
3020 infos->AddAt(this, fNumber);
3021 }
3022 }
3023
3024 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3025
3026
3027 Int_t ndata = fElements->GetEntriesFast();
3028
3029
3032
3035
3038
3039 if (fReadText) fReadText->fActions.clear();
3040 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3041
3044
3047
3050
3051 if (fWriteText) fWriteText->fActions.clear();
3053
3054 if (!ndata) {
3055 // This may be the case for empty classes (e.g., TAtt3D).
3056 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3058 fSize = sizeof(TStreamerInfo*);
3059 }
3060 fComp = new TCompInfo[1];
3061 fCompFull = new TCompInfo*[1];
3062 fCompOpt = new TCompInfo*[1];
3063 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3064 SetIsCompiled();
3065 return;
3066 }
3067
3068 // At most half of the elements can be used to hold optimized versions.
3069 // We use the bottom to hold the optimized-into elements and the non-optimized elements
3070 // and the top to hold the original copy of the optimized out elements.
3071 fNslots = ndata + ndata/2 + 1;
3072 Int_t optiOut = 0;
3073
3074 fComp = new TCompInfo[fNslots];
3075 fCompFull = new TCompInfo*[ndata];
3076 fCompOpt = new TCompInfo*[ndata];
3077
3078 TStreamerElement* element;
3079 TStreamerElement* previous = 0;
3080 Int_t keep = -1;
3081 Int_t i;
3082
3083 if (!CanOptimize()) {
3085 }
3086
3087 Bool_t isOptimized = kFALSE;
3088 Bool_t previousOptimized = kFALSE;
3089
3090 for (i = 0; i < ndata; ++i) {
3091 element = (TStreamerElement*) fElements->At(i);
3092 if (!element) {
3093 break;
3094 }
3095
3096 Int_t asize = element->GetSize();
3097 if (element->GetArrayLength()) {
3098 asize /= element->GetArrayLength();
3099 }
3100 fComp[fNdata].fType = element->GetType();
3101 fComp[fNdata].fNewType = element->GetNewType();
3102 fComp[fNdata].fOffset = element->GetOffset();
3103 fComp[fNdata].fLength = element->GetArrayLength();
3104 fComp[fNdata].fElem = element;
3105 fComp[fNdata].fMethod = element->GetMethod();
3106 fComp[fNdata].fClass = element->GetClassPointer();
3107 fComp[fNdata].fNewClass = element->GetNewClass();
3109 fComp[fNdata].fStreamer = element->GetStreamer();
3110
3111 // try to group consecutive members of the same type
3113 && (keep >= 0)
3114 && (element->GetType() > 0)
3115 && (element->GetType() < 10)
3117 && (fComp[keep].fMethod == 0)
3118 && (element->GetArrayDim() == 0)
3119 && (fComp[keep].fType < kObject)
3120 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3121 && (element->GetType() == (fComp[keep].fType%kRegrouped))
3122 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3123 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3124 ((element->GetFactor() == previous->GetFactor())
3125 && (element->GetXmin() == previous->GetXmin())
3126 && (element->GetXmax() == previous->GetXmax())
3127 )
3128 )
3131 // kWholeObject and kDoNotDelete do not apply to numerical elements.
3132 )
3133 {
3134 if (!previousOptimized) {
3135 // The element was not yet optimized we first need to copy it into
3136 // the set of original copies.
3137 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3138 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3139 }
3140 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3141 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3142
3143 R__ASSERT( keep < (fNslots - optiOut) );
3144
3145 if (fComp[keep].fLength == 0) {
3146 fComp[keep].fLength++;
3147 }
3148 fComp[keep].fLength++;
3149 fComp[keep].fType = element->GetType() + kRegrouped;
3150 isOptimized = kTRUE;
3151 previousOptimized = kTRUE;
3152 } else if (element->GetType() < 0) {
3153
3154 // -- Deal with an ignored TObject base class.
3155 // Note: The only allowed negative value here is -1,
3156 // and signifies that Build() has found a TObject
3157 // base class and TClass::IgnoreTObjectStreamer() was
3158 // called. In this case the compiled version of the
3159 // elements omits the TObject base class element,
3160 // which has to be compensated for by TTree::Bronch()
3161 // when it is making branches for a split object.
3162 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3163 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3164 keep = -1;
3165 previousOptimized = kFALSE;
3166
3167 } else {
3168 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3169 if (fComp[fNdata].fNewType > 0) {
3170 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3171 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3172 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3176 ) {
3178 } else if (fComp[fNdata].fType != kCounter) {
3179 fComp[fNdata].fType += kConv;
3180 }
3181 } else {
3182 if (fComp[fNdata].fType == kCounter) {
3183 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3184 }
3185 fComp[fNdata].fType += kSkip;
3186 }
3187 }
3188 fCompOpt[fNdata] = &(fComp[fNdata]);
3190
3191 R__ASSERT( fNdata < (fNslots - optiOut) );
3192
3193 keep = fNdata;
3194 if (fComp[keep].fLength == 0) {
3195 fComp[keep].fLength = 1;
3196 }
3197 fNdata++;
3198 previousOptimized = kFALSE;
3199 }
3200 // The test 'fMethod[keep] == 0' fails to detect a variable size array
3201 // if the counter happens to have an offset of zero, so let's explicitly
3202 // prevent for here.
3203 if (element->HasCounter()) keep = -1;
3204 ++fNfulldata;
3205 previous = element;
3206 }
3207
3208 for (i = 0; i < fNdata; ++i) {
3209 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3210 continue;
3211 }
3214 }
3215 for (i = 0; i < fNfulldata; ++i) {
3216 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3217 continue;
3218 }
3223
3226 }
3227 ComputeSize();
3228
3229 fOptimized = isOptimized;
3230 SetIsCompiled();
3231
3232 if (gDebug > 0) {
3233 ls();
3234 }
3235}
3236
3237template <typename From>
3239{
3240 switch (newtype) {
3257 }
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// Add a read action for the given element.
3262
3264{
3265 TStreamerElement *element = compinfo->fElem;
3266
3267 if (element->TestBit(TStreamerElement::kWrite)) return;
3268
3269 switch (compinfo->fType) {
3270 // read basic types
3271 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3272 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3273 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3274 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3275 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3276 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3277 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3278 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3279 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3280 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3281 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3282 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3283 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3284 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3286 if (element->GetFactor() != 0) {
3287 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3288 } else {
3289 Int_t nbits = (Int_t)element->GetXmin();
3290 if (!nbits) nbits = 12;
3291 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3292 }
3293 break;
3294 }
3296 if (element->GetFactor() != 0) {
3297 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3298 } else {
3299 Int_t nbits = (Int_t)element->GetXmin();
3300 if (!nbits) {
3301 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3302 } else {
3303 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3304 }
3305 }
3306 break;
3307 }
3308 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3309 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3310 // Streamer alltogether.
3311 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3312 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3313 case TStreamerInfo::kSTL: {
3314 TClass *newClass = element->GetNewClass();
3315 TClass *oldClass = element->GetClassPointer();
3316 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3317
3318 if (element->GetArrayLength() <= 1) {
3319 if (fOldVersion<3){ // case of old TStreamerInfo
3320 if (newClass && newClass != oldClass) {
3321 if (element->GetStreamer()) {
3322 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3323 } else {
3324 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3325 }
3326 } else {
3327 if (element->GetStreamer()) {
3328 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3329 } else {
3330 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3331 }
3332 }
3333 } else {
3334 if (newClass && newClass != oldClass) {
3335 if (element->GetStreamer()) {
3336 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3337 } else {
3338 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3339 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3340 } else {
3341 switch (SelectLooper(*newClass->GetCollectionProxy())) {
3342 case kVectorLooper:
3343 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3344 break;
3345 case kAssociativeLooper:
3346 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3347 break;
3348 case kVectorPtrLooper:
3349 case kGenericLooper:
3350 default:
3351 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3352 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3353 break;
3354 }
3355 }
3356 }
3357 } else {
3358 if (element->GetStreamer()) {
3359 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3360 } else {
3361 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3362 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3363 } else {
3364 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3365 case kVectorLooper:
3366 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3367 break;
3368 case kAssociativeLooper:
3369 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3370 break;
3371 case kVectorPtrLooper:
3372 case kGenericLooper:
3373 default:
3374 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3375 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3376 break;
3377 }
3378 }
3379 }
3380 }
3381 }
3382 } else {
3383 if (fOldVersion<3){ // case of old TStreamerInfo
3384 if (newClass && newClass != oldClass) {
3385 if (element->GetStreamer()) {
3386 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3387 } else {
3388 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3389 }
3390 } else {
3391 if (element->GetStreamer()) {
3392 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3393 } else {
3394 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3395 }
3396 }
3397 } else {
3398 if (newClass && newClass != oldClass) {
3399 if (element->GetStreamer()) {
3400 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3401 } else {
3402 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3403 }
3404 } else {
3405 if (element->GetStreamer()) {
3406 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3407 } else {
3408 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3409 }
3410 }
3411 }
3412 }
3413 break;
3414 }
3415
3417 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3418 break;
3420 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3421 break;
3423 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3424 break;
3426 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3427 break;
3429 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3430 break;
3432 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3433 break;
3435 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3436 break;
3438 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3439 break;
3441 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3442 break;
3444 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3445 break;
3447 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3448 break;
3450 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3451 break;
3453 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3454 break;
3456 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3457 break;
3459 if (element->GetFactor() != 0) {
3460 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3461 } else {
3462 Int_t nbits = (Int_t)element->GetXmin();
3463 if (!nbits) nbits = 12;
3464 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3465 }
3466 break;
3467 }
3469 if (element->GetFactor() != 0) {
3470 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3471 } else {
3472 Int_t nbits = (Int_t)element->GetXmin();
3473 if (!nbits) {
3474 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3475 } else {
3476 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3477 }
3478 }
3479 break;
3480 }
3481 default:
3482 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3483 break;
3484 }
3485 if (element->TestBit(TStreamerElement::kCache)) {
3486 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3487 readSequence->fActions.pop_back();
3488 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3489 }
3490}
3491
3492////////////////////////////////////////////////////////////////////////////////
3493/// Add a read text action for the given element.
3494
3496{
3497 TStreamerElement *element = compinfo->fElem;
3498
3499 if (element->TestBit(TStreamerElement::kWrite))
3500 return;
3501
3502 Bool_t generic = kFALSE, isBase = kFALSE;
3503
3504 switch (compinfo->fType) {
3506 if (element->IsBase())
3507 isBase = kTRUE;
3508 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3509 else
3510 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3511 break;
3512
3514 if (element->IsBase())
3515 isBase = kTRUE;
3516 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3517 else
3518 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3519 break;
3520
3521 case TStreamerInfo::kObject: // Class derived from TObject
3522 case TStreamerInfo::kAny: // Class NOT derived from TObject
3525 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3526 break;
3527
3528 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3530 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3531 readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3532 break;
3533
3536 readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3537 break;
3538
3539 case TStreamerInfo::kBase: isBase = kTRUE; break;
3540
3542 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3543 break;
3544
3545 default: generic = kTRUE; break;
3546 }
3547
3548 if (isBase) {
3549 if (compinfo->fStreamer) {
3550 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3551 } else {
3552 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3553 }
3554 } else if (generic)
3555 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3556}
3557
3558////////////////////////////////////////////////////////////////////////////////
3559/// Add a read action for the given element.
3560/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3561
3563{
3564 TStreamerElement *element = compinfo->fElem;
3565
3566 if (element->TestBit(TStreamerElement::kWrite)) return;
3567
3568 if (element->TestBit(TStreamerElement::kCache)) {
3569 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3570 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3571 } else {
3572 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3573 }
3574}
3575
3576////////////////////////////////////////////////////////////////////////////////
3577
3579{
3580 TStreamerElement *element = compinfo->fElem;
3582 // Skip element cached for reading purposes.
3583 return;
3584 }
3585 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3586 // Skip artificial element used for reading purposes.
3587 return;
3588 }
3589 switch (compinfo->fType) {
3590 // write basic types
3591 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3592 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3593 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3594 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3595 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3596 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3597 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3598 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3599 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3600 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3601 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3602 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3603 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3604 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3605 /*case TStreamerInfo::kFloat16: {
3606 if (element->GetFactor() != 0) {
3607 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3608 } else {
3609 Int_t nbits = (Int_t)element->GetXmin();
3610 if (!nbits) nbits = 12;
3611 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3612 }
3613 break;
3614 } */
3615 /*case TStreamerInfo::kDouble32: {
3616 if (element->GetFactor() != 0) {
3617 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3618 } else {
3619 Int_t nbits = (Int_t)element->GetXmin();
3620 if (!nbits) {
3621 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3622 } else {
3623 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3624 }
3625 }
3626 break;
3627 } */
3628 //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3629 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3630 // Streamer alltogether.
3631 //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3632 //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3633 /*case TStreamerInfo::kSTL: {
3634 TClass *newClass = element->GetNewClass();
3635 TClass *oldClass = element->GetClassPointer();
3636 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3637
3638 if (element->GetArrayLength() <= 1) {
3639 if (newClass && newClass != oldClass) {
3640 if (element->GetStreamer()) {
3641 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3642 } else {
3643 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3644 }
3645 } else {
3646 if (element->GetStreamer()) {
3647 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3648 } else {
3649 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3650 }
3651 }
3652 } else {
3653 if (newClass && newClass != oldClass) {
3654 if (element->GetStreamer()) {
3655 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3656 } else {
3657 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3658 }
3659 } else {
3660 if (element->GetStreamer()) {
3661 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3662 } else {
3663 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3664 }
3665 }
3666 }
3667 break;
3668 } */
3669 default:
3670 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3671 break;
3672 }
3673#if defined(CDJ_NO_COMPILE)
3674 if (element->TestBit(TStreamerElement::kCache)) {
3675 TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3676 writeSequence->fActions.pop_back();
3677 writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3678 }
3679#endif
3680}
3681
3682////////////////////////////////////////////////////////////////////////////////
3683
3685{
3686 TStreamerElement *element = compinfo->fElem;
3688 // Skip element cached for reading purposes.
3689 return;
3690 }
3691 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3692 // Skip artificial element used for reading purposes.
3693 return;
3694 }
3695
3696 Bool_t generic = kFALSE, isBase = kFALSE;
3697
3698 switch (compinfo->fType) {
3699 // write basic types
3701 writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3702 break;
3704 writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3705 break;
3707 writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3708 break;
3710 writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3711 break;
3713 writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3714 break;
3716 writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3717 break;
3719 writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3720 break;
3722 writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3723 break;
3725 writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3726 break;
3728 writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3729 break;
3731 writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3732 break;
3734 writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3735 break;
3737 writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3738 break;
3739
3741 if (element->IsBase())
3742 isBase = kTRUE;
3743 else
3744 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3745 break;
3746
3748 if (element->IsBase())
3749 isBase = kTRUE;
3750 else
3751 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3752 break;
3753
3754 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3756 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3757 writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3758 break;
3759
3762 writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3763 break;
3764
3765 case TStreamerInfo::kBase: isBase = kTRUE; break;
3766
3768 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3769 break;
3770
3771 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3772 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3773 /*case TStreamerInfo::kFloat16: {
3774 if (element->GetFactor() != 0) {
3775 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3776 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3777 } else {
3778 Int_t nbits = (Int_t)element->GetXmin();
3779 if (!nbits) nbits = 12;
3780 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3781 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3782 }
3783 break;
3784 } */
3785 /*case TStreamerInfo::kDouble32: {
3786 if (element->GetFactor() != 0) {
3787 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3788 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3789 } else {
3790 Int_t nbits = (Int_t)element->GetXmin();
3791 if (!nbits) {
3792 writeSequence->AddAction( ConvertBasicType<float,double>, new
3793 TConfiguration(this,i,compinfo,compinfo->fOffset) );
3794 } else {
3795 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3796 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3797 }
3798 }
3799 break;
3800 } */
3801 // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3802 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3803 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3804 // Streamer alltogether.
3805 // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3806 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3807 // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3808 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3809 /*case TStreamerInfo::kSTL: {
3810 TClass *newClass = element->GetNewClass();
3811 TClass *oldClass = element->GetClassPointer();
3812 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3813
3814 if (element->GetArrayLength() <= 1) {
3815 if (newClass && newClass != oldClass) {
3816 if (element->GetStreamer()) {
3817 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3818 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3819 } else {
3820 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3821 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3822 }
3823 } else {
3824 if (element->GetStreamer()) {
3825 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3826 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3827 } else {
3828 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3829 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3830 }
3831 }
3832 } else {
3833 if (newClass && newClass != oldClass) {
3834 if (element->GetStreamer()) {
3835 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3836 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3837 } else {
3838 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3839 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3840 }
3841 } else {
3842 if (element->GetStreamer()) {
3843 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3844 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3845 } else {
3846 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3847 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3848 }
3849 }
3850 }
3851 break;
3852 } */
3853 default: generic = kTRUE; break;
3854 }
3855
3856 if (isBase) {
3857 if (compinfo->fStreamer) {
3858 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3859 } else {
3860 writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3861 }
3862
3863 } else
3864
3865 // use generic write action when special handling is not provided
3866 if (generic)
3867 writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3868
3869#if defined(CDJ_NO_COMPILE)
3870 if (element->TestBit(TStreamerElement::kCache)) {
3871 TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3872 writeSequence->fActions.pop_back();
3873 writeSequence->AddAction(UseCache,
3874 new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3875 }
3876#endif
3877}
3878
3879////////////////////////////////////////////////////////////////////////////////
3880/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3881
3883{
3884 TStreamerElement *element = compinfo->fElem;
3886 // Skip element cached for reading purposes.
3887 return;
3888 }
3889 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3890 // Skip artificial element used for reading purposes.
3891 return;
3892 }
3893
3894#if defined(CDJ_NO_COMPILE)
3895 if (element->TestBit(TStreamerElement::kCache)) {
3896 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3897 writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3898 } else {
3899 writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3900 }
3901#else
3902 writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3903#endif
3904
3905}
3906
3907////////////////////////////////////////////////////////////////////////////////
3908/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3909
3911{
3912 if (info == 0) {
3914 }
3915
3916 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3917
3918 UInt_t ndata = info->GetElements()->GetEntriesFast();
3920 if (IsDefaultVector(proxy))
3921 {
3922 if (proxy.HasPointers()) {
3923 // Instead of the creating a new one let's copy the one from the StreamerInfo.
3924 delete sequence;
3925
3926 sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3927
3928 return sequence;
3929 }
3930
3931 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3932 Long_t increment = proxy.GetIncrement();
3933 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3938 {
3939 Long_t increment = proxy.GetIncrement();
3940 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3941 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3942 } else {
3943 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);