Logo ROOT  
Reference Guide
TStreamerInfoActions.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Philippe Canal 05/2010
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TStreamerInfo.h"
14#include "TROOT.h"
15#include "TStreamerElement.h"
16#include "TVirtualMutex.h"
17#include "TInterpreter.h"
18#include "TError.h"
19#include "TVirtualArray.h"
20#include "TBufferFile.h"
21#include "TBufferText.h"
22#include "TMemberStreamer.h"
23#include "TError.h"
24#include "TClassEdit.h"
26#include "TProcessID.h"
27#include "TFile.h"
28
30
31// More possible optimizations:
32// Avoid call the virtual version of TBuffer::ReadInt and co.
33// Merge the Reading of the version and the looking up or the StreamerInfo
34// Avoid if (bytecnt) inside the CheckByteCount routines and avoid multiple (mostly useless nested calls)
35// Try to avoid if statement on onfile class being set (TBufferFile::ReadClassBuffer).
36
37using namespace TStreamerInfoActions;
38
39#ifdef _AIX
40# define INLINE_TEMPLATE_ARGS
41#else
42# define INLINE_TEMPLATE_ARGS inline
43#endif
44
45
47{
49 {
50 const auto props = proxy.GetProperties();
51 const bool isVector = proxy.GetCollectionType() == ROOT::kSTLvector;
52 const bool hasDefaultAlloc = !(props & TVirtualCollectionProxy::kCustomAlloc);
53 const bool isEmulated = props & TVirtualCollectionProxy::kIsEmulated;
54
55 return isEmulated || (isVector && hasDefaultAlloc);
56 }
57
58 template <typename From>
59 struct WithFactorMarker {
60 typedef From Value_t;
61 };
62
63 template <typename From>
64 struct NoFactorMarker {
65 typedef From Value_t;
66 };
67
68 struct BitsMarker {
69 typedef UInt_t Value_t;
70 };
71
73 {
74 // Add the (potentially negative) delta to all the configuration's offset. This is used by
75 // TBranchElement in the case of split sub-object.
76
78 fOffset += delta;
79 }
80
82 {
83 // Add the (potentially negative) delta to all the configuration's offset. This is used by
84 // TBranchElement in the case of split sub-object.
85
87 }
88
89 void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
90 {
91 // Inform the user what we are about to stream.
92
93 // Idea, we should find a way to print the name of the function
95 }
96
98 {
99 // Inform the user what we are about to stream.
100
102 TStreamerElement *aElement = fCompInfo->fElem;
103 TString sequenceType;
104 aElement->GetSequenceType(sequenceType);
105
106 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
107 " %s, offset=%d (%s), elemnId=%d \n",
108 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
109 aElement->ClassName(), fOffset, sequenceType.Data(), fElemId);
110 }
111
112 void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
113 {
114 // Inform the user what we are about to stream.
115
116 if (gDebug > 1) {
117 // Idea: We should print the name of the action function.
119 TStreamerElement *aElement = fCompInfo->fElem;
120 TString sequenceType;
121 aElement->GetSequenceType(sequenceType);
122
123 printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
124 " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
125 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
126 aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
127 }
128 }
129
131 {
132 // Inform the user what we are about to stream.
133
134 printf("TLoopConfiguration: unconfigured\n");
135 }
136
137
138 struct TGenericConfiguration : TConfiguration {
139 // Configuration of action using the legacy code.
140 // Mostly to cancel out the PrintDebug.
141 public:
142 TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset) {};
143 void PrintDebug(TBuffer &, void *) const {
144 // Since we call the old code, it will print the debug statement.
145 }
146
147 virtual TConfiguration *Copy() { return new TGenericConfiguration(*this); }
148 };
149
150 struct TBitsConfiguration : TConfiguration {
151 // Configuration of action handling kBits.
152 // In this case we need to know both the location
153 // of the member (fBits) and the start of the object
154 // (its TObject part to be exact).
155
156 Int_t fObjectOffset; // Offset of the TObject part within the object
157
158 TBitsConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset = 0) : TConfiguration(info,id,compinfo,offset),fObjectOffset(0) {};
159 void PrintDebug(TBuffer &, void *) const {
160 TStreamerInfo *info = (TStreamerInfo*)fInfo;
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)
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
176 if (fOffset != TVirtualStreamerInfo::kMissing)
177 fOffset += delta;
178 fObjectOffset = 0;
179 }
180
181 void SetMissing()
182 {
184 fObjectOffset = 0;
185 }
186
187 virtual TConfiguration *Copy() { return new TBitsConfiguration(*this); }
188
189 };
190
191 Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
192 {
193 char *obj = (char*)addr;
194 TGenericConfiguration *conf = (TGenericConfiguration*)config;
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;
201 TGenericConfiguration *conf = (TGenericConfiguration*)config;
202 return ((TStreamerInfo*)conf->fInfo)->WriteBufferAux(buf, &obj, &(conf->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ 1, config->fOffset, 2);
203 }
204
205 template <typename T>
207 {
208 T *x = (T*)( ((char*)addr) + config->fOffset );
209 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
210 buf >> *x;
211 return 0;
212 }
213
214 void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config) {
215 TBitsConfiguration *conf = (TBitsConfiguration*)config;
216 UShort_t pidf;
217 buf >> pidf;
218 pidf += buf.GetPidOffset();
219 TProcessID *pid = buf.ReadProcessID(pidf);
220 if (pid!=0) {
221 TObject *obj = (TObject*)( ((char*)addr) + conf->fObjectOffset);
222 UInt_t gpid = pid->GetUniqueID();
223 UInt_t uid;
224 if (gpid>=0xff) {
225 uid = obj->GetUniqueID() | 0xff000000;
226 } else {
227 uid = ( obj->GetUniqueID() & 0xffffff) + (gpid<<24);
228 }
229 obj->SetUniqueID(uid);
230 pid->PutObjectWithID(obj);
231 }
232 }
233
234 template <>
236 {
237 UInt_t *x = (UInt_t*)( ((char*)addr) + config->fOffset );
238 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
239 // Idea: This code really belongs inside TBuffer[File]
240 buf >> *x;
241
242 if ((*x & kIsReferenced) != 0) {
243 HandleReferencedTObject(buf,addr,config);
244 }
245 return 0;
246 }
247
248 template <typename T>
250 {
251 T *x = (T *)(((char *)addr) + config->fOffset);
252 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
253 buf << *x;
254 return 0;
255 }
256
258 {
259 void *x = (void *)(((char *)addr) + config->fOffset);
260 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
262 return 0;
263 }
264
266 {
267 void *x = (void *)(((char *)addr) + config->fOffset);
268 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
270 return 0;
271 }
272
274 {
275 void *x = (void *)(((char *)addr) + config->fOffset);
276 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
277 ((TBufferText *)&buf)->WriteBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
278 return 0;
279 }
280
282 {
283 void *x = (void *)(((char *)addr) + config->fOffset);
284 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
285 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
286 (*pstreamer)(buf, x, config->fCompInfo->fLength);
287 buf.SetByteCount(pos, kTRUE);
288 return 0;
289 }
290
292 {
293 void *x = (void *)(((char *)addr) + config->fOffset);
294 buf.ReadFastArray(x, config->fCompInfo->fClass, config->fCompInfo->fLength, config->fCompInfo->fStreamer);
295 return 0;
296 }
297
299 {
300 void *x = (void *)(((char *)addr) + config->fOffset);
302 return 0;
303 }
304
306 {
307 void *x = (void *)(((char *)addr) + config->fOffset);
308 // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
309 ((TBufferText *)&buf)->ReadBaseClass(x, (TStreamerBase *)config->fCompInfo->fElem);
310 return 0;
311 }
312
314 {
315 void *x = (void *)(((char *)addr) + config->fOffset);
316 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
317
318 UInt_t start, count;
319 /* Version_t v = */ buf.ReadVersion(&start, &count, config->fCompInfo->fClass);
320 (*pstreamer)(buf, x, config->fCompInfo->fLength);
321 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
322 return 0;
323 }
324
326 {
327 // action required to call custom code for TObject as base class
328 void *x = (void *)(((char *)addr) + config->fOffset);
330 return 0;
331 }
332
334 {
335 void *x = (void *)(((char *)addr) + config->fOffset);
337 return 0;
338 }
339
340 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
341 * potentially can be used later for non-text streaming */
342 template<bool kIsTextT>
344 {
345 TClass *cl = config->fCompInfo->fClass;
346 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
348 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
349 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
350 UInt_t ioffset = eoffset + config->fOffset;
351
353 && proxy && vClass
354 && config->fInfo->GetStreamMemberWise()
355 && cl->CanSplit()
356 && !(strspn(config->fCompInfo->fElem->GetTitle(),"||") == 2)
358 // Let's save the collection member-wise.
359
360 UInt_t pos = buf.WriteVersionMemberWise(config->fInfo->IsA(),kTRUE);
361 buf.WriteVersion( vClass, kFALSE );
362
363 // TODO: subinfo used for WriteBufferSTL call, which is private for the moment
364 //TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
365
366 //for (int k = 0; k < narr; ++k) {
367 char **contp = (char **)((char *)addr + ioffset);
368 for(int j=0;j<config->fCompInfo->fLength;++j) {
369 char *cont = contp[j];
370 TVirtualCollectionProxy::TPushPop helper( proxy, cont );
371 Int_t nobjects = cont ? proxy->Size() : 0;
372 buf << nobjects;
373
374 // TODO: method is private, should be made accesible from here
375 // subinfo->WriteBufferSTL(buf,proxy,nobjects);
376 }
377 //}
378 buf.SetByteCount(pos,kTRUE);
379 return 0;
380 }
381 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
382 if (kIsTextT) {
383 // use same method which is used in kSTL
384 buf.WriteFastArray((void **)((char *)addr + ioffset), cl, config->fCompInfo->fLength, kFALSE, pstreamer);
385 } else if (pstreamer == nullptr) {
386 // for (int k = 0; k < narr; ++k) {
387 char **contp = (char **)((char *)addr + ioffset);
388 for (int j = 0; j < config->fCompInfo->fLength; ++j) {
389 char *cont = contp[j];
390 cl->Streamer(cont, buf);
391 }
392 // }
393 } else {
394 // for (int k = 0; k < narr; ++k) {
395 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
396 //}
397 }
398 buf.SetByteCount(pos, kTRUE);
399 return 0;
400 }
401
402
403 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
404 * potentially can be used later for non-text streaming */
405 template<bool kIsTextT>
407 {
408 TClass *cle = config->fCompInfo->fClass;
409 TStreamerElement * aElement = (TStreamerElement*) config->fCompInfo->fElem;
410 TMemberStreamer *pstreamer = config->fCompInfo->fStreamer;
411 //TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
412 //TClass* vClass = proxy ? proxy->GetValueClass() : 0;
413
414 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
415 UInt_t ioffset = eoffset + config->fOffset;
416
417
418 UInt_t start,count;
419 Version_t vers = buf.ReadVersion(&start, &count, cle);
420
421 if (!kIsTextT && (vers & TBufferFile::kStreamedMemberWise) ) {
422 // Collection was saved member-wise
423
425
426 TClass *newClass = aElement->GetNewClass();
427 TClass *oldClass = aElement->GetClassPointer();
428 if( vers < 9 && newClass && newClass!=oldClass ) {
429 Error( "ReadBuffer", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
430 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
431 return 0;
432 }
433
434 Version_t vClVersion = 0; // For vers less than 9, we have to use the current version.
435 if( vers >= 9 ) {
436 vClVersion = buf.ReadVersionForMemberWise( cle->GetCollectionProxy()->GetValueClass() );
437 }
438
439 TVirtualCollectionProxy *newProxy = (newClass ? newClass->GetCollectionProxy() : nullptr);
440 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
441 TStreamerInfo *subinfo = nullptr;
442
443 if( newProxy ) {
444 // coverity[dereference] oldProxy->GetValueClass() can not be null since this was streamed memberwise.
445 subinfo = (TStreamerInfo*)newProxy->GetValueClass()->GetConversionStreamerInfo( oldProxy->GetValueClass(), vClVersion );
446 } else {
447 subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( vClVersion );
448 newProxy = oldProxy;
449 }
450 if (subinfo) {
451 // DOLOOP {
452 void* env;
453 void **contp = (void**)((char *) addr + ioffset);
454 for(int j=0;j<config->fCompInfo->fLength;j++) {
455 void *cont = contp[j];
456 if (cont==nullptr) {
457 contp[j] = cle->New();
458 cont = contp[j];
459 }
460 TVirtualCollectionProxy::TPushPop helper( newProxy, cont );
461 Int_t nobjects;
462 buf >> nobjects;
463 env = newProxy->Allocate(nobjects,true);
464 subinfo->ReadBufferSTL(buf,newProxy,nobjects,/* offset */ 0, vers>=7 );
465 newProxy->Commit(env);
466 }
467 // } // DOLOOP
468 }
469 buf.CheckByteCount(start,count,aElement->GetFullName());
470 return 0;
471 }
472
473 if (kIsTextT) {
474 // use same method which is used in kSTL
475 buf.ReadFastArray((void **)((char *)addr + ioffset), cle, config->fCompInfo->fLength, kFALSE, pstreamer);
476 } else if (pstreamer == nullptr) {
477 // DOLOOP {
478 void **contp = (void **)((char *)addr + ioffset);
479 for (int j = 0; j < config->fCompInfo->fLength; j++) {
480 void *cont = contp[j];
481 if (cont == nullptr) {
482 // int R__n;
483 // b >> R__n;
484 // b.SetOffset(b.GetOffset()-4); // rewind to the start of the int
485 // if (R__n) continue;
486 contp[j] = cle->New();
487 cont = contp[j];
488 }
489 cle->Streamer(cont, buf);
490 }
491 // }
492 } else {
493 (*pstreamer)(buf, (char *)addr + ioffset, config->fCompInfo->fLength);
494 }
495 buf.CheckByteCount(start, count, aElement->GetFullName());
496
497 return 0;
498 }
499
500 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
501 * potentially can be used later for non-text streaming */
502 template<bool kIsTextT>
504 {
505 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
506 UInt_t ioffset = eoffset + config->fOffset;
507
508 if (!kIsTextT && config->fCompInfo->fStreamer) {
509 // Get any private streamer which was set for the data member.
510 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
511 // -- We have a private streamer.
512 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
513 // Loop over the entries in the clones array or the STL container.
514 //for (int k = 0; k < narr; ++k) {
515 // Get a pointer to the counter for the varying length array.
516 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
517
518 // And call the private streamer, passing it the buffer, the object, and the counter.
519 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
520 //} for k
521 buf.SetByteCount(pos, kTRUE);
522 // We are done, next streamer element.
523 return 0;
524 }
525
526 // Get the class of the data member.
527 TClass* cl = config->fCompInfo->fClass;
528 // Which are we, an array of objects or an array of pointers to objects?
529 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
530
531 // By default assume the file version is the newest.
532 Int_t fileVersion = kMaxInt;
533
534 if (!kIsTextT) {
535 // At this point we do *not* have a private streamer.
536 // Get the version of the file we are writing to.
537 TFile* file = (TFile*) buf.GetParent();
538 if (file) {
539 fileVersion = file->GetVersion();
540 }
541 }
542 // Write the class version to the buffer.
543 UInt_t pos = buf.WriteVersion(config->fInfo->IsA(), kTRUE);
544 if (fileVersion > 51508) {
545 // -- Newer versions allow polymorphic pointers to objects.
546 // Loop over the entries in the clones array or the STL container.
547 //for (int k = 0; k < narr; ++k) {
548 // Get the counter for the varying length array.
549 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
550
551 //b << vlen;
552 if (vlen) {
553 // Get a pointer to the array of pointers.
554 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
555 // Loop over each element of the array of pointers to varying-length arrays.
556 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
557 if (!pp[ndx]) {
558 // -- We do not have a pointer to a varying-length array.
559 // Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
560 // ::ErrorHandler(kError, "::WriteStreamerLoop", Form("The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName()));
561 printf("WriteStreamerLoop - The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName());
562 continue;
563 }
564 if (!isPtrPtr) {
565 // -- We are a varying-length array of objects.
566 // Write the entire array of objects to the buffer.
567 // Note: Polymorphism is not allowed here.
568 buf.WriteFastArray(pp[ndx], cl, vlen, nullptr);
569 } else {
570 // -- We are a varying-length array of pointers to objects.
571 // Write the entire array of object pointers to the buffer.
572 // Note: The object pointers are allowed to be polymorphic.
573 buf.WriteFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
574 } // isPtrPtr
575 } // ndx
576 } else // vlen
577 if (kIsTextT) {
578 // special handling for the text-based streamers
579 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx)
580 buf.WriteFastArray((void *)nullptr, cl, -1, nullptr);
581 }
582 //} // k
583 }
584 else {
585 // -- Older versions do *not* allow polymorphic pointers to objects.
586 // Loop over the entries in the clones array or the STL container.
587 //for (int k = 0; k < narr; ++k) {
588 // Get the counter for the varying length array.
589 Int_t vlen = *((Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/));
590 //b << vlen;
591 if (vlen) {
592 // Get a pointer to the array of pointers.
593 char** pp = (char**) ((char *) addr /*entry pointer*/ + ioffset /*object offset*/);
594 // -- Older versions do *not* allow polymorphic pointers to objects.
595 // Loop over each element of the array of pointers to varying-length arrays.
596 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
597 if (!pp[ndx]) {
598 // -- We do not have a pointer to a varying-length array.
599 //Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
600 // ::ErrorHandler(kError, "::WriteTextStreamerLoop", Form("The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName()));
601 printf("WriteStreamerLoop - The pointer to element %s::%s type %d (%s) is null\n", config->fInfo->GetName(), config->fCompInfo->fElem->GetFullName(), config->fCompInfo->fType, config->fCompInfo->fElem->GetTypeName());
602 continue;
603 }
604 if (!isPtrPtr) {
605 // -- We are a varying-length array of objects.
606 // Loop over the elements of the varying length array.
607 for (Int_t v = 0; v < vlen; ++v) {
608 // Write the object to the buffer.
609 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
610 } // v
611 }
612 else {
613 // -- We are a varying-length array of pointers to objects.
614 // Loop over the elements of the varying length array.
615 for (Int_t v = 0; v < vlen; ++v) {
616 // Get a pointer to the object pointer.
617 char** r = (char**) pp[ndx];
618 // Write the object to the buffer.
619 cl->Streamer(r[v], buf);
620 } // v
621 } // isPtrPtr
622 } // ndx
623 } // vlen
624 //} // k
625 } // fileVersion
626 // Backpatch the byte count into the buffer.
627 buf.SetByteCount(pos, kTRUE);
628
629 return 0;
630 }
631
632
633 /** Direct copy of code from TStreamerInfo::WriteBufferAux,
634 * potentially can be used later for non-text streaming */
635 template<bool kIsTextT>
637 {
638 UInt_t eoffset = 0; // extra parameter of TStreamerInfo::WriteBufferAux, 0 for all kind of objects writing
639 UInt_t ioffset = eoffset + config->fOffset;
640
641 // Get the class of the data member.
642 TClass* cl = config->fCompInfo->fClass;
643
644 // Check for a private streamer.
645 if (!kIsTextT && config->fCompInfo->fStreamer) {
646 // Get any private streamer which was set for the data member.
647 TMemberStreamer* pstreamer = config->fCompInfo->fStreamer;
648 // -- We have a private streamer.
649 // Read the class version and byte count from the buffer.
650 UInt_t start = 0;
651 UInt_t count = 0;
652 buf.ReadVersion(&start, &count, cl);
653 // Loop over the entries in the clones array or the STL container.
654 //for (Int_t k = 0; k < narr; ++k) {
655
656 Int_t* counter = (Int_t*) ((char *) addr /*entry pointer*/ + eoffset /*entry offset*/ + config->fCompInfo->fMethod /*counter offset*/);
657 // And call the private streamer, passing it the buffer, the object, and the counter.
658 (*pstreamer)(buf, (char *) addr /*entry pointer*/ + ioffset /*object offset*/, *counter);
659
660 // } // for k
661 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
662 // We are done, next streamer element.
663 return 0;
664 }
665
666 // Which are we, an array of objects or an array of pointers to objects?
667 Bool_t isPtrPtr = (strstr(config->fCompInfo->fElem->GetTypeName(), "**") != 0);
668
669 // By default assume the file version is the newest.
670 Int_t fileVersion = kMaxInt;
671 if (!kIsTextT) {
672 // At this point we do *not* have a private streamer.
673 // Get the version of the file we are reading from.
674 TFile* file = (TFile*) buf.GetParent();
675 if (file) {
676 fileVersion = file->GetVersion();
677 }
678 }
679 // Read the class version and byte count from the buffer.
680 UInt_t start = 0;
681 UInt_t count = 0;
682 buf.ReadVersion(&start, &count, cl);
683 if (fileVersion > 51508) {
684 // -- Newer versions allow polymorphic pointers.
685 // Loop over the entries in the clones array or the STL container.
686 // for (Int_t k = 0; k < narr; ++k) {
687 // Get the counter for the varying length array.
688 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
689 config->fCompInfo->fMethod /*counter offset*/));
690 // Int_t realLen;
691 // b >> realLen;
692 // if (realLen != vlen) {
693 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
694 //}
695 // Get a pointer to the array of pointers.
696 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
697 // Loop over each element of the array of pointers to varying-length arrays.
698 // if (!pp) {
699 // continue;
700 // }
701
702 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
703 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
704 // if (!pp[ndx]) {
705 // -- We do not have a pointer to a varying-length array.
706 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
707 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
708 // continue;
709 //}
710 // Delete any memory at pp[ndx].
711 if (!isPtrPtr) {
712 cl->DeleteArray(pp[ndx]);
713 pp[ndx] = 0;
714 } else {
715 // Using vlen is wrong here because it has already
716 // been overwritten with the value needed to read
717 // the current record. Fixing this will require
718 // doing a pass over the object at the beginning
719 // of the I/O and releasing all the buffer memory
720 // for varying length arrays before we overwrite
721 // the counter values.
722 //
723 // For now we will just leak memory, just as we
724 // have always done in the past. Fix this.
725 //
726 // char** r = (char**) pp[ndx];
727 // if (r) {
728 // for (Int_t v = 0; v < vlen; ++v) {
729 // cl->Destructor(r[v]);
730 // r[v] = 0;
731 // }
732 //}
733 delete[] pp[ndx];
734 pp[ndx] = 0;
735 }
736 if (!vlen) {
737 if (kIsTextT) {
738 // special handling for the text-based streamers - keep calling to shift array index
739 buf.ReadFastArray((void *)nullptr, cl, -1, nullptr);
740 }
741 continue;
742 }
743 // Note: We now have pp[ndx] is null.
744 // Allocate memory to read into.
745 if (!isPtrPtr) {
746 // -- We are a varying-length array of objects.
747 // Note: Polymorphism is not allowed here.
748 // Allocate a new array of objects to read into.
749 pp[ndx] = (char *)cl->NewArray(vlen);
750 if (!pp[ndx]) {
751 Error("ReadBuffer", "Memory allocation failed!\n");
752 continue;
753 }
754 } else {
755 // -- We are a varying-length array of pointers to objects.
756 // Note: The object pointers are allowed to be polymorphic.
757 // Allocate a new array of pointers to objects to read into.
758 pp[ndx] = (char *)new char *[vlen];
759 if (!pp[ndx]) {
760 Error("ReadBuffer", "Memory allocation failed!\n");
761 continue;
762 }
763 // And set each pointer to null.
764 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
765 // = (char*) new char*[vlen];
766 }
767 if (!isPtrPtr) {
768 // -- We are a varying-length array of objects.
769 buf.ReadFastArray(pp[ndx], cl, vlen, nullptr);
770 } else {
771 // -- We are a varying-length array of object pointers.
772 buf.ReadFastArray((void **)pp[ndx], cl, vlen, kFALSE, nullptr);
773 } // isPtrPtr
774 } // ndx
775 // } // k
776 } else {
777 // -- Older versions do *not* allow polymorphic pointers.
778 // Loop over the entries in the clones array or the STL container.
779 // for (Int_t k = 0; k < narr; ++k) {
780 // Get the counter for the varying length array.
781 Int_t vlen = *((Int_t *)((char *)addr /*entry pointer*/ + eoffset /*entry offset*/ +
782 config->fCompInfo->fMethod /*counter offset*/));
783 // Int_t realLen;
784 // b >> realLen;
785 // if (realLen != vlen) {
786 // fprintf(stderr, "read vlen: %d realLen: %s\n", vlen, realLen);
787 //}
788 // Get a pointer to the array of pointers.
789 char **pp = (char **)((char *)addr /*entry pointer*/ + ioffset /*object offset*/);
790 // if (!pp) {
791 // continue;
792 //}
793
794 if (pp) // SL: place it here instead of continue, which is related to for(k) loop
795
796 // Loop over each element of the array of pointers to varying-length arrays.
797 for (Int_t ndx = 0; ndx < config->fCompInfo->fLength; ++ndx) {
798 // if (!pp[ndx]) {
799 // -- We do not have a pointer to a varying-length array.
800 // Error("ReadBuffer", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(),
801 // aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
802 // continue;
803 //}
804 // Delete any memory at pp[ndx].
805 if (!isPtrPtr) {
806 cl->DeleteArray(pp[ndx]);
807 pp[ndx] = 0;
808 } else {
809 // Using vlen is wrong here because it has already
810 // been overwritten with the value needed to read
811 // the current record. Fixing this will require
812 // doing a pass over the object at the beginning
813 // of the I/O and releasing all the buffer memory
814 // for varying length arrays before we overwrite
815 // the counter values.
816 //
817 // For now we will just leak memory, just as we
818 // have always done in the past. Fix this.
819 //
820 // char** r = (char**) pp[ndx];
821 // if (r) {
822 // for (Int_t v = 0; v < vlen; ++v) {
823 // cl->Destructor(r[v]);
824 // r[v] = 0;
825 // }
826 //}
827 delete[] pp[ndx];
828 pp[ndx] = 0;
829 }
830 if (!vlen) {
831 continue;
832 }
833 // Note: We now have pp[ndx] is null.
834 // Allocate memory to read into.
835 if (!isPtrPtr) {
836 // -- We are a varying-length array of objects.
837 // Note: Polymorphism is not allowed here.
838 // Allocate a new array of objects to read into.
839 pp[ndx] = (char *)cl->NewArray(vlen);
840 if (!pp[ndx]) {
841 Error("ReadBuffer", "Memory allocation failed!\n");
842 continue;
843 }
844 } else {
845 // -- We are a varying-length array of pointers to objects.
846 // Note: The object pointers are allowed to be polymorphic.
847 // Allocate a new array of pointers to objects to read into.
848 pp[ndx] = (char *)new char *[vlen];
849 if (!pp[ndx]) {
850 Error("ReadBuffer", "Memory allocation failed!\n");
851 continue;
852 }
853 // And set each pointer to null.
854 memset(pp[ndx], 0, vlen * sizeof(char *)); // This is the right size we really have a char**: pp[ndx]
855 // = (char*) new char*[vlen];
856 }
857 if (!isPtrPtr) {
858 // -- We are a varying-length array of objects.
859 // Loop over the elements of the varying length array.
860 for (Int_t v = 0; v < vlen; ++v) {
861 // Read the object from the buffer.
862 cl->Streamer(pp[ndx] + (v * cl->Size()), buf);
863 } // v
864 } else {
865 // -- We are a varying-length array of object pointers.
866 // Get a pointer to the object pointer array.
867 char **r = (char **)pp[ndx];
868 // Loop over the elements of the varying length array.
869 for (Int_t v = 0; v < vlen; ++v) {
870 // Allocate an object to read into.
871 r[v] = (char *)cl->New();
872 if (!r[v]) {
873 // Do not print a second error message here.
874 // Error("ReadBuffer", "Memory allocation failed!\n");
875 continue;
876 }
877 // Read the object from the buffer.
878 cl->Streamer(r[v], buf);
879 } // v
880 } // isPtrPtr
881 } // ndx
882 // } // k
883 } // fileVersion
884 buf.CheckByteCount(start, count, config->fCompInfo->fElem->GetFullName());
885 return 0;
886 }
887
888 class TConfWithFactor : public TConfiguration {
889 // Configuration object for the Float16/Double32 where a factor has been specified.
890 public:
891 Double_t fFactor;
892 Double_t fXmin;
893 TConfWithFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Double_t factor, Double_t xmin) : TConfiguration(info,id,compinfo,offset),fFactor(factor),fXmin(xmin) {};
894 virtual TConfiguration *Copy() { return new TConfWithFactor(*this); }
895 };
896
897 template <typename T>
899 {
900 // Stream a Float16 or Double32 where a factor has been specified.
901 //a range was specified. We read an integer and convert it back to a double.
902
903 TConfWithFactor *conf = (TConfWithFactor *)config;
904 buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
905 return 0;
906 }
907
908 class TConfNoFactor : public TConfiguration {
909 // Configuration object for the Float16/Double32 where a factor has been specified.
910 public:
911 Int_t fNbits;
912 TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, Int_t nbits) : TConfiguration(info,id,compinfo,offset),fNbits(nbits) {};
913 virtual TConfiguration *Copy() { return new TConfNoFactor(*this); }
914 };
915
916 template <typename T>
918 {
919 // Stream a Float16 or Double32 where a factor has not been specified.
920
921 TConfNoFactor *conf = (TConfNoFactor *)config;
922 Int_t nbits = conf->fNbits;
923
924 buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
925 return 0;
926 }
927
929 {
930 // Read in a TString object.
931
932 // Idea: We could separate the TString Streamer in its two parts and
933 // avoid the if (buf.IsReading()) and try having it inlined.
934 ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
935 return 0;
936 }
937
939 {
940 // Read in a TObject object part.
941
942 // Idea: We could separate the TObject Streamer in its two parts and
943 // avoid the if (buf.IsReading()).
944 ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
945 return 0;
946 }
947
949 {
950 // Read in a TNamed object part.
951 // Since the TNamed streamer is solely delegating back to the StreamerInfo we
952 // can skip the streamer.
953
954 // Idea: We could extract the code from ReadClassBuffer and avoid one function
955 // code.
956 static const TClass *TNamed_cl = TNamed::Class();
957 return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
958 }
959
960 class TConfigSTL : public TConfiguration {
961 // Configuration object for the kSTL case
962 private:
963 void Init() {
964 TVirtualCollectionProxy *proxy = fNewClass->GetCollectionProxy();
965 if (proxy) {
966 fCreateIterators = proxy->GetFunctionCreateIterators();
967 fCopyIterator = proxy->GetFunctionCopyIterator();
968 fDeleteIterator = proxy->GetFunctionDeleteIterator();
969 fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
970 }
971 }
972
973 public:
974 TClass *fOldClass; // Class of the content on file
975 TClass *fNewClass; // Class of the content in memory.
976 TMemberStreamer *fStreamer;
977 const char *fTypeName; // Type name of the member as typed by ther user.
978 Bool_t fIsSTLBase; // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
979
984
985 TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) :
986 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
987 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
988
989 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) :
990 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(0), fTypeName(type_name), fIsSTLBase(isbase),
991 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
992
993 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) :
994 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
995 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
996
997 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) :
998 TConfiguration(info,id,compinfo,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
999 fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
1000
1001 virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
1002 };
1003
1004 class TConfSTLWithFactor : public TConfigSTL {
1005 // Configuration object for the Float16/Double32 where a factor has been specified.
1006 public:
1007 Double_t fFactor;
1008 Double_t fXmin;
1009 TConfSTLWithFactor(TConfigSTL *orig, Double_t factor, Double_t xmin) : TConfigSTL(*orig),fFactor(factor),fXmin(xmin) {};
1010 virtual TConfiguration *Copy() { return new TConfSTLWithFactor(*this); }
1011 };
1012
1013 class TConfSTLNoFactor : public TConfigSTL {
1014 // Configuration object for the Float16/Double32 where a factor has been specified.
1015 public:
1016 Int_t fNbits;
1017 TConfSTLNoFactor(TConfigSTL *orig, Int_t nbits) : TConfigSTL(*orig),fNbits(nbits) {};
1018 virtual TConfiguration *Copy() { return new TConfSTLNoFactor(*this); }
1019 };
1020
1021 class TVectorLoopConfig : public TLoopConfiguration {
1022 // Base class of the Configurations used in member wise streaming.
1023 protected:
1024 public:
1025 Long_t fIncrement; // Either a value to increase the cursor by and
1026 public:
1027 TVectorLoopConfig(TVirtualCollectionProxy *proxy, Long_t increment, Bool_t /* read */) : TLoopConfiguration(proxy), fIncrement(increment) {};
1028 //virtual void PrintDebug(TBuffer &buffer, void *);
1029 virtual ~TVectorLoopConfig() {};
1030 void Print() const
1031 {
1032 printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
1033 }
1034
1035 void* GetFirstAddress(void *start, const void * /* end */) const
1036 {
1037 // Return the address of the first element of the collection.
1038
1039 return start;
1040 }
1041
1042 virtual TLoopConfiguration* Copy() const { return new TVectorLoopConfig(*this); }
1043 };
1044
1045 class TAssocLoopConfig : public TLoopConfiguration {
1046 // Base class of the Configurations used in member wise streaming.
1047 public:
1048 TAssocLoopConfig(TVirtualCollectionProxy *proxy, Bool_t /* read */) : TLoopConfiguration(proxy) {};
1049 //virtual void PrintDebug(TBuffer &buffer, void *);
1050 virtual ~TAssocLoopConfig() {};
1051 void Print() const
1052 {
1053 printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1054 }
1055 virtual TLoopConfiguration* Copy() const { return new TAssocLoopConfig(*this); }
1056
1057 void* GetFirstAddress(void *start, const void * /* end */) const
1058 {
1059 // Return the address of the first element of the collection.
1060
1061 R__ASSERT(0);
1062// char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
1063// void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
1064// arr0 = genloopconfig->fNext(iter,end_collection);
1065// if (iter != &iterator[0]) {
1066// genloopconfig->fDeleteIterator(iter);
1067// }
1068 return start;
1069 }
1070 };
1071
1072 class TGenericLoopConfig : public TLoopConfiguration {
1073 // Configuration object for the generic case of member wise streaming looping.
1074 private:
1075 void Init(Bool_t read) {
1076 if (fProxy) {
1077 if (fProxy->HasPointers()) {
1081 } else {
1082 fNext = fProxy->GetFunctionNext(read);
1083 fCopyIterator = fProxy->GetFunctionCopyIterator(read);
1084 fDeleteIterator = fProxy->GetFunctionDeleteIterator(read);
1085 }
1086 }
1087 }
1088 public:
1092
1093 TGenericLoopConfig(TVirtualCollectionProxy *proxy, Bool_t read) : TLoopConfiguration(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
1094 {
1095 Init(read);
1096 }
1097 virtual ~TGenericLoopConfig() {};
1098 void Print() const
1099 {
1100 printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
1101 }
1102 virtual TLoopConfiguration* Copy() const { return new TGenericLoopConfig(*this); }
1103
1104 void* GetFirstAddress(void *start_collection, const void *end_collection) const
1105 {
1106 // Return the address of the first element of the collection.
1107
1109 void *iter = fCopyIterator(&iterator,start_collection);
1110 void *arr0 = fNext(iter,end_collection);
1111 if (iter != &iterator[0]) {
1112 fDeleteIterator(iter);
1113 }
1114 return arr0;
1115 }
1116 };
1117
1119 {
1120 // Collection was saved member-wise
1121
1122 TConfigSTL *config = (TConfigSTL*)conf;
1124
1125 if( vers >= 8 ) {
1126
1127 TClass *oldClass = config->fOldClass;
1128
1129 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1130 if (!oldProxy) {
1131 // Missing information, broken file ... give up
1132 return;
1133 }
1134 TClass *valueClass = oldProxy->GetValueClass();
1135 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1136
1137 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1138 Int_t nobjects;
1139 buf.ReadInt(nobjects);
1140 void* alternative = oldProxy->Allocate(nobjects,true);
1141 if (nobjects) {
1142 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1143
1146 void *begin = &(startbuf[0]);
1147 void *end = &(endbuf[0]);
1148 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1149 // We can not get here with a split vector of pointer, so we can indeed assume
1150 // that actions->fConfiguration != null.
1151 buf.ApplySequence(*actions, begin, end);
1152 if (begin != &(startbuf[0])) {
1153 // assert(end != endbuf);
1154 config->fDeleteTwoIterators(begin,end);
1155 }
1156 }
1157 oldProxy->Commit(alternative);
1158
1159 } else {
1160
1161 TClass *oldClass = config->fOldClass;
1162
1163 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1164 if (!oldProxy) {
1165 // Missing information, broken file ... give up
1166 return;
1167 }
1168
1169 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
1170 Int_t nobjects;
1171 buf.ReadInt(nobjects);
1172 void* env = oldProxy->Allocate(nobjects,true);
1173
1174 if (nobjects || vers < 7 ) {
1175 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1176 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1177
1178 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1179 }
1180 oldProxy->Commit(env);
1181 }
1182 }
1183
1185 {
1186 // Collection was saved member-wise
1187
1188 TConfigSTL *config = (TConfigSTL*)conf;
1190
1191 if( vers >= 8 ) {
1192
1193 TClass *oldClass = config->fOldClass;
1194
1195 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1196 if (!oldProxy) {
1197 // Missing information, broken file ... give up
1198 return;
1199 }
1200 TClass *valueClass = oldProxy->GetValueClass();
1201 Version_t vClVersion = buf.ReadVersionForMemberWise( valueClass );
1202
1203 TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
1204
1205 int objectSize = oldClass->Size();
1206 char *obj = (char*)addr;
1207 char *endobj = obj + conf->fLength*objectSize;
1208
1209 for(; obj<endobj; obj+=objectSize) {
1210 Int_t nobjects;
1211 buf.ReadInt(nobjects);
1212 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1213 void* alternative = oldProxy->Allocate(nobjects,true);
1214 if (nobjects) {
1217 void *begin = &(startbuf[0]);
1218 void *end = &(endbuf[0]);
1219 config->fCreateIterators(alternative, &begin, &end, oldProxy);
1220 // We can not get here with a split vector of pointer, so we can indeed assume
1221 // that actions->fConfiguration != null.
1222 buf.ApplySequence(*actions, begin, end);
1223 if (begin != &(startbuf[0])) {
1224 // assert(end != endbuf);
1225 config->fDeleteTwoIterators(begin,end);
1226 }
1227 }
1228 oldProxy->Commit(alternative);
1229 }
1230
1231 } else {
1232
1233 TClass *oldClass = config->fOldClass;
1234
1235 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1236 if (!oldProxy) {
1237 // Missing information, broken file ... give up
1238 return;
1239 }
1240
1241 int objectSize = oldClass->Size();
1242 char *obj = (char*)addr;
1243 char *endobj = obj + conf->fLength*objectSize;
1244
1245 for(; obj<endobj; obj+=objectSize) {
1246 TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
1247 Int_t nobjects;
1248 buf.ReadInt(nobjects);
1249 void* env = oldProxy->Allocate(nobjects,true);
1250
1251 if (nobjects || vers < 7 ) {
1252 // coverity[dereference] since this is a member streaming action by definition the collection contains objects.
1253 TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
1254
1255 subinfo->ReadBufferSTL(buf, oldProxy, nobjects, /* offset */ 0, /* v7 */ kFALSE);
1256 }
1257 oldProxy->Commit(env);
1258 }
1259 }
1260 }
1261
1263 {
1264 // Collection was saved member-wise
1265
1266 TConfigSTL *config = (TConfigSTL*)conf;
1267
1269
1270 TClass *newClass = config->fNewClass;
1271 TClass *oldClass = config->fOldClass;
1272
1273 if( vers < 8 ) {
1274 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1275 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1276 } else {
1277
1278 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1279
1280 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1281 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1282
1283 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
1284 Int_t nobjects;
1285 buf.ReadInt(nobjects);
1286 void* alternative = newProxy->Allocate(nobjects,true);
1287 if (nobjects) {
1288 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1291 void *begin = &(startbuf[0]);
1292 void *end = &(endbuf[0]);
1293 config->fCreateIterators( alternative, &begin, &end, newProxy);
1294 // We can not get here with a split vector of pointer, so we can indeed assume
1295 // that actions->fConfiguration != null.
1296 buf.ApplySequence(*actions, begin, end);
1297 if (begin != &(startbuf[0])) {
1298 // assert(end != endbuf);
1299 config->fDeleteTwoIterators(begin,end);
1300 }
1301 }
1302 newProxy->Commit(alternative);
1303 }
1304 }
1305
1307 {
1308 // Collection was saved member-wise
1309
1310 TConfigSTL *config = (TConfigSTL*)conf;
1311
1313
1314 TClass *newClass = config->fNewClass;
1315 TClass *oldClass = config->fOldClass;
1316
1317 if( vers < 8 ) {
1318 Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
1319 vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
1320 } else {
1321
1322 Version_t vClVersion = buf.ReadVersionForMemberWise( oldClass->GetCollectionProxy()->GetValueClass() );
1323
1324 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1325 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1326
1327 int objectSize = newClass->Size();
1328 char *obj = (char*)addr;
1329 char *endobj = obj + conf->fLength*objectSize;
1330
1331 for(; obj<endobj; obj+=objectSize) {
1332 TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
1333 Int_t nobjects;
1334 buf.ReadInt(nobjects);
1335 void* alternative = newProxy->Allocate(nobjects,true);
1336 if (nobjects) {
1337 TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
1340 void *begin = &(startbuf[0]);
1341 void *end = &(endbuf[0]);
1342 config->fCreateIterators( alternative, &begin, &end, newProxy);
1343 // We can not get here with a split vector of pointer, so we can indeed assume
1344 // that actions->fConfiguration != null.
1345 buf.ApplySequence(*actions, begin, end);
1346 if (begin != &(startbuf[0])) {
1347 // assert(end != endbuf);
1348 config->fDeleteTwoIterators(begin,end);
1349 }
1350 }
1351 newProxy->Commit(alternative);
1352 }
1353 }
1354 }
1355
1356
1357 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1358 {
1359 TConfigSTL *config = (TConfigSTL*)conf;
1360 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1361 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1362 }
1363 INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
1364 {
1365 TConfigSTL *config = (TConfigSTL*)conf;
1366 (*config->fStreamer)(buf,addr,conf->fLength);
1367 }
1369 {
1370 // case of old TStreamerInfo
1371
1372 TConfigSTL *config = (TConfigSTL*)conf;
1373 // Backward compatibility. Some TStreamerElement's where without
1374 // Streamer but were not removed from element list
1375 if (config->fIsSTLBase || vers == 0) {
1376 buf.SetBufferOffset(start); //there is no byte count
1377 }
1378 // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
1379 buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
1380 }
1382 {
1383 // case of old TStreamerInfo
1384
1385 TConfigSTL *config = (TConfigSTL*)conf;
1386 // Backward compatibility. Some TStreamerElement's where without
1387 // Streamer but were not removed from element list
1388 if (config->fIsSTLBase || vers == 0) {
1389 buf.SetBufferOffset(start); //there is no byte count
1390 }
1391 (*config->fStreamer)(buf,addr,conf->fLength);
1392 }
1393
1394 template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t),
1395 void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
1397 {
1398 TConfigSTL *config = (TConfigSTL*)conf;
1399 UInt_t start, count;
1400 Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
1401 if ( vers & TBufferFile::kStreamedMemberWise ) {
1402 memberwise(buf,((char*)addr)+config->fOffset,config, vers);
1403 } else {
1404 objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
1405 }
1406 buf.CheckByteCount(start,count,config->fTypeName);
1407 return 0;
1408 }
1409
1410 template <typename From, typename To>
1411 struct ConvertBasicType {
1412 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1413 {
1414 // Simple conversion from a 'From' on disk to a 'To' in memory.
1415 From temp;
1416 buf >> temp;
1417 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1418 return 0;
1419 }
1420 };
1421
1422 template <typename To>
1423 struct ConvertBasicType<BitsMarker,To> {
1424 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1425 {
1426 // Simple conversion from a 'From' on disk to a 'To' in memory
1427 UInt_t temp;
1428 buf >> temp;
1429
1430 if ((temp & kIsReferenced) != 0) {
1431 HandleReferencedTObject(buf,addr,config);
1432 }
1433
1434 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1435 return 0;
1436 }
1437 };
1438
1439 template <typename From, typename To>
1440 struct ConvertBasicType<WithFactorMarker<From>,To> {
1441 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1442 {
1443 // Simple conversion from a 'From' on disk to a 'To' in memory.
1444 TConfWithFactor *conf = (TConfWithFactor *)config;
1445 From temp;
1446 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1447 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1448 return 0;
1449 }
1450 };
1451
1452 template <typename From, typename To>
1453 struct ConvertBasicType<NoFactorMarker<From>,To> {
1454 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *config)
1455 {
1456 // Simple conversion from a 'From' on disk to a 'To' in memory.
1457 TConfNoFactor *conf = (TConfNoFactor *)config;
1458 From temp;
1459 buf.ReadWithNbits(&temp, conf->fNbits);
1460 *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
1461 return 0;
1462 }
1463 };
1464
1465 class TConfigurationPushDataCache : public TConfiguration {
1466 // Configuration object for the PushDataCache case.
1467 public:
1468 TVirtualArray *fOnfileObject;
1469
1470 TConfigurationPushDataCache(TVirtualStreamerInfo *info, TVirtualArray *onfileObject, Int_t offset) :
1471 TConfiguration(info, -1, nullptr, offset), fOnfileObject(onfileObject)
1472 {}
1473
1474 virtual void Print() const {
1475 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1476 if (fOnfileObject)
1477 printf("StreamerInfoAction, class:%s, PushDataCache offset=%d\n",
1478 info->GetClass()->GetName(), fOffset);
1479 else
1480 printf("StreamerInfoAction, class:%s, PopDataCache offset=%d\n",
1481 info->GetClass()->GetName(), fOffset);
1482 }
1483 virtual void PrintDebug(TBuffer &buffer, void *object) const {
1484 if (gDebug > 1) {
1485 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1486 printf("StreamerInfoAction, class:%s, %sDataCache, bufpos=%d, arr=%p, offset=%d, onfileObject=%p\n",
1487 info->GetClass()->GetName(), fOnfileObject ? "Push" : "Pop", buffer.Length(), object, fOffset, fOnfileObject);
1488
1489 }
1490 }
1491 };
1492
1494 {
1495 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1496 auto onfileObject = config->fOnfileObject;
1497
1498 // onfileObject->SetSize(1);
1499 b.PushDataCache( onfileObject );
1500
1501 return 0;
1502 }
1503
1504 Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
1505 {
1506 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1507 auto onfileObject = config->fOnfileObject;
1508
1509 // onfileObject->SetSize(n);
1510 b.PushDataCache( onfileObject );
1511
1512 return 0;
1513 }
1514
1515 Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1516 {
1517 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1518 auto onfileObject = config->fOnfileObject;
1519
1520 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1521 UInt_t n = proxy->Size();
1522
1523 onfileObject->SetSize(n);
1524 b.PushDataCache( onfileObject );
1525
1526 return 0;
1527 }
1528
1530 {
1531 b.PopDataCache();
1532 return 0;
1533 }
1534
1535 Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
1536 {
1537 b.PopDataCache();
1538 return 0;
1539 }
1540
1542 {
1543 b.PopDataCache();
1544 return 0;
1545 }
1546
1547 class TConfigurationUseCache : public TConfiguration {
1548 // Configuration object for the UseCache case.
1549 public:
1550 TConfiguredAction fAction;
1551 Bool_t fNeedRepeat;
1552
1553 TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1554 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1555 virtual void PrintDebug(TBuffer &b, void *addr) const
1556 {
1557 if (gDebug > 1) {
1558 // Idea: We should print the name of the action function.
1559 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1560 TStreamerElement *aElement = fCompInfo->fElem;
1561 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1562 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1563 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1564 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1565 }
1566
1567 }
1568 virtual ~TConfigurationUseCache() {};
1569 virtual TConfiguration *Copy() {
1570 TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1571 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1572 return copy;
1573 }
1574 };
1575
1577 {
1578 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1579
1580 Int_t bufpos = b.Length();
1581 TVirtualArray *cached = b.PeekDataCache();
1582 if (cached==0) {
1583 TStreamerElement *aElement = conf->fCompInfo->fElem;
1584 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1585 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1586 char *ptr = (char*)addr;
1587 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1588 } else {
1589 config->fAction(b, (*cached)[0]);
1590 }
1591 // Idea: Factor out this 'if' to a UseCacheRepeat function
1592 if (config->fNeedRepeat) {
1593 b.SetBufferOffset(bufpos);
1594 }
1595 return 0;
1596 }
1597
1598 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1599 {
1600 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1601 Int_t bufpos = b.Length();
1602
1603 TVirtualArray *cached = b.PeekDataCache();
1604 if (cached==0) {
1605 TStreamerElement *aElement = config->fCompInfo->fElem;
1606 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1607 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1608 char *ptr = (char*)start;
1609 UInt_t n = (((void**)end)-((void**)start));
1610 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1611 } else {
1612 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1613 void *cached_start = (*cached)[0];
1614 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1615 config->fAction(b,cached_start,cached_end,&cached_config);
1616 }
1617 // Idea: Factor out this 'if' to a UseCacheRepeat function
1618 if (config->fNeedRepeat) {
1619 b.SetBufferOffset(bufpos);
1620 }
1621 return 0;
1622 }
1623
1624 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1625 {
1626 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1627
1628 Int_t bufpos = b.Length();
1629 TVirtualArray *cached = b.PeekDataCache();
1630 if (cached==0) {
1631 TStreamerElement *aElement = config->fCompInfo->fElem;
1632 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1633 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1634 char *ptr = (char*)start;
1635 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1636 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1637 } else {
1638 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1639 void *cached_start = (*cached)[0];
1640 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1641 config->fAction(b,cached_start,cached_end,&cached_config);
1642 }
1643 // Idea: Factor out this 'if' to a UseCacheRepeat function
1644 if (config->fNeedRepeat) {
1645 b.SetBufferOffset(bufpos);
1646 }
1647 return 0;
1648 }
1649
1651 {
1652 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1653
1654 Int_t bufpos = b.Length();
1655 TVirtualArray *cached = b.PeekDataCache();
1656 if (cached==0) {
1657 TStreamerElement *aElement = config->fCompInfo->fElem;
1658 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1659
1660 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1661 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1662 UInt_t n = proxy->Size();
1663 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1664 } else {
1665 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1666 void *cached_start = (*cached)[0];
1667 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1668 config->fAction(b,cached_start,cached_end,&cached_config);
1669 }
1670 // Idea: Factor out this 'if' to a UseCacheRepeat function
1671 if (config->fNeedRepeat) {
1672 b.SetBufferOffset(bufpos);
1673 }
1674 return 0;
1675 }
1676
1677 // Support for collections.
1678
1679 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1680 {
1681 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1682 return 0;
1683 }
1684
1685 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1686 {
1687 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1688 return 0;
1689 }
1690
1692
1694 {
1696 return kVectorLooper;
1697 } else if ( (proxy.GetCollectionType() == ROOT::kSTLvector)) {
1699 return kGenericLooper;
1700 else
1701 return kVectorLooper;
1706 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1707 return kAssociativeLooper;
1708 } else {
1709 return kGenericLooper;
1710 }
1711 }
1712
1713 struct VectorLooper {
1714
1715 template <typename T>
1716 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1717 {
1718 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1719 iter = (char*)iter + config->fOffset;
1720 end = (char*)end + config->fOffset;
1721 for(; iter != end; iter = (char*)iter + incr ) {
1722 T *x = (T*) ((char*) iter);
1723 buf >> *x;
1724 }
1725 return 0;
1726 }
1727
1728 template <typename From, typename To>
1729 struct ConvertBasicType {
1730 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1731 {
1732 // Simple conversion from a 'From' on disk to a 'To' in memory.
1733 From temp;
1734 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1735 iter = (char*)iter + config->fOffset;
1736 end = (char*)end + config->fOffset;
1737 for(; iter != end; iter = (char*)iter + incr ) {
1738 buf >> temp;
1739 *(To*)( ((char*)iter) ) = (To)temp;
1740 }
1741 return 0;
1742 }
1743 };
1744
1745 template <typename To>
1746 struct ConvertBasicType<BitsMarker,To> {
1747 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1748 {
1749 // Simple conversion from a 'From' on disk to a 'To' in memory.
1750 UInt_t temp;
1751 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1752 iter = (char*)iter + config->fOffset;
1753 end = (char*)end + config->fOffset;
1754 for(; iter != end; iter = (char*)iter + incr ) {
1755 buf >> temp;
1756
1757 if ((temp & kIsReferenced) != 0) {
1758 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1759 }
1760
1761 *(To*)( ((char*)iter) ) = (To)temp;
1762 }
1763 return 0;
1764 }
1765 };
1766
1767 template <typename From, typename To>
1768 struct ConvertBasicType<WithFactorMarker<From>,To> {
1769 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1770 {
1771 // Simple conversion from a 'From' on disk to a 'To' in memory.
1772 TConfWithFactor *conf = (TConfWithFactor *)config;
1773 From temp;
1774 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1775 iter = (char*)iter + config->fOffset;
1776 end = (char*)end + config->fOffset;
1777 for(; iter != end; iter = (char*)iter + incr ) {
1778 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1779 *(To*)( ((char*)iter) ) = (To)temp;
1780 }
1781 return 0;
1782 }
1783 };
1784
1785 template <typename From, typename To>
1786 struct ConvertBasicType<NoFactorMarker<From>,To> {
1787 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1788 {
1789 // Simple conversion from a 'From' on disk to a 'To' in memory.
1790 TConfNoFactor *conf = (TConfNoFactor *)config;
1791 From temp;
1792 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1793 iter = (char*)iter + config->fOffset;
1794 end = (char*)end + config->fOffset;
1795 for(; iter != end; iter = (char*)iter + incr ) {
1796 buf.ReadWithNbits(&temp, conf->fNbits);
1797 *(To*)( ((char*)iter) ) = (To)temp;
1798 }
1799 return 0;
1800 }
1801 };
1802
1803 template <typename T>
1804 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1805 {
1806 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1807 iter = (char*)iter + config->fOffset;
1808 end = (char*)end + config->fOffset;
1809 for(; iter != end; iter = (char*)iter + incr ) {
1810 T *x = (T*) ((char*) iter);
1811 buf << *x;
1812 }
1813 return 0;
1814 }
1815
1816 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1817 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1818 {
1819 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1820 //Idea: can we factor out the addition of fOffset
1821 // iter = (char*)iter + config->fOffset;
1822 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1823 iter_action(buf, iter, config);
1824 }
1825 return 0;
1826 }
1827
1828 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1829 {
1830 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1831 // punt.
1832
1833 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1834 UInt_t n = (((char*)end)-((char*)start))/incr;
1835 char **arrptr = new char*[n];
1836 UInt_t i = 0;
1837 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1838 arrptr[i] = (char*)iter;
1839 }
1840 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1841 delete [] arrptr;
1842
1843 // // Idea: need to cache this result!
1844 // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1845 // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1846 //
1847 // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1848 // *TClass *cle = aElement->GetNewBaseClass();
1849 // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1850 //
1851 // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1852 //
1853 // actions->ReadBuffer(b,start,end);
1854 // delete actions;
1855
1856 // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1857 // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1858 // {
1859 // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1860 //
1861 // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1862 // }
1863 return 0;
1864 }
1865
1866 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1867 {
1868 // Well the implementation is non trivial. For now punt.
1869
1870 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1871 UInt_t n = (((char*)end)-((char*)start))/incr;
1872 char **arrptr = new char*[n];
1873 UInt_t i = 0;
1874 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1875 arrptr[i] = (char*)iter;
1876 }
1877 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1878 delete [] arrptr;
1879 return 0;
1880 }
1881
1882 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1883 {
1884 // Well the implementation is non trivial. For now punt.
1885
1886 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1887 UInt_t n = (((char*)end)-((char*)start))/incr;
1888 char **arrptr = new char*[n];
1889 UInt_t i = 0;
1890 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1891 arrptr[i] = (char*)iter;
1892 }
1893 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1894 delete [] arrptr;
1895 return 0;
1896 }
1897
1898 template <typename T>
1899 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1900 {
1901 // Collection of numbers. Memberwise or not, it is all the same.
1902
1903 TConfigSTL *config = (TConfigSTL*)conf;
1904 UInt_t start, count;
1905 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1906
1907 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1908 Int_t nvalues;
1909 buf.ReadInt(nvalues);
1910 vec->resize(nvalues);
1911
1912#ifdef R__VISUAL_CPLUSPLUS
1913 if (nvalues <= 0) {
1914 buf.CheckByteCount(start,count,config->fTypeName);
1915 return 0;
1916 }
1917#endif
1918 T *begin = &(*vec->begin());
1919 buf.ReadFastArray(begin, nvalues);
1920
1921 buf.CheckByteCount(start,count,config->fTypeName);
1922 return 0;
1923 }
1924
1925 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1926 {
1927 // Collection of numbers. Memberwise or not, it is all the same.
1928
1929 TConfigSTL *config = (TConfigSTL*)conf;
1930 UInt_t start, count;
1931 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1932
1933 std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1934 Int_t nvalues;
1935 buf.ReadInt(nvalues);
1936 vec->resize(nvalues);
1937
1938 bool *items = new bool[nvalues];
1939 buf.ReadFastArray(items, nvalues);
1940 for(Int_t i = 0 ; i < nvalues; ++i) {
1941 (*vec)[i] = items[i];
1942 }
1943 delete [] items;
1944
1945 // We could avoid the call to ReadFastArray, and we could
1946 // the following, however this breaks TBufferXML ...
1947 // for(Int_t i = 0 ; i < nvalues; ++i) {
1948 // bool tmp; buf >> tmp;
1949 // (*vec)[i] = tmp;
1950 // }
1951
1952 buf.CheckByteCount(start,count,config->fTypeName);
1953 return 0;
1954 }
1955
1956 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1957 {
1958 // Collection of numbers. Memberwise or not, it is all the same.
1959
1960 TConfigSTL *config = (TConfigSTL*)conf;
1961 UInt_t start, count;
1962 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1963
1964 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1965 Int_t nvalues;
1966 buf.ReadInt(nvalues);
1967 vec->resize(nvalues);
1968
1969#ifdef R__VISUAL_CPLUSPLUS
1970 if (nvalues <= 0) {
1971 buf.CheckByteCount(start,count,config->fTypeName);
1972 return 0;
1973 }
1974#endif
1975 float *begin = &(*vec->begin());
1976 buf.ReadFastArrayFloat16(begin, nvalues);
1977
1978 buf.CheckByteCount(start,count,config->fTypeName);
1979 return 0;
1980 }
1981
1982 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1983 {
1984 // Collection of numbers. Memberwise or not, it is all the same.
1985
1986 TConfigSTL *config = (TConfigSTL*)conf;
1987 UInt_t start, count;
1988 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1989
1990 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1991 Int_t nvalues;
1992 buf.ReadInt(nvalues);
1993 vec->resize(nvalues);
1994
1995#ifdef R__VISUAL_CPLUSPLUS
1996 if (nvalues <= 0) {
1997 buf.CheckByteCount(start,count,config->fTypeName);
1998 return 0;
1999 }
2000#endif
2001 double *begin = &(*vec->begin());
2002 buf.ReadFastArrayDouble32(begin, nvalues);
2003
2004 buf.CheckByteCount(start,count,config->fTypeName);
2005 return 0;
2006 }
2007
2008 template <typename From, typename To>
2009 struct ConvertCollectionBasicType {
2010 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2011 {
2012 // Collection of numbers. Memberwise or not, it is all the same.
2013
2014 TConfigSTL *config = (TConfigSTL*)conf;
2015 UInt_t start, count;
2016 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2017
2018 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2019 Int_t nvalues;
2020 buf.ReadInt(nvalues);
2021 vec->resize(nvalues);
2022
2023 From *temp = new From[nvalues];
2024 buf.ReadFastArray(temp, nvalues);
2025 for(Int_t ind = 0; ind < nvalues; ++ind) {
2026 (*vec)[ind] = (To)temp[ind];
2027 }
2028 delete [] temp;
2029
2030 buf.CheckByteCount(start,count,config->fTypeName);
2031 return 0;
2032 }
2033 };
2034
2035 template <typename From, typename To>
2036 struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
2037 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2038 {
2039 // Collection of numbers. Memberwise or not, it is all the same.
2040
2041 TConfigSTL *config = (TConfigSTL*)conf;
2042 UInt_t start, count;
2043 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2044
2045 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2046 Int_t nvalues;
2047 buf.ReadInt(nvalues);
2048 vec->resize(nvalues);
2049
2050 From *temp = new From[nvalues];
2051 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2052 for(Int_t ind = 0; ind < nvalues; ++ind) {
2053 (*vec)[ind] = (To)temp[ind];
2054 }
2055 delete [] temp;
2056
2057 buf.CheckByteCount(start,count,config->fTypeName);
2058 return 0;
2059 }
2060 };
2061
2062 template <typename To>
2063 static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2064 {
2065 // Collection of numbers. Memberwise or not, it is all the same.
2066
2067 TConfigSTL *config = (TConfigSTL*)conf;
2068 UInt_t start, count;
2069 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2070
2071 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2072 Int_t nvalues;
2073 buf.ReadInt(nvalues);
2074 vec->resize(nvalues);
2075
2076 Double32_t *temp = new Double32_t[nvalues];
2077 buf.ReadFastArrayDouble32(temp, nvalues);
2078 for(Int_t ind = 0; ind < nvalues; ++ind) {
2079 (*vec)[ind] = (To)temp[ind];
2080 }
2081 delete [] temp;
2082
2083 buf.CheckByteCount(start,count,config->fTypeName);
2084 return 0;
2085 }
2086
2087 };
2088
2089 struct VectorPtrLooper {
2090
2091 template <typename T>
2092 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2093 {
2094 const Int_t offset = config->fOffset;
2095
2096 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2097 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2098 buf >> *x;
2099 }
2100 return 0;
2101 }
2102
2103 template <typename From, typename To>
2104 struct ConvertBasicType {
2105 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2106 {
2107 // Simple conversion from a 'From' on disk to a 'To' in memory.
2108 From temp;
2109 const Int_t offset = config->fOffset;
2110 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2111 buf >> temp;
2112 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2113 *x = (To)temp;
2114 }
2115 return 0;
2116 }
2117 };
2118
2119 template <typename To>
2120 struct ConvertBasicType<BitsMarker,To> {
2121 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2122 {
2123 // Simple conversion from a 'From' on disk to a 'To' in memory.
2124 UInt_t temp;
2125 const Int_t offset = config->fOffset;
2126 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2127 buf >> temp;
2128
2129 if ((temp & kIsReferenced) != 0) {
2130 HandleReferencedTObject(buf,*(void**)iter,config);
2131 }
2132
2133 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2134 *x = (To)temp;
2135 }
2136 return 0;
2137 }
2138 };
2139
2140 template <typename From, typename To>
2141 struct ConvertBasicType<WithFactorMarker<From>,To> {
2142 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2143 {
2144 // Simple conversion from a 'From' on disk to a 'To' in memory.
2145 TConfWithFactor *conf = (TConfWithFactor *)config;
2146 From temp;
2147 const Int_t offset = config->fOffset;
2148 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2149 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2150 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2151 *x = (To)temp;
2152 }
2153 return 0;
2154 }
2155 };
2156
2157 template <typename From, typename To>
2158 struct ConvertBasicType<NoFactorMarker<From>,To> {
2159 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2160 {
2161 // Simple conversion from a 'From' on disk to a 'To' in memory.
2162 TConfNoFactor *conf = (TConfNoFactor *)config;
2163 From temp;
2164 const Int_t offset = config->fOffset;
2165 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2166 buf.ReadWithNbits(&temp, conf->fNbits);
2167 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2168 *x = (To)temp;
2169 }
2170 return 0;
2171 }
2172 };
2173
2174 template <typename T>
2175 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2176 {
2177 const Int_t offset = config->fOffset;
2178
2179 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2180 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2181 buf << *x;
2182 }
2183 return 0;
2184 }
2185
2186 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2187 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2188 {
2189 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2190 action(buf, *(void**)iter, config);
2191 }
2192 return 0;
2193 }
2194
2195 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2196 {
2197 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2198 // punt.
2199
2200 return GenericRead(buf,start,end,config);
2201 }
2202
2203 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2204 {
2205 Int_t n = ( ((void**)end) - ((void**)iter) );
2206 char **arr = (char**)iter;
2207 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2208 }
2209
2210 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2211 {
2212 Int_t n = ( ((void**)end) - ((void**)iter) );
2213 char **arr = (char**)iter;
2214 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2215 }
2216
2217 };
2218
2219 struct AssociativeLooper {
2220
2221 template <typename T>
2222 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2223 {
2224 buf.ReadFastArray((T*)addr, nvalues);
2225 }
2226
2227 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2228 {
2229 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2230 }
2231
2232 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2233 {
2234 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2235 }
2236
2237 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2238 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2239 {
2240 // Collection of numbers. Memberwise or not, it is all the same.
2241
2242 TConfigSTL *config = (TConfigSTL*)conf;
2243 UInt_t start, count;
2244 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2245
2246 TClass *newClass = config->fNewClass;
2247 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2248 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2249
2250 Int_t nvalues;
2251 buf.ReadInt(nvalues);
2252 void* alternative = newProxy->Allocate(nvalues,true);
2253 if (nvalues) {
2256 void *begin = &(startbuf[0]);
2257 void *end = &(endbuf[0]);
2258 config->fCreateIterators(alternative, &begin, &end, newProxy);
2259 // We can not get here with a split vector of pointer, so we can indeed assume
2260 // that actions->fConfiguration != null.
2261
2262 action(buf,begin,nvalues);
2263
2264 if (begin != &(startbuf[0])) {
2265 // assert(end != endbuf);
2266 config->fDeleteTwoIterators(begin,end);
2267 }
2268 }
2269 newProxy->Commit(alternative);
2270
2271 buf.CheckByteCount(start,count,config->fTypeName);
2272 return 0;
2273 }
2274
2275 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2276 {
2277 return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2278 }
2279
2280 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2281 {
2282 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2283 }
2284
2285 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2286 {
2287 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2288 }
2289
2290 template <typename T>
2291 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2292 {
2293 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2294 }
2295
2296 template <typename From, typename To>
2297 struct ConvertRead {
2298 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2299 {
2300 From *temp = new From[nvalues];
2301 buf.ReadFastArray(temp, nvalues);
2302 To *vec = (To*)addr;
2303 for(Int_t ind = 0; ind < nvalues; ++ind) {
2304 vec[ind] = (To)temp[ind];
2305 }
2306 delete [] temp;
2307 }
2308 };
2309
2310 template <typename From, typename To>
2311 struct ConvertRead<NoFactorMarker<From>,To> {
2312 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2313 {
2314 From *temp = new From[nvalues];
2315 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2316 To *vec = (To*)addr;
2317 for(Int_t ind = 0; ind < nvalues; ++ind) {
2318 vec[ind] = (To)temp[ind];
2319 }
2320 delete [] temp;
2321 }
2322 };
2323
2324 template <typename From, typename To>
2325 struct ConvertRead<WithFactorMarker<From>,To> {
2326 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2327 {
2328 From *temp = new From[nvalues];
2329 double factor,min; // needs to be initialized.
2330 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2331 To *vec = (To*)addr;
2332 for(Int_t ind = 0; ind < nvalues; ++ind) {
2333 vec[ind] = (To)temp[ind];
2334 }
2335 delete [] temp;
2336 }
2337 };
2338
2339 template <typename From, typename To>
2340 struct ConvertCollectionBasicType {
2341 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2342 {
2343 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2344 }
2345 };
2346
2347 };
2348
2349 struct GenericLooper {
2350
2351 template <typename T>
2352 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2353 {
2354 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2355
2356 Next_t next = loopconfig->fNext;
2357 const Int_t offset = config->fOffset;
2358
2360 void *iter = loopconfig->fCopyIterator(iterator,start);
2361 void *addr;
2362 while( (addr = next(iter,end)) ) {
2363 T *x = (T*)( ((char*)addr) + offset );
2364 buf >> *x;
2365 }
2366 if (iter != &iterator[0]) {
2367 loopconfig->fDeleteIterator(iter);
2368 }
2369 return 0;
2370 }
2371
2372 template <typename T>
2373 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2374 {
2375 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2376
2377 Next_t next = loopconfig->fNext;
2378 const Int_t offset = config->fOffset;
2379
2381 void *iter = loopconfig->fCopyIterator(iterator,start);
2382 void *addr;
2383 while( (addr = next(iter,end)) ) {
2384 T *x = (T*)( ((char*)addr) + offset );
2385 buf << *x;
2386 }
2387 if (iter != &iterator[0]) {
2388 loopconfig->fDeleteIterator(iter);
2389 }
2390 return 0;
2391 }
2392
2393 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2394 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2395 {
2396 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2397
2398 // const Int_t offset = config->fOffset;
2399 Next_t next = loopconfig->fNext;
2400
2402 void *iter = loopconfig->fCopyIterator(&iterator,start);
2403 void *addr;
2404 while( (addr = next(iter,end)) ) {
2405 iter_action(buf, addr, config);
2406 }
2407 if (iter != &iterator[0]) {
2408 loopconfig->fDeleteIterator(iter);
2409 }
2410 return 0;
2411 }
2412
2413 template <typename From, typename To>
2414 struct Generic {
2415 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2416 {
2417 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2418
2419 const Int_t offset = config->fOffset;
2420 Next_t next = loopconfig->fNext;
2421
2423 void *iter = loopconfig->fCopyIterator(&iterator,start);
2424 void *addr;
2425 while( (addr = next(iter,end)) ) {
2426 To *x = (To*)( ((char*)addr) + offset );
2427 *x = (To)(*items);
2428 ++items;
2429 }
2430 if (iter != &iterator[0]) {
2431 loopconfig->fDeleteIterator(iter);
2432 }
2433 }
2434 };
2435
2436 template <typename From, typename To>
2437 struct Numeric {
2438 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2439 {
2440 // The difference with ConvertAction is that we can modify the start
2441 // iterator and skip the copy. We also never have an offset.
2442
2443 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2444 Next_t next = loopconfig->fNext;
2445
2446 void *iter = start;
2447 void *addr;
2448 while( (addr = next(iter,end)) ) {
2449 To *x = (To*)(addr);
2450 *x = (To)(*items);
2451 ++items;
2452 }
2453 }
2454 };
2455
2456 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2457 struct ConvertBasicType {
2458 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2459 {
2460 // Simple conversion from a 'From' on disk to a 'To' in memory.
2461
2462 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2463 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2464 Int_t nvalues = proxy->Size();
2465
2466 From *items = new From[nvalues];
2467 buf.ReadFastArray(items, nvalues);
2468 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2469 delete [] items;
2470 return 0;
2471 }
2472 };
2473
2474 template <typename To>
2475 struct ConvertBasicType<BitsMarker, To, Generic> {
2476 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2477 {
2478 // Simple conversion from a 'From' on disk to a 'To' in memory.
2479
2480 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2481 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2482 Int_t nvalues = proxy->Size();
2483
2484 UInt_t *items_storage = new UInt_t[nvalues];
2485 UInt_t *items = items_storage;
2486
2487 const Int_t offset = config->fOffset;
2488 Next_t next = loopconfig->fNext;
2489
2491 void *iter = loopconfig->fCopyIterator(&iterator,start);
2492 void *addr;
2493 while( (addr = next(iter,end)) ) {
2494 buf >> (*items);
2495 if (((*items) & kIsReferenced) != 0) {
2496 HandleReferencedTObject(buf, addr, config);
2497 }
2498 To *x = (To*)( ((char*)addr) + offset );
2499 *x = (To)(*items);
2500 ++items;
2501 }
2502 if (iter != &iterator[0]) {
2503 loopconfig->fDeleteIterator(iter);
2504 }
2505
2506 delete [] items_storage;
2507 return 0;
2508 }
2509 };
2510
2511 template <typename From, typename To, template <typename F, typename T> class Converter >
2512 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2513 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2514 {
2515 // Simple conversion from a 'From' on disk to a 'To' in memory.
2516
2517 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2518 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2519 Int_t nvalues = proxy->Size();
2520
2521 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2522
2523 From *items = new From[nvalues];
2524 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2525 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2526 delete [] items;
2527 return 0;
2528 }
2529 };
2530
2531 template <typename From, typename To, template <typename F, typename T> class Converter >
2532 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2533 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2534 {
2535 // Simple conversion from a 'From' on disk to a 'To' in memory.
2536
2537 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2538 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2539 Int_t nvalues = proxy->Size();
2540
2541 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2542
2543 From *items = new From[nvalues];
2544 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2545 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2546 delete [] items;
2547 return 0;
2548 }
2549 };
2550
2551 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2552 {
2553 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2554 // punt.
2555
2556 return GenericRead(buf,start,end,loopconfig, config);
2557 }
2558
2559 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2560 {
2561 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2562 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2563 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2564 }
2565
2566 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2567 {
2568 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2569 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2570 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2571 }
2572
2573 template <typename T>
2574 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2575 {
2576 buf >> *(T*)addr;
2577 }
2578
2579 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2580 {
2581 buf.ReadWithNbits((float*)addr,12);
2582 }
2583
2584 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2585 {
2586 //we read a float and convert it to double
2587 Float_t afloat;
2588 buf >> afloat;
2589 *(double*)addr = (Double_t)afloat;
2590 }
2591
2592 template <typename ActionHolder>
2593 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2594 {
2595 // Collection of numbers. Memberwise or not, it is all the same.
2596
2597 TConfigSTL *config = (TConfigSTL*)conf;
2598 UInt_t start, count;
2599 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2600
2601 TClass *newClass = config->fNewClass;
2602 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2603 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2604
2605 Int_t nvalues;
2606 buf.ReadInt(nvalues);
2607 void* alternative = newProxy->Allocate(nvalues,true);
2608 if (nvalues) {
2611 void *begin = &(startbuf[0]);
2612 void *end = &(endbuf[0]);
2613 config->fCreateIterators(alternative, &begin, &end, newProxy);
2614 // We can not get here with a split vector of pointer, so we can indeed assume
2615 // that actions->fConfiguration != null.
2616
2617 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2618 ActionHolder::Action(buf,begin,end,&loopconf,config);
2619
2620 if (begin != &(startbuf[0])) {
2621 // assert(end != endbuf);
2622 config->fDeleteTwoIterators(begin,end);
2623 }
2624 }
2625 newProxy->Commit(alternative);
2626
2627 buf.CheckByteCount(start,count,config->fTypeName);
2628 return 0;
2629 }
2630
2631 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2632 {
2633 return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2634 }
2635
2636 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2637 {
2638 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2639 }
2640
2641 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2642 {
2643 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2644 // Could also use:
2645 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2646 }
2647
2648 template <typename T>
2649 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2650 {
2651 //TODO: Check whether we can implement this without loading the data in
2652 // a temporary variable and whether this is noticeably faster.
2653 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2654 }
2655
2656 template <typename From, typename To>
2657 struct ConvertCollectionBasicType {
2658 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2659 {
2660 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2661 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2662 }
2663 };
2664
2665 };
2666}
2667
2668template <typename Looper, typename From>
2670{
2671 switch (newtype) {
2672 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2673 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2674 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2675 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2676 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2677 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2678 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2679 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2680 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2681 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2682 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2683 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2684 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2685 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2686 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2687 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2688 default:
2689 return TConfiguredAction( Looper::GenericRead, conf );
2690 break;
2691 }
2692 R__ASSERT(0); // We should never be here
2693 return TConfiguredAction();
2694}
2695
2696template <class Looper>
2698{
2699 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2700
2701 switch (type) {
2702 // Read basic types.
2703 case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2704 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2705 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2706 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2707 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2708 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2709 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2710 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2711 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2712 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2713 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2714 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2715 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2716 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2718 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2719 delete conf;
2720 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2721 // if (element->GetFactor() != 0) {
2722 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2723 // } else {
2724 // Int_t nbits = (Int_t)element->GetXmin();
2725 // if (!nbits) nbits = 12;
2726 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2727 // }
2728 break;
2729 }
2731 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2732 delete conf;
2733 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2734 // if (element->GetFactor() != 0) {
2735 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2736 // } else {
2737 // Int_t nbits = (Int_t)element->GetXmin();
2738 // if (!nbits) {
2739 // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2740 // } else {
2741 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2742 // }
2743 // }
2744 break;
2745 }
2746 }
2747 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2748 R__ASSERT(0); // We should never be here
2749 return TConfiguredAction();
2750}
2751
2752template <typename Looper, typename From>
2754{
2755 switch (newtype) {
2756 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2757 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2758 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2759 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2760 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2761 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2762 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2763 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2764 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2765 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2766 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2767 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2768 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2769 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2770 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2771 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2772 default:
2773 break;
2774 }
2775 R__ASSERT(0); // We should never be here
2776 return TConfiguredAction();
2777}
2778
2779template <typename Looper>
2781{
2782 switch (oldtype) {
2784 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2785 break;
2787 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2788 break;
2790 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2791 break;
2793 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2794 break;
2796 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2797 break;
2799 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2800 break;
2802 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2803 break;
2805 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2806 break;
2808 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2809 break;
2811 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2812 break;
2814 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2815 break;
2817 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2818 break;
2820 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2821 break;
2823 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2824 break;
2826 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2827 break;
2829 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2830 break;
2831 default:
2832 break;
2833 }
2834 R__ASSERT(0); // We should never be here
2835 return TConfiguredAction();
2836}
2837
2838template <class Looper>
2840{
2841 switch (type) {
2842 // Read basic types.
2843 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2844 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2845 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2846 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2847 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2848 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2849 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2850 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2851 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2852 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2853 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2854 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2855 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2856 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2858 if (element->GetFactor() != 0) {
2859 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2860 } else {
2861 Int_t nbits = (Int_t)element->GetXmin();
2862 if (!nbits) nbits = 12;
2863 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2864 }
2865 break;
2866 }
2868 if (element->GetFactor() != 0) {
2869 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2870 } else {
2871 Int_t nbits = (Int_t)element->GetXmin();
2872 if (!nbits) {
2873 return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2874 } else {
2875 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2876 }
2877 }
2878 break;
2879 }
2880 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2881 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2882 // Streamer alltogether.
2883 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2884 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2888 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2889 case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2890
2891 // Conversions.
2893 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2894 break;
2896 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2897 break;
2899 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2900 break;
2902 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2903 break;
2905 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2906 break;
2908 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2909 break;
2911 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2912 break;
2914 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2915 break;
2917 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2918 break;
2920 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2921 break;
2923 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2924 break;
2926 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2927 break;
2929 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2930 break;
2932 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2933 break;
2935 if (element->GetFactor() != 0) {
2936 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2937 } else {
2938 Int_t nbits = (Int_t)element->GetXmin();
2939 if (!nbits) nbits = 12;
2940 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2941 }
2942 break;
2943 }
2945 if (element->GetFactor() != 0) {
2946 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2947 } else {
2948 Int_t nbits = (Int_t)element->GetXmin();
2949 if (!nbits) {
2950 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2951 } else {
2952 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2953 }
2954 }
2955 break;
2956 }
2957 default:
2958 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2959 break;
2960 }
2961 R__ASSERT(0); // We should never be here
2962 return TConfiguredAction();
2963}
2964
2965template <class Looper>
2967 switch (type) {
2968 // read basic types
2969 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2970 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2971 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2972 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2973 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2974 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2975 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2976 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2977 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2978 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2979 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2980 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2981 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2982 // the simple type missing are kBits and kCounter.
2983 default:
2984 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2985 }
2986 R__ASSERT(0); // We should never be here
2987 return TConfiguredAction();
2988}
2989
2990
2991////////////////////////////////////////////////////////////////////////////////
2992/// loop on the TStreamerElement list
2993/// regroup members with same type
2994/// Store predigested information into local arrays. This saves a huge amount
2995/// of time compared to an explicit iteration on all elements.
2996
2998{
2999 if (IsCompiled()) {
3000 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
3001 return;
3002 }
3004
3005 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
3006
3007 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
3009 fNdata = 0;
3010 fNfulldata = 0;
3011
3012 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
3013 if (fNumber < 0) {
3014 ++fgCount;
3015 fNumber = fgCount;
3016 }
3017 if (fNumber >= infos->GetSize()) {
3018 infos->AddAtAndExpand(this, fNumber);
3019 } else {
3020 if (!infos->At(fNumber)) {
3021 infos->AddAt(this, fNumber);
3022 }
3023 }
3024
3025 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3026
3027
3028 Int_t ndata = fElements->GetEntries();
3029
3030
3033
3036
3039
3040 if (fReadText) fReadText->fActions.clear();
3041 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3042
3045
3048
3051
3052 if (fWriteText) fWriteText->fActions.clear();
3054
3055 if (!ndata) {
3056 // This may be the case for empty classes (e.g., TAtt3D).
3057 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3059 fSize = sizeof(TStreamerInfo*);
3060 }
3061 fComp = new TCompInfo[1];
3062 fCompFull = new TCompInfo*[1];
3063 fCompOpt = new TCompInfo*[1];
3064 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3065 SetIsCompiled();
3066 return;
3067 }
3068
3069 // At most half of the elements can be used to hold optimized versions.
3070 // We use the bottom to hold the optimized-into elements and the non-optimized elements
3071 // and the top to hold the original copy of the optimized out elements.
3072 fNslots = ndata + ndata/2 + 1;
3073 Int_t optiOut = 0;
3074
3075 fComp = new TCompInfo[fNslots];
3076 fCompFull = new TCompInfo*[ndata];
3077 fCompOpt = new TCompInfo*[ndata];
3078
3079 TStreamerElement* element;
3080 TStreamerElement* previous = 0;
3081 Int_t keep = -1;
3082 Int_t i;
3083
3084 if (!CanOptimize()) {
3086 }
3087
3088 Bool_t isOptimized = kFALSE;
3089 Bool_t previousOptimized = kFALSE;
3090
3091 for (i = 0; i < ndata; ++i) {
3092 element = (TStreamerElement*) fElements->At(i);
3093 if (!element) {
3094 break;
3095 }
3096
3097 Int_t asize = element->GetSize();
3098 if (element->GetArrayLength()) {
3099 asize /= element->GetArrayLength();
3100 }
3101 fComp[fNdata].fType = element->GetType();
3102 fComp[fNdata].fNewType = element->GetNewType();
3103 fComp[fNdata].fOffset = element->GetOffset();
3104 fComp[fNdata].fLength = element->GetArrayLength();
3105 fComp[fNdata].fElem = element;
3106 fComp[fNdata].fMethod = element->GetMethod();
3107 fComp[fNdata].fClass = element->GetClassPointer();
3108 fComp[fNdata].fNewClass = element->GetNewClass();
3110 fComp[fNdata].fStreamer = element->GetStreamer();
3111
3112 // try to group consecutive members of the same type
3114 && (keep >= 0)
3115 && (element->GetType() > 0)
3116 && (element->GetType() < 10)
3118 && (fComp[keep].fMethod == 0)
3119 && (element->GetArrayDim() == 0)
3120 && (fComp[keep].fType < kObject)
3121 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3122 && (element->GetType() == (fComp[keep].fType%kRegrouped))
3123 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3124 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3125 ((element->GetFactor() == previous->GetFactor())
3126 && (element->GetXmin() == previous->GetXmin())
3127 && (element->GetXmax() == previous->GetXmax())
3128 )
3129 )
3132 // kWholeObject and kDoNotDelete do not apply to numerical elements.
3133 )
3134 {
3135 if (!previousOptimized) {
3136 // The element was not yet optimized we first need to copy it into
3137 // the set of original copies.
3138 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3139 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3140 }
3141 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3142 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3143
3144 R__ASSERT( keep < (fNslots - optiOut) );
3145
3146 if (fComp[keep].fLength == 0) {
3147 fComp[keep].fLength++;
3148 }
3149 fComp[keep].fLength++;
3150 fComp[keep].fType = element->GetType() + kRegrouped;
3151 isOptimized = kTRUE;
3152 previousOptimized = kTRUE;
3153 } else if (element->GetType() < 0) {
3154
3155 // -- Deal with an ignored TObject base class.
3156 // Note: The only allowed negative value here is -1,
3157 // and signifies that Build() has found a TObject
3158 // base class and TClass::IgnoreTObjectStreamer() was
3159 // called. In this case the compiled version of the
3160 // elements omits the TObject base class element,
3161 // which has to be compensated for by TTree::Bronch()
3162 // when it is making branches for a split object.
3163 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3164 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3165 keep = -1;
3166 previousOptimized = kFALSE;
3167
3168 } else {
3169 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3170 if (fComp[fNdata].fNewType > 0) {
3171 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3172 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3173 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3177 ) {
3179 } else if (fComp[fNdata].fType != kCounter) {
3180 fComp[fNdata].fType += kConv;
3181 }
3182 } else {
3183 if (fComp[fNdata].fType == kCounter) {
3184 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3185 }
3186 fComp[fNdata].fType += kSkip;
3187 }
3188 }
3189 fCompOpt[fNdata] = &(fComp[fNdata]);
3191
3192 R__ASSERT( fNdata < (fNslots - optiOut) );
3193
3194 keep = fNdata;
3195 if (fComp[keep].fLength == 0) {
3196 fComp[keep].fLength = 1;
3197 }
3198 fNdata++;
3199 previousOptimized = kFALSE;
3200 }
3201 // The test 'fMethod[keep] == 0' fails to detect a variable size array
3202 // if the counter happens to have an offset of zero, so let's explicitly
3203 // prevent for here.
3204 if (element->HasCounter()) keep = -1;
3205 ++fNfulldata;
3206 previous = element;
3207 }
3208
3209 for (i = 0; i < fNdata; ++i) {
3210 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3211 continue;
3212 }
3215 }
3216 for (i = 0; i < fNfulldata; ++i) {
3217 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3218 continue;
3219 }
3224
3227 }
3228 ComputeSize();
3229
3230 fOptimized = isOptimized;
3231 SetIsCompiled();
3232
3233 if (gDebug > 0) {
3234 ls();
3235 }
3236}
3237
3238template <typename From>
3240{
3241 switch (newtype) {
3242 case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
3243 case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
3244 case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
3245 case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
3246 case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
3247 case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
3248 case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3249 case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3250 case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3251 case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3252 case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
3253 case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
3254 case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3255 case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
3256 case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
3257 case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3258 }
3259}
3260
3261////////////////////////////////////////////////////////////////////////////////
3262/// Add a read action for the given element.
3263
3265{
3266 TStreamerElement *element = compinfo->fElem;
3267
3268 if (element->TestBit(TStreamerElement::kWrite)) return;
3269
3270 switch (compinfo->fType) {
3271 // read basic types
3272 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3273 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3274 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3275 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3276 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3277 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3278 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3279 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3280 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3281 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3282 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3283 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3284 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3285 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3287 if (element->GetFactor() != 0) {
3288 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3289 } else {
3290 Int_t nbits = (Int_t)element->GetXmin();
3291 if (!nbits) nbits = 12;
3292 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3293 }
3294 break;
3295 }
3297 if (element->GetFactor() != 0) {
3298 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3299 } else {
3300 Int_t nbits = (Int_t)element->GetXmin();
3301 if (!nbits) {
3302 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3303 } else {
3304 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3305 }
3306 }
3307 break;
3308 }
3309 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3310 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3311 // Streamer alltogether.
3312 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3313 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3314 case TStreamerInfo::kSTL: {
3315 TClass *newClass = element->GetNewClass();
3316 TClass *oldClass = element->GetClassPointer();
3317 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3318
3319 if (element->GetArrayLength() <= 1) {
3320 if (fOldVersion<3){ // case of old TStreamerInfo
3321 if (newClass && newClass != oldClass) {
3322 if (element->GetStreamer()) {
3323 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3324 } else {
3325 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3326 }
3327 } else {
3328 if (element->GetStreamer()) {
3329 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3330 } else {
3331 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3332 }
3333 }
3334 } else {
3335 if (newClass && newClass != oldClass) {
3336 if (element->GetStreamer()) {
3337 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3338 } else {
3339 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3340 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3341 } else {
3342 switch (SelectLooper(*newClass->GetCollectionProxy())) {
3343 case kVectorLooper:
3344 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3345 break;
3346 case kAssociativeLooper:
3347 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3348 break;
3349 case kVectorPtrLooper:
3350 case kGenericLooper:
3351 default:
3352 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3353 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3354 break;
3355 }
3356 }
3357 }
3358 } else {
3359 if (element->GetStreamer()) {
3360 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3361 } else {
3362 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3363 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3364 } else {
3365 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3366 case kVectorLooper:
3367 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3368 break;
3369 case kAssociativeLooper:
3370 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3371 break;
3372 case kVectorPtrLooper:
3373 case kGenericLooper:
3374 default:
3375 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3376 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3377 break;
3378 }
3379 }
3380 }
3381 }
3382 }
3383 } else {
3384 if (fOldVersion<3){ // case of old TStreamerInfo
3385 if (newClass && newClass != oldClass) {
3386 if (element->GetStreamer()) {
3387 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3388 } else {
3389 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3390 }
3391 } else {
3392 if (element->GetStreamer()) {
3393 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3394 } else {
3395 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3396 }
3397 }
3398 } else {
3399 if (newClass && newClass != oldClass) {
3400 if (element->GetStreamer()) {
3401 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3402 } else {
3403 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3404 }
3405 } else {
3406 if (element->GetStreamer()) {
3407 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3408 } else {
3409 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3410 }
3411 }
3412 }
3413 }
3414 break;
3415 }
3416
3418 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3419 break;
3421 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3422 break;
3424 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3425 break;
3427 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3428 break;
3430 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3431 break;
3433 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3434 break;
3436 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3437 break;
3439 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3440 break;
3442 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3443 break;
3445 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3446 break;
3448 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3449 break;
3451 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3452 break;
3454 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3455 break;
3457 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3458 break;
3460 if (element->GetFactor() != 0) {
3461 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3462 } else {
3463 Int_t nbits = (Int_t)element->GetXmin();
3464 if (!nbits) nbits = 12;
3465 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3466 }
3467 break;
3468 }
3470 if (element->GetFactor() != 0) {
3471 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3472 } else {
3473 Int_t nbits = (Int_t)element->GetXmin();
3474 if (!nbits) {
3475 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3476 } else {
3477 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3478 }
3479 }
3480 break;
3481 }
3482 default:
3483 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3484 break;
3485 }
3486 if (element->TestBit(TStreamerElement::kCache)) {
3487 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3488 readSequence->fActions.pop_back();
3489 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3490 }
3491}
3492
3493////////////////////////////////////////////////////////////////////////////////
3494/// Add a read text action for the given element.
3495
3497{
3498 TStreamerElement *element = compinfo->fElem;
3499
3500 if (element->TestBit(TStreamerElement::kWrite))
3501 return;
3502
3503 Bool_t generic = kFALSE, isBase = kFALSE;
3504
3505 switch (compinfo->fType) {
3507 if (element->IsBase())
3508 isBase = kTRUE;
3509 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3510 else
3511 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3512 break;
3513
3515 if (element->IsBase())
3516 isBase = kTRUE;
3517 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3518 else
3519 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3520 break;
3521
3522 case TStreamerInfo::kObject: // Class derived from TObject
3523 case TStreamerInfo::kAny: // Class NOT derived from TObject
3526 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3527 break;
3528
3529 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3531 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3532 readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3533 break;
3534
3537 readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3538 break;
3539
3540 case TStreamerInfo::kBase: isBase = kTRUE; break;
3541
3543 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3544 break;
3545
3546 default: generic = kTRUE; break;
3547 }
3548
3549 if (isBase) {
3550 if (compinfo->fStreamer) {
3551 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3552 } else {
3553 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3554 }
3555 } else if (generic)
3556 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3557}
3558
3559////////////////////////////////////////////////////////////////////////////////
3560/// Add a read action for the given element.
3561/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3562
3564{
3565 TStreamerElement *element = compinfo->fElem;
3566
3567 if (element->TestBit(TStreamerElement::kWrite)) return;
3568
3569 if (element->TestBit(TStreamerElement::kCache)) {
3570 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3571 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3572 } else {
3573 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3574 }
3575}
3576
3577////////////////////////////////////////////////////////////////////////////////
3578
3580{
3581 TStreamerElement *element = compinfo->fElem;
3583 // Skip element cached for reading purposes.
3584 return;
3585 }
3586 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3587 // Skip artificial element used for reading purposes.
3588 return;
3589 }
3590 switch (compinfo->fType) {
3591 // write basic types
3592 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3593 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3594 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3595 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3596 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3597 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3598 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3599 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3600 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3601 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3602 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3603 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3604 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3605 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3606 /*case TStreamerInfo::kFloat16: {
3607 if (element->GetFactor() != 0) {
3608 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3609 } else {
3610 Int_t nbits = (Int_t)element->GetXmin();
3611 if (!nbits) nbits = 12;
3612 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3613 }
3614 break;
3615 } */
3616 /*case TStreamerInfo::kDouble32: {
3617 if (element->GetFactor() != 0) {
3618 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3619 } else {
3620 Int_t nbits = (Int_t)element->GetXmin();
3621 if (!nbits) {
3622 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3623 } else {
3624 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3625 }
3626 }
3627 break;
3628 } */
3629 //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3630 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3631 // Streamer alltogether.
3632 //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3633 //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3634 /*case TStreamerInfo::kSTL: {
3635 TClass *newClass = element->GetNewClass();
3636 TClass *oldClass = element->GetClassPointer();
3637 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3638
3639 if (element->GetArrayLength() <= 1) {
3640 if (newClass && newClass != oldClass) {
3641 if (element->GetStreamer()) {
3642 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3643 } else {
3644 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3645 }
3646 } else {
3647 if (element->GetStreamer()) {
3648 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3649 } else {
3650 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3651 }
3652 }
3653 } else {
3654 if (newClass && newClass != oldClass) {
3655 if (element->GetStreamer()) {
3656 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3657 } else {
3658 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3659 }
3660 } else {
3661 if (element->GetStreamer()) {
3662 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3663 } else {
3664 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3665 }
3666 }
3667 }
3668 break;
3669 } */
3670 default:
3671 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3672 break;
3673 }
3674#if defined(CDJ_NO_COMPILE)
3675 if (element->TestBit(TStreamerElement::kCache)) {
3676 TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3677 writeSequence->fActions.pop_back();
3678 writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3679 }
3680#endif
3681}
3682
3683////////////////////////////////////////////////////////////////////////////////
3684
3686{
3687 TStreamerElement *element = compinfo->fElem;
3689 // Skip element cached for reading purposes.
3690 return;
3691 }
3692 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3693 // Skip artificial element used for reading purposes.
3694 return;
3695 }
3696
3697 Bool_t generic = kFALSE, isBase = kFALSE;
3698
3699 switch (compinfo->fType) {
3700 // write basic types
3702 writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3703 break;
3705 writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3706 break;
3708 writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3709 break;
3711 writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3712 break;
3714 writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3715 break;
3717 writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3718 break;
3720 writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3721 break;
3723 writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3724 break;
3726 writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3727 break;
3729 writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3730 break;
3732 writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3733 break;
3735 writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3736 break;
3738 writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3739 break;
3740
3742 if (element->IsBase())
3743 isBase = kTRUE;
3744 else
3745 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3746 break;
3747
3749 if (element->IsBase())
3750 isBase = kTRUE;
3751 else
3752 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3753 break;
3754
3755 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3757 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3758 writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3759 break;
3760
3763 writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3764 break;
3765
3766 case TStreamerInfo::kBase: isBase = kTRUE; break;
3767
3769 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3770 break;
3771
3772 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3773 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3774 /*case TStreamerInfo::kFloat16: {
3775 if (element->GetFactor() != 0) {
3776 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3777 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3778 } else {
3779 Int_t nbits = (Int_t)element->GetXmin();
3780 if (!nbits) nbits = 12;
3781 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3782 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3783 }
3784 break;
3785 } */
3786 /*case TStreamerInfo::kDouble32: {
3787 if (element->GetFactor() != 0) {
3788 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3789 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3790 } else {
3791 Int_t nbits = (Int_t)element->GetXmin();
3792 if (!nbits) {
3793 writeSequence->AddAction( ConvertBasicType<float,double>, new
3794 TConfiguration(this,i,compinfo,compinfo->fOffset) );
3795 } else {
3796 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3797 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3798 }
3799 }
3800 break;
3801 } */
3802 // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3803 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3804 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3805 // Streamer alltogether.
3806 // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3807 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3808 // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3809 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3810 /*case TStreamerInfo::kSTL: {
3811 TClass *newClass = element->GetNewClass();
3812 TClass *oldClass = element->GetClassPointer();
3813 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3814
3815 if (element->GetArrayLength() <= 1) {
3816 if (newClass && newClass != oldClass) {
3817 if (element->GetStreamer()) {
3818 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3819 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3820 } else {
3821 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3822 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3823 }
3824 } else {
3825 if (element->GetStreamer()) {
3826 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3827 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3828 } else {
3829 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3830 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3831 }
3832 }
3833 } else {
3834 if (newClass && newClass != oldClass) {
3835 if (element->GetStreamer()) {
3836 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3837 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3838 } else {
3839 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3840 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3841 }
3842 } else {
3843 if (element->GetStreamer()) {
3844 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3845 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3846 } else {
3847 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3848 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3849 }
3850 }
3851 }
3852 break;
3853 } */
3854 default: generic = kTRUE; break;
3855 }
3856
3857 if (isBase) {
3858 if (compinfo->fStreamer) {
3859 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3860 } else {
3861 writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3862 }
3863
3864 } else
3865
3866 // use generic write action when special handling is not provided
3867 if (generic)
3868 writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3869
3870#if defined(CDJ_NO_COMPILE)
3871 if (element->TestBit(TStreamerElement::kCache)) {
3872 TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3873 writeSequence->fActions.pop_back();
3874 writeSequence->AddAction(UseCache,
3875 new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3876 }
3877#endif
3878}
3879
3880////////////////////////////////////////////////////////////////////////////////
3881/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3882
3884{
3885 TStreamerElement *element = compinfo->fElem;
3887 // Skip element cached for reading purposes.
3888 return;
3889 }
3890 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3891 // Skip artificial element used for reading purposes.
3892 return;
3893 }
3894
3895#if defined(CDJ_NO_COMPILE)
3896 if (element->TestBit(TStreamerElement::kCache)) {
3897 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3898 writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3899 } else {
3900 writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3901 }
3902#else
3903 writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3904#endif
3905
3906}
3907
3908////////////////////////////////////////////////////////////////////////////////
3909/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3910
3912{
3913 if (info == 0) {
3915 }
3916
3917 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3918
3919 UInt_t ndata = info->GetElements()->GetEntries();
3921 if (IsDefaultVector(proxy))
3922 {
3923 if (proxy.HasPointers()) {
3924 // Instead of the creating a new one let's copy the one from the StreamerInfo.
3925 delete sequence;
3926
3927 sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3928
3929 return sequence;
3930 }
3931
3932 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3933 Long_t increment = proxy.GetIncrement();
3934 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3939 {
3940 Long_t increment = proxy.GetIncrement();
3941 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3942 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3943 } else {
3944 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3945 }
3946 for (UInt_t i = 0; i < ndata; ++i) {
3947 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3948 if (!element) {
3949 break;
3950 }
3951 if (element->GetType() < 0) {
3952 // -- Skip an ignored TObject base class.
3953 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3954 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3955 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3956 // when it is making branches for a split object.
3957 continue;
3958 }
3959 if (element->TestBit(TStreamerElement::kWrite)) {
3960 // Skip element that only for writing.
3961 continue;
3962 }
3963 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3964 if (baseEl) {
3965 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3966 // There was a problem with the checksum, the user likely did not
3967 // increment the version number of the derived class when the
3968 // base class changed. Since we will be member wise streaming
3969 // this class, let's warn the user that something is wrong.
3970 ::Warning("CreateReadMemberWiseActions","%s",
3971 baseEl->GetErrorMessage());
3973 }
3974 }
3975
3976 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3977
3978 Int_t asize = element->GetSize();
3979 if (element->GetArrayLength()) {
3980 asize /= element->GetArrayLength();
3981 }
3982 Int_t oldType = element->GetType();
3983 Int_t newType = element->GetNewType();
3984
3985 Int_t offset = element->GetOffset();
3986 if (newType != oldType) {
3987 if (newType > 0) {
3988 if (oldType != TVirtualStreamerInfo::kCounter) {
3989 oldType += TVirtualStreamerInfo::kConv;
3990 }
3991 } else {
3992 oldType += TVirtualStreamerInfo::kSkip;
3993 }
3994 }
3995 switch (SelectLooper(proxy)) {
3996 case kAssociativeLooper:
3997// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3998// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3999// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4000 case kVectorLooper:
4001 case kVectorPtrLooper:
4002 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4003 if (element->TestBit(TStreamerElement::kCache)) {
4004 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4005 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4006 } else {
4007 sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4008 }
4009 break;
4010 case kGenericLooper:
4011 default:
4012 // The usual collection case.
4013 if (element->TestBit(TStreamerElement::kCache)) {
4014 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4015 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4016 } else {
4017 sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4018 }
4019 break;
4020 }
4021 }
4022 return sequence;
4023}
4024
4025////////////////////////////////////////////////////////////////////////////////
4026/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
4027
4029{
4030 if (info == 0) {
4032 }
4033
4034 UInt_t ndata = info->GetElements()->GetEntries();
4035 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
4037
4038 if (IsDefaultVector(proxy))
4039 {
4040 if (proxy.HasPointers()) {
4041 // Instead of the creating a new one let's copy the one from the StreamerInfo.
4042 delete sequence;
4043
4044 sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
4045
4046 return sequence;
4047 }
4048
4049 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4050 Long_t increment = proxy.GetIncrement();
4051 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
4052 /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4053 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
4054 {
4055 Long_t increment = proxy.GetIncrement();
4056 sequence->fLoopConfig = new TVectorLoopConfig(increment);
4057 // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
4058 } else {
4059 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
4060 }
4061 for (UInt_t i = 0; i < ndata; ++i) {
4062 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
4063 if (!element) {
4064 break;
4065 }
4066 if (element->GetType() < 0) {
4067 // -- Skip an ignored TObject base class.
4068 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
4069 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
4070 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
4071 // when it is making branches for a split object.
4072 continue;
4073 }
4075 // Skip element cached for reading purposes.
4076 continue;
4077 }
4079 // Skip artificial element used for reading purposes.
4080 continue;
4081 }
4082 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
4083 Int_t asize = element->GetSize();
4084 if (element->GetArrayLength()) {
4085 asize /= element->GetArrayLength();
4086 }
4087 Int_t oldType = element->GetType();
4088 Int_t offset = element->GetOffset();
4089#if defined(CDJ_NO_COMPILE)
4090 Int_t newType = element->GetNewType();
4091
4092 if (newType != oldType) {
4093 if (newType > 0) {
4094 if (oldType != TVirtualStreamerInfo::kCounter) {
4095 oldType += TVirtualStreamerInfo::kConv;
4096 }
4097 } else {
4098 oldType += TVirtualStreamerInfo::kSkip;
4099 }
4100 }
4101 if ( IsDefaultVector(proxy)
4102 /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4103 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
4104 {
4105
4106 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4107 if (element->TestBit(TStreamerElement::kCache)) {
4108 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4109 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4110 } else {
4111 sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4112 }
4113
4114 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4115 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
4116 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4117 } else {
4118 // The usual collection case.
4119 if (element->TestBit(TStreamerElement::kCache)) {
4120 TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4121 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4122 } else {
4123 switch (oldType) {
4124 // read basic types
4125 case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4126 case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4127 case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4128 case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4129 case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4130 case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4131 case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4132 case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4133 case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4134 case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4135 case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4136 case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4137 case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4138 // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
4140 if (element->GetFactor() != 0) {
4141 sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4142 } else {
4143 Int_t nbits = (Int_t)element->GetXmin();
4144 if (!nbits) nbits = 12;
4145 sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4146 }
4147 break;
4148 }
4150 if (element->GetFactor() != 0) {
4151 sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4152 } else {
4153 Int_t nbits = (Int_t)element->GetXmin();
4154 if (!nbits) {
4155 sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4156 } else {
4157 sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4158 }
4159 }
4160 break;
4161 }
4162 case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
4163 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4164 // Streamer alltogether.
4165 case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
4166 case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
4167 default:
4168 sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4169 break;
4170 }
4171 }
4172 }
4173#else
4174 if ( IsDefaultVector(proxy)
4175 /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4176 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
4177 {
4178 sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4179 } else {
4180 // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
4181 // as it does not create/use a TStaging as expected ... but then again it might
4182 // not be the right things to expect ...
4183 // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4184 sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4185 }
4186#endif
4187 }
4188 return sequence;
4189}
4190
4192{
4193 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4194 // TBranchElement in the case of split sub-object.
4195
4196 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4197 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4198 iter != end;
4199 ++iter)
4200 {
4201 // (fElemId == -1) indications that the action is a Push or Pop DataCache.
4202 if (iter->fConfiguration->fElemId != (UInt_t)-1 &&
4203 !iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4204 iter->fConfiguration->AddToOffset(delta);
4205 }
4206}
4207
4209{
4210 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4211 // TBranchElement in the case of split sub-object.
4212
4213 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4214 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4215 iter != end;
4216 ++iter)
4217 {
4218 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4219 iter->fConfiguration->SetMissing();
4220 }
4221}
4222
4224{
4225 // Create a copy of this sequence.
4226
4227 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, fActions.size(), IsForVectorPtrLooper());
4228
4229 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4230
4231 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4232 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4233 iter != end;
4234 ++iter)
4235 {
4236 TConfiguration *conf = iter->fConfiguration->Copy();
4237 sequence->AddAction( iter->fAction, conf );
4238 }
4239 return sequence;
4240}
4241
4243 const TStreamerInfoActions::TIDs &element_ids,
4244 Int_t offset,
4246{
4247 for(UInt_t id = 0; id < element_ids.size(); ++id) {
4248 if ( element_ids[id].fElemID < 0 ) {
4249 if (element_ids[id].fNestedIDs) {
4250 auto original = create(element_ids[id].fNestedIDs->fInfo,
4251 sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
4252 nullptr);
4253 if (element_ids[id].fNestedIDs->fOnfileObject) {
4254 auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
4255 if ( sequence->fLoopConfig )
4256 sequence->AddAction( PushDataCacheGenericCollection, conf );
4257 else if ( sequence->IsForVectorPtrLooper() )
4258 sequence->AddAction( PushDataCacheVectorPtr, conf );
4259 else
4260 sequence->AddAction( PushDataCache, conf );
4261 }
4262
4263 original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
4264
4265 if (element_ids[id].fNestedIDs->fOnfileObject) {
4266 auto conf =
4267 new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset);
4268 if ( sequence->fLoopConfig )
4269 sequence->AddAction( PopDataCacheGenericCollection, conf );
4270 else if ( sequence->IsForVectorPtrLooper() )
4271 sequence->AddAction( PopDataCacheVectorPtr, conf );
4272 else
4273 sequence->AddAction( PopDataCache, conf );
4274 }
4275 } else {
4276 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4277 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4278 iter != end;
4279 ++iter)
4280 {
4281 TConfiguration *conf = iter->fConfiguration->Copy();
4282 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4283 conf->AddToOffset(offset);
4284 sequence->AddAction( iter->fAction, conf );
4285 }
4286 }
4287 } else {
4288 int localIndex = 0;
4289 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4290 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4291 iter != end;
4292 ++iter) {
4293 // fprintf(stderr, "With element_ids[%d] For %s comparing act[%d/%zu] %d to %d for %p vs %p %s\n",
4294 // id,
4295 // iter->fConfiguration->fInfo->GetName(),
4296 // localIndex, fActions.size(),
4297 // iter->fConfiguration->fElemId,
4298 // (UInt_t)element_ids[id].fElemID, iter->fConfiguration->fInfo,
4299 // element_ids[id].fInfo,
4300 // element_ids[id].fInfo ? element_ids[id].fInfo->GetName() : "nullptr" );
4301 ++localIndex;
4302 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
4303 TConfiguration *conf = iter->fConfiguration->Copy();
4304 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4305 conf->AddToOffset(offset);
4306 sequence->AddAction( iter->fAction, conf );
4307 }
4308 }
4309 }
4310 }
4311}
4312
4315{
4316 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4317 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4318
4319 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
4320
4321 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4322
4323 AddToSubSequence(sequence, element_ids, offset, create);
4324
4325 return sequence;
4326}
4327
4329{
4330 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4331 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4332
4333 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo, element_ids.size(), IsForVectorPtrLooper());
4334
4335 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4336
4337 for(UInt_t id = 0; id < element_ids.size(); ++id) {
4338 if ( element_ids[id] < 0 ) {
4339 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4340 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4341 iter != end;
4342 ++iter)
4343 {
4344 TConfiguration *conf = iter->fConfiguration->Copy();
4345 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4346 conf->AddToOffset(offset);
4347 sequence->AddAction( iter->fAction, conf );
4348 }
4349 } else {
4350 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4351 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4352 iter != end;
4353 ++iter) {
4354 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
4355 TConfiguration *conf = iter->fConfiguration->Copy();
4356 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4357 conf->AddToOffset(offset);
4358 sequence->AddAction( iter->fAction, conf );
4359 }
4360 }
4361 }
4362 }
4363 return sequence;
4364}
4365
4366#if !defined(R__WIN32) && !defined(_AIX)
4367
4368#include <dlfcn.h>
4369
4370#endif
4371
4372typedef void (*voidfunc)();
4373static const char *R__GetSymbolName(voidfunc func)
4374{
4375#if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
4376 return "not available on this platform";
4377#if 0
4378 MEMORY_BASIC_INFORMATION mbi;
4379 if (!VirtualQuery (func, &mbi, sizeof (mbi)))
4380 {
4381 return 0;
4382 }
4383
4384 HMODULE hMod = (HMODULE) mbi.AllocationBase;
4385 static char moduleName[MAX_PATH];
4386
4387 if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
4388 {
4389 return 0;
4390 }
4391 return moduleName;
4392#endif
4393#else
4394 Dl_info info;
4395 if (dladdr((void*)func,&info)==0) {
4396 // Not in a known share library, let's give up
4397 return "name not found";
4398 } else {
4399 //fprintf(stdout,"Found address in %s\n",info.dli_fname);
4400 return info.dli_sname;
4401 }
4402#endif
4403}
4404
4406{
4407 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4408 // TTBranchElement in the case of split sub-object.
4409 // If opt contains 'func', also print the (mangled) name of the function that will be executed.
4410
4411 if (fLoopConfig) {
4412 fLoopConfig->Print();
4413 }
4414 TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
4415 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
4416 iter != end;
4417 ++iter)
4418 {
4419 iter->fConfiguration->Print();
4420 if (strstr(opt,"func")) {
4421 printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
4422 }
4423 }
4424}
4425
4426
void Class()
Definition: Class.C:29
PyObject * fType
ROOT::R::TRInterface & r
Definition: Object.C:4
#define b(i)
Definition: RSha256.hxx:100
unsigned short UShort_t
Definition: RtypesCore.h:36
double Double32_t
Definition: RtypesCore.h:56
int Int_t
Definition: RtypesCore.h:41
const Int_t kMaxInt
Definition: RtypesCore.h:99
short Version_t
Definition: RtypesCore.h:61
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
void Fatal(const char *location, const char *msgfmt,...)
XFontStruct * id
Definition: TGX11.cxx:108
int type
Definition: TGX11.cxx:120
float xmin
Definition: THbookFile.cxx:93
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
@ kIsReferenced
Definition: TObject.h:342
#define gROOT
Definition: TROOT.h:415
static TConfiguredAction GetNumericCollectionReadAction(Int_t type, TConfigSTL *conf)
void(* voidfunc)()
static void AddReadConvertAction(TStreamerInfoActions::TActionSequence *sequence, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionReadConvertAction(Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionReadAction(TVirtualStreamerInfo *info, TStreamerElement *element, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
static const Int_t kRegrouped
#define INLINE_TEMPLATE_ARGS
static const char * R__GetSymbolName(voidfunc func)
static TConfiguredAction GetConvertCollectionReadAction(Int_t oldtype, Int_t newtype, TConfiguration *conf)
static TConfiguredAction GetCollectionWriteAction(TVirtualStreamerInfo *info, TStreamerElement *, Int_t type, UInt_t i, TStreamerInfo::TCompInfo_t *compinfo, Int_t offset)
static TConfiguredAction GetConvertCollectionReadActionFrom(Int_t newtype, TConfiguration *conf)
virtual void ReadBuffer(char *&buffer)
typedef void((*Func_t)())
#define R__LOCKGUARD(mutex)
@ kStreamedMemberWise
Definition: TBufferFile.h:68
Base class for text-based streamers like TBufferJSON or TBufferXML Special actions list will use meth...
Definition: TBufferText.h:21
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual void ReadWithNbits(Float_t *ptr, Int_t nbits)=0
virtual void ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue)=0
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:344
virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0)=0
virtual UInt_t WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual void ReadInt(Int_t &i)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:262
virtual UShort_t GetPidOffset() const =0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
@ kCannotHandleMemberWiseStreaming
Definition: TBuffer.h:75
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=0)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele=0)=0
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)=0
virtual void ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits)=0
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:92
virtual void ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue)=0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual Version_t ReadVersionForMemberWise(const TClass *cl=0)=0
Int_t Length() const
Definition: TBuffer.h:99
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4440
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2250
void * NewArray(Long_t nElements, ENewType defConstructor=kClassNew) const
Return a pointer to a newly allocated array of objects of this class.
Definition: TClass.cxx:4994
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4812
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5454
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition: TClass.cxx:5286
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2835
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:568
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6780
@ kHasCustomStreamerMember
Definition: TClass.h:99
@ kIsEmulation
Definition: TClass.h:95
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:253
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
void PutObjectWithID(TObject *obj, UInt_t uid=0)
stores the object at the uid th slot in the table of objects The object uniqued is set as well as its...
Definition: TProcessID.cxx:381
const char * GetErrorMessage() const
Int_t GetNewType() const
virtual Int_t GetSize() const
Returns size of this element in bytes.
Int_t GetType() const
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetArrayDim() const
TMemberStreamer * GetStreamer() const
Return the local streamer object.
Double_t GetXmax() const
TClass * GetNewClass() const
Int_t GetArrayLength() const
Double_t GetFactor() const
const char * GetTypeName() const
Double_t GetXmin() const
Int_t GetOffset() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
virtual ULong_t GetMethod() const
virtual Bool_t HasCounter() const
void GetSequenceType(TString &type) const
Fill type with the string representation of sequence information including 'cached',...
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
void Print(Option_t *="") const
This method must be overridden when a class wants to print itself.
TLoopConfiguration * fLoopConfig
If this is a bundle of memberwise streaming action, this configures the looping.
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) SequenceGetter_t
void AddToSubSequence(TActionSequence *sequence, const TIDs &element_ids, Int_t offset, SequenceGetter_t create)
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
void AddAction(action_t action, TConfiguration *conf)
Base class of the Configurations.
virtual void PrintDebug(TBuffer &buffer, void *object) const
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
Int_t fOffset
Offset within the object.
TCompInfo_t * fCompInfo
Access to compiled information (for legacy code)
UInt_t fLength
Number of element in a fixed length array.
UInt_t fElemId
Identifier of the TStreamerElement.
void PrintDebug(TBuffer &buffer, void *object) const
Base class of the Configurations for the member wise looping routines.
virtual TVirtualCollectionProxy * GetCollectionProxy() const
virtual TLoopConfiguration * Copy() const =0
TClass * fClass
Not Owned.
Definition: TStreamerInfo.h:57
TMemberStreamer * fStreamer
Not Owned.
Definition: TStreamerInfo.h:60
TStreamerElement * fElem
Not Owned.
Definition: TStreamerInfo.h:55
TClass * fNewClass
Not Owned.
Definition: TStreamerInfo.h:58
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
Int_t fNVirtualInfoLoc
! Number of virtual info location to update.
Int_t ReadBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t eoffset, Bool_t v7=kTRUE)
The STL vector/list is deserialized from the buffer b.
void AddWriteAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
Int_t fNfulldata
!number of elements
Definition: TStreamerInfo.h:98
TCompInfo * fComp
![fNslots with less than fElements->GetEntries()*1.5 used] Compiled info
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions(Bool_t forCollection)
void Compile()
loop on the TStreamerElement list regroup members with same type Store predigested information into l...
TStreamerInfoActions::TActionSequence * fWriteMemberWiseVecPtr
! List of write action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fReadText
! List of text read action resulting from the compilation, used for JSON.
void AddReadTextAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read text action for the given element.
TCompInfo ** fCompFull
![fElements->GetEntries()]
TObjArray * fElements
Array of TStreamerElements.
@ kArtificial
Cache the value in memory than is not part of the object but is accessible via a SchemaRule.
@ kUChar
Equal to TDataType's kchar.
void AddReadMemberWiseVecPtrAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
TClass * GetClass() const
void ls(Option_t *option="") const
List the TStreamerElement list and also the precomputed tables if option contains the string "incOrig...
TStreamerInfoActions::TActionSequence * fReadMemberWise
! List of read action resulting from the compilation for use in member wise streaming.
Int_t fNdata
!number of optimized elements
Definition: TStreamerInfo.h:97
TStreamerInfoActions::TActionSequence * fReadMemberWiseVecPtr
! List of read action resulting from the compilation for use in member wise streaming.
TStreamerInfoActions::TActionSequence * fReadObjectWise
! List of read action resulting from the compilation.
TClass * fClass
!pointer to class
TCompInfo ** fCompOpt
![fNdata]
static std::atomic< Int_t > fgCount
Number of TStreamerInfo instances.
void AddWriteTextAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
void ComputeSize()
Compute total size of all persistent elements of the class.
void AddReadAction(TStreamerInfoActions::TActionSequence *readSequence, Int_t index, TCompInfo *compinfo)
Add a read action for the given element.
void AddWriteMemberWiseVecPtrAction(TStreamerInfoActions::TActionSequence *writeSequence, Int_t index, TCompInfo *compinfo)
This is for streaming via a TClonesArray (or a vector of pointers of this type).
Int_t fNumber
!Unique identifier
Definition: TStreamerInfo.h:95
TStreamerInfoActions::TActionSequence * fWriteObjectWise
! List of write action resulting from the compilation.
Int_t fSize
!size of the persistent class
Definition: TStreamerInfo.h:96
Int_t ReadBufferSkip(TBuffer &b, const T &arrptr, const TCompInfo *compinfo, Int_t kase, TStreamerElement *aElement, Int_t narr, Int_t eoffset)
Skip an element.
TStreamerInfoActions::TActionSequence * fWriteMemberWise
! List of write action resulting from the compilation for use in member wise streaming.
Int_t fNslots
!total numbrer of slots in fComp.
Definition: TStreamerInfo.h:99
Version_t fOldVersion
! Version of the TStreamerInfo object read from the file
TStreamerInfoActions::TActionSequence * fWriteText
! List of text write action resulting for the compilation, used for JSON.
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Bool_t forCollection)
Basic string class.
Definition: TString.h:131
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
const char * Data() const
Definition: TString.h:364
@ kTrailing
Definition: TString.h:262
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:26
TClassRef fClass
Definition: TVirtualArray.h:28
virtual Int_t GetProperties() const
virtual ULong_t GetIncrement() const =0
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
virtual EDataType GetType() const =0
void *(* CopyIterator_t)(void *dest, const void *source)
void *(* Next_t)(void *iter, const void *end)
virtual TClass * GetValueClass() const =0
virtual void Commit(void *)=0
virtual Int_t GetCollectionType() const =0
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual UInt_t Size() const =0
void(* DeleteTwoIterators_t)(void *begin, void *end)
void(* DeleteIterator_t)(void *iter)
static const Int_t fgIteratorArenaSize
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)=0
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)=0
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)=0
virtual Bool_t HasPointers() const =0
virtual TClass * GetCollectionClass() const
static void * Next(void *iter, const void *end)
static void * CopyIterator(void *dest, const void *source)
Abstract Interface class describing Streamer information for one class.
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible.
static Bool_t CanOptimize()
static function returning true if optimization can be on
virtual TObjArray * GetElements() const =0
virtual Int_t GetClassVersion() const =0
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
double T(double x)
Definition: ChebyshevPol.h:34
void Copy(void *source, void *dest)
void Print(std::ostream &os, const OptionType &opt)
@ kSTLbitset
Definition: ESTLType.h:37
@ kSTLmap
Definition: ESTLType.h:33
@ kSTLunorderedmultiset
Definition: ESTLType.h:43
@ kSTLset
Definition: ESTLType.h:35
@ kSTLmultiset
Definition: ESTLType.h:36
@ kSTLvector
Definition: ESTLType.h:30
@ kSTLunorderedmultimap
Definition: ESTLType.h:45
@ kSTLunorderedset
Definition: ESTLType.h:42
@ kSTLunorderedmap
Definition: ESTLType.h:44
@ kSTLmultimap
Definition: ESTLType.h:34
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:155
INLINE_TEMPLATE_ARGS Int_t UseCache(TBuffer &b, void *addr, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t ReadTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PushDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t WriteTextStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t WriteTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadTextTObjectBase(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PopDataCache(TBuffer &b, void *, const TConfiguration *)
INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t WriteTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArrayV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
INLINE_TEMPLATE_ARGS Int_t ReadTString(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS void ReadArraySTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t GenericWriteAction(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadTextTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PopDataCacheVectorPtr(TBuffer &b, void *, const void *, const TConfiguration *)
Int_t GenericReadAction(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS void ReadArraySTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
INLINE_TEMPLATE_ARGS Int_t ReadTextObject(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadTextStreamer(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
Int_t PushDataCache(TBuffer &b, void *, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType_NoFactor(TBuffer &buf, void *addr, const TConfiguration *config)
std::vector< TIDNode > TIDs
INLINE_TEMPLATE_ARGS void ReadSTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t WriteStreamerLoop(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
INLINE_TEMPLATE_ARGS Int_t ReadTextBaseClass(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
INLINE_TEMPLATE_ARGS Int_t WriteTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamerV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
INLINE_TEMPLATE_ARGS void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t, UInt_t)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType< BitsMarker >(TBuffer &buf, void *addr, const TConfiguration *config)
bool IsDefaultVector(TVirtualCollectionProxy &proxy)
Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t WriteSTLp(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
INLINE_TEMPLATE_ARGS void ReadSTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
void HandleReferencedTObject(TBuffer &buf, void *addr, const TConfiguration *config)
Int_t PopDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *, const TConfiguration *)
INLINE_TEMPLATE_ARGS Int_t ReadStreamerLoop(TBuffer &buf, void *addr, const TConfiguration *config)
Direct copy of code from TStreamerInfo::WriteBufferAux, potentially can be used later for non-text st...
Int_t PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
ESelectLooper SelectLooper(TVirtualCollectionProxy &proxy)
INLINE_TEMPLATE_ARGS Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadTextTNamed(TBuffer &buf, void *addr, const TConfiguration *config)
INLINE_TEMPLATE_ARGS Int_t ReadBasicType_WithFactor(TBuffer &buf, void *addr, const TConfiguration *config)
TVirtualCollectionProxy::Next_t Next_t
Definition: file.py:1