Logo ROOT   6.16/01
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"
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"
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
34Local optimization class.
35
36Collection proxies get copied. On copy we switch the type of the
37proxy to the concrete STL type. The concrete types are optimized
38for element access.
39*/
40
41class TGenVectorProxy : public TGenCollectionProxy {
42public:
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
84Local optimization class.
85
86Collection proxies get copied. On copy we switch the type of the
87proxy to the concrete STL type. The concrete types are optimized
88for element access.
89*/
90class TGenVectorBoolProxy : public TGenCollectionProxy {
91 Bool_t fLastValue;
92
93public:
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//////////////////////////////////////////////////////////////////////////
137class TGenBitsetProxy : public TGenCollectionProxy {
138
139public:
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
186Local optimization class.
187
188Collection proxies get copied. On copy we switch the type of the
189proxy to the concrete STL type. The concrete types are optimized
190for element access.
191**/
192
193class TGenListProxy : public TGenVectorProxy {
194public:
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
228Localoptimization class.
229
230Collection proxies get copied. On copy we switch the type of the
231proxy to the concrete STL type. The concrete types are optimized
232for element access.
233*/
234
235class TGenSetProxy : public TGenVectorProxy {
236public:
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
273Localoptimization class.
274
275Collection proxies get copied. On copy we switch the type of the
276proxy to the concrete STL type. The concrete types are optimized
277for element access.
278*/
279
280class TGenMapProxy : public TGenSetProxy {
281public:
282 // Standard Destructor
283 TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c)
284{
285 }
286 // Standard Destructor
287 virtual ~TGenMapProxy()
288{
289 }
290 // Call to delete/destruct individual item
291 virtual void DeleteItem(Bool_t force, void* ptr) const
292 {
293 if (force) {
294 if ( fKey->fProperties&kNeedDelete) {
296 TPushPop helper(proxy,fKey->fCase&kIsPointer ? *(void**)ptr : ptr);
297 proxy->Clear("force");
298 }
299 if ( fVal->fProperties&kNeedDelete) {
301 char *addr = ((char*)ptr)+fValOffset;
302 TPushPop helper(proxy,fVal->fCase&kIsPointer ? *(void**)addr : addr);
303 proxy->Clear("force");
304 }
305 }
306 if ( fKey->fCase&kIsPointer ) {
307 fKey->DeleteItem(*(void**)ptr);
308 }
309 if ( fVal->fCase&kIsPointer ) {
310 char *addr = ((char*)ptr)+fValOffset;
311 fVal->DeleteItem(*(void**)addr);
312 }
313 }
314};
315
316////////////////////////////////////////////////////////////////////////////////
317/// Constructor.
318
319TGenCollectionProxy::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;
329 std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar );
330 if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) {
332 fType = TClass::GetClass("string");
333 fCtor = fType->GetNew();
336 switch(inside[inside.length()-1]) {
337 case '*':
338 fCase |= kIsPointer;
339 fSize = sizeof(void*);
340 break;
341 default:
342 fSize = sizeof(std::string);
343 break;
344 }
345 }
346 else {
347 // In the case where we have an emulated class,
348 // if the class is nested (in a class or a namespace),
349 // calling G__TypeInfo ti(inside.c_str());
350 // might fail because CINT does not known the nesting
351 // scope, so let's first look for an emulated class:
352
353 fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
354
355 if (fType) {
356 if (intype != inside) {
357 fCase |= kIsPointer;
358 fSize = sizeof(void*);
359 if (fType == TString::Class()) {
361 }
362 }
363 fCase |= kIsClass;
364 fCtor = fType->GetNew();
367 } else {
369
370 // Try to avoid autoparsing.
371
372 THashTable *typeTable = dynamic_cast<THashTable*>( gROOT->GetListOfTypes() );
373 THashList *enumTable = dynamic_cast<THashList*>( gROOT->GetListOfEnums() );
374
375 assert(typeTable && "The type of the list of type has changed");
376 assert(enumTable && "The type of the list of enum has changed");
377
378 TDataType *fundType = (TDataType *)typeTable->THashTable::FindObject( intype.c_str() );
379 if (fundType && fundType->GetType() < 0x17 && fundType->GetType() > 0) {
380 fKind = (EDataType)fundType->GetType();
381 // R__ASSERT((fKind>0 && fKind<0x17) || (fKind==-1&&(prop&kIsPointer)) );
382
384 if (intype != inside) {
385 fCase |= kIsPointer;
386 fSize = sizeof(void*);
387 } else {
388 fSize = fundType->Size();
389 }
390 } else if (enumTable->THashList::FindObject( intype.c_str() ) ) {
391 // This is a known enum.
392 fCase = kIsEnum;
393 fSize = sizeof(Int_t);
394 fKind = kInt_t;
395 if (intype != inside) {
396 fCase |= kIsPointer;
397 fSize = sizeof(void*);
398 }
399 } else {
400 // This fallback solution should be hardly used ...
401 // One of the common use case is to 'discover' that this is a
402 // collection for the content of which we do not have a dictionary
403 // which can happen at least in the following cases:
404 // - empty emulated collection
405 // - emulated collection of enums
406 // In those two cases there is no StreamerInfo stored in the file
407 // for the content.
408
409 // R__ASSERT("FallBack, should be hardly used.");
410
411 TypeInfo_t *ti = gCling->TypeInfo_Factory();
412 gCling->TypeInfo_Init(ti,inside.c_str());
413 if ( !gCling->TypeInfo_IsValid(ti) ) {
414 if (intype != inside) {
415 fCase |= kIsPointer;
416 fSize = sizeof(void*);
417 }
418 // Since we already search for GetClass earlier, this should
419 // never be true.
420// fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
421// if (fType) {
422// fCase |= kIsClass;
423// fCtor = fType->GetNew();
424// fDtor = fType->GetDestructor();
425// fDelete = fType->GetDelete();
426// }
427// else {
428 // either we have an Emulated enum or a really unknown class!
429 // let's just claim its an enum :(
430 fCase = kIsEnum;
431 fSize = sizeof(Int_t);
432 fKind = kInt_t;
433// }
434 }
435 else {
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();
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 }
473 if (fType == TString::Class() && (fCase&kIsPointer)) {
475 }
476 }
478 }
479 }
480 if (fType) {
482 if (proxy && (proxy->GetProperties() & kNeedDelete)) {
484 }
485 }
486 }
487 if ( fSize == std::string::npos ) {
488 if ( fType == 0 ) {
489 // The caller should check the validity by calling IsValid()
490 } else {
491 fSize = fType->Size();
492 }
493 }
494}
495
496////////////////////////////////////////////////////////////////////////////////
497/// Return true if the Value has been properly initialized.
498
500{
501
502
503 return fSize != std::string::npos;
504}
505
507{
508 // Delete an item.
509
510 if ( ptr && fCase&kIsPointer ) {
511 if ( fDelete ) {
512 (*fDelete)(ptr);
513 }
514 else if ( fType ) {
515 fType->Destructor(ptr);
516 }
517 else {
518 ::operator delete(ptr);
519 }
520 }
521}
522
523/**
524 \class TGenCollectionProxy TGenCollectionProxy.cxx
525 \ingroup IO
526
527 Proxy around an arbitrary container, which implements basic
528 functionality and iteration.
529
530 The purpose of this implementation
531 is to shield any generated dictionary implementation from the
532 underlying streamer/proxy implementation and only expose
533 the creation functions.
534
535 In particular this is used to implement splitting and abstract
536 element access of any container. Access to compiled code is necessary
537 to implement the abstract iteration sequence and functionality like
538 size(), clear(), resize(). resize() may be a void operation.
539*/
540
541////////////////////////////////////////////////////////////////////////////////
542/// Build a proxy for an emulated container.
543
546 fTypeinfo(copy.fTypeinfo)
547{
548 fEnv = 0;
549 fName = copy.fName;
550 fPointers = copy.fPointers;
551 fSTL_type = copy.fSTL_type;
552 fSize.call = copy.fSize.call;
553 fNext.call = copy.fNext.call;
554 fFirst.call = copy.fFirst.call;
555 fClear.call = copy.fClear.call;
556 fResize = copy.fResize;
557 fDestruct = copy.fDestruct;
558 fConstruct = copy.fConstruct;
559 fFeed = copy.fFeed;
560 fCollect = copy.fCollect;
562 fValOffset = copy.fValOffset;
563 fValDiff = copy.fValDiff;
564 fValue = copy.fValue.load(std::memory_order_relaxed) ? new Value(*copy.fValue) : 0;
565 fVal = copy.fVal ? new Value(*copy.fVal) : 0;
566 fKey = copy.fKey ? new Value(*copy.fKey) : 0;
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 }
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;
634 fSize.call = info.fSizeFunc;
635 fResize = info.fResizeFunc;
636 fNext.call = info.fNextFunc;
637 fFirst.call = info.fFirstFunc;
638 fClear.call = info.fClearFunc;
641 fFeed = info.fFeedFunc;
642 fCollect = info.fCollectFunc;
644
645 if (cl) {
646 fName = cl->GetName();
647 }
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 }
673}
674
675namespace {
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(std::memory_order_relaxed) ) 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:
744 return new TGenMapProxy(*this);
745 case ROOT::kSTLset:
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
805static TGenCollectionProxy::Value *R__CreateValue(const std::string &name, Bool_t silent)
806{
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:
843 case ROOT::kSTLset:
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:
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 ) {
875 fValDiff += (slong - fKey->fSize%slong)%slong;
876 fValDiff += (slong - fValDiff%slong)%slong;
877 }
878 if ( 0 == fValOffset ) {
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 ) {
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(std::memory_order_relaxed)) {
932 }
933 return fSTL_type;
934}
935
936////////////////////////////////////////////////////////////////////////////////
937/// Return the offset between two consecutive value_types (memory layout).
938
940 if (!fValue.load(std::memory_order_relaxed)) {
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(std::memory_order_relaxed) )
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 auto value = fValue.load(std::memory_order_relaxed);
976 if (!value) {
978 value = fValue.load(std::memory_order_relaxed);
979 }
980 return value ? (*value).fType.GetClass() : 0;
981}
982
983////////////////////////////////////////////////////////////////////////////////
984/// If the content is a simple numerical value, return its type (see TDataType)
985
987{
988 auto value = fValue.load(std::memory_order_relaxed);
989 if (!value) {
991 value = fValue.load(std::memory_order_relaxed);
992 }
993 return value ? (*value).fKind : kNoType_t;
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// Return the address of the value at index 'idx'
998
1000{
1001 if ( fEnv && fEnv->fObject ) {
1002 switch (fSTL_type) {
1003 case ROOT::kSTLvector:
1004 if ((*fValue).fKind == kBool_t) {
1005 auto vec = (std::vector<bool> *)(fEnv->fObject);
1006 fEnv->fLastValueVecBool = (*vec)[idx];
1007 fEnv->fIdx = idx;
1008 return &(fEnv->fLastValueVecBool);
1009 }
1010 fEnv->fIdx = idx;
1011 switch( idx ) {
1012 case 0:
1013 return fEnv->fStart = fFirst.invoke(fEnv);
1014 default:
1015 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1016 return ((char*)fEnv->fStart) + fValDiff*idx;
1017 }
1018 case ROOT::kSTLbitset: {
1019 switch (idx) {
1020 case 0:
1022 fEnv->fIdx = idx;
1023 break;
1024 default:
1025 fEnv->fIdx = idx - fEnv->fIdx;
1026 if (!fEnv->fStart) fEnv->fStart = fFirst.invoke(fEnv);
1027 fNext.invoke(fEnv);
1028 fEnv->fIdx = idx;
1029 break;
1030 }
1031 typedef ROOT::TCollectionProxyInfo::Environ <std::pair<size_t, Bool_t>> EnvType_t;
1032 EnvType_t *e = (EnvType_t *) fEnv;
1033 return &(e->fIterator.second);
1034 }
1035 case ROOT::kSTLset:
1037 case ROOT::kSTLmultiset:
1039 case ROOT::kSTLmap:
1041 case ROOT::kSTLmultimap:
1043 if ( fEnv->fUseTemp ) {
1044 return (((char*)fEnv->fTemp)+idx*fValDiff);
1045 }
1046 // Intentional fall through.
1047 default:
1048 switch( idx ) {
1049 case 0:
1050 fEnv->fIdx = idx;
1051 return fEnv->fStart = fFirst.invoke(fEnv);
1052 default: {
1053 fEnv->fIdx = idx - fEnv->fIdx;
1054 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1055 void* result = fNext.invoke(fEnv);
1056 fEnv->fIdx = idx;
1057 return result;
1058 }
1059 }
1060 }
1061 }
1062 Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1063 return 0;
1064}
1065
1066////////////////////////////////////////////////////////////////////////////////
1067/// Clear the emulated collection.
1068
1069void TGenCollectionProxy::Clear(const char* opt)
1070{
1071 if ( fEnv && fEnv->fObject ) {
1072 if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1073 size_t i, n = *(size_t*)fSize.invoke(fEnv);
1074 if ( n > 0 ) {
1075 for (i=0; i<n; ++i)
1077 }
1078 }
1080 }
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084/// Return the current size of the container
1085
1087{
1088 if ( fEnv && fEnv->fObject ) {
1089 if (fEnv->fUseTemp) {
1090 return fEnv->fSize;
1091 } else {
1092 return *(size_t*)fSize.invoke(fEnv);
1093 }
1094 }
1095 Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1096 return 0;
1097}
1098
1099////////////////////////////////////////////////////////////////////////////////
1100/// Resize the container
1101
1103{
1104 if ( fEnv && fEnv->fObject ) {
1105 if ( force && fPointers ) {
1106 size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1107 if ( n != nold ) {
1108 for (i=n; i<nold; ++i)
1109 DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1110 }
1111 }
1112 MESSAGE(3, "Resize(n)" );
1113 fEnv->fSize = n;
1115 return;
1116 }
1117 Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1118}
1119
1120////////////////////////////////////////////////////////////////////////////////
1121/// Allocate the needed space.
1122/// For associative collection, this returns a TStaging object that
1123/// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1124
1126{
1127 if ( fEnv && fEnv->fObject ) {
1128 switch ( fSTL_type ) {
1129 case ROOT::kSTLset:
1131 case ROOT::kSTLmultiset:
1133 case ROOT::kSTLmap:
1135 case ROOT::kSTLmultimap:
1137 if ( (fProperties & kNeedDelete) )
1138 Clear("force");
1139 else
1141 // Commit no longer use the environment and thus no longer decrease
1142 // the count. Consequently we no longer should increase it here.
1143 // ++fEnv->fRefCount;
1144 fEnv->fSize = n;
1145
1146 TStaging *s;
1147 if (fStaged.empty()) {
1148 s = new TStaging(n,fValDiff);
1149 } else {
1150 s = fStaged.back();
1151 fStaged.pop_back();
1152 s->Resize(n);
1153 }
1154 fConstruct(s->GetContent(),s->GetSize());
1155
1156 s->SetTarget(fEnv->fObject);
1157
1158 fEnv->fTemp = s->GetContent();
1159 fEnv->fUseTemp = kTRUE;
1160 fEnv->fStart = fEnv->fTemp;
1161
1162 return s;
1163 }
1164 case ROOT::kSTLvector:
1165 case ROOT::kSTLlist:
1167 case ROOT::kSTLdeque:
1168 if( (fProperties & kNeedDelete) ) {
1169 Clear("force");
1170 }
1171 fEnv->fSize = n;
1173 return fEnv->fObject;
1174
1175 case ROOT::kSTLbitset: {
1176 TStaging *s;
1177 if (fStaged.empty()) {
1178 s = new TStaging(n,fValDiff);
1179 } else {
1180 s = fStaged.back();
1181 fStaged.pop_back();
1182 s->Resize(n);
1183 }
1184 s->SetTarget(fEnv->fObject);
1185
1186 fEnv->fTemp = s->GetContent();
1187 fEnv->fUseTemp = kTRUE;
1188 fEnv->fStart = fEnv->fTemp;
1189
1190 return s;
1191 }
1192 }
1193 }
1194 return 0;
1195}
1196
1197////////////////////////////////////////////////////////////////////////////////
1198/// Insert data into the container where data is a C-style array of the actual type contained in the collection
1199/// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1200
1201void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1202{
1203 fFeed((void*)data,container,size);
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Commit the change.
1208
1210{
1212// case ROOT::kSTLmap:
1213// case ROOT::kSTLmultimap:
1214// case ROOT::kSTLset:
1215// case ROOT::kSTLmultiset:
1216 if ( from ) {
1217 TStaging *s = (TStaging*) from;
1218 if ( s->GetTarget() ) {
1219 fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1220 }
1221 fDestruct(s->GetContent(),s->GetSize());
1222 s->SetTarget(0);
1223 fStaged.push_back(s);
1224 }
1225 }
1226}
1227
1228////////////////////////////////////////////////////////////////////////////////
1229/// Add an object.
1230
1232{
1233 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
1234 if ( !fProxyList.empty() ) {
1235 EnvironBase_t* back = fProxyList.back();
1236 if ( back->fObject == objstart ) {
1237 ++back->fRefCount;
1238 fProxyList.push_back(back);
1239 fEnv = back;
1240 return;
1241 }
1242 }
1243 EnvironBase_t* e = 0;
1244 if ( fProxyKept.empty() ) {
1246 e->fTemp = 0;
1247 e->fUseTemp = kFALSE;
1248 }
1249 else {
1250 e = fProxyKept.back();
1251 fProxyKept.pop_back();
1252 }
1253 e->fSize = 0;
1254 e->fRefCount = 1;
1255 e->fObject = objstart;
1256 e->fStart = 0;
1257 e->fIdx = 0;
1258 // ::memset(e->buff,0,sizeof(e->buff));
1259 fProxyList.push_back(e);
1260 fEnv = e;
1261}
1262
1263////////////////////////////////////////////////////////////////////////////////
1264/// Remove the last object.
1265
1267{
1268 if ( !fProxyList.empty() ) {
1269 EnvironBase_t* e = fProxyList.back();
1270 if ( --e->fRefCount <= 0 ) {
1271 fProxyKept.push_back(e);
1272 e->fUseTemp = kFALSE;
1273 }
1274 fProxyList.pop_back();
1275 }
1276 fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1277}
1278
1279////////////////////////////////////////////////////////////////////////////////
1280/// Call to delete/destruct individual item.
1281
1282void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
1283{
1284 if ( force && ptr ) {
1285 switch (fSTL_type) {
1286 case ROOT::kSTLmap:
1288 case ROOT::kSTLmultimap:
1290 if ( fKey->fCase&kIsPointer ) {
1293 TPushPop helper(proxy,*(void**)ptr);
1294 proxy->Clear("force");
1295 }
1296 fKey->DeleteItem(*(void**)ptr);
1297 } else {
1300 TPushPop helper(proxy,ptr);
1301 proxy->Clear("force");
1302 }
1303 }
1304 char *addr = ((char*)ptr)+fValOffset;
1305 if ( fVal->fCase&kIsPointer ) {
1308 TPushPop helper(proxy,*(void**)addr);
1309 proxy->Clear("force");
1310 }
1311 fVal->DeleteItem(*(void**)addr);
1312 } else {
1315 TPushPop helper(proxy,addr);
1316 proxy->Clear("force");
1317 }
1318 }
1319 break;
1320 }
1321 default: {
1322 if ( fVal->fCase&kIsPointer ) {
1325 TPushPop helper(proxy,*(void**)ptr);
1326 proxy->Clear("force");
1327 }
1328 fVal->DeleteItem(*(void**)ptr);
1329 } else {
1332 TPushPop helper(proxy,ptr);
1333 proxy->Clear("force");
1334 }
1335 }
1336 break;
1337 }
1338 }
1339 }
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343
1344void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1345{
1346 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1347}
1348
1349////////////////////////////////////////////////////////////////////////////////
1350
1351void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1352{
1353 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Streamer Function.
1358
1360{
1361 if ( fEnv ) {
1363 return;
1364 }
1365 Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1366}
1367
1368////////////////////////////////////////////////////////////////////////////////
1369/// Streamer I/O overload
1370
1371void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1372{
1373 TPushPop env(this, objp);
1374 Streamer(buff);
1375}
1376
1377////////////////////////////////////////////////////////////////////////////////
1378/// TClassStreamer IO overload
1379
1381{
1382 Streamer(b, objp, 0);
1383}
1384
1385
1386struct TGenCollectionProxy__SlowIterator {
1388 UInt_t fIndex;
1389 TGenCollectionProxy__SlowIterator(TVirtualCollectionProxy *proxy) : fProxy(proxy), fIndex(0) {}
1390};
1391
1392////////////////////////////////////////////////////////////////////////////////
1393
1394void TGenCollectionProxy__SlowCreateIterators(void * /* collection */, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
1395{
1396 new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1397 *(UInt_t*)*end_arena = proxy->Size();
1398}
1399
1400////////////////////////////////////////////////////////////////////////////////
1401
1402void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1403{
1404 TGenCollectionProxy__SlowIterator *iterator = (TGenCollectionProxy__SlowIterator*)iter;
1405 if (iterator->fIndex != *(UInt_t*)end) {
1406 void *result = iterator->fProxy->At(iterator->fIndex);
1407 ++(iterator->fIndex);
1408 return result;
1409 } else {
1410 return 0;
1411 }
1412}
1413
1414////////////////////////////////////////////////////////////////////////////////
1415
1416void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
1417{
1418 *(TGenCollectionProxy__SlowIterator*)dest = *(TGenCollectionProxy__SlowIterator*)source;
1419 return dest;
1420}
1421
1422////////////////////////////////////////////////////////////////////////////////
1423/// Nothing to do
1424
1426{
1427}
1428
1429////////////////////////////////////////////////////////////////////////////////
1430/// Nothing to do
1431
1433{
1434}
1435
1436
1437////////////////////////////////////////////////////////////////////////////////
1438/// We can safely assume that the std::vector layout does not really depend on
1439/// the content!
1440
1441void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy*)
1442{
1443 std::vector<char> *vec = (std::vector<char>*)obj;
1444 if (vec->empty()) {
1445 *begin_arena = 0;
1446 *end_arena = 0;
1447 return;
1448 }
1449 *begin_arena = &(*vec->begin());
1450#ifdef R__VISUAL_CPLUSPLUS
1451 *end_arena = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
1452#else
1453 // coverity[past_the_end] Safe on other platforms
1454 *end_arena = &(*vec->end());
1455#endif
1456
1457}
1458
1459////////////////////////////////////////////////////////////////////////////////
1460/// Should not be used.
1461
1462void *TGenCollectionProxy__VectorNext(void *, const void *)
1463{
1464 R__ASSERT(0);
1465 return 0;
1466}
1467
1468////////////////////////////////////////////////////////////////////////////////
1469
1470void *TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
1471{
1472 *(void**)dest = *(void**)source;
1473 return dest;
1474}
1475
1476////////////////////////////////////////////////////////////////////////////////
1477/// Nothing to do
1478
1480{
1481}
1482
1483////////////////////////////////////////////////////////////////////////////////
1484/// Nothing to do
1485
1487{
1488}
1489
1490
1491
1492////////////////////////////////////////////////////////////////////////////////
1493
1494void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
1495{
1497 *begin_arena = s->GetContent();
1498 *end_arena = s->GetEnd();
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Should not be used.
1503
1504void *TGenCollectionProxy__StagingNext(void *, const void *)
1505{
1506 R__ASSERT(0);
1507 return 0;
1508}
1509
1510////////////////////////////////////////////////////////////////////////////////
1511
1512void *TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
1513{
1514 *(void**)dest = *(void**)source;
1515 return dest;
1516}
1517
1518////////////////////////////////////////////////////////////////////////////////
1519/// Nothing to do
1520
1522{
1523}
1524
1525////////////////////////////////////////////////////////////////////////////////
1526/// Nothing to do
1527
1529{
1530}
1531
1532
1533////////////////////////////////////////////////////////////////////////////////
1534/// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1535/// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1536/// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1537/// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1538
1540{
1541 if (read) {
1542 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1543 if ( (fProperties & kIsAssociative) && read)
1545 }
1546
1548
1549 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1550
1551// fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1552// if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1553// fprintf(stderr,"vector/emulated iterator\n");
1554// else if ( (fProperties & kIsAssociative) && read)
1555// fprintf(stderr,"an associative read iterator\n");
1556// else
1557// fprintf(stderr,"a generic iterator\n");
1558
1561 else if ( (fProperties & kIsAssociative) && read)
1563 else
1565}
1566
1567////////////////////////////////////////////////////////////////////////////////
1568/// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1569/// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1570/// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1571/// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1572
1574{
1575 if (read) {
1576 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1577 if ( (fProperties & kIsAssociative) && read)
1579 }
1580
1582
1583 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1584
1587 else if ( (fProperties & kIsAssociative) && read)
1589 else
1591}
1592
1593////////////////////////////////////////////////////////////////////////////////
1594/// See typedef void* (*Next_t)(void *iter, void *end);
1595/// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1596/// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1597/// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1598/// which case 'Next' will return the value of the pointer.
1599
1601{
1602 if (read) {
1603 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1604 if ( (fProperties & kIsAssociative) && read)
1606 }
1607
1609
1610 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1611
1614 else if ( (fProperties & kIsAssociative) && read)
1616 else
1618}
1619
1620////////////////////////////////////////////////////////////////////////////////
1621/// See typedef void (*DeleteIterator_t)(void *iter);
1622/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1623/// Otherwise just call the iterator's destructor.
1624
1626{
1627 if (read) {
1628 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1629 if ( (fProperties & kIsAssociative) && read)
1631 }
1632
1634
1635 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1636
1639 else if ( (fProperties & kIsAssociative) && read)
1641 else
1643}
1644
1645////////////////////////////////////////////////////////////////////////////////
1646/// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1647/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1648/// Otherwise just call the iterator's destructor.
1649
1651{
1652 if (read) {
1653 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1654 if ( (fProperties & kIsAssociative) && read)
1656 }
1657
1659
1660 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1661
1664 else if ( (fProperties & kIsAssociative) && read)
1666 else
1668}
1669
1670////////////////////////////////////////////////////////////////////////////////
1671/// Return the set of action necessary to stream in this collection member-wise coming from
1672/// the old value class layout refered to by 'version'.
1673
1675{
1676 if (oldClass == 0) {
1677 return 0;
1678 }
1679 TObjArray* arr = 0;
1682 std::map<std::string, TObjArray*>::iterator it;
1683
1684 it = fConversionReadMemberWise->find( oldClass->GetName() );
1685
1686 if( it != fConversionReadMemberWise->end() ) {
1687 arr = it->second;
1688 }
1689
1690 if (arr) {
1691 result = (TStreamerInfoActions::TActionSequence *)arr->At(version);
1692 if (result) {
1693 return result;
1694 }
1695 }
1696 }
1697
1698 // Need to create it.
1699 TClass *valueClass = GetValueClass();
1700 if (valueClass == 0) {
1701 return 0;
1702 }
1703 TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1704 if (info == 0) {
1705 return 0;
1706 }
1708
1709 if (!arr) {
1710 arr = new TObjArray(version+10, -1);
1712 fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1713 }
1714 (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1715 }
1716 arr->AddAtAndExpand( result, version );
1717
1718 return result;
1719}
1720
1721////////////////////////////////////////////////////////////////////////////////
1722/// Return the set of action necessary to stream in this collection member-wise coming from
1723/// the old value class layout refered to by 'version'.
1724
1726{
1728 if (version < (fReadMemberWise->GetSize()-1)) { // -1 because the 'index' starts at -1
1730 }
1731 if (result == 0) {
1732 // Need to create it.
1733 TClass *valueClass = GetValueClass();
1734 TVirtualStreamerInfo *info = 0;
1735 if (valueClass) {
1736 info = valueClass->GetStreamerInfo(version);
1737 }
1739 fReadMemberWise->AddAtAndExpand(result,version);
1740 }
1741 return result;
1742}
1743
1744////////////////////////////////////////////////////////////////////////////////
1745/// Return the set of action necessary to stream out this collection member-wise.
1746
1748{
1750 if (result == 0) {
1751 // Need to create it.
1752 TClass *valueClass = GetValueClass();
1753 TVirtualStreamerInfo *info = 0;
1754 if (valueClass) {
1755 info = valueClass->GetStreamerInfo();
1756 }
1758 fWriteMemberWise=result;
1759 }
1760 return result;
1761}
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
PyObject * fType
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
EDataType
Definition: TDataType.h:28
@ kNoType_t
Definition: TDataType.h:33
@ kInt_t
Definition: TDataType.h:30
@ kBool_t
Definition: TDataType.h:32
@ kIsPointer
Definition: TDictionary.h:77
@ kIsClass
Definition: TDictionary.h:65
@ kIsEnum
Definition: TDictionary.h:68
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsStruct
Definition: TDictionary.h:66
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
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 Fatal(const char *location, const char *msgfmt,...)
#define MESSAGE(which, text)
void * TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
void TGenCollectionProxy__StagingDeleteTwoIterators(void *, void *)
Nothing to do.
void * TGenCollectionProxy__VectorNext(void *, const void *)
Should not be used.
void TGenCollectionProxy__StagingDeleteSingleIterators(void *)
Nothing to do.
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.
void TGenCollectionProxy__SlowCreateIterators(void *, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
void * TGenCollectionProxy__SlowNext(void *iter, const void *end)
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!
void * TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
void * TGenCollectionProxy__StagingNext(void *, const void *)
Should not be used.
void TGenCollectionProxy__VectorDeleteSingleIterators(void *)
Nothing to do.
void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
void TGenCollectionProxy__SlowDeleteTwoIterators(void *, void *)
Nothing to do.
void TGenCollectionProxy__VectorDeleteTwoIterators(void *, void *)
Nothing to do.
void TGenCollectionProxy__SlowDeleteSingleIterators(void *)
Nothing to do.
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
#define gROOT
Definition: TROOT.h:410
#define R__LOCKGUARD(mutex)
T1 fFirst
Definition: X11Events.mm:86
void *(* fCopyIterator)(void *dest, const void *source)
void *(* fConstructFunc)(void *, size_t)
void(* fDeleteTwoIterators)(void *begin, void *end)
void *(* fCollectFunc)(void *, void *)
void *(* fFeedFunc)(void *, void *, size_t)
void(* fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
void *(* fNext)(void *iter, const void *end)
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
TClass * GetClass() const
Definition: TClassRef.h:71
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
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:4452
ROOT::DesFunc_t GetDestructor() const
ROOT::NewFunc_t GetNew() const
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5466
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:566
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6793
ROOT::DelFunc_t GetDelete() const
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:2885
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Int_t GetType() const
Definition: TDataType.h:68
Int_t Size() const
Get size of basic typedef'ed type.
Definition: TDataType.cxx:366
void * invoke(void *obj) const
Small helper to stage the content of an associative container when reading and before inserting it in...
Proxy around an arbitrary container, which implements basic functionality and iteration.
Method fFirst
Container accessors: generic iteration: first.
std::atomic< Value * > fValue
Descriptor of the container value type.
virtual ~TGenCollectionProxy()
Standard destructor.
Bool_t fPointers
Flag to indicate if containee has pointers (key or value)
Method fNext
Container accessors: generic iteration: next.
virtual void Streamer(TBuffer &refBuffer)
Streamer Function.
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...
TStreamerInfoActions::TActionSequence * fWriteMemberWise
virtual EDataType GetType() const
If the content is a simple numerical value, return its type (see TDataType)
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 UInt_t Size() const
Return the current size of the container.
virtual UInt_t Sizeof() const
Return the sizeof the collection object.
Info_t fTypeinfo
Type information.
int fValOffset
Offset from key to value (in maps)
EnvironBase_t * fEnv
Address of the currently proxied object.
virtual void PopProxy()
Remove the last object.
virtual TClass * GetCollectionClass() const
Return a pointer to the TClass representing the container.
DeleteIterator_t fFunctionDeleteIterator
Collectfunc_t fCollect
Method to collect objects from container.
virtual Bool_t HasPointers() const
Return true if the content is of type 'pointer to'.
virtual TClass * GetValueClass() const
Return a pointer to the TClass representing the content.
TGenCollectionProxy * Initialize(Bool_t silent) const
Proxy initializer.
virtual ULong_t GetIncrement() const
Return the offset between two consecutive value_types (memory layout).
virtual TGenCollectionProxy * InitializeEx(Bool_t silent)
Proxy initializer.
virtual void PushProxy(void *objstart)
Add an object.
std::string fName
Name of the class being proxied.
int fSTL_type
STL container type.
CopyIterator_t fFunctionCopyIterator
Value * fKey
Descriptor of the key_type.
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...
virtual void Resize(UInt_t n, Bool_t force_delete)
Resize the container.
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 fProxyList
Stack of recursive proxies.
virtual void * Allocate(UInt_t n, Bool_t forceDelete)
Allocate the needed space.
Sizing_t fDestruct
Container accessors: block destruct.
Method0 fCreateEnv
Method to allocate an Environment holder.
virtual void Commit(void *env)
Commit the change.
Value * fVal
Descriptor of the Value_type.
virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE)
See typedef void (*DeleteIterator_t)(void *iter); If the sizeof iterator is greater than fgIteratorAr...
virtual void operator()(TBuffer &refBuffer, void *pObject)
TClassStreamer IO overload.
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()
Return the set of action necessary to stream out this collection member-wise.
TClass * fOnFileClass
On file class.
Sizing_t fResize
Container accessors: resize container.
ArrIterfunc_t fConstruct
Container accessors: block construct.
std::map< std::string, TObjArray * > * fConversionReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read) derived from another class.
void CheckFunctions() const
Check existence of function pointers.
DeleteTwoIterators_t fFunctionDeleteTwoIterators
virtual Int_t GetCollectionType() const
Return the type of collection see TClassEdit::ESTLType.
virtual void * At(UInt_t idx)
Return the address of the value at index 'idx'.
CreateIterators_t fFunctionCreateIterators
virtual void Clear(const char *opt="")
Clear the emulated collection.
TObjArray * fReadMemberWise
Array of bundle of TStreamerInfoActions to stream out (read)
virtual void DeleteItem(Bool_t force, void *ptr) const
Call to delete/destruct individual item.
virtual TVirtualCollectionProxy * Generate() const
Virtual copy constructor.
Staged_t fStaged
Optimization: Keep staged array once they were created.
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...
Method fSize
Container accessors: size of container.
virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE)
See typedef void (*CopyIterator_t)(void *&dest, const void *source); Copy the iterator source,...
Method fClear
Method cache for container accessors: clear container.
Feedfunc_t fFeed
Container accessors: block feed.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)
See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena); begin_...
int fValDiff
Offset between two consecutive value_types (memory layout).
virtual void ReadBuffer(TBuffer &b, void *obj)
Proxies_t fProxyKept
Optimization: Keep proxies once they were created.
const std::type_info & Info_t
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:35
virtual void TypeInfo_Init(TypeInfo_t *, const char *) const
Definition: TInterpreter.h:505
virtual void TypeInfo_Delete(TypeInfo_t *) const
Definition: TInterpreter.h:501
virtual TypeInfo_t * TypeInfo_Factory() const
Definition: TInterpreter.h:502
virtual Long_t TypeInfo_Property(TypeInfo_t *) const
Definition: TInterpreter.h:508
virtual int TypeInfo_Size(TypeInfo_t *) const
Definition: TInterpreter.h:510
virtual Bool_t TypeInfo_IsValid(TypeInfo_t *) const
Definition: TInterpreter.h:506
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by '...
virtual Int_t GetProperties() const
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
void *(* CopyIterator_t)(void *dest, const void *source)
virtual void Clear(const char *opt="")=0
void *(* Next_t)(void *iter, const void *end)
virtual UInt_t Size() const =0
void(* DeleteTwoIterators_t)(void *begin, void *end)
void(* DeleteIterator_t)(void *iter)
Abstract Interface class describing Streamer information for one class.
const Int_t n
Definition: legend1.C:16
@ kSTLbitset
Definition: ESTLType.h:37
@ kSTLmap
Definition: ESTLType.h:33
@ kSTLunorderedmultiset
Definition: ESTLType.h:43
@ kSTLset
Definition: ESTLType.h:35
@ kSTLmultiset
Definition: ESTLType.h:36
@ kSTLdeque
Definition: ESTLType.h:32
@ kSTLvector
Definition: ESTLType.h:30
@ kSTLunorderedmultimap
Definition: ESTLType.h:45
@ kSTLunorderedset
Definition: ESTLType.h:42
@ kSTLlist
Definition: ESTLType.h:31
@ kSTLforwardlist
Definition: ESTLType.h:41
@ kSTLunorderedmap
Definition: ESTLType.h:44
@ kNotSTL
Definition: ESTLType.h:29
@ kSTLmultimap
Definition: ESTLType.h:34
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:478
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
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:948
bool IsDefAlloc(const char *alloc, const char *classname)
return whether or not 'allocname' is the STL default allocator for type 'classname'
Definition: TClassEdit.cxx:567
@ kDropTrailStar
Definition: TClassEdit.h:76
static constexpr double s
const char * Value
Definition: TXMLSetup.cxx:72
Small helper to save proxy environment in the event of recursive calls.
Small helper to describe the Value_type or the key_type of an STL container.
UInt_t fCase
type of data of Value_type
TClassRef fType
TClass reference of Value_type in collection.
UInt_t fProperties
Additional properties of the value type (kNeedDelete)
Value(const std::string &info, Bool_t silent)
Constructor.
size_t fSize
fSize of the contained object
ROOT::DelFunc_t fDelete
Method cache for containee delete.
ROOT::DesFunc_t fDtor
Method cache for containee destructor.
ROOT::NewFunc_t fCtor
Method cache for containee constructor.
EDataType fKind
kind of ROOT-fundamental type
Bool_t IsValid()
Return true if the Value has been properly initialized.
#define dest(otri, vertexptr)
Definition: triangle.c:1040