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;