42 static TStreamerElement* R__CreateEmulatedElement(
const char *dmName,
const char *dmFull, Int_t offset);
43 static TStreamerInfo *R__GenerateTClassForPair(
const std::string &f,
const std::string &s);
45 TEmulatedCollectionProxy::TEmulatedCollectionProxy(
const TEmulatedCollectionProxy& copy)
46 : TGenCollectionProxy(copy)
49 fProperties |= kIsEmulated;
52 TEmulatedCollectionProxy::TEmulatedCollectionProxy(
const char* cl_name, Bool_t silent)
53 : TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator))
58 if ( this->TEmulatedCollectionProxy::InitializeEx(silent) ) {
59 fCreateEnv = TGenCollectionProxy::Env_t::Create;
61 fProperties |= kIsEmulated;
64 TEmulatedCollectionProxy::~TEmulatedCollectionProxy()
67 if ( fEnv && fEnv->fObject ) {
72 TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate()
const
76 if ( !fClass ) Initialize(kFALSE);
77 return new TEmulatedCollectionProxy(*
this);
80 void TEmulatedCollectionProxy::Destructor(
void* p, Bool_t dtorOnly)
const
85 if (!fEnv || fEnv->fObject != p) {
87 TVirtualCollectionProxy::TPushPop env(const_cast<TEmulatedCollectionProxy*>(
this), p);
88 const_cast<TEmulatedCollectionProxy*
>(
this)->Clear(
"force");
90 const_cast<TEmulatedCollectionProxy*
>(
this)->Clear(
"force");
93 ((Cont_t*)p)->~Cont_t();
99 void TEmulatedCollectionProxy::DeleteArray(
void* p, Bool_t dtorOnly)
const
105 Warning(
"DeleteArray",
"Cannot properly delete emulated array of %s at %p, I don't know how many elements it has!", fClass->GetName(), p);
107 delete[] (Cont_t*) p;
111 TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx(Bool_t silent)
114 R__LOCKGUARD(gInterpreterMutex);
115 if (fClass)
return this;
118 TClass *cl = TClass::GetClass(fName.c_str());
123 std::vector<std::string> inside;
125 int num = TClassEdit::GetSplit(fName.c_str(),inside,nested);
128 if ( inside[0].find(
"stdext::hash_") != std::string::npos ) {
129 inside[0].replace(3,10,
"::");
131 if ( inside[0].find(
"__gnu_cxx::hash_") != std::string::npos ) {
132 inside[0].replace(0,16,
"std::");
134 fSTL_type = TClassEdit::STLKind(inside[0]);
139 auto alignedSize = [](
size_t in) {
140 constexpr
size_t kSizeOfPtr =
sizeof(
void*);
141 return in + (kSizeOfPtr - in%kSizeOfPtr)%kSizeOfPtr;
143 switch ( fSTL_type ) {
145 case ROOT::kSTLmultimap:
146 nam =
"pair<"+inside[1]+
","+inside[2];
147 nam += (nam[nam.length()-1]==
'>') ?
" >" :
">";
148 if (0==TClass::GetClass(nam.c_str())) {
150 R__GenerateTClassForPair(inside[1],inside[2]);
152 fValue =
new Value(nam,silent);
153 fKey =
new Value(inside[1],silent);
154 fVal =
new Value(inside[2],silent);
155 if ( !(*fValue).IsValid() || !fKey->IsValid() || !fVal->IsValid() ) {
158 fPointers |= 0 != (fKey->fCase&kIsPointer);
159 if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
160 fProperties |= kNeedDelete;
162 if ( 0 == fValOffset ) {
163 fValOffset = alignedSize(fKey->fSize);
165 if ( 0 == fValDiff ) {
166 fValDiff = alignedSize(fValOffset + fVal->fSize);
168 if (num > 3 && !inside[3].empty()) {
169 if (! TClassEdit::IsDefAlloc(inside[3].c_str(),inside[0].c_str())) {
170 fProperties |= kCustomAlloc;
174 case ROOT::kSTLbitset:
178 fValue =
new Value(inside[1],silent);
179 fVal =
new Value(*fValue);
180 if ( !(*fValue).IsValid() || !fVal->IsValid() ) {
183 if ( 0 == fValDiff ) {
184 fValDiff = fVal->fSize;
188 if (num > 2 && !inside[2].empty()) {
189 if (! TClassEdit::IsDefAlloc(inside[2].c_str(),inside[0].c_str())) {
190 fProperties |= kCustomAlloc;
195 fPointers |= 0 != (fVal->fCase&kIsPointer);
196 if (fPointers || (0 != (fVal->fProperties&kNeedDelete))) {
197 fProperties |= kNeedDelete;
202 Fatal(
"TEmulatedCollectionProxy",
"Components of %s not analysed!",cl->GetName());
204 Fatal(
"TEmulatedCollectionProxy",
"Collection class %s not found!",fTypeinfo.name());
208 Bool_t TEmulatedCollectionProxy::IsValid()
const
211 return (0 != fCreateEnv.call);
214 UInt_t TEmulatedCollectionProxy::Size()
const
218 if ( fEnv && fEnv->fObject ) {
219 return fEnv->fSize = PCont_t(fEnv->fObject)->size()/fValDiff;
221 Fatal(
"TEmulatedCollectionProxy",
"Size> Logic error - no proxy object set.");
225 void TEmulatedCollectionProxy::Clear(
const char* opt)
228 Resize(0, opt && *opt==
'f');
231 void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t force )
235 typedef std::string String_t;
236 PCont_t c = PCont_t(fEnv->fObject);
237 char* addr = ((
char*)fEnv->fStart) + fValDiff*left;
240 switch ( fSTL_type ) {
242 case ROOT::kSTLmultimap:
243 addr = ((
char*)fEnv->fStart) + fValDiff*left;
244 switch(fKey->fCase) {
249 for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) {
251 fKey->fType->Destructor(addr, kTRUE);
255 for( i=left; i<nCurr; ++i, addr += fValDiff ) {
256 ((std::string*)addr)->~String_t();
259 case kIsPointer|kIsClass:
260 for( i=left; i<nCurr; ++i, addr += fValDiff ) {
261 StreamHelper* h = (StreamHelper*)addr;
264 void* ptr = h->ptr();
265 if (force) fKey->fType->Destructor(ptr);
269 case kIsPointer|kBIT_ISSTRING:
270 for( i=nCurr; i<left; ++i, addr += fValDiff ) {
271 StreamHelper* h = (StreamHelper*)addr;
274 if (force)
delete (std::string*)h->ptr();
278 case kIsPointer|kBIT_ISTSTRING|kIsClass:
279 for( i=nCurr; i<left; ++i, addr += fValDiff ) {
280 StreamHelper* h = (StreamHelper*)addr;
281 if (force)
delete (TString*)h->ptr();
286 addr = ((
char*)fEnv->fStart)+fValOffset+fValDiff*left;
291 switch( fVal->fCase ) {
296 for( i=left; i<nCurr; ++i, addr += fValDiff ) {
298 fVal->fType->Destructor(addr,kTRUE);
302 for( i=left; i<nCurr; ++i, addr += fValDiff )
303 ((std::string*)addr)->~String_t();
305 case kIsPointer|kIsClass:
306 for( i=left; i<nCurr; ++i, addr += fValDiff ) {
307 StreamHelper* h = (StreamHelper*)addr;
310 fVal->fType->Destructor(p);
315 case kIsPointer|kBIT_ISSTRING:
316 for( i=nCurr; i<left; ++i, addr += fValDiff ) {
317 StreamHelper* h = (StreamHelper*)addr;
318 if (force)
delete (std::string*)h->ptr();
322 case kIsPointer|kBIT_ISTSTRING|kIsClass:
323 for( i=nCurr; i<left; ++i, addr += fValDiff ) {
324 StreamHelper* h = (StreamHelper*)addr;
325 if (force)
delete (TString*)h->ptr();
331 c->resize(left*fValDiff,0);
332 fEnv->fStart = left>0 ? &(*c->begin()) : 0;
336 void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left)
340 PCont_t c = PCont_t(fEnv->fObject);
341 c->resize(left*fValDiff,0);
342 void *oldstart = fEnv->fStart;
343 fEnv->fStart = left>0 ? &(*c->begin()) : 0;
345 char* addr = ((
char*)fEnv->fStart) + fValDiff*nCurr;
346 switch ( fSTL_type ) {
348 case ROOT::kSTLmultimap:
349 switch(fKey->fCase) {
354 if (oldstart && oldstart != fEnv->fStart) {
356 for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
360 fKey->fType->Move(((
char*)oldstart)+offset,((
char*)fEnv->fStart)+offset);
363 for( i=nCurr; i<left; ++i, addr += fValDiff )
364 fKey->fType->New(addr);
367 for( i=nCurr; i<left; ++i, addr += fValDiff )
368 ::
new(addr) std::string();
370 case kIsPointer|kIsClass:
371 case kIsPointer|kBIT_ISSTRING:
372 case kIsPointer|kBIT_ISTSTRING|kIsClass:
373 for( i=nCurr; i<left; ++i, addr += fValDiff )
377 addr = ((
char*)fEnv->fStart)+fValOffset+fValDiff*nCurr;
382 switch(fVal->fCase) {
387 if (oldstart && oldstart != fEnv->fStart) {
389 for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
393 fVal->fType->Move(((
char*)oldstart)+offset,((
char*)fEnv->fStart)+offset);
396 for( i=nCurr; i<left; ++i, addr += fValDiff ) {
397 fVal->fType->New(addr);
401 for( i=nCurr; i<left; ++i, addr += fValDiff )
402 ::
new(addr) std::string();
404 case kIsPointer|kIsClass:
405 case kIsPointer|kBIT_ISSTRING:
406 case kIsPointer|kBIT_ISTSTRING|kIsClass:
407 for( i=nCurr; i<left; ++i, addr += fValDiff )
415 void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force)
419 if ( fEnv && fEnv->fObject ) {
420 size_t nCurr = Size();
421 PCont_t c = PCont_t(fEnv->fObject);
422 fEnv->fStart = nCurr>0 ? &(*c->begin()) : 0;
423 if ( left == nCurr ) {
426 else if ( left < nCurr ) {
427 Shrink(nCurr, left, force);
433 Fatal(
"TEmulatedCollectionProxy",
"Resize> Logic error - no proxy object set.");
436 void* TEmulatedCollectionProxy::At(UInt_t idx)
439 if ( fEnv && fEnv->fObject ) {
440 PCont_t c = PCont_t(fEnv->fObject);
441 size_t s = c->size();
442 if ( idx >= (s/fValDiff) ) {
445 return idx<(s/fValDiff) ? ((
char*)&(*c->begin()))+idx*fValDiff : 0;
447 Fatal(
"TEmulatedCollectionProxy",
"At> Logic error - no proxy object set.");
451 void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete)
455 Resize(n, forceDelete);
456 return fEnv->fObject;
463 void TEmulatedCollectionProxy::Insert(
const void * ,
void * ,
size_t )
465 Fatal(
"Insert",
"Not yet implemented, require copy of objects.");
468 void TEmulatedCollectionProxy::Commit(
void* )
472 void TEmulatedCollectionProxy::ReadItems(
int nElements, TBuffer &b)
475 Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3;
476 StreamHelper* itm = (StreamHelper*)At(0);
477 switch (fVal->fCase) {
480 switch(
int(fVal->fKind) ) {
481 case kBool_t: b.ReadFastArray(&itm->boolean , nElements);
break;
482 case kChar_t: b.ReadFastArray(&itm->s_char , nElements);
break;
483 case kShort_t: b.ReadFastArray(&itm->s_short , nElements);
break;
484 case kInt_t: b.ReadFastArray(&itm->s_int , nElements);
break;
485 case kLong_t: b.ReadFastArray(&itm->s_long , nElements);
break;
486 case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements);
break;
487 case kFloat_t: b.ReadFastArray(&itm->flt , nElements);
break;
488 case kFloat16_t: b.ReadFastArrayFloat16(&itm->flt, nElements);
break;
489 case kDouble_t: b.ReadFastArray(&itm->dbl , nElements);
break;
490 case kUChar_t: b.ReadFastArray(&itm->u_char , nElements);
break;
491 case kUShort_t: b.ReadFastArray(&itm->u_short , nElements);
break;
492 case kUInt_t: b.ReadFastArray(&itm->u_int , nElements);
break;
493 case kULong_t: b.ReadFastArray(&itm->u_long , nElements);
break;
494 case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements);
break;
495 case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements);
break;
499 Error(
"TEmulatedCollectionProxy",
"fType %d is not supported yet!\n",fVal->fKind);
503 #define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
506 DOLOOP( b.StreamObject(i,fVal->fType) );
508 DOLOOP( i->read_std_string(b) );
509 case kIsPointer|kIsClass:
510 DOLOOP( i->read_any_object(fVal,b) );
511 case kIsPointer|kBIT_ISSTRING:
512 DOLOOP( i->read_std_string_pointer(b) );
513 case kIsPointer|kBIT_ISTSTRING|kIsClass:
514 DOLOOP( i->read_tstring_pointer(vsn3,b) );
521 void TEmulatedCollectionProxy::WriteItems(
int nElements, TBuffer &b)
524 StreamHelper* itm = (StreamHelper*)At(0);
525 switch (fVal->fCase) {
528 itm = (StreamHelper*)At(0);
529 switch(
int(fVal->fKind) ) {
530 case kBool_t: b.WriteFastArray(&itm->boolean , nElements);
break;
531 case kChar_t: b.WriteFastArray(&itm->s_char , nElements);
break;
532 case kShort_t: b.WriteFastArray(&itm->s_short , nElements);
break;
533 case kInt_t: b.WriteFastArray(&itm->s_int , nElements);
break;
534 case kLong_t: b.WriteFastArray(&itm->s_long , nElements);
break;
535 case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements);
break;
536 case kFloat_t: b.WriteFastArray(&itm->flt , nElements);
break;
537 case kFloat16_t: b.WriteFastArrayFloat16(&itm->flt, nElements);
break;
538 case kDouble_t: b.WriteFastArray(&itm->dbl , nElements);
break;
539 case kUChar_t: b.WriteFastArray(&itm->u_char , nElements);
break;
540 case kUShort_t: b.WriteFastArray(&itm->u_short , nElements);
break;
541 case kUInt_t: b.WriteFastArray(&itm->u_int , nElements);
break;
542 case kULong_t: b.WriteFastArray(&itm->u_long , nElements);
break;
543 case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements);
break;
544 case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements);
break;
548 Error(
"TEmulatedCollectionProxy",
"fType %d is not supported yet!\n",fVal->fKind);
551 #define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
553 DOLOOP( b.StreamObject(i,fVal->fType) );
555 DOLOOP( TString(i->c_str()).Streamer(b) );
556 case kIsPointer|kIsClass:
557 DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) );
558 case kBIT_ISSTRING|kIsPointer:
559 DOLOOP( i->write_std_string_pointer(b) );
560 case kBIT_ISTSTRING|kIsClass|kIsPointer:
561 DOLOOP( i->write_tstring_pointer(b) );
566 void TEmulatedCollectionProxy::ReadBuffer(TBuffer &b,
void *obj,
const TClass *onfileClass)
570 SetOnFileClass((TClass*)onfileClass);
574 void TEmulatedCollectionProxy::ReadBuffer(TBuffer &b,
void *obj)
578 TPushPop env(
this,obj);
581 if ( fEnv->fObject ) {
582 Resize(nElements,
true);
584 if ( nElements > 0 ) {
585 ReadItems(nElements, b);
589 void TEmulatedCollectionProxy::Streamer(TBuffer &b)
592 if ( b.IsReading() ) {
595 if ( fEnv->fObject ) {
596 Resize(nElements,
true);
598 if ( nElements > 0 ) {
599 ReadItems(nElements, b);
603 int nElements = fEnv->fObject ? Size() : 0;
605 if ( nElements > 0 ) {
606 WriteItems(nElements, b);
614 static TStreamerElement* R__CreateEmulatedElement(
const char *dmName,
const char *dmFull, Int_t offset)
618 TString s1( TClassEdit::ShortType(dmFull,0) );
619 TString dmType( TClassEdit::ShortType(dmFull,1) );
620 Bool_t dmIsPtr = (s1 != dmType);
621 const char *dmTitle =
"Emulation";
623 TDataType *dt = gROOT->GetType(dmType);
624 if (dt && dt->GetType() > 0 ) {
626 dtype = dt->GetType();
628 if (dmIsPtr && dtype != kCharStar) {
629 Error(
"Pair Emulation Building",
"%s is not yet supported in pair emulation",
633 TStreamerElement *el =
new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
639 static const char *full_string_name =
"basic_string<char,char_traits<char>,allocator<char> >";
640 if (strcmp(dmType,
"string") == 0 || strcmp(dmType,
"std::string") == 0 || strcmp(dmType,full_string_name)==0 ) {
641 return new TStreamerSTLstring(dmName,dmTitle,offset,dmFull,dmIsPtr);
643 if (TClassEdit::IsSTLCont(dmType)) {
644 return new TStreamerSTL(dmName,dmTitle,offset,dmFull,dmFull,dmIsPtr);
646 TClass *clm = TClass::GetClass(dmType);
650 Int_t dtype = kInt_t;
651 return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
655 if (clm->IsTObject()) {
656 return new TStreamerObjectPointer(dmName,dmTitle,offset,dmFull);
658 return new TStreamerObjectAnyPointer(dmName,dmTitle,offset,dmFull);
662 if (clm->IsTObject()) {
663 return new TStreamerObject(dmName,dmTitle,offset,dmFull);
664 }
else if(clm == TString::Class() && !dmIsPtr) {
665 return new TStreamerString(dmName,dmTitle,offset);
667 return new TStreamerObjectAny(dmName,dmTitle,offset,dmFull);
673 static TStreamerInfo *R__GenerateTClassForPair(
const std::string &fname,
const std::string &sname)
679 TStreamerInfo *i = (TStreamerInfo*)TClass::GetClass(
"pair<const int,int>")->GetStreamerInfo()->Clone();
680 std::string pname =
"pair<"+fname+
","+sname;
681 pname += (pname[pname.length()-1]==
'>') ?
" >" :
">";
682 i->SetName(pname.c_str());
684 i->GetElements()->Delete();
685 TStreamerElement *fel = R__CreateEmulatedElement(
"first", fname.c_str(), 0);
688 i->GetElements()->Add( fel );
690 size = fel->GetSize();
691 Int_t sp =
sizeof(
void *);
693 if (size%sp != 0) size = size - size%sp + sp;
698 TStreamerElement *second = R__CreateEmulatedElement(
"second", sname.c_str(), size);
700 i->GetElements()->Add( second );
705 Int_t oldlevel = gErrorIgnoreLevel;
707 gErrorIgnoreLevel = kError;
709 gErrorIgnoreLevel = oldlevel;