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