Logo ROOT  
Reference Guide
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
92 namespace {
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 
113 template <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 
188  case TStreamerInfo::kBool: WriteBasicType(Bool_t); continue;
189  case TStreamerInfo::kChar: WriteBasicType(Char_t); continue;
191  case TStreamerInfo::kInt: WriteBasicType(Int_t); continue;
192  case TStreamerInfo::kLong: WriteBasicType(Long_t); continue;
198  case TStreamerInfo::kUInt: WriteBasicType(UInt_t); continue;
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
406  case TStreamerInfo::kBits: { DOLOOP {
407  UInt_t *x=(UInt_t*)(arr[k]+ioffset); b << *x;
408  if ((*x & kIsReferenced) != 0) {
409  TObject *obj = (TObject*)(arr[k]+eoffset);
412  if(table) table->Add(obj->GetUniqueID(),pid);
413  UShort_t pidf = b.WriteProcessID(pid);
414  b << pidf;
415  }
416  }
417  continue; }
418 
419  // Special case for TString, TObject, TNamed
420  case TStreamerInfo::kTString: { DOLOOP{ ((TString*)(arr[k]+ioffset))->Streamer(b); }; continue; }
421  case TStreamerInfo::kTObject: { DOLOOP{ ((TObject*)(arr[k]+ioffset))->TObject::Streamer(b);}; continue; }
422  case TStreamerInfo::kTNamed: { DOLOOP{ ((TNamed *)(arr[k]+ioffset))->TNamed::Streamer(b); }; continue; }
423 
424  case TStreamerInfo::kAnyp: // Class* Class not derived from TObject and with comment field //->
426 
427  case TStreamerInfo::kObjectp: // Class * Class derived from TObject and with comment field //->
429 
430  isPreAlloc = kTRUE;
431 
432  // Intentional fallthrough now that isPreAlloc is set.
433  case TStreamerInfo::kAnyP: // Class* Class not derived from TObject and no comment
435 
436  case TStreamerInfo::kObjectP: // Class* Class derived from TObject
438  TClass *cl = compinfo[i]->fClass;
439  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
440  DOLOOP {
441  Int_t res = b.WriteFastArray((void**)(arr[k]+ioffset),cl,compinfo[i]->fLength,isPreAlloc,pstreamer);
442  if (res==2) {
443  Warning("WriteBuffer",
444  "The actual class of %s::%s is not available. Only the \"%s\" part will be written\n",
445  GetName(),aElement->GetName(),cl->GetName());
446  }
447  }
448  continue;
449  }
450 
451  case TStreamerInfo::kAnyPnoVT: // Class* Class not derived from TObject and no virtual table and no comment
453  TClass *cl = compinfo[i]->fClass;
454  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
455  DOLOOP {
456  void **f = (void**)(arr[k]+ioffset);
457  int j;
458  for(j=0;j<compinfo[i]->fLength;j++) {
459  void *af = f[j];
460  if (af) b << Char_t(1);
461  else {b << Char_t(0); continue;}
462  if (pstreamer) (*pstreamer)(b, af, 0);
463  else cl->Streamer( af, b );
464  }
465  }
466  continue;
467  }
468 
469 // case TStreamerInfo::kSTLvarp: // Variable size array of STL containers.
470 // {
471 // TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
472 // TClass *cl = compinfo[i]->fClass;
473 // UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
474 // if (pstreamer == 0) {
475 // Int_t size = cl->Size();
476 // Int_t imethod = compinfo[i]->fMethod+eoffset;
477 // DOLOOP {
478 // char **contp = (char**)(arr[k]+ioffset);
479 // const Int_t *counter = (Int_t*)(arr[k]+imethod);
480 // const Int_t sublen = (*counter);
481 
482 // for(int j=0;j<compinfo[i]->fLength;++j) {
483 // char *cont = contp[j];
484 // for(int k=0;k<sublen;++k) {
485 // cl->Streamer( cont, b );
486 // cont += size;
487 // }
488 // }
489 // }
490 // } else {
491 // DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
492 // }
493 // b.SetByteCount(pos,kTRUE);
494 // }
495 // continue;
496 
497 
498  case TStreamerInfo::kSTLp: // Pointer to container with no virtual table (stl) and no comment
499  case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL: // array of pointers to container with no virtual table (stl) and no comment
500  {
501  TClass *cl = compinfo[i]->fClass;
502  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
504  TClass* vClass = proxy ? proxy->GetValueClass() : 0;
505 
507  && proxy && vClass
509  && cl->CanSplit()
510  && !(strspn(aElement->GetTitle(),"||") == 2)
511  && !(vClass->TestBit(TClass::kHasCustomStreamerMember)) ) {
512  // Let's save the collection member-wise.
513 
514  UInt_t pos = b.WriteVersionMemberWise(this->IsA(),kTRUE);
515  b.WriteVersion( vClass, kFALSE );
516  DOLOOP {
517  char **contp = (char**)(arr[k]+ioffset);
518  for(int j=0;j<compinfo[i]->fLength;++j) {
519  char *cont = contp[j];
520  TVirtualCollectionProxy::TPushPop helper( proxy, cont );
521  Int_t nobjects = cont ? proxy->Size() : 0;
522  b << nobjects;
523  if (nobjects) {
524  auto actions = proxy->GetWriteMemberWiseActions();
525 
528  void *begin = &(startbuf[0]);
529  void *end = &(endbuf[0]);
530  proxy->GetFunctionCreateIterators(/* read = */ kFALSE)(cont, &begin, &end, proxy);
531  // We can not get here with a split vector of pointer, so we can indeed assume
532  // that actions->fConfiguration != null.
533  b.ApplySequence(*actions, begin, end);
534 
535  if (begin != &(startbuf[0])) {
536  // assert(end != endbuf);
537  proxy->GetFunctionDeleteTwoIterators()(begin,end);
538  }
539  }
540  }
541  }
542  b.SetByteCount(pos,kTRUE);
543  continue;
544  }
545  UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
546  if (pstreamer == 0) {
547  DOLOOP {
548  char **contp = (char**)(arr[k]+ioffset);
549  for(int j=0;j<compinfo[i]->fLength;++j) {
550  char *cont = contp[j];
551  cl->Streamer( cont, b );
552  }
553  }
554  } else {
555  DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
556  }
557  b.SetByteCount(pos,kTRUE);
558  }
559  continue;
560 
561  case TStreamerInfo::kSTL: // container with no virtual table (stl) and no comment
562  case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL: // array of containers with no virtual table (stl) and no comment
563  {
564  TClass *cl = compinfo[i]->fClass;
565  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
567  TClass* vClass = proxy ? proxy->GetValueClass() : 0;
569  && proxy && vClass
570  && GetStreamMemberWise() && cl->CanSplit()
571  && !(strspn(aElement->GetTitle(),"||") == 2)
572  && !(vClass->TestBit(TClass::kHasCustomStreamerMember)) ) {
573  // Let's save the collection in member-wise order.
574 
575  UInt_t pos = b.WriteVersionMemberWise(this->IsA(),kTRUE);
576  b.WriteVersion( vClass, kFALSE );
577  DOLOOP {
578  char *obj = (char*)(arr[k]+ioffset);
579  Int_t n = compinfo[i]->fLength;
580  if (!n) n=1;
581  int size = cl->Size();
582 
583  for(Int_t j=0; j<n; j++,obj+=size) {
584  TVirtualCollectionProxy::TPushPop helper( proxy, obj );
585  Int_t nobjects = proxy->Size();
586  b << nobjects;
587  if (nobjects) {
588  auto actions = proxy->GetWriteMemberWiseActions();
589 
592  void *begin = &(startbuf[0]);
593  void *end = &(endbuf[0]);
594  proxy->GetFunctionCreateIterators(/*read = */ kFALSE)(obj, &begin, &end, proxy);
595  // We can not get here with a split vector of pointer, so we can indeed assume
596  // that actions->fConfiguration != null.
597  b.ApplySequence(*actions, begin, end);
598  if (begin != &(startbuf[0])) {
599  // assert(end != endbuf);
600  proxy->GetFunctionDeleteTwoIterators()(begin,end);
601  }
602  }
603  }
604  }
605  b.SetByteCount(pos,kTRUE);
606  continue;
607  }
608  UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
609  if (pstreamer == 0) {
610  DOLOOP {
611  b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,0);
612  }
613  } else {
614  DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
615  }
616  b.SetByteCount(pos,kTRUE);
617 
618  continue;
619  }
620 
621  case TStreamerInfo::kObject: // Class derived from TObject
622  case TStreamerInfo::kAny: // Class NOT derived from TObject
625  TClass *cl = compinfo[i]->fClass;
626  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
627  DOLOOP
628  {b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,pstreamer);}
629  continue;
630  }
631 
635  {
636  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
637  TClass *cl = compinfo[i]->fClass;
638 
639  UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
640  DOLOOP {b.WriteFastArray((void*)(arr[k]+ioffset),cl,compinfo[i]->fLength,pstreamer);}
641  b.SetByteCount(pos,kTRUE);
642  continue;
643  }
644 
645  // Base Class
647  if (!(arrayMode&1)) {
648  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
649  if(pstreamer) {
650  // See kStreamer case (similar code)
651  UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
652  DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
653  b.SetByteCount(pos,kTRUE);
654  } else {
655  DOLOOP { ((TStreamerBase*)aElement)->WriteBuffer(b,arr[k]);}
656  }
657  } else {
658  TClass *cl = compinfo[i]->fClass;
659  TStreamerInfo *binfo = ((TStreamerInfo*)cl->GetStreamerInfo());
660  binfo->WriteBufferAux(b,arr,binfo->fCompFull,0,binfo->fNfulldata,narr,ioffset,arrayMode);
661  }
662  continue;
663 
665  {
666  TMemberStreamer *pstreamer = compinfo[i]->fStreamer;
667 
668  UInt_t pos = b.WriteVersion(this->IsA(),kTRUE);
669  if (pstreamer == 0) {
670  printf("ERROR, Streamer is null\n");
671  aElement->ls();continue;
672  } else {
673  DOLOOP{(*pstreamer)(b,arr[k]+ioffset,compinfo[i]->fLength);}
674  }
675  b.SetByteCount(pos,kTRUE);
676  }
677  continue;
678 
680  // -- A pointer to a varying-length array of objects.
681  // MyClass* ary; //[n]
682  // -- Or a pointer to a varying-length array of pointers to objects.
683  // MyClass** ary; //[n]
685  // -- An array of pointers to a varying-length array of objects.
686  // MyClass* ary[d]; //[n]
687  // -- Or an array of pointers to a varying-length array of pointers to objects.
688  // MyClass** ary[d]; //[n]
689  {
690  // Get the class of the data member.
691  TClass* cl = compinfo[i]->fClass;
692  // Get any private streamer which was set for the data member.
693  TMemberStreamer* pstreamer = compinfo[i]->fStreamer;
694  // Which are we, an array of objects or an array of pointers to objects?
695  Bool_t isPtrPtr = (strstr(aElement->GetTypeName(), "**") != 0);
696  if (pstreamer) {
697  // -- We have a private streamer.
698  UInt_t pos = b.WriteVersion(this->IsA(), kTRUE);
699  // Loop over the entries in the clones array or the STL container.
700  for (int k = 0; k < narr; ++k) {
701  // Get a pointer to the counter for the varying length array.
702  Int_t* counter = (Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/);
703  // And call the private streamer, passing it the buffer, the object, and the counter.
704  (*pstreamer)(b, arr[k] /*entry pointer*/ + ioffset /*object offset*/, *counter);
705  }
706  b.SetByteCount(pos, kTRUE);
707  // We are done, next streamer element.
708  continue;
709  }
710  // At this point we do *not* have a private streamer.
711  // Get the version of the file we are writing to.
712  TFile* file = (TFile*) b.GetParent();
713  // By default assume the file version is the newest.
714  Int_t fileVersion = kMaxInt;
715  if (file) {
716  fileVersion = file->GetVersion();
717  }
718  // Write the class version to the buffer.
719  UInt_t pos = b.WriteVersion(this->IsA(), kTRUE);
720  if (fileVersion > 51508) {
721  // -- Newer versions allow polymorphic pointers to objects.
722  // Loop over the entries in the clones array or the STL container.
723  for (int k = 0; k < narr; ++k) {
724  // Get the counter for the varying length array.
725  Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
726  //b << vlen;
727  if (vlen) {
728  // Get a pointer to the array of pointers.
729  char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
730  // Loop over each element of the array of pointers to varying-length arrays.
731  for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
732  if (!pp[ndx]) {
733  // -- We do not have a pointer to a varying-length array.
734  Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
735  continue;
736  }
737  if (!isPtrPtr) {
738  // -- We are a varying-length array of objects.
739  // Write the entire array of objects to the buffer.
740  // Note: Polymorphism is not allowed here.
741  b.WriteFastArray(pp[ndx], cl, vlen, 0);
742  }
743  else {
744  // -- We are a varying-length array of pointers to objects.
745  // Write the entire array of object pointers to the buffer.
746  // Note: The object pointers are allowed to be polymorphic.
747  b.WriteFastArray((void**) pp[ndx], cl, vlen, kFALSE, 0);
748  } // isPtrPtr
749  } // ndx
750  } // vlen
751  } // k
752  }
753  else {
754  // -- Older versions do *not* allow polymorphic pointers to objects.
755  // Loop over the entries in the clones array or the STL container.
756  for (int k = 0; k < narr; ++k) {
757  // Get the counter for the varying length array.
758  Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + compinfo[i]->fMethod /*counter offset*/));
759  //b << vlen;
760  if (vlen) {
761  // Get a pointer to the array of pointers.
762  char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
763  // -- Older versions do *not* allow polymorphic pointers to objects.
764  // Loop over each element of the array of pointers to varying-length arrays.
765  for (Int_t ndx = 0; ndx < compinfo[i]->fLength; ++ndx) {
766  if (!pp[ndx]) {
767  // -- We do not have a pointer to a varying-length array.
768  Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", GetName(), aElement->GetFullName(), compinfo[i]->fType, aElement->GetTypeName());
769  continue;
770  }
771  if (!isPtrPtr) {
772  // -- We are a varying-length array of objects.
773  // Loop over the elements of the varying length array.
774  for (Int_t v = 0; v < vlen; ++v) {
775  // Write the object to the buffer.
776  cl->Streamer(pp[ndx] + (v * cl->Size()), b);
777  } // v
778  }
779  else {
780  // -- We are a varying-length array of pointers to objects.
781  // Loop over the elements of the varying length array.
782  for (Int_t v = 0; v < vlen; ++v) {
783  // Get a pointer to the object pointer.
784  char** r = (char**) pp[ndx];
785  // Write the object to the buffer.
786  cl->Streamer(r[v], b);
787  } // v
788  } // isPtrPtr
789  } // ndx
790  } // vlen
791  } // k
792  } // fileVersion
793  // Backpatch the byte count into the buffer.
794  b.SetByteCount(pos, kTRUE);
795  continue;
796  }
797 
799  ((TBufferFile&)b).PushDataCache( new TVirtualArray( aElement->GetClassPointer(), narr ) );
800  continue;
802  delete ((TBufferFile&)b).PopDataCache();
803  continue;
805 #if 0
806  ROOT::TSchemaRule::WriteFuncPtr_t writefunc = ((TStreamerArtificial*)aElement)->GetWriteFunc();
807  if (writefunc) {
808  DOLOOP( writefunc(arr[k]+eoffset, b) );
809  }
810 #endif
811  continue;
812  case -1:
813  // -- Skip an ignored TObject base class.
814  continue;
815  default:
816  Error("WriteBuffer","The element %s::%s type %d (%s) is not supported yet\n",GetName(),aElement->GetFullName(),compinfo[i]->fType,aElement->GetTypeName());
817  continue;
818  }
819  }
820 
821  if (needIncrement) b.DecrementLevel(this);
822 
823  return 0;
824 }
825 
826 template 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);
827 
828 ////////////////////////////////////////////////////////////////////////////////
829 /// Write for STL container. ('first' is an id between -1 and fNfulldata).
830 
832 {
833  if (!nc) return 0;
834  R__ASSERT((unsigned int)nc==cont->Size());
835 
836 
837  int ret = WriteBufferAux(b,*cont,fCompFull,0,fNfulldata,nc,/* eoffset = */ 0,1);
838  return ret;
839 }
840 
841 ////////////////////////////////////////////////////////////////////////////////
842 /// Write for STL container. ('first' is an id between -1 and fNfulldata).
843 /// Note: This is no longer used.
844 
846 {
847  if (!nc) return 0;
848  R__ASSERT((unsigned int)nc==cont->Size());
849  int ret = WriteBufferAux(b, TPointerCollectionAdapter(cont),fCompFull,first==-1?0:first,first==-1?fNfulldata:first+1,nc,eoffset,1);
850  return ret;
851 }
852 
853 
854 ////////////////////////////////////////////////////////////////////////////////
855 /// General Write. ('first' is an id between -1 and fNdata).
856 /// Note: This is no longer used.
857 
859 {
860  return WriteBufferAux(b,&ipointer,fCompOpt,first==-1?0:first,first==-1?fNdata:first+1,1,0,0);
861 }
862 
863 ////////////////////////////////////////////////////////////////////////////////
864 /// Write for ClonesArray ('first' is an id between -1 and fNfulldata).
865 /// Note: This is no longer used.
866 
868  Int_t nc, Int_t first, Int_t eoffset)
869 {
870  char **arr = reinterpret_cast<char**>(clones->GetObjectRef(0));
871  return WriteBufferAux(b,arr,fCompFull,first==-1?0:first,first==-1?fNfulldata:first+1,nc,eoffset,1);
872 }
873 
874 
TVirtualStreamerInfo::GetStreamMemberWise
static Bool_t GetStreamMemberWise()
Return whether the TStreamerInfos will save the collections in "member-wise" order whenever possible.
Definition: TVirtualStreamerInfo.cxx:155
l
auto * l
Definition: textangle.C:4
TStreamerInfo::kFloat16
@ kFloat16
Definition: TStreamerInfo.h:171
n
const Int_t n
Definition: legend1.C:16
first
Definition: first.py:1
TVirtualCollectionProxy.h
TClass::GetCollectionProxy
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2875
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
TStreamerElement::ls
virtual void ls(Option_t *option="") const
Print the content of the element.
Definition: TStreamerElement.cxx:456
TClass::Streamer
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:602
f
#define f(i)
Definition: RSha256.hxx:104
TStreamerInfo::fNdata
Int_t fNdata
!number of optimized elements
Definition: TStreamerInfo.h:98
TStreamerElement::GetTypeName
const char * GetTypeName() const
Definition: TStreamerElement.h:123
TStreamerInfo.h
TClass::Size
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5688
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:40
TStreamerInfo::kLong
@ kLong
Definition: TStreamerInfo.h:167
TStreamerInfo::kULong64
@ kULong64
Definition: TStreamerInfo.h:171
TStreamerInfo::kDouble
@ kDouble
Definition: TStreamerInfo.h:168
TStreamerInfo::kStreamer
@ kStreamer
Definition: TStreamerInfo.h:178
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
DOLOOP
#define DOLOOP
Definition: TStreamerInfoWriteBuffer.cxx:30
TStreamerElement::kCache
@ kCache
Definition: TStreamerElement.h:78
TStreamerInfo::kULong
@ kULong
Definition: TStreamerInfo.h:170
TStreamerElement.h
r
ROOT::R::TRInterface & r
Definition: Object.C:4
TRefTable::Add
virtual Int_t Add(Int_t uid, TProcessID *context=0)
Add a new uid to the table.
Definition: TRefTable.cxx:88
Long64_t
long long Long64_t
Definition: RtypesCore.h:80
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
TStreamerInfo::WriteBufferSTLPtrs
Int_t WriteBufferSTLPtrs(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t first, Int_t eoffset)
Write for STL container.
Definition: TStreamerInfoWriteBuffer.cxx:845
TStreamerInfo::kOffsetL
@ kOffsetL
Definition: TStreamerInfo.h:166
TStreamerInfo::kBool
@ kBool
Definition: TStreamerInfo.h:171
TStreamerInfo::fCompOpt
TCompInfo ** fCompOpt
![fNdata]
Definition: TStreamerInfo.h:102
Float_t
float Float_t
Definition: RtypesCore.h:57
TBuffer::kCannotHandleMemberWiseStreaming
@ kCannotHandleMemberWiseStreaming
Definition: TBuffer.h:76
TProcessID
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:74
WriteBasicPointerLoop
#define WriteBasicPointerLoop(name)
Definition: TStreamerInfoWriteBuffer.cxx:83
Int_t
int Int_t
Definition: RtypesCore.h:45
TObject::GetUniqueID
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:377
TStreamerInfo::kFloat
@ kFloat
Definition: TStreamerInfo.h:167
TStreamerInfo::kAny
@ kAny
Definition: TStreamerInfo.h:172
TStreamerInfo::kBits
@ kBits
Definition: TStreamerInfo.h:170
x
Double_t x[n]
Definition: legend1.C:17
TVirtualCollectionProxy::GetValueClass
virtual TClass * GetValueClass() const =0
TClass.h
TStreamerInfo::TCompInfo::fType
Int_t fType
Definition: TStreamerInfo.h:52
TStreamerInfo::kTObject
@ kTObject
Definition: TStreamerInfo.h:173
TClass::GetStreamerInfo
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:4583
TVirtualArray
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:27
TStreamerElement::GetFullName
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
Definition: TStreamerElement.cxx:337
TStreamerInfo::TCompInfo::fStreamer
TMemberStreamer * fStreamer
Not Owned.
Definition: TStreamerInfo.h:61
TBuffer
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
TVirtualCollectionProxy::GetFunctionDeleteTwoIterators
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
TStreamerInfo::kUInt
@ kUInt
Definition: TStreamerInfo.h:170
TObjArray::GetObjectRef
TObject ** GetObjectRef() const
Definition: TObjArray.h:69
TStreamerInfo::kDouble32
@ kDouble32
Definition: TStreamerInfo.h:168
TString
Basic string class.
Definition: TString.h:136
TStreamer.h
Bool_t
bool Bool_t
Definition: RtypesCore.h:63
TStreamerInfo::TCompInfo::fClass
TClass * fClass
Not Owned.
Definition: TStreamerInfo.h:58
v
@ v
Definition: rootcling_impl.cxx:3664
b
#define b(i)
Definition: RSha256.hxx:100
TFile.h
TStreamerInfo::TPointerCollectionAdapter
Definition: TStreamerInfo.h:78
bool
WriteBasicPointer
#define WriteBasicPointer(name)
Definition: TStreamerInfoWriteBuffer.cxx:77
TClonesArray.h
WriteBasicType
#define WriteBasicType(name)
Definition: TStreamerInfoWriteBuffer.cxx:38
TStreamerInfo::kAnyp
@ kAnyp
Definition: TStreamerInfo.h:173
TStreamerInfo::kAnyP
@ kAnyP
Definition: TStreamerInfo.h:173
TVirtualCollectionProxy::GetFunctionCreateIterators
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
TRefTable.h
TStreamerElement::kWrite
@ kWrite
Definition: TStreamerElement.h:81
TProcessID.h
TStreamerInfo::kCacheDelete
@ kCacheDelete
Definition: TStreamerInfo.h:182
TStreamerInfo::fNfulldata
Int_t fNfulldata
!number of elements
Definition: TStreamerInfo.h:99
TStreamerInfo::kUShort
@ kUShort
Definition: TStreamerInfo.h:170
TStreamerInfo::WriteBufferClones
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).
Definition: TStreamerInfoWriteBuffer.cxx:867
TBuffer.h
TStreamerInfo::kAnyPnoVT
@ kAnyPnoVT
Definition: TStreamerInfo.h:173
TStreamerInfo
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:44
size
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
TStreamerInfo::WriteBufferAux
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...
Definition: TStreamerInfoWriteBuffer.cxx:114
TStreamerInfo::kObjectP
@ kObjectP
Definition: TStreamerInfo.h:172
TVirtualCollectionProxy::GetWriteMemberWiseActions
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()=0
TNamed
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TStreamerElement::GetClassPointer
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Definition: TStreamerElement.cxx:292
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
TStreamerElement::kRepeat
@ kRepeat
Definition: TStreamerElement.h:79
TProcessID::GetProcessWithUID
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
Definition: TProcessID.cxx:297
Long_t
long Long_t
Definition: RtypesCore.h:54
TRefTable::GetRefTable
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
TStreamerInfo::kUChar
@ kUChar
Equal to TDataType's kchar.
Definition: TStreamerInfo.h:170
TStreamerInfo::kCacheNew
@ kCacheNew
Definition: TStreamerInfo.h:181
TStreamerInfo::fClass
TClass * fClass
!pointer to class
Definition: TStreamerInfo.h:104
TStreamerInfo::kCharStar
@ kCharStar
Definition: TStreamerInfo.h:166
TVirtualCollectionProxy::fgIteratorArenaSize
static const Int_t fgIteratorArenaSize
Definition: TVirtualCollectionProxy.h:178
gDebug
Int_t gDebug
Definition: TROOT.cxx:590
TClass::CanSplit
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2298
TVirtualArray.h
ULong_t
unsigned long ULong_t
Definition: RtypesCore.h:55
Short_t
short Short_t
Definition: RtypesCore.h:39
TClass::kHasCustomStreamerMember
@ kHasCustomStreamerMember
Definition: TClass.h:105
TStreamerInfo::kShort
@ kShort
Definition: TStreamerInfo.h:167
TStreamerInfo::kSTL
@ kSTL
Definition: TStreamerInfo.h:177
TObject::Warning
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:879
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TStreamerInfo::kTString
@ kTString
Definition: TStreamerInfo.h:172
unsigned int
TStreamerInfo::TCompInfo
Definition: TStreamerInfo.h:46
TRefTable
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
TStreamerInfo::kStreamLoop
@ kStreamLoop
Definition: TStreamerInfo.h:178
ULong64_t
unsigned long long ULong64_t
Definition: RtypesCore.h:81
TStreamerInfo::kObjectp
@ kObjectp
Definition: TStreamerInfo.h:172
TStreamerArtificial
Definition: TStreamerElement.h:450
Double_t
double Double_t
Definition: RtypesCore.h:59
TStreamerInfo::kLong64
@ kLong64
Definition: TStreamerInfo.h:171
TObject::kIsReferenced
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:118
TStreamerInfo::TCompInfo::fOffset
Int_t fOffset
Definition: TStreamerInfo.h:54
TStreamerInfo::kArtificial
@ kArtificial
Cache the value in memory than is not part of the object but is accessible via a SchemaRule.
Definition: TStreamerInfo.h:180
TInterpreter.h
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
file
Definition: file.py:1
UChar_t
unsigned char UChar_t
Definition: RtypesCore.h:38
TVirtualCollectionProxy::TPushPop
Definition: TVirtualCollectionProxy.h:58
TStreamerInfo::kInt
@ kInt
Definition: TStreamerInfo.h:167
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TBufferFile.h
TStreamerInfo::kTNamed
@ kTNamed
Definition: TStreamerInfo.h:173
TStreamerInfo::kCounter
@ kCounter
Definition: TStreamerInfo.h:166
TStreamerInfo::kBase
@ kBase
Definition: TStreamerInfo.h:166
TStreamerInfo::kSTLp
@ kSTLp
Definition: TStreamerInfo.h:174
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:34
TStreamerInfo::TCompInfo::fMethod
ULong_t fMethod
Definition: TStreamerInfo.h:57
kMaxInt
const Int_t kMaxInt
Definition: RtypesCore.h:112
WriteBasicArray
#define WriteBasicArray(name)
Definition: TStreamerInfoWriteBuffer.cxx:54
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TMemberStreamer
Definition: TMemberStreamer.h:26
TStreamerInfo::kChar
@ kChar
Definition: TStreamerInfo.h:167
TStreamerInfo::kObject
@ kObject
Definition: TStreamerInfo.h:172
TStreamerInfo::kOffsetP
@ kOffsetP
Definition: TStreamerInfo.h:166
Char_t
char Char_t
Definition: RtypesCore.h:33
TObject::ClassName
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:130
TClonesArray
An array of clone (identical) objects.
Definition: TClonesArray.h:29
TStreamerInfo::WriteBuffer
Int_t WriteBuffer(TBuffer &b, char *pointer, Int_t first)
General Write.
Definition: TStreamerInfoWriteBuffer.cxx:858
TBufferFile
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:47
TStreamerInfo::WriteBufferSTL
Int_t WriteBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc)
Write for STL container. ('first' is an id between -1 and fNfulldata).
Definition: TStreamerInfoWriteBuffer.cxx:831
TStreamerElement
Definition: TStreamerElement.h:33
WriteBasicTypeLoop
#define WriteBasicTypeLoop(name)
Definition: TStreamerInfoWriteBuffer.cxx:43
TStreamerBase
Definition: TStreamerElement.h:151
TStreamerInfo::fCompFull
TCompInfo ** fCompFull
![fElements->GetEntries()]
Definition: TStreamerInfo.h:103
TVirtualCollectionProxy
Definition: TVirtualCollectionProxy.h:38
TVirtualCollectionProxy::Size
virtual UInt_t Size() const =0
int
WriteBasicArrayLoop
#define WriteBasicArrayLoop(name)
Definition: TStreamerInfoWriteBuffer.cxx:59
TError.h
TStreamerInfo::TCompInfo::fLength
Int_t fLength
Definition: TStreamerInfo.h:55