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