Logo ROOT   6.18/05
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)\n",
108 info->GetClass()->GetName(), aElement->GetName(), fElemId, fCompInfo->fType,
109 aElement->ClassName(), fOffset, sequenceType.Data());
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 PushDataCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf)
1505 {
1506 TConfigurationPushDataCache *config = (TConfigurationPushDataCache*)conf;
1507 auto onfileObject = config->fOnfileObject;
1508
1509 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1510 UInt_t n = proxy->Size();
1511
1512 onfileObject->SetSize(n);
1513 b.PushDataCache( onfileObject );
1514
1515 return 0;
1516 }
1517
1519 {
1520 b.PopDataCache();
1521 return 0;
1522 }
1523
1525 {
1526 b.PopDataCache();
1527 return 0;
1528 }
1529
1530 class TConfigurationUseCache : public TConfiguration {
1531 // Configuration object for the UseCache case.
1532 public:
1533 TConfiguredAction fAction;
1534 Bool_t fNeedRepeat;
1535
1536 TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) :
1537 TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fCompInfo,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
1538 virtual void PrintDebug(TBuffer &b, void *addr) const
1539 {
1540 if (gDebug > 1) {
1541 // Idea: We should print the name of the action function.
1542 TStreamerInfo *info = (TStreamerInfo*)fInfo;
1543 TStreamerElement *aElement = fCompInfo->fElem;
1544 fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
1545 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
1546 info->GetClass()->GetName(),aElement->GetName(),fElemId,fCompInfo->fType,
1547 aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache() ? b.PeekDataCache()->GetObjectAt(0) : 0);
1548 }
1549
1550 }
1551 virtual ~TConfigurationUseCache() {};
1552 virtual TConfiguration *Copy() {
1553 TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
1554 fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
1555 return copy;
1556 }
1557 };
1558
1560 {
1561 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1562
1563 Int_t bufpos = b.Length();
1564 TVirtualArray *cached = b.PeekDataCache();
1565 if (cached==0) {
1566 TStreamerElement *aElement = conf->fCompInfo->fElem;
1567 TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
1568 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1569 char *ptr = (char*)addr;
1570 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,1,0);
1571 } else {
1572 config->fAction(b, (*cached)[0]);
1573 }
1574 // Idea: Factor out this 'if' to a UseCacheRepeat function
1575 if (config->fNeedRepeat) {
1576 b.SetBufferOffset(bufpos);
1577 }
1578 return 0;
1579 }
1580
1581 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf)
1582 {
1583 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1584 Int_t bufpos = b.Length();
1585
1586 TVirtualArray *cached = b.PeekDataCache();
1587 if (cached==0) {
1588 TStreamerElement *aElement = config->fCompInfo->fElem;
1589 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1590 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1591 char *ptr = (char*)start;
1592 UInt_t n = (((void**)end)-((void**)start));
1593 info->ReadBufferSkip(b,&ptr,config->fCompInfo,conf->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1594 } else {
1595 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1596 void *cached_start = (*cached)[0];
1597 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1598 config->fAction(b,cached_start,cached_end,&cached_config);
1599 }
1600 // Idea: Factor out this 'if' to a UseCacheRepeat function
1601 if (config->fNeedRepeat) {
1602 b.SetBufferOffset(bufpos);
1603 }
1604 return 0;
1605 }
1606
1607 INLINE_TEMPLATE_ARGS Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf)
1608 {
1609 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1610
1611 Int_t bufpos = b.Length();
1612 TVirtualArray *cached = b.PeekDataCache();
1613 if (cached==0) {
1614 TStreamerElement *aElement = config->fCompInfo->fElem;
1615 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1616 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1617 char *ptr = (char*)start;
1618 UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
1619 info->ReadBufferSkip(b,&ptr,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1620 } else {
1621 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1622 void *cached_start = (*cached)[0];
1623 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1624 config->fAction(b,cached_start,cached_end,&cached_config);
1625 }
1626 // Idea: Factor out this 'if' to a UseCacheRepeat function
1627 if (config->fNeedRepeat) {
1628 b.SetBufferOffset(bufpos);
1629 }
1630 return 0;
1631 }
1632
1634 {
1635 TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
1636
1637 Int_t bufpos = b.Length();
1638 TVirtualArray *cached = b.PeekDataCache();
1639 if (cached==0) {
1640 TStreamerElement *aElement = config->fCompInfo->fElem;
1641 TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1642
1643 TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
1644 Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
1645 UInt_t n = proxy->Size();
1646 info->ReadBufferSkip(b, *proxy,config->fCompInfo,config->fCompInfo->fType+TStreamerInfo::kSkip,aElement,n,0);
1647 } else {
1648 TVectorLoopConfig cached_config( nullptr, cached->fClass->Size(), /* read */ kTRUE );
1649 void *cached_start = (*cached)[0];
1650 void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
1651 config->fAction(b,cached_start,cached_end,&cached_config);
1652 }
1653 // Idea: Factor out this 'if' to a UseCacheRepeat function
1654 if (config->fNeedRepeat) {
1655 b.SetBufferOffset(bufpos);
1656 }
1657 return 0;
1658 }
1659
1660 // Support for collections.
1661
1662 Int_t ReadLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1663 {
1664 Fatal("ApplySequence","The sequence of actions to read %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1665 return 0;
1666 }
1667
1668 Int_t WriteLoopInvalid(TBuffer &, void *, const void *, const TConfiguration *config)
1669 {
1670 Fatal("ApplySequence","The sequence of actions to write %s:%d member-wise was not initialized.",config->fInfo->GetName(),config->fInfo->GetClassVersion());
1671 return 0;
1672 }
1673
1675
1677 {
1680 return kGenericLooper;
1681 else
1682 return kVectorLooper;
1687 || proxy.GetCollectionType() == ROOT::kSTLbitset) {
1688 return kAssociativeLooper;
1689 } else {
1690 return kGenericLooper;
1691 }
1692 }
1693
1694 struct VectorLooper {
1695
1696 template <typename T>
1697 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1698 {
1699 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1700 iter = (char*)iter + config->fOffset;
1701 end = (char*)end + config->fOffset;
1702 for(; iter != end; iter = (char*)iter + incr ) {
1703 T *x = (T*) ((char*) iter);
1704 buf >> *x;
1705 }
1706 return 0;
1707 }
1708
1709 template <typename From, typename To>
1710 struct ConvertBasicType {
1711 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1712 {
1713 // Simple conversion from a 'From' on disk to a 'To' in memory.
1714 From temp;
1715 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1716 iter = (char*)iter + config->fOffset;
1717 end = (char*)end + config->fOffset;
1718 for(; iter != end; iter = (char*)iter + incr ) {
1719 buf >> temp;
1720 *(To*)( ((char*)iter) ) = (To)temp;
1721 }
1722 return 0;
1723 }
1724 };
1725
1726 template <typename To>
1727 struct ConvertBasicType<BitsMarker,To> {
1728 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1729 {
1730 // Simple conversion from a 'From' on disk to a 'To' in memory.
1731 UInt_t temp;
1732 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1733 iter = (char*)iter + config->fOffset;
1734 end = (char*)end + config->fOffset;
1735 for(; iter != end; iter = (char*)iter + incr ) {
1736 buf >> temp;
1737
1738 if ((temp & kIsReferenced) != 0) {
1739 HandleReferencedTObject(buf, (char*)iter - config->fOffset, config);
1740 }
1741
1742 *(To*)( ((char*)iter) ) = (To)temp;
1743 }
1744 return 0;
1745 }
1746 };
1747
1748 template <typename From, typename To>
1749 struct ConvertBasicType<WithFactorMarker<From>,To> {
1750 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1751 {
1752 // Simple conversion from a 'From' on disk to a 'To' in memory.
1753 TConfWithFactor *conf = (TConfWithFactor *)config;
1754 From temp;
1755 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1756 iter = (char*)iter + config->fOffset;
1757 end = (char*)end + config->fOffset;
1758 for(; iter != end; iter = (char*)iter + incr ) {
1759 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
1760 *(To*)( ((char*)iter) ) = (To)temp;
1761 }
1762 return 0;
1763 }
1764 };
1765
1766 template <typename From, typename To>
1767 struct ConvertBasicType<NoFactorMarker<From>,To> {
1768 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1769 {
1770 // Simple conversion from a 'From' on disk to a 'To' in memory.
1771 TConfNoFactor *conf = (TConfNoFactor *)config;
1772 From temp;
1773 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1774 iter = (char*)iter + config->fOffset;
1775 end = (char*)end + config->fOffset;
1776 for(; iter != end; iter = (char*)iter + incr ) {
1777 buf.ReadWithNbits(&temp, conf->fNbits);
1778 *(To*)( ((char*)iter) ) = (To)temp;
1779 }
1780 return 0;
1781 }
1782 };
1783
1784 template <typename T>
1785 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1786 {
1787 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1788 iter = (char*)iter + config->fOffset;
1789 end = (char*)end + config->fOffset;
1790 for(; iter != end; iter = (char*)iter + incr ) {
1791 T *x = (T*) ((char*) iter);
1792 buf << *x;
1793 }
1794 return 0;
1795 }
1796
1797 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
1798 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
1799 {
1800 const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1801 //Idea: can we factor out the addition of fOffset
1802 // iter = (char*)iter + config->fOffset;
1803 for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
1804 iter_action(buf, iter, config);
1805 }
1806 return 0;
1807 }
1808
1809 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1810 {
1811 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
1812 // punt.
1813
1814 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1815 UInt_t n = (((char*)end)-((char*)start))/incr;
1816 char **arrptr = new char*[n];
1817 UInt_t i = 0;
1818 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1819 arrptr[i] = (char*)iter;
1820 }
1821 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1822 delete [] arrptr;
1823
1824 // // Idea: need to cache this result!
1825 // TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
1826 // TStreamerElement *aElement = (TStreamerElement*)info->GetElem(config->fElemId);
1827 //
1828 // *Int_t clversion = ((TStreamerBase*)aElement)->Get BaseVersion();
1829 // *TClass *cle = aElement->GetNewBaseClass();
1830 // *(TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
1831 //
1832 // TSequence *actions = CreateReadMemberWiseActions( ((TStreamerBase*)aElement)->GetBaseStreamerInfo(), ???? );
1833 //
1834 // actions->ReadBuffer(b,start,end);
1835 // delete actions;
1836
1837 // const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1838 // for(void *iter = start; iter != end; iter = (char*)iter + incr )
1839 // {
1840 // ((TStreamerInfo*)(((TStreamerBase*)aElement)->GetBaseStreamerInfo())->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
1841 //
1842 // ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
1843 // }
1844 return 0;
1845 }
1846
1847 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1848 {
1849 // Well the implementation is non trivial. For now punt.
1850
1851 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1852 UInt_t n = (((char*)end)-((char*)start))/incr;
1853 char **arrptr = new char*[n];
1854 UInt_t i = 0;
1855 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1856 arrptr[i] = (char*)iter;
1857 }
1858 ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
1859 delete [] arrptr;
1860 return 0;
1861 }
1862
1863 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
1864 {
1865 // Well the implementation is non trivial. For now punt.
1866
1867 UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
1868 UInt_t n = (((char*)end)-((char*)start))/incr;
1869 char **arrptr = new char*[n];
1870 UInt_t i = 0;
1871 for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
1872 arrptr[i] = (char*)iter;
1873 }
1874 ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arrptr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
1875 delete [] arrptr;
1876 return 0;
1877 }
1878
1879 template <typename T>
1880 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
1881 {
1882 // Collection of numbers. Memberwise or not, it is all the same.
1883
1884 TConfigSTL *config = (TConfigSTL*)conf;
1885 UInt_t start, count;
1886 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1887
1888 std::vector<T> *const vec = (std::vector<T>*)(((char*)addr)+config->fOffset);
1889 Int_t nvalues;
1890 buf.ReadInt(nvalues);
1891 vec->resize(nvalues);
1892
1893#ifdef R__VISUAL_CPLUSPLUS
1894 if (nvalues <= 0) {
1895 buf.CheckByteCount(start,count,config->fTypeName);
1896 return 0;
1897 }
1898#endif
1899 T *begin = &(*vec->begin());
1900 buf.ReadFastArray(begin, nvalues);
1901
1902 buf.CheckByteCount(start,count,config->fTypeName);
1903 return 0;
1904 }
1905
1906 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
1907 {
1908 // Collection of numbers. Memberwise or not, it is all the same.
1909
1910 TConfigSTL *config = (TConfigSTL*)conf;
1911 UInt_t start, count;
1912 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1913
1914 std::vector<bool> *const vec = (std::vector<bool>*)(((char*)addr)+config->fOffset);
1915 Int_t nvalues;
1916 buf.ReadInt(nvalues);
1917 vec->resize(nvalues);
1918
1919 bool *items = new bool[nvalues];
1920 buf.ReadFastArray(items, nvalues);
1921 for(Int_t i = 0 ; i < nvalues; ++i) {
1922 (*vec)[i] = items[i];
1923 }
1924 delete [] items;
1925
1926 // We could avoid the call to ReadFastArray, and we could
1927 // the following, however this breaks TBufferXML ...
1928 // for(Int_t i = 0 ; i < nvalues; ++i) {
1929 // bool tmp; buf >> tmp;
1930 // (*vec)[i] = tmp;
1931 // }
1932
1933 buf.CheckByteCount(start,count,config->fTypeName);
1934 return 0;
1935 }
1936
1937 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
1938 {
1939 // Collection of numbers. Memberwise or not, it is all the same.
1940
1941 TConfigSTL *config = (TConfigSTL*)conf;
1942 UInt_t start, count;
1943 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1944
1945 std::vector<float> *const vec = (std::vector<float>*)(((char*)addr)+config->fOffset);
1946 Int_t nvalues;
1947 buf.ReadInt(nvalues);
1948 vec->resize(nvalues);
1949
1950#ifdef R__VISUAL_CPLUSPLUS
1951 if (nvalues <= 0) {
1952 buf.CheckByteCount(start,count,config->fTypeName);
1953 return 0;
1954 }
1955#endif
1956 float *begin = &(*vec->begin());
1957 buf.ReadFastArrayFloat16(begin, nvalues);
1958
1959 buf.CheckByteCount(start,count,config->fTypeName);
1960 return 0;
1961 }
1962
1963 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
1964 {
1965 // Collection of numbers. Memberwise or not, it is all the same.
1966
1967 TConfigSTL *config = (TConfigSTL*)conf;
1968 UInt_t start, count;
1969 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1970
1971 std::vector<double> *const vec = (std::vector<double>*)(((char*)addr)+config->fOffset);
1972 Int_t nvalues;
1973 buf.ReadInt(nvalues);
1974 vec->resize(nvalues);
1975
1976#ifdef R__VISUAL_CPLUSPLUS
1977 if (nvalues <= 0) {
1978 buf.CheckByteCount(start,count,config->fTypeName);
1979 return 0;
1980 }
1981#endif
1982 double *begin = &(*vec->begin());
1983 buf.ReadFastArrayDouble32(begin, nvalues);
1984
1985 buf.CheckByteCount(start,count,config->fTypeName);
1986 return 0;
1987 }
1988
1989 template <typename From, typename To>
1990 struct ConvertCollectionBasicType {
1991 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
1992 {
1993 // Collection of numbers. Memberwise or not, it is all the same.
1994
1995 TConfigSTL *config = (TConfigSTL*)conf;
1996 UInt_t start, count;
1997 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
1998
1999 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2000 Int_t nvalues;
2001 buf.ReadInt(nvalues);
2002 vec->resize(nvalues);
2003
2004 From *temp = new From[nvalues];
2005 buf.ReadFastArray(temp, nvalues);
2006 for(Int_t ind = 0; ind < nvalues; ++ind) {
2007 (*vec)[ind] = (To)temp[ind];
2008 }
2009 delete [] temp;
2010
2011 buf.CheckByteCount(start,count,config->fTypeName);
2012 return 0;
2013 }
2014 };
2015
2016 template <typename From, typename To>
2017 struct ConvertCollectionBasicType<NoFactorMarker<From>,To> {
2018 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2019 {
2020 // Collection of numbers. Memberwise or not, it is all the same.
2021
2022 TConfigSTL *config = (TConfigSTL*)conf;
2023 UInt_t start, count;
2024 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2025
2026 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2027 Int_t nvalues;
2028 buf.ReadInt(nvalues);
2029 vec->resize(nvalues);
2030
2031 From *temp = new From[nvalues];
2032 buf.ReadFastArrayWithNbits(temp, nvalues, 0);
2033 for(Int_t ind = 0; ind < nvalues; ++ind) {
2034 (*vec)[ind] = (To)temp[ind];
2035 }
2036 delete [] temp;
2037
2038 buf.CheckByteCount(start,count,config->fTypeName);
2039 return 0;
2040 }
2041 };
2042
2043 template <typename To>
2044 static INLINE_TEMPLATE_ARGS Int_t ConvertCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2045 {
2046 // Collection of numbers. Memberwise or not, it is all the same.
2047
2048 TConfigSTL *config = (TConfigSTL*)conf;
2049 UInt_t start, count;
2050 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2051
2052 std::vector<To> *const vec = (std::vector<To>*)(((char*)addr)+config->fOffset);
2053 Int_t nvalues;
2054 buf.ReadInt(nvalues);
2055 vec->resize(nvalues);
2056
2057 Double32_t *temp = new Double32_t[nvalues];
2058 buf.ReadFastArrayDouble32(temp, nvalues);
2059 for(Int_t ind = 0; ind < nvalues; ++ind) {
2060 (*vec)[ind] = (To)temp[ind];
2061 }
2062 delete [] temp;
2063
2064 buf.CheckByteCount(start,count,config->fTypeName);
2065 return 0;
2066 }
2067
2068 };
2069
2070 struct VectorPtrLooper {
2071
2072 template <typename T>
2073 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2074 {
2075 const Int_t offset = config->fOffset;
2076
2077 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2078 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2079 buf >> *x;
2080 }
2081 return 0;
2082 }
2083
2084 template <typename From, typename To>
2085 struct ConvertBasicType {
2086 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2087 {
2088 // Simple conversion from a 'From' on disk to a 'To' in memory.
2089 From temp;
2090 const Int_t offset = config->fOffset;
2091 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2092 buf >> temp;
2093 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2094 *x = (To)temp;
2095 }
2096 return 0;
2097 }
2098 };
2099
2100 template <typename To>
2101 struct ConvertBasicType<BitsMarker,To> {
2102 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2103 {
2104 // Simple conversion from a 'From' on disk to a 'To' in memory.
2105 UInt_t temp;
2106 const Int_t offset = config->fOffset;
2107 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2108 buf >> temp;
2109
2110 if ((temp & kIsReferenced) != 0) {
2111 HandleReferencedTObject(buf,*(void**)iter,config);
2112 }
2113
2114 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2115 *x = (To)temp;
2116 }
2117 return 0;
2118 }
2119 };
2120
2121 template <typename From, typename To>
2122 struct ConvertBasicType<WithFactorMarker<From>,To> {
2123 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2124 {
2125 // Simple conversion from a 'From' on disk to a 'To' in memory.
2126 TConfWithFactor *conf = (TConfWithFactor *)config;
2127 From temp;
2128 const Int_t offset = config->fOffset;
2129 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2130 buf.ReadWithFactor(&temp, conf->fFactor, conf->fXmin);
2131 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2132 *x = (To)temp;
2133 }
2134 return 0;
2135 }
2136 };
2137
2138 template <typename From, typename To>
2139 struct ConvertBasicType<NoFactorMarker<From>,To> {
2140 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2141 {
2142 // Simple conversion from a 'From' on disk to a 'To' in memory.
2143 TConfNoFactor *conf = (TConfNoFactor *)config;
2144 From temp;
2145 const Int_t offset = config->fOffset;
2146 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2147 buf.ReadWithNbits(&temp, conf->fNbits);
2148 To *x = (To*)( ((char*) (*(void**)iter) ) + offset );
2149 *x = (To)temp;
2150 }
2151 return 0;
2152 }
2153 };
2154
2155 template <typename T>
2156 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2157 {
2158 const Int_t offset = config->fOffset;
2159
2160 for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
2161 T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
2162 buf << *x;
2163 }
2164 return 0;
2165 }
2166
2167 template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
2168 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2169 {
2170 for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
2171 action(buf, *(void**)iter, config);
2172 }
2173 return 0;
2174 }
2175
2176 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TConfiguration *config)
2177 {
2178 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2179 // punt.
2180
2181 return GenericRead(buf,start,end,config);
2182 }
2183
2184 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2185 {
2186 Int_t n = ( ((void**)end) - ((void**)iter) );
2187 char **arr = (char**)iter;
2188 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ n, config->fOffset, 1|2 );
2189 }
2190
2191 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
2192 {
2193 Int_t n = ( ((void**)end) - ((void**)iter) );
2194 char **arr = (char**)iter;
2195 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, arr, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, n, config->fOffset, 1|2 );
2196 }
2197
2198 };
2199
2200 struct AssociativeLooper {
2201
2202 template <typename T>
2203 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr, Int_t nvalues)
2204 {
2205 buf.ReadFastArray((T*)addr, nvalues);
2206 }
2207
2208 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr, Int_t nvalues)
2209 {
2210 buf.ReadFastArrayFloat16((float*)addr, nvalues);
2211 }
2212
2213 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr, Int_t nvalues)
2214 {
2215 buf.ReadFastArrayDouble32((double*)addr, nvalues);
2216 }
2217
2218 template <typename T,void (*action)(TBuffer&,void *,Int_t)>
2219 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2220 {
2221 // Collection of numbers. Memberwise or not, it is all the same.
2222
2223 TConfigSTL *config = (TConfigSTL*)conf;
2224 UInt_t start, count;
2225 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2226
2227 TClass *newClass = config->fNewClass;
2228 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2229 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2230
2231 Int_t nvalues;
2232 buf.ReadInt(nvalues);
2233 void* alternative = newProxy->Allocate(nvalues,true);
2234 if (nvalues) {
2237 void *begin = &(startbuf[0]);
2238 void *end = &(endbuf[0]);
2239 config->fCreateIterators(alternative, &begin, &end, newProxy);
2240 // We can not get here with a split vector of pointer, so we can indeed assume
2241 // that actions->fConfiguration != null.
2242
2243 action(buf,begin,nvalues);
2244
2245 if (begin != &(startbuf[0])) {
2246 // assert(end != endbuf);
2247 config->fDeleteTwoIterators(begin,end);
2248 }
2249 }
2250 newProxy->Commit(alternative);
2251
2252 buf.CheckByteCount(start,count,config->fTypeName);
2253 return 0;
2254 }
2255
2256 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2257 {
2258 return ReadNumericalCollection<bool,SimpleRead<bool> >(buf,addr,conf);
2259 }
2260
2261 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2262 {
2263 return ReadNumericalCollection<Float_t,SimpleReadFloat16 >(buf,addr,conf);
2264 }
2265
2266 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2267 {
2268 return ReadNumericalCollection<Double_t,SimpleReadDouble32 >(buf,addr,conf);
2269 }
2270
2271 template <typename T>
2272 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2273 {
2274 return ReadNumericalCollection<T,SimpleRead<T> >(buf,addr,conf);
2275 }
2276
2277 template <typename From, typename To>
2278 struct ConvertRead {
2279 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2280 {
2281 From *temp = new From[nvalues];
2282 buf.ReadFastArray(temp, nvalues);
2283 To *vec = (To*)addr;
2284 for(Int_t ind = 0; ind < nvalues; ++ind) {
2285 vec[ind] = (To)temp[ind];
2286 }
2287 delete [] temp;
2288 }
2289 };
2290
2291 template <typename From, typename To>
2292 struct ConvertRead<NoFactorMarker<From>,To> {
2293 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2294 {
2295 From *temp = new From[nvalues];
2296 buf.ReadFastArrayWithNbits(temp, nvalues,0);
2297 To *vec = (To*)addr;
2298 for(Int_t ind = 0; ind < nvalues; ++ind) {
2299 vec[ind] = (To)temp[ind];
2300 }
2301 delete [] temp;
2302 }
2303 };
2304
2305 template <typename From, typename To>
2306 struct ConvertRead<WithFactorMarker<From>,To> {
2307 static INLINE_TEMPLATE_ARGS void Action(TBuffer &buf, void *addr, Int_t nvalues)
2308 {
2309 From *temp = new From[nvalues];
2310 double factor,min; // needs to be initialized.
2311 buf.ReadFastArrayWithFactor(temp, nvalues, factor, min);
2312 To *vec = (To*)addr;
2313 for(Int_t ind = 0; ind < nvalues; ++ind) {
2314 vec[ind] = (To)temp[ind];
2315 }
2316 delete [] temp;
2317 }
2318 };
2319
2320 template <typename From, typename To>
2321 struct ConvertCollectionBasicType {
2322 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2323 {
2324 return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2325 }
2326 };
2327
2328 };
2329
2330 struct GenericLooper {
2331
2332 template <typename T>
2333 static INLINE_TEMPLATE_ARGS Int_t ReadBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2334 {
2335 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2336
2337 Next_t next = loopconfig->fNext;
2338 const Int_t offset = config->fOffset;
2339
2341 void *iter = loopconfig->fCopyIterator(iterator,start);
2342 void *addr;
2343 while( (addr = next(iter,end)) ) {
2344 T *x = (T*)( ((char*)addr) + offset );
2345 buf >> *x;
2346 }
2347 if (iter != &iterator[0]) {
2348 loopconfig->fDeleteIterator(iter);
2349 }
2350 return 0;
2351 }
2352
2353 template <typename T>
2354 static INLINE_TEMPLATE_ARGS Int_t WriteBasicType(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2355 {
2356 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2357
2358 Next_t next = loopconfig->fNext;
2359 const Int_t offset = config->fOffset;
2360
2362 void *iter = loopconfig->fCopyIterator(iterator,start);
2363 void *addr;
2364 while( (addr = next(iter,end)) ) {
2365 T *x = (T*)( ((char*)addr) + offset );
2366 buf << *x;
2367 }
2368 if (iter != &iterator[0]) {
2369 loopconfig->fDeleteIterator(iter);
2370 }
2371 return 0;
2372 }
2373
2374 template <Int_t (*iter_action)(TBuffer&,void *,const TConfiguration*)>
2375 static INLINE_TEMPLATE_ARGS Int_t ReadAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2376 {
2377 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2378
2379 // const Int_t offset = config->fOffset;
2380 Next_t next = loopconfig->fNext;
2381
2383 void *iter = loopconfig->fCopyIterator(&iterator,start);
2384 void *addr;
2385 while( (addr = next(iter,end)) ) {
2386 iter_action(buf, addr, config);
2387 }
2388 if (iter != &iterator[0]) {
2389 loopconfig->fDeleteIterator(iter);
2390 }
2391 return 0;
2392 }
2393
2394 template <typename From, typename To>
2395 struct Generic {
2396 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2397 {
2398 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2399
2400 const Int_t offset = config->fOffset;
2401 Next_t next = loopconfig->fNext;
2402
2404 void *iter = loopconfig->fCopyIterator(&iterator,start);
2405 void *addr;
2406 while( (addr = next(iter,end)) ) {
2407 To *x = (To*)( ((char*)addr) + offset );
2408 *x = (To)(*items);
2409 ++items;
2410 }
2411 if (iter != &iterator[0]) {
2412 loopconfig->fDeleteIterator(iter);
2413 }
2414 }
2415 };
2416
2417 template <typename From, typename To>
2418 struct Numeric {
2419 static void ConvertAction(From *items, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration * /* config */)
2420 {
2421 // The difference with ConvertAction is that we can modify the start
2422 // iterator and skip the copy. We also never have an offset.
2423
2424 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2425 Next_t next = loopconfig->fNext;
2426
2427 void *iter = start;
2428 void *addr;
2429 while( (addr = next(iter,end)) ) {
2430 To *x = (To*)(addr);
2431 *x = (To)(*items);
2432 ++items;
2433 }
2434 }
2435 };
2436
2437 template <typename From, typename To, template <typename F, typename T> class Converter = Generic >
2438 struct ConvertBasicType {
2439 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2440 {
2441 // Simple conversion from a 'From' on disk to a 'To' in memory.
2442
2443 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2444 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2445 Int_t nvalues = proxy->Size();
2446
2447 From *items = new From[nvalues];
2448 buf.ReadFastArray(items, nvalues);
2449 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2450 delete [] items;
2451 return 0;
2452 }
2453 };
2454
2455 template <typename To>
2456 struct ConvertBasicType<BitsMarker, To, Generic> {
2457 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2458 {
2459 // Simple conversion from a 'From' on disk to a 'To' in memory.
2460
2461 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2462 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2463 Int_t nvalues = proxy->Size();
2464
2465 UInt_t *items_storage = new UInt_t[nvalues];
2466 UInt_t *items = items_storage;
2467
2468 const Int_t offset = config->fOffset;
2469 Next_t next = loopconfig->fNext;
2470
2472 void *iter = loopconfig->fCopyIterator(&iterator,start);
2473 void *addr;
2474 while( (addr = next(iter,end)) ) {
2475 buf >> (*items);
2476 if (((*items) & kIsReferenced) != 0) {
2477 HandleReferencedTObject(buf, addr, config);
2478 }
2479 To *x = (To*)( ((char*)addr) + offset );
2480 *x = (To)(*items);
2481 ++items;
2482 }
2483 if (iter != &iterator[0]) {
2484 loopconfig->fDeleteIterator(iter);
2485 }
2486
2487 delete [] items_storage;
2488 return 0;
2489 }
2490 };
2491
2492 template <typename From, typename To, template <typename F, typename T> class Converter >
2493 struct ConvertBasicType<WithFactorMarker<From>,To,Converter > {
2494 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2495 {
2496 // Simple conversion from a 'From' on disk to a 'To' in memory.
2497
2498 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2499 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2500 Int_t nvalues = proxy->Size();
2501
2502 TConfSTLWithFactor *conf = (TConfSTLWithFactor *)config;
2503
2504 From *items = new From[nvalues];
2505 buf.ReadFastArrayWithFactor(items, nvalues, conf->fFactor, conf->fXmin);
2506 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2507 delete [] items;
2508 return 0;
2509 }
2510 };
2511
2512 template <typename From, typename To, template <typename F, typename T> class Converter >
2513 struct ConvertBasicType<NoFactorMarker<From>,To,Converter > {
2514 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
2515 {
2516 // Simple conversion from a 'From' on disk to a 'To' in memory.
2517
2518 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2519 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2520 Int_t nvalues = proxy->Size();
2521
2522 TConfSTLNoFactor *conf = (TConfSTLNoFactor *)config;
2523
2524 From *items = new From[nvalues];
2525 buf.ReadFastArrayWithNbits(items, nvalues, conf->fNbits);
2526 Converter<From,To>::ConvertAction(items,start,end,loopconfig,config);
2527 delete [] items;
2528 return 0;
2529 }
2530 };
2531
2532 static INLINE_TEMPLATE_ARGS Int_t ReadBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config)
2533 {
2534 // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class. For now
2535 // punt.
2536
2537 return GenericRead(buf,start,end,loopconfig, config);
2538 }
2539
2540 static INLINE_TEMPLATE_ARGS Int_t GenericRead(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2541 {
2542 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2543 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2544 return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, /*narr*/ proxy->Size(), config->fOffset, 1|2 );
2545 }
2546
2547 static INLINE_TEMPLATE_ARGS Int_t GenericWrite(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config)
2548 {
2549 TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
2550 TVirtualCollectionProxy *proxy = loopconfig->fProxy;
2551 return ((TStreamerInfo*)config->fInfo)->WriteBufferAux(buf, *proxy, &(config->fCompInfo), /*first*/ 0, /*last*/ 1, proxy->Size(), config->fOffset, 1|2 );
2552 }
2553
2554 template <typename T>
2555 static INLINE_TEMPLATE_ARGS void SimpleRead(TBuffer &buf, void *addr)
2556 {
2557 buf >> *(T*)addr;
2558 }
2559
2560 static INLINE_TEMPLATE_ARGS void SimpleReadFloat16(TBuffer &buf, void *addr)
2561 {
2562 buf.ReadWithNbits((float*)addr,12);
2563 }
2564
2565 static INLINE_TEMPLATE_ARGS void SimpleReadDouble32(TBuffer &buf, void *addr)
2566 {
2567 //we read a float and convert it to double
2568 Float_t afloat;
2569 buf >> afloat;
2570 *(double*)addr = (Double_t)afloat;
2571 }
2572
2573 template <typename ActionHolder>
2574 static INLINE_TEMPLATE_ARGS Int_t ReadNumericalCollection(TBuffer &buf, void *addr, const TConfiguration *conf)
2575 {
2576 // Collection of numbers. Memberwise or not, it is all the same.
2577
2578 TConfigSTL *config = (TConfigSTL*)conf;
2579 UInt_t start, count;
2580 /* Version_t vers = */ buf.ReadVersion(&start, &count, config->fOldClass);
2581
2582 TClass *newClass = config->fNewClass;
2583 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
2584 TVirtualCollectionProxy::TPushPop helper( newProxy, ((char*)addr)+config->fOffset );
2585
2586 Int_t nvalues;
2587 buf.ReadInt(nvalues);
2588 void* alternative = newProxy->Allocate(nvalues,true);
2589 if (nvalues) {
2592 void *begin = &(startbuf[0]);
2593 void *end = &(endbuf[0]);
2594 config->fCreateIterators(alternative, &begin, &end, newProxy);
2595 // We can not get here with a split vector of pointer, so we can indeed assume
2596 // that actions->fConfiguration != null.
2597
2598 TGenericLoopConfig loopconf(newProxy, /* read */ kTRUE);
2599 ActionHolder::Action(buf,begin,end,&loopconf,config);
2600
2601 if (begin != &(startbuf[0])) {
2602 // assert(end != endbuf);
2603 config->fDeleteTwoIterators(begin,end);
2604 }
2605 }
2606 newProxy->Commit(alternative);
2607
2608 buf.CheckByteCount(start,count,config->fTypeName);
2609 return 0;
2610 }
2611
2612 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBool(TBuffer &buf, void *addr, const TConfiguration *conf)
2613 {
2614 return ReadNumericalCollection<ConvertBasicType<bool,bool,Numeric > >(buf,addr,conf);
2615 }
2616
2617 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionFloat16(TBuffer &buf, void *addr, const TConfiguration *conf)
2618 {
2619 return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<float>,float,Numeric > >(buf,addr,conf);
2620 }
2621
2622 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionDouble32(TBuffer &buf, void *addr, const TConfiguration *conf)
2623 {
2624 return ReadNumericalCollection<ConvertBasicType<float,double,Numeric > >(buf,addr,conf);
2625 // Could also use:
2626 // return ReadNumericalCollection<ConvertBasicType<NoFactorMarker<double>,double,Numeric > >(buf,addr,conf);
2627 }
2628
2629 template <typename T>
2630 static INLINE_TEMPLATE_ARGS Int_t ReadCollectionBasicType(TBuffer &buf, void *addr, const TConfiguration *conf)
2631 {
2632 return ReadNumericalCollection<ConvertBasicType<T,T,Numeric > >(buf,addr,conf);
2633 }
2634
2635 template <typename From, typename To>
2636 struct ConvertCollectionBasicType {
2637 static INLINE_TEMPLATE_ARGS Int_t Action(TBuffer &buf, void *addr, const TConfiguration *conf)
2638 {
2639 // return ReadNumericalCollection<To,ConvertRead<From,To>::Action >(buf,addr,conf);
2640 return ReadNumericalCollection<ConvertBasicType<From,To,Numeric > >(buf,addr,conf);
2641 }
2642 };
2643
2644 };
2645}
2646
2647template <typename Looper, typename From>
2649{
2650 switch (newtype) {
2651 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertBasicType<From,bool>::Action, conf ); break;
2652 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertBasicType<From,char>::Action, conf ); break;
2653 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertBasicType<From,short>::Action, conf ); break;
2654 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertBasicType<From,Int_t>::Action, conf ); break;
2655 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertBasicType<From,Long_t>::Action, conf ); break;
2656 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertBasicType<From,Long64_t>::Action, conf ); break;
2657 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2658 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertBasicType<From,float>::Action, conf ); break;
2659 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2660 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertBasicType<From,double>::Action, conf ); break;
2661 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertBasicType<From,UChar_t>::Action, conf ); break;
2662 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertBasicType<From,UShort_t>::Action, conf ); break;
2663 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2664 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong_t>::Action, conf ); break;
2665 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertBasicType<From,ULong64_t>::Action, conf ); break;
2666 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertBasicType<From,UInt_t>::Action, conf ); break;
2667 default:
2668 return TConfiguredAction( Looper::GenericRead, conf );
2669 break;
2670 }
2671 R__ASSERT(0); // We should never be here
2672 return TConfiguredAction();
2673}
2674
2675template <class Looper>
2677{
2678 // If we ever support std::vector<Double32_t> fValues; //[...] we would get the info from the StreamerElement for fValues.
2679
2680 switch (type) {
2681 // Read basic types.
2682 case TStreamerInfo::kBool: return TConfiguredAction( Looper::ReadCollectionBool, conf ); break;
2683 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<Char_t>, conf ); break;
2684 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<Short_t>,conf ); break;
2685 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<Int_t>, conf ); break;
2686 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long_t>, conf ); break;
2687 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<Long64_t>, conf ); break;
2688 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadCollectionBasicType<Float_t>, conf ); break;
2689 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadCollectionBasicType<Double_t>, conf ); break;
2690 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadCollectionBasicType<UChar_t>, conf ); break;
2691 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadCollectionBasicType<UShort_t>, conf ); break;
2692 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadCollectionBasicType<UInt_t>, conf ); break;
2693 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong_t>, conf ); break;
2694 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadCollectionBasicType<ULong64_t>, conf ); break;
2695 case TStreamerInfo::kBits: Error("GetNumericCollectionReadAction","There is no support for kBits outside of a TObject."); break;
2697 TConfigSTL *alternate = new TConfSTLNoFactor(conf,12);
2698 delete conf;
2699 return TConfiguredAction( Looper::ReadCollectionFloat16, alternate );
2700 // if (element->GetFactor() != 0) {
2701 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2702 // } else {
2703 // Int_t nbits = (Int_t)element->GetXmin();
2704 // if (!nbits) nbits = 12;
2705 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2706 // }
2707 break;
2708 }
2710 TConfigSTL *alternate = new TConfSTLNoFactor(conf,0);
2711 delete conf;
2712 return TConfiguredAction( Looper::ReadCollectionDouble32, alternate );
2713 // if (element->GetFactor() != 0) {
2714 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2715 // } else {
2716 // Int_t nbits = (Int_t)element->GetXmin();
2717 // if (!nbits) {
2718 // return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
2719 // } else {
2720 // return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2721 // }
2722 // }
2723 break;
2724 }
2725 }
2726 Fatal("GetNumericCollectionReadAction","Is confused about %d",type);
2727 R__ASSERT(0); // We should never be here
2728 return TConfiguredAction();
2729}
2730
2731template <typename Looper, typename From>
2733{
2734 switch (newtype) {
2735 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,bool>::Action, conf ); break;
2736 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,char>::Action, conf ); break;
2737 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,short>::Action, conf ); break;
2738 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Int_t>::Action, conf ); break;
2739 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long_t>::Action, conf ); break;
2740 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,Long64_t>::Action, conf ); break;
2741 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2742 case TStreamerInfo::kFloat16: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,float>::Action, conf ); break;
2743 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2744 case TStreamerInfo::kDouble32:return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,double>::Action, conf ); break;
2745 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UChar_t>::Action, conf ); break;
2746 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UShort_t>::Action, conf ); break;
2747 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2748 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong_t>::Action, conf ); break;
2749 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,ULong64_t>::Action, conf ); break;
2750 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ConvertCollectionBasicType<From,UInt_t>::Action, conf ); break;
2751 default:
2752 break;
2753 }
2754 R__ASSERT(0); // We should never be here
2755 return TConfiguredAction();
2756}
2757
2758template <typename Looper>
2760{
2761 switch (oldtype) {
2763 return GetConvertCollectionReadActionFrom<Looper,Bool_t>(newtype, conf );
2764 break;
2766 return GetConvertCollectionReadActionFrom<Looper,Char_t>(newtype, conf );
2767 break;
2769 return GetConvertCollectionReadActionFrom<Looper,Short_t>(newtype, conf );
2770 break;
2772 return GetConvertCollectionReadActionFrom<Looper,Int_t>(newtype, conf );
2773 break;
2775 return GetConvertCollectionReadActionFrom<Looper,Long_t>(newtype, conf );
2776 break;
2778 return GetConvertCollectionReadActionFrom<Looper,Long64_t>(newtype, conf );
2779 break;
2781 return GetConvertCollectionReadActionFrom<Looper,Float_t>( newtype, conf );
2782 break;
2784 return GetConvertCollectionReadActionFrom<Looper,Double_t>(newtype, conf );
2785 break;
2787 return GetConvertCollectionReadActionFrom<Looper,UChar_t>(newtype, conf );
2788 break;
2790 return GetConvertCollectionReadActionFrom<Looper,UShort_t>(newtype, conf );
2791 break;
2793 return GetConvertCollectionReadActionFrom<Looper,UInt_t>(newtype, conf );
2794 break;
2796 return GetConvertCollectionReadActionFrom<Looper,ULong_t>(newtype, conf );
2797 break;
2799 return GetConvertCollectionReadActionFrom<Looper,ULong64_t>(newtype, conf );
2800 break;
2802 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Float16_t> >( newtype, conf );
2803 break;
2805 return GetConvertCollectionReadActionFrom<Looper,NoFactorMarker<Double32_t> >( newtype, conf );
2806 break;
2808 Error("GetConvertCollectionReadAction","There is no support for kBits outside of a TObject.");
2809 break;
2810 default:
2811 break;
2812 }
2813 R__ASSERT(0); // We should never be here
2814 return TConfiguredAction();
2815}
2816
2817template <class Looper>
2819{
2820 switch (type) {
2821 // Read basic types.
2822 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template ReadBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2823 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template ReadBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2824 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template ReadBasicType<Short_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2825 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template ReadBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2826 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template ReadBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2827 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template ReadBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2828 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template ReadBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2829 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template ReadBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2830 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template ReadBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2831 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template ReadBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2832 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template ReadBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2833 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template ReadBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2834 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template ReadBasicType<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2835 case TStreamerInfo::kBits: return TConfiguredAction( Looper::template ReadAction<TStreamerInfoActions::ReadBasicType<BitsMarker> > , new TBitsConfiguration(info,i,compinfo,offset) ); break;
2837 if (element->GetFactor() != 0) {
2838 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2839 } else {
2840 Int_t nbits = (Int_t)element->GetXmin();
2841 if (!nbits) nbits = 12;
2842 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2843 }
2844 break;
2845 }
2847 if (element->GetFactor() != 0) {
2848 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2849 } else {
2850 Int_t nbits = (Int_t)element->GetXmin();
2851 if (!nbits) {
2852 return TConfiguredAction( Looper::template ReadAction<ConvertBasicType<float,double>::Action >, new TConfiguration(info,i,compinfo,offset) );
2853 } else {
2854 return TConfiguredAction( Looper::template ReadAction<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
2855 }
2856 }
2857 break;
2858 }
2859 case TStreamerInfo::kTNamed: return TConfiguredAction( Looper::template ReadAction<ReadTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
2860 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
2861 // Streamer alltogether.
2862 case TStreamerInfo::kTObject: return TConfiguredAction( Looper::template ReadAction<ReadTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
2863 case TStreamerInfo::kTString: return TConfiguredAction( Looper::template ReadAction<ReadTString >, new TConfiguration(info,i,compinfo,offset) ); break;
2867 case TStreamerInfo::kSTL: return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) ); break;
2868 case TStreamerInfo::kBase: return TConfiguredAction( Looper::ReadBase, new TGenericConfiguration(info,i,compinfo) ); break;
2869
2870 // Conversions.
2872 return GetCollectionReadConvertAction<Looper,Bool_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2873 break;
2875 return GetCollectionReadConvertAction<Looper,Char_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2876 break;
2878 return GetCollectionReadConvertAction<Looper,Short_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2879 break;
2881 return GetCollectionReadConvertAction<Looper,Int_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2882 break;
2884 return GetCollectionReadConvertAction<Looper,Long_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2885 break;
2887 return GetCollectionReadConvertAction<Looper,Long64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2888 break;
2890 return GetCollectionReadConvertAction<Looper,Float_t>( element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2891 break;
2893 return GetCollectionReadConvertAction<Looper,Double_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2894 break;
2896 return GetCollectionReadConvertAction<Looper,UChar_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2897 break;
2899 return GetCollectionReadConvertAction<Looper,UShort_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2900 break;
2902 return GetCollectionReadConvertAction<Looper,UInt_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2903 break;
2905 return GetCollectionReadConvertAction<Looper,ULong_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2906 break;
2908 return GetCollectionReadConvertAction<Looper,ULong64_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2909 break;
2911 return GetCollectionReadConvertAction<Looper,BitsMarker>(element->GetNewType(), new TBitsConfiguration(info,i,compinfo,offset) );
2912 break;
2914 if (element->GetFactor() != 0) {
2915 return GetCollectionReadConvertAction<Looper,WithFactorMarker<float> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2916 } else {
2917 Int_t nbits = (Int_t)element->GetXmin();
2918 if (!nbits) nbits = 12;
2919 return GetCollectionReadConvertAction<Looper,NoFactorMarker<float> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2920 }
2921 break;
2922 }
2924 if (element->GetFactor() != 0) {
2925 return GetCollectionReadConvertAction<Looper,WithFactorMarker<double> >(element->GetNewType(), new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
2926 } else {
2927 Int_t nbits = (Int_t)element->GetXmin();
2928 if (!nbits) {
2929 return GetCollectionReadConvertAction<Looper,Float_t>(element->GetNewType(), new TConfiguration(info,i,compinfo,offset) );
2930 } else {
2931 return GetCollectionReadConvertAction<Looper,NoFactorMarker<double> >(element->GetNewType(), new TConfNoFactor(info,i,compinfo,offset,nbits) );
2932 }
2933 }
2934 break;
2935 }
2936 default:
2937 return TConfiguredAction( Looper::GenericRead, new TGenericConfiguration(info,i,compinfo) );
2938 break;
2939 }
2940 R__ASSERT(0); // We should never be here
2941 return TConfiguredAction();
2942}
2943
2944template <class Looper>
2946 switch (type) {
2947 // read basic types
2948 case TStreamerInfo::kBool: return TConfiguredAction( Looper::template WriteBasicType<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2949 case TStreamerInfo::kChar: return TConfiguredAction( Looper::template WriteBasicType<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2950 case TStreamerInfo::kShort: return TConfiguredAction( Looper::template WriteBasicType<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2951 case TStreamerInfo::kInt: return TConfiguredAction( Looper::template WriteBasicType<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2952 case TStreamerInfo::kLong: return TConfiguredAction( Looper::template WriteBasicType<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2953 case TStreamerInfo::kLong64: return TConfiguredAction( Looper::template WriteBasicType<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2954 case TStreamerInfo::kFloat: return TConfiguredAction( Looper::template WriteBasicType<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2955 case TStreamerInfo::kDouble: return TConfiguredAction( Looper::template WriteBasicType<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2956 case TStreamerInfo::kUChar: return TConfiguredAction( Looper::template WriteBasicType<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2957 case TStreamerInfo::kUShort: return TConfiguredAction( Looper::template WriteBasicType<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2958 case TStreamerInfo::kUInt: return TConfiguredAction( Looper::template WriteBasicType<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2959 case TStreamerInfo::kULong: return TConfiguredAction( Looper::template WriteBasicType<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
2960 case TStreamerInfo::kULong64: return TConfiguredAction( Looper::template WriteBasicType<ULong64_t>,new TConfiguration(info,i,compinfo,offset) ); break;
2961 // the simple type missing are kBits and kCounter.
2962 default:
2963 return TConfiguredAction( Looper::GenericWrite, new TConfiguration(info,i,compinfo,0 /* 0 because we call the legacy code */) );
2964 }
2965 R__ASSERT(0); // We should never be here
2966 return TConfiguredAction();
2967}
2968
2969
2970////////////////////////////////////////////////////////////////////////////////
2971/// loop on the TStreamerElement list
2972/// regroup members with same type
2973/// Store predigested information into local arrays. This saves a huge amount
2974/// of time compared to an explicit iteration on all elements.
2975
2977{
2978 if (IsCompiled()) {
2979 //Error("Compile","can only be called once; this first call generates both the optimized and memberwise actions.");
2980 return;
2981 }
2983
2984 // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
2985
2986 // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
2988 fNdata = 0;
2989 fNfulldata = 0;
2990
2991 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
2992 if (fNumber < 0) {
2993 ++fgCount;
2994 fNumber = fgCount;
2995 }
2996 if (fNumber >= infos->GetSize()) {
2997 infos->AddAtAndExpand(this, fNumber);
2998 } else {
2999 if (!infos->At(fNumber)) {
3000 infos->AddAt(this, fNumber);
3001 }
3002 }
3003
3004 assert(fComp == 0 && fCompFull == 0 && fCompOpt == 0);
3005
3006
3007 Int_t ndata = fElements->GetEntries();
3008
3009
3012
3015
3018
3019 if (fReadText) fReadText->fActions.clear();
3020 else fReadText = new TStreamerInfoActions::TActionSequence(this,ndata);
3021
3024
3027
3030
3031 if (fWriteText) fWriteText->fActions.clear();
3033
3034 if (!ndata) {
3035 // This may be the case for empty classes (e.g., TAtt3D).
3036 // We still need to properly set the size of emulated classes (i.e. add the virtual table)
3038 fSize = sizeof(TStreamerInfo*);
3039 }
3040 fComp = new TCompInfo[1];
3041 fCompFull = new TCompInfo*[1];
3042 fCompOpt = new TCompInfo*[1];
3043 fCompOpt[0] = fCompFull[0] = &(fComp[0]);
3044 SetIsCompiled();
3045 return;
3046 }
3047
3048 // At most half of the elements can be used to hold optimized versions.
3049 // We use the bottom to hold the optimized-into elements and the non-optimized elements
3050 // and the top to hold the original copy of the optimized out elements.
3051 fNslots = ndata + ndata/2 + 1;
3052 Int_t optiOut = 0;
3053
3054 fComp = new TCompInfo[fNslots];
3055 fCompFull = new TCompInfo*[ndata];
3056 fCompOpt = new TCompInfo*[ndata];
3057
3058 TStreamerElement* element;
3059 TStreamerElement* previous = 0;
3060 Int_t keep = -1;
3061 Int_t i;
3062
3063 if (!CanOptimize()) {
3065 }
3066
3067 Bool_t isOptimized = kFALSE;
3068 Bool_t previousOptimized = kFALSE;
3069
3070 for (i = 0; i < ndata; ++i) {
3071 element = (TStreamerElement*) fElements->At(i);
3072 if (!element) {
3073 break;
3074 }
3075
3076 Int_t asize = element->GetSize();
3077 if (element->GetArrayLength()) {
3078 asize /= element->GetArrayLength();
3079 }
3080 fComp[fNdata].fType = element->GetType();
3081 fComp[fNdata].fNewType = element->GetNewType();
3082 fComp[fNdata].fOffset = element->GetOffset();
3083 fComp[fNdata].fLength = element->GetArrayLength();
3084 fComp[fNdata].fElem = element;
3085 fComp[fNdata].fMethod = element->GetMethod();
3086 fComp[fNdata].fClass = element->GetClassPointer();
3087 fComp[fNdata].fNewClass = element->GetNewClass();
3089 fComp[fNdata].fStreamer = element->GetStreamer();
3090
3091 // try to group consecutive members of the same type
3093 && (keep >= 0)
3094 && (element->GetType() >=0)
3095 && (element->GetType() < 10)
3097 && (fComp[keep].fMethod == 0)
3098 && (element->GetType() > 0)
3099 && (element->GetArrayDim() == 0)
3100 && (fComp[keep].fType < kObject)
3101 && (fComp[keep].fType != kCharStar) /* do not optimize char* */
3102 && (element->GetType() == (fComp[keep].fType%kRegrouped))
3103 && ((element->GetOffset()-fComp[keep].fOffset) == (fComp[keep].fLength)*asize)
3104 && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
3105 ((element->GetFactor() == previous->GetFactor())
3106 && (element->GetXmin() == previous->GetXmin())
3107 && (element->GetXmax() == previous->GetXmax())
3108 )
3109 )
3112 // kWholeObject and kDoNotDelete do not apply to numerical elements.
3113 )
3114 {
3115 if (!previousOptimized) {
3116 // The element was not yet optimized we first need to copy it into
3117 // the set of original copies.
3118 fComp[fNslots - (++optiOut) ] = fComp[keep]; // Copy the optimized out elements.
3119 fCompFull[fNfulldata-1] = &(fComp[fNslots - optiOut]); // Reset the pointer in the full list.
3120 }
3121 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the optimized out elements.
3122 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3123
3124 R__ASSERT( keep < (fNslots - optiOut) );
3125
3126 if (fComp[keep].fLength == 0) {
3127 fComp[keep].fLength++;
3128 }
3129 fComp[keep].fLength++;
3130 fComp[keep].fType = element->GetType() + kRegrouped;
3131 isOptimized = kTRUE;
3132 previousOptimized = kTRUE;
3133 } else if (element->GetType() < 0) {
3134
3135 // -- Deal with an ignored TObject base class.
3136 // Note: The only allowed negative value here is -1,
3137 // and signifies that Build() has found a TObject
3138 // base class and TClass::IgnoreTObjectStreamer() was
3139 // called. In this case the compiled version of the
3140 // elements omits the TObject base class element,
3141 // which has to be compensated for by TTree::Bronch()
3142 // when it is making branches for a split object.
3143 fComp[fNslots - (++optiOut) ] = fComp[fNdata]; // Copy the 'ignored' element.
3144 fCompFull[fNfulldata] = &(fComp[fNslots - optiOut]);
3145 keep = -1;
3146 previousOptimized = kFALSE;
3147
3148 } else {
3149 if (fComp[fNdata].fNewType != fComp[fNdata].fType) {
3150 if (fComp[fNdata].fNewType > 0) {
3151 if ( (fComp[fNdata].fNewType == kObjectp || fComp[fNdata].fNewType == kAnyp
3152 || fComp[fNdata].fNewType == kObject || fComp[fNdata].fNewType == kAny
3153 || fComp[fNdata].fNewType == kTObject || fComp[fNdata].fNewType == kTNamed || fComp[fNdata].fNewType == kTString)
3157 ) {
3159 } else if (fComp[fNdata].fType != kCounter) {
3160 fComp[fNdata].fType += kConv;
3161 }
3162 } else {
3163 if (fComp[fNdata].fType == kCounter) {
3164 Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
3165 }
3166 fComp[fNdata].fType += kSkip;
3167 }
3168 }
3169 fCompOpt[fNdata] = &(fComp[fNdata]);
3171
3172 R__ASSERT( fNdata < (fNslots - optiOut) );
3173
3174 keep = fNdata;
3175 if (fComp[keep].fLength == 0) {
3176 fComp[keep].fLength = 1;
3177 }
3178 fNdata++;
3179 previousOptimized = kFALSE;
3180 }
3181 // The test 'fMethod[keep] == 0' fails to detect a variable size array
3182 // if the counter happens to have an offset of zero, so let's explicitly
3183 // prevent for here.
3184 if (element->HasCounter()) keep = -1;
3185 ++fNfulldata;
3186 previous = element;
3187 }
3188
3189 for (i = 0; i < fNdata; ++i) {
3190 if (!fCompOpt[i]->fElem || fCompOpt[i]->fElem->GetType()< 0) {
3191 continue;
3192 }
3195 }
3196 for (i = 0; i < fNfulldata; ++i) {
3197 if (!fCompFull[i]->fElem || fCompFull[i]->fElem->GetType()< 0) {
3198 continue;
3199 }
3204
3207 }
3208 ComputeSize();
3209
3210 fOptimized = isOptimized;
3211 SetIsCompiled();
3212
3213 if (gDebug > 0) {
3214 ls();
3215 }
3216}
3217
3218template <typename From>
3220{
3221 switch (newtype) {
3222 case TStreamerInfo::kBool: sequence->AddAction( ConvertBasicType<From,bool>::Action, conf ); break;
3223 case TStreamerInfo::kChar: sequence->AddAction( ConvertBasicType<From,char>::Action, conf ); break;
3224 case TStreamerInfo::kShort: sequence->AddAction( ConvertBasicType<From,short>::Action, conf ); break;
3225 case TStreamerInfo::kInt: sequence->AddAction( ConvertBasicType<From,Int_t>::Action, conf ); break;
3226 case TStreamerInfo::kLong: sequence->AddAction( ConvertBasicType<From,Long_t>::Action,conf ); break;
3227 case TStreamerInfo::kLong64: sequence->AddAction( ConvertBasicType<From,Long64_t>::Action, conf ); break;
3228 case TStreamerInfo::kFloat: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3229 case TStreamerInfo::kFloat16: sequence->AddAction( ConvertBasicType<From,float>::Action, conf ); break;
3230 case TStreamerInfo::kDouble: sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3231 case TStreamerInfo::kDouble32:sequence->AddAction( ConvertBasicType<From,double>::Action, conf ); break;
3232 case TStreamerInfo::kUChar: sequence->AddAction( ConvertBasicType<From,UChar_t>::Action, conf ); break;
3233 case TStreamerInfo::kUShort: sequence->AddAction( ConvertBasicType<From,UShort_t>::Action, conf ); break;
3234 case TStreamerInfo::kUInt: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3235 case TStreamerInfo::kULong: sequence->AddAction( ConvertBasicType<From,ULong_t>::Action, conf ); break;
3236 case TStreamerInfo::kULong64: sequence->AddAction( ConvertBasicType<From,ULong64_t>::Action,conf ); break;
3237 case TStreamerInfo::kBits: sequence->AddAction( ConvertBasicType<From,UInt_t>::Action, conf ); break;
3238 }
3239}
3240
3241////////////////////////////////////////////////////////////////////////////////
3242/// Add a read action for the given element.
3243
3245{
3246 TStreamerElement *element = compinfo->fElem;
3247
3248 if (element->TestBit(TStreamerElement::kWrite)) return;
3249
3250 switch (compinfo->fType) {
3251 // read basic types
3252 case TStreamerInfo::kBool: readSequence->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3253 case TStreamerInfo::kChar: readSequence->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3254 case TStreamerInfo::kShort: readSequence->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3255 case TStreamerInfo::kInt: readSequence->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3256 case TStreamerInfo::kLong: readSequence->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3257 case TStreamerInfo::kLong64: readSequence->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3258 case TStreamerInfo::kFloat: readSequence->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3259 case TStreamerInfo::kDouble: readSequence->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3260 case TStreamerInfo::kUChar: readSequence->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3261 case TStreamerInfo::kUShort: readSequence->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3262 case TStreamerInfo::kUInt: readSequence->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3263 case TStreamerInfo::kULong: readSequence->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3264 case TStreamerInfo::kULong64: readSequence->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3265 case TStreamerInfo::kBits: readSequence->AddAction( ReadBasicType<BitsMarker>, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3267 if (element->GetFactor() != 0) {
3268 readSequence->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3269 } else {
3270 Int_t nbits = (Int_t)element->GetXmin();
3271 if (!nbits) nbits = 12;
3272 readSequence->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3273 }
3274 break;
3275 }
3277 if (element->GetFactor() != 0) {
3278 readSequence->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3279 } else {
3280 Int_t nbits = (Int_t)element->GetXmin();
3281 if (!nbits) {
3282 readSequence->AddAction( ConvertBasicType<float,double>::Action, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3283 } else {
3284 readSequence->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3285 }
3286 }
3287 break;
3288 }
3289 case TStreamerInfo::kTNamed: readSequence->AddAction( ReadTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3290 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3291 // Streamer alltogether.
3292 case TStreamerInfo::kTObject: readSequence->AddAction( ReadTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3293 case TStreamerInfo::kTString: readSequence->AddAction( ReadTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3294 case TStreamerInfo::kSTL: {
3295 TClass *newClass = element->GetNewClass();
3296 TClass *oldClass = element->GetClassPointer();
3297 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3298
3299 if (element->GetArrayLength() <= 1) {
3300 if (fOldVersion<3){ // case of old TStreamerInfo
3301 if (newClass && newClass != oldClass) {
3302 if (element->GetStreamer()) {
3303 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3304 } else {
3305 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3306 }
3307 } else {
3308 if (element->GetStreamer()) {
3309 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3310 } else {
3311 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3312 }
3313 }
3314 } else {
3315 if (newClass && newClass != oldClass) {
3316 if (element->GetStreamer()) {
3317 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3318 } else {
3319 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3320 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3321 } else {
3322 switch (SelectLooper(*newClass->GetCollectionProxy())) {
3323 case kVectorLooper:
3324 readSequence->AddAction(GetConvertCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3325 break;
3326 case kAssociativeLooper:
3327 readSequence->AddAction(GetConvertCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3328 break;
3329 case kVectorPtrLooper:
3330 case kGenericLooper:
3331 default:
3332 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3333 readSequence->AddAction(GetConvertCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), newClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase)));
3334 break;
3335 }
3336 }
3337 }
3338 } else {
3339 if (element->GetStreamer()) {
3340 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3341 } else {
3342 if (oldClass->GetCollectionProxy() == 0 || oldClass->GetCollectionProxy()->GetValueClass() || oldClass->GetCollectionProxy()->HasPointers() ) {
3343 readSequence->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3344 } else {
3345 switch (SelectLooper(*oldClass->GetCollectionProxy())) {
3346 case kVectorLooper:
3347 readSequence->AddAction(GetNumericCollectionReadAction<VectorLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3348 break;
3349 case kAssociativeLooper:
3350 readSequence->AddAction(GetNumericCollectionReadAction<AssociativeLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3351 break;
3352 case kVectorPtrLooper:
3353 case kGenericLooper:
3354 default:
3355 // For now TBufferXML would force use to allocate the data buffer each time and copy into the real thing.
3356 readSequence->AddAction(GetNumericCollectionReadAction<GenericLooper>(oldClass->GetCollectionProxy()->GetType(), new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase)));
3357 break;
3358 }
3359 }
3360 }
3361 }
3362 }
3363 } else {
3364 if (fOldVersion<3){ // case of old TStreamerInfo
3365 if (newClass && newClass != oldClass) {
3366 if (element->GetStreamer()) {
3367 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3368 } else {
3369 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3370 }
3371 } else {
3372 if (element->GetStreamer()) {
3373 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3374 } else {
3375 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3376 }
3377 }
3378 } else {
3379 if (newClass && newClass != oldClass) {
3380 if (element->GetStreamer()) {
3381 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3382 } else {
3383 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3384 }
3385 } else {
3386 if (element->GetStreamer()) {
3387 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3388 } else {
3389 readSequence->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3390 }
3391 }
3392 }
3393 }
3394 break;
3395 }
3396
3398 AddReadConvertAction<Bool_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3399 break;
3401 AddReadConvertAction<Char_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3402 break;
3404 AddReadConvertAction<Short_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3405 break;
3407 AddReadConvertAction<Int_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3408 break;
3410 AddReadConvertAction<Long_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3411 break;
3413 AddReadConvertAction<Long64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3414 break;
3416 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3417 break;
3419 AddReadConvertAction<Double_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3420 break;
3422 AddReadConvertAction<UChar_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3423 break;
3425 AddReadConvertAction<UShort_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3426 break;
3428 AddReadConvertAction<UInt_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3429 break;
3431 AddReadConvertAction<ULong_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3432 break;
3434 AddReadConvertAction<ULong64_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3435 break;
3437 AddReadConvertAction<BitsMarker>(readSequence, compinfo->fNewType, new TBitsConfiguration(this,i,compinfo,compinfo->fOffset) );
3438 break;
3440 if (element->GetFactor() != 0) {
3441 AddReadConvertAction<WithFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3442 } else {
3443 Int_t nbits = (Int_t)element->GetXmin();
3444 if (!nbits) nbits = 12;
3445 AddReadConvertAction<NoFactorMarker<float> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3446 }
3447 break;
3448 }
3450 if (element->GetFactor() != 0) {
3451 AddReadConvertAction<WithFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3452 } else {
3453 Int_t nbits = (Int_t)element->GetXmin();
3454 if (!nbits) {
3455 AddReadConvertAction<Float_t>(readSequence, compinfo->fNewType, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3456 } else {
3457 AddReadConvertAction<NoFactorMarker<double> >(readSequence, compinfo->fNewType, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3458 }
3459 }
3460 break;
3461 }
3462 default:
3463 readSequence->AddAction( GenericReadAction, new TGenericConfiguration(this,i,compinfo) );
3464 break;
3465 }
3466 if (element->TestBit(TStreamerElement::kCache)) {
3467 TConfiguredAction action( readSequence->fActions.back() ); // Action is moved, we must pop it next.
3468 readSequence->fActions.pop_back();
3469 readSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3470 }
3471}
3472
3473////////////////////////////////////////////////////////////////////////////////
3474/// Add a read text action for the given element.
3475
3477{
3478 TStreamerElement *element = compinfo->fElem;
3479
3480 if (element->TestBit(TStreamerElement::kWrite))
3481 return;
3482
3483 Bool_t generic = kFALSE, isBase = kFALSE;
3484
3485 switch (compinfo->fType) {
3487 if (element->IsBase())
3488 isBase = kTRUE;
3489 // readSequence->AddAction( ReadTextTObjectBase, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3490 else
3491 readSequence->AddAction(ReadTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3492 break;
3493
3495 if (element->IsBase())
3496 isBase = kTRUE;
3497 // generic = kTRUE; // for the base class one cannot call TClass::Streamer() as performed for the normal object
3498 else
3499 readSequence->AddAction(ReadTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3500 break;
3501
3502 case TStreamerInfo::kObject: // Class derived from TObject
3503 case TStreamerInfo::kAny: // Class NOT derived from TObject
3506 readSequence->AddAction(ReadTextObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3507 break;
3508
3509 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3511 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3512 readSequence->AddAction(ReadSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3513 break;
3514
3517 readSequence->AddAction(ReadStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3518 break;
3519
3520 case TStreamerInfo::kBase: isBase = kTRUE; break;
3521
3523 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3524 break;
3525
3526 default: generic = kTRUE; break;
3527 }
3528
3529 if (isBase) {
3530 if (compinfo->fStreamer) {
3531 readSequence->AddAction(ReadTextStreamer, new TGenericConfiguration(this, i, compinfo));
3532 } else {
3533 readSequence->AddAction(ReadTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3534 }
3535 } else if (generic)
3536 readSequence->AddAction(GenericReadAction, new TGenericConfiguration(this, i, compinfo));
3537}
3538
3539////////////////////////////////////////////////////////////////////////////////
3540/// Add a read action for the given element.
3541/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3542
3544{
3545 TStreamerElement *element = compinfo->fElem;
3546
3547 if (element->TestBit(TStreamerElement::kWrite)) return;
3548
3549 if (element->TestBit(TStreamerElement::kCache)) {
3550 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3551 readSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3552 } else {
3553 readSequence->AddAction( GetCollectionReadAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3554 }
3555}
3556
3557////////////////////////////////////////////////////////////////////////////////
3558
3560{
3561 TStreamerElement *element = compinfo->fElem;
3563 // Skip element cached for reading purposes.
3564 return;
3565 }
3566 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3567 // Skip artificial element used for reading purposes.
3568 return;
3569 }
3570 switch (compinfo->fType) {
3571 // write basic types
3572 case TStreamerInfo::kBool: writeSequence->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3573 case TStreamerInfo::kChar: writeSequence->AddAction( WriteBasicType<Char_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3574 case TStreamerInfo::kShort: writeSequence->AddAction( WriteBasicType<Short_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3575 case TStreamerInfo::kInt: writeSequence->AddAction( WriteBasicType<Int_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3576 case TStreamerInfo::kLong: writeSequence->AddAction( WriteBasicType<Long_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3577 case TStreamerInfo::kLong64: writeSequence->AddAction( WriteBasicType<Long64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3578 case TStreamerInfo::kFloat: writeSequence->AddAction( WriteBasicType<Float_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3579 case TStreamerInfo::kDouble: writeSequence->AddAction( WriteBasicType<Double_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3580 case TStreamerInfo::kUChar: writeSequence->AddAction( WriteBasicType<UChar_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3581 case TStreamerInfo::kUShort: writeSequence->AddAction( WriteBasicType<UShort_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3582 case TStreamerInfo::kUInt: writeSequence->AddAction( WriteBasicType<UInt_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3583 case TStreamerInfo::kULong: writeSequence->AddAction( WriteBasicType<ULong_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3584 case TStreamerInfo::kULong64: writeSequence->AddAction( WriteBasicType<ULong64_t>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3585 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3586 /*case TStreamerInfo::kFloat16: {
3587 if (element->GetFactor() != 0) {
3588 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3589 } else {
3590 Int_t nbits = (Int_t)element->GetXmin();
3591 if (!nbits) nbits = 12;
3592 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3593 }
3594 break;
3595 } */
3596 /*case TStreamerInfo::kDouble32: {
3597 if (element->GetFactor() != 0) {
3598 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3599 } else {
3600 Int_t nbits = (Int_t)element->GetXmin();
3601 if (!nbits) {
3602 writeSequence->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,compinfo,compinfo->fOffset) );
3603 } else {
3604 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3605 }
3606 }
3607 break;
3608 } */
3609 //case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3610 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3611 // Streamer alltogether.
3612 //case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3613 //case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3614 /*case TStreamerInfo::kSTL: {
3615 TClass *newClass = element->GetNewClass();
3616 TClass *oldClass = element->GetClassPointer();
3617 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3618
3619 if (element->GetArrayLength() <= 1) {
3620 if (newClass && newClass != oldClass) {
3621 if (element->GetStreamer()) {
3622 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3623 } else {
3624 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3625 }
3626 } else {
3627 if (element->GetStreamer()) {
3628 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3629 } else {
3630 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3631 }
3632 }
3633 } else {
3634 if (newClass && newClass != oldClass) {
3635 if (element->GetStreamer()) {
3636 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3637 } else {
3638 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3639 }
3640 } else {
3641 if (element->GetStreamer()) {
3642 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3643 } else {
3644 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3645 }
3646 }
3647 }
3648 break;
3649 } */
3650 default:
3651 writeSequence->AddAction( GenericWriteAction, new TGenericConfiguration(this,i,compinfo) );
3652 break;
3653 }
3654#if defined(CDJ_NO_COMPILE)
3655 if (element->TestBit(TStreamerElement::kCache)) {
3656 TConfiguredAction action( writeSequence->fActions.back() ); // Action is moved, we must pop it next.
3657 writeSequence->fActions.pop_back();
3658 writeSequence->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3659 }
3660#endif
3661}
3662
3663////////////////////////////////////////////////////////////////////////////////
3664
3666{
3667 TStreamerElement *element = compinfo->fElem;
3669 // Skip element cached for reading purposes.
3670 return;
3671 }
3672 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3673 // Skip artificial element used for reading purposes.
3674 return;
3675 }
3676
3677 Bool_t generic = kFALSE, isBase = kFALSE;
3678
3679 switch (compinfo->fType) {
3680 // write basic types
3682 writeSequence->AddAction(WriteBasicType<Bool_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3683 break;
3685 writeSequence->AddAction(WriteBasicType<Char_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3686 break;
3688 writeSequence->AddAction(WriteBasicType<Short_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3689 break;
3691 writeSequence->AddAction(WriteBasicType<Int_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3692 break;
3694 writeSequence->AddAction(WriteBasicType<Long_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3695 break;
3697 writeSequence->AddAction(WriteBasicType<Long64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3698 break;
3700 writeSequence->AddAction(WriteBasicType<Float_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3701 break;
3703 writeSequence->AddAction(WriteBasicType<Double_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3704 break;
3706 writeSequence->AddAction(WriteBasicType<UChar_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3707 break;
3709 writeSequence->AddAction(WriteBasicType<UShort_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3710 break;
3712 writeSequence->AddAction(WriteBasicType<UInt_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3713 break;
3715 writeSequence->AddAction(WriteBasicType<ULong_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3716 break;
3718 writeSequence->AddAction(WriteBasicType<ULong64_t>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3719 break;
3720
3722 if (element->IsBase())
3723 isBase = kTRUE;
3724 else
3725 writeSequence->AddAction(WriteTextTObject, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3726 break;
3727
3729 if (element->IsBase())
3730 isBase = kTRUE;
3731 else
3732 writeSequence->AddAction(WriteTextTNamed, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3733 break;
3734
3735 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
3737 TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
3738 writeSequence->AddAction(WriteSTLp<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3739 break;
3740
3743 writeSequence->AddAction(WriteStreamerLoop<true>, new TConfiguration(this, i, compinfo, compinfo->fOffset));
3744 break;
3745
3746 case TStreamerInfo::kBase: isBase = kTRUE; break;
3747
3749 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3750 break;
3751
3752 // case TStreamerInfo::kBits: writeSequence->AddAction( WriteBasicType<BitsMarker>, new
3753 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3754 /*case TStreamerInfo::kFloat16: {
3755 if (element->GetFactor() != 0) {
3756 writeSequence->AddAction( WriteBasicType_WithFactor<float>, new
3757 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3758 } else {
3759 Int_t nbits = (Int_t)element->GetXmin();
3760 if (!nbits) nbits = 12;
3761 writeSequence->AddAction( WriteBasicType_NoFactor<float>, new
3762 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3763 }
3764 break;
3765 } */
3766 /*case TStreamerInfo::kDouble32: {
3767 if (element->GetFactor() != 0) {
3768 writeSequence->AddAction( WriteBasicType_WithFactor<double>, new
3769 TConfWithFactor(this,i,compinfo,compinfo->fOffset,element->GetFactor(),element->GetXmin()) );
3770 } else {
3771 Int_t nbits = (Int_t)element->GetXmin();
3772 if (!nbits) {
3773 writeSequence->AddAction( ConvertBasicType<float,double>, new
3774 TConfiguration(this,i,compinfo,compinfo->fOffset) );
3775 } else {
3776 writeSequence->AddAction( WriteBasicType_NoFactor<double>, new
3777 TConfNoFactor(this,i,compinfo,compinfo->fOffset,nbits) );
3778 }
3779 }
3780 break;
3781 } */
3782 // case TStreamerInfo::kTNamed: writeSequence->AddAction( WriteTNamed, new
3783 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3784 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
3785 // Streamer alltogether.
3786 // case TStreamerInfo::kTObject: writeSequence->AddAction( WriteTObject, new
3787 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3788 // case TStreamerInfo::kTString: writeSequence->AddAction( WriteTString, new
3789 // TConfiguration(this,i,compinfo,compinfo->fOffset) ); break;
3790 /*case TStreamerInfo::kSTL: {
3791 TClass *newClass = element->GetNewClass();
3792 TClass *oldClass = element->GetClassPointer();
3793 Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
3794
3795 if (element->GetArrayLength() <= 1) {
3796 if (newClass && newClass != oldClass) {
3797 if (element->GetStreamer()) {
3798 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3799 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3800 } else {
3801 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3802 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,newClass,element->GetTypeName(),isSTLbase));
3803 }
3804 } else {
3805 if (element->GetStreamer()) {
3806 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3807 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3808 } else {
3809 writeSequence->AddAction(WriteSTL<WriteSTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3810 TConfigSTL(this,i,compinfo,compinfo->fOffset,1,oldClass,element->GetTypeName(),isSTLbase));
3811 }
3812 }
3813 } else {
3814 if (newClass && newClass != oldClass) {
3815 if (element->GetStreamer()) {
3816 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseStreamer>, new
3817 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3818 } else {
3819 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseChangedClass,WriteSTLObjectWiseFastArray>, new
3820 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));
3821 }
3822 } else {
3823 if (element->GetStreamer()) {
3824 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseStreamer>, new
3825 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
3826 } else {
3827 writeSequence->AddAction(WriteSTL<WriteArraySTLMemberWiseSameClass,WriteSTLObjectWiseFastArray>, new
3828 TConfigSTL(this,i,compinfo,compinfo->fOffset,element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
3829 }
3830 }
3831 }
3832 break;
3833 } */
3834 default: generic = kTRUE; break;
3835 }
3836
3837 if (isBase) {
3838 if (compinfo->fStreamer) {
3839 writeSequence->AddAction(WriteTextStreamer, new TGenericConfiguration(this, i, compinfo));
3840 } else {
3841 writeSequence->AddAction(WriteTextBaseClass, new TGenericConfiguration(this, i, compinfo));
3842 }
3843
3844 } else
3845
3846 // use generic write action when special handling is not provided
3847 if (generic)
3848 writeSequence->AddAction(GenericWriteAction, new TGenericConfiguration(this, i, compinfo));
3849
3850#if defined(CDJ_NO_COMPILE)
3851 if (element->TestBit(TStreamerElement::kCache)) {
3852 TConfiguredAction action(writeSequence->fActions.back()); // Action is moved, we must pop it next.
3853 writeSequence->fActions.pop_back();
3854 writeSequence->AddAction(UseCache,
3855 new TConfigurationUseCache(this, action, element->TestBit(TStreamerElement::kRepeat)));
3856 }
3857#endif
3858}
3859
3860////////////////////////////////////////////////////////////////////////////////
3861/// This is for streaming via a TClonesArray (or a vector of pointers of this type).
3862
3864{
3865 TStreamerElement *element = compinfo->fElem;
3867 // Skip element cached for reading purposes.
3868 return;
3869 }
3870 if (element->GetType() >= kArtificial && !element->TestBit(TStreamerElement::kWrite)) {
3871 // Skip artificial element used for reading purposes.
3872 return;
3873 }
3874
3875#if defined(CDJ_NO_COMPILE)
3876 if (element->TestBit(TStreamerElement::kCache)) {
3877 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3878 writeSequence->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
3879 } else {
3880 writeSequence->Addaction( GetCollectionWriteAction<VectorPtrLooper>(this,element,compinfo->fType,i,compinfo,compinfo->fOffset) );
3881 }
3882#else
3883 writeSequence->AddAction( VectorPtrLooper::GenericWrite, new TGenericConfiguration(this,i,compinfo) );
3884#endif
3885
3886}
3887
3888////////////////////////////////////////////////////////////////////////////////
3889/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
3890
3892{
3893 if (info == 0) {
3895 }
3896
3897 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
3898
3899 UInt_t ndata = info->GetElements()->GetEntries();
3901 if (IsDefaultVector(proxy))
3902 {
3903 if (proxy.HasPointers()) {
3904 // Instead of the creating a new one let's copy the one from the StreamerInfo.
3905 delete sequence;
3906
3907 sequence = sinfo->GetReadMemberWiseActions(kTRUE)->CreateCopy();
3908
3909 return sequence;
3910 }
3911
3912 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3913 Long_t increment = proxy.GetIncrement();
3914 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3919 {
3920 Long_t increment = proxy.GetIncrement();
3921 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kTRUE);
3922 // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
3923 } else {
3924 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kTRUE);
3925 }
3926 for (UInt_t i = 0; i < ndata; ++i) {
3927 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
3928 if (!element) {
3929 break;
3930 }
3931 if (element->GetType() < 0) {
3932 // -- Skip an ignored TObject base class.
3933 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
3934 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
3935 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
3936 // when it is making branches for a split object.
3937 continue;
3938 }
3939 if (element->TestBit(TStreamerElement::kWrite)) {
3940 // Skip element that only for writing.
3941 continue;
3942 }
3943 TStreamerBase *baseEl = dynamic_cast<TStreamerBase*>(element);
3944 if (baseEl) {
3945 if (!baseEl->TestBit(TStreamerElement::kWarned) && baseEl->GetErrorMessage()[0]) {
3946 // There was a problem with the checksum, the user likely did not
3947 // increment the version number of the derived class when the
3948 // base class changed. Since we will be member wise streaming
3949 // this class, let's warn the user that something is wrong.
3950 ::Warning("CreateReadMemberWiseActions","%s",
3951 baseEl->GetErrorMessage());
3953 }
3954 }
3955
3956 TStreamerInfo::TCompInfo_t *compinfo = sinfo->fCompFull[i];
3957
3958 Int_t asize = element->GetSize();
3959 if (element->GetArrayLength()) {
3960 asize /= element->GetArrayLength();
3961 }
3962 Int_t oldType = element->GetType();
3963 Int_t newType = element->GetNewType();
3964
3965 Int_t offset = element->GetOffset();
3966 if (newType != oldType) {
3967 if (newType > 0) {
3968 if (oldType != TVirtualStreamerInfo::kCounter) {
3969 oldType += TVirtualStreamerInfo::kConv;
3970 }
3971 } else {
3972 oldType += TVirtualStreamerInfo::kSkip;
3973 }
3974 }
3975 switch (SelectLooper(proxy)) {
3976 case kAssociativeLooper:
3977// } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
3978// || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
3979// sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
3980 case kVectorLooper:
3981 case kVectorPtrLooper:
3982 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
3983 if (element->TestBit(TStreamerElement::kCache)) {
3984 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3985 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3986 } else {
3987 sequence->AddAction( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
3988 }
3989 break;
3990 case kGenericLooper:
3991 default:
3992 // The usual collection case.
3993 if (element->TestBit(TStreamerElement::kCache)) {
3994 TConfiguredAction action( GetCollectionReadAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
3995 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
3996 } else {
3997 sequence->AddAction( GetCollectionReadAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
3998 }
3999 break;
4000 }
4001 }
4002 return sequence;
4003}
4004
4005////////////////////////////////////////////////////////////////////////////////
4006/// Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
4007
4009{
4010 if (info == 0) {
4012 }
4013
4014 UInt_t ndata = info->GetElements()->GetEntries();
4015 TStreamerInfo *sinfo = static_cast<TStreamerInfo*>(info);
4017
4018 if (IsDefaultVector(proxy))
4019 {
4020 if (proxy.HasPointers()) {
4021 // Instead of the creating a new one let's copy the one from the StreamerInfo.
4022 delete sequence;
4023
4024 sequence = sinfo->GetWriteMemberWiseActions(kTRUE)->CreateCopy();
4025
4026 return sequence;
4027 }
4028
4029 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4030 Long_t increment = proxy.GetIncrement();
4031 sequence->fLoopConfig = new TVectorLoopConfig(&proxy, increment, /* read */ kFALSE);
4032 /*} else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4033 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)
4034 {
4035 Long_t increment = proxy.GetIncrement();
4036 sequence->fLoopConfig = new TVectorLoopConfig(increment);
4037 // sequence->fLoopConfig = new TAssocLoopConfig(proxy); */
4038 } else {
4039 sequence->fLoopConfig = new TGenericLoopConfig(&proxy, /* read */ kFALSE);
4040 }
4041 for (UInt_t i = 0; i < ndata; ++i) {
4042 TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
4043 if (!element) {
4044 break;
4045 }
4046 if (element->GetType() < 0) {
4047 // -- Skip an ignored TObject base class.
4048 // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
4049 // base class and TClass::IgnoreTObjectStreamer() was called. In this case the compiled version of the
4050 // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
4051 // when it is making branches for a split object.
4052 continue;
4053 }
4055 // Skip element cached for reading purposes.
4056 continue;
4057 }
4059 // Skip artificial element used for reading purposes.
4060 continue;
4061 }
4062 TStreamerInfo::TCompInfo *compinfo = sinfo->fCompFull[i];
4063 Int_t asize = element->GetSize();
4064 if (element->GetArrayLength()) {
4065 asize /= element->GetArrayLength();
4066 }
4067 Int_t oldType = element->GetType();
4068 Int_t offset = element->GetOffset();
4069#if defined(CDJ_NO_COMPILE)
4070 Int_t newType = element->GetNewType();
4071
4072 if (newType != oldType) {
4073 if (newType > 0) {
4074 if (oldType != TVirtualStreamerInfo::kCounter) {
4075 oldType += TVirtualStreamerInfo::kConv;
4076 }
4077 } else {
4078 oldType += TVirtualStreamerInfo::kSkip;
4079 }
4080 }
4081 if ( IsDefaultVector(proxy)
4082 /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4083 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) */ )
4084 {
4085
4086 // We can speed up the iteration in case of vector. We also know that all emulated collection are stored internally as a vector.
4087 if (element->TestBit(TStreamerElement::kCache)) {
4088 TConfiguredAction action( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4089 sequence->AddAction( UseCacheVectorLoop, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4090 } else {
4091 sequence->AddAction(GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset));
4092 }
4093
4094 // } else if (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4095 // || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap) {
4096 // sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,compinfo,offset,0,proxy.GetCollectionClass(),0,0) );
4097 } else {
4098 // The usual collection case.
4099 if (element->TestBit(TStreamerElement::kCache)) {
4100 TConfiguredAction action( GetWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4101 sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
4102 } else {
4103 switch (oldType) {
4104 // read basic types
4105 case TVirtualStreamerInfo::kBool: sequence->AddAction( WriteBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4106 case TVirtualStreamerInfo::kChar: sequence->AddAction( WriteBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4107 case TVirtualStreamerInfo::kShort: sequence->AddAction( WriteBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4108 case TVirtualStreamerInfo::kInt: sequence->AddAction( WriteBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4109 case TVirtualStreamerInfo::kLong: sequence->AddAction( WriteBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4110 case TVirtualStreamerInfo::kLong64: sequence->AddAction( WriteBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4111 case TVirtualStreamerInfo::kFloat: sequence->AddAction( WriteBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4112 case TVirtualStreamerInfo::kDouble: sequence->AddAction( WriteBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4113 case TVirtualStreamerInfo::kUChar: sequence->AddAction( WriteBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4114 case TVirtualStreamerInfo::kUShort: sequence->AddAction( WriteBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4115 case TVirtualStreamerInfo::kUInt: sequence->AddAction( WriteBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4116 case TVirtualStreamerInfo::kULong: sequence->AddAction( WriteBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4117 case TVirtualStreamerInfo::kULong64: sequence->AddAction( WriteBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,compinfo,offset) ); break;
4118 // case TVirtualStreamerInfo::kBits: sequence->AddAction( WriteBasicTypeGenericLoop<BitsMarker>, new TConfiguration(info,i,compinfo,offset) ); break;
4120 if (element->GetFactor() != 0) {
4121 sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<float> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4122 } else {
4123 Int_t nbits = (Int_t)element->GetXmin();
4124 if (!nbits) nbits = 12;
4125 sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<float> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4126 }
4127 break;
4128 }
4130 if (element->GetFactor() != 0) {
4131 sequence->AddAction( GenericLooper<WriteBasicType_WithFactor<double> >, new TConfWithFactor(info,i,compinfo,offset,element->GetFactor(),element->GetXmin()) );
4132 } else {
4133 Int_t nbits = (Int_t)element->GetXmin();
4134 if (!nbits) {
4135 sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,compinfo,offset) );
4136 } else {
4137 sequence->AddAction( GenericLooper<WriteBasicType_NoFactor<double> >, new TConfNoFactor(info,i,compinfo,offset,nbits) );
4138 }
4139 }
4140 break;
4141 }
4142 case TVirtualStreamerInfo::kTNamed: sequence->AddAction( GenericLooper<WriteTNamed >, new TConfiguration(info,i,compinfo,offset) ); break;
4143 // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
4144 // Streamer alltogether.
4145 case TVirtualStreamerInfo::kTObject: sequence->AddAction( GenericLooper<WriteTObject >, new TConfiguration(info,i,compinfo,offset) ); break;
4146 case TVirtualStreamerInfo::kTString: sequence->AddAction( GenericLooper<WriteTString >, new TConfiguration(info,i,compinfo,offset) ); break;
4147 default:
4148 sequence->AddAction( GenericCollectionWriteAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4149 break;
4150 }
4151 }
4152 }
4153#else
4154 if ( IsDefaultVector(proxy)
4155 /*|| (proxy.GetCollectionType() == ROOT::kSTLset || proxy.GetCollectionType() == ROOT::kSTLmultiset
4156 || proxy.GetCollectionType() == ROOT::kSTLmap || proxy.GetCollectionType() == ROOT::kSTLmultimap)*/ )
4157 {
4158 sequence->AddAction( GetCollectionWriteAction<VectorLooper>(info,element,oldType,i,compinfo,offset) );
4159 } else {
4160 // NOTE: TBranch::FillLeavesCollection[Member] is not yet ready to handle the sequence
4161 // as it does not create/use a TStaging as expected ... but then again it might
4162 // not be the right things to expect ...
4163 // sequence->AddAction( GetCollectionWriteAction<GenericLooper>(info,element,oldType,i,compinfo,offset) );
4164 sequence->AddAction( GenericLooper::GenericWrite, new TConfigSTL(info,i,compinfo,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
4165 }
4166#endif
4167 }
4168 return sequence;
4169}
4170
4172{
4173 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4174 // TBranchElement in the case of split sub-object.
4175
4176 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4177 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4178 iter != end;
4179 ++iter)
4180 {
4181 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4182 iter->fConfiguration->AddToOffset(delta);
4183 }
4184}
4185
4187{
4188 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4189 // TBranchElement in the case of split sub-object.
4190
4191 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4192 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4193 iter != end;
4194 ++iter)
4195 {
4196 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4197 iter->fConfiguration->SetMissing();
4198 }
4199}
4200
4202{
4203 // Create a copy of this sequence.
4204
4205 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,fActions.size());
4206
4207 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4208
4209 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4210 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4211 iter != end;
4212 ++iter)
4213 {
4214 TConfiguration *conf = iter->fConfiguration->Copy();
4215 sequence->AddAction( iter->fAction, conf );
4216 }
4217 return sequence;
4218}
4219
4221 const TStreamerInfoActions::TIDs &element_ids,
4222 Int_t offset,
4224{
4225 for(UInt_t id = 0; id < element_ids.size(); ++id) {
4226 if ( element_ids[id].fElemID < 0 ) {
4227 if (element_ids[id].fNestedIDs) {
4228 auto original = create(element_ids[id].fNestedIDs->fInfo,
4229 sequence->fLoopConfig ? sequence->fLoopConfig->GetCollectionProxy() : nullptr,
4230 nullptr);
4231 if (element_ids[id].fNestedIDs->fOnfileObject) {
4232 auto conf = new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, element_ids[id].fNestedIDs->fOnfileObject, offset);
4233 if ( sequence->fLoopConfig )
4234 sequence->AddAction( PushDataCacheGenericCollection, conf );
4235 else
4236 sequence->AddAction( PushDataCache, conf );
4237 }
4238
4239 original->AddToSubSequence(sequence, element_ids[id].fNestedIDs->fIDs, element_ids[id].fNestedIDs->fOffset, create);
4240
4241 if (element_ids[id].fNestedIDs->fOnfileObject)
4242 sequence->AddAction( PopDataCache,
4243 new TConfigurationPushDataCache(element_ids[id].fNestedIDs->fInfo, nullptr, element_ids[id].fNestedIDs->fOffset) );
4244 } else {
4245 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4246 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4247 iter != end;
4248 ++iter)
4249 {
4250 TConfiguration *conf = iter->fConfiguration->Copy();
4251 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4252 conf->AddToOffset(offset);
4253 sequence->AddAction( iter->fAction, conf );
4254 }
4255 }
4256 } else {
4257 int localIndex = 0;
4258 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4259 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4260 iter != end;
4261 ++iter) {
4262 // fprintf(stderr, "With element_ids[%d] For %s comparing act[%d/%zu] %d to %d for %p vs %p %s\n",
4263 // id,
4264 // iter->fConfiguration->fInfo->GetName(),
4265 // localIndex, fActions.size(),
4266 // iter->fConfiguration->fElemId,
4267 // (UInt_t)element_ids[id].fElemID, iter->fConfiguration->fInfo,
4268 // element_ids[id].fInfo,
4269 // element_ids[id].fInfo ? element_ids[id].fInfo->GetName() : "nullptr" );
4270 ++localIndex;
4271 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id].fElemID ) {
4272 TConfiguration *conf = iter->fConfiguration->Copy();
4273 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4274 conf->AddToOffset(offset);
4275 sequence->AddAction( iter->fAction, conf );
4276 }
4277 }
4278 }
4279 }
4280}
4281
4284{
4285 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4286 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4287
4288 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
4289
4290 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4291
4292 AddToSubSequence(sequence, element_ids, offset, create);
4293
4294 return sequence;
4295}
4296
4298{
4299 // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
4300 // 'offset' is the location of this 'class' within the object (address) that will be passed to ReadBuffer when using this sequence.
4301
4302 TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
4303
4304 sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
4305
4306 for(UInt_t id = 0; id < element_ids.size(); ++id) {
4307 if ( element_ids[id] < 0 ) {
4308 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4309 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4310 iter != end;
4311 ++iter)
4312 {
4313 TConfiguration *conf = iter->fConfiguration->Copy();
4314 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4315 conf->AddToOffset(offset);
4316 sequence->AddAction( iter->fAction, conf );
4317 }
4318 } else {
4319 TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
4320 for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
4321 iter != end;
4322 ++iter) {
4323 if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
4324 TConfiguration *conf = iter->fConfiguration->Copy();
4325 if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
4326 conf->AddToOffset(offset);
4327 sequence->AddAction( iter->fAction, conf );
4328 }
4329 }
4330 }
4331 }
4332 return sequence;
4333}
4334
4335#if !defined(R__WIN32) && !defined(_AIX)
4336
4337#include <dlfcn.h>
4338
4339#endif
4340
4341typedef void (*voidfunc)();
4342static const char *R__GetSymbolName(voidfunc func)
4343{
4344#if defined(R__WIN32) || defined(__CYGWIN__) || defined(_AIX)
4345 return "not available on this platform";
4346#if 0
4347 MEMORY_BASIC_INFORMATION mbi;
4348 if (!VirtualQuery (func, &mbi, sizeof (mbi)))
4349 {
4350 return 0;
4351 }
4352
4353 HMODULE hMod = (HMODULE) mbi.AllocationBase;
4354 static char moduleName[MAX_PATH];
4355
4356 if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
4357 {
4358 return 0;
4359 }
4360 return moduleName;
4361#endif
4362#else
4363 Dl_info info;
4364 if (dladdr((void*)func,&info)==0) {
4365 // Not in a known share library, let's give up
4366 return "name not found";
4367 } else {
4368 //fprintf(stdout,"Found address in %s\n",info.dli_fname);
4369 return info.dli_sname;
4370 }
4371#endif
4372}
4373
4375{
4376 // Add the (potentially negative) delta to all the configuration's offset. This is used by
4377 // TTBranchElement in the case of split sub-object.
4378 // If opt contains 'func', also print the (mangled) name of the function that will be executed.
4379
4380 if (fLoopConfig) {
4381 fLoopConfig->Print();
4382 }
4383 TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
4384 for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
4385 iter != end;
4386 ++iter)
4387 {
4388 iter->fConfiguration->Print();
4389 if (strstr(opt,"func")) {
4390 printf("StreamerInfoAction func: %s\n",R__GetSymbolName((voidfunc)iter->fAction));
4391 }
4392 }
4393}
4394
4395
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
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:414
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:4469
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2239
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:5023
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4841
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5483
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition: TClass.cxx:5315
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2824
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:6809
@ 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:144
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)
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 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