Logo ROOT   6.07/09
Reference Guide
TGenCollectionProxy.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Markus Frank 28/10/04
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, 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 "TGenCollectionProxy.h"
13 #include "TVirtualStreamerInfo.h"
14 #include "TStreamerElement.h"
15 #include "TClassEdit.h"
16 #include "TClass.h"
17 #include "TError.h"
18 #include "TROOT.h"
19 #include "TInterpreter.h"
20 #include "Riostream.h"
21 #include "TVirtualMutex.h"
22 #include "TStreamerInfoActions.h"
23 #include "THashTable.h"
24 #include "THashList.h"
25 #include <stdlib.h>
26 
27 #include "TInterpreter.h" // For gInterpreterMutex
28 
29 #define MESSAGE(which,text)
30 
31 /**
32 \class TGenVectorProxy
33 \ingroup IO
34 Local optimization class.
35 
36 Collection proxies get copied. On copy we switch the type of the
37 proxy to the concrete STL type. The concrete types are optimized
38 for element access.
39 */
40 
41 class TGenVectorProxy : public TGenCollectionProxy {
42 public:
43  // Standard Destructor
44  TGenVectorProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c)
45  {
46  }
47  // Standard Destructor
48  virtual ~TGenVectorProxy()
49 {
50  }
51  // Return the address of the value at index 'idx'
52  virtual void* At(UInt_t idx)
53 {
54  if ( fEnv && fEnv->fObject ) {
55  fEnv->fIdx = idx;
56  switch( idx ) {
57  case 0:
58  return fEnv->fStart = fFirst.invoke(fEnv);
59  default:
60  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
61  return ((char*)fEnv->fStart) + fValDiff*idx;
62  }
63  }
64  Fatal("TGenVectorProxy","At> Logic error - no proxy object set.");
65  return 0;
66  }
67  // Call to delete/destruct individual item
68  virtual void DeleteItem(Bool_t force, void* ptr) const
69  {
70  if ( force && ptr ) {
71  if ( fVal->fProperties&kNeedDelete) {
73  TPushPop helper(proxy,ptr);
74  proxy->Clear("force");
75  }
76  fVal->DeleteItem(ptr);
77  }
78  }
79 };
80 
81 /**
82 \class TGenVectorBoolProxy
83 \ingroup IO
84 Local optimization class.
85 
86 Collection proxies get copied. On copy we switch the type of the
87 proxy to the concrete STL type. The concrete types are optimized
88 for element access.
89 */
90 class TGenVectorBoolProxy : public TGenCollectionProxy {
91  Bool_t fLastValue;
92 
93 public:
94  TGenVectorBoolProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c), fLastValue(false)
95  {
96  // Standard Constructor.
97  }
98  virtual ~TGenVectorBoolProxy()
99  {
100  // Standard Destructor.
101  }
102  virtual void* At(UInt_t idx)
103  {
104  // Return the address of the value at index 'idx'
105 
106  // However we can 'take' the address of the content of std::vector<bool>.
107  if ( fEnv && fEnv->fObject ) {
108  switch( idx ) {
109  case 0:
110  fEnv->fStart = fFirst.invoke(fEnv);
111  fEnv->fIdx = idx;
112  break;
113  default:
114  fEnv->fIdx = idx - fEnv->fIdx;
115  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
116  fNext.invoke(fEnv);
117  fEnv->fIdx = idx;
118  break;
119  }
120  typedef ROOT::TCollectionProxyInfo::Type<std::vector<Bool_t> >::Env_t EnvType_t;
121  EnvType_t *e = (EnvType_t*)fEnv;
122  fLastValue = *(e->iter());
123  return &fLastValue;
124  }
125  Fatal("TGenVectorProxy","At> Logic error - no proxy object set.");
126  return 0;
127  }
128 
129  virtual void DeleteItem(Bool_t force, void* ptr) const
130  {
131  // Call to delete/destruct individual item
132  if ( force && ptr ) {
133  fVal->DeleteItem(ptr);
134  }
135  }
136 };
137 
138 //////////////////////////////////////////////////////////////////////////
139 // //
140 // class TGenBitsetProxy
141 //
142 // Local optimization class.
143 //
144 // Collection proxies get copied. On copy we switch the type of the
145 // proxy to the concrete STL type. The concrete types are optimized
146 // for element access.
147 //
148 //////////////////////////////////////////////////////////////////////////
149 class TGenBitsetProxy : public TGenCollectionProxy {
150 
151 public:
152  TGenBitsetProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c)
153  {
154  // Standard Constructor.
155  }
156  virtual ~TGenBitsetProxy()
157  {
158  // Standard Destructor.
159  }
160  virtual void* At(UInt_t idx)
161  {
162  // Return the address of the value at index 'idx'
163 
164  // However we can 'take' the address of the content of std::vector<bool>.
165  if ( fEnv && fEnv->fObject ) {
166  switch( idx ) {
167  case 0:
168  fEnv->fStart = fFirst.invoke(fEnv);
169  fEnv->fIdx = idx;
170  break;
171  default:
172  fEnv->fIdx = idx - fEnv->fIdx;
173  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
174  fNext.invoke(fEnv);
175  fEnv->fIdx = idx;
176  break;
177  }
178  typedef ROOT::TCollectionProxyInfo::Environ<std::pair<size_t,Bool_t> > EnvType_t;
179  EnvType_t *e = (EnvType_t*)fEnv;
180  return &(e->fIterator.second);
181  }
182  Fatal("TGenVectorProxy","At> Logic error - no proxy object set.");
183  return 0;
184  }
185 
186  virtual void DeleteItem(Bool_t force, void* ptr) const
187  {
188  // Call to delete/destruct individual item
189  if ( force && ptr ) {
190  fVal->DeleteItem(ptr);
191  }
192  }
193 };
194 
195 /*
196 \class TGenListProxy
197 \ingroup IO
198 Local optimization class.
199 
200 Collection proxies get copied. On copy we switch the type of the
201 proxy to the concrete STL type. The concrete types are optimized
202 for element access.
203 **/
204 
205 class TGenListProxy : public TGenVectorProxy {
206 public:
207  // Standard Destructor
208  TGenListProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c)
209 {
210  }
211  // Standard Destructor
212  virtual ~TGenListProxy()
213 {
214  }
215  // Return the address of the value at index 'idx'
216  void* At(UInt_t idx)
217 {
218  if ( fEnv && fEnv->fObject ) {
219  switch( idx ) {
220  case 0:
221  fEnv->fIdx = idx;
222  return fEnv->fStart = fFirst.invoke(fEnv);
223  default: {
224  fEnv->fIdx = idx - fEnv->fIdx;
225  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
226  void* result = fNext.invoke(fEnv);
227  fEnv->fIdx = idx;
228  return result;
229  }
230  }
231  }
232  Fatal("TGenListProxy","At> Logic error - no proxy object set.");
233  return 0;
234  }
235 };
236 
237 /**
238 \class TGenSetProxy
239 \ingroup IO
240 Localoptimization class.
241 
242 Collection proxies get copied. On copy we switch the type of the
243 proxy to the concrete STL type. The concrete types are optimized
244 for element access.
245 */
246 
247 class TGenSetProxy : public TGenVectorProxy {
248 public:
249  // Standard Destructor
250  TGenSetProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c)
251 {
252  }
253  // Standard Destructor
254  virtual ~TGenSetProxy()
255 {
256  }
257  // Return the address of the value at index 'idx'
258  void* At(UInt_t idx)
259 {
260  if ( fEnv && fEnv->fObject ) {
261  if ( fEnv->fUseTemp ) {
262  return (((char*)fEnv->fTemp)+idx*fValDiff);
263  }
264  switch( idx ) {
265  case 0:
266  fEnv->fIdx = idx;
267  return fEnv->fStart = fFirst.invoke(fEnv);
268  default: {
269  fEnv->fIdx = idx - fEnv->fIdx;
270  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
271  void* result = fNext.invoke(fEnv);
272  fEnv->fIdx = idx;
273  return result;
274  }
275  }
276  }
277  Fatal("TGenSetProxy","At> Logic error - no proxy object set.");
278  return 0;
279  }
280 };
281 
282 /**
283 \class TGenMapProxy
284 \ingroup IO
285 Localoptimization class.
286 
287 Collection proxies get copied. On copy we switch the type of the
288 proxy to the concrete STL type. The concrete types are optimized
289 for element access.
290 */
291 
292 class TGenMapProxy : public TGenSetProxy {
293 public:
294  // Standard Destructor
295  TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c)
296 {
297  }
298  // Standard Destructor
299  virtual ~TGenMapProxy()
300 {
301  }
302  // Call to delete/destruct individual item
303  virtual void DeleteItem(Bool_t force, void* ptr) const
304  {
305  if (force) {
306  if ( fKey->fProperties&kNeedDelete) {
307  TVirtualCollectionProxy *proxy = fKey->fType->GetCollectionProxy();
308  TPushPop helper(proxy,fKey->fCase&kIsPointer ? *(void**)ptr : ptr);
309  proxy->Clear("force");
310  }
311  if ( fVal->fProperties&kNeedDelete) {
312  TVirtualCollectionProxy *proxy = fVal->fType->GetCollectionProxy();
313  char *addr = ((char*)ptr)+fValOffset;
314  TPushPop helper(proxy,fVal->fCase&kIsPointer ? *(void**)addr : addr);
315  proxy->Clear("force");
316  }
317  }
318  if ( fKey->fCase&kIsPointer ) {
319  fKey->DeleteItem(*(void**)ptr);
320  }
321  if ( fVal->fCase&kIsPointer ) {
322  char *addr = ((char*)ptr)+fValOffset;
323  fVal->DeleteItem(*(void**)addr);
324  }
325  }
326 };
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// Constructor.
330 
331 TGenCollectionProxy::Value::Value(const std::string& inside_type, Bool_t silent)
332 {
333  std::string inside = (inside_type.find("const ")==0) ? inside_type.substr(6) : inside_type;
334  fCase = 0;
335  fProperties = 0;
336  fCtor = 0;
337  fDtor = 0;
338  fDelete = 0;
339  fSize = std::string::npos;
340  fKind = kNoType_t;
341  std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar );
342  if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) {
343  fCase = kBIT_ISSTRING;
344  fType = TClass::GetClass("string");
345  fCtor = fType->GetNew();
346  fDtor = fType->GetDestructor();
347  fDelete = fType->GetDelete();
348  switch(inside[inside.length()-1]) {
349  case '*':
350  fCase |= kIsPointer;
351  fSize = sizeof(void*);
352  break;
353  default:
354  fSize = sizeof(std::string);
355  break;
356  }
357  }
358  else {
359  // In the case where we have an emulated class,
360  // if the class is nested (in a class or a namespace),
361  // calling G__TypeInfo ti(inside.c_str());
362  // might fail because CINT does not known the nesting
363  // scope, so let's first look for an emulated class:
364 
365  fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
366 
367  if (fType) {
368  if (intype != inside) {
369  fCase |= kIsPointer;
370  fSize = sizeof(void*);
371  if (fType == TString::Class()) {
372  fCase |= kBIT_ISTSTRING;
373  }
374  }
375  fCase |= kIsClass;
376  fCtor = fType->GetNew();
377  fDtor = fType->GetDestructor();
378  fDelete = fType->GetDelete();
379  } else {
381 
382  // Try to avoid autoparsing.
383 
384  THashTable *typeTable = dynamic_cast<THashTable*>( gROOT->GetListOfTypes() );
385  THashList *enumTable = dynamic_cast<THashList*>( gROOT->GetListOfEnums() );
386 
387  assert(typeTable && "The type of the list of type has changed");
388  assert(enumTable && "The type of the list of enum has changed");
389 
390  TDataType *fundType = (TDataType *)typeTable->THashTable::FindObject( intype.c_str() );
391  if (fundType && fundType->GetType() < 0x17 && fundType->GetType() > 0) {
392  fKind = (EDataType)fundType->GetType();
393  if ( 0 == strcmp("bool",fundType->GetFullTypeName()) ) {
394  fKind = (EDataType)kBOOL_t;
395  }
396  // R__ASSERT((fKind>0 && fKind<0x17) || (fKind==-1&&(prop&kIsPointer)) );
397 
398  fCase |= kIsFundamental;
399  if (intype != inside) {
400  fCase |= kIsPointer;
401  fSize = sizeof(void*);
402  } else {
403  fSize = fundType->Size();
404  }
405  } else if (enumTable->THashList::FindObject( intype.c_str() ) ) {
406  // This is a known enum.
407  fCase = kIsEnum;
408  fSize = sizeof(Int_t);
409  fKind = kInt_t;
410  if (intype != inside) {
411  fCase |= kIsPointer;
412  fSize = sizeof(void*);
413  }
414  } else {
415  // This fallback solution should be hardly used ...
416  // One of the common use case is to 'discover' that this is a
417  // collection for the content of which we do not have a dictionary
418  // which can happen at least in the following cases:
419  // - empty emulated collection
420  // - emulated collection of enums
421  // In those two cases there is no StreamerInfo stored in the file
422  // for the content.
423 
424  // R__ASSERT("FallBack, should be hardly used.");
425 
426  TypeInfo_t *ti = gCling->TypeInfo_Factory();
427  gCling->TypeInfo_Init(ti,inside.c_str());
428  if ( !gCling->TypeInfo_IsValid(ti) ) {
429  if (intype != inside) {
430  fCase |= kIsPointer;
431  fSize = sizeof(void*);
432  }
433  // Since we already search for GetClass earlier, this should
434  // never be true.
435 // fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
436 // if (fType) {
437 // fCase |= kIsClass;
438 // fCtor = fType->GetNew();
439 // fDtor = fType->GetDestructor();
440 // fDelete = fType->GetDelete();
441 // }
442 // else {
443  // either we have an Emulated enum or a really unknown class!
444  // let's just claim its an enum :(
445  fCase = kIsEnum;
446  fSize = sizeof(Int_t);
447  fKind = kInt_t;
448 // }
449  }
450  else {
451  Long_t prop = gCling->TypeInfo_Property(ti);
452  if ( prop&kIsPointer ) {
453  fSize = sizeof(void*);
454  }
455  if ( prop&kIsStruct ) {
456  prop |= kIsClass;
457  }
458  // Since we already searched GetClass earlier, this should
459  // never be true.
460  R__ASSERT(! (prop&kIsClass) && "Impossible code path" );
461 // if ( prop&kIsClass ) {
462 // fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
463 // R__ASSERT(fType);
464 // fCtor = fType->GetNew();
465 // fDtor = fType->GetDestructor();
466 // fDelete = fType->GetDelete();
467 // }
468 // else
469  if ( prop&kIsFundamental ) {
470  fundType = gROOT->GetType( intype.c_str() );
471  if (fundType==0) {
472  if (intype != "long double") {
473  Error("TGenCollectionProxy","Unknown fundamental type %s",intype.c_str());
474  }
475  fSize = sizeof(int);
476  fKind = kInt_t;
477  } else {
478  fKind = (EDataType)fundType->GetType();
479  if ( 0 == strcmp("bool",fundType->GetFullTypeName()) ) {
480  fKind = (EDataType)kBOOL_t;
481  }
482  fSize = gCling->TypeInfo_Size(ti);
483  R__ASSERT((fKind>0 && fKind<0x17) || (fKind==-1&&(prop&kIsPointer)) );
484  }
485  }
486  else if ( prop&kIsEnum ) {
487  fSize = sizeof(int);
488  fKind = kInt_t;
489  }
490  fCase = prop & (kIsPointer|kIsFundamental|kIsEnum|kIsClass);
491  if (fType == TString::Class() && (fCase&kIsPointer)) {
492  fCase |= kBIT_ISTSTRING;
493  }
494  }
495  gCling->TypeInfo_Delete(ti);
496  }
497  }
498  if (fType) {
499  TVirtualCollectionProxy *proxy = fType->GetCollectionProxy();
500  if (proxy && (proxy->GetProperties() & kNeedDelete)) {
501  fProperties |= kNeedDelete;
502  }
503  }
504  }
505  if ( fSize == std::string::npos ) {
506  if ( fType == 0 ) {
507  // The caller should check the validity by calling IsValid()
508  } else {
509  fSize = fType->Size();
510  }
511  }
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////////
515 /// Return true if the Value has been properly initialized.
516 
518 {
519 
520 
521  return fSize != std::string::npos;
522 }
523 
525 {
526  // Delete an item.
527 
528  if ( ptr && fCase&kIsPointer ) {
529  if ( fDelete ) {
530  (*fDelete)(ptr);
531  }
532  else if ( fType ) {
533  fType->Destructor(ptr);
534  }
535  else {
536  ::operator delete(ptr);
537  }
538  }
539 }
540 
541 /**
542  \class TGenCollectionProxy TGenCollectionProxy.cxx
543  \ingroup IO
544 
545  Proxy around an arbitrary container, which implements basic
546  functionality and iteration.
547 
548  The purpose of this implementation
549  is to shield any generated dictionary implementation from the
550  underlying streamer/proxy implementation and only expose
551  the creation functions.
552 
553  In particular this is used to implement splitting and abstract
554  element access of any container. Access to compiled code is necessary
555  to implement the abstract iteration sequence and functionality like
556  size(), clear(), resize(). resize() may be a void operation.
557 */
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Build a proxy for an emulated container.
561 
563  : TVirtualCollectionProxy(copy.fClass),
564  fTypeinfo(copy.fTypeinfo)
565 {
566  fEnv = 0;
567  fName = copy.fName;
568  fPointers = copy.fPointers;
569  fSTL_type = copy.fSTL_type;
570  fSize.call = copy.fSize.call;
571  fNext.call = copy.fNext.call;
572  fFirst.call = copy.fFirst.call;
573  fClear.call = copy.fClear.call;
574  fResize = copy.fResize;
575  fDestruct = copy.fDestruct;
576  fConstruct = copy.fConstruct;
577  fFeed = copy.fFeed;
578  fCollect = copy.fCollect;
580  fValOffset = copy.fValOffset;
581  fValDiff = copy.fValDiff;
582  fValue = copy.fValue.load() ? new Value(*copy.fValue) : 0;
583  fVal = copy.fVal ? new Value(*copy.fVal) : 0;
584  fKey = copy.fKey ? new Value(*copy.fKey) : 0;
585  fOnFileClass = copy.fOnFileClass;
588  fWriteMemberWise = 0;
589  fProperties = copy.fProperties;
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 /// Build a proxy for a collection whose type is described by 'collectionClass'.
599 
602  fTypeinfo(info)
603 {
604  fEnv = 0;
605  fSize.call = 0;
606  fFirst.call = 0;
607  fNext.call = 0;
608  fClear.call = 0;
609  fResize = 0;
610  fDestruct = 0;
611  fConstruct = 0;
612  fCollect = 0;
613  fCreateEnv.call = 0;
614  fFeed = 0;
615  fValue = 0;
616  fKey = 0;
617  fVal = 0;
618  fValOffset = 0;
619  fValDiff = 0;
620  fPointers = false;
621  fOnFileClass = 0;
623  Env_t e;
624  if ( iter_size > sizeof(e.fIterator) ) {
625  Fatal("TGenCollectionProxy",
626  "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
627  "Iterators for collection",
628  fClass->GetName(),
629  (Long_t)iter_size,
630  (Long_t)sizeof(e.fIterator));
631  }
634  fWriteMemberWise = 0;
640 }
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 /// Build a proxy for a collection whose type is described by 'collectionClass'.
644 
647  fTypeinfo(info.fInfo), fOnFileClass(0)
648 {
649  fEnv = 0;
650  fValDiff = info.fValueDiff;
651  fValOffset = info.fValueOffset;
652  fSize.call = info.fSizeFunc;
653  fResize = info.fResizeFunc;
654  fNext.call = info.fNextFunc;
655  fFirst.call = info.fFirstFunc;
656  fClear.call = info.fClearFunc;
657  fConstruct = info.fConstructFunc;
658  fDestruct = info.fDestructFunc;
659  fFeed = info.fFeedFunc;
660  fCollect = info.fCollectFunc;
661  fCreateEnv.call = info.fCreateEnv;
662 
663  if (cl) {
664  fName = cl->GetName();
665  }
666  CheckFunctions();
667 
668  fValue = 0;
669  fKey = 0;
670  fVal = 0;
671  fPointers = false;
673 
674  Env_t e;
675  if ( info.fIterSize > sizeof(e.fIterator) ) {
676  Fatal("TGenCollectionProxy",
677  "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
678  "Iterators for collection",
679  fClass->GetName(),
680  (Long_t)info.fIterSize,
681  (Long_t)sizeof(e.fIterator));
682  }
685  fWriteMemberWise = 0;
691 }
692 
693 namespace {
694  template <class vec>
695  void clearVector(vec& v)
696  {
697  // Clear out the proxies.
698 
699  for(typename vec::iterator i=v.begin(); i != v.end(); ++i) {
700  typename vec::value_type e = *i;
701  if ( e ) {
702  delete e;
703  }
704  }
705  v.clear();
706  }
707 }
708 ////////////////////////////////////////////////////////////////////////////////
709 /// Standard destructor
710 
712 {
713  clearVector(fProxyList);
714  clearVector(fProxyKept);
715  clearVector(fStaged);
716 
717  if ( fValue.load() ) delete fValue.load();
718  if ( fVal ) delete fVal;
719  if ( fKey ) delete fKey;
720 
721  delete fReadMemberWise;
723  std::map<std::string, TObjArray*>::iterator it;
724  std::map<std::string, TObjArray*>::iterator end = fConversionReadMemberWise->end();
725  for( it = fConversionReadMemberWise->begin(); it != end; ++it ) {
726  delete it->second;
727  }
730  }
731  delete fWriteMemberWise;
732 }
733 
734 ////////////////////////////////////////////////////////////////////////////////
735 /// Virtual copy constructor
736 
738 {
739  if ( !fValue.load() ) Initialize(kFALSE);
740 
741  if( fPointers )
742  return new TGenCollectionProxy(*this);
743 
744  switch(fSTL_type) {
745  case ROOT::kSTLbitset: {
746  return new TGenBitsetProxy(*this);
747  }
748  case ROOT::kSTLvector: {
749  if ((*fValue).fKind == (EDataType)kBOOL_t) {
750  return new TGenVectorBoolProxy(*this);
751  } else {
752  return new TGenVectorProxy(*this);
753  }
754  }
755  case ROOT::kSTLlist:
757  return new TGenListProxy(*this);
758  case ROOT::kSTLmap:
760  case ROOT::kSTLmultimap:
762  return new TGenMapProxy(*this);
763  case ROOT::kSTLset:
765  case ROOT::kSTLmultiset:
767  return new TGenSetProxy(*this);
768  default:
769  return new TGenCollectionProxy(*this);
770  }
771 }
772 
773 ////////////////////////////////////////////////////////////////////////////////
774 /// Proxy initializer
775 
777 {
778  TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this);
779  if ( fValue.load() ) return p;
780  return p->InitializeEx(silent);
781 }
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 /// Check existence of function pointers
785 
787 {
788  if ( 0 == fSize.call ) {
789  Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str());
790  }
791  if ( 0 == fResize ) {
792  Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str());
793  }
794  if ( 0 == fNext.call ) {
795  Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str());
796  }
797  if ( 0 == fFirst.call ) {
798  Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str());
799  }
800  if ( 0 == fClear.call ) {
801  Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str());
802  }
803  if ( 0 == fConstruct ) {
804  Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str());
805  }
806  if ( 0 == fDestruct ) {
807  Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str());
808  }
809  if ( 0 == fFeed ) {
810  Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str());
811  }
812  if ( 0 == fCollect ) {
813  Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str());
814  }
815  if (0 == fCreateEnv.call ) {
816  Fatal("TGenCollectionProxy","No 'environment creation' function for class %s present.",fName.c_str());
817  }
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////////
821 /// Utility routine to issue a Fatal error is the Value object is not valid
822 
823 static TGenCollectionProxy::Value *R__CreateValue(const std::string &name, Bool_t silent)
824 {
825  TGenCollectionProxy::Value *val = new TGenCollectionProxy::Value( name, silent );
826  if ( !val->IsValid() ) {
827  Fatal("TGenCollectionProxy","Could not find %s!",name.c_str());
828  }
829  return val;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// Proxy initializer
834 
836 {
838  if (fValue.load()) return this;
839 
841  if ( cl ) {
842  fEnv = 0;
843  fName = cl->GetName();
844  fPointers = false;
845  int nested = 0;
846  std::vector<std::string> inside;
847  int num = TClassEdit::GetSplit(cl->GetName(),inside,nested);
848  if ( num > 1 ) {
849  std::string nam;
850  Value* newfValue = nullptr;
851  if ( inside[0].find("stdext::hash_") != std::string::npos )
852  inside[0].replace(3,10,"::");
853  if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos )
854  inside[0].replace(0,16,"std::");
855  fSTL_type = TClassEdit::STLKind(inside[0].c_str());
856  switch ( fSTL_type ) {
857  case ROOT::kSTLmap:
859  case ROOT::kSTLmultimap:
861  case ROOT::kSTLset:
863  case ROOT::kSTLmultiset:
865  case ROOT::kSTLbitset: // not really an associate container but it has no real iterator.
867  break;
868  };
869 
870  int slong = sizeof(void*);
871  switch ( fSTL_type ) {
872  case ROOT::kSTLmap:
874  case ROOT::kSTLmultimap:
876  nam = "pair<"+inside[1]+","+inside[2];
877  nam += (nam[nam.length()-1]=='>') ? " >" : ">";
878  newfValue = R__CreateValue(nam, silent);
879 
880  fVal = R__CreateValue(inside[2], silent);
881  fKey = R__CreateValue(inside[1], silent);
882  fPointers = (0 != (fKey->fCase&kIsPointer));
883  if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
885  }
886  if ( 0 == fValDiff ) {
887  fValDiff = fKey->fSize + fVal->fSize;
888  fValDiff += (slong - fKey->fSize%slong)%slong;
889  fValDiff += (slong - fValDiff%slong)%slong;
890  }
891  if ( 0 == fValOffset ) {
892  fValOffset = fKey->fSize;
893  fValOffset += (slong - fKey->fSize%slong)%slong;
894  }
895  break;
896  case ROOT::kSTLbitset:
897  inside[1] = "bool";
898  // Intentional fall through
899  default:
900  newfValue = R__CreateValue(inside[1], silent);
901 
902  fVal = new Value(*newfValue);
903  if ( 0 == fValDiff ) {
904  fValDiff = fVal->fSize;
905  fValDiff += (slong - fValDiff%slong)%slong;
906  }
907  break;
908  }
909 
910  fPointers = fPointers || (0 != (fVal->fCase&kIsPointer));
911  if (fPointers || (0 != (fVal->fProperties&kNeedDelete))) {
913  }
914  fClass = cl;
915  //fValue must be set last since we use it to indicate that we are initialized
916  fValue = newfValue;
917  return this;
918  }
919  Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName());
920  }
921  Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name());
922  return 0;
923 }
924 
925 ////////////////////////////////////////////////////////////////////////////////
926 /// Return a pointer to the TClass representing the container
927 
929 {
930  return fClass ? fClass : Initialize(kFALSE)->fClass;
931 }
932 
933 ////////////////////////////////////////////////////////////////////////////////
934 /// Return the type of collection see TClassEdit::ESTLType
935 
937 {
938  if (!fValue.load()) {
940  }
941  return fSTL_type;
942 }
943 
944 ////////////////////////////////////////////////////////////////////////////////
945 /// Return the offset between two consecutive value_types (memory layout).
946 
948  if (!fValue.load()) {
950  }
951  return fValDiff;
952 }
953 
954 ////////////////////////////////////////////////////////////////////////////////
955 /// Return the sizeof the collection object.
956 
958 {
959  return fClass->Size();
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// Return true if the content is of type 'pointer to'
964 
966 {
967  // Initialize proxy in case it hasn't been initialized yet
968  if( !fValue.load() )
970 
971  // The content of a map and multimap is always a 'pair' and hence
972  // fPointers means "Flag to indicate if containee has pointers (key or value)"
973  // so we need to ignore its value for map and multimap;
975 }
976 
977 ////////////////////////////////////////////////////////////////////////////////
978 /// Return a pointer to the TClass representing the content.
979 
981 {
982  if (!fValue.load()) Initialize(kFALSE);
983  return fValue.load() ? (*fValue).fType.GetClass() : 0;
984 }
985 
986 ////////////////////////////////////////////////////////////////////////////////
987 /// Update the internal ValueClass when a TClass constructor need to
988 /// replace an emulated TClass by the real TClass.
989 
990 void TGenCollectionProxy::UpdateValueClass(const TClass *oldValueType, TClass *newValueType)
991 {
992  // Note that we do not need to update anything if we have not yet been
993  // initialized. In addition (see ROOT-6040) doing an initialization here
994  // might hence a nested dlopen (due to autoloading).
995  if (fValue.load() && (*fValue).fType == oldValueType) {
996  // Set pointer to the TClass representing the content.
997  (*fValue).fType = newValueType;
998  }
999 }
1000 
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// If the content is a simple numerical value, return its type (see TDataType)
1003 
1005 {
1006  if ( !fValue.load() ) Initialize(kFALSE);
1007  return (*fValue).fKind;
1008 }
1009 
1010 ////////////////////////////////////////////////////////////////////////////////
1011 /// Return the address of the value at index 'idx'
1012 
1014 {
1015  if ( fEnv && fEnv->fObject ) {
1016  switch (fSTL_type) {
1017  case ROOT::kSTLvector:
1018  fEnv->fIdx = idx;
1019  switch( idx ) {
1020  case 0:
1021  return fEnv->fStart = fFirst.invoke(fEnv);
1022  default:
1023  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1024  return ((char*)fEnv->fStart) + fValDiff*idx;
1025  }
1026  case ROOT::kSTLset:
1028  case ROOT::kSTLmultiset:
1030  case ROOT::kSTLmap:
1032  case ROOT::kSTLmultimap:
1034  if ( fEnv->fUseTemp ) {
1035  return (((char*)fEnv->fTemp)+idx*fValDiff);
1036  }
1037  // Intentional fall through.
1038  default:
1039  switch( idx ) {
1040  case 0:
1041  fEnv->fIdx = idx;
1042  return fEnv->fStart = fFirst.invoke(fEnv);
1043  default: {
1044  fEnv->fIdx = idx - fEnv->fIdx;
1045  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1046  void* result = fNext.invoke(fEnv);
1047  fEnv->fIdx = idx;
1048  return result;
1049  }
1050  }
1051  }
1052  }
1053  Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1054  return 0;
1055 }
1056 
1057 ////////////////////////////////////////////////////////////////////////////////
1058 /// Clear the emulated collection.
1059 
1060 void TGenCollectionProxy::Clear(const char* opt)
1061 {
1062  if ( fEnv && fEnv->fObject ) {
1063  if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1064  size_t i, n = *(size_t*)fSize.invoke(fEnv);
1065  if ( n > 0 ) {
1066  for (i=0; i<n; ++i)
1068  }
1069  }
1070  fClear.invoke(fEnv);
1071  }
1072 }
1073 
1074 ////////////////////////////////////////////////////////////////////////////////
1075 /// Return the current size of the container
1076 
1078 {
1079  if ( fEnv && fEnv->fObject ) {
1080  if (fEnv->fUseTemp) {
1081  return fEnv->fSize;
1082  } else {
1083  return *(size_t*)fSize.invoke(fEnv);
1084  }
1085  }
1086  Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1087  return 0;
1088 }
1089 
1090 ////////////////////////////////////////////////////////////////////////////////
1091 /// Resize the container
1092 
1094 {
1095  if ( fEnv && fEnv->fObject ) {
1096  if ( force && fPointers ) {
1097  size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1098  if ( n != nold ) {
1099  for (i=n; i<nold; ++i)
1100  DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1101  }
1102  }
1103  MESSAGE(3, "Resize(n)" );
1104  fEnv->fSize = n;
1106  return;
1107  }
1108  Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1109 }
1110 
1111 ////////////////////////////////////////////////////////////////////////////////
1112 /// Allocate the needed space.
1113 /// For associative collection, this returns a TStaging object that
1114 /// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1115 
1116 void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t /* forceDelete */ )
1117 {
1118  if ( fEnv && fEnv->fObject ) {
1119  switch ( fSTL_type ) {
1120  case ROOT::kSTLset:
1122  case ROOT::kSTLmultiset:
1124  case ROOT::kSTLmap:
1126  case ROOT::kSTLmultimap:
1128  if ( (fProperties & kNeedDelete) )
1129  Clear("force");
1130  else
1131  fClear.invoke(fEnv);
1132  // Commit no longer use the environment and thus no longer decrease
1133  // the count. Consequently we no longer should increase it here.
1134  // ++fEnv->fRefCount;
1135  fEnv->fSize = n;
1136 
1137  TStaging *s;
1138  if (fStaged.empty()) {
1139  s = new TStaging(n,fValDiff);
1140  } else {
1141  s = fStaged.back();
1142  fStaged.pop_back();
1143  s->Resize(n);
1144  }
1145  fConstruct(s->GetContent(),s->GetSize());
1146 
1147  s->SetTarget(fEnv->fObject);
1148 
1149  fEnv->fTemp = s->GetContent();
1150  fEnv->fUseTemp = kTRUE;
1151  fEnv->fStart = fEnv->fTemp;
1152 
1153  return s;
1154  }
1155  case ROOT::kSTLvector:
1156  case ROOT::kSTLlist:
1157  case ROOT::kSTLforwardlist:
1158  case ROOT::kSTLdeque:
1159  if( (fProperties & kNeedDelete) ) {
1160  Clear("force");
1161  }
1162  fEnv->fSize = n;
1163  fResize(fEnv->fObject,n);
1164  return fEnv->fObject;
1165 
1166  case ROOT::kSTLbitset: {
1167  TStaging *s;
1168  if (fStaged.empty()) {
1169  s = new TStaging(n,fValDiff);
1170  } else {
1171  s = fStaged.back();
1172  fStaged.pop_back();
1173  s->Resize(n);
1174  }
1175  s->SetTarget(fEnv->fObject);
1176 
1177  fEnv->fTemp = s->GetContent();
1178  fEnv->fUseTemp = kTRUE;
1179  fEnv->fStart = fEnv->fTemp;
1180 
1181  return s;
1182  }
1183  }
1184  }
1185  return 0;
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////////
1189 /// Insert data into the container where data is a C-style array of the actual type contained in the collection
1190 /// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1191 
1192 void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1193 {
1194  fFeed((void*)data,container,size);
1195 }
1196 
1197 ////////////////////////////////////////////////////////////////////////////////
1198 /// Commit the change.
1199 
1201 {
1202  if (fProperties & kIsAssociative) {
1203 // case ROOT::kSTLmap:
1204 // case ROOT::kSTLmultimap:
1205 // case ROOT::kSTLset:
1206 // case ROOT::kSTLmultiset:
1207  if ( from ) {
1208  TStaging *s = (TStaging*) from;
1209  if ( s->GetTarget() ) {
1210  fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1211  }
1212  fDestruct(s->GetContent(),s->GetSize());
1213  s->SetTarget(0);
1214  fStaged.push_back(s);
1215  }
1216  }
1217 }
1218 
1219 ////////////////////////////////////////////////////////////////////////////////
1220 /// Add an object.
1221 
1223 {
1224  if ( !fValue.load() ) Initialize(kFALSE);
1225  if ( !fProxyList.empty() ) {
1226  EnvironBase_t* back = fProxyList.back();
1227  if ( back->fObject == objstart ) {
1228  ++back->fRefCount;
1229  fProxyList.push_back(back);
1230  fEnv = back;
1231  return;
1232  }
1233  }
1234  EnvironBase_t* e = 0;
1235  if ( fProxyKept.empty() ) {
1237  e->fTemp = 0;
1238  e->fUseTemp = kFALSE;
1239  }
1240  else {
1241  e = fProxyKept.back();
1242  fProxyKept.pop_back();
1243  }
1244  e->fSize = 0;
1245  e->fRefCount = 1;
1246  e->fObject = objstart;
1247  e->fStart = 0;
1248  e->fIdx = 0;
1249  // ::memset(e->buff,0,sizeof(e->buff));
1250  fProxyList.push_back(e);
1251  fEnv = e;
1252 }
1253 
1254 ////////////////////////////////////////////////////////////////////////////////
1255 /// Remove the last object.
1256 
1258 {
1259  if ( !fProxyList.empty() ) {
1260  EnvironBase_t* e = fProxyList.back();
1261  if ( --e->fRefCount <= 0 ) {
1262  fProxyKept.push_back(e);
1263  e->fUseTemp = kFALSE;
1264  }
1265  fProxyList.pop_back();
1266  }
1267  fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1268 }
1269 
1270 ////////////////////////////////////////////////////////////////////////////////
1271 /// Call to delete/destruct individual item.
1272 
1273 void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
1274 {
1275  if ( force && ptr ) {
1276  switch (fSTL_type) {
1277  case ROOT::kSTLmap:
1278  case ROOT::kSTLmultimap: {
1279  if ( fKey->fCase&kIsPointer ) {
1280  if (fKey->fProperties&kNeedDelete) {
1282  TPushPop helper(proxy,*(void**)ptr);
1283  proxy->Clear("force");
1284  }
1285  fKey->DeleteItem(*(void**)ptr);
1286  } else {
1287  if (fKey->fProperties&kNeedDelete) {
1289  TPushPop helper(proxy,ptr);
1290  proxy->Clear("force");
1291  }
1292  }
1293  char *addr = ((char*)ptr)+fValOffset;
1294  if ( fVal->fCase&kIsPointer ) {
1295  if ( fVal->fProperties&kNeedDelete) {
1297  TPushPop helper(proxy,*(void**)addr);
1298  proxy->Clear("force");
1299  }
1300  fVal->DeleteItem(*(void**)addr);
1301  } else {
1302  if ( fVal->fProperties&kNeedDelete) {
1304  TPushPop helper(proxy,addr);
1305  proxy->Clear("force");
1306  }
1307  }
1308  break;
1309  }
1310  default: {
1311  if ( fVal->fCase&kIsPointer ) {
1312  if (fVal->fProperties&kNeedDelete) {
1314  TPushPop helper(proxy,*(void**)ptr);
1315  proxy->Clear("force");
1316  }
1317  fVal->DeleteItem(*(void**)ptr);
1318  } else {
1319  if (fVal->fProperties&kNeedDelete) {
1321  TPushPop helper(proxy,ptr);
1322  proxy->Clear("force");
1323  }
1324  }
1325  break;
1326  }
1327  }
1328  }
1329 }
1330 
1331 ////////////////////////////////////////////////////////////////////////////////
1332 
1333 void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1334 {
1335  MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1336 }
1337 
1338 ////////////////////////////////////////////////////////////////////////////////
1339 
1340 void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1341 {
1342  MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1343 }
1344 
1345 ////////////////////////////////////////////////////////////////////////////////
1346 /// Streamer Function.
1347 
1349 {
1350  if ( fEnv ) {
1351  GetCollectionClass()->Streamer( fEnv->fObject, buff );
1352  return;
1353  }
1354  Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1355 }
1356 
1357 ////////////////////////////////////////////////////////////////////////////////
1358 /// Streamer I/O overload
1359 
1360 void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1361 {
1362  TPushPop env(this, objp);
1363  Streamer(buff);
1364 }
1365 
1366 ////////////////////////////////////////////////////////////////////////////////
1367 /// TClassStreamer IO overload
1368 
1370 {
1371  Streamer(b, objp, 0);
1372 }
1373 
1374 
1375 struct TGenCollectionProxy__SlowIterator {
1376  TVirtualCollectionProxy *fProxy;
1377  UInt_t fIndex;
1378  TGenCollectionProxy__SlowIterator(TVirtualCollectionProxy *proxy) : fProxy(proxy), fIndex(0) {}
1379 };
1380 
1381 ////////////////////////////////////////////////////////////////////////////////
1382 
1383 void TGenCollectionProxy__SlowCreateIterators(void * /* collection */, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
1384 {
1385  new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1386  *(UInt_t*)*end_arena = proxy->Size();
1387 }
1388 
1389 ////////////////////////////////////////////////////////////////////////////////
1390 
1391 void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1392 {
1393  TGenCollectionProxy__SlowIterator *iterator = (TGenCollectionProxy__SlowIterator*)iter;
1394  if (iterator->fIndex != *(UInt_t*)end) {
1395  void *result = iterator->fProxy->At(iterator->fIndex);
1396  ++(iterator->fIndex);
1397  return result;
1398  } else {
1399  return 0;
1400  }
1401 }
1402 
1403 ////////////////////////////////////////////////////////////////////////////////
1404 
1405 void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
1406 {
1407  *(TGenCollectionProxy__SlowIterator*)dest = *(TGenCollectionProxy__SlowIterator*)source;
1408  return dest;
1409 }
1410 
1411 ////////////////////////////////////////////////////////////////////////////////
1412 /// Nothing to do
1413 
1415 {
1416 }
1417 
1418 ////////////////////////////////////////////////////////////////////////////////
1419 /// Nothing to do
1420 
1422 {
1423 }
1424 
1425 
1426 ////////////////////////////////////////////////////////////////////////////////
1427 /// We can safely assume that the std::vector layout does not really depend on
1428 /// the content!
1429 
1430 void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy*)
1431 {
1432  std::vector<char> *vec = (std::vector<char>*)obj;
1433  if (vec->empty()) {
1434  *begin_arena = 0;
1435  *end_arena = 0;
1436  return;
1437  }
1438  *begin_arena = &(*vec->begin());
1439 #ifdef R__VISUAL_CPLUSPLUS
1440  *end_arena = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
1441 #else
1442  // coverity[past_the_end] Safe on other platforms
1443  *end_arena = &(*vec->end());
1444 #endif
1445 
1446 }
1447 
1448 ////////////////////////////////////////////////////////////////////////////////
1449 /// Should not be used.
1450 
1451 void *TGenCollectionProxy__VectorNext(void *, const void *)
1452 {
1453  R__ASSERT(0);
1454  return 0;
1455 }
1456 
1457 ////////////////////////////////////////////////////////////////////////////////
1458 
1459 void *TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
1460 {
1461  *(void**)dest = *(void**)source;
1462  return dest;
1463 }
1464 
1465 ////////////////////////////////////////////////////////////////////////////////
1466 /// Nothing to do
1467 
1469 {
1470 }
1471 
1472 ////////////////////////////////////////////////////////////////////////////////
1473 /// Nothing to do
1474 
1476 {
1477 }
1478 
1479 
1480 
1481 ////////////////////////////////////////////////////////////////////////////////
1482 
1483 void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
1484 {
1486  *begin_arena = s->GetContent();
1487  *end_arena = s->GetEnd();
1488 }
1489 
1490 ////////////////////////////////////////////////////////////////////////////////
1491 /// Should not be used.
1492 
1493 void *TGenCollectionProxy__StagingNext(void *, const void *)
1494 {
1495  R__ASSERT(0);
1496  return 0;
1497 }
1498 
1499 ////////////////////////////////////////////////////////////////////////////////
1500 
1501 void *TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
1502 {
1503  *(void**)dest = *(void**)source;
1504  return dest;
1505 }
1506 
1507 ////////////////////////////////////////////////////////////////////////////////
1508 /// Nothing to do
1509 
1511 {
1512 }
1513 
1514 ////////////////////////////////////////////////////////////////////////////////
1515 /// Nothing to do
1516 
1518 {
1519 }
1520 
1521 
1522 ////////////////////////////////////////////////////////////////////////////////
1523 /// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1524 /// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1525 /// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1526 /// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1527 
1529 {
1530  if (read) {
1531  if ( !fValue.load() ) InitializeEx(kFALSE);
1532  if ( (fProperties & kIsAssociative) && read)
1534  }
1535 
1537 
1538  if ( !fValue.load() ) InitializeEx(kFALSE);
1539 
1540 // fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1541 // if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1542 // fprintf(stderr,"vector/emulated iterator\n");
1543 // else if ( (fProperties & kIsAssociative) && read)
1544 // fprintf(stderr,"an associative read iterator\n");
1545 // else
1546 // fprintf(stderr,"a generic iterator\n");
1547 
1550  else if ( (fProperties & kIsAssociative) && read)
1552  else
1554 }
1555 
1556 ////////////////////////////////////////////////////////////////////////////////
1557 /// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1558 /// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1559 /// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1560 /// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1561 
1563 {
1564  if (read) {
1565  if ( !fValue.load() ) InitializeEx(kFALSE);
1566  if ( (fProperties & kIsAssociative) && read)
1568  }
1569 
1571 
1572  if ( !fValue.load() ) InitializeEx(kFALSE);
1573 
1576  else if ( (fProperties & kIsAssociative) && read)
1578  else
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// See typedef void* (*Next_t)(void *iter, void *end);
1584 /// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1585 /// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1586 /// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1587 /// which case 'Next' will return the value of the pointer.
1588 
1590 {
1591  if (read) {
1592  if ( !fValue.load() ) InitializeEx(kFALSE);
1593  if ( (fProperties & kIsAssociative) && read)
1595  }
1596 
1598 
1599  if ( !fValue.load() ) InitializeEx(kFALSE);
1600 
1603  else if ( (fProperties & kIsAssociative) && read)
1605  else
1607 }
1608 
1609 ////////////////////////////////////////////////////////////////////////////////
1610 /// See typedef void (*DeleteIterator_t)(void *iter);
1611 /// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1612 /// Otherwise just call the iterator's destructor.
1613 
1615 {
1616  if (read) {
1617  if ( !fValue.load() ) InitializeEx(kFALSE);
1618  if ( (fProperties & kIsAssociative) && read)
1620  }
1621 
1623 
1624  if ( !fValue.load() ) InitializeEx(kFALSE);
1625 
1628  else if ( (fProperties & kIsAssociative) && read)
1630  else
1632 }
1633 
1634 ////////////////////////////////////////////////////////////////////////////////
1635 /// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1636 /// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1637 /// Otherwise just call the iterator's destructor.
1638 
1640 {
1641  if (read) {
1642  if ( !fValue.load() ) InitializeEx(kFALSE);
1643  if ( (fProperties & kIsAssociative) && read)
1645  }
1646 
1648 
1649  if ( !fValue.load() ) InitializeEx(kFALSE);
1650 
1653  else if ( (fProperties & kIsAssociative) && read)
1655  else
1657 }
1658 
1659 ////////////////////////////////////////////////////////////////////////////////
1660 /// Return the set of action necessary to stream in this collection member-wise coming from
1661 /// the old value class layout refered to by 'version'.
1662 
1664 {
1665  if (oldClass == 0) {
1666  return 0;
1667  }
1668  TObjArray* arr = 0;
1671  std::map<std::string, TObjArray*>::iterator it;
1672 
1673  it = fConversionReadMemberWise->find( oldClass->GetName() );
1674 
1675  if( it != fConversionReadMemberWise->end() ) {
1676  arr = it->second;
1677  }
1678 
1679  if (arr) {
1680  result = (TStreamerInfoActions::TActionSequence *)arr->At(version);
1681  if (result) {
1682  return result;
1683  }
1684  }
1685  }
1686 
1687  // Need to create it.
1688  TClass *valueClass = GetValueClass();
1689  if (valueClass == 0) {
1690  return 0;
1691  }
1692  TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1693  if (info == 0) {
1694  return 0;
1695  }
1697 
1698  if (!arr) {
1699  arr = new TObjArray(version+10, -1);
1701  fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1702  }
1703  (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1704  }
1705  arr->AddAtAndExpand( result, version );
1706 
1707  return result;
1708 }
1709 
1710 ////////////////////////////////////////////////////////////////////////////////
1711 /// Return the set of action necessary to stream in this collection member-wise coming from
1712 /// the old value class layout refered to by 'version'.
1713 
1715 {
1717  if (version < (fReadMemberWise->GetSize()-1)) { // -1 because the 'index' starts at -1
1719  }
1720  if (result == 0) {
1721  // Need to create it.
1722  TClass *valueClass = GetValueClass();
1723  TVirtualStreamerInfo *info = 0;
1724  if (valueClass) {
1725  info = valueClass->GetStreamerInfo(version);
1726  }
1728  fReadMemberWise->AddAtAndExpand(result,version);
1729  }
1730  return result;
1731 }
1732 
1733 ////////////////////////////////////////////////////////////////////////////////
1734 /// Return the set of action necessary to stream out this collection member-wise.
1735 
1737 {
1739  if (result == 0) {
1740  // Need to create it.
1741  TClass *valueClass = GetValueClass();
1742  TVirtualStreamerInfo *info = 0;
1743  if (valueClass) {
1744  info = valueClass->GetStreamerInfo();
1745  }
1748  }
1749  return result;
1750 }
Method fSize
Container accessors: size of container.
double read(const std::string &file_name)
reading
void * TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
DeleteIterator_t fFunctionDeleteIterator
void TGenCollectionProxy__StagingDeleteSingleIterators(void *)
Nothing to do.
An array of TObjects.
Definition: TObjArray.h:39
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)
Return the set of action necessary to stream in this collection member-wise coming from the old value...
virtual Int_t GetProperties() const
Proxies_t fProxyKept
Optimization: Keep proxies once they were created.
virtual TVirtualCollectionProxy * Generate() const
Virtual copy constructor.
DeleteTwoIterators_t fFunctionDeleteTwoIterators
void * invoke(void *obj) const
void *(* fNext)(void *iter, const void *end)
UInt_t fProperties
Additional properties of the value type (kNeedDelete)
void *(* fConstructFunc)(void *, size_t)
void TGenCollectionProxy__VectorDeleteTwoIterators(void *, void *)
Nothing to do.
virtual void UpdateValueClass(const TClass *oldcl, TClass *newcl)
Update the internal ValueClass when a TClass constructor need to replace an emulated TClass by the re...
Int_t GetType() const
Definition: TDataType.h:70
void Fatal(const char *location, const char *msgfmt,...)
Bool_t fPointers
Flag to indicate if containee has pointers (key or value)
std::map< std::string, TObjArray * > * fConversionReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read) derived from another class...
TGenCollectionProxy * Initialize(Bool_t silent) const
Proxy initializer.
return c
Collectfunc_t fCollect
Method to collect objects from container.
std::string fName
Name of the class being proxied.
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Definition: TClassEdit.cxx:938
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()
Return the set of action necessary to stream out this collection member-wise.
virtual void PopProxy()
Remove the last object.
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Definition: TDataType.cxx:175
virtual void Insert(const void *data, void *container, size_t size)
Insert data into the container where data is a C-style array of the actual type contained in the coll...
Method fFirst
Container accessors: generic iteration: first.
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
#define R__ASSERT(e)
Definition: TError.h:98
#define gROOT
Definition: TROOT.h:364
virtual TypeInfo_t * TypeInfo_Factory() const
Definition: TInterpreter.h:479
TClass * fOnFileClass
On file class.
Feedfunc_t fFeed
Container accessors: block feed.
void *(* fFeedFunc)(void *, void *, size_t)
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual void Clear(const char *opt="")=0
const Bool_t kFALSE
Definition: Rtypes.h:92
#define MESSAGE(which, text)
const char * Class
Definition: TXMLSetup.cxx:64
UInt_t fCase
type of data of Value_type
virtual Bool_t HasPointers() const
Return true if the content is of type &#39;pointer to&#39;.
void * TGenCollectionProxy__StagingNext(void *, const void *)
Should not be used.
void *(* CopyIterator_t)(void *dest, const void *source)
virtual ULong_t GetIncrement() const
Return the offset between two consecutive value_types (memory layout).
Sizing_t fResize
Container accessors: resize container.
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
size_t fSize
fSize of the contained object
virtual int TypeInfo_Size(TypeInfo_t *) const
Definition: TInterpreter.h:487
void(* DeleteIterator_t)(void *iter)
virtual Int_t GetCollectionType() const
Return the type of collection see TClassEdit::ESTLType.
virtual void DeleteItem(Bool_t force, void *ptr) const
Call to delete/destruct individual item.
void * TGenCollectionProxy__SlowNext(void *iter, const void *end)
void * TGenCollectionProxy__VectorNext(void *, const void *)
Should not be used.
TObjArray * fReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read)
CopyIterator_t fFunctionCopyIterator
THashTable implements a hash table to store TObject&#39;s.
Definition: THashTable.h:39
void TGenCollectionProxy__SlowCreateIterators(void *, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:36
static TGenCollectionProxy::Value * R__CreateValue(const std::string &name, Bool_t silent)
Utility routine to issue a Fatal error is the Value object is not valid.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)
See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena); begin_...
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)
Return the set of action necessary to stream in this collection member-wise coming from the old value...
virtual void TypeInfo_Delete(TypeInfo_t *) const
Definition: TInterpreter.h:478
void TGenCollectionProxy__SlowDeleteTwoIterators(void *, void *)
Nothing to do.
virtual Bool_t TypeInfo_IsValid(TypeInfo_t *) const
Definition: TInterpreter.h:483
virtual UInt_t Size() const
Return the current size of the container.
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:468
Proxies_t fProxyList
Stack of recursive proxies.
Method fClear
Method cache for container accessors: clear container.
Method0 fCreateEnv
Method to allocate an Environment holder.
ArrIterfunc_t fConstruct
Container accessors: block construct.
virtual void Streamer(TBuffer &refBuffer)
Streamer Function.
void Error(const char *location, const char *msgfmt,...)
Staged_t fStaged
Optimization: Keep staged array once they were created.
void MayNotUse(const char *method)
This function can be used in classes that should override a certain function, but in the inherited cl...
Definition: TError.cxx:269
void TGenCollectionProxy__StagingDeleteTwoIterators(void *, void *)
Nothing to do.
virtual EDataType GetType() const
If the content is a simple numerical value, return its type (see TDataType)
int fValOffset
Offset from key to value (in maps)
Small helper to save proxy environment in the event of recursive calls.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
int fSTL_type
STL container type.
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4356
SVector< double, 2 > v
Definition: Dict.h:5
#define dest(otri, vertexptr)
Definition: triangle.c:1040
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
virtual void TypeInfo_Init(TypeInfo_t *, const char *) const
Definition: TInterpreter.h:482
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for version number &#39;version&#39; to this clas...
Definition: TClass.cxx:6633
virtual void Commit(void *env)
Commit the change.
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
void *(* fCopyIterator)(void *dest, const void *source)
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual Long_t TypeInfo_Property(TypeInfo_t *) const
Definition: TInterpreter.h:485
virtual void PushProxy(void *objstart)
Add an object.
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)
See typedef void* (*Next_t)(void *iter, void *end); iter and end should be pointer to respectively an...
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
CreateIterators_t fFunctionCreateIterators
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
int fValDiff
Offset between two consecutive value_types (memory layout).
void TGenCollectionProxy__SlowDeleteSingleIterators(void *)
Nothing to do.
#define R__LOCKGUARD2(mutex)
PyObject * fType
long Long_t
Definition: RtypesCore.h:50
virtual void Resize(UInt_t n, Bool_t force_delete)
Resize the container.
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)
See typedef void (*DeleteIterator_t)(void *iter); If the sizeof iterator is greater than fgIteratorAr...
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)
See typedef void (*DeleteTwoIterators_t)(void *begin, void *end); If the sizeof iterator is greater t...
virtual TGenCollectionProxy * InitializeEx(Bool_t silent)
Proxy initializer.
unsigned long ULong_t
Definition: RtypesCore.h:51
void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
EDataType
Definition: TDataType.h:30
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
void CheckFunctions() const
Check existence of function pointers.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2882
std::atomic< Value * > fValue
Descriptor of the container value type.
TClassRef fType
TClass reference of Value_type in collection.
virtual void Clear(const char *opt="")
Clear the emulated collection.
virtual void ReadBuffer(TBuffer &b, void *obj)
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)
See typedef void (*CopyIterator_t)(void *&dest, const void *source); Copy the iterator source...
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2811
virtual TClass * GetValueClass() const
Return a pointer to the TClass representing the content.
Value(const std::string &info, Bool_t silent)
Constructor.
virtual void * At(UInt_t idx)
Return the address of the value at index &#39;idx&#39;.
Int_t Size() const
Get size of basic typedef&#39;ed type.
Definition: TDataType.cxx:366
void * TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
TClass * GetClass() const
Definition: TClassRef.h:75
Value * fKey
Descriptor of the key_type.
virtual void operator()(TBuffer &refBuffer, void *pObject)
TClassStreamer IO overload.
void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
void *(* fCollectFunc)(void *, void *)
Small helper to stage the content of an associative container when reading and before inserting it in...
Proxy around an arbitrary container, which implements basic functionality and iteration.
EnvironBase_t * fEnv
Address of the currently proxied object.
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Sizing_t fDestruct
Container accessors: block destruct.
void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
We can safely assume that the std::vector layout does not really depend on the content! ...
Bool_t IsValid()
Return true if the Value has been properly initialized.
void(* fDeleteTwoIterators)(void *begin, void *end)
Method fNext
Container accessors: generic iteration: next.
void *(* Next_t)(void *iter, const void *end)
double result[121]
Info_t fTypeinfo
Type information.
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:517
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:540
Abstract Interface class describing Streamer information for one class.
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual TClass * GetCollectionClass() const
Return a pointer to the TClass representing the container.
void(* DeleteTwoIterators_t)(void *begin, void *end)
virtual UInt_t Sizeof() const
Return the sizeof the collection object.
const std::type_info & Info_t
const Int_t n
Definition: legend1.C:16
void(* fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
TStreamerInfoActions::TActionSequence * fWriteMemberWise
char name[80]
Definition: TGX11.cxx:109
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5344
Small helper to describe the Value_type or the key_type of an STL container.
void TGenCollectionProxy__VectorDeleteSingleIterators(void *)
Nothing to do.
const char * Value
Definition: TXMLSetup.cxx:73
virtual ~TGenCollectionProxy()
Standard destructor.
virtual void * Allocate(UInt_t n, Bool_t forceDelete)
Allocate the needed space.
Value * fVal
Descriptor of the Value_type.
virtual UInt_t Size() const =0
T1 fFirst
Definition: X11Events.mm:86