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