ROOT  6.06/09
Reference Guide
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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) {
296  TPushPop helper(proxy,fKey->fCase&kIsPointer ? *(void**)ptr : ptr);
297  proxy->Clear("force");
298  }
299  if ( fVal->fProperties&kNeedDelete) {
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" ) {
332  fType = TClass::GetClass("string");
333  fCtor = fType->GetNew();
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()) {
361  }
362  }
363  fCase |= kIsClass;
364  fCtor = fType->GetNew();
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 
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 {
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)) {
475  }
476  }
477  gCling->TypeInfo_Delete(ti);
478  }
479  }
480  if (fType) {
482  if (proxy && (proxy->GetProperties() & 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 
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].c_str());
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;
957 }
958 
959 ////////////////////////////////////////////////////////////////////////////////
960 /// Return a pointer to the TClass representing the content.
961 
963 {
964  if (!fValue.load()) Initialize(kFALSE);
965  return fValue.load() ? (*fValue).fType.GetClass() : 0;
966 }
967 
968 ////////////////////////////////////////////////////////////////////////////////
969 /// Update the internal ValueClass when a TClass constructor need to
970 /// replace an emulated TClass by the real TClass.
971 
972 void TGenCollectionProxy::UpdateValueClass(const TClass *oldValueType, TClass *newValueType)
973 {
974  // Note that we do not need to update anything if we have not yet been
975  // initialized. In addition (see ROOT-6040) doing an initialization here
976  // might hence a nested dlopen (due to autoloading).
977  if (fValue.load() && (*fValue).fType == oldValueType) {
978  // Set pointer to the TClass representing the content.
979  (*fValue).fType = newValueType;
980  }
981 }
982 
983 ////////////////////////////////////////////////////////////////////////////////
984 /// If the content is a simple numerical value, return its type (see TDataType)
985 
987 {
988  if ( !fValue.load() ) Initialize(kFALSE);
989  return (*fValue).fKind;
990 }
991 
992 ////////////////////////////////////////////////////////////////////////////////
993 /// Return the address of the value at index 'idx'
994 
996 {
997  if ( fEnv && fEnv->fObject ) {
998  switch (fSTL_type) {
999  case ROOT::kSTLvector:
1000  if ((*fValue).fKind == kBool_t) {
1001  auto vec = (std::vector<bool> *)(fEnv->fObject);
1002  fEnv->fLastValueVecBool = (*vec)[idx];
1003  fEnv->fIdx = idx;
1004  return &(fEnv->fLastValueVecBool);
1005  }
1006  fEnv->fIdx = idx;
1007  switch( idx ) {
1008  case 0:
1009  return fEnv->fStart = fFirst.invoke(fEnv);
1010  default:
1011  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1012  return ((char*)fEnv->fStart) + fValDiff*idx;
1013  }
1014  case ROOT::kSTLbitset: {
1015  switch (idx) {
1016  case 0:
1018  fEnv->fIdx = idx;
1019  break;
1020  default:
1021  fEnv->fIdx = idx - fEnv->fIdx;
1022  if (!fEnv->fStart) fEnv->fStart = fFirst.invoke(fEnv);
1023  fNext.invoke(fEnv);
1024  fEnv->fIdx = idx;
1025  break;
1026  }
1027  typedef ROOT::TCollectionProxyInfo::Environ <std::pair<size_t, Bool_t>> EnvType_t;
1028  EnvType_t *e = (EnvType_t *) fEnv;
1029  return &(e->fIterator.second);
1030  }
1031  case ROOT::kSTLset:
1033  case ROOT::kSTLmultiset:
1035  case ROOT::kSTLmap:
1037  case ROOT::kSTLmultimap:
1039  if ( fEnv->fUseTemp ) {
1040  return (((char*)fEnv->fTemp)+idx*fValDiff);
1041  }
1042  // Intentional fall through.
1043  default:
1044  switch( idx ) {
1045  case 0:
1046  fEnv->fIdx = idx;
1047  return fEnv->fStart = fFirst.invoke(fEnv);
1048  default: {
1049  fEnv->fIdx = idx - fEnv->fIdx;
1050  if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1051  void* result = fNext.invoke(fEnv);
1052  fEnv->fIdx = idx;
1053  return result;
1054  }
1055  }
1056  }
1057  }
1058  Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1059  return 0;
1060 }
1061 
1062 ////////////////////////////////////////////////////////////////////////////////
1063 /// Clear the emulated collection.
1064 
1065 void TGenCollectionProxy::Clear(const char* opt)
1066 {
1067  if ( fEnv && fEnv->fObject ) {
1068  if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1069  size_t i, n = *(size_t*)fSize.invoke(fEnv);
1070  if ( n > 0 ) {
1071  for (i=0; i<n; ++i)
1073  }
1074  }
1075  fClear.invoke(fEnv);
1076  }
1077 }
1078 
1079 ////////////////////////////////////////////////////////////////////////////////
1080 /// Return the current size of the container
1081 
1083 {
1084  if ( fEnv && fEnv->fObject ) {
1085  if (fEnv->fUseTemp) {
1086  return fEnv->fSize;
1087  } else {
1088  return *(size_t*)fSize.invoke(fEnv);
1089  }
1090  }
1091  Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1092  return 0;
1093 }
1094 
1095 ////////////////////////////////////////////////////////////////////////////////
1096 /// Resize the container
1097 
1099 {
1100  if ( fEnv && fEnv->fObject ) {
1101  if ( force && fPointers ) {
1102  size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1103  if ( n != nold ) {
1104  for (i=n; i<nold; ++i)
1105  DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1106  }
1107  }
1108  MESSAGE(3, "Resize(n)" );
1109  fEnv->fSize = n;
1111  return;
1112  }
1113  Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1114 }
1115 
1116 ////////////////////////////////////////////////////////////////////////////////
1117 /// Allocate the needed space.
1118 /// For associative collection, this returns a TStaging object that
1119 /// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1120 
1121 void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t /* forceDelete */ )
1122 {
1123  if ( fEnv && fEnv->fObject ) {
1124  switch ( fSTL_type ) {
1125  case ROOT::kSTLset:
1127  case ROOT::kSTLmultiset:
1129  case ROOT::kSTLmap:
1131  case ROOT::kSTLmultimap:
1133  if ( (fProperties & kNeedDelete) )
1134  Clear("force");
1135  else
1136  fClear.invoke(fEnv);
1137  // Commit no longer use the environment and thus no longer decrease
1138  // the count. Consequently we no longer should increase it here.
1139  // ++fEnv->fRefCount;
1140  fEnv->fSize = n;
1141 
1142  TStaging *s;
1143  if (fStaged.empty()) {
1144  s = new TStaging(n,fValDiff);
1145  } else {
1146  s = fStaged.back();
1147  fStaged.pop_back();
1148  s->Resize(n);
1149  }
1150  fConstruct(s->GetContent(),s->GetSize());
1151 
1152  s->SetTarget(fEnv->fObject);
1153 
1154  fEnv->fTemp = s->GetContent();
1155  fEnv->fUseTemp = kTRUE;
1156  fEnv->fStart = fEnv->fTemp;
1157 
1158  return s;
1159  }
1160  case ROOT::kSTLvector:
1161  case ROOT::kSTLlist:
1162  case ROOT::kSTLforwardlist:
1163  case ROOT::kSTLdeque:
1164  if( (fProperties & kNeedDelete) ) {
1165  Clear("force");
1166  }
1167  fEnv->fSize = n;
1168  fResize(fEnv->fObject,n);
1169  return fEnv->fObject;
1170 
1171  case ROOT::kSTLbitset: {
1172  TStaging *s;
1173  if (fStaged.empty()) {
1174  s = new TStaging(n,fValDiff);
1175  } else {
1176  s = fStaged.back();
1177  fStaged.pop_back();
1178  s->Resize(n);
1179  }
1180  s->SetTarget(fEnv->fObject);
1181 
1182  fEnv->fTemp = s->GetContent();
1183  fEnv->fUseTemp = kTRUE;
1184  fEnv->fStart = fEnv->fTemp;
1185 
1186  return s;
1187  }
1188  }
1189  }
1190  return 0;
1191 }
1192 
1193 ////////////////////////////////////////////////////////////////////////////////
1194 /// Insert data into the container where data is a C-style array of the actual type contained in the collection
1195 /// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1196 
1197 void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1198 {
1199  fFeed((void*)data,container,size);
1200 }
1201 
1202 ////////////////////////////////////////////////////////////////////////////////
1203 /// Commit the change.
1204 
1206 {
1207  if (fProperties & kIsAssociative) {
1208 // case ROOT::kSTLmap:
1209 // case ROOT::kSTLmultimap:
1210 // case ROOT::kSTLset:
1211 // case ROOT::kSTLmultiset:
1212  if ( from ) {
1213  TStaging *s = (TStaging*) from;
1214  if ( s->GetTarget() ) {
1215  fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1216  }
1217  fDestruct(s->GetContent(),s->GetSize());
1218  s->SetTarget(0);
1219  fStaged.push_back(s);
1220  }
1221  }
1222 }
1223 
1224 ////////////////////////////////////////////////////////////////////////////////
1225 /// Add an object.
1226 
1228 {
1229  if ( !fValue.load() ) Initialize(kFALSE);
1230  if ( !fProxyList.empty() ) {
1231  EnvironBase_t* back = fProxyList.back();
1232  if ( back->fObject == objstart ) {
1233  ++back->fRefCount;
1234  fProxyList.push_back(back);
1235  fEnv = back;
1236  return;
1237  }
1238  }
1239  EnvironBase_t* e = 0;
1240  if ( fProxyKept.empty() ) {
1242  e->fTemp = 0;
1243  e->fUseTemp = kFALSE;
1244  }
1245  else {
1246  e = fProxyKept.back();
1247  fProxyKept.pop_back();
1248  }
1249  e->fSize = 0;
1250  e->fRefCount = 1;
1251  e->fObject = objstart;
1252  e->fStart = 0;
1253  e->fIdx = 0;
1254  // ::memset(e->buff,0,sizeof(e->buff));
1255  fProxyList.push_back(e);
1256  fEnv = e;
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// Remove the last object.
1261 
1263 {
1264  if ( !fProxyList.empty() ) {
1265  EnvironBase_t* e = fProxyList.back();
1266  if ( --e->fRefCount <= 0 ) {
1267  fProxyKept.push_back(e);
1268  e->fUseTemp = kFALSE;
1269  }
1270  fProxyList.pop_back();
1271  }
1272  fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1273 }
1274 
1275 ////////////////////////////////////////////////////////////////////////////////
1276 /// Call to delete/destruct individual item.
1277 
1278 void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
1279 {
1280  if ( force && ptr ) {
1281  switch (fSTL_type) {
1282  case ROOT::kSTLmap:
1283  case ROOT::kSTLmultimap: {
1284  if ( fKey->fCase&kIsPointer ) {
1285  if (fKey->fProperties&kNeedDelete) {
1287  TPushPop helper(proxy,*(void**)ptr);
1288  proxy->Clear("force");
1289  }
1290  fKey->DeleteItem(*(void**)ptr);
1291  } else {
1292  if (fKey->fProperties&kNeedDelete) {
1294  TPushPop helper(proxy,ptr);
1295  proxy->Clear("force");
1296  }
1297  }
1298  char *addr = ((char*)ptr)+fValOffset;
1299  if ( fVal->fCase&kIsPointer ) {
1300  if ( fVal->fProperties&kNeedDelete) {
1302  TPushPop helper(proxy,*(void**)addr);
1303  proxy->Clear("force");
1304  }
1305  fVal->DeleteItem(*(void**)addr);
1306  } else {
1307  if ( fVal->fProperties&kNeedDelete) {
1309  TPushPop helper(proxy,addr);
1310  proxy->Clear("force");
1311  }
1312  }
1313  break;
1314  }
1315  default: {
1316  if ( fVal->fCase&kIsPointer ) {
1317  if (fVal->fProperties&kNeedDelete) {
1319  TPushPop helper(proxy,*(void**)ptr);
1320  proxy->Clear("force");
1321  }
1322  fVal->DeleteItem(*(void**)ptr);
1323  } else {
1324  if (fVal->fProperties&kNeedDelete) {
1326  TPushPop helper(proxy,ptr);
1327  proxy->Clear("force");
1328  }
1329  }
1330  break;
1331  }
1332  }
1333  }
1334 }
1335 
1336 ////////////////////////////////////////////////////////////////////////////////
1337 
1338 void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1339 {
1340  MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1341 }
1342 
1343 ////////////////////////////////////////////////////////////////////////////////
1344 
1345 void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1346 {
1347  MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1348 }
1349 
1350 ////////////////////////////////////////////////////////////////////////////////
1351 /// Streamer Function.
1352 
1354 {
1355  if ( fEnv ) {
1356  GetCollectionClass()->Streamer( fEnv->fObject, buff );
1357  return;
1358  }
1359  Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1360 }
1361 
1362 ////////////////////////////////////////////////////////////////////////////////
1363 /// Streamer I/O overload
1364 
1365 void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1366 {
1367  TPushPop env(this, objp);
1368  Streamer(buff);
1369 }
1370 
1371 ////////////////////////////////////////////////////////////////////////////////
1372 /// TClassStreamer IO overload
1373 
1375 {
1376  Streamer(b, objp, 0);
1377 }
1378 
1379 
1380 struct TGenCollectionProxy__SlowIterator {
1381  TVirtualCollectionProxy *fProxy;
1382  UInt_t fIndex;
1383  TGenCollectionProxy__SlowIterator(TVirtualCollectionProxy *proxy) : fProxy(proxy), fIndex(0) {}
1384 };
1385 
1386 ////////////////////////////////////////////////////////////////////////////////
1387 
1388 void TGenCollectionProxy__SlowCreateIterators(void * /* collection */, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
1389 {
1390  new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1391  *(UInt_t*)*end_arena = proxy->Size();
1392 }
1393 
1394 ////////////////////////////////////////////////////////////////////////////////
1395 
1396 void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1397 {
1398  TGenCollectionProxy__SlowIterator *iterator = (TGenCollectionProxy__SlowIterator*)iter;
1399  if (iterator->fIndex != *(UInt_t*)end) {
1400  void *result = iterator->fProxy->At(iterator->fIndex);
1401  ++(iterator->fIndex);
1402  return result;
1403  } else {
1404  return 0;
1405  }
1406 }
1407 
1408 ////////////////////////////////////////////////////////////////////////////////
1409 
1410 void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
1411 {
1412  *(TGenCollectionProxy__SlowIterator*)dest = *(TGenCollectionProxy__SlowIterator*)source;
1413  return dest;
1414 }
1415 
1416 ////////////////////////////////////////////////////////////////////////////////
1417 /// Nothing to do
1418 
1420 {
1421 }
1422 
1423 ////////////////////////////////////////////////////////////////////////////////
1424 /// Nothing to do
1425 
1427 {
1428 }
1429 
1430 
1431 ////////////////////////////////////////////////////////////////////////////////
1432 /// We can safely assume that the std::vector layout does not really depend on
1433 /// the content!
1434 
1435 void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy*)
1436 {
1437  std::vector<char> *vec = (std::vector<char>*)obj;
1438  if (vec->empty()) {
1439  *begin_arena = 0;
1440  *end_arena = 0;
1441  return;
1442  }
1443  *begin_arena = &(*vec->begin());
1444 #ifdef R__VISUAL_CPLUSPLUS
1445  *end_arena = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
1446 #else
1447  // coverity[past_the_end] Safe on other platforms
1448  *end_arena = &(*vec->end());
1449 #endif
1450 
1451 }
1452 
1453 ////////////////////////////////////////////////////////////////////////////////
1454 /// Should not be used.
1455 
1456 void *TGenCollectionProxy__VectorNext(void *, const void *)
1457 {
1458  R__ASSERT(0);
1459  return 0;
1460 }
1461 
1462 ////////////////////////////////////////////////////////////////////////////////
1463 
1464 void *TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
1465 {
1466  *(void**)dest = *(void**)source;
1467  return dest;
1468 }
1469 
1470 ////////////////////////////////////////////////////////////////////////////////
1471 /// Nothing to do
1472 
1474 {
1475 }
1476 
1477 ////////////////////////////////////////////////////////////////////////////////
1478 /// Nothing to do
1479 
1481 {
1482 }
1483 
1484 
1485 
1486 ////////////////////////////////////////////////////////////////////////////////
1487 
1488 void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
1489 {
1491  *begin_arena = s->GetContent();
1492  *end_arena = s->GetEnd();
1493 }
1494 
1495 ////////////////////////////////////////////////////////////////////////////////
1496 /// Should not be used.
1497 
1498 void *TGenCollectionProxy__StagingNext(void *, const void *)
1499 {
1500  R__ASSERT(0);
1501  return 0;
1502 }
1503 
1504 ////////////////////////////////////////////////////////////////////////////////
1505 
1506 void *TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
1507 {
1508  *(void**)dest = *(void**)source;
1509  return dest;
1510 }
1511 
1512 ////////////////////////////////////////////////////////////////////////////////
1513 /// Nothing to do
1514 
1516 {
1517 }
1518 
1519 ////////////////////////////////////////////////////////////////////////////////
1520 /// Nothing to do
1521 
1523 {
1524 }
1525 
1526 
1527 ////////////////////////////////////////////////////////////////////////////////
1528 /// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1529 /// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1530 /// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1531 /// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1532 
1534 {
1535  if (read) {
1536  if ( !fValue.load() ) InitializeEx(kFALSE);
1537  if ( (fProperties & kIsAssociative) && read)
1539  }
1540 
1542 
1543  if ( !fValue.load() ) InitializeEx(kFALSE);
1544 
1545 // fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1546 // if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1547 // fprintf(stderr,"vector/emulated iterator\n");
1548 // else if ( (fProperties & kIsAssociative) && read)
1549 // fprintf(stderr,"an associative read iterator\n");
1550 // else
1551 // fprintf(stderr,"a generic iterator\n");
1552 
1555  else if ( (fProperties & kIsAssociative) && read)
1557  else
1559 }
1560 
1561 ////////////////////////////////////////////////////////////////////////////////
1562 /// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1563 /// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1564 /// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1565 /// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1566 
1568 {
1569  if (read) {
1570  if ( !fValue.load() ) InitializeEx(kFALSE);
1571  if ( (fProperties & kIsAssociative) && read)
1573  }
1574 
1576 
1577  if ( !fValue.load() ) InitializeEx(kFALSE);
1578 
1581  else if ( (fProperties & kIsAssociative) && read)
1583  else
1585 }
1586 
1587 ////////////////////////////////////////////////////////////////////////////////
1588 /// See typedef void* (*Next_t)(void *iter, void *end);
1589 /// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1590 /// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1591 /// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1592 /// which case 'Next' will return the value of the pointer.
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 (*DeleteIterator_t)(void *iter);
1616 /// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1617 /// Otherwise just call the iterator's destructor.
1618 
1620 {
1621  if (read) {
1622  if ( !fValue.load() ) InitializeEx(kFALSE);
1623  if ( (fProperties & kIsAssociative) && read)
1625  }
1626 
1628 
1629  if ( !fValue.load() ) InitializeEx(kFALSE);
1630 
1633  else if ( (fProperties & kIsAssociative) && read)
1635  else
1637 }
1638 
1639 ////////////////////////////////////////////////////////////////////////////////
1640 /// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1641 /// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1642 /// Otherwise just call the iterator's destructor.
1643 
1645 {
1646  if (read) {
1647  if ( !fValue.load() ) InitializeEx(kFALSE);
1648  if ( (fProperties & kIsAssociative) && read)
1650  }
1651 
1653 
1654  if ( !fValue.load() ) InitializeEx(kFALSE);
1655 
1658  else if ( (fProperties & kIsAssociative) && read)
1660  else
1662 }
1663 
1664 ////////////////////////////////////////////////////////////////////////////////
1665 /// Return the set of action necessary to stream in this collection member-wise coming from
1666 /// the old value class layout refered to by 'version'.
1667 
1669 {
1670  if (oldClass == 0) {
1671  return 0;
1672  }
1673  TObjArray* arr = 0;
1676  std::map<std::string, TObjArray*>::iterator it;
1677 
1678  it = fConversionReadMemberWise->find( oldClass->GetName() );
1679 
1680  if( it != fConversionReadMemberWise->end() ) {
1681  arr = it->second;
1682  }
1683 
1684  if (arr) {
1685  result = (TStreamerInfoActions::TActionSequence *)arr->At(version);
1686  if (result) {
1687  return result;
1688  }
1689  }
1690  }
1691 
1692  // Need to create it.
1693  TClass *valueClass = GetValueClass();
1694  if (valueClass == 0) {
1695  return 0;
1696  }
1697  TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1698  if (info == 0) {
1699  return 0;
1700  }
1702 
1703  if (!arr) {
1704  arr = new TObjArray(version+10, -1);
1706  fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1707  }
1708  (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1709  }
1710  arr->AddAtAndExpand( result, version );
1711 
1712  return result;
1713 }
1714 
1715 ////////////////////////////////////////////////////////////////////////////////
1716 /// Return the set of action necessary to stream in this collection member-wise coming from
1717 /// the old value class layout refered to by 'version'.
1718 
1720 {
1722  if (version < (fReadMemberWise->GetSize()-1)) { // -1 because the 'index' starts at -1
1724  }
1725  if (result == 0) {
1726  // Need to create it.
1727  TClass *valueClass = GetValueClass();
1728  TVirtualStreamerInfo *info = 0;
1729  if (valueClass) {
1730  info = valueClass->GetStreamerInfo(version);
1731  }
1733  fReadMemberWise->AddAtAndExpand(result,version);
1734  }
1735  return result;
1736 }
1737 
1738 ////////////////////////////////////////////////////////////////////////////////
1739 /// Return the set of action necessary to stream out this collection member-wise.
1740 
1742 {
1744  if (result == 0) {
1745  // Need to create it.
1746  TClass *valueClass = GetValueClass();
1747  TVirtualStreamerInfo *info = 0;
1748  if (valueClass) {
1749  info = valueClass->GetStreamerInfo();
1750  }
1753  }
1754  return result;
1755 }
Method fSize
Container accessors: size of container.
double read(const std::string &file_name)
reading
void * TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
DeleteIterator_t fFunctionDeleteIterator
void TGenCollectionProxy__StagingDeleteSingleIterators(void *)
Nothing to do.
ROOT::DelFunc_t fDelete
Method cache for containee delete.
An array of TObjects.
Definition: TObjArray.h:39
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...
virtual Int_t GetProperties() const
Proxies_t fProxyKept
Optimization: Keep proxies once they were created.
virtual TVirtualCollectionProxy * Generate() const
Virtual copy constructor.
DeleteTwoIterators_t fFunctionDeleteTwoIterators
void * invoke(void *obj) const
void *(* fNext)(void *iter, const void *end)
UInt_t fProperties
Additional properties of the value type (kNeedDelete)
void *(* fConstructFunc)(void *, size_t)
void TGenCollectionProxy__VectorDeleteTwoIterators(void *, void *)
Nothing to do.
virtual void UpdateValueClass(const TClass *oldcl, TClass *newcl)
Update the internal ValueClass when a TClass constructor need to replace an emulated TClass by the re...
Int_t GetType() const
Definition: TDataType.h:70
void Fatal(const char *location, const char *msgfmt,...)
Bool_t fPointers
Flag to indicate if containee has pointers (key or value)
std::map< std::string, TObjArray * > * fConversionReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read) derived from another class...
TGenCollectionProxy * Initialize(Bool_t silent) const
Proxy initializer.
Collectfunc_t fCollect
Method to collect objects from container.
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition: TClass.cxx:6917
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 splited type.
Definition: TClassEdit.cxx:937
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
#define assert(cond)
Definition: unittest.h:542
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()
Return the set of action necessary to stream out this collection member-wise.
virtual void PopProxy()
Remove the last object.
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:98
#define gROOT
Definition: TROOT.h:340
virtual TypeInfo_t * TypeInfo_Factory() const
Definition: TInterpreter.h:466
TClass * fOnFileClass
On file class.
Feedfunc_t fFeed
Container accessors: block feed.
void *(* fFeedFunc)(void *, void *, size_t)
int Int_t
Definition: RtypesCore.h:41
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition: TClass.cxx:6885
bool Bool_t
Definition: RtypesCore.h:59
virtual void Clear(const char *opt="")=0
const Bool_t kFALSE
Definition: Rtypes.h:92
#define MESSAGE(which, text)
UInt_t fCase
type of data of Value_type
virtual Bool_t HasPointers() const
Return true if the content is of type 'pointer to'.
void * TGenCollectionProxy__StagingNext(void *, const void *)
Should not be used.
void *(* CopyIterator_t)(void *dest, const void *source)
ClassImp(TIterator) Bool_t TIterator return false
Compare two iterator objects.
Definition: TIterator.cxx:20
virtual ULong_t GetIncrement() const
Return the offset between two consecutive value_types (memory layout).
Sizing_t fResize
Container accessors: resize container.
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
size_t fSize
fSize of the contained object
virtual int TypeInfo_Size(TypeInfo_t *) const
Definition: TInterpreter.h:474
void(* DeleteIterator_t)(void *iter)
virtual Int_t GetCollectionType() const
Return the type of collection see TClassEdit::ESTLType.
virtual void DeleteItem(Bool_t force, void *ptr) const
Call to delete/destruct individual item.
void * TGenCollectionProxy__SlowNext(void *iter, const void *end)
void * TGenCollectionProxy__VectorNext(void *, const void *)
Should not be used.
TObjArray * fReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read)
CopyIterator_t fFunctionCopyIterator
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:39
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:36
static TGenCollectionProxy::Value * R__CreateValue(const std::string &name, Bool_t silent)
Utility routine to issue a Fatal error is the Value object is not valid.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)
See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena); begin_...
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)
Return the set of action necessary to stream in this collection member-wise coming from the old value...
virtual void TypeInfo_Delete(TypeInfo_t *) const
Definition: TInterpreter.h:465
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
void TGenCollectionProxy__SlowDeleteTwoIterators(void *, void *)
Nothing to do.
virtual Bool_t TypeInfo_IsValid(TypeInfo_t *) const
Definition: TInterpreter.h:470
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
virtual UInt_t Size() const
Return the current size of the container.
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:467
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,...)
EDataType fKind
kind of ROOT-fundamental type
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThiObject.
Definition: TClass.cxx:6901
Staged_t fStaged
Optimization: Keep staged array once they were created.
void MayNotUse(const char *method)
This function can be used in classes that should override a certain function, but in the inherited cl...
Definition: TError.cxx:269
void TGenCollectionProxy__StagingDeleteTwoIterators(void *, void *)
Nothing to do.
virtual EDataType GetType() const
If the content is a simple numerical value, return its type (see TDataType)
int fValOffset
Offset from key to value (in maps)
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:221
int fSTL_type
STL container type.
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4337
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
virtual void TypeInfo_Init(TypeInfo_t *, const char *) const
Definition: TInterpreter.h:469
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6614
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 '...
void *(* fCopyIterator)(void *dest, const void *source)
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual Long_t TypeInfo_Property(TypeInfo_t *) const
Definition: TInterpreter.h:472
virtual void PushProxy(void *objstart)
Add an object.
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)
See typedef void* (*Next_t)(void *iter, void *end); iter and end should be pointer to respectively an...
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
CreateIterators_t fFunctionCreateIterators
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
int fValDiff
Offset between two consecutive value_types (memory layout).
void TGenCollectionProxy__SlowDeleteSingleIterators(void *)
Nothing to do.
PyObject * fType
long Long_t
Definition: RtypesCore.h:50
virtual void Resize(UInt_t n, Bool_t force_delete)
Resize the container.
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)
See typedef void (*DeleteIterator_t)(void *iter); If the sizeof iterator is greater than fgIteratorAr...
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)
See typedef void (*DeleteTwoIterators_t)(void *begin, void *end); If the sizeof iterator is greater t...
virtual TGenCollectionProxy * InitializeEx(Bool_t silent)
Proxy initializer.
unsigned long ULong_t
Definition: RtypesCore.h:51
void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
EDataType
Definition: TDataType.h:30
void CheckFunctions() const
Check existence of function pointers.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
std::atomic< Value * > fValue
Descriptor of the container value type.
TClassRef fType
TClass reference of Value_type in collection.
virtual void Clear(const char *opt="")
Clear the emulated collection.
virtual void ReadBuffer(TBuffer &b, void *obj)
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)
See typedef void (*CopyIterator_t)(void *&dest, const void *source); Copy the iterator source...
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2810
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual TClass * GetValueClass() const
Return a pointer to the TClass representing the content.
Value(const std::string &info, Bool_t silent)
Constructor.
virtual void * At(UInt_t idx)
Return the address of the value at index 'idx'.
Int_t Size() const
Get size of basic typedef'ed type.
Definition: TDataType.cxx:366
void * TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
TClass * GetClass() const
Definition: TClassRef.h:75
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.
EnvironBase_t * fEnv
Address of the currently proxied object.
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
Sizing_t fDestruct
Container accessors: block destruct.
void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
We can safely assume that the std::vector layout does not really depend on the content! ...
Bool_t IsValid()
Return true if the Value has been properly initialized.
void(* fDeleteTwoIterators)(void *begin, void *end)
Method fNext
Container accessors: generic iteration: next.
void *(* Next_t)(void *iter, const void *end)
double result[121]
Info_t fTypeinfo
Type information.
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:504
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:540
Abstract Interface class describing Streamer information for one class.
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
virtual TClass * GetCollectionClass() const
Return a pointer to the TClass representing the container.
void(* DeleteTwoIterators_t)(void *begin, void *end)
virtual UInt_t Sizeof() const
Return the sizeof the collection object.
const std::type_info & Info_t
const Int_t n
Definition: legend1.C:16
void(* fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
TStreamerInfoActions::TActionSequence * fWriteMemberWise
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5325
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.
T1 fFirst
Definition: X11Events.mm:85
ROOT::DesFunc_t fDtor
Method cache for containee destructor.