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