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