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
40public:
41 // Standard Destructor
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 ) {
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;
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
196 // Standard Destructor
197 ~TGenListProxy() override
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
238 // Standard Destructor
239 ~TGenSetProxy() override
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
283 // Standard Destructor
284 ~TGenMapProxy() override
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;
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
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
329
330 bool isPointer = false;
331 // The incoming name is normalized (it comes from splitting the name of a TClass),
332 // so all we need to do is drop the last trailing star (if any) and record that information.
333 if (intype.back() == '*') {
334 isPointer = true;
335 intype.pop_back();
336 if (intype.back() == '*') {
337 // The value is a pointer to a pointer
338 if (!silent)
339 Warning("TGenCollectionProxy::Value::Value", "I/O not supported for collection of pointer to pointer: %s", inside_type.c_str());
340 fSize = sizeof(void*);
341 fKind = kVoid_t;
342 return;
343 }
344 }
345
346 if ( intype.substr(0,6) == "string" || intype.substr(0,11) == "std::string" ) {
348 fType = TClass::GetClass("string");
349 fCtor = fType->GetNew();
352 if (isPointer) {
353 fCase |= kIsPointer;
354 fSize = sizeof(void*);
355 } else {
356 fSize = sizeof(std::string);
357 }
358 }
359 else {
360 // In the case where we have an emulated class,
361 // if the class is nested (in a class or a namespace),
362 // calling G__TypeInfo ti(inside.c_str());
363 // might fail because CINT does not known the nesting
364 // scope, so let's first look for an emulated class:
365
367
368 if (fType) {
369 if (isPointer) {
370 fCase |= kIsPointer;
371 fSize = sizeof(void*);
372 if (fType == TString::Class()) {
374 }
375 }
376 fCase |= kIsClass;
377 fCtor = fType->GetNew();
380 } else {
382
383 // Try to avoid autoparsing.
384
385 THashTable *typeTable = dynamic_cast<THashTable*>( gROOT->GetListOfTypes() );
386 assert(typeTable && "The type of the list of type has changed");
387
388 TDataType *fundType = (TDataType *)typeTable->THashTable::FindObject( intype.c_str() );
389 if (fundType && fundType->GetType() < 0x17 && fundType->GetType() > 0) {
390 fKind = (EDataType)fundType->GetType();
391 // R__ASSERT((fKind>0 && fKind<0x17) || (fKind==-1&&(prop&kIsPointer)) );
392
394 if (isPointer) {
395 fCase |= kIsPointer;
396 fSize = sizeof(void*);
397 } else {
398 fSize = fundType->Size();
399 }
400 } else if (auto e = TEnum::GetEnum(intype.c_str(), TEnum::kNone)) {
401 R__ASSERT(e->IsValid());
402 // This is a known enum.
403 fCase = kIsEnum;
404 fSize = TDataType::GetDataType(e->GetUnderlyingType())->Size();
405 fKind = e->GetUnderlyingType();
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
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;
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Build a proxy for a collection whose type is described by 'collectionClass'.
595
598 fTypeinfo(info)
599{
600 fEnv = 0;
601 fSize.call = 0;
602 fFirst.call = 0;
603 fNext.call = 0;
604 fClear.call = 0;
605 fResize = 0;
606 fDestruct = 0;
607 fConstruct = 0;
608 fCollect = 0;
609 fCreateEnv.call = 0;
610 fFeed = 0;
611 fValue = 0;
612 fKey = 0;
613 fVal = 0;
614 fValOffset = 0;
615 fValDiff = 0;
616 fPointers = false;
617 fOnFileClass = 0;
619 Env_t e;
620 if ( iter_size > sizeof(e.fIterator) ) {
621 Fatal("TGenCollectionProxy",
622 "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
623 "Iterators for collection",
624 fClass->GetName(),
626 (Long_t)sizeof(e.fIterator));
627 }
637}
638
639////////////////////////////////////////////////////////////////////////////////
640/// Build a proxy for a collection whose type is described by 'collectionClass'.
641
644 fTypeinfo(info.fInfo), fOnFileClass(0)
645{
646 fEnv = 0;
647 fValDiff = info.fValueDiff;
648 fValOffset = info.fValueOffset;
649 fSize.call = info.fSizeFunc;
650 fResize = info.fResizeFunc;
651 fNext.call = info.fNextFunc;
652 fFirst.call = info.fFirstFunc;
653 fClear.call = info.fClearFunc;
654 fConstruct = info.fConstructFunc;
655 fDestruct = info.fDestructFunc;
656 fFeed = info.fFeedFunc;
657 fCollect = info.fCollectFunc;
658 fCreateEnv.call = info.fCreateEnv;
659
660 if (cl) {
661 fName = cl->GetName();
662 }
664
665 fValue = 0;
666 fKey = 0;
667 fVal = 0;
668 fPointers = false;
670
671 Env_t e;
672 if ( info.fIterSize > sizeof(e.fIterator) ) {
673 Fatal("TGenCollectionProxy",
674 "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
675 "Iterators for collection",
676 fClass->GetName(),
677 (Long_t)info.fIterSize,
678 (Long_t)sizeof(e.fIterator));
679 }
684 fFunctionCreateIterators = info.fCreateIterators;
685 fFunctionCopyIterator = info.fCopyIterator;
687 fFunctionDeleteIterator = info.fDeleteSingleIterator;
688 fFunctionDeleteTwoIterators = info.fDeleteTwoIterators;
689}
690
691namespace {
692 template <class vec>
693 void clearVector(vec& v)
694 {
695 // Clear out the proxies.
696
697 for(typename vec::iterator i=v.begin(); i != v.end(); ++i) {
698 typename vec::value_type e = *i;
699 if ( e ) {
700 delete e;
701 }
702 }
703 v.clear();
704 }
705}
706////////////////////////////////////////////////////////////////////////////////
707/// Standard destructor
708
710{
714
715 if ( fValue.load() ) delete fValue.load();
716 if ( fVal ) delete fVal;
717 if ( fKey ) delete fKey;
718
719 delete fReadMemberWise;
721 std::map<std::string, TObjArray*>::iterator it;
722 std::map<std::string, TObjArray*>::iterator end = fConversionReadMemberWise->end();
723 for( it = fConversionReadMemberWise->begin(); it != end; ++it ) {
724 delete it->second;
725 }
728 }
729 delete fWriteMemberWise;
730}
731
732////////////////////////////////////////////////////////////////////////////////
733/// Virtual copy constructor
734
736{
737 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
738
739 if( fPointers )
740 return new TGenCollectionProxy(*this);
741
742 switch(fSTL_type) {
743 case ROOT::kSTLbitset: {
744 return new TGenBitsetProxy(*this);
745 }
746 case ROOT::kSTLvector: {
747 if ((*fValue).fKind == kBool_t) {
748 return new TGenVectorBoolProxy(*this);
749 } else {
750 return new TGenVectorProxy(*this);
751 }
752 }
753 case ROOT::kSTLlist:
755 return new TGenListProxy(*this);
756 case ROOT::kSTLmap:
760 return new TGenMapProxy(*this);
761 case ROOT::kSTLset:
765 return new TGenSetProxy(*this);
766 default:
767 return new TGenCollectionProxy(*this);
768 }
769}
770
771////////////////////////////////////////////////////////////////////////////////
772/// Proxy initializer
773
775{
776 TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this);
777 if ( fValue.load() ) return p;
778 return p->InitializeEx(silent);
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// Reset the info gathered from StreamerInfos and value's TClass.
793
794////////////////////////////////////////////////////////////////////////////////
795/// Check existence of function pointers
796
798{
799 if ( 0 == fSize.call ) {
800 Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str());
801 }
802 if ( 0 == fResize ) {
803 Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str());
804 }
805 if ( 0 == fNext.call ) {
806 Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str());
807 }
808 if ( 0 == fFirst.call ) {
809 Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str());
810 }
811 if ( 0 == fClear.call ) {
812 Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str());
813 }
814 if ( 0 == fConstruct ) {
815 Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str());
816 }
817 if ( 0 == fDestruct ) {
818 Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str());
819 }
820 if ( 0 == fFeed ) {
821 Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str());
822 }
823 if ( 0 == fCollect ) {
824 Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str());
825 }
826 if (0 == fCreateEnv.call ) {
827 Fatal("TGenCollectionProxy","No 'environment creation' function for class %s present.",fName.c_str());
828 }
829}
830
831////////////////////////////////////////////////////////////////////////////////
832/// Utility routine to issue a Fatal error is the Value object is not valid
833
835 size_t hint_pair_offset = 0, size_t hint_pair_size = 0)
836{
838 if ( !val->IsValid() ) {
839 Fatal("TGenCollectionProxy","Could not find %s!",name.c_str());
840 }
841 return val;
842}
843
844////////////////////////////////////////////////////////////////////////////////
845/// Proxy initializer
846
848{
850 if (fValue.load()) return this;
851
853 if ( cl ) {
854 fEnv = 0;
855 fName = cl->GetName();
856 fPointers = false;
857 int nested = 0;
858 std::vector<std::string> inside;
859 int num = TClassEdit::GetSplit(cl->GetName(),inside,nested);
860 if ( num > 1 ) {
861 std::string nam;
862 Value* newfValue = nullptr;
863 if ( inside[0].find("stdext::hash_") != std::string::npos )
864 inside[0].replace(3,10,"::");
865 if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos )
866 inside[0].replace(0,16,"std::");
867 fSTL_type = TClassEdit::STLKind(inside[0]);
868 switch ( fSTL_type ) {
869 case ROOT::kSTLmap:
873 case ROOT::kSTLset:
877 case ROOT::kSTLbitset: // not really an associate container but it has no real iterator.
879 if (num > 3 && !inside[3].empty()) {
880 if (! TClassEdit::IsDefAlloc(inside[3].c_str(),inside[0].c_str())) {
882 }
883 }
884 break;
885 };
886
887 int slong = sizeof(void*);
888 switch ( fSTL_type ) {
889 case ROOT::kSTLmap:
893 nam = "pair<"+inside[1]+","+inside[2];
894 nam += (nam[nam.length()-1]=='>') ? " >" : ">";
895
896 fVal = R__CreateValue(inside[2], silent);
897 fKey = R__CreateValue(inside[1], silent);
898
899 {
901 TClass *paircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
902 if (paircl == nullptr) {
903 // We need to emulate the pair
904 auto info = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1], inside[2], silent, fValOffset, fValDiff);
905 if (!info) {
906 Fatal("InitializeEx",
907 "Could not load nor generate the dictionary for \"%s\", some element might be missing their dictionary (eg. enums)",
908 nam.c_str());
909 }
910 } else {
911 if ((!paircl->IsSyntheticPair() && paircl->GetState() < TClass::kInterpreted) || paircl->GetClassSize() != fValDiff) {
912 if (paircl->GetState() >= TClass::kInterpreted)
913 Fatal("InitializeEx",
914 "The %s for %s reports a class size that is inconsistent with the one registered "
915 "through the CollectionProxy for %s: %d vs %d\n",
916 paircl->IsLoaded() ? "dictionary" : "interpreter information for", nam.c_str(),
917 cl->GetName(), (int)paircl->GetClassSize(), (int)fValDiff);
918 else {
919 gROOT->GetListOfClasses()->Remove(paircl);
920 TClass *newpaircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
921 if (!newpaircl || newpaircl == paircl || newpaircl->GetClassSize() != fValDiff)
922 Fatal("InitializeEx",
923 "The TClass creation for %s did not get the right size: %d instead of%d\n",
924 nam.c_str(), (int)paircl->GetClassSize(), (int)fValDiff);
925 newpaircl->ForceReload(paircl);
926 }
927 }
928 }
929 }
931
932 fPointers = (0 != (fKey->fCase&kIsPointer));
933 if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
935 }
936 if ( 0 == fValDiff ) {
940 }
941 if ( 0 == fValOffset ) {
944 }
945 break;
946 case ROOT::kSTLbitset:
947 inside[1] = "bool";
948 // Intentional fall through
949 default:
950 newfValue = R__CreateValue(inside[1], silent);
951
952 fVal = new Value(*newfValue);
953 if ( 0 == fValDiff ) {
956 }
957 if (num > 2 && !inside[2].empty()) {
958 if (! TClassEdit::IsDefAlloc(inside[2].c_str(),inside[0].c_str())) {
960 }
961 }
962 break;
963 }
964 if (!(fProperties & kIsEmulated) && newfValue->fType && !newfValue->fType->IsSyntheticPair()) {
965 if (!newfValue->fType->IsLoaded() && !newfValue->fType->HasInterpreterInfo())
966 Error("TGenCollectionProxy::InitializeEx",
967 "The TClass for %s used as the value type of the compiled collection proxy %s is not loaded.",
968 newfValue->fType->GetName(), cl->GetName());
969 }
970
971 fPointers = fPointers || (0 != (fVal->fCase&kIsPointer));
972 if (fPointers || (0 != (fVal->fProperties&kNeedDelete))) {
974 }
975 fClass = cl;
976 //fValue must be set last since we use it to indicate that we are initialized
978 return this;
979 }
980 Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName());
981 }
982 Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name());
983 return 0;
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Return a pointer to the TClass representing the container
988
993
994////////////////////////////////////////////////////////////////////////////////
995/// Return the type of collection see TClassEdit::ESTLType
996
998{
999 if (!fValue.load(std::memory_order_relaxed)) {
1001 }
1002 return fSTL_type;
1003}
1004
1005////////////////////////////////////////////////////////////////////////////////
1006/// Return the offset between two consecutive value_types (memory layout).
1007
1009 if (!fValue.load(std::memory_order_relaxed)) {
1011 }
1012 return fValDiff;
1013}
1014
1015////////////////////////////////////////////////////////////////////////////////
1016/// Return the sizeof the collection object.
1017
1019{
1020 return fClass->Size();
1021}
1022
1023////////////////////////////////////////////////////////////////////////////////
1024/// Return true if the content is of type 'pointer to'
1025
1027{
1028 // Initialize proxy in case it hasn't been initialized yet
1029 if( !fValue.load(std::memory_order_relaxed) )
1031
1032 // The content of a map and multimap is always a 'pair' and hence
1033 // fPointers means "Flag to indicate if containee has pointers (key or value)"
1034 // so we need to ignore its value for map and multimap;
1037}
1038
1039////////////////////////////////////////////////////////////////////////////////
1040/// Return a pointer to the TClass representing the content.
1041
1043{
1044 auto value = fValue.load(std::memory_order_relaxed);
1045 if (!value) {
1047 value = fValue.load(std::memory_order_relaxed);
1048 }
1049 return value ? (*value).fType.GetClass() : 0;
1050}
1051
1052////////////////////////////////////////////////////////////////////////////////
1053/// If the content is a simple numerical value, return its type (see TDataType)
1054
1056{
1057 auto value = fValue.load(std::memory_order_relaxed);
1058 if (!value) {
1060 value = fValue.load(std::memory_order_relaxed);
1061 }
1062 return value ? (*value).fKind : kNoType_t;
1063}
1064
1065////////////////////////////////////////////////////////////////////////////////
1066/// Return the address of the value at index 'idx'
1067
1069{
1070 if ( fEnv && fEnv->fObject ) {
1071 switch (fSTL_type) {
1072 case ROOT::kSTLvector:
1073 if ((*fValue).fKind == kBool_t) {
1074 auto vec = (std::vector<bool> *)(fEnv->fObject);
1075 fEnv->fLastValueVecBool = (*vec)[idx];
1076 fEnv->fIdx = idx;
1077 return &(fEnv->fLastValueVecBool);
1078 }
1079 // intentional fall through
1080 case ROOT::kROOTRVec:
1081 fEnv->fIdx = idx;
1082 switch( idx ) {
1083 case 0:
1084 return fEnv->fStart = fFirst.invoke(fEnv);
1085 default:
1086 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1087 return ((char*)fEnv->fStart) + fValDiff*idx;
1088 }
1089 case ROOT::kSTLbitset: {
1090 switch (idx) {
1091 case 0:
1093 fEnv->fIdx = idx;
1094 break;
1095 default:
1096 fEnv->fIdx = idx - fEnv->fIdx;
1097 if (!fEnv->fStart) fEnv->fStart = fFirst.invoke(fEnv);
1098 fNext.invoke(fEnv);
1099 fEnv->fIdx = idx;
1100 break;
1101 }
1102 typedef ROOT::TCollectionProxyInfo::Environ <std::pair<size_t, Bool_t>> EnvType_t;
1103 EnvType_t *e = (EnvType_t *) fEnv;
1104 return &(e->fIterator.second);
1105 }
1106 case ROOT::kSTLset:
1108 case ROOT::kSTLmultiset:
1110 case ROOT::kSTLmap:
1112 case ROOT::kSTLmultimap:
1114 if ( fEnv->fUseTemp ) {
1115 return (((char*)fEnv->fTemp)+idx*fValDiff);
1116 }
1117 // Intentional fall through.
1118 default:
1119 switch( idx ) {
1120 case 0:
1121 fEnv->fIdx = idx;
1122 return fEnv->fStart = fFirst.invoke(fEnv);
1123 default: {
1124 fEnv->fIdx = idx - fEnv->fIdx;
1125 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1126 void* result = fNext.invoke(fEnv);
1127 fEnv->fIdx = idx;
1128 return result;
1129 }
1130 }
1131 }
1132 }
1133 Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1134 return 0;
1135}
1136
1137////////////////////////////////////////////////////////////////////////////////
1138/// Clear the emulated collection.
1139
1140void TGenCollectionProxy::Clear(const char* opt)
1141{
1142 if ( fEnv && fEnv->fObject ) {
1143 if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1144 size_t i, n = *(size_t*)fSize.invoke(fEnv);
1145 if ( n > 0 ) {
1146 for (i=0; i<n; ++i)
1148 }
1149 }
1151 }
1152}
1153
1154////////////////////////////////////////////////////////////////////////////////
1155/// Return the current size of the container
1156
1158{
1159 if ( fEnv && fEnv->fObject ) {
1160 if (fEnv->fUseTemp) {
1161 return fEnv->fSize;
1162 } else {
1163 return *(size_t*)fSize.invoke(fEnv);
1164 }
1165 }
1166 Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1167 return 0;
1168}
1169
1170////////////////////////////////////////////////////////////////////////////////
1171/// Resize the container
1172
1174{
1175 if ( fEnv && fEnv->fObject ) {
1176 if ( force && fPointers ) {
1177 size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1178 if ( n != nold ) {
1179 for (i=n; i<nold; ++i)
1180 DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1181 }
1182 }
1183 MESSAGE(3, "Resize(n)" );
1184 fEnv->fSize = n;
1186 return;
1187 }
1188 Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1189}
1190
1191////////////////////////////////////////////////////////////////////////////////
1192/// Allocate the needed space.
1193/// For associative collection, this returns a TStaging object that
1194/// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1195
1197{
1198 if ( fEnv && fEnv->fObject ) {
1199 switch ( fSTL_type ) {
1200 case ROOT::kSTLset:
1202 case ROOT::kSTLmultiset:
1204 case ROOT::kSTLmap:
1206 case ROOT::kSTLmultimap:
1208 if ( (fProperties & kNeedDelete) )
1209 Clear("force");
1210 else
1212 // Commit no longer use the environment and thus no longer decrease
1213 // the count. Consequently we no longer should increase it here.
1214 // ++fEnv->fRefCount;
1215 fEnv->fSize = n;
1216
1217 TStaging *s;
1218 if (fStaged.empty()) {
1219 s = new TStaging(n,fValDiff);
1220 } else {
1221 s = fStaged.back();
1222 fStaged.pop_back();
1223 s->Resize(n);
1224 }
1225 fConstruct(s->GetContent(),s->GetSize());
1226
1227 s->SetTarget(fEnv->fObject);
1228
1229 fEnv->fTemp = s->GetContent();
1230 fEnv->fUseTemp = kTRUE;
1231 fEnv->fStart = fEnv->fTemp;
1232
1233 return s;
1234 }
1235 case ROOT::kSTLvector:
1236 case ROOT::kSTLlist:
1238 case ROOT::kSTLdeque:
1239 case ROOT::kROOTRVec:
1240 if( (fProperties & kNeedDelete) ) {
1241 Clear("force");
1242 }
1243 fEnv->fSize = n;
1245 return fEnv->fObject;
1246
1247 case ROOT::kSTLbitset: {
1248 TStaging *s;
1249 if (fStaged.empty()) {
1250 s = new TStaging(n,fValDiff);
1251 } else {
1252 s = fStaged.back();
1253 fStaged.pop_back();
1254 s->Resize(n);
1255 }
1256 s->SetTarget(fEnv->fObject);
1257
1258 fEnv->fTemp = s->GetContent();
1259 fEnv->fUseTemp = kTRUE;
1260 fEnv->fStart = fEnv->fTemp;
1261
1262 return s;
1263 }
1264 }
1265 }
1266 return 0;
1267}
1268
1269////////////////////////////////////////////////////////////////////////////////
1270/// Insert data into the container where data is a C-style array of the actual type contained in the collection
1271/// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1272
1273void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1274{
1275 fFeed((void*)data,container,size);
1276}
1277
1278////////////////////////////////////////////////////////////////////////////////
1279/// Commit the change.
1280
1282{
1284// case ROOT::kSTLmap:
1285// case ROOT::kSTLmultimap:
1286// case ROOT::kSTLset:
1287// case ROOT::kSTLmultiset:
1288 if ( from ) {
1289 TStaging *s = (TStaging*) from;
1290 if ( s->GetTarget() ) {
1291 fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1292 }
1293 fDestruct(s->GetContent(),s->GetSize());
1294 s->SetTarget(0);
1295 fStaged.push_back(s);
1296 }
1297 }
1298}
1299
1300////////////////////////////////////////////////////////////////////////////////
1301/// Add an object.
1302
1304{
1305 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
1306 if ( !fProxyList.empty() ) {
1307 EnvironBase_t* back = fProxyList.back();
1308 if ( back->fObject == objstart ) {
1309 ++back->fRefCount;
1310 fProxyList.push_back(back);
1311 fEnv = back;
1312 return;
1313 }
1314 }
1315 EnvironBase_t* e = 0;
1316 if ( fProxyKept.empty() ) {
1318 e->fTemp = 0;
1319 e->fUseTemp = kFALSE;
1320 }
1321 else {
1322 e = fProxyKept.back();
1323 fProxyKept.pop_back();
1324 }
1325 e->fSize = 0;
1326 e->fRefCount = 1;
1327 e->fObject = objstart;
1328 e->fStart = 0;
1329 e->fIdx = 0;
1330 // ::memset(e->buff,0,sizeof(e->buff));
1331 fProxyList.push_back(e);
1332 fEnv = e;
1333}
1334
1335////////////////////////////////////////////////////////////////////////////////
1336/// Remove the last object.
1337
1339{
1340 if ( !fProxyList.empty() ) {
1341 EnvironBase_t* e = fProxyList.back();
1342 if ( --e->fRefCount <= 0 ) {
1343 fProxyKept.push_back(e);
1344 e->fUseTemp = kFALSE;
1345 }
1346 fProxyList.pop_back();
1347 }
1348 fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1349}
1350
1351////////////////////////////////////////////////////////////////////////////////
1352/// Call to delete/destruct individual item.
1353
1355{
1356 if ( force && ptr ) {
1357 switch (fSTL_type) {
1358 case ROOT::kSTLmap:
1360 case ROOT::kSTLmultimap:
1362 if ( fKey->fCase&kIsPointer ) {
1365 TPushPop helper(proxy,*(void**)ptr);
1366 proxy->Clear("force");
1367 }
1368 fKey->DeleteItem(*(void**)ptr);
1369 } else {
1372 TPushPop helper(proxy,ptr);
1373 proxy->Clear("force");
1374 }
1375 }
1376 char *addr = ((char*)ptr)+fValOffset;
1377 if ( fVal->fCase&kIsPointer ) {
1380 TPushPop helper(proxy,*(void**)addr);
1381 proxy->Clear("force");
1382 }
1383 fVal->DeleteItem(*(void**)addr);
1384 } else {
1388 proxy->Clear("force");
1389 }
1390 }
1391 break;
1392 }
1393 default: {
1394 if ( fVal->fCase&kIsPointer ) {
1397 TPushPop helper(proxy,*(void**)ptr);
1398 proxy->Clear("force");
1399 }
1400 fVal->DeleteItem(*(void**)ptr);
1401 } else {
1404 TPushPop helper(proxy,ptr);
1405 proxy->Clear("force");
1406 }
1407 }
1408 break;
1409 }
1410 }
1411 }
1412}
1413
1414////////////////////////////////////////////////////////////////////////////////
1415
1416void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1417{
1418 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1419}
1420
1421////////////////////////////////////////////////////////////////////////////////
1422
1423void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1424{
1425 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1426}
1427
1428////////////////////////////////////////////////////////////////////////////////
1429/// Streamer Function.
1430
1432{
1433 if ( fEnv ) {
1435 return;
1436 }
1437 Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// Streamer I/O overload
1442
1443void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1444{
1445 TPushPop env(this, objp);
1446 Streamer(buff);
1447}
1448
1449////////////////////////////////////////////////////////////////////////////////
1450/// TClassStreamer IO overload
1451
1453{
1454 Streamer(b, objp, 0);
1455}
1456
1457
1463
1464////////////////////////////////////////////////////////////////////////////////
1465
1467{
1468 new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1469 *(UInt_t*)*end_arena = proxy->Size();
1470}
1471
1472////////////////////////////////////////////////////////////////////////////////
1473
1474void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1475{
1477 if (iterator->fIndex != *(UInt_t*)end) {
1478 void *result = iterator->fProxy->At(iterator->fIndex);
1479 ++(iterator->fIndex);
1480 return result;
1481 } else {
1482 return 0;
1483 }
1484}
1485
1486////////////////////////////////////////////////////////////////////////////////
1487
1493
1494////////////////////////////////////////////////////////////////////////////////
1495/// Nothing to do
1496
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Nothing to do
1503
1505{
1506}
1507
1508
1509////////////////////////////////////////////////////////////////////////////////
1510/// We can safely assume that the std::vector layout does not really depend on
1511/// the content!
1512
1514{
1515 std::vector<char> *vec = (std::vector<char>*)obj;
1516 if (vec->empty()) {
1517 *begin_arena = 0;
1518 *end_arena = 0;
1519 return;
1520 }
1521 *begin_arena = vec->data();
1522 *end_arena = vec->data() + vec->size();
1523
1524}
1525
1526////////////////////////////////////////////////////////////////////////////////
1527/// Should not be used.
1528
1529void *TGenCollectionProxy__VectorNext(void *, const void *)
1530{
1531 R__ASSERT(0);
1532 return 0;
1533}
1534
1535////////////////////////////////////////////////////////////////////////////////
1536
1538{
1539 *(void**)dest = *(void**)source;
1540 return dest;
1541}
1542
1543////////////////////////////////////////////////////////////////////////////////
1544/// Nothing to do
1545
1549
1550////////////////////////////////////////////////////////////////////////////////
1551/// Nothing to do
1552
1554{
1555}
1556
1557
1558
1559////////////////////////////////////////////////////////////////////////////////
1560
1567
1568////////////////////////////////////////////////////////////////////////////////
1569/// Should not be used.
1570
1571void *TGenCollectionProxy__StagingNext(void *, const void *)
1572{
1573 R__ASSERT(0);
1574 return 0;
1575}
1576
1577////////////////////////////////////////////////////////////////////////////////
1578
1580{
1581 *(void**)dest = *(void**)source;
1582 return dest;
1583}
1584
1585////////////////////////////////////////////////////////////////////////////////
1586/// Nothing to do
1587
1591
1592////////////////////////////////////////////////////////////////////////////////
1593/// Nothing to do
1594
1596{
1597}
1598
1599
1600////////////////////////////////////////////////////////////////////////////////
1601/// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1602/// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1603/// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1604/// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1605
1607{
1608 if (read) {
1609 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1610 if ( (fProperties & kIsAssociative) && read)
1612 }
1613
1615
1616 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1617
1618// fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1619// if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1620// fprintf(stderr,"vector/emulated iterator\n");
1621// else if ( (fProperties & kIsAssociative) && read)
1622// fprintf(stderr,"an associative read iterator\n");
1623// else
1624// fprintf(stderr,"a generic iterator\n");
1625
1626 // TODO could we do better than SlowCreateIterators for RVec?
1629 else if ( (fProperties & kIsAssociative) && read)
1631 else
1633}
1634
1635////////////////////////////////////////////////////////////////////////////////
1636/// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1637/// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1638/// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1639/// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1640
1642{
1643 if (read) {
1644 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1645 if ( (fProperties & kIsAssociative) && read)
1647 }
1648
1650
1651 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1652
1653 // TODO can we do better than the default for RVec?
1656 else if ( (fProperties & kIsAssociative) && read)
1658 else
1660}
1661
1662////////////////////////////////////////////////////////////////////////////////
1663/// See typedef void* (*Next_t)(void *iter, void *end);
1664/// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1665/// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1666/// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1667/// which case 'Next' will return the value of the pointer.
1668
1670{
1671 if (read) {
1672 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1673 if ( (fProperties & kIsAssociative) && read)
1675 }
1676
1678
1679 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1680
1681 // TODO can we do better than the default for RVec?
1684 else if ( (fProperties & kIsAssociative) && read)
1686 else
1688}
1689
1690////////////////////////////////////////////////////////////////////////////////
1691/// See typedef void (*DeleteIterator_t)(void *iter);
1692/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1693/// Otherwise just call the iterator's destructor.
1694
1696{
1697 if (read) {
1698 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1699 if ( (fProperties & kIsAssociative) && read)
1701 }
1702
1704
1705 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1706
1707 // TODO can we do better than the default for RVec?
1710 else if ( (fProperties & kIsAssociative) && read)
1712 else
1714}
1715
1716////////////////////////////////////////////////////////////////////////////////
1717/// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1718/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1719/// Otherwise just call the iterator's destructor.
1720
1722{
1723 if (read) {
1724 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1725 if ( (fProperties & kIsAssociative) && read)
1727 }
1728
1730
1731 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1732
1733 // TODO could RVec use something faster than SlowCopyIterator?
1736 else if ( (fProperties & kIsAssociative) && read)
1738 else
1740}
1741
1742////////////////////////////////////////////////////////////////////////////////
1743/// Return the set of action necessary to stream in this collection member-wise coming from
1744/// the old value class layout refered to by 'version'.
1745
1747{
1748 if (oldClass == 0) {
1749 return 0;
1750 }
1751 TObjArray* arr = 0;
1754 std::map<std::string, TObjArray*>::iterator it;
1755
1756 it = fConversionReadMemberWise->find( oldClass->GetName() );
1757
1758 if( it != fConversionReadMemberWise->end() ) {
1759 arr = it->second;
1760 }
1761
1762 if (arr) {
1764 if (result) {
1765 return result;
1766 }
1767 }
1768 }
1769
1770 // Need to create it.
1772 if (valueClass == 0) {
1773 return 0;
1774 }
1775 TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1776 if (info == 0) {
1777 return 0;
1778 }
1780
1781 if (!arr) {
1782 arr = new TObjArray(version+10, -1);
1784 fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1785 }
1786 (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1787 }
1788 arr->AddAtAndExpand( result, version );
1789
1790 return result;
1791}
1792
1793////////////////////////////////////////////////////////////////////////////////
1794/// Return the set of action necessary to stream in this collection member-wise coming from
1795/// the old value class layout refered to by 'version'.
1796
1815
1816////////////////////////////////////////////////////////////////////////////////
1817/// Return the set of action necessary to stream out this collection member-wise.
1818
#define b(i)
Definition RSha256.hxx:100
#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
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
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:168
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
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:244
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 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
R__EXTERN TInterpreter * gCling
#define gROOT
Definition TROOT.h:414
#define R__LOCKGUARD(mutex)
Buffer base class used for serializing objects.
Definition TBuffer.h:43
TClass * GetClass() const
Definition TClassRef.h:67
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:616
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition TClass.cxx:7669
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition TClass.cxx:7637
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5844
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:3003
@ kInterpreted
Definition TClass.h:129
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThisObject.
Definition TClass.cxx:7653
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:3074
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
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
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:182
@ kNone
Definition TEnum.h:49
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...
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
~TGenCollectionProxy() override
Standard destructor.
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.
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
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
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
void Clear(Option_t *option="") override
Remove all objects from the array.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
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()
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
*begin_arena and *end_arena should contain the location of a memory arena of size fgIteratorArenaSize...
@ kCustomAlloc
The collection has a custom allocator.
@ kNeedDelete
The collection contains directly or indirectly (via other collection) some pointers that need explici...
void *(* CopyIterator_t)(void *dest, const void *source)
Copy the iterator source into dest.
void *(* Next_t)(void *iter, const void *end)
iter and end should be pointers to an iterator to be incremented and an iterator that points to the e...
void(* DeleteTwoIterators_t)(void *begin, void *end)
void(* DeleteIterator_t)(void *iter)
If the size of the iterator is greater than fgIteratorArenaSize, call delete on the addresses; otherw...
Abstract Interface class describing Streamer information for one class.
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.
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.
TGenCollectionProxy__SlowIterator(TVirtualCollectionProxy *proxy)