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