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
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
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
236 {
237 }
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
281 {
282 }
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;
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 std::string intype = TClassEdit::GetNameForIO(inside, TClassEdit::EModType::kNone);
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
366 fType = TClass::GetClass(intype.c_str(),kTRUE,silent, hint_pair_offset, hint_pair_size);
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 (TEnum::GetEnum( intype.c_str(), TEnum::kNone) ) {
401 // This is a known enum.
402 fCase = kIsEnum;
403 fSize = sizeof(Int_t);
404 fKind = kInt_t;
405 if (isPointer) {
406 fCase |= kIsPointer;
407 fSize = sizeof(void*);
408 }
409 } else {
410 // This fallback solution should be hardly used ...
411 // One of the common use case is to 'discover' that this is a
412 // collection for the content of which we do not have a dictionary
413 // which can happen at least in the following cases:
414 // - empty emulated collection
415 // - emulated collection of enums
416 // In those two cases there is no StreamerInfo stored in the file
417 // for the content.
418
419 // R__ASSERT("FallBack, should be hardly used.");
420
421 TypeInfo_t *ti = gCling->TypeInfo_Factory();
422 gCling->TypeInfo_Init(ti,inside.c_str());
423 if ( !gCling->TypeInfo_IsValid(ti) ) {
424 if (isPointer) {
425 fCase |= kIsPointer;
426 fSize = sizeof(void*);
427 }
428 // Since we already search for GetClass earlier, this should
429 // never be true.
430// fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
431// if (fType) {
432// fCase |= kIsClass;
433// fCtor = fType->GetNew();
434// fDtor = fType->GetDestructor();
435// fDelete = fType->GetDelete();
436// }
437// else {
438 // either we have an Emulated enum or a really unknown class!
439 // let's just claim its an enum :(
440 fCase = kIsEnum;
441 fSize = sizeof(Int_t);
442 fKind = kInt_t;
443// }
444 }
445 else {
447 if ( prop&kIsPointer ) {
448 fSize = sizeof(void*);
449 }
450 if ( prop&kIsStruct ) {
451 prop |= kIsClass;
452 }
453
454 if ( prop&kIsClass ) {
455 // We can get here in the case where the value if forward declared or
456 // is an std::pair that can not be (yet) emulated (eg. "std::pair<int,void*>")
457 fSize = std::string::npos;
458 if (!silent)
459 Error("TGenCollectionProxy", "Could not retrieve the TClass for %s", intype.c_str());
460// fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
461// R__ASSERT(fType);
462// fCtor = fType->GetNew();
463// fDtor = fType->GetDestructor();
464// fDelete = fType->GetDelete();
465 }
466 else if ( prop&kIsFundamental ) {
467 fundType = gROOT->GetType( intype.c_str() );
468 if (fundType==0) {
469 if (intype != "long double" && !silent) {
470 Error("TGenCollectionProxy","Unknown fundamental type %s",intype.c_str());
471 }
472 fSize = sizeof(int);
473 fKind = kInt_t;
474 } else {
475 fKind = (EDataType)fundType->GetType();
477 R__ASSERT((fKind>0 && fKind<0x17) || (fKind==-1&&(prop&kIsPointer)) );
478 }
479 }
480 else if ( prop&kIsEnum ) {
481 fSize = sizeof(int);
482 fKind = kInt_t;
483 }
485 if (fType == TString::Class() && (fCase&kIsPointer)) {
487 }
488 }
490 }
491 }
492 if (fType) {
494 if (proxy && (proxy->GetProperties() & kNeedDelete)) {
496 }
497 }
498 }
499 if ( fSize == std::string::npos ) {
500 if ( fType == 0 ) {
501 // The caller should check the validity by calling IsValid()
502 } else {
503 fSize = fType->Size();
504 }
505 }
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Return true if the Value has been properly initialized.
510
512{
513
514
515 return fSize != std::string::npos;
516}
517
519{
520 // Delete an item.
521
522 if ( ptr && fCase&kIsPointer ) {
523 if ( fDelete ) {
524 (*fDelete)(ptr);
525 }
526 else if ( fType ) {
527 fType->Destructor(ptr);
528 }
529 else {
530 ::operator delete(ptr);
531 }
532 }
533}
534
535/**
536 \class TGenCollectionProxy TGenCollectionProxy.cxx
537 \ingroup IO
538
539 Proxy around an arbitrary container, which implements basic
540 functionality and iteration.
541
542 The purpose of this implementation
543 is to shield any generated dictionary implementation from the
544 underlying streamer/proxy implementation and only expose
545 the creation functions.
546
547 In particular this is used to implement splitting and abstract
548 element access of any container. Access to compiled code is necessary
549 to implement the abstract iteration sequence and functionality like
550 size(), clear(), resize(). resize() may be a void operation.
551*/
552
553////////////////////////////////////////////////////////////////////////////////
554/// Build a proxy for an emulated container.
555
558 fTypeinfo(copy.fTypeinfo)
559{
560 fEnv = 0;
561 fName = copy.fName;
562 fPointers = copy.fPointers;
563 fSTL_type = copy.fSTL_type;
564 fSize.call = copy.fSize.call;
565 fNext.call = copy.fNext.call;
566 fFirst.call = copy.fFirst.call;
567 fClear.call = copy.fClear.call;
568 fResize = copy.fResize;
569 fDestruct = copy.fDestruct;
570 fConstruct = copy.fConstruct;
571 fFeed = copy.fFeed;
572 fCollect = copy.fCollect;
574 fValOffset = copy.fValOffset;
575 fValDiff = copy.fValDiff;
576 fValue = copy.fValue.load(std::memory_order_relaxed) ? new Value(*copy.fValue) : 0;
577 fVal = copy.fVal ? new Value(*copy.fVal) : 0;
578 fKey = copy.fKey ? new Value(*copy.fKey) : 0;
589}
590
591////////////////////////////////////////////////////////////////////////////////
592/// Build a proxy for a collection whose type is described by 'collectionClass'.
593
596 fTypeinfo(info)
597{
598 fEnv = 0;
599 fSize.call = 0;
600 fFirst.call = 0;
601 fNext.call = 0;
602 fClear.call = 0;
603 fResize = 0;
604 fDestruct = 0;
605 fConstruct = 0;
606 fCollect = 0;
607 fCreateEnv.call = 0;
608 fFeed = 0;
609 fValue = 0;
610 fKey = 0;
611 fVal = 0;
612 fValOffset = 0;
613 fValDiff = 0;
614 fPointers = false;
615 fOnFileClass = 0;
617 Env_t e;
618 if ( iter_size > sizeof(e.fIterator) ) {
619 Fatal("TGenCollectionProxy",
620 "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
621 "Iterators for collection",
622 fClass->GetName(),
623 (Long_t)iter_size,
624 (Long_t)sizeof(e.fIterator));
625 }
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Build a proxy for a collection whose type is described by 'collectionClass'.
638
641 fTypeinfo(info.fInfo), fOnFileClass(0)
642{
643 fEnv = 0;
644 fValDiff = info.fValueDiff;
646 fSize.call = info.fSizeFunc;
647 fResize = info.fResizeFunc;
648 fNext.call = info.fNextFunc;
649 fFirst.call = info.fFirstFunc;
650 fClear.call = info.fClearFunc;
653 fFeed = info.fFeedFunc;
654 fCollect = info.fCollectFunc;
656
657 if (cl) {
658 fName = cl->GetName();
659 }
661
662 fValue = 0;
663 fKey = 0;
664 fVal = 0;
665 fPointers = false;
667
668 Env_t e;
669 if ( info.fIterSize > sizeof(e.fIterator) ) {
670 Fatal("TGenCollectionProxy",
671 "%s %s are too large:%ld bytes. Maximum is:%ld bytes",
672 "Iterators for collection",
673 fClass->GetName(),
674 (Long_t)info.fIterSize,
675 (Long_t)sizeof(e.fIterator));
676 }
685}
686
687namespace {
688 template <class vec>
689 void clearVector(vec& v)
690 {
691 // Clear out the proxies.
692
693 for(typename vec::iterator i=v.begin(); i != v.end(); ++i) {
694 typename vec::value_type e = *i;
695 if ( e ) {
696 delete e;
697 }
698 }
699 v.clear();
700 }
701}
702////////////////////////////////////////////////////////////////////////////////
703/// Standard destructor
704
706{
707 clearVector(fProxyList);
708 clearVector(fProxyKept);
709 clearVector(fStaged);
710
711 if ( fValue.load() ) delete fValue.load();
712 if ( fVal ) delete fVal;
713 if ( fKey ) delete fKey;
714
715 delete fReadMemberWise;
717 std::map<std::string, TObjArray*>::iterator it;
718 std::map<std::string, TObjArray*>::iterator end = fConversionReadMemberWise->end();
719 for( it = fConversionReadMemberWise->begin(); it != end; ++it ) {
720 delete it->second;
721 }
724 }
725 delete fWriteMemberWise;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729/// Virtual copy constructor
730
732{
733 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
734
735 if( fPointers )
736 return new TGenCollectionProxy(*this);
737
738 switch(fSTL_type) {
739 case ROOT::kSTLbitset: {
740 return new TGenBitsetProxy(*this);
741 }
742 case ROOT::kSTLvector: {
743 if ((*fValue).fKind == kBool_t) {
744 return new TGenVectorBoolProxy(*this);
745 } else {
746 return new TGenVectorProxy(*this);
747 }
748 }
749 case ROOT::kSTLlist:
751 return new TGenListProxy(*this);
752 case ROOT::kSTLmap:
756 return new TGenMapProxy(*this);
757 case ROOT::kSTLset:
761 return new TGenSetProxy(*this);
762 default:
763 return new TGenCollectionProxy(*this);
764 }
765}
766
767////////////////////////////////////////////////////////////////////////////////
768/// Proxy initializer
769
771{
772 TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this);
773 if ( fValue.load() ) return p;
774 return p->InitializeEx(silent);
775}
776
777////////////////////////////////////////////////////////////////////////////////
778/// Reset the info gathered from StreamerInfos and value's TClass.
780{
781 if (fReadMemberWise)
783 delete fWriteMemberWise;
784 fWriteMemberWise = nullptr;
787 return kTRUE;
788}
789
790////////////////////////////////////////////////////////////////////////////////
791/// Check existence of function pointers
792
794{
795 if ( 0 == fSize.call ) {
796 Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str());
797 }
798 if ( 0 == fResize ) {
799 Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str());
800 }
801 if ( 0 == fNext.call ) {
802 Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str());
803 }
804 if ( 0 == fFirst.call ) {
805 Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str());
806 }
807 if ( 0 == fClear.call ) {
808 Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str());
809 }
810 if ( 0 == fConstruct ) {
811 Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str());
812 }
813 if ( 0 == fDestruct ) {
814 Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str());
815 }
816 if ( 0 == fFeed ) {
817 Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str());
818 }
819 if ( 0 == fCollect ) {
820 Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str());
821 }
822 if (0 == fCreateEnv.call ) {
823 Fatal("TGenCollectionProxy","No 'environment creation' function for class %s present.",fName.c_str());
824 }
825}
826
827////////////////////////////////////////////////////////////////////////////////
828/// Utility routine to issue a Fatal error is the Value object is not valid
829
830static TGenCollectionProxy::Value *R__CreateValue(const std::string &name, Bool_t silent,
831 size_t hint_pair_offset = 0, size_t hint_pair_size = 0)
832{
833 TGenCollectionProxy::Value *val = new TGenCollectionProxy::Value( name, silent, hint_pair_offset, hint_pair_size );
834 if ( !val->IsValid() ) {
835 Fatal("TGenCollectionProxy","Could not find %s!",name.c_str());
836 }
837 return val;
838}
839
840////////////////////////////////////////////////////////////////////////////////
841/// Proxy initializer
842
844{
846 if (fValue.load()) return this;
847
849 if ( cl ) {
850 fEnv = 0;
851 fName = cl->GetName();
852 fPointers = false;
853 int nested = 0;
854 std::vector<std::string> inside;
855 int num = TClassEdit::GetSplit(cl->GetName(),inside,nested);
856 if ( num > 1 ) {
857 std::string nam;
858 Value* newfValue = nullptr;
859 if ( inside[0].find("stdext::hash_") != std::string::npos )
860 inside[0].replace(3,10,"::");
861 if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos )
862 inside[0].replace(0,16,"std::");
863 fSTL_type = TClassEdit::STLKind(inside[0]);
864 switch ( fSTL_type ) {
865 case ROOT::kSTLmap:
869 case ROOT::kSTLset:
873 case ROOT::kSTLbitset: // not really an associate container but it has no real iterator.
875 if (num > 3 && !inside[3].empty()) {
876 if (! TClassEdit::IsDefAlloc(inside[3].c_str(),inside[0].c_str())) {
878 }
879 }
880 break;
881 };
882
883 int slong = sizeof(void*);
884 switch ( fSTL_type ) {
885 case ROOT::kSTLmap:
889 nam = "pair<"+inside[1]+","+inside[2];
890 nam += (nam[nam.length()-1]=='>') ? " >" : ">";
891
892 fVal = R__CreateValue(inside[2], silent);
893 fKey = R__CreateValue(inside[1], silent);
894
895 {
897 TClass *paircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
898 if (paircl == nullptr) {
899 // We need to emulate the pair
900 auto info = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1], inside[2], silent, fValOffset, fValDiff);
901 if (!info) {
902 Fatal("InitializeEx",
903 "Could not load nor generate the dictionary for \"%s\", some element might be missing their dictionary (eg. enums)",
904 nam.c_str());
905 }
906 } else {
907 if ((!paircl->IsSyntheticPair() && paircl->GetState() < TClass::kInterpreted) || paircl->GetClassSize() != fValDiff) {
908 if (paircl->GetState() >= TClass::kInterpreted)
909 Fatal("InitializeEx",
910 "The %s for %s reports a class size that is inconsistent with the one registered "
911 "through the CollectionProxy for %s: %d vs %d\n",
912 paircl->IsLoaded() ? "dictionary" : "interpreter information for", nam.c_str(),
913 cl->GetName(), (int)paircl->GetClassSize(), (int)fValDiff);
914 else {
915 gROOT->GetListOfClasses()->Remove(paircl);
916 TClass *newpaircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
917 if (!newpaircl || newpaircl == paircl || newpaircl->GetClassSize() != fValDiff)
918 Fatal("InitializeEx",
919 "The TClass creation for %s did not get the right size: %d instead of%d\n",
920 nam.c_str(), (int)paircl->GetClassSize(), (int)fValDiff);
921 newpaircl->ForceReload(paircl);
922 }
923 }
924 }
925 }
926 newfValue = R__CreateValue(nam, silent, fValOffset, fValDiff);
927
928 fPointers = (0 != (fKey->fCase&kIsPointer));
929 if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
931 }
932 if ( 0 == fValDiff ) {
934 fValDiff += (slong - fKey->fSize%slong)%slong;
935 fValDiff += (slong - fValDiff%slong)%slong;
936 }
937 if ( 0 == fValOffset ) {
939 fValOffset += (slong - fKey->fSize%slong)%slong;
940 }
941 break;
942 case ROOT::kSTLbitset:
943 inside[1] = "bool";
944 // Intentional fall through
945 default:
946 newfValue = R__CreateValue(inside[1], silent);
947
948 fVal = new Value(*newfValue);
949 if ( 0 == fValDiff ) {
951 fValDiff += (slong - fValDiff%slong)%slong;
952 }
953 if (num > 2 && !inside[2].empty()) {
954 if (! TClassEdit::IsDefAlloc(inside[2].c_str(),inside[0].c_str())) {
956 }
957 }
958 break;
959 }
960 if (!(fProperties & kIsEmulated) && newfValue->fType && !newfValue->fType->IsSyntheticPair()) {
961 if (!newfValue->fType->IsLoaded() && !newfValue->fType->HasInterpreterInfo())
962 Error("TGenCollectionProxy::InitializeEx",
963 "The TClass for %s used as the value type of the compiled collection proxy %s is not loaded.",
964 newfValue->fType->GetName(), cl->GetName());
965 }
966
967 fPointers = fPointers || (0 != (fVal->fCase&kIsPointer));
968 if (fPointers || (0 != (fVal->fProperties&kNeedDelete))) {
970 }
971 fClass = cl;
972 //fValue must be set last since we use it to indicate that we are initialized
973 fValue = newfValue;
974 return this;
975 }
976 Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName());
977 }
978 Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name());
979 return 0;
980}
981
982////////////////////////////////////////////////////////////////////////////////
983/// Return a pointer to the TClass representing the container
984
986{
987 return fClass ? fClass : Initialize(kFALSE)->fClass;
988}
989
990////////////////////////////////////////////////////////////////////////////////
991/// Return the type of collection see TClassEdit::ESTLType
992
994{
995 if (!fValue.load(std::memory_order_relaxed)) {
997 }
998 return fSTL_type;
999}
1000
1001////////////////////////////////////////////////////////////////////////////////
1002/// Return the offset between two consecutive value_types (memory layout).
1003
1005 if (!fValue.load(std::memory_order_relaxed)) {
1007 }
1008 return fValDiff;
1009}
1010
1011////////////////////////////////////////////////////////////////////////////////
1012/// Return the sizeof the collection object.
1013
1015{
1016 return fClass->Size();
1017}
1018
1019////////////////////////////////////////////////////////////////////////////////
1020/// Return true if the content is of type 'pointer to'
1021
1023{
1024 // Initialize proxy in case it hasn't been initialized yet
1025 if( !fValue.load(std::memory_order_relaxed) )
1027
1028 // The content of a map and multimap is always a 'pair' and hence
1029 // fPointers means "Flag to indicate if containee has pointers (key or value)"
1030 // so we need to ignore its value for map and multimap;
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Return a pointer to the TClass representing the content.
1037
1039{
1040 auto value = fValue.load(std::memory_order_relaxed);
1041 if (!value) {
1043 value = fValue.load(std::memory_order_relaxed);
1044 }
1045 return value ? (*value).fType.GetClass() : 0;
1046}
1047
1048////////////////////////////////////////////////////////////////////////////////
1049/// If the content is a simple numerical value, return its type (see TDataType)
1050
1052{
1053 auto value = fValue.load(std::memory_order_relaxed);
1054 if (!value) {
1056 value = fValue.load(std::memory_order_relaxed);
1057 }
1058 return value ? (*value).fKind : kNoType_t;
1059}
1060
1061////////////////////////////////////////////////////////////////////////////////
1062/// Return the address of the value at index 'idx'
1063
1065{
1066 if ( fEnv && fEnv->fObject ) {
1067 switch (fSTL_type) {
1068 case ROOT::kSTLvector:
1069 if ((*fValue).fKind == kBool_t) {
1070 auto vec = (std::vector<bool> *)(fEnv->fObject);
1071 fEnv->fLastValueVecBool = (*vec)[idx];
1072 fEnv->fIdx = idx;
1073 return &(fEnv->fLastValueVecBool);
1074 }
1075 // intentional fall through
1076 case ROOT::kROOTRVec:
1077 fEnv->fIdx = idx;
1078 switch( idx ) {
1079 case 0:
1080 return fEnv->fStart = fFirst.invoke(fEnv);
1081 default:
1082 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1083 return ((char*)fEnv->fStart) + fValDiff*idx;
1084 }
1085 case ROOT::kSTLbitset: {
1086 switch (idx) {
1087 case 0:
1089 fEnv->fIdx = idx;
1090 break;
1091 default:
1092 fEnv->fIdx = idx - fEnv->fIdx;
1093 if (!fEnv->fStart) fEnv->fStart = fFirst.invoke(fEnv);
1094 fNext.invoke(fEnv);
1095 fEnv->fIdx = idx;
1096 break;
1097 }
1098 typedef ROOT::TCollectionProxyInfo::Environ <std::pair<size_t, Bool_t>> EnvType_t;
1099 EnvType_t *e = (EnvType_t *) fEnv;
1100 return &(e->fIterator.second);
1101 }
1102 case ROOT::kSTLset:
1104 case ROOT::kSTLmultiset:
1106 case ROOT::kSTLmap:
1108 case ROOT::kSTLmultimap:
1110 if ( fEnv->fUseTemp ) {
1111 return (((char*)fEnv->fTemp)+idx*fValDiff);
1112 }
1113 // Intentional fall through.
1114 default:
1115 switch( idx ) {
1116 case 0:
1117 fEnv->fIdx = idx;
1118 return fEnv->fStart = fFirst.invoke(fEnv);
1119 default: {
1120 fEnv->fIdx = idx - fEnv->fIdx;
1121 if (! fEnv->fStart ) fEnv->fStart = fFirst.invoke(fEnv);
1122 void* result = fNext.invoke(fEnv);
1123 fEnv->fIdx = idx;
1124 return result;
1125 }
1126 }
1127 }
1128 }
1129 Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
1130 return 0;
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// Clear the emulated collection.
1135
1136void TGenCollectionProxy::Clear(const char* opt)
1137{
1138 if ( fEnv && fEnv->fObject ) {
1139 if ( (fProperties & kNeedDelete) && opt && *opt=='f' ) {
1140 size_t i, n = *(size_t*)fSize.invoke(fEnv);
1141 if ( n > 0 ) {
1142 for (i=0; i<n; ++i)
1144 }
1145 }
1147 }
1148}
1149
1150////////////////////////////////////////////////////////////////////////////////
1151/// Return the current size of the container
1152
1154{
1155 if ( fEnv && fEnv->fObject ) {
1156 if (fEnv->fUseTemp) {
1157 return fEnv->fSize;
1158 } else {
1159 return *(size_t*)fSize.invoke(fEnv);
1160 }
1161 }
1162 Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
1163 return 0;
1164}
1165
1166////////////////////////////////////////////////////////////////////////////////
1167/// Resize the container
1168
1170{
1171 if ( fEnv && fEnv->fObject ) {
1172 if ( force && fPointers ) {
1173 size_t i, nold = *(size_t*)fSize.invoke(fEnv);
1174 if ( n != nold ) {
1175 for (i=n; i<nold; ++i)
1176 DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
1177 }
1178 }
1179 MESSAGE(3, "Resize(n)" );
1180 fEnv->fSize = n;
1182 return;
1183 }
1184 Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
1185}
1186
1187////////////////////////////////////////////////////////////////////////////////
1188/// Allocate the needed space.
1189/// For associative collection, this returns a TStaging object that
1190/// need to be deleted manually __or__ returned by calling Commit(TStaging*)
1191
1193{
1194 if ( fEnv && fEnv->fObject ) {
1195 switch ( fSTL_type ) {
1196 case ROOT::kSTLset:
1198 case ROOT::kSTLmultiset:
1200 case ROOT::kSTLmap:
1202 case ROOT::kSTLmultimap:
1204 if ( (fProperties & kNeedDelete) )
1205 Clear("force");
1206 else
1208 // Commit no longer use the environment and thus no longer decrease
1209 // the count. Consequently we no longer should increase it here.
1210 // ++fEnv->fRefCount;
1211 fEnv->fSize = n;
1212
1213 TStaging *s;
1214 if (fStaged.empty()) {
1215 s = new TStaging(n,fValDiff);
1216 } else {
1217 s = fStaged.back();
1218 fStaged.pop_back();
1219 s->Resize(n);
1220 }
1221 fConstruct(s->GetContent(),s->GetSize());
1222
1223 s->SetTarget(fEnv->fObject);
1224
1225 fEnv->fTemp = s->GetContent();
1226 fEnv->fUseTemp = kTRUE;
1227 fEnv->fStart = fEnv->fTemp;
1228
1229 return s;
1230 }
1231 case ROOT::kSTLvector:
1232 case ROOT::kSTLlist:
1234 case ROOT::kSTLdeque:
1235 case ROOT::kROOTRVec:
1236 if( (fProperties & kNeedDelete) ) {
1237 Clear("force");
1238 }
1239 fEnv->fSize = n;
1241 return fEnv->fObject;
1242
1243 case ROOT::kSTLbitset: {
1244 TStaging *s;
1245 if (fStaged.empty()) {
1246 s = new TStaging(n,fValDiff);
1247 } else {
1248 s = fStaged.back();
1249 fStaged.pop_back();
1250 s->Resize(n);
1251 }
1252 s->SetTarget(fEnv->fObject);
1253
1254 fEnv->fTemp = s->GetContent();
1255 fEnv->fUseTemp = kTRUE;
1256 fEnv->fStart = fEnv->fTemp;
1257
1258 return s;
1259 }
1260 }
1261 }
1262 return 0;
1263}
1264
1265////////////////////////////////////////////////////////////////////////////////
1266/// Insert data into the container where data is a C-style array of the actual type contained in the collection
1267/// of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
1268
1269void TGenCollectionProxy::Insert(const void *data, void *container, size_t size)
1270{
1271 fFeed((void*)data,container,size);
1272}
1273
1274////////////////////////////////////////////////////////////////////////////////
1275/// Commit the change.
1276
1278{
1280// case ROOT::kSTLmap:
1281// case ROOT::kSTLmultimap:
1282// case ROOT::kSTLset:
1283// case ROOT::kSTLmultiset:
1284 if ( from ) {
1285 TStaging *s = (TStaging*) from;
1286 if ( s->GetTarget() ) {
1287 fFeed(s->GetContent(),s->GetTarget(),s->GetSize());
1288 }
1289 fDestruct(s->GetContent(),s->GetSize());
1290 s->SetTarget(0);
1291 fStaged.push_back(s);
1292 }
1293 }
1294}
1295
1296////////////////////////////////////////////////////////////////////////////////
1297/// Add an object.
1298
1300{
1301 if ( !fValue.load(std::memory_order_relaxed) ) Initialize(kFALSE);
1302 if ( !fProxyList.empty() ) {
1303 EnvironBase_t* back = fProxyList.back();
1304 if ( back->fObject == objstart ) {
1305 ++back->fRefCount;
1306 fProxyList.push_back(back);
1307 fEnv = back;
1308 return;
1309 }
1310 }
1311 EnvironBase_t* e = 0;
1312 if ( fProxyKept.empty() ) {
1314 e->fTemp = 0;
1315 e->fUseTemp = kFALSE;
1316 }
1317 else {
1318 e = fProxyKept.back();
1319 fProxyKept.pop_back();
1320 }
1321 e->fSize = 0;
1322 e->fRefCount = 1;
1323 e->fObject = objstart;
1324 e->fStart = 0;
1325 e->fIdx = 0;
1326 // ::memset(e->buff,0,sizeof(e->buff));
1327 fProxyList.push_back(e);
1328 fEnv = e;
1329}
1330
1331////////////////////////////////////////////////////////////////////////////////
1332/// Remove the last object.
1333
1335{
1336 if ( !fProxyList.empty() ) {
1337 EnvironBase_t* e = fProxyList.back();
1338 if ( --e->fRefCount <= 0 ) {
1339 fProxyKept.push_back(e);
1340 e->fUseTemp = kFALSE;
1341 }
1342 fProxyList.pop_back();
1343 }
1344 fEnv = fProxyList.empty() ? 0 : fProxyList.back();
1345}
1346
1347////////////////////////////////////////////////////////////////////////////////
1348/// Call to delete/destruct individual item.
1349
1350void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
1351{
1352 if ( force && ptr ) {
1353 switch (fSTL_type) {
1354 case ROOT::kSTLmap:
1356 case ROOT::kSTLmultimap:
1358 if ( fKey->fCase&kIsPointer ) {
1361 TPushPop helper(proxy,*(void**)ptr);
1362 proxy->Clear("force");
1363 }
1364 fKey->DeleteItem(*(void**)ptr);
1365 } else {
1368 TPushPop helper(proxy,ptr);
1369 proxy->Clear("force");
1370 }
1371 }
1372 char *addr = ((char*)ptr)+fValOffset;
1373 if ( fVal->fCase&kIsPointer ) {
1376 TPushPop helper(proxy,*(void**)addr);
1377 proxy->Clear("force");
1378 }
1379 fVal->DeleteItem(*(void**)addr);
1380 } else {
1383 TPushPop helper(proxy,addr);
1384 proxy->Clear("force");
1385 }
1386 }
1387 break;
1388 }
1389 default: {
1390 if ( fVal->fCase&kIsPointer ) {
1393 TPushPop helper(proxy,*(void**)ptr);
1394 proxy->Clear("force");
1395 }
1396 fVal->DeleteItem(*(void**)ptr);
1397 } else {
1400 TPushPop helper(proxy,ptr);
1401 proxy->Clear("force");
1402 }
1403 }
1404 break;
1405 }
1406 }
1407 }
1408}
1409
1410////////////////////////////////////////////////////////////////////////////////
1411
1412void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */, const TClass * /* onfileClass */)
1413{
1414 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *, const TClass *)");
1415}
1416
1417////////////////////////////////////////////////////////////////////////////////
1418
1419void TGenCollectionProxy::ReadBuffer(TBuffer & /* b */, void * /* obj */)
1420{
1421 MayNotUse("TGenCollectionProxy::ReadBuffer(TBuffer &, void *)");
1422}
1423
1424////////////////////////////////////////////////////////////////////////////////
1425/// Streamer Function.
1426
1428{
1429 if ( fEnv ) {
1431 return;
1432 }
1433 Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
1434}
1435
1436////////////////////////////////////////////////////////////////////////////////
1437/// Streamer I/O overload
1438
1439void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ )
1440{
1441 TPushPop env(this, objp);
1442 Streamer(buff);
1443}
1444
1445////////////////////////////////////////////////////////////////////////////////
1446/// TClassStreamer IO overload
1447
1449{
1450 Streamer(b, objp, 0);
1451}
1452
1453
1458};
1459
1460////////////////////////////////////////////////////////////////////////////////
1461
1462void TGenCollectionProxy__SlowCreateIterators(void * /* collection */, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
1463{
1464 new (*begin_arena) TGenCollectionProxy__SlowIterator(proxy);
1465 *(UInt_t*)*end_arena = proxy->Size();
1466}
1467
1468////////////////////////////////////////////////////////////////////////////////
1469
1470void *TGenCollectionProxy__SlowNext(void *iter, const void *end)
1471{
1473 if (iterator->fIndex != *(UInt_t*)end) {
1474 void *result = iterator->fProxy->At(iterator->fIndex);
1475 ++(iterator->fIndex);
1476 return result;
1477 } else {
1478 return 0;
1479 }
1480}
1481
1482////////////////////////////////////////////////////////////////////////////////
1483
1484void * TGenCollectionProxy__SlowCopyIterator(void *dest, const void *source)
1485{
1487 return dest;
1488}
1489
1490////////////////////////////////////////////////////////////////////////////////
1491/// Nothing to do
1492
1494{
1495}
1496
1497////////////////////////////////////////////////////////////////////////////////
1498/// Nothing to do
1499
1501{
1502}
1503
1504
1505////////////////////////////////////////////////////////////////////////////////
1506/// We can safely assume that the std::vector layout does not really depend on
1507/// the content!
1508
1509void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy*)
1510{
1511 std::vector<char> *vec = (std::vector<char>*)obj;
1512 if (vec->empty()) {
1513 *begin_arena = 0;
1514 *end_arena = 0;
1515 return;
1516 }
1517 *begin_arena = &(*vec->begin());
1518#ifdef R__VISUAL_CPLUSPLUS
1519 *end_arena = &(*(vec->end()-1)) + 1; // On windows we can not dererence the end iterator at all.
1520#else
1521 // coverity[past_the_end] Safe on other platforms
1522 *end_arena = &(*vec->end());
1523#endif
1524
1525}
1526
1527////////////////////////////////////////////////////////////////////////////////
1528/// Should not be used.
1529
1530void *TGenCollectionProxy__VectorNext(void *, const void *)
1531{
1532 R__ASSERT(0);
1533 return 0;
1534}
1535
1536////////////////////////////////////////////////////////////////////////////////
1537
1538void *TGenCollectionProxy__VectorCopyIterator(void *dest, const void *source)
1539{
1540 *(void**)dest = *(void**)source;
1541 return dest;
1542}
1543
1544////////////////////////////////////////////////////////////////////////////////
1545/// Nothing to do
1546
1548{
1549}
1550
1551////////////////////////////////////////////////////////////////////////////////
1552/// Nothing to do
1553
1555{
1556}
1557
1558
1559
1560////////////////////////////////////////////////////////////////////////////////
1561
1562void TGenCollectionProxy__StagingCreateIterators(void *obj, void **begin_arena, void **end_arena, TVirtualCollectionProxy *)
1563{
1565 *begin_arena = s->GetContent();
1566 *end_arena = s->GetEnd();
1567}
1568
1569////////////////////////////////////////////////////////////////////////////////
1570/// Should not be used.
1571
1572void *TGenCollectionProxy__StagingNext(void *, const void *)
1573{
1574 R__ASSERT(0);
1575 return 0;
1576}
1577
1578////////////////////////////////////////////////////////////////////////////////
1579
1580void *TGenCollectionProxy__StagingCopyIterator(void *dest, const void *source)
1581{
1582 *(void**)dest = *(void**)source;
1583 return dest;
1584}
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Nothing to do
1588
1590{
1591}
1592
1593////////////////////////////////////////////////////////////////////////////////
1594/// Nothing to do
1595
1597{
1598}
1599
1600
1601////////////////////////////////////////////////////////////////////////////////
1602/// See typedef void (*CreateIterators_t)(void *collection, void *&begin_arena, void *&end_arena);
1603/// begin_arena and end_arena should contain the location of memory arena of size fgIteratorSize.
1604/// If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
1605/// Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
1606
1608{
1609 if (read) {
1610 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1611 if ( (fProperties & kIsAssociative) && read)
1613 }
1614
1616
1617 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1618
1619// fprintf(stderr,"GetFunctinCreateIterator for %s will give: ",fClass.GetClassName());
1620// if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated))
1621// fprintf(stderr,"vector/emulated iterator\n");
1622// else if ( (fProperties & kIsAssociative) && read)
1623// fprintf(stderr,"an associative read iterator\n");
1624// else
1625// fprintf(stderr,"a generic iterator\n");
1626
1627 // TODO could we do better than SlowCreateIterators for RVec?
1630 else if ( (fProperties & kIsAssociative) && read)
1632 else
1634}
1635
1636////////////////////////////////////////////////////////////////////////////////
1637/// See typedef void (*CopyIterator_t)(void *&dest, const void *source);
1638/// Copy the iterator source, into dest. dest should contain should contain the location of memory arena of size fgIteratorSize.
1639/// If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
1640/// Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
1641
1643{
1644 if (read) {
1645 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1646 if ( (fProperties & kIsAssociative) && read)
1648 }
1649
1651
1652 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1653
1654 // TODO can we do better than the default for RVec?
1657 else if ( (fProperties & kIsAssociative) && read)
1659 else
1661}
1662
1663////////////////////////////////////////////////////////////////////////////////
1664/// See typedef void* (*Next_t)(void *iter, void *end);
1665/// iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
1666/// 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
1667/// If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
1668/// which case 'Next' will return the value of the pointer.
1669
1671{
1672 if (read) {
1673 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1674 if ( (fProperties & kIsAssociative) && read)
1676 }
1677
1679
1680 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1681
1682 // TODO can we do better than the default for RVec?
1685 else if ( (fProperties & kIsAssociative) && read)
1687 else
1689}
1690
1691////////////////////////////////////////////////////////////////////////////////
1692/// See typedef void (*DeleteIterator_t)(void *iter);
1693/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1694/// Otherwise just call the iterator's destructor.
1695
1697{
1698 if (read) {
1699 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1700 if ( (fProperties & kIsAssociative) && read)
1702 }
1703
1705
1706 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1707
1708 // TODO can we do better than the default for RVec?
1711 else if ( (fProperties & kIsAssociative) && read)
1713 else
1715}
1716
1717////////////////////////////////////////////////////////////////////////////////
1718/// See typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
1719/// If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
1720/// Otherwise just call the iterator's destructor.
1721
1723{
1724 if (read) {
1725 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1726 if ( (fProperties & kIsAssociative) && read)
1728 }
1729
1731
1732 if ( !fValue.load(std::memory_order_relaxed) ) InitializeEx(kFALSE);
1733
1734 // TODO could RVec use something faster than SlowCopyIterator?
1737 else if ( (fProperties & kIsAssociative) && read)
1739 else
1741}
1742
1743////////////////////////////////////////////////////////////////////////////////
1744/// Return the set of action necessary to stream in this collection member-wise coming from
1745/// the old value class layout refered to by 'version'.
1746
1748{
1749 if (oldClass == 0) {
1750 return 0;
1751 }
1752 TObjArray* arr = 0;
1755 std::map<std::string, TObjArray*>::iterator it;
1756
1757 it = fConversionReadMemberWise->find( oldClass->GetName() );
1758
1759 if( it != fConversionReadMemberWise->end() ) {
1760 arr = it->second;
1761 }
1762
1763 if (arr) {
1765 if (result) {
1766 return result;
1767 }
1768 }
1769 }
1770
1771 // Need to create it.
1772 TClass *valueClass = GetValueClass();
1773 if (valueClass == 0) {
1774 return 0;
1775 }
1776 TVirtualStreamerInfo *info = valueClass->GetConversionStreamerInfo(oldClass,version);
1777 if (info == 0) {
1778 return 0;
1779 }
1781
1782 if (!arr) {
1783 arr = new TObjArray(version+10, -1);
1785 fConversionReadMemberWise = new std::map<std::string, TObjArray*>();
1786 }
1787 (*fConversionReadMemberWise)[oldClass->GetName()] = arr;
1788 }
1789 arr->AddAtAndExpand( result, version );
1790
1791 return result;
1792}
1793
1794////////////////////////////////////////////////////////////////////////////////
1795/// Return the set of action necessary to stream in this collection member-wise coming from
1796/// the old value class layout refered to by 'version'.
1797
1799{
1801 if (version < (fReadMemberWise->GetSize()-1)) { // -1 because the 'index' starts at -1
1803 }
1804 if (result == 0) {
1805 // Need to create it.
1806 TClass *valueClass = GetValueClass();
1807 TVirtualStreamerInfo *info = 0;
1808 if (valueClass) {
1809 info = valueClass->GetStreamerInfo(version);
1810 }
1813 }
1814 return result;
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Return the set of action necessary to stream out this collection member-wise.
1819
1821{
1823 if (result == 0) {
1824 // Need to create it.
1825 TClass *valueClass = GetValueClass();
1826 TVirtualStreamerInfo *info = 0;
1827 if (valueClass) {
1828 info = valueClass->GetStreamerInfo();
1829 }
1832 }
1833 return result;
1834}
#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
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:406
#define R__LOCKGUARD(mutex)
void *(* fCopyIterator)(void *dest, const void *source)
void *(* fConstructFunc)(void *, size_t)
void(* fDeleteTwoIterators)(void *begin, void *end)
void *(* fFeedFunc)(void *, void *, size_t)
void(* fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
void *(* fNext)(void *iter, const void *end)
Buffer base class used for serializing objects.
Definition TBuffer.h:43
TClass * GetClass() const
Definition TClassRef.h:66
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
Bool_t IsSyntheticPair() const
Definition TClass.h:521
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:607
void ForceReload(TClass *oldcl)
we found at least one equivalent.
Definition TClass.cxx:1405
EState GetState() const
Definition TClass.h:488
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition TClass.cxx:7548
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition TClass.cxx:7516
Bool_t HasInterpreterInfo() const
Definition TClass.h:410
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5773
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5981
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:4668
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2966
Int_t GetClassSize() const
Definition TClass.h:425
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:7155
@ kInterpreted
Definition TClass.h:126
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThisObject.
Definition TClass.cxx:7532
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:3037
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
Int_t Size() const
Get size of basic typedef'ed type.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:175
@ 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...
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:47
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.
virtual Int_t GetProperties() const
Return miscallenous properties of the proxy (see TVirtualCollectionProxy::EProperty)
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.
virtual void Clear(const char *opt="")=0
Clear the container.
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...
virtual void * At(UInt_t idx)=0
Return the address of the value at index idx
virtual UInt_t Size() const =0
Return the current number of elements in the container.
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.
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.
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)