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