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