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