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