Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TStreamerInfoWriteBuffer.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Rene Brun 12/10/2000
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 "TBuffer.h"
13#include "TClass.h"
14#include "TClonesArray.h"
15#include "TError.h"
16#include "TProcessID.h"
17#include "TStreamer.h"
18#include "TStreamerElement.h"
19#include "TStreamerInfo.h"
21#include "TRefTable.h"
22#include "TFile.h"
23
24#include "TVirtualArray.h"
25#include "TBufferFile.h"
26#include "TInterpreter.h"
27
28//==========CPP macros
29
30#define DOLOOP for(int k=0; k<narr; ++k)
31
32#define WriteBasicTypeElem(name,index) \
33 { \
34 name *x=(name*)(arr[index]+ioffset); \
35 b << *x; \
36 }
37
38#define WriteBasicType(name) \
39 { \
40 WriteBasicTypeElem(name,0); \
41 }
42
43#define WriteBasicTypeLoop(name) \
44 { \
45 for(int k=0; k<narr; ++k) WriteBasicTypeElem(name,k); \
46 }
47
48#define WriteBasicArrayElem(name,index) \
49 { \
50 name *x=(name*)(arr[index]+ioffset); \
51 b.WriteFastArray(x,compinfo[i]->fLength); \
52 }
53
54#define WriteBasicArray(name) \
55 { \
56 WriteBasicArrayElem(name,0); \
57 }
58
59#define WriteBasicArrayLoop(name) \
60 { \
61 for(int k=0; k<narr; ++k) WriteBasicArrayElem(name,k); \
62 }
63
64#define WriteBasicPointerElem(name,index) \
65 { \
66 Int_t *l = (Int_t*)(arr[index]+imethod); \
67 name **f = (name**)(arr[index]+ioffset); \
68 name *af = *f; \
69 if (af && *l) b << Char_t(1); \
70 else {b << Char_t(0); continue;} \
71 int j; \
72 for(j=0;j<compinfo[i]->fLength;j++) { \
73 b.WriteFastArray(f[j],*l); \
74 } \
75 }
76
77#define WriteBasicPointer(name) \
78 { \
79 int imethod = compinfo[i]->fMethod+eoffset; \
80 WriteBasicPointerElem(name,0); \
81 }
82
83#define WriteBasicPointerLoop(name) \
84 { \
85 int imethod = compinfo[i]->fMethod+eoffset; \
86 for(int k=0; k<narr; ++k) { \
87 WriteBasicPointerElem(name,k); \
88 } \
89 }
90
91// Helper function for TStreamerInfo::WriteBuffer
92namespace {
93 template <class T> Bool_t R__TestUseCache(TStreamerElement *element)
94 {
95 return element->TestBit(TStreamerElement::kCache);
96 }
97
98 template <> Bool_t R__TestUseCache<TVirtualArray>(TStreamerElement*)
99 {
100 // We are already using the cache, no need to recurse one more time.
101 return kFALSE;
102 }
103}
104
105////////////////////////////////////////////////////////////////////////////////
106/// The object at pointer is serialized to the buffer b
107/// if (arrayMode & 1) ptr is a pointer to array of pointers to the objects
108/// otherwise it is a pointer to a pointer to a single object.
109/// This also means that T is of a type such that arr[i] is a pointer to an
110/// object. Currently the only anticipated instantiation are for T==char**
111/// and T==TVirtualCollectionProxy
112
113template <class T>
115 TCompInfo *const*const compinfo, Int_t first, Int_t last,
116 Int_t narr, Int_t eoffset, Int_t arrayMode)
117{
118 Bool_t needIncrement = !( arrayMode & 2 );
119 arrayMode = arrayMode & (~2);
120
121 if (needIncrement) b.IncrementLevel(this);
122
123 //mark this class as being used in the current file
124 b.TagStreamerInfo(this);
125
126 //============
127
128 //loop on all active members
129// Int_t last;
130// if (first < 0) {first = 0; last = ninfo;}
131// else last = first+1;
132
133 // In order to speed up the case where the object being written is
134 // not in a collection (i.e. arrayMode is false), we actually
135 // duplicate the elementary types using this typeOffset.
136 static const int kHaveLoop = 1024;
137 const Int_t typeOffset = arrayMode ? kHaveLoop : 0;
138
139 for (Int_t i=first;i<last;i++) {
140
141 TStreamerElement *aElement = (TStreamerElement*)compinfo[i]->fElem;
142
143 if (needIncrement) b.SetStreamerElementNumber(aElement,compinfo[i]->fType);
144
145 Int_t ioffset = eoffset+compinfo[i]->fOffset;
146
147 if (R__TestUseCache<T>(aElement)) {
148 if (aElement->TestBit(TStreamerElement::kWrite)) {
149 if (((TBufferFile&)b).PeekDataCache()==0) {
150 Warning("WriteBuffer","Skipping %s::%s because the cache is missing.",GetName(),aElement->GetName());
151 } else {
152 if (gDebug > 1) {
153 printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d,"
154 " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
155 fClass->GetName(),aElement->GetName(),i,compinfo[i]->fType,
156 aElement->ClassName(),b.Length(),arr[0], eoffset,((TBufferFile&)b).PeekDataCache()->GetObjectAt(0));
157 }
158 WriteBufferAux(b,*((TBufferFile&)b).PeekDataCache(),compinfo,i,i+1,narr,eoffset, arrayMode);
159 }
160 continue;
161 } else {
162 if (gDebug > 1) {
163 printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d,"
164 " %s, bufpos=%d, arr=%p, eoffset=%d, not a write rule, skipping.\n",
165 fClass->GetName(),aElement->GetName(),i,compinfo[i]->fType,
166 aElement->ClassName(),b.Length(),arr[0], eoffset);
167 }
168 // The rule was a cached element for a read, rule, the real offset is in the
169 // next element (the one for the rule itself).
170 if (aElement->TestBit(TStreamerElement::kRepeat)) continue;
171 ioffset = eoffset+compinfo[i]->fOffset;
172 continue;
173 }
174 }
175
176 if (gDebug > 1) {
177 printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d, %s, "
178 "bufpos=%d, arr=%p, offset=%d\n",
179 fClass->GetName(),aElement->GetName(),i,compinfo[i]->fType,aElement->ClassName(),
180 b.Length(),arr[0],ioffset);
181 }
182
183 switch (compinfo[i]->fType+typeOffset) {
184 // In this switch we intentionally use 'continue' instead of
185 // 'break' to avoid running the 2nd switch (see later in this
186 // function).
187
202 Float_t *x=(Float_t*)(arr[0]+ioffset);
203 b.WriteFloat16(x,aElement);
204 continue;
205 }
207 Double_t *x=(Double_t*)(arr[0]+ioffset);
208 b.WriteDouble32(x,aElement);
209 continue;
210 }
211
212 case TStreamerInfo::kBool + kHaveLoop: WriteBasicTypeLoop(Bool_t); continue;
213 case TStreamerInfo::kChar + kHaveLoop: WriteBasicTypeLoop(Char_t); continue;
214 case TStreamerInfo::kShort + kHaveLoop: WriteBasicTypeLoop(Short_t); continue;
215 case TStreamerInfo::kInt + kHaveLoop: WriteBasicTypeLoop(Int_t); continue;
216 case TStreamerInfo::kLong + kHaveLoop: WriteBasicTypeLoop(Long_t); continue;
217 case TStreamerInfo::kLong64 + kHaveLoop: WriteBasicTypeLoop(Long64_t); continue;
218 case TStreamerInfo::kFloat + kHaveLoop: WriteBasicTypeLoop(Float_t); continue;
219 case TStreamerInfo::kDouble + kHaveLoop: WriteBasicTypeLoop(Double_t); continue;
220 case TStreamerInfo::kUChar + kHaveLoop: WriteBasicTypeLoop(UChar_t); continue;
221 case TStreamerInfo::kUShort + kHaveLoop: WriteBasicTypeLoop(UShort_t); continue;
222 case TStreamerInfo::kUInt + kHaveLoop: WriteBasicTypeLoop(UInt_t); continue;
223 case TStreamerInfo::kULong + kHaveLoop: WriteBasicTypeLoop(ULong_t); continue;
224 case TStreamerInfo::kULong64 + kHaveLoop: WriteBasicTypeLoop(ULong64_t); continue;
225 case TStreamerInfo::kFloat16+ kHaveLoop: {
226 for(int k=0; k<narr; ++k) {
227 Float_t *x=(Float_t*)(arr[k]+ioffset);
228 b.WriteFloat16(x,aElement);
229 }
230 continue;
231 }
232 case TStreamerInfo::kDouble32+ kHaveLoop: {
233 for(int k=0; k<narr; ++k) {
234 Double_t *x=(Double_t*)(arr[k]+ioffset);
235 b.WriteDouble32(x,aElement);
236 }
237 continue;
238 }
239
240 // write array of basic types array[8]
255 b.WriteFastArrayFloat16((Float_t*)(arr[0]+ioffset),compinfo[i]->fLength,aElement);
256 continue;
257 }
259 b.WriteFastArrayDouble32((Double_t*)(arr[0]+ioffset),compinfo[i]->fLength,aElement);
260 continue;
261 }
262
277 for(int k=0; k<narr; ++k) {
278 b.WriteFastArrayFloat16((Float_t*)(arr[k]+ioffset),compinfo[i]->fLength,aElement);
279 }
280 continue;
281 }
283 for(int k=0; k<narr; ++k) {
284 b.WriteFastArrayDouble32((Double_t*)(arr[k]+ioffset),compinfo[i]->fLength,aElement);
285 }
286 continue;
287 }
288
289 // write pointer to an array of basic types array[n]
304 int imethod = compinfo[i]->fMethod+eoffset;
305 Int_t *l = (Int_t*)(arr[0]+imethod);
306 Float_t **f = (Float_t**)(arr[0]+ioffset);
307 Float_t *af = *f;
308 if (af && *l) b << Char_t(1);
309 else {b << Char_t(0); continue;}
310 int j;
311 for(j=0;j<compinfo[i]->fLength;j++) {
312 b.WriteFastArrayFloat16(f[j],*l,aElement);
313 }
314 continue;
315 }
317 int imethod = compinfo[i]->fMethod+eoffset;
318 Int_t *l = (Int_t*)(arr[0]+imethod);
319 Double_t **f = (Double_t**)(arr[0]+ioffset);
320 Double_t *af = *f;
321 if (af && *l) b << Char_t(1);
322 else {b << Char_t(0); continue;}
323 int j;
324 for(j=0;j<compinfo[i]->fLength;j++) {
325 b.WriteFastArrayDouble32(f[j],*l,aElement);
326 }
327 continue;
328 }
329
344 int imethod = compinfo[i]->fMethod+eoffset;
345 for(int k=0; k<narr; ++k) {
346 Int_t *l = (Int_t*)(arr[k]+imethod);
347 Float_t **f = (Float_t**)(arr[k]+ioffset);
348 Float_t *af = *f;
349 if (af && *l) b << Char_t(1);
350 else {b << Char_t(0); continue;}
351 int j;
352 for(j=0;j<compinfo[i]->fLength;j++) {
353 b.WriteFastArrayFloat16(f[j],*l,aElement);
354 }
355 }
356 continue;
357 }
359 int imethod = compinfo[i]->fMethod+eoffset;
360 for(int k=0; k<narr; ++k) {
361 Int_t *l = (Int_t*)(arr[k]+imethod);
362 Double_t **f = (Double_t**)(arr[k]+ioffset);
363 Double_t *af = *f;
364 if (af && *l) b << Char_t(1);
365 else {b << Char_t(0); continue;}
366 int j;
367 for(j=0;j<compinfo[i]->fLength;j++) {
368 b.WriteFastArrayDouble32(f[j],*l,aElement);
369 }
370 }
371 continue;
372 }
373
375 Int_t *x=(Int_t*)(arr[0]+ioffset);
376 b << *x;
377 if (i == last-1) {
378 if (needIncrement) b.DecrementLevel(this);
379 return x[0]; // info used by TBranchElement::FillLeaves
380 }
381 continue;
382 }
383
384 case TStreamerInfo::kCounter + kHaveLoop : {
385 DOLOOP {
386 Int_t *x=(Int_t*)(arr[k]+ioffset);
387 b << x[0];
388 }
389 continue;
390 }
391
392
393 };
394 Bool_t isPreAlloc = 0;
395
396 switch (compinfo[i]->fType) {
397
398 // char*
400 char **f = (char**)(arr[k]+ioffset);
401 b.WriteCharStar(*f);
402 }
403 continue; }
404
405 // special case for TObject::fBits in case of a referenced object
407 UInt_t *x=(UInt_t*)(arr[k]+ioffset);
408 const auto parent = b.GetParent();
409 if (R__unlikely(parent && parent->TestBit(TFile::k630forwardCompatibility)))
410 b << *x;
411 else
412 b << (*x & (~kIsOnHeap & ~kNotDeleted));
413 if ((*x & kIsReferenced) != 0) {
414 TObject *obj = (TObject*)(arr[k]+eoffset);
417 if(table) table->Add(obj->GetUniqueID(),pid);
418 UShort_t pidf = b.WriteProcessID(pid);
419 b << pidf;
420 }
421 }
422 continue; }
423
424 // Special case for TString, TObject, TNamed
425 case TStreamerInfo::kTString: { DOLOOP{ ((TString*)(arr[k]+ioffset))->Streamer(b); }; continue; }
426 case TStreamerInfo::kTObject: { DOLOOP{ ((TObject*)(arr[k]+ioffset))->TObject::Streamer(b);}; continue; }
427 case TStreamerInfo::kTNamed: { DOLOOP{ ((TNamed *)(arr[k]+ioffset))->TNamed::Streamer(b); }; continue; }
428
429 case TStreamerInfo::kAnyp: // Class* Class not derived from TObject and with comment field //->
431
432 case TStreamerInfo::kObjectp: // Class * Class derived from TObject and with comment field //->
434
435 isPreAlloc = kTRUE;
436
437 // Intentional fallthrough now that isPreAlloc is set.
438 case TStreamerInfo::kAnyP: // Class* Class not derived from TObject and no comment
440
441 case TStreamerInfo::kObjectP: // Class* Class derived from TObject
443 TClass *cl = compinfo[i]->fClass;
444 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
445 DOLOOP {
446 Int_t res = b.WriteFastArray((void**)(arr[k]+ioffset),cl,compinfo[i]->fLength,isPreAlloc,pstreamer);
447 if (res==2) {
448 Warning("WriteBuffer",
449 "The actual class of %s::%s is not available. Only the \"%s\" part will be written\n",
450 GetName(),aElement->GetName(),cl->GetName());
451 }
452 }
453 continue;
454 }
455
456 case TStreamerInfo::kAnyPnoVT: // Class* Class not derived from TObject and no virtual table and no comment
458 TClass *cl = compinfo[i]->fClass;
459 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
460 DOLOOP {
461 void **f = (void**)(arr[k]+ioffset);
462 int j;
463 for(j=0;j<compinfo[i]->fLength;j++) {
464 void *af = f[j];
465 if (af) b << Char_t(1);
466 else {b << Char_t(0); continue;}
467 if (pstreamer) (*pstreamer)(b, af, 0);
468 else cl->Streamer( af, b );
469 }
470 }
471 continue;
472 }
473
474// case TStreamerInfo::kSTLvarp: // Variable size array of STL containers.
475// {
476// TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
477// TClass *cl = compinfo[i]->fClass;
478// UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
479// if (pstreamer == 0) {
480// Int_t size = cl->Size();
481// Int_t imethod = compinfo[i]->fMethod+eoffset;
482// DOLOOP {
483// char **contp = (char**)(arr[k]+ioffset);
484// const Int_t *counter = (Int_t*)(arr[k]+imethod);
485// const Int_t sublen = (*counter);
486
487// for(int j=0;j<compinfo[i]->fLength;++j) {
488// char *cont = contp[j];
489// for(int k=0;k<sublen;++k) {
490// cl->Streamer( cont, b );
491// cont += size;
492// }
493// }
494// }
495// } else {
496// DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
497// }
498// b.SetByteCount(pos,kTRUE);
499// }
500// continue;
501
502
503 case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
504 case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
505 {
506 TClass *cl = compinfo[i]->fClass;
507 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
509 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
510
512 && proxy && vClass
514 && cl->CanSplit()
515 && !(strspn(aElement->GetTitle(),"||") == 2)
516 && !(vClass->HasCustomStreamerMember()) ) {
517 // Let's save the collection member-wise.
518
519 UInt_t pos = b.WriteVersionMemberWise(this->IsA(),kTRUE);
520 b.WriteVersion( vClass, kFALSE );
521 DOLOOP {
522 char **contp = (char**)(arr[k]+ioffset);
523 for(int j=0;j<compinfo[i]->fLength;++j) {
524 char *cont = contp[j];
525 TVirtualCollectionProxy::TPushPop helper( proxy, cont );
526 Int_t nobjects = cont ? proxy->Size() : 0;
527 b << nobjects;
528 if (nobjects) {
529 auto actions = proxy->GetWriteMemberWiseActions();
530
533 void *begin = &(startbuf[0]);
534 void *end = &(endbuf[0]);
535 proxy->GetFunctionCreateIterators(/* read = */ kFALSE)(cont, &begin, &end, proxy);
536 // We can not get here with a split vector of pointer, so we can indeed assume
537 // that actions->fConfiguration != null.
538 b.ApplySequence(*actions, begin, end);
539
540 if (begin != &(startbuf[0])) {
541 // assert(end != endbuf);
542 proxy->GetFunctionDeleteTwoIterators()(begin,end);
543 }
544 }
545 }
546 }
547 b.SetByteCount(pos,kTRUE);
548 continue;
549 }
550 UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
551 if (pstreamer == 0) {
552 DOLOOP {
553 char **contp = (char**)(arr[k]+ioffset);
554 for(int j=0;j<compinfo[i]->fLength;++j) {
555 char *cont = contp[j];
556 cl->Streamer( cont, b );
557 }
558 }
559 } else {
560 DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
561 }
562 b.SetByteCount(pos,kTRUE);
563 }
564 continue;
565
566 case TStreamerInfo::kSTL: // container with no virtual table (stl) and no comment
567 case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL: // array of containers with no virtual table (stl) and no comment
568 {
569 TClass *cl = compinfo[i]->fClass;
570 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
572 TClass* vClass = proxy ? proxy->GetValueClass() : 0;
574 && proxy && vClass
575 && GetStreamMemberWise() && cl->CanSplit()
576 && !(strspn(aElement->GetTitle(),"||") == 2)
577 && !(vClass->HasCustomStreamerMember()) ) {
578 // Let's save the collection in member-wise order.
579
580 UInt_t pos = b.WriteVersionMemberWise(this->IsA(),kTRUE);
581 b.WriteVersion( vClass, kFALSE );
582 DOLOOP {
583 char *obj = (char*)(arr[k]+ioffset);
584 Int_t n = compinfo[i]->fLength;
585 if (!n) n=1;
586 int size = cl->Size();
587
588 for(Int_t j=0; j<n; j++,obj+=size) {
589 TVirtualCollectionProxy::TPushPop helper( proxy, obj );
590 Int_t nobjects = proxy->Size();
591 b << nobjects;
592 if (nobjects) {
593 auto actions = proxy->GetWriteMemberWiseActions();
594
597 void *begin = &(startbuf[0]);
598 void *end = &(endbuf[0]);
599 proxy->GetFunctionCreateIterators(/*read = */ kFALSE)(obj, &begin, &end, proxy);
600 // We can not get here with a split vector of pointer, so we can indeed assume
601 // that actions->fConfiguration != null.
602 b.ApplySequence(*actions, begin, end);
603 if (begin != &(startbuf[0])) {
604 // assert(end != endbuf);
605 proxy->GetFunctionDeleteTwoIterators()(begin,end);
606 }
607 }
608 }
609 }
610 b.SetByteCount(pos,kTRUE);
611 continue;
612 }
613 UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
614 if (pstreamer == 0) {
615 DOLOOP {
616 b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,0);
617 }
618 } else {
619 DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
620 }
621 b.SetByteCount(pos,kTRUE);
622
623 continue;
624 }
625
626 case TStreamerInfo::kObject: // Class derived from TObject
627 case TStreamerInfo::kAny: // Class NOT derived from TObject
630 TClass *cl = compinfo[i]->fClass;
631 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
632 DOLOOP
633 {b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,pstreamer);}
634 continue;
635 }
636
640 {
641 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
642 TClass *cl = compinfo[i]->fClass;
643
644 UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
645 DOLOOP {b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,pstreamer);}
646 b.SetByteCount(pos,kTRUE);
647 continue;
648 }
649
650 // Base Class
652 if (!(arrayMode&1)) {
653 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
654 if(pstreamer) {
655 // See kStreamer case (similar code)
656 UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
657 DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
658 b.SetByteCount(pos,kTRUE);
659 } else {
660 DOLOOP { ((TStreamerBase*)aElement)->WriteBuffer(b,arr[k]);}
661 }
662 } else {
663 TClass *cl = compinfo[i]->fClass;
665 binfo->WriteBufferAux(b,arr,binfo->fCompFull,0,binfo->fNfulldata,narr,ioffset,arrayMode);
666 }
667 continue;
668
670 {
671 TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
672
673 UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
674 if (pstreamer == 0) {
675 printf("ERROR, Streamer is null\n");
676 aElement->ls();continue;
677 } else {
678 DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
679 }
680 b.SetByteCount(pos,kTRUE);
681 }
682 continue;
683
685 // -- A pointer to a varying-length array of objects.
686 // MyClass* ary; //[n]
687 // -- Or a pointer to a varying-length array of pointers to objects.
688 // MyClass** ary; //[n]
690 // -- An array of pointers to a varying-length array of objects.
691 // MyClass* ary[d]; //[n]
692 // -- Or an array of pointers to a varying-length array of pointers to objects.
693 // MyClass** ary[d]; //[n]
694 {
695 // Get the class of the data member.
696 TClass* cl = compinfo[i]->fClass;
697 // Get any private streamer which was set for the data member.
698 TMemberStreamer* pstreamer = compinfo[i]->fStreamer;
699 // Which are we, an array of objects or an array of pointers to objects?
700 Bool_t isPtrPtr = (strstr(aElement->GetTypeName(), "**") != 0);
701 if (pstreamer) {
702 // -- We have a private streamer.
703 UInt_t pos = b.WriteVersion(this->IsA(), kTRUE);
704 // Loop over the entries in the clones array or the STL container.
705 for (int k = 0; k < narr; ++k) {
706 // Get a pointer to the counter for the varying length array.
707 Int_t* counter = (Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/);
708 // And call the private streamer, passing it the buffer, the object, and the counter.
709 (*pstreamer)(b, arr[k] /*entry pointer*/ + ioffset /*object offset*/, *counter);
710 }
711 b.SetByteCount(pos, kTRUE);
712 // We are done, next streamer element.
713 continue;
714 }
715 // At this point we do *not* have a private streamer.
716 // Get the version of the file we are writing to.
717 TFile* file = (TFile*) b.GetParent();
718 // By default assume the file version is the newest.
719 Int_t fileVersion = kMaxInt;
720 if (file) {
721 fileVersion = file->GetVersion();
722 }
723 // Write the class version to the buffer.
724 UInt_t pos = b.WriteVersion(this->IsA(), kTRUE);
725 if (fileVersion > 51508) {
726 // -- Newer versions allow polymorphic pointers to objects.
727 // Loop over the entries in the clones array or the STL container.
728 for (int k = 0; k < narr; ++k) {
729 // Get the counter for the varying length array.
730 Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
731 //b << vlen;
732 if (vlen) {
733 // Get a pointer to the array of pointers.
734 char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
735 // Loop over each element of the array of pointers to varying-length arrays.
736 for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
737 if (!pp[ndx]) {
738 // -- We do not have a pointer to a varying-length array.
739 Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
740 continue;
741 }
742 if (!isPtrPtr) {
743 // -- We are a varying-length array of objects.
744 // Write the entire array of objects to the buffer.
745 // Note: Polymorphism is not allowed here.
746 b.WriteFastArray(pp[ndx], cl, vlen, 0);
747 }
748 else {
749 // -- We are a varying-length array of pointers to objects.
750 // Write the entire array of object pointers to the buffer.
751 // Note: The object pointers are allowed to be polymorphic.
752 b.WriteFastArray((void**) pp[ndx], cl, vlen, kFALSE, 0);
753 } // isPtrPtr
754 } // ndx
755 } // vlen
756 } // k
757 }
758 else {
759 // -- Older versions do *not* allow polymorphic pointers to objects.
760 // Loop over the entries in the clones array or the STL container.
761 for (int k = 0; k < narr; ++k) {
762 // Get the counter for the varying length array.
763 Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
764 //b << vlen;
765 if (vlen) {
766 // Get a pointer to the array of pointers.
767 char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
768 // -- Older versions do *not* allow polymorphic pointers to objects.
769 // Loop over each element of the array of pointers to varying-length arrays.
770 for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
771 if (!pp[ndx]) {
772 // -- We do not have a pointer to a varying-length array.
773 Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
774 continue;
775 }
776 if (!isPtrPtr) {
777 // -- We are a varying-length array of objects.
778 // Loop over the elements of the varying length array.
779 for (Int_t v = 0; v < vlen; ++v) {
780 // Write the object to the buffer.
781 cl->Streamer(pp[ndx] + (v * cl->Size()), b);
782 } // v
783 }
784 else {
785 // -- We are a varying-length array of pointers to objects.
786 // Loop over the elements of the varying length array.
787 for (Int_t v = 0; v < vlen; ++v) {
788 // Get a pointer to the object pointer.
789 char** r = (char**) pp[ndx];
790 // Write the object to the buffer.
791 cl->Streamer(r[v], b);
792 } // v
793 } // isPtrPtr
794 } // ndx
795 } // vlen
796 } // k
797 } // fileVersion
798 // Backpatch the byte count into the buffer.
799 b.SetByteCount(pos, kTRUE);
800 continue;
801 }
802
804 ((TBufferFile&)b).PushDataCache( new TVirtualArray( aElement->GetClassPointer(), narr ) );
805 continue;
807 delete ((TBufferFile&)b).PopDataCache();
808 continue;
810#if 0
811 ROOT::TSchemaRule::WriteFuncPtr_t writefunc = ((TStreamerArtificial*)aElement)->GetWriteFunc();
812 if (writefunc) {
813 DOLOOP( writefunc(arr[k]+eoffset, b) );
814 }
815#endif
816 continue;
817 case -1:
818 // -- Skip an ignored TObject base class.
819 continue;
820 default:
821 Error("WriteBuffer","The element %s::%s type %d (%s) is not supported yet\n",GetName(),aElement->GetFullName(),compinfo[i]->fType,aElement->GetTypeName());
822 continue;
823 }
824 }
825
826 if (needIncrement) b.DecrementLevel(this);
827
828 return 0;
829}
830
831template Int_t TStreamerInfo::WriteBufferAux<char**>(TBuffer &b, char ** const &arr, TCompInfo *const*const compinfo, Int_t first, Int_t last, Int_t narr,Int_t eoffset,Int_t mode);
832
833////////////////////////////////////////////////////////////////////////////////
834/// Write for STL container. ('first' is an id between -1 and fNfulldata).
835
837{
838 if (!nc) return 0;
839 R__ASSERT((unsigned int)nc==cont->Size());
840
841
842 int ret = WriteBufferAux(b,*cont,fCompFull,0,fNfulldata,nc,/* eoffset = */ 0,1);
843 return ret;
844}
845
846////////////////////////////////////////////////////////////////////////////////
847/// Write for STL container. ('first' is an id between -1 and fNfulldata).
848/// Note: This is no longer used.
849
851{
852 if (!nc) return 0;
853 R__ASSERT((unsigned int)nc==cont->Size());
854 int ret = WriteBufferAux(b, TPointerCollectionAdapter(cont),fCompFull,first==-1?0:first,first==-1?fNfulldata:first+1,nc,eoffset,1);
855 return ret;
856}
857
858
859////////////////////////////////////////////////////////////////////////////////
860/// General Write. ('first' is an id between -1 and fNdata).
861/// Note: This is no longer used.
862
864{
865 return WriteBufferAux(b,&ipointer,fCompOpt,first==-1?0:first,first==-1?fNdata:first+1,1,0,0);
866}
867
868////////////////////////////////////////////////////////////////////////////////
869/// Write for ClonesArray ('first' is an id between -1 and fNfulldata).
870/// Note: This is no longer used.
871
873 Int_t nc, Int_t first, Int_t eoffset)
874{
875 char **arr = reinterpret_cast<char**>(clones->GetObjectRef(0));
876 return WriteBufferAux(b,arr,fCompFull,first==-1?0:first,first==-1?fNfulldata:first+1,nc,eoffset,1);
877}
878
879
#define R__unlikely(expr)
Definition RConfig.hxx:578
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
constexpr Int_t kMaxInt
Definition RtypesCore.h:112
unsigned char UChar_t
Definition RtypesCore.h:38
char Char_t
Definition RtypesCore.h:37
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
unsigned long long ULong64_t
Definition RtypesCore.h:81
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define DOLOOP(x)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char mode
Int_t gDebug
Definition TROOT.cxx:597
#define WriteBasicArray(name)
#define WriteBasicPointer(name)
#define WriteBasicPointerLoop(name)
#define WriteBasicArrayLoop(name)
#define WriteBasicTypeLoop(name)
#define WriteBasicType(name)
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
Buffer base class used for serializing objects.
Definition TBuffer.h:43
@ kCannotHandleMemberWiseStreaming
Definition TBuffer.h:76
virtual void WriteFastArray(const Bool_t *b, Long64_t n)=0
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:607
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2319
Bool_t HasCustomStreamerMember() const
The class has a Streamer method and it is implemented by the user or an older (not StreamerInfo based...
Definition TClass.h:508
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5704
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4599
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2897
An array of clone (identical) objects.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
Int_t GetVersion() const
Definition TFile.h:245
@ k630forwardCompatibility
Definition TFile.h:190
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
void Streamer(TBuffer &) override
Stream an object of class TObject.
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TObject ** GetObjectRef() const
Definition TObjArray.h:63
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:456
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:888
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:65
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition TRefTable.h:35
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
virtual Int_t Add(Int_t uid, TProcessID *context=nullptr)
Add a new uid to the table.
Definition TRefTable.cxx:88
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
void ls(Option_t *option="") const override
Print the content of the element.
const char * GetTypeName() const
TClass * fClass
Not Owned.
TMemberStreamer * fStreamer
Not Owned.
Describes a persistent version of a class.
Int_t fNfulldata
!number of elements
Int_t WriteBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc)
Write for STL container. ('first' is an id between -1 and fNfulldata).
TCompInfo ** fCompFull
![fElements->GetEntries()]
@ kArtificial
Cache the value in memory than is not part of the object but is accessible via a SchemaRule.
@ kUChar
Equal to TDataType's kchar.
Int_t fNdata
!number of optimized elements
TClass * IsA() const override
TClass * fClass
!pointer to class
TCompInfo ** fCompOpt
![fNdata]
void Streamer(TBuffer &) override
Stream an object of class TStreamerInfo.
Int_t WriteBuffer(TBuffer &b, char *pointer, Int_t first)
General Write.
Int_t WriteBufferClones(TBuffer &b, TClonesArray *clones, Int_t nc, Int_t first, Int_t eoffset)
Write for ClonesArray ('first' is an id between -1 and fNfulldata).
Int_t WriteBufferAux(TBuffer &b, const T &arr, TCompInfo *const *const compinfo, Int_t first, Int_t last, Int_t narr, Int_t eoffset, Int_t mode)
The object at pointer is serialized to the buffer b if (arrayMode & 1) ptr is a pointer to array of p...
Int_t WriteBufferSTLPtrs(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t first, Int_t eoffset)
Write for STL container.
Basic string class.
Definition TString.h:139
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()=0
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual UInt_t Size() const =0
Return the current number of elements in the container.
static const Int_t fgIteratorArenaSize
The size of a small buffer that can be allocated on the stack to store iterator-specific information.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Return a pointer to a function that can create an iterator pair, where each iterator points to the be...
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible.
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TLine l
Definition textangle.C:4