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