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>
58 struct WithFactorMarker {
59 typedef From Value_t;
60 };
61
62 template <typename From>
63 struct NoFactorMarker {
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
137 struct TGenericConfiguration : TConfiguration {
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
149 struct TBitsConfiguration : TConfiguration {
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 {
159 TStreamerInfo *info = (TStreamerInfo*)fInfo;
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
175 if (fOffset != TVirtualStreamerInfo::kMissing)
176 fOffset += delta;
177 fObjectOffset = 0;
178 }
179
180 void SetMissing()
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;
193 TGenericConfiguration *conf = (TGenericConfiguration*)config;
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;
200 TGenericConfiguration *conf = (TGenericConfiguration*)config;
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
887 class TConfWithFactor : public TConfiguration {
888 // Configuration object for the Float16/Double32 where a factor has been specified.
889 public:
890 Double_t fFactor;
891 Double_t fXmin;
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
907 class TConfNoFactor : public TConfiguration {
908 // Configuration object for the Float16/Double32 where a factor has been specified.
909 public:
910 Int_t fNbits;
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() {
963 TVirtualCollectionProxy *proxy = fNewClass->GetCollectionProxy();
964 if (proxy) {
965 fCreateIterators = proxy->GetFunctionCreateIterators();
966 fCopyIterator = proxy->GetFunctionCopyIterator();
967 fDeleteIterator = proxy->GetFunctionDeleteIterator();
968 fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
969 }
970 }
971
972 public:
973 TClass *fOldClass; // Class of the content on file
974 TClass *fNewClass; // Class of the content in memory.
975 TMemberStreamer *fStreamer;
976 const char *fTypeName; // Type name of the member as typed by ther user.
977 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
978
983
984 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
985 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
986 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
987
988 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) :
989 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
990 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
991
992 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) :
993 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
994 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
995
996 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) :
997 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
998 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
999
1000 virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
1001 };
1002
1003 class TConfSTLWithFactor : public TConfigSTL {
1004 // Configuration object for the Float16/Double32 where a factor has been specified.
1005 public:
1006 Double_t fFactor;
1007 Double_t fXmin;
1008 TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin) : TConfigSTL(*orig),fFactor(factor),fXmin(xmin) {};
1009 virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
1010 };
1011
1012 class TConfSTLNoFactor : public TConfigSTL {
1013 // Configuration object for the Float16/Double32 where a factor has been specified.
1014 public:
1015 Int_t fNbits;
1016 TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1017 virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
1018 };
1019
1020 class TVectorLoopConfig : public TLoopConfiguration {
1021 // Base class of the Configurations used in member wise streaming.
1022 protected:
1023 public:
1024 Long_t fIncrement; // Either a value to increase the cursor by and
1025 public:
1026 TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1027 //virtual void PrintDebug(TBuffer &buffer, void *);
1028 virtual ~TVectorLoopConfig() {};
1029 void Print() const
1030 {
1031 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1032 }
1033
1034 void* GetFirstAddress(void *start, const void * /* end */) const
1035 {
1036 // Return the address of the first element of the collection.
1037
1038 return start;
1039 }
1040
1041 virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
1042 };
1043
1044 class TAssocLoopConfig : public TLoopConfiguration {
1045 // Base class of the Configurations used in member wise streaming.
1046 public:
1047 TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : TLoopConfiguration(proxy) {};
1048 //virtual void PrintDebug(TBuffer &buffer, void *);
1049 virtual ~TAssocLoopConfig() {};
1050 void Print() const
1051 {
1052 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1053 }
1054 virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
1055
1056 void* GetFirstAddress(void *start, const void * /* end */) const
1057 {
1058 // Return the address of the first element of the collection.
1059
1060 R__ASSERT(0);
1061// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1062// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1063// arr0 = genloopconfig->fNext(iter,end_collection);
1064// if (iter != &iterator[0]) {
1065// genloopconfig->fDeleteIterator(iter);
1066// }
1067 return start;
1068 }
1069 };
1070
1071 class TGenericLoopConfig : public TLoopConfiguration {
1072 // Configuration object for the generic case of member wise streaming looping.
1073 private:
1074 void Init(Bool_t read) {
1075 if (fProxy) {
1076 if (fProxy->HasPointers()) {
1080 } else {
1081 fNext = fProxy->GetFunctionNext(read);
1082 fCopyIterator = fProxy->GetFunctionCopyIterator(read);
1083 fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
1084 }
1085 }
1086 }
1087 public:
1091
1092 TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : TLoopConfiguration(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
1093 {
1094 Init(read);
1095 }
1096 virtual ~TGenericLoopConfig() {};
1097 void Print() const
1098 {
1099 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1100 }
1101 virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
1102
1103 void* GetFirstAddress(void *start_collection, const void *end_collection) const
1104 {
1105 // Return the address of the first element of the collection.
1106
1108 void *iter = fCopyIterator(&iterator,start_collection);
1109 void *arr0 = fNext(iter,end_collection);
1110 if (iter != &iterator[0]) {
1111 fDeleteIterator(iter);
1112 }
1113 return arr0;
1114 }
1115 };
1116
1118 {
1119 // Collection was saved member-wise
1120
1121 TConfigSTL *config = (TConfigSTL*)conf;
1123
1124 if( vers >= 8 ) {
1125
1126 TClass *oldClass = config->fOldClass;
1127
1128 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1129 if (!oldProxy) {
1130 // Missing information, broken file ... give up
1131 return;
1132 }
1133 TClass *valueClass = oldProxy->GetValueClass();
1134 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1135
1136 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1137 Int_t nobjects;
1138 buf.ReadInt(nobjects);
1139 void* alternative = oldProxy->Allocate(nobjects,true);
1140 if (nobjects) {
1141 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1142
1145 void *begin = &(startbuf[0]);
1146 void *end = &(endbuf[0]);
1147 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1148 // We can not get here with a split vector of pointer, so we can indeed assume
1149 // that actions->fConfiguration != null.
1150 buf.ApplySequence(*actions, begin, end);
1151 if (begin != &(startbuf[0])) {
1152 // assert(end != endbuf);
1153 config->fDeleteTwoIterators(begin,end);
1154 }
1155 }
1156 oldProxy->Commit(alternative);
1157
1158 } else {
1159
1160 TClass *oldClass = config->fOldClass;
1161
1162 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1163 if (!oldProxy) {
1164 // Missing information, broken file ... give up
1165 return;
1166 }
1167
1168 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1169 Int_t nobjects;
1170 buf.ReadInt(nobjects);
1171 void* env = oldProxy->Allocate(nobjects,true);
1172
1173 if (nobjects || vers < 7 ) {
1174 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1175 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1176
1177 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1178 }
1179 oldProxy->Commit(env);
1180 }
1181 }
1182
1184 {
1185 // Collection was saved member-wise
1186
1187 TConfigSTL *config = (TConfigSTL*)conf;
1189
1190 if( vers >= 8 ) {
1191
1192 TClass *oldClass = config->fOldClass;
1193
1194 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1195 if (!oldProxy) {
1196 // Missing information, broken file ... give up
1197 return;
1198 }
1199 TClass *valueClass = oldProxy->GetValueClass();
1200 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1201
1202 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1203
1204 int objectSize = oldClass->Size();
1205 char *obj = (char*)addr;
1206 char *endobj = obj + conf->fLength*objectSize;
1207
1208 for(; obj<endobj; obj+=objectSize) {
1209 Int_t nobjects;
1210 buf.ReadInt(nobjects);
1211 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1212 void* alternative = oldProxy->Allocate(nobjects,true);
1213 if (nobjects) {
1216 void *begin = &(startbuf[0]);
1217 void *end = &(endbuf[0]);
1218 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1219 // We can not get here with a split vector of pointer, so we can indeed assume
1220 // that actions->fConfiguration != null.
1221 buf.ApplySequence(*actions, begin, end);
1222 if (begin != &(startbuf[0])) {
1223 // assert(end != endbuf);
1224 config->fDeleteTwoIterators(begin,end);
1225 }
1226 }
1227 oldProxy->Commit(alternative);
1228 }
1229
1230 } else {
1231
1232 TClass *oldClass = config->fOldClass;
1233
1234 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1235 if (!oldProxy) {
1236 // Missing information, broken file ... give up
1237 return;
1238 }
1239
1240 int objectSize = oldClass->Size();
1241 char *obj = (char*)addr;
1242 char *endobj = obj + conf->fLength*objectSize;
1243
1244 for(; obj<endobj; obj+=objectSize) {
1245 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1246 Int_t nobjects;
1247 buf.ReadInt(nobjects);
1248 void* env = oldProxy->Allocate(nobjects,true);
1249
1250 if (nobjects || vers < 7 ) {
1251 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1252 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1253
1254 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1255 }
1256 oldProxy->Commit(env);
1257 }
1258 }
1259 }
1260
1262 {
1263 // Collection was saved member-wise
1264
1265 TConfigSTL *config = (TConfigSTL*)conf;
1266
1268
1269 TClass *newClass = config->fNewClass;
1270 TClass *oldClass = config->fOldClass;
1271
1272 if( vers < 8 ) {
1273 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1274 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1275 } else {
1276
1277 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1278
1279 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1280 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1281
1282 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1283 Int_t nobjects;
1284 buf.ReadInt(nobjects);
1285 void* alternative = newProxy->Allocate(nobjects,true);
1286 if (nobjects) {
1287 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1290 void *begin = &(startbuf[0]);
1291 void *end = &(endbuf[0]);
1292 config->fCreateIterators( alternative, &begin, &end, newProxy);
1293 // We can not get here with a split vector of pointer, so we can indeed assume
1294 // that actions->fConfiguration != null.
1295 buf.ApplySequence(*actions, begin, end);
1296 if (begin != &(startbuf[0])) {
1297 // assert(end != endbuf);
1298 config->fDeleteTwoIterators(begin,end);
1299 }
1300 }
1301 newProxy->Commit(alternative);
1302 }
1303 }
1304
1306 {
1307 // Collection was saved member-wise
1308
1309 TConfigSTL *config = (TConfigSTL*)conf;
1310
1312
1313 TClass *newClass = config->fNewClass;
1314 TClass *oldClass = config->fOldClass;
1315
1316 if( vers < 8 ) {
1317 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1318 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1319 } else {
1320
1321 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1322
1323 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1324 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1325
1326 int objectSize = newClass->Size();
1327 char *obj = (char*)addr;
1328 char *endobj = obj + conf->fLength*objectSize;
1329
1330 for(; obj<endobj; obj+=objectSize) {
1331 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1332 Int_t nobjects;
1333 buf.ReadInt(nobjects);
1334 void* alternative = newProxy->Allocate(nobjects,true);
1335 if (nobjects) {
1336 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1339 void *begin = &(startbuf[0]);
1340 void *end = &(endbuf[0]);
1341 config->fCreateIterators( alternative, &begin, &end, newProxy);
1342 // We can not get here with a split vector of pointer, so we can indeed assume
1343 // that actions->fConfiguration != null.
1344 buf.ApplySequence(*actions, begin, end);
1345 if (begin != &(startbuf[0])) {
1346 // assert(end != endbuf);
1347 config->fDeleteTwoIterators(begin,end);
1348 }
1349 }
1350 newProxy->Commit(alternative);
1351 }
1352 }
1353 }
1354
1355
1356 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1357 {
1358 TConfigSTL *config = (TConfigSTL*)conf;
1359 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1360 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1361 }
1362 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1363 {
1364 TConfigSTL *config = (TConfigSTL*)conf;
1365 (*config->fStreamer)(buf,addr,conf->fLength);
1366 }
1368 {
1369 // case of old TStreamerInfo
1370
1371 TConfigSTL *config = (TConfigSTL*)conf;
1372 // Backward compatibility. Some TStreamerElement's where without
1373 // Streamer but were not removed from element list
1374 if (config->fIsSTLBase || vers == 0) {
1375 buf.SetBufferOffset(start); //there is no byte count
1376 }
1377 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1378 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1379 }
1381 {
1382 // case of old TStreamerInfo
1383
1384 TConfigSTL *config = (TConfigSTL*)conf;
1385 // Backward compatibility. Some TStreamerElement's where without
1386 // Streamer but were not removed from element list
1387 if (config->fIsSTLBase || vers == 0) {
1388 buf.SetBufferOffset(start); //there is no byte count
1389 }
1390 (*config->fStreamer)(buf,addr,conf->fLength);
1391 }
1392
1393 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1394 void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1396 {
1397 TConfigSTL *config = (TConfigSTL*)conf;
1398 UInt_t start, count;
1399 Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1400 if ( vers & TBufferFile::kStreamedMemberWise ) {
1401 memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1402 } else {
1403 objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1404 }
1405 buf.CheckByteCount(start,count,config->fTypeName);
1406 return 0;
1407 }
1408
1409 template <typename From, typename To>
1410 struct ConvertBasicType {
1411 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1412 {
1413 // Simple conversion from a 'From' on disk to a 'To' in memory.
1414 From temp;
1415 buf >> temp;
1416 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1417 return 0;
1418 }
1419 };
1420
1421 template <typename To>
1422 struct ConvertBasicType<BitsMarker,To> {
1423 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1424 {
1425 // Simple conversion from a 'From' on disk to a 'To' in memory
1426 UInt_t temp;
1427 buf >> temp;
1428
1429 if ((temp & kIsReferenced) != 0) {
1430 HandleReferencedTObject(buf,addr,config);
1431 }
1432
1433 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1434 return 0;
1435 }
1436 };
1437
1438 template <typename From, typename To>
1439 struct ConvertBasicType<WithFactorMarker<From>,To> {
1440 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1441 {
1442 // Simple conversion from a 'From' on disk to a 'To' in memory.
1443 TConfWithFactor *conf = (TConfWithFactor *)config;
1444 From temp;
1445 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1446 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1447 return 0;
1448 }
1449 };
1450
1451 template <typename From, typename To>
1452 struct ConvertBasicType<NoFactorMarker<From>,To> {
1453 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1454 {
1455 // Simple conversion from a 'From' on disk to a 'To' in memory.
1456 TConfNoFactor *conf = (TConfNoFactor *)config;
1457 From temp;
1458 buf.ReadWithNbits(&temp, conf->fNbits);
1459 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1460 return 0;
1461 }
1462 };
1463
1464 class TConfigurationPushDataCache : public TConfiguration {
1465 // Configuration object for the PushDataCache case.
1466 public:
1467 TVirtualArray *fOnfileObject;
1468
1469 TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset) :
1470 TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1471 {}
1472
1473 virtual void Print() const {
1474 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1475 if (fOnfileObject)
1476 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1477 info->GetClass()->GetName(), fOffset);
1478 else
1479 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1480 info->GetClass()->GetName(), fOffset);
1481 }
1482 virtual void PrintDebug(TBuffer &buffer, void *object) const {
1483 if (gDebug > 1) {
1484 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1485 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1486 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1487
1488 }
1489 }
1490 };
1491
1493 {
1494 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1495 auto onfileObject = config->fOnfileObject;
1496
1497 // onfileObject->SetSize(1);
1498 b.PushDataCache( onfileObject );
1499
1500 return 0;
1501 }
1502
1503 Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1504 {
1505 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1506 auto onfileObject = config->fOnfileObject;
1507
1508 // onfileObject->SetSize(n);
1509 b.PushDataCache( onfileObject );
1510
1511 return 0;
1512 }
1513
1514 Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1515 {
1516 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1517 auto onfileObject = config->fOnfileObject;
1518
1519 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1520 UInt_t n = proxy->Size();
1521
1522 onfileObject->SetSize(n);
1523 b.PushDataCache( onfileObject );
1524
1525 return 0;
1526 }
1527
1529 {
1530 b.PopDataCache();
1531 return 0;
1532 }
1533
1534 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1535 {
1536 b.PopDataCache();
1537 return 0;
1538 }
1539
1541 {
1542 b.PopDataCache();
1543 return 0;
1544 }
1545
1546 class TConfigurationUseCache : public TConfiguration {
1547 // Configuration object for the UseCache case.
1548 public:
1549 TConfiguredAction fAction;
1550 Bool_t fNeedRepeat;
1551
1552 TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1553 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1554 virtual void PrintDebug(TBuffer &b, void *addr) const
1555 {
1556 if (gDebug > 1) {
1557 // Idea: We should print the name of the action function.
1558 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1559 TStreamerElement *aElement = fCompInfo->fElem;
1560 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1561 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1562 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1563 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1564 }
1565
1566 }
1567 virtual ~TConfigurationUseCache() {};
1568 virtual TConfiguration *Copy() {
1569 TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1570 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1571 return copy;
1572 }
1573 };
1574
1576 {
1577 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1578
1579 Int_t bufpos = b.Length();
1580 TVirtualArray *cached = b.PeekDataCache();
1581 if (cached==0) {
1582 TStreamerElement *aElement = conf->fCompInfo->fElem;
1583 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1584 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1585 char *ptr = (char*)addr;
1586 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1587 } else {
1588 config->fAction(b, (*cached)[0]);
1589 }
1590 // Idea: Factor out this 'if' to a UseCacheRepeat function
1591 if (config->fNeedRepeat) {
1592 b.SetBufferOffset(bufpos);
1593 }
1594 return 0;
1595 }
1596
1597 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1598 {
1599 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1600 Int_t bufpos = b.Length();
1601
1602 TVirtualArray *cached = b.PeekDataCache();
1603 if (cached==0) {
1604 TStreamerElement *aElement = config->fCompInfo->fElem;
1605 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1606 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1607 char *ptr = (char*)start;
1608 UInt_t n = (((void**)end)-((void**)start));
1609 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1610 } else {
1611 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1612 void *cached_start = (*cached)[0];
1613 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1614 config->fAction(b,cached_start,cached_end,&cached_config);
1615 }
1616 // Idea: Factor out this 'if' to a UseCacheRepeat function
1617 if (config->fNeedRepeat) {
1618 b.SetBufferOffset(bufpos);
1619 }
1620 return 0;
1621 }
1622
1623 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1624 {
1625 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1626
1627 Int_t bufpos = b.Length();
1628 TVirtualArray *cached = b.PeekDataCache();
1629 if (cached==0) {
1630 TStreamerElement *aElement = config->fCompInfo->fElem;
1631 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1632 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1633 char *ptr = (char*)start;
1634 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1635 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1636 } else {
1637 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1638 void *cached_start = (*cached)[0];
1639 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1640 config->fAction(b,cached_start,cached_end,&cached_config);
1641 }
1642 // Idea: Factor out this 'if' to a UseCacheRepeat function
1643 if (config->fNeedRepeat) {
1644 b.SetBufferOffset(bufpos);
1645 }
1646 return 0;
1647 }
1648
1650 {
1651 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1652
1653 Int_t bufpos = b.Length();
1654 TVirtualArray *cached = b.PeekDataCache();
1655 if (cached==0) {
1656 TStreamerElement *aElement = config->fCompInfo->fElem;
1657 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1658
1659 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1660 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1661 UInt_t n = proxy->Size();
1662 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1663 } else {
1664 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1665 void *cached_start = (*cached)[0];
1666 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1667 config->fAction(b,cached_start,cached_end,&cached_config);
1668 }
1669 // Idea: Factor out this 'if' to a UseCacheRepeat function
1670 if (config->fNeedRepeat) {
1671 b.SetBufferOffset(bufpos);
1672 }
1673 return 0;
1674 }
1675
1676 // Support for collections.
1677
1678 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1679 {
1680 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1681 return 0;
1682 }
1683
1684 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1685 {
1686 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1687 return 0;
1688 }
1689
1691
1693 {
1696 return kGenericLooper;
1697 else
1698 return kVectorLooper;
1703 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1704 return kAssociativeLooper;
1705 } else {
1706 return kGenericLooper;
1707 }
1708 }
1709
1710 struct VectorLooper {
1711
1712 template <typename T>
1713 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1714 {
1715 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1716 iter = (char*)iter + config->fOffset;
1717 end = (char*)end + config->fOffset;
1718 for(; iter != end; iter = (char*)iter + incr ) {
1719 T *x = (T*) ((char*) iter);
1720 buf >> *x;
1721 }
1722 return 0;
1723 }
1724
1725 template <typename From, typename To>
1726 struct ConvertBasicType {
1727 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1728 {
1729 // Simple conversion from a 'From' on disk to a 'To' in memory.
1730 From temp;
1731 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1732 iter = (char*)iter + config->fOffset;
1733 end = (char*)end + config->fOffset;
1734 for(; iter != end; iter = (char*)iter + incr ) {
1735 buf >> temp;
1736 *(To*)( ((char*)iter) ) = (To)temp;
1737 }
1738 return 0;
1739 }
1740 };
1741
1742 template <typename To>
1743 struct ConvertBasicType<BitsMarker,To> {
1744 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1745 {
1746 // Simple conversion from a 'From' on disk to a 'To' in memory.
1747 UInt_t temp;
1748 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1749 iter = (char*)iter + config->fOffset;
1750 end = (char*)end + config->fOffset;
1751 for(; iter != end; iter = (char*)iter + incr ) {
1752 buf >> temp;
1753
1754 if ((temp & kIsReferenced) != 0) {
1755 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1756 }
1757
1758 *(To*)( ((char*)iter) ) = (To)temp;
1759 }
1760 return 0;
1761 }
1762 };
1763
1764 template <typename From, typename To>
1765 struct ConvertBasicType<WithFactorMarker<From>,To> {
1766 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1767 {
1768 // Simple conversion from a 'From' on disk to a 'To' in memory.
1769 TConfWithFactor *conf = (TConfWithFactor *)config;
1770 From temp;
1771 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1772 iter = (char*)iter + config->fOffset;
1773 end = (char*)end + config->fOffset;
1774 for(; iter != end; iter = (char*)iter + incr ) {
1775 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1776 *(To*)( ((char*)iter) ) = (To)temp;
1777 }
1778 return 0;
1779 }
1780 };
1781
1782 template <typename From, typename To>
1783 struct ConvertBasicType<NoFactorMarker<From>,To> {
1784 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1785 {
1786 // Simple conversion from a 'From' on disk to a 'To' in memory.
1787 TConfNoFactor *conf = (TConfNoFactor *)config;
1788 From temp;
1789 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1790 iter = (char*)iter + config->fOffset;
1791 end = (char*)end + config->fOffset;
1792 for(; iter != end; iter = (char*)iter + incr ) {
1793 buf.ReadWithNbits(&temp, conf->fNbits);
1794 *(To*)( ((char*)iter) ) = (To)temp;
1795 }
1796 return 0;
1797 }
1798 };
1799
1800 template <typename T>
1801 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1802 {
1803 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1804 iter = (char*)iter + config->fOffset;
1805 end = (char*)end + config->fOffset;
1806 for(; iter != end; iter = (char*)iter + incr ) {
1807 T *x = (T*) ((char*) iter);
1808 buf << *x;
1809 }
1810 return 0;
1811 }
1812
1813 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1814 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1815 {
1816 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1817 //Idea: can we factor out the addition of fOffset
1818 // iter = (char*)iter + config->fOffset;
1819 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1820 iter_action(buf, iter, config);
1821 }
1822 return 0;
1823 }
1824
1825 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1826 {
1827 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1828 // punt.
1829
1830 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1831 UInt_t n = (((char*)end)-((char*)start))/incr;
1832 char **arrptr = new char*[n];
1833 UInt_t i = 0;
1834 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1835 arrptr[i] = (char*)iter;
1836 }
1837 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1838 delete [] arrptr;
1839
1840 // // Idea: need to cache this result!
1841 // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1842 // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1843 //
1844 // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1845 // *TClass *cle = aElement->GetNewBaseClass();
1846 // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1847 //
1848 // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1849 //
1850 // actions->ReadBuffer(b,start,end);
1851 // delete actions;
1852
1853 // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1854 // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1855 // {
1856 // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1857 //
1858 // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1859 // }
1860 return 0;
1861 }
1862
1863 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1864 {
1865 // Well the implementation is non trivial. For now punt.
1866
1867 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1868 UInt_t n = (((char*)end)-((char*)start))/incr;
1869 char **arrptr = new char*[n];
1870 UInt_t i = 0;
1871 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1872 arrptr[i] = (char*)iter;
1873 }
1874 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1875 delete [] arrptr;
1876 return 0;
1877 }
1878
1879 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1880 {
1881 // Well the implementation is non trivial. For now punt.
1882
1883 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1884 UInt_t n = (((char*)end)-((char*)start))/incr;
1885 char **arrptr = new char*[n];
1886 UInt_t i = 0;
1887 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1888 arrptr[i] = (char*)iter;
1889 }
1890 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1891 delete [] arrptr;
1892 return 0;
1893 }
1894
1895 template <typename T>
1896 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1897 {
1898 // Collection of numbers. Memberwise or not, it is all the same.
1899
1900 TConfigSTL *config = (TConfigSTL*)conf;
1901 UInt_t start, count;
1902 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1903
1904 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1905 Int_t nvalues;
1906 buf.ReadInt(nvalues);
1907 vec->resize(nvalues);
1908
1909#ifdef R__VISUAL_CPLUSPLUS
1910 if (nvalues <= 0) {
1911 buf.CheckByteCount(start,count,config->fTypeName);
1912 return 0;
1913 }
1914#endif
1915 T *begin = &(*vec->begin());
1916 buf.ReadFastArray(begin, nvalues);
1917
1918 buf.CheckByteCount(start,count,config->fTypeName);
1919 return 0;
1920 }
1921
1922 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1923 {
1924 // Collection of numbers. Memberwise or not, it is all the same.
1925
1926 TConfigSTL *config = (TConfigSTL*)conf;
1927 UInt_t start, count;
1928 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1929
1930 std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1931 Int_t nvalues;
1932 buf.ReadInt(nvalues);
1933 vec->resize(nvalues);
1934
1935 bool *items = new bool[nvalues];
1936 buf.ReadFastArray(items, nvalues);
1937 for(Int_t i = 0 ; i < nvalues; ++i) {
1938 (*vec)[i] = items[i];
1939 }
1940 delete [] items;
1941
1942 // We could avoid the call to ReadFastArray, and we could
1943 // the following, however this breaks TBufferXML ...
1944 // for(Int_t i = 0 ; i < nvalues; ++i) {
1945 // bool tmp; buf >> tmp;
1946 // (*vec)[i] = tmp;
1947 // }
1948
1949 buf.CheckByteCount(start,count,config->fTypeName);
1950 return 0;
1951 }
1952
1953 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1954 {
1955 // Collection of numbers. Memberwise or not, it is all the same.
1956
1957 TConfigSTL *config = (TConfigSTL*)conf;
1958 UInt_t start, count;
1959 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1960
1961 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1962 Int_t nvalues;
1963 buf.ReadInt(nvalues);
1964 vec->resize(nvalues);
1965
1966#ifdef R__VISUAL_CPLUSPLUS
1967 if (nvalues <= 0) {
1968 buf.CheckByteCount(start,count,config->fTypeName);
1969 return 0;
1970 }
1971#endif
1972 float *begin = &(*vec->begin());
1973 buf.ReadFastArrayFloat16(begin, nvalues);
1974
1975 buf.CheckByteCount(start,count,config->fTypeName);
1976 return 0;
1977 }
1978
1979 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1980 {
1981 // Collection of numbers. Memberwise or not, it is all the same.
1982
1983 TConfigSTL *config = (TConfigSTL*)conf;
1984 UInt_t start, count;
1985 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1986
1987 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1988 Int_t nvalues;
1989 buf.ReadInt(nvalues);
1990 vec->resize(nvalues);
1991
1992#ifdef R__VISUAL_CPLUSPLUS
1993 if (nvalues <= 0) {
1994 buf.CheckByteCount(start,count,config->fTypeName);
1995 return 0;
1996 }
1997#endif
1998 double *begin = &(*vec->begin());
1999 buf.ReadFastArrayDouble32(begin, nvalues);
2000
2001 buf.CheckByteCount(start,count,config->fTypeName);
2002 return 0;
2003 }
2004
2005 template <typename From, typename To>
2006 struct ConvertCollectionBasicType {
2007 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2008 {
2009 // Collection of numbers. Memberwise or not, it is all the same.
2010
2011 TConfigSTL *config = (TConfigSTL*)conf;
2012 UInt_t start, count;
2013 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2014
2015 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2016 Int_t nvalues;
2017 buf.ReadInt(nvalues);
2018 vec->resize(nvalues);
2019
2020 From *temp = new From[nvalues];
2021 buf.ReadFastArray(temp, nvalues);
2022 for(Int_t ind = 0; ind < nvalues; ++ind) {
2023 (*vec)[ind] = (To)temp[ind];
2024 }
2025 delete [] temp;
2026
2027 buf.CheckByteCount(start,count,config->fTypeName);
2028 return 0;
2029 }
2030 };
2031
2032 template <typename From, typename To>
2033 struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
2034 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2035 {
2036 // Collection of numbers. Memberwise or not, it is all the same.
2037
2038 TConfigSTL *config = (TConfigSTL*)conf;
2039 UInt_t start, count;
2040 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2041
2042 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2043 Int_t nvalues;
2044 buf.ReadInt(nvalues);
2045 vec->resize(nvalues);
2046
2047 From *temp = new From[nvalues];
2048 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2049 for(Int_t ind = 0; ind < nvalues; ++ind) {
2050 (*vec)[ind] = (To)temp[ind];
2051 }
2052 delete [] temp;
2053
2054 buf.CheckByteCount(start,count,config->fTypeName);
2055 return 0;
2056 }
2057 };
2058
2059 template <typename To>
2060 static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2061 {
2062 // Collection of numbers. Memberwise or not, it is all the same.
2063
2064 TConfigSTL *config = (TConfigSTL*)conf;
2065 UInt_t start, count;
2066 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2067
2068 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2069 Int_t nvalues;
2070 buf.ReadInt(nvalues);
2071 vec->resize(nvalues);
2072
2073 Double32_t *temp = new Double32_t[nvalues];
2074 buf.ReadFastArrayDouble32(temp, nvalues);
2075 for(Int_t ind = 0; ind < nvalues; ++ind) {
2076 (*vec)[ind] = (To)temp[ind];
2077 }
2078 delete [] temp;
2079
2080 buf.CheckByteCount(start,count,config->fTypeName);
2081 return 0;
2082 }
2083
2084 };
2085
2086 struct VectorPtrLooper {
2087
2088 template <typename T>
2089 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2090 {
2091 const Int_t offset = config->fOffset;
2092
2093 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2094 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2095 buf >> *x;
2096 }
2097 return 0;
2098 }
2099
2100 template <typename From, typename To>
2101 struct ConvertBasicType {
2102 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2103 {
2104 // Simple conversion from a 'From' on disk to a 'To' in memory.
2105 From temp;
2106 const Int_t offset = config->fOffset;
2107 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2108 buf >> temp;
2109 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2110 *x = (To)temp;
2111 }
2112 return 0;
2113 }
2114 };
2115
2116 template <typename To>
2117 struct ConvertBasicType<BitsMarker,To> {
2118 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2119 {
2120 // Simple conversion from a 'From' on disk to a 'To' in memory.
2121 UInt_t temp;
2122 const Int_t offset = config->fOffset;
2123 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2124 buf >> temp;
2125
2126 if ((temp & kIsReferenced) != 0) {
2127 HandleReferencedTObject(buf,*(void**)iter,config);
2128 }
2129
2130 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2131 *x = (To)temp;
2132 }
2133 return 0;
2134 }
2135 };
2136
2137 template <typename From, typename To>
2138 struct ConvertBasicType<WithFactorMarker<From>,To> {
2139 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2140 {
2141 // Simple conversion from a 'From' on disk to a 'To' in memory.
2142 TConfWithFactor *conf = (TConfWithFactor *)config;
2143 From temp;
2144 const Int_t offset = config->fOffset;
2145 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2146 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2147 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2148 *x = (To)temp;
2149 }
2150 return 0;
2151 }
2152 };
2153
2154 template <typename From, typename To>
2155 struct ConvertBasicType<NoFactorMarker<From>,To> {
2156 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2157 {
2158 // Simple conversion from a 'From' on disk to a 'To' in memory.
2159 TConfNoFactor *conf = (TConfNoFactor *)config;
2160 From temp;
2161 const Int_t offset = config->fOffset;
2162 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2163 buf.ReadWithNbits(&temp, conf->fNbits);
2164 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2165 *x = (To)temp;
2166 }
2167 return 0;
2168 }
2169 };
2170
2171 template <typename T>
2172 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2173 {
2174 const Int_t offset = config->fOffset;
2175
2176 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2177 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2178 buf << *x;
2179 }
2180 return 0;
2181 }
2182
2183 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2184 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2185 {
2186 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2187 action(buf, *(void**)iter, config);
2188 }
2189 return 0;
2190 }
2191
2192 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2193 {
2194 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2195 // punt.
2196
2197 return GenericRead(buf,start,end,config);
2198 }
2199
2200 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2201 {
2202 Int_t n = ( ((void**)end) - ((void**)iter) );
2203 char **arr = (char**)iter;
2204 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2205 }
2206
2207 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2208 {
2209 Int_t n = ( ((void**)end) - ((void**)iter) );
2210 char **arr = (char**)iter;
2211 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2212 }
2213
2214 };
2215
2216 struct AssociativeLooper {
2217
2218 template <typename T>
2219 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2220 {
2221 buf.ReadFastArray((T*)addr, nvalues);
2222 }
2223
2224 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2225 {
2226 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2227 }
2228
2229 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2230 {
2231 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2232 }
2233
2234 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2235 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2236 {
2237 // Collection of numbers. Memberwise or not, it is all the same.
2238
2239 TConfigSTL *config = (TConfigSTL*)conf;
2240 UInt_t start, count;
2241 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2242
2243 TClass *newClass = config->fNewClass;
2244 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2245 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2246
2247 Int_t nvalues;
2248 buf.ReadInt(nvalues);
2249 void* alternative = newProxy->Allocate(nvalues,true);
2250 if (nvalues) {
2253 void *begin = &(startbuf[0]);
2254 void *end = &(endbuf[0]);
2255 config->fCreateIterators(alternative, &begin, &end, newProxy);
2256 // We can not get here with a split vector of pointer, so we can indeed assume
2257 // that actions->fConfiguration != null.
2258
2259 action(buf,begin,nvalues);
2260
2261 if (begin != &(startbuf[0])) {
2262 // assert(end != endbuf);
2263 config->fDeleteTwoIterators(begin,end);
2264 }
2265 }
2266 newProxy->Commit(alternative);
2267
2268 buf.CheckByteCount(start,count,config->fTypeName);
2269 return 0;
2270 }
2271
2272 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2273 {
2274 return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2275 }
2276
2277 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2278 {
2279 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2280 }
2281
2282 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2283 {
2284 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2285 }
2286
2287 template <typename T>
2288 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2289 {
2290 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2291 }
2292
2293 template <typename From, typename To>
2294 struct ConvertRead {
2295 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2296 {
2297 From *temp = new From[nvalues];
2298 buf.ReadFastArray(temp, nvalues);
2299 To *vec = (To*)addr;
2300 for(Int_t ind = 0; ind < nvalues; ++ind) {
2301 vec[ind] = (To)temp[ind];
2302 }
2303 delete [] temp;
2304 }
2305 };
2306
2307 template <typename From, typename To>
2308 struct ConvertRead<NoFactorMarker<From>,To> {
2309 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2310 {
2311 From *temp = new From[nvalues];
2312 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2313 To *vec = (To*)addr;
2314 for(Int_t ind = 0; ind < nvalues; ++ind) {
2315 vec[ind] = (To)temp[ind];
2316 }
2317 delete [] temp;
2318 }
2319 };
2320
2321 template <typename From, typename To>
2322 struct ConvertRead<WithFactorMarker<From>,To> {
2323 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2324 {
2325 From *temp = new From[nvalues];
2326 double factor,min; // needs to be initialized.
2327 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2328 To *vec = (To*)addr;
2329 for(Int_t ind = 0; ind < nvalues; ++ind) {
2330 vec[ind] = (To)temp[ind];
2331 }
2332 delete [] temp;
2333 }
2334 };
2335
2336 template <typename From, typename To>
2337 struct ConvertCollectionBasicType {
2338 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2339 {
2340 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2341 }
2342 };
2343
2344 };
2345
2346 struct GenericLooper {
2347
2348 template <typename T>
2349 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2350 {
2351 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2352
2353 Next_t next = loopconfig->fNext;
2354 const Int_t offset = config->fOffset;
2355
2357 void *iter = loopconfig->fCopyIterator(iterator,start);
2358 void *addr;
2359 while( (addr = next(iter,end)) ) {
2360 T *x = (T*)( ((char*)addr) + offset );
2361 buf >> *x;
2362 }
2363 if (iter != &iterator[0]) {
2364 loopconfig->fDeleteIterator(iter);
2365 }
2366 return 0;
2367 }
2368
2369 template <typename T>
2370 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2371 {
2372 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2373
2374 Next_t next = loopconfig->fNext;
2375 const Int_t offset = config->fOffset;
2376
2378 void *iter = loopconfig->fCopyIterator(iterator,start);
2379 void *addr;
2380 while( (addr = next(iter,end)) ) {
2381 T *x = (T*)( ((char*)addr) + offset );
2382 buf << *x;
2383 }
2384 if (iter != &iterator[0]) {
2385 loopconfig->fDeleteIterator(iter);
2386 }
2387 return 0;
2388 }
2389
2390 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2391 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2392 {
2393 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2394
2395 // const Int_t offset = config->fOffset;
2396 Next_t next = loopconfig->fNext;
2397
2399 void *iter = loopconfig->fCopyIterator(&iterator,start);
2400 void *addr;
2401 while( (addr = next(iter,end)) ) {
2402 iter_action(buf, addr, config);
2403 }
2404 if (iter != &iterator[0]) {
2405 loopconfig->fDeleteIterator(iter);
2406 }
2407 return 0;
2408 }
2409
2410 template <typename From, typename To>
2411 struct Generic {
2412 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2413 {
2414 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2415
2416 const Int_t offset = config->fOffset;
2417 Next_t next = loopconfig->fNext;
2418
2420 void *iter = loopconfig->fCopyIterator(&iterator,start);
2421 void *addr;
2422 while( (addr = next(iter,end)) ) {
2423 To *x = (To*)( ((char*)addr) + offset );
2424 *x = (To)(*items);
2425 ++items;
2426 }
2427 if (iter != &iterator[0]) {
2428 loopconfig->fDeleteIterator(iter);
2429 }
2430 }
2431 };
2432
2433 template <typename From, typename To>
2434 struct Numeric {
2435 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2436 {
2437 // The difference with ConvertAction is that we can modify the start
2438 // iterator and skip the copy. We also never have an offset.
2439
2440 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2441 Next_t next = loopconfig->fNext;
2442
2443 void *iter = start;
2444 void *addr;
2445 while( (addr = next(iter,end)) ) {
2446 To *x = (To*)(addr);
2447 *x = (To)(*items);
2448 ++items;
2449 }
2450 }
2451 };
2452
2453 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2454 struct ConvertBasicType {
2455 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2456 {
2457 // Simple conversion from a 'From' on disk to a 'To' in memory.
2458
2459 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2460 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2461 Int_t nvalues = proxy->Size();
2462
2463 From *items = new From[nvalues];
2464 buf.ReadFastArray(items, nvalues);
2465 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2466 delete [] items;
2467 return 0;
2468 }
2469 };
2470
2471 template <typename To>
2472 struct ConvertBasicType<BitsMarker, To, Generic> {
2473 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2474 {
2475 // Simple conversion from a 'From' on disk to a 'To' in memory.
2476
2477 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2478 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2479 Int_t nvalues = proxy->Size();
2480
2481 UInt_t *items_storage = new UInt_t[nvalues];
2482 UInt_t *items = items_storage;
2483
2484 const Int_t offset = config->fOffset;
2485 Next_t next = loopconfig->fNext;
2486
2488 void *iter = loopconfig->fCopyIterator(&iterator,start);
2489 void *addr;
2490 while( (addr = next(iter,end)) ) {
2491 buf >> (*items);
2492 if (((*items) & kIsReferenced) != 0) {
2493 HandleReferencedTObject(buf, addr, config);
2494 }
2495 To *x = (To*)( ((char*)addr) + offset );
2496 *x = (To)(*items);
2497 ++items;
2498 }
2499 if (iter != &iterator[0]) {
2500 loopconfig->fDeleteIterator(iter);
2501 }
2502
2503 delete [] items_storage;
2504 return 0;
2505 }
2506 };
2507
2508 template <typename From, typename To, template <typename F, typename T> class Converter >
2509 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2510 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2511 {
2512 // Simple conversion from a 'From' on disk to a 'To' in memory.
2513
2514 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2515 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2516 Int_t nvalues = proxy->Size();
2517
2518 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2519
2520 From *items = new From[nvalues];
2521 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2522 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2523 delete [] items;
2524 return 0;
2525 }
2526 };
2527
2528 template <typename From, typename To, template <typename F, typename T> class Converter >
2529 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2530 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2531 {
2532 // Simple conversion from a 'From' on disk to a 'To' in memory.
2533
2534 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2535 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2536 Int_t nvalues = proxy->Size();
2537
2538 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2539
2540 From *items = new From[nvalues];
2541 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2542 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2543 delete [] items;
2544 return 0;
2545 }
2546 };
2547
2548 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2549 {
2550 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2551 // punt.
2552
2553 return GenericRead(buf,start,end,loopconfig, config);
2554 }
2555
2556 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2557 {
2558 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2559 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2560 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2561 }
2562
2563 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2564 {
2565 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2566 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2567 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2568 }
2569
2570 template <typename T>
2571 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2572 {
2573 buf >> *(T*)addr;
2574 }
2575
2576 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2577 {
2578 buf.ReadWithNbits((float*)addr,12);
2579 }
2580
2581 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2582 {
2583 //we read a float and convert it to double
2584 Float_t afloat;
2585 buf >> afloat;
2586 *(double*)addr = (Double_t)afloat;
2587 }
2588
2589 template <typename ActionHolder>
2590 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2591 {
2592 // Collection of numbers. Memberwise or not, it is all the same.
2593
2594 TConfigSTL *config = (TConfigSTL*)conf;
2595 UInt_t start, count;
2596 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2597
2598 TClass *newClass = config->fNewClass;
2599 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2600 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2601
2602 Int_t nvalues;
2603 buf.ReadInt(nvalues);
2604 void* alternative = newProxy->Allocate(nvalues,true);
2605 if (nvalues) {
2608 void *begin = &(startbuf[0]);
2609 void *end = &(endbuf[0]);
2610 config->fCreateIterators(alternative, &begin, &end, newProxy);
2611 // We can not get here with a split vector of pointer, so we can indeed assume
2612 // that actions->fConfiguration != null.
2613
2614 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2615 ActionHolder::Action(buf,begin,end,&loopconf,config);
2616
2617 if (begin != &(startbuf[0])) {
2618 // assert(end != endbuf);
2619 config->fDeleteTwoIterators(begin,end);
2620 }
2621 }
2622 newProxy->Commit(alternative);
2623
2624 buf.CheckByteCount(start,count,config->fTypeName);
2625 return 0;
2626 }
2627
2628 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2629 {
2630 return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2631 }
2632
2633 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2634 {
2635 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2636 }
2637
2638 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2639 {
2640 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2641 // Could also use:
2642 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2643 }
2644
2645 template <typename T>
2646 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2647 {
2648 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2649 }
2650
2651 template <typename From, typename To>
2652 struct ConvertCollectionBasicType {
2653 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2654 {
2655 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2656 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2657 }
2658 };
2659
2660 };
2661}
2662
2663template <typename Looper, typename From>
2665{
2666 switch (newtype) {
2667 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2668 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2669 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2670 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2671 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2672 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2673 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2674 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2675 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2676 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2677 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2678 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2679 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2680 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2681 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2682 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2683 default:
2684 return TConfiguredAction( Looper::GenericRead, conf );
2685 break;
2686 }
2687 R__ASSERT(0); // We should never be here
2688 return TConfiguredAction();
2689}
2690
2691template <class Looper>
2693{
2694 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2695
2696 switch (type) {
2697 // Read basic types.
2698 case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2699 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2700 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2701 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2702 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2703 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2704 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2705 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2706 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2707 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2708 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2709 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2710 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2711 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2713 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2714 delete conf;
2715 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2716 // if (element->GetFactor() != 0) {
2717 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2718 // } else {
2719 // Int_t nbits = (Int_t)element->GetXmin();
2720 // if (!nbits) nbits = 12;
2721 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2722 // }
2723 break;
2724 }
2726 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2727 delete conf;
2728 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2729 // if (element->GetFactor() != 0) {
2730 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2731 // } else {
2732 // Int_t nbits = (Int_t)element->GetXmin();
2733 // if (!nbits) {
2734 // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2735 // } else {
2736 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2737 // }
2738 // }
2739 break;
2740 }
2741 }
2742 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2743 R__ASSERT(0); // We should never be here
2744 return TConfiguredAction();
2745}
2746
2747template <typename Looper, typename From>
2749{
2750 switch (newtype) {
2751 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2752 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2753 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2754 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2755 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2756 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2757 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2758 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2759 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2760 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2761 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2762 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2763 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2764 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2765 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2766 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2767 default:
2768 break;
2769 }
2770 R__ASSERT(0); // We should never be here
2771 return TConfiguredAction();
2772}
2773
2774template <typename Looper>
2776{
2777 switch (oldtype) {
2779 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2780 break;
2782 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2783 break;
2785 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2786 break;
2788 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2789 break;
2791 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2792 break;
2794 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2795 break;
2797 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2798 break;
2800 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2801 break;
2803 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2804 break;
2806 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2807 break;
2809 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2810 break;
2812 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2813 break;
2815 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2816 break;
2818 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2819 break;
2821 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2822 break;
2824 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2825 break;
2826 default:
2827 break;
2828 }
2829 R__ASSERT(0); // We should never be here
2830 return TConfiguredAction();
2831}
2832
2833template <class Looper>
2835{
2836 switch (type) {
2837 // Read basic types.
2838 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2839 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2840 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2841 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2842 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2843 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2844 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2845 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2846 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2847 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2848 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2849 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2850 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2851 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2853 if (element->GetFactor() != 0) {
2854 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2855 } else {
2856 Int_t nbits = (Int_t)element->GetXmin();
2857 if (!nbits) nbits = 12;
2858 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2859 }
2860 break;
2861 }
2863 if (element->GetFactor() != 0) {
2864 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2865 } else {
2866 Int_t nbits = (Int_t)element->GetXmin();
2867 if (!nbits) {
2868 return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2869 } else {
2870 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2871 }
2872 }
2873 break;
2874 }
2875 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2876 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2877 // Streamer alltogether.
2878 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2879 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2883 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2884 case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2885
2886 // Conversions.
2888 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2889 break;
2891 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2892 break;
2894 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2895 break;
2897 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2898 break;
2900 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2901 break;
2903 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2904 break;
2906 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2907 break;
2909 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2910 break;
2912 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2913 break;
2915 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2916 break;
2918 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2919 break;
2921 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2922 break;
2924 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2925 break;
2927 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2928 break;
2930 if (element->GetFactor() != 0) {
2931 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2932 } else {
2933 Int_t nbits = (Int_t)element->GetXmin();
2934 if (!nbits) nbits = 12;
2935 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2936 }
2937 break;
2938 }
2940 if (element->GetFactor() != 0) {
2941 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2942 } else {
2943 Int_t nbits = (Int_t)element->GetXmin();
2944 if (!nbits) {
2945 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2946 } else {
2947 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2948 }
2949 }
2950 break;
2951 }
2952 default:
2953 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2954 break;
2955 }
2956 R__ASSERT(0); // We should never be here
2957 return TConfiguredAction();
2958}
2959
2960template <class Looper>
2962 switch (type) {
2963 // read basic types
2964 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2965 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2966 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2967 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2968 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2969 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2970 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2971 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2972 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2973 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2974 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2975 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2976 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2977 // the simple type missing are kBits and kCounter.
2978 default:
2979 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2980 }
2981 R__ASSERT(0); // We should never be here
2982 return TConfiguredAction();
2983}
2984
2985
2986////////////////////////////////////////////////////////////////////////////////
2987/// loop on the TStreamerElement list
2988/// regroup members with same type
2989/// Store predigested information into local arrays. This saves a huge amount
2990/// of time compared to an explicit iteration on all elements.
2991
2993{
2994 if (IsCompiled()) {
2995 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
2996 return;
2997 }
2999
3000 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
3001
3002 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
3004 fNdata = 0;
3005 fNfulldata = 0;
3006
3007 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
3008 if (fNumber < 0) {
3009 ++fgCount;
3010 fNumber = fgCount;
3011 }
3012 if (fNumber >= infos->GetSize()) {
3013 infos->AddAtAndExpand(this, fNumber);
3014 } else {
3015 if (!infos->At(fNumber)) {
3016 infos->AddAt(this, fNumber);
3017 }
3018 }
3019
3020 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3021
3022
3023 Int_t ndata = fElements->GetEntriesFast();
3024
3025
3028
3031
3034
3035 if (fReadText) fReadText->fActions.clear();
3036 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3037
3040
3043
3046
3047 if (fWriteText) fWriteText->fActions.clear();
3049
3050 if (!ndata) {
3051 // This may be the case for empty classes (e.g., TAtt3D).
3052 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3054 fSize = sizeof(TStreamerInfo*);
3055 }
3056 fComp = new TCompInfo[1];
3057 fCompFull = new TCompInfo*[1];
3058 fCompOpt = new TCompInfo*[1];
3059 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3060 SetIsCompiled();
3061 return;
3062 }
3063
3064 // At most half of the elements can be used to hold optimized versions.
3065 // We use the bottom to hold the optimized-into elements and the non-optimized elements
3066 // and the top to hold the original copy of the optimized out elements.
3067 fNslots = ndata + ndata/2 + 1;
3068 Int_t optiOut = 0;
3069
3070 fComp = new TCompInfo[fNslots];
3071 fCompFull = new TCompInfo*[ndata];
3072 fCompOpt = new TCompInfo*[ndata];
3073
3074 TStreamerElement* element;
3075 TStreamerElement* previous = 0;
3076 Int_t keep = -1;
3077 Int_t i;
3078
3079 if (!CanOptimize()) {
3081 }
3082
3083 Bool_t isOptimized = kFALSE;
3084 Bool_t previousOptimized = kFALSE;
3085
3086 for (i = 0; i < ndata; ++i) {
3087 element = (TStreamerElement*) fElements->At(i);
3088 if (!element) {
3089 break;
3090 }
3091
3092 Int_t asize = element->GetSize();
3093 if (element->GetArrayLength()) {
3094 asize /= element->GetArrayLength();
3095 }
3096 fComp[fNdata].fType = element->GetType();
3097 fComp[fNdata].fNewType = element->GetNewType();
3098 fComp[fNdata].fOffset = element->GetOffset();
3099 fComp[fNdata].fLength = element->GetArrayLength();
3100 fComp[fNdata].fElem = element;
3101 fComp[fNdata].fMethod = element->GetMethod();
3102 fComp[fNdata].fClass = element->GetClassPointer();
3103 fComp[fNdata].fNewClass = element->GetNewClass();
3105 fComp[fNdata].fStreamer = element->GetStreamer();
3106
3107 // try to group consecutive members of the same type
3109 && (keep >= 0)
3110 && (element->GetType() > 0)
3111 && (element->GetType() < 10)
3113 && (fComp[keep].fMethod == 0)
3114 && (element->GetArrayDim() == 0)
3115 && (fComp[keep].fType < kObject)
3116 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3117 && (element->GetType() == (fComp[keep].fType%kRegrouped))
3118 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3119 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3120 ((element->GetFactor() == previous->GetFactor())
3121 && (element->GetXmin() == previous->GetXmin())
3122 && (element->GetXmax() == previous->GetXmax())
3123 )
3124 )
3127 // kWholeObject and kDoNotDelete do not apply to numerical elements.
3128 )
3129 {
3130 if (!previousOptimized) {
3131 // The element was not yet optimized we first need to copy it into
3132 // the set of original copies.
3133 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3134 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3135 }
3136 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3137 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3138
3139 R__ASSERT( keep < (fNslots - optiOut) );
3140
3141 if (fComp[keep].fLength == 0) {
3142 fComp[keep].fLength++;
3143 }
3144 fComp[keep].fLength++;
3145 fComp[keep].fType = element->GetType() + kRegrouped;
3146 isOptimized = kTRUE;
3147 previousOptimized = kTRUE;
3148 } else if (element->GetType() < 0) {
3149
3150 // -- Deal with an ignored TObject base class.
3151 // Note: The only allowed negative value here is -1,
3152 // and signifies that Build() has found a TObject
3153 // base class and TClass::IgnoreTObjectStreamer() was
3154 // called. In this case the compiled version of the
3155 // elements omits the TObject base class element,
3156 // which has to be compensated for by TTree::Bronch()
3157 // when it is making branches for a split object.
3158 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3159 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3160 keep = -1;
3161 previousOptimized = kFALSE;
3162
3163 } else {
3164 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3165 if (fComp[fNdata].fNewType > 0) {
3166 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3167 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3168 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3172 ) {
3174 } else if (fComp[fNdata].fType != kCounter) {
3175 fComp[fNdata].fType += kConv;
3176 }
3177 } else {
3178 if (fComp[fNdata].fType == kCounter) {
3179 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3180 }
3181 fComp[fNdata].fType += kSkip;
3182 }
3183 }
3184 fCompOpt[fNdata] = &(fComp[fNdata]);
3186
3187 R__ASSERT( fNdata < (fNslots - optiOut) );
3188
3189 keep = fNdata;
3190 if (fComp[keep].fLength == 0) {
3191 fComp[keep].fLength = 1;
3192 }
3193 fNdata++;
3194 previousOptimized = kFALSE;
3195 }
3196 // The test 'fMethod[keep] == 0' fails to detect a variable size array
3197 // if the counter happens to have an offset of zero, so let's explicitly
3198 // prevent for here.
3199 if (element->HasCounter()) keep = -1;
3200 ++fNfulldata;
3201 previous = element;
3202 }
3203
3204 for (i = 0; i < fNdata; ++i) {
3205 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3206 continue;
3207 }
3210 }
3211 for (i = 0; i < fNfulldata; ++i) {
3212 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3213 continue;
3214 }
3219
3222 }
3223 ComputeSize();
3224
3225 fOptimized = isOptimized;
3226 SetIsCompiled();
3227
3228 if (gDebug > 0) {
3229 ls();
3230 }
3231}
3232
3233template <typename From>
3235{
3236 switch (newtype) {
3237 case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
3238 case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
3239 case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
3240 case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
3241 case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
3242 case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
3243 case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3244 case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3245 case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3246 case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3247 case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
3248 case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
3249 case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3250 case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
3251 case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
3252 case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3253 }
3254}
3255
3256////////////////////////////////////////////////////////////////////////////////
3257/// Add a read action for the given element.
3258
3260{
3261 TStreamerElement *element = compinfo->fElem;
3262
3263 if (element->TestBit(TStreamerElement::kWrite)) return;
3264
3265 switch (compinfo->fType) {
3266 // read basic types
3267 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3268 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3269 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3270 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3271 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3272 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3273 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3274 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3275 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3276 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3277 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3278 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3279 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3280 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3282 if (element->GetFactor() != 0) {
3283 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3284 } else {
3285 Int_t nbits = (Int_t)element->GetXmin();
3286 if (!nbits) nbits = 12;
3287 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3288 }
3289 break;
3290 }
3292 if (element->GetFactor() != 0) {
3293 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3294 } else {
3295 Int_t nbits = (Int_t)element->GetXmin();
3296 if (!nbits) {
3297 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3298 } else {
3299 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3300 }
3301 }
3302 break;
3303 }
3304 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3305 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3306 // Streamer alltogether.
3307 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3308 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3309 case TStreamerInfo::kSTL: {
3310 TClass *newClass = element->GetNewClass();
3311 TClass *oldClass = element->GetClassPointer();
3312 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3313
3314 if (element->GetArrayLength() <= 1) {
3315 if (fOldVersion<3){ // case of old TStreamerInfo
3316 if (newClass && newClass != oldClass) {
3317 if (element->GetStreamer()) {
3318 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3319 } else {
3320 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3321 }
3322 } else {
3323 if (element->GetStreamer()) {
3324 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3325 } else {
3326 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3327 }
3328 }
3329 } else {
3330 if (newClass && newClass != oldClass) {
3331 if (element->GetStreamer()) {
3332 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3333 } else {
3334 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3335 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3336 } else {
3337 switch (SelectLooper(*newClass->GetCollectionProxy())) {
3338 case kVectorLooper:
3339 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3340 break;
3341 case kAssociativeLooper:
3342 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3343 break;
3344 case kVectorPtrLooper:
3345 case kGenericLooper:
3346 default:
3347 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3348 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3349 break;
3350 }
3351 }
3352 }
3353 } else {
3354 if (element->GetStreamer()) {
3355 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3356 } else {
3357 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3358 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3359 } else {
3360 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3361 case kVectorLooper:
3362 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3363 break;
3364 case kAssociativeLooper:
3365 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3366 break;
3367 case kVectorPtrLooper:
3368 case kGenericLooper:
3369 default:
3370 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3371 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3372 break;
3373 }
3374 }
3375 }
3376 }
3377 }
3378 } else {
3379 if (fOldVersion<3){ // case of old TStreamerInfo
3380 if (newClass && newClass != oldClass) {
3381 if (element->GetStreamer()) {
3382 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3383 } else {
3384 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3385 }
3386 } else {
3387 if (element->GetStreamer()) {
3388 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3389 } else {
3390 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3391 }
3392 }
3393 } else {
3394 if (newClass && newClass != oldClass) {
3395 if (element->GetStreamer()) {
3396 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3397 } else {
3398 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3399 }
3400 } else {
3401 if (element->GetStreamer()) {
3402 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3403 } else {
3404 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3405 }
3406 }
3407 }
3408 }
3409 break;
3410 }
3411
3413 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3414 break;
3416 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3417 break;
3419 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3420 break;
3422 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3423 break;
3425 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3426 break;
3428 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3429 break;
3431 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3432 break;
3434 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3435 break;
3437 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3438 break;
3440 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3441 break;
3443 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3444 break;
3446 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3447 break;
3449 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3450 break;
3452 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3453 break;
3455 if (element->GetFactor() != 0) {
3456 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3457 } else {
3458 Int_t nbits = (Int_t)element->GetXmin();
3459 if (!nbits) nbits = 12;
3460 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3461 }
3462 break;
3463 }
3465 if (element->GetFactor() != 0) {
3466 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3467 } else {
3468 Int_t nbits = (Int_t)element->GetXmin();
3469 if (!nbits) {
3470 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3471 } else {
3472 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3473 }
3474 }
3475 break;
3476 }
3477 default:
3478 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3479 break;
3480 }
3481 if (element->TestBit(TStreamerElement::kCache)) {
3482 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3483 readSequence->fActions.pop_back();
3484 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3485 }
3486}
3487
3488////////////////////////////////////////////////////////////////////////////////
3489/// Add a read text action for the given element.
3490
3492{
3493 TStreamerElement *element = compinfo->fElem;
3494
3495 if (element->TestBit(TStreamerElement::kWrite))
3496 return;
3497
3498 Bool_t generic = kFALSE, isBase = kFALSE;
3499
3500 switch (compinfo->fType) {
3502 if (element->IsBase())
3503 isBase = kTRUE;
3504 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3505 else
3506 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3507 break;
3508
3510 if (element->IsBase())
3511 isBase = kTRUE;
3512 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3513 else
3514 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3515 break;
3516
3517 case TStreamerInfo::kObject: // Class derived from TObject
3518 case TStreamerInfo::kAny: // Class NOT derived from TObject
3521 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3522 break;
3523
3524 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3526 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3527 readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3528 break;
3529
3532 readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3533 break;
3534
3535 case TStreamerInfo::kBase: isBase = kTRUE; break;
3536
3538 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3539 break;
3540
3541 default: generic = kTRUE; break;
3542 }
3543
3544 if (isBase) {
3545 if (compinfo->fStreamer) {
3546 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3547 } else {
3548 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3549 }
3550 } else if (generic)
3551 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3552}
3553
3554////////////////////////////////////////////////////////////////////////////////
3555/// Add a read action for the given element.
3556/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3557
3559{
3560 TStreamerElement *element = compinfo->fElem;
3561
3562 if (element->TestBit(TStreamerElement::kWrite)) return;
3563
3564 if (element->TestBit(TStreamerElement::kCache)) {
3565 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3566 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3567 } else {
3568 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3569 }
3570}
3571
3572////////////////////////////////////////////////////////////////////////////////
3573
3575{
3576 TStreamerElement *element = compinfo->fElem;
3578 // Skip element cached for reading purposes.
3579 return;
3580 }
3581 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3582 // Skip artificial element used for reading purposes.
3583 return;
3584 }
3585 switch (compinfo->fType) {
3586 // write basic types
3587 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3588 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3589 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3590 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3591 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3592 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3593 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3594 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3595 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3596 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3597 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3598 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3599 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3600 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3601 /*case TStreamerInfo::kFloat16: {
3602 if (element->GetFactor() != 0) {
3603 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3604 } else {
3605 Int_t nbits = (Int_t)element->GetXmin();
3606 if (!nbits) nbits = 12;
3607 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3608 }
3609 break;
3610 } */
3611 /*case TStreamerInfo::kDouble32: {
3612 if (element->GetFactor() != 0) {
3613 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3614 } else {
3615 Int_t nbits = (Int_t)element->GetXmin();
3616 if (!nbits) {
3617 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3618 } else {
3619 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3620 }
3621 }
3622 break;
3623 } */
3624 //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3625 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3626 // Streamer alltogether.
3627 //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3628 //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3629 /*case TStreamerInfo::kSTL: {
3630 TClass *newClass = element->GetNewClass();
3631 TClass *oldClass = element->GetClassPointer();
3632 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3633
3634 if (element->GetArrayLength() <= 1) {
3635 if (newClass && newClass != oldClass) {
3636 if (element->GetStreamer()) {
3637 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3638 } else {
3639 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3640 }
3641 } else {
3642 if (element->GetStreamer()) {
3643 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3644 } else {
3645 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3646 }
3647 }
3648 } else {
3649 if (newClass && newClass != oldClass) {
3650 if (element->GetStreamer()) {
3651 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3652 } else {
3653 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3654 }
3655 } else {
3656 if (element->GetStreamer()) {
3657 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3658 } else {
3659 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3660 }
3661 }
3662 }
3663 break;
3664 } */
3665 default:
3666 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3667 break;
3668 }
3669#if defined(CDJ_NO_COMPILE)
3670 if (element->TestBit(TStreamerElement::kCache)) {
3671 TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3672 writeSequence->fActions.pop_back();
3673 writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3674 }
3675#endif
3676}
3677
3678////////////////////////////////////////////////////////////////////////////////
3679
3681{
3682 TStreamerElement *element = compinfo->fElem;
3684 // Skip element cached for reading purposes.
3685 return;
3686 }
3687 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3688 // Skip artificial element used for reading purposes.
3689 return;
3690 }
3691
3692 Bool_t generic = kFALSE, isBase = kFALSE;
3693
3694 switch (compinfo->fType) {
3695 // write basic types
3697 writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3698 break;
3700 writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3701 break;
3703 writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3704 break;
3706 writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3707 break;
3709 writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3710 break;
3712 writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3713 break;
3715 writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3716 break;
3718 writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3719 break;
3721 writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3722 break;
3724 writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3725 break;
3727 writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3728 break;
3730 writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3731 break;
3733 writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3734 break;
3735
3737 if (element->IsBase())
3738 isBase = kTRUE;
3739 else
3740 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3741 break;
3742
3744 if (element->IsBase())
3745 isBase = kTRUE;
3746 else
3747 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3748 break;
3749
3750 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3752 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3753 writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3754 break;
3755
3758 writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3759 break;
3760
3761 case TStreamerInfo::kBase: isBase = kTRUE; break;
3762
3764 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3765 break;
3766
3767 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3768 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3769 /*case TStreamerInfo::kFloat16: {
3770 if (element->GetFactor() != 0) {
3771 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3772 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3773 } else {
3774 Int_t nbits = (Int_t)element->GetXmin();
3775 if (!nbits) nbits = 12;
3776 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3777 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3778 }
3779 break;
3780 } */
3781 /*case TStreamerInfo::kDouble32: {
3782 if (element->GetFactor() != 0) {
3783 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3784 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3785 } else {
3786 Int_t nbits = (Int_t)element->GetXmin();
3787 if (!nbits) {
3788 writeSequence->AddAction( ConvertBasicType<float,double>, new
3789 TConfiguration(this,i,compinfo,compinfo->fOffset) );
3790 } else {
3791 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3792 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3793 }
3794 }
3795 break;
3796 } */
3797 // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3798 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3799 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3800 // Streamer alltogether.
3801 // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3802 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3803 // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3804 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3805 /*case TStreamerInfo::kSTL: {
3806 TClass *newClass = element->GetNewClass();
3807 TClass *oldClass = element->GetClassPointer();
3808 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3809
3810 if (element->GetArrayLength() <= 1) {
3811 if (newClass && newClass != oldClass) {
3812 if (element->GetStreamer()) {
3813 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3814 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3815 } else {
3816 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3817 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3818 }
3819 } else {
3820 if (element->GetStreamer()) {
3821 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3822 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3823 } else {
3824 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3825 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3826 }
3827 }
3828 } else {
3829 if (newClass && newClass != oldClass) {
3830 if (element->GetStreamer()) {
3831 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3832 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3833 } else {
3834 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3835 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3836 }
3837 } else {
3838 if (element->GetStreamer()) {
3839 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3840 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3841 } else {
3842 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3843 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3844 }
3845 }
3846 }
3847 break;
3848 } */
3849 default: generic = kTRUE; break;
3850 }
3851
3852 if (isBase) {
3853 if (compinfo->fStreamer) {
3854 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3855 } else {
3856 writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3857 }
3858
3859 } else
3860
3861 // use generic write action when special handling is not provided
3862 if (generic)
3863 writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3864
3865#if defined(CDJ_NO_COMPILE)
3866 if (element->TestBit(TStreamerElement::kCache)) {
3867 TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3868 writeSequence->fActions.pop_back();
3869 writeSequence->AddAction(UseCache,
3870 new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3871 }
3872#endif
3873}
3874
3875////////////////////////////////////////////////////////////////////////////////
3876/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3877
3879{
3880 TStreamerElement *element = compinfo->fElem;
3882 // Skip element cached for reading purposes.
3883 return;
3884 }
3885 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3886 // Skip artificial element used for reading purposes.
3887 return;
3888 }
3889
3890#if defined(CDJ_NO_COMPILE)
3891 if (element->TestBit(TStreamerElement::kCache)) {
3892 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3893 writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3894 } else {
3895 writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3896 }
3897#else
3898 writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3899#endif
3900
3901}
3902
3903////////////////////////////////////////////////////////////////////////////////
3904/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3905
3907{
3908 if (info == 0) {
3910 }
3911
3912 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3913
3914 UInt_t ndata = info->GetElements()->GetEntriesFast();
3916 if (IsDefaultVector(proxy))
3917 {
3918 if (proxy.HasPointers()) {
3919 // Instead of the creating a new one let's copy the one from the StreamerInfo.
3920 delete sequence;
3921
3922 sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3923
3924 return sequence;
3925 }
3926
3927 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3928 Long_t increment = proxy.GetIncrement();
3929 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3934 {
3935 Long_t increment = proxy.GetIncrement();
3936 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3937 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3938 } else {
3939 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3940 }
3941 for (UInt_t i = 0; i < ndata; ++i) {
3942 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3943 if (!element) {
3944 break;
3945 }
3946 if (element->GetType() < 0) {
3947 // -- Skip an ignored TObject base class.
3948 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3949 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3950 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3951 // when it is making branches for a split object.
3952 continue;
3953 }
3954 if (element->TestBit(TStreamerElement::kWrite)) {
3955 // Skip element that only for writing.
3956 continue;
3957 }
3958 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3959 if (baseEl) {
3960 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3961 // There was a problem with the checksum, the user likely did not
3962 // increment the version number of the derived class when the
3963 // base class changed. Since we will be member wise streaming
3964 // this class, let's warn the user that something is wrong.
3965 ::Warning("CreateReadMemberWiseActions","%s",
3966 baseEl->GetErrorMessage());
3968 }
3969 }
3970
3971 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3972
3973 Int_t asize = element->GetSize();
3974 if (element->GetArrayLength()) {
3975 asize /= element->GetArrayLength();
3976 }
3977 Int_t oldType = element->GetType();
3978 Int_t newType = element->GetNewType();
3979
3980 Int_t offset = element->GetOffset();
3981 if (newType != oldType) {
3982 if (newType > 0) {
3983 if (oldType != TVirtualStreamerInfo::kCounter) {
3984 oldType += TVirtualStreamerInfo::kConv;
3985 }
3986 } else {
3987 oldType += TVirtualStreamerInfo::kSkip;
3988 }
3989 }
3990 switch (SelectLooper(proxy)) {
3991 case kAssociativeLooper:
3992// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3993// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3994// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3995 case kVectorLooper:
3996 case kVectorPtrLooper:
3997 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3998 if (element->TestBit(TStreamerElement::kCache)) {
3999 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4000 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4001 } else {
4002 sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4003 }
4004 break;
4005 case kGenericLooper:
4006 default:
4007 // The usual collection case.
4008 if (element->TestBit(TStreamerElement::kCache)) {
4009 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4010 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4011 } else {
4012 sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4013 }
4014 break;
4015 }
4016 }
4017 return sequence;
4018}
4019
4020////////////////////////////////////////////////////////////////////////////////
4021/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
4022
4024{
4025 if (info == 0) {
4027 }
4028
4029 UInt_t ndata = info->GetElements()->GetEntriesFast();
4030 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
4032
4033 if (IsDefaultVector(proxy))
4034 {
4035 if (proxy.HasPointers()) {
4036 // Instead of the creating a new one let's copy the one from the StreamerInfo.
4037 delete sequence;
4038
4039 sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
4040
4041 return sequence;
4042 }
4043
4044 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4045 Long_t increment = proxy.GetIncrement();
4046 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
4047 /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4048 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
4049 {
4050 Long_t increment = proxy.GetIncrement();
4051 sequence->fLoopConfig = new TVectorLoopConfig(increment);
4052 // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
4053 } else {
4054 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
4055 }
4056 for (UInt_t i = 0; i < ndata; ++i) {
4057 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
4058 if (!element) {
4059 break;
4060 }
4061 if (element->GetType() < 0) {
4062 // -- Skip an ignored TObject base class.
4063 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
4064 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
4065 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
4066 // when it is making branches for a split object.
4067 continue;
4068 }
4070 // Skip element cached for reading purposes.
4071 continue;
4072 }
4074 // Skip artificial element used for reading purposes.
4075 continue;
4076 }
4077 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
4078 Int_t asize = element->GetSize();
4079 if (element->GetArrayLength()) {
4080 asize /= element->GetArrayLength();
4081 }
4082 Int_t oldType = element->GetType();
4083 Int_t offset = element->GetOffset();
4084#if defined(CDJ_NO_COMPILE)
4085 Int_t newType = element->GetNewType();
4086
4087 if (newType != oldType) {
4088 if (newType > 0) {
4089 if (oldType != TVirtualStreamerInfo::kCounter) {
4090 oldType += TVirtualStreamerInfo::kConv;
4091 }
4092 } else {
4093 oldType += TVirtualStreamerInfo::kSkip;
4094 }
4095 }
4096 if ( IsDefaultVector(proxy)
4097 /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4098 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
4099 {
4100
4101 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4102 if (element->TestBit(TStreamerElement::kCache)) {
4103 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4104 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4105 } else {
4106 sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4107 }
4108
4109 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4110 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
4111 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4112 } else {
4113 // The usual collection case.
4114 if (element->TestBit(TStreamerElement::kCache)) {
4115 TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4116 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4117 } else {
4118 switch (oldType) {
4119 // read basic types
4120 case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4121 case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4122 case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4123 case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4124 case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4125 case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4126 case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4127 case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4128 case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4129 case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;