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