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