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 "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
40public:
41 // Standard Destructor
43 {
44 }
45 // Standard Destructor
47 {
48 }
49 // Return the address of the value at index 'idx'
50 void* At(UInt_t idx) override
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 nullptr;
64 }
65 // Call to delete/destruct individual item
66 void DeleteItem(Bool_t force, void* ptr) const override
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*/
90
91public:
93 {
94 // Standard Constructor.
95 }
97 {
98 // Standard Destructor.
99 }
100 void* At(UInt_t idx) override
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 nullptr;
113 }
114
115 void DeleteItem(Bool_t force, void* ptr) const override
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//////////////////////////////////////////////////////////////////////////
136
137public:
139 {
140 // Standard Constructor.
141 }
143 {
144 // Standard Destructor.
145 }
146 void* At(UInt_t idx) override
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 void DeleteItem(Bool_t force, void* ptr) const override
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
191public:
192 // Standard Destructor
194 {
195 }
196 // Standard Destructor
198 {
199 }
200 // Return the address of the value at index 'idx'
201 void* At(UInt_t idx) override
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 nullptr;
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
233public:
234 // Standard Destructor
236 {
237 }
238 // Standard Destructor
240 {
241 }
242 // Return the address of the value at index 'idx'
243 void* At(UInt_t idx) override
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 nullptr;
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
278public:
279 // Standard Destructor
281 {
282 }
283 // Standard Destructor
285 {
286 }
287 // Call to delete/destruct individual item
288 void DeleteItem(Bool_t force, void* ptr) const override
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 {
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 newpaircl->ForceReload(paircl);
923 }
924 }
925 }
926 }
927 newfValue = R__CreateValue(nam, silent, fValOffset, fValDiff);
928
929 fPointers = (0 != (fKey->fCase&kIsPointer));
930 if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
932 }
933 if ( 0 == fValDiff ) {
935 fValDiff += (slong - fKey->fSize%slong)%slong;
936 fValDiff += (slong - fValDiff%slong)%slong;
937 }
938 if ( 0 == fValOffset ) {
940 fValOffset += (slong - fKey->fSize%slong)%slong;
941 }
942 break;
943 case ROOT::kSTLbitset:
944 inside[1] = "bool";
945 // Intentional fall through
946 default:
947 newfValue = R__CreateValue(inside[1], silent);
948
949 fVal = new Value(*newfValue);
950 if ( 0 == fValDiff ) {
952 fValDiff += (slong - fValDiff%slong)%slong;
953 }
954 if (num > 2 && !inside[2].empty()) {
955 if (! TClassEdit::IsDefAlloc(inside[2].c_str(),inside[0].c_str())) {
957 }
958 }
959 break;
960 }
961
962 fPointers = fPointers || (0 != (fVal->fCase&kIsPointer));
963 if (fPointers || (0 != (fVal->fProperties&kNeedDelete))) {
965 }
966 fClass = cl;
967 //fValue must be set last since we use it to indicate that we are initialized
968 fValue = newfValue;
969 return this;
970 }
971 Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName());
972 }
973 Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name());
974 return 0;
975}
976
977////////////////////////////////////////////////////////////////////////////////
978/// Return a pointer to the TClass representing the container
979
981{
982 return fClass ? fClass : Initialize(kFALSE)->fClass;
983}
984
985////////////////////////////////////////////////////////////////////////////////
986/// Return the type of collection see TClassEdit::ESTLType
987
989{
990 if (!fValue.load(std::memory_order_relaxed)) {
992 }
993 return fSTL_type;
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// Return the offset between two consecutive value_types (memory layout).
998
1000 if (!fValue.load(std::memory_order_relaxed)) {
1002 }
1003 return fValDiff;
1004}
1005
1006////////////////////////////////////////////////////////////////////////////////
1007/// Return the sizeof the collection object.
1008
1010{
1011 return fClass->Size();
1012}
1013
1014////////////////////////////////////////////////////////////////////////////////
1015/// Return true if the content is of type 'pointer to'
1016
1018{
1019 // Initialize proxy in case it hasn't been initialized yet
1020 if( !fValue.load(std::memory_order_relaxed) )
1022
1023 // The content of a map and multimap is always a 'pair' and hence
1024 // fPointers means "Flag to indicate if containee has pointers (key or value)"
1025 // so we need to ignore its value for map and multimap;
1028}
1029
1030////////////////////////////////////////////////////////////////////////////////
1031/// Return a pointer to the TClass representing the content.
1032
1034{
1035 auto value = fValue.load(std::memory_order_relaxed);
1036 if (!value) {
1038 value = fValue.load(std::memory_order_relaxed);
1039 }
1040 return value ? (*value).fType.GetClass() : 0;
1041}
1042
1043////////////////////////////////////////////////////////////////////////////////
1044/// If the content is a simple numerical value, return its type (see TDataType)
1045
1047{
1048 auto value = fValue.load(std::memory_order_relaxed);
1049 if (!value) {
1051 value = fValue.load(std::memory_order_relaxed);
1052 }
1053 return value ? (*value).fKind : kNoType_t;
1054}
1055
1056////////////////////////////////////////////////////////////////////////////////
1057/// Return the address of the value at index 'idx'
1058
1060{
1061 if ( fEnv && fEnv->fObject ) {
1062 switch (fSTL_type) {
1063 case ROOT::kSTLvector:
1064 if ((*fValue).fKind == kBool_t) {
1065 auto vec = (std::vector<bool> *)(fEnv->fObject);
1066 fEnv->fLastValueVecBool = (*vec)[idx];
1067 fEnv->fIdx = idx;
1068 return &(fEnv->fLastValueVecBool);
1069 }
1070 // intentional fall through
1071 case ROOT::kROOTRVec:
1072 fEnv->fIdx = idx;
1073 switch( idx ) {
1074 case 0:
1075 return fEnv->fStart = fFirst.invoke(fEnv);
1076 default:
1077 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1078 return ((char*)fEnv->fStart) + fValDiff*idx;
1079 }
1080 case ROOT::kSTLbitset: {
1081 switch (idx) {
1082 case 0:
1084 fEnv->fIdx = idx;
1085 break;
1086 default:
1087 fEnv->fIdx = idx - fEnv->fIdx;
1088 if (!fEnv->fStart) fEnv->fStart = fFirst.invoke(fEnv);
1089 fNext.invoke(fEnv);
1090 fEnv->fIdx = idx;
1091 break;
1092 }
1093 typedef ROOT::TCollectionProxyInfo::Environ <std::pair<size_t, Bool_t>> EnvType_t;
1094 EnvType_t *e = (EnvType_t *) fEnv;
1095 return &(e->fIterator.second);
1096 }
1097 case ROOT::kSTLset:
1099 case ROOT::kSTLmultiset:
1101 case ROOT::kSTLmap:
1103 case ROOT::kSTLmultimap:
1105 if ( fEnv->fUseTemp ) {
1106 return (((char*)fEnv->fTemp)+idx*fValDiff);
1107 }
1108 // Intentional fall through.
1109 default:
1110 switch( idx ) {
1111 case 0:
1112 fEnv->fIdx = idx;
1113 return fEnv->fStart = fFirst.invoke(fEnv);
1114 default: {
1115 fEnv->fIdx = idx - fEnv->fIdx;
1116 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1117 void* result = fNext.invoke(fEnv);
1118 fEnv->fIdx = idx;
1119 return result;
1120 }
1121 }
1122 }
1123 }
1124 Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1125 return 0;
1126}
1127
1128////////////////////////////////////////////////////////////////////////////////
1129/// Clear the emulated collection.
1130
1131void TGenCollectionProxy::Clear(const char* opt)
1132{
1133 if ( fEnv && fEnv->fObject ) {
1134 if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1135 size_t i, n = *(size_t*)fSize.invoke(fEnv);
1136 if ( n > 0 ) {
1137 for (i=0; i<n; ++i)
1139 }
1140 }
1142 }
1143}
1144
1145////////////////////////////////////////////////////////////////////////////////
1146/// Return the current size of the container
1147
1149{
1150 if ( fEnv && fEnv->fObject ) {
1151 if (fEnv->fUseTemp) {
1152 return fEnv->fSize;
1153 } else {
1154 return *(size_t*)fSize.invoke(fEnv);
1155 }
1156 }
1157 Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1158 return 0;
1159}
1160
1161////////////////////////////////////////////////////////////////////////////////
1162/// Resize the container
1163
1165{
1166 if ( fEnv && fEnv->fObject ) {
1167 if ( force && fPointers ) {
1168 size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1169 if ( n != nold ) {
1170 for (i=n; i<nold; ++i)
1171 DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1172 }
1173 }
1174 MESSAGE(3, "Resize(n)" );
1175 fEnv->fSize = n;
1177 return;
1178 }
1179 Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Allocate the needed space.
1184/// For associative collection, this returns a TStaging object that
1185/// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1186
1188{
1189 if ( fEnv && fEnv->fObject ) {
1190 switch ( fSTL_type ) {
1191 case ROOT::kSTLset:
1193 case ROOT::kSTLmultiset:
1195 case ROOT::kSTLmap:
1197 case ROOT::kSTLmultimap:
1199 if ( (fProperties & kNeedDelete) )
1200 Clear("force");
1201 else
1203 // Commit no longer use the environment and thus no longer decrease
1204 // the count. Consequently we no longer should increase it here.
1205 // ++fEnv->fRefCount;
1206 fEnv->fSize = n;
1207
1208 TStaging *s;
1209 if (fStaged.empty()) {
1210 s = new TStaging(n,fValDiff);
1211 } else {
1212 s = fStaged.back();
1213 fStaged.pop_back();
1214 s->Resize(n);
1215 }
1216 fConstruct(s->GetContent(),s->GetSize());
1217
1218 s->SetTarget(fEnv->fObject);
1219
1220 fEnv->fTemp = s->GetContent();
1221 fEnv->fUseTemp = kTRUE;
1222 fEnv->fStart = fEnv->fTemp;
1223
1224 return s;
1225 }
1226 case ROOT::kSTLvector:
1227 case ROOT::kSTLlist:
1229 case ROOT::kSTLdeque:
1230 case ROOT::kROOTRVec:
1231 if( (fProperties & kNeedDelete) ) {
1232 Clear("force");
1233 }
1234 fEnv->fSize = n;
1236 return fEnv->fObject;
1237
1238 case ROOT::kSTLbitset: {
1239 TStaging *s;
1240 if (fStaged.empty()) {
1241 s = new TStaging(n,fValDiff);
1242 } else {
1243 s = fStaged.back();
1244 fStaged.pop_back();
1245 s->Resize(n);
1246 }
1247 s->SetTarget(fEnv->fObject);
1248
1249 fEnv->fTemp = s->GetContent();
1250 fEnv->fUseTemp = kTRUE;
1251 fEnv->fStart = fEnv->fTemp;
1252
1253 return s;
1254 }
1255 }
1256 }
1257 return 0;
1258}
1259
1260////////////////////////////////////////////////////////////////////////////////
1261/// Insert data into the container where data is a C-style array of the actual type contained in the collection
1262/// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1263
1264void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1265{
1266 fFeed((void*)data,container,size);
1267}
1268
1269////////////////////////////////////////////////////////////////////////////////
1270/// Commit the change.
1271
1273{
1275// case ROOT::kSTLmap:
1276// case ROOT::kSTLmultimap:
1277// case ROOT::kSTLset:
1278// case ROOT::kSTLmultiset:
1279 if ( from ) {
1280 TStaging *s = (TStaging*) from;
1281 if ( s->GetTarget() ) {
1282 fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1283 }
1284 fDestruct(s->GetContent(),s->GetSize());
1285 s->SetTarget(0);
1286 fStaged.push_back(s);
1287 }
1288 }
1289}
1290
1291////////////////////////////////////////////////////////////////////////////////
1292/// Add an object.
1293
1295{
1296 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
1297 if ( !fProxyList.empty() ) {
1298 EnvironBase_t* back = fProxyList.back();
1299 if ( back->fObject == objstart ) {
1300 ++back->fRefCount;
1301 fProxyList.push_back(back);
1302 fEnv = back;
1303 return;
1304 }
1305 }
1306 EnvironBase_t* e = 0;
1307 if ( fProxyKept.empty() ) {
1309 e->fTemp = 0;
1310 e->fUseTemp = kFALSE;
1311 }
1312 else {
1313 e = fProxyKept.back();
1314 fProxyKept.pop_back();
1315 }
1316 e->fSize = 0;
1317 e->fRefCount = 1;
1318 e->fObject = objstart;
1319 e->fStart = 0;
1320 e->fIdx = 0;
1321 // ::memset(e->buff,0,sizeof(e->buff));
1322 fProxyList.push_back(e);
1323 fEnv = e;
1324}
1325
1326////////////////////////////////////////////////////////////////////////////////
1327/// Remove the last object.
1328
1330{
1331 if ( !fProxyList.empty() ) {
1332 EnvironBase_t* e = fProxyList.back();
1333 if ( --e->fRefCount <= 0 ) {
1334 fProxyKept.push_back(e);
1335 e->fUseTemp = kFALSE;
1336 }
1337 fProxyList.pop_back();
1338 }
1339 fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343/// Call to delete/destruct individual item.
1344
1345void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
1346{
1347 if ( force && ptr ) {
1348 switch (fSTL_type) {
1349 case ROOT::kSTLmap:
1351 case ROOT::kSTLmultimap:
1353 if ( fKey->fCase&kIsPointer ) {
1356 TPushPop helper(proxy,*(void**)ptr);
1357 proxy->Clear("force");
1358 }
1359 fKey->DeleteItem(*(void**)ptr);
1360 } else {
1363 TPushPop helper(proxy,ptr);
1364 proxy->Clear("force");
1365 }
1366 }
1367 char *addr = ((char*)ptr)+fValOffset;
1368 if ( fVal->fCase&kIsPointer ) {
1371 TPushPop helper(proxy,*(void**)addr);
1372 proxy->Clear("force");
1373 }
1374 fVal->DeleteItem(*(void**)addr);
1375 } else {
1378 TPushPop helper(proxy,addr);
1379 proxy->Clear("force");
1380 }
1381 }
1382 break;
1383 }
1384 default: {
1385 if ( fVal->fCase&kIsPointer ) {
1388 TPushPop helper(proxy,*(void**)ptr);
1389 proxy->Clear("force");
1390 }
1391 fVal->DeleteItem(*(void**)ptr);
1392 } else {
1395 TPushPop helper(proxy,ptr);
1396 proxy->Clear("force");
1397 }
1398 }
1399 break;
1400 }
1401 }
1402 }
1403}
1404
1405////////////////////////////////////////////////////////////////////////////////
1406
1407void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1408{
1409 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1410}
1411
1412////////////////////////////////////////////////////////////////////////////////
1413
1414void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1415{
1416 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1417}
1418
1419////////////////////////////////////////////////////////////////////////////////
1420/// Streamer Function.
1421
1423{
1424 if ( fEnv ) {
1426 return;
1427 }
1428 Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1429}
1430
1431////////////////////////////////////////////////////////////////////////////////
1432/// Streamer I/O overload
1433
1434void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1435{
1436 TPushPop env(this, objp);
1437 Streamer(buff);
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// TClassStreamer IO overload
1442
1444{
1445 Streamer(b, objp, 0);
1446}
1447
1448
1453};
1454
1455////////////////////////////////////////////////////////////////////////////////
1456
1457void TGenCollectionProxy__SlowCreateIterators(void * /* collection */, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
1458{
1459 new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1460 *(UInt_t*)*end_arena = proxy->Size();
1461}
1462
1463////////////////////////////////////////////////////////////////////////////////
1464
1465void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1466{
1468 if (iterator->fIndex != *(UInt_t*)end) {
1469 void *result = iterator->fProxy->At(iterator->fIndex);
1470 ++(iterator->fIndex);
1471 return result;
1472 } else {
1473 return 0;
1474 }
1475}
1476
1477////////////////////////////////////////////////////////////////////////////////
1478
1479void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
1480{
1482 return dest;
1483}
1484
1485////////////////////////////////////////////////////////////////////////////////
1486/// Nothing to do
1487
1489{
1490}
1491
1492////////////////////////////////////////////////////////////////////////////////
1493/// Nothing to do
1494
1496{
1497}
1498
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// We can safely assume that the std::vector layout does not really depend on
1502/// the content!
1503
1504void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy*)
1505{
1506 std::vector<char> *vec = (std::vector<char>*)obj;
1507 if (vec->empty()) {
1508 *begin_arena = 0;
1509 *end_arena = 0;
1510 return;
1511 }
1512 *begin_arena = &(*vec->begin());
1513#ifdef R__VISUAL_CPLUSPLUS
1514 *end_arena = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
1515#else
1516 // coverity[past_the_end] Safe on other platforms
1517 *end_arena = &(*vec->end());
1518#endif
1519
1520}
1521
1522////////////////////////////////////////////////////////////////////////////////
1523/// Should not be used.
1524
1525void *TGenCollectionProxy__VectorNext(void *, const void *)
1526{
1527 R__ASSERT(0);
1528 return 0;
1529}
1530
1531////////////////////////////////////////////////////////////////////////////////
1532
1533void *TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
1534{
1535 *(void**)dest = *(void**)source;
1536 return dest;
1537}
1538
1539////////////////////////////////////////////////////////////////////////////////
1540/// Nothing to do
1541
1543{
1544}
1545
1546////////////////////////////////////////////////////////////////////////////////
1547/// Nothing to do
1548
1550{
1551}
1552
1553
1554
1555////////////////////////////////////////////////////////////////////////////////
1556
1557void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
1558{
1560 *begin_arena = s->GetContent();
1561 *end_arena = s->GetEnd();
1562}
1563
1564////////////////////////////////////////////////////////////////////////////////
1565/// Should not be used.
1566
1567void *TGenCollectionProxy__StagingNext(void *, const void *)
1568{
1569 R__ASSERT(0);
1570 return 0;
1571}
1572
1573////////////////////////////////////////////////////////////////////////////////
1574
1575void *TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
1576{
1577 *(void**)dest = *(void**)source;
1578 return dest;
1579}
1580
1581////////////////////////////////////////////////////////////////////////////////
1582/// Nothing to do
1583
1585{
1586}
1587
1588////////////////////////////////////////////////////////////////////////////////
1589/// Nothing to do
1590
1592{
1593}
1594
1595
1596////////////////////////////////////////////////////////////////////////////////
1597/// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1598/// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1599/// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1600/// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1601
1603{
1604 if (read) {
1605 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1606 if ( (fProperties & kIsAssociative) && read)
1608 }
1609
1611
1612 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1613
1614// fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1615// if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1616// fprintf(stderr,"vector/emulated iterator\n");
1617// else if ( (fProperties & kIsAssociative) && read)
1618// fprintf(stderr,"an associative read iterator\n");
1619// else
1620// fprintf(stderr,"a generic iterator\n");
1621
1622 // TODO could we do better than SlowCreateIterators for RVec?
1625 else if ( (fProperties & kIsAssociative) && read)
1627 else
1629}
1630
1631////////////////////////////////////////////////////////////////////////////////
1632/// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1633/// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1634/// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1635/// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1636
1638{
1639 if (read) {
1640 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1641 if ( (fProperties & kIsAssociative) && read)
1643 }
1644
1646
1647 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1648
1649 // TODO can we do better than the default for RVec?
1652 else if ( (fProperties & kIsAssociative) && read)
1654 else
1656}
1657
1658////////////////////////////////////////////////////////////////////////////////
1659/// See typedef void* (*Next_t)(void *iter, void *end);
1660/// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1661/// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1662/// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1663/// which case 'Next' will return the value of the pointer.
1664
1666{
1667 if (read) {
1668 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1669 if ( (fProperties & kIsAssociative) && read)
1671 }
1672
1674
1675 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1676
1677 // TODO can we do better than the default for RVec?
1680 else if ( (fProperties & kIsAssociative) && read)
1682 else
1684}
1685
1686////////////////////////////////////////////////////////////////////////////////
1687/// See typedef void (*DeleteIterator_t)(void *iter);
1688/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1689/// Otherwise just call the iterator's destructor.
1690
1692{
1693 if (read) {
1694 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1695 if ( (fProperties & kIsAssociative) && read)
1697 }
1698
1700
1701 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1702
1703 // TODO can we do better than the default for RVec?
1706 else if ( (fProperties & kIsAssociative) && read)
1708 else
1710}
1711
1712////////////////////////////////////////////////////////////////////////////////
1713/// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1714/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1715/// Otherwise just call the iterator's destructor.
1716
1718{
1719 if (read) {
1720 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1721 if ( (fProperties & kIsAssociative) && read)
1723 }
1724
1726
1727 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1728
1729 // TODO could RVec use something faster than SlowCopyIterator?
1732 else if ( (fProperties & kIsAssociative) && read)
1734 else
1736}
1737
1738////////////////////////////////////////////////////////////////////////////////
1739/// Return the set of action necessary to stream in this collection member-wise coming from
1740/// the old value class layout refered to by 'version'.
1741
1743{
1744 if (oldClass == 0) {
1745 return 0;
1746 }
1747 TObjArray* arr = 0;
1750 std::map<std::string, TObjArray*>::iterator it;
1751
1752 it = fConversionReadMemberWise->find( oldClass->GetName() );
1753
1754 if( it != fConversionReadMemberWise->end() ) {
1755 arr = it->second;
1756 }
1757
1758 if (arr) {
1760 if (result) {
1761 return result;
1762 }
1763 }
1764 }
1765
1766 // Need to create it.
1767 TClass *valueClass = GetValueClass();
1768 if (valueClass == 0) {
1769 return 0;
1770 }
1771 TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1772 if (info == 0) {
1773 return 0;
1774 }
1776
1777 if (!arr) {
1778 arr = new TObjArray(version+10, -1);
1780 fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1781 }
1782 (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1783 }
1784 arr->AddAtAndExpand( result, version );
1785
1786 return result;
1787}
1788
1789////////////////////////////////////////////////////////////////////////////////
1790/// Return the set of action necessary to stream in this collection member-wise coming from
1791/// the old value class layout refered to by 'version'.
1792
1794{
1796 if (version < (fReadMemberWise->GetSize()-1)) { // -1 because the 'index' starts at -1
1798 }
1799 if (result == 0) {
1800 // Need to create it.
1801 TClass *valueClass = GetValueClass();
1802 TVirtualStreamerInfo *info = 0;
1803 if (valueClass) {
1804 info = valueClass->GetStreamerInfo(version);
1805 }
1808 }
1809 return result;
1810}
1811
1812////////////////////////////////////////////////////////////////////////////////
1813/// Return the set of action necessary to stream out this collection member-wise.
1814
1816{
1818 if (result == 0) {
1819 // Need to create it.
1820 TClass *valueClass = GetValueClass();
1821 TVirtualStreamerInfo *info = 0;
1822 if (valueClass) {
1823 info = valueClass->GetStreamerInfo();
1824 }
1827 }
1828 return result;
1829}
const Handle_t kNone
Definition: GuiTypes.h:88
#define c(i)
Definition: RSha256.hxx:101
#define e(i)
Definition: RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition: RtypesCore.h:63
int Int_t
Definition: RtypesCore.h:45
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kTRUE
Definition: RtypesCore.h:100
unsigned long ULong_t
Definition: RtypesCore.h:55
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:118
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
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h prop
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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
Definition: TInterpreter.h:46
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:565
#define gROOT
Definition: TROOT.h:404
#define R__LOCKGUARD(mutex)
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: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
void ForceReload(TClass *oldcl)
we found at least one equivalent.
Definition: TClass.cxx:1336
EState GetState() const
Definition: TClass.h:485
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition: TClass.cxx:7467
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition: TClass.cxx:7435
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5692
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5900
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:4587
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2897
Int_t GetClassSize() const
Definition: TClass.h:422
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:7074
@ kInterpreted
Definition: TClass.h:126
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThiObject.
Definition: TClass.cxx:7451
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:2968
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:184
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
TGenBitsetProxy(const TGenCollectionProxy &c)
void DeleteItem(Bool_t force, void *ptr) const override
Call to delete/destruct individual item.
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
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.
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version) override
Return the set of action necessary to stream in this collection member-wise coming from the old value...
Method fFirst
Container accessors: generic iteration: first.
std::atomic< Value * > fValue
Descriptor of the container value type.
void Insert(const void *data, void *container, size_t size) override
Insert data into the container where data is a C-style array of the actual type contained in the coll...
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.
TStreamerInfoActions::TActionSequence * fWriteMemberWise
void * Allocate(UInt_t n, Bool_t forceDelete) override
Allocate the needed space.
Bool_t Reset() override
Reset the info gathered from StreamerInfos and value's TClass.
Info_t fTypeinfo
Type information.
int fValOffset
Offset from key to value (in maps)
TClass * GetValueClass() const override
Return a pointer to the TClass representing the content.
EnvironBase_t * fEnv
Address of the currently proxied object.
DeleteIterator_t fFunctionDeleteIterator
Collectfunc_t fCollect
Method to collect objects from container.
void PushProxy(void *objstart) override
Add an object.
void PopProxy() override
Remove the last object.
EDataType GetType() const override
If the content is a simple numerical value, return its type (see TDataType)
TGenCollectionProxy * Initialize(Bool_t silent) const
Proxy initializer.
virtual TGenCollectionProxy * InitializeEx(Bool_t silent)
Proxy initializer.
void Commit(void *env) override
Commit the change.
std::string fName
Name of the class being proxied.
CopyIterator_t GetFunctionCopyIterator(Bool_t read=kTRUE) override
See typedef void (*CopyIterator_t)(void *&dest, const void *source); Copy the iterator source,...
int fSTL_type
STL container type.
CopyIterator_t fFunctionCopyIterator
ULong_t GetIncrement() const override
Return the offset between two consecutive value_types (memory layout).
Value * fKey
Descriptor of the key_type.
virtual void Resize(UInt_t n, Bool_t force_delete)
Resize the container.
Int_t GetCollectionType() const override
Return the type of collection see TClassEdit::ESTLType.
void Clear(const char *opt="") override
Clear the emulated collection.
Proxies_t fProxyList
Stack of recursive proxies.
DeleteIterator_t GetFunctionDeleteIterator(Bool_t read=kTRUE) override
See typedef void (*DeleteIterator_t)(void *iter); If the sizeof iterator is greater than fgIteratorAr...
UInt_t Size() const override
Return the current size of the container.
Sizing_t fDestruct
Container accessors: block destruct.
Method0 fCreateEnv
Method to allocate an Environment holder.
Value * fVal
Descriptor of the Value_type.
Next_t GetFunctionNext(Bool_t read=kTRUE) override
See typedef void* (*Next_t)(void *iter, void *end); iter and end should be pointer to respectively an...
virtual void operator()(TBuffer &refBuffer, void *pObject)
TClassStreamer IO overload.
TClass * fOnFileClass
On file class.
Sizing_t fResize
Container accessors: resize container.
ArrIterfunc_t fConstruct
Container accessors: block construct.
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE) override
See typedef void (*DeleteTwoIterators_t)(void *begin, void *end); If the sizeof iterator is greater t...
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.
virtual TVirtualCollectionProxy * Generate() const override
Virtual copy constructor.
DeleteTwoIterators_t fFunctionDeleteTwoIterators
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions() override
Return the set of action necessary to stream out this collection member-wise.
Bool_t HasPointers() const override
Return true if the content is of type 'pointer to'.
CreateIterators_t fFunctionCreateIterators
TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version) override
Return the set of action necessary to stream in this collection member-wise coming from the old value...
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.
TClass * GetCollectionClass() const override
Return a pointer to the TClass representing the container.
Staged_t fStaged
Optimization: Keep staged array once they were created.
Method fSize
Container accessors: size of container.
Method fClear
Method cache for container accessors: clear container.
Feedfunc_t fFeed
Container accessors: block feed.
CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE) override
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.
UInt_t Sizeof() const override
Return the sizeof the collection object.
const std::type_info & Info_t
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
TGenListProxy(const TGenCollectionProxy &c)
Localoptimization class.
TGenMapProxy(const TGenCollectionProxy &c)
void DeleteItem(Bool_t force, void *ptr) const override
Call to delete/destruct individual item.
Localoptimization class.
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
TGenSetProxy(const TGenCollectionProxy &c)
Local optimization class.
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
TGenVectorBoolProxy(const TGenCollectionProxy &c)
void DeleteItem(Bool_t force, void *ptr) const override
Call to delete/destruct individual item.
Local optimization class.
void DeleteItem(Bool_t force, void *ptr) const override
Call to delete/destruct individual item.
void * At(UInt_t idx) override
Return the address of the value at index 'idx'.
TGenVectorProxy(const TGenCollectionProxy &c)
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:531
virtual void TypeInfo_Delete(TypeInfo_t *) const
Definition: TInterpreter.h:527
virtual TypeInfo_t * TypeInfo_Factory() const
Definition: TInterpreter.h:528
virtual Long_t TypeInfo_Property(TypeInfo_t *) const
Definition: TInterpreter.h:534
virtual int TypeInfo_Size(TypeInfo_t *) const
Definition: TInterpreter.h:536
virtual Bool_t TypeInfo_IsValid(TypeInfo_t *) const
Definition: TInterpreter.h:532
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:31
void Clear(Option_t *option="") override
Remove all objects from the array.
Definition: TObjArray.cxx:321
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:235
TObject * At(Int_t idx) const override
Definition: TObjArray.h:164
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 '...
static TClass * Class()
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 void * At(UInt_t idx)=0
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
Generate the TClass and TStreamerInfo for the requested pair.
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
@ kROOTRVec
Definition: ESTLType.h:46
@ 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:528
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:621
static constexpr double s
const char * Value
Definition: TXMLSetup.cxx:73
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.
TGenCollectionProxy__SlowIterator(TVirtualCollectionProxy *proxy)
Definition: civetweb.c:1856