51 const UInt_t kIsBigFile = BIT(16);
 
   52 const Int_t  kMaxLen = 2048;
 
   54 ClassImp(TDirectoryFile);
 
   60 TDirectoryFile::TDirectoryFile()
 
   80 TDirectoryFile::TDirectoryFile(
const char *name, 
const char *title, Option_t *classname, TDirectory* initMotherDir)
 
   88    R__LOCKGUARD(gROOTMutex);
 
   93    if (!initMotherDir) initMotherDir = gDirectory;
 
   95    if (strchr(name,
'/')) {
 
   96       ::Error(
"TDirectoryFile",
"directory name (%s) cannot contain a slash", name);
 
  100    if (strlen(GetName()) == 0) {
 
  101       ::Error(
"TDirectoryFile",
"directory name cannot be \"\"");
 
  102       gDirectory = 
nullptr;
 
  106    BuildDirectoryFile(initMotherDir ? initMotherDir->GetFile() : 
nullptr, initMotherDir);
 
  108    TDirectory* motherdir = GetMotherDir();
 
  109    TFile* f = TDirectoryFile::GetFile();
 
  111    if (!motherdir || !f) 
return;
 
  112    if (!f->IsWritable()) 
return; 
 
  113    if (motherdir->GetKey(name)) {
 
  114       Error(
"TDirectoryFile",
"An object with name %s exists already", name);
 
  117    TClass *cl = 
nullptr;
 
  119       cl = TClass::GetClass(classname);
 
  121          Error(
"TDirectoryFile",
"Invalid class name: %s",classname);
 
  125       cl = TDirectoryFile::IsA();
 
  131    InitDirectoryFile(cl);
 
  137    gROOT->GetUUIDs()->AddUUID(fUUID,
this);
 
  147 void TDirectoryFile::InitDirectoryFile(TClass *cl)
 
  149    TFile* f = GetFile(); 
 
  154       TDirectory* motherdir = GetMotherDir();
 
  155       fSeekParent  = f->GetSeekDir();
 
  156       Int_t nbytes = TDirectoryFile::Sizeof();
 
  157       TKey *key    = 
new TKey(fName,fTitle,cl,nbytes,motherdir);
 
  158       fNbytesName  = key->GetKeylen();
 
  159       fSeekDir     = key->GetSeekKey();
 
  160       if (fSeekDir == 0) 
return;
 
  161       char *buffer = key->GetBuffer();
 
  162       TDirectoryFile::FillBuffer(buffer);
 
  163       Int_t cycle = motherdir ? motherdir->AppendKey(key) : 0;
 
  164       key->WriteFile(cycle);
 
  168       fSeekDir     = f->DirCreateEntry(
this);
 
  169       if (fSeekDir == 0) 
return;
 
  177 TDirectoryFile::~TDirectoryFile()
 
  180       fKeys->Delete(
"slow");
 
  184    TDirectoryFile::CleanTargets();
 
  194       fList->Delete(
"slow");
 
  199       Info(
"~TDirectoryFile", 
"dtor called for %s", GetName());
 
  209 void TDirectoryFile::Append(TObject *obj, Bool_t replace )
 
  211    if (!obj || !fList) 
return;
 
  213    TDirectory::Append(obj,replace);
 
  215    if (!fMother) 
return;
 
  216    if (fMother->IsA() == TMapFile::Class()) {
 
  217       TMapFile *mfile = (TMapFile*)fMother;
 
  225 Int_t TDirectoryFile::AppendKey(TKey *key)
 
  228       Error(
"AppendKey",
"TDirectoryFile not initialized yet.");
 
  234    key->SetMotherDir(
this);
 
  237    TKey *oldkey = (TKey*)fKeys->FindObject(key->GetName());
 
  245    TObjLink *lnk = fKeys->FirstLink();
 
  247       oldkey = (TKey*)lnk->GetObject();
 
  248       if (!strcmp(oldkey->GetName(), key->GetName()))
 
  253    fKeys->AddBefore(lnk, key);
 
  254    return oldkey->GetCycle() + 1;
 
  260 void TDirectoryFile::Browse(TBrowser *b)
 
  265       TObject *obj = 
nullptr;
 
  267       TKey *key = 
nullptr, *keyo = 
nullptr;
 
  273       while ((obj = nextin())) {
 
  274          if (fKeys->FindObject(obj->GetName())) 
continue;
 
  275          b->Add(obj, obj->GetName());
 
  279       while ((key = (TKey *) next())) {
 
  281          if (!keyo || (keyo && strcmp(keyo->GetName(), key->GetName()))) {
 
  283             obj = fList->FindObject(key->GetName());
 
  286                b->Add(obj, obj->GetName());
 
  287                if (obj->IsFolder() && !obj->InheritsFrom(
"TTree"))
 
  293             name.Form(
"%s;%d", key->GetName(), key->GetCycle());
 
  305 void TDirectoryFile::BuildDirectoryFile(TFile* motherFile, TDirectory* motherDir)
 
  311    if (motherDir && strlen(GetName()) != 0) motherDir->Append(
this);
 
  321    fList       = 
new THashList(100,50);
 
  322    fKeys       = 
new THashList(100,50);
 
  325    fFile       = motherFile ? motherFile : TFile::CurrentFile();
 
  340 Bool_t TDirectoryFile::cd(
const char *path)
 
  342    Bool_t ok = TDirectory::cd(path);
 
  343    if (ok) TFile::CurrentFile() = fFile;
 
  350 void TDirectoryFile::CleanTargets()
 
  358    TDirectory::CleanTargets();
 
  373 TObject *TDirectoryFile::CloneObject(
const TObject *obj, Bool_t autoadd )
 
  376    char *pobj = (
char*)obj->IsA()->New();
 
  377    if (!pobj) 
return nullptr;
 
  379    Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
 
  380    if (baseOffset==-1) {
 
  384       Fatal(
"CloneObject",
"Incorrect detection of the inheritance from TObject for class %s.\n",
 
  385             obj->IsA()->GetName());
 
  387    TObject *newobj = (TObject*)(pobj+baseOffset);
 
  394       TFile *filsav = gFile;
 
  396       const Int_t bufsize = 10000;
 
  397       TBufferFile buffer(TBuffer::kWrite,bufsize);
 
  398       buffer.MapObject(obj);  
 
  400          Bool_t isRef = obj->TestBit(kIsReferenced);
 
  401          ((TObject*)obj)->ResetBit(kIsReferenced);
 
  403          ((TObject*)obj)->Streamer(buffer);
 
  405          if (isRef) ((TObject*)obj)->SetBit(kIsReferenced);
 
  409       buffer.SetReadMode();
 
  411       buffer.SetBufferOffset(0);
 
  412       buffer.MapObject(newobj);  
 
  413       newobj->Streamer(buffer);
 
  414       newobj->ResetBit(kIsReferenced);
 
  415       newobj->ResetBit(kCanDelete);
 
  420       ROOT::DirAutoAdd_t func = obj->IsA()->GetDirectoryAutoAdd();
 
  431 TObject *TDirectoryFile::FindObjectAnyFile(
const char *name)
 const 
  434    R__LOCKGUARD(gROOTMutex);
 
  435    TIter next(gROOT->GetListOfFiles());
 
  436    while ((f = (TFile*)next())) {
 
  437       TObject *obj = f->GetList()->FindObject(name);
 
  458 TDirectory *TDirectoryFile::GetDirectory(
const char *apath,
 
  459                                          Bool_t printError, 
const char *funcname)
 
  462    if (apath) nch = strlen(apath);
 
  467    if (funcname==0 || strlen(funcname)==0) funcname = 
"GetDirectory";
 
  469    TDirectory *result = 
this;
 
  471    char *path = 
new char[nch+1]; path[0] = 0;
 
  472    if (nch) strlcpy(path,apath,nch+1);
 
  473    char *s = (
char*)strchr(path, 
':');
 
  476       R__LOCKGUARD(gROOTMutex);
 
  477       TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
 
  481          auto url = GetFile()->GetEndpointUrl();
 
  482          if (f && 0 == url->Compare(f->GetFile()->GetEndpointUrl()))
 
  483             return GetDirectory(s+1,printError,funcname);
 
  485       if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
 
  489          if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
 
  490          delete [] path; 
return result;
 
  492          if (printError) Error(funcname, 
"No such file %s", path);
 
  493          delete [] path; 
return nullptr;
 
  498    if (path[0] == 
'/') {
 
  499       TDirectory *td = fFile;
 
  500       if (!fFile) td = gROOT;
 
  501       result = td->GetDirectory(path+1,printError,funcname);
 
  502       delete [] path; 
return result;
 
  506    char *slash = (
char*)strchr(path,
'/');
 
  508       if (!strcmp(path, 
"..")) {
 
  509          result = GetMotherDir();
 
  510          delete [] path; 
return result;
 
  514          if (printError) Error(funcname,
"Unknown directory %s", path);
 
  515          delete [] path; 
return nullptr;
 
  518       delete [] path; 
return obj;
 
  521    TString subdir(path);
 
  522    slash = (
char*)strchr(subdir.Data(),
'/');
 
  525    if (!strcmp(subdir, 
"..")) {
 
  526       TDirectory* mom = GetMotherDir();
 
  528          result = mom->GetDirectory(slash+1,printError,funcname);
 
  529       delete [] path; 
return result;
 
  531    GetObject(subdir,obj);
 
  533       if (printError) Error(funcname,
"Unknown directory %s", subdir.Data());
 
  534       delete [] path; 
return nullptr;
 
  537    result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
 
  538    delete [] path; 
return result;
 
  544 void TDirectoryFile::Close(Option_t *option)
 
  546    if (!fList || !fSeekDir) {
 
  553    Bool_t nodelete = option ? (!strcmp(option, 
"nodelete") ? kTRUE : kFALSE) : kFALSE;
 
  557       TObjLink *lnk = fList->FirstLink();
 
  559          if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;
break;}
 
  568          if (fast) fList->Delete();
 
  569          else      fList->Delete(
"slow");
 
  575       fKeys->Delete(
"slow");
 
  578    TDirectoryFile::CleanTargets();
 
  615 void TDirectoryFile::Delete(
const char *namecycle)
 
  618      Info(
"Delete",
"Call for this = %s namecycle = %s",
 
  619                GetName(), (namecycle ? namecycle : 
"null"));
 
  621    TDirectory::TContext ctxt(
this);
 
  624    const char *nmcy = (namecycle) ? namecycle : 
"";
 
  625    DecodeNameCycle(nmcy, name, cycle, kMaxLen);
 
  628    Int_t deletetree   = 0;
 
  629    if(strcmp(name,
"*") == 0)   deleteall = 1;
 
  630    if(strcmp(name,
"*T") == 0){ deleteall = 1; deletetree = 1;}
 
  631    if(strcmp(name,
"T*") == 0){ deleteall = 1; deletetree = 1;}
 
  632    if(namecycle==0 || !namecycle[0]){ deleteall = 1; deletetree = 1;}
 
  633    TRegexp re(name,kTRUE);
 
  639    if (cycle >= 9999 ) {
 
  642       while ((idcur = (TNamed *) next())) {
 
  644          s = idcur->GetName();
 
  645          if (deleteall || s.Index(re) != kNPOS) {
 
  647             if (idcur->IsA() == TDirectoryFile::Class()) {
 
  649                if (!deletetree && deleteall) deleteOK = 0;
 
  653             fList->Remove(idcur);
 
  657                   ((TDirectory*) idcur)->ReadAll(
"dirs");
 
  658                idcur->Delete(deletetree ? 
"T*;*" : 
"*");
 
  671    if (cycle != 9999 ) {
 
  674          TIter nextkey(GetListOfKeys());
 
  675          while ((key = (TKey *) nextkey())) {
 
  678             if (deleteall || s.Index(re) != kNPOS) {
 
  679                if (cycle == key->GetCycle()) deleteOK = 1;
 
  680                if (cycle > 9999) deleteOK = 1;
 
  682                if (strstr(key->GetClassName(),
"TDirectory")) {
 
  684                   if (!deletetree && deleteall) deleteOK = 0;
 
  685                   if (cycle == key->GetCycle()) deleteOK = 2;
 
  691                   TDirectory* dir = GetDirectory(key->GetName(), kTRUE, 
"Delete");
 
  705          TFile* f = GetFile();
 
  706          if (fModified && (f!=0)) {
 
  719 void TDirectoryFile::FillBuffer(
char *&buffer)
 
  721    Version_t version = TDirectoryFile::Class_Version();
 
  722    if (fSeekDir > TFile::kStartBigFile ||
 
  723        fSeekParent > TFile::kStartBigFile ||
 
  724        fSeekKeys > TFile::kStartBigFile )
 
  732    tobuf(buffer, version);
 
  733    const bool reproducible = TestBit(TFile::kReproducible) || (fFile && fFile->TestBit(TFile::kReproducible));
 
  735       TDatime((UInt_t) 1).FillBuffer(buffer);
 
  736       TDatime((UInt_t) 1).FillBuffer(buffer);
 
  738       fDatimeC.FillBuffer(buffer);
 
  739       fDatimeM.FillBuffer(buffer);
 
  741    tobuf(buffer, fNbytesKeys);
 
  742    tobuf(buffer, fNbytesName);
 
  743    if (version > 1000) {
 
  744       tobuf(buffer, fSeekDir);
 
  745       tobuf(buffer, fSeekParent);
 
  746       tobuf(buffer, fSeekKeys);
 
  748       tobuf(buffer, (Int_t)fSeekDir);
 
  749       tobuf(buffer, (Int_t)fSeekParent);
 
  750       tobuf(buffer, (Int_t)fSeekKeys);
 
  753       TUUID(
"00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
 
  755       fUUID.FillBuffer(buffer);
 
  756    if (fFile && fFile->GetVersion() < 40000) 
return;
 
  757    if (version <=1000) 
for (Int_t i=0;i<3;i++) tobuf(buffer,Int_t(0));
 
  763 TKey *TDirectoryFile::FindKey(
const char *keyname)
 const 
  768    DecodeNameCycle(keyname, name, cycle, kMaxLen);
 
  769    return GetKey(name,cycle);
 
  779 TKey *TDirectoryFile::FindKeyAny(
const char *keyname)
 const 
  781    TDirectory *dirsav = gDirectory;
 
  785    DecodeNameCycle(keyname, name, cycle, kMaxLen);
 
  787    TIter next(GetListOfKeys());
 
  789    while ((key = (TKey *) next())) {
 
  790       if (!strcmp(name, key->GetName()))
 
  791          if ((cycle == 9999) || (cycle >= key->GetCycle()))  {
 
  792             const_cast<TDirectoryFile*
>(
this)->cd(); 
 
  798    while ((key = (TKey *) next())) {
 
  800       if (strstr(key->GetClassName(),
"TDirectory")) {
 
  802              const_cast<TDirectoryFile*
>(
this)->GetDirectory(key->GetName(), kTRUE, 
"FindKeyAny");
 
  803          TKey *k = subdir ? subdir->FindKeyAny(keyname) : 
nullptr;
 
  807    if (dirsav) dirsav->cd();
 
  819 TObject *TDirectoryFile::FindObjectAny(
const char *aname)
 const 
  822    TObject *obj = TDirectory::FindObjectAny(aname);
 
  825    TDirectory *dirsav = gDirectory;
 
  829    DecodeNameCycle(aname, name, cycle, kMaxLen);
 
  831    TIter next(GetListOfKeys());
 
  834    while ((key = (TKey *) next())) {
 
  835       if (!strcmp(name, key->GetName())) {
 
  836          if (cycle == 9999)             
return key->ReadObj();
 
  837          if (cycle >= key->GetCycle())  
return key->ReadObj();
 
  842    while ((key = (TKey *) next())) {
 
  844       if (strstr(key->GetClassName(),
"TDirectory")) {
 
  846            ((TDirectory*)
this)->GetDirectory(key->GetName(), kTRUE, 
"FindKeyAny");
 
  847          TKey *k = subdir ? subdir->FindKeyAny(aname) : 
nullptr;
 
  848          if (k) { 
if (dirsav) dirsav->cd(); 
return k->ReadObj();}
 
  851    if (dirsav) dirsav->cd();
 
  906 TObject *TDirectoryFile::Get(
const char *namecycle)
 
  911    DecodeNameCycle(namecycle, name, cycle, kMaxLen);
 
  912    Int_t nch = strlen(name);
 
  913    for (Int_t i = nch-1; i > 0; i--) {
 
  914       if (name[i] == 
'/') {
 
  916          TDirectory* dirToSearch=GetDirectory(name);
 
  917          const char *subnamecycle = namecycle + i + 1;
 
  919          return dirToSearch?dirToSearch->Get(subnamecycle):0;
 
  922    const char *namobj = name;
 
  926    TObject *idcur = fList ? fList->FindObject(namobj) : 
nullptr;
 
  928       if (idcur==
this && strlen(namobj)!=0) {
 
  933       } 
else if (cycle == 9999) {
 
  936          if (idcur->InheritsFrom(TCollection::Class()))
 
  946    TIter nextkey(GetListOfKeys());
 
  947    while ((key = (TKey *) nextkey())) {
 
  948       if (strcmp(namobj,key->GetName()) == 0) {
 
  949          if ((cycle == 9999) || (cycle == key->GetCycle())) {
 
  950             TDirectory::TContext ctxt(
this);
 
  951             idcur = key->ReadObj();
 
  975 void *TDirectoryFile::GetObjectUnchecked(
const char *namecycle)
 
  977    return GetObjectChecked(namecycle,(TClass*)
nullptr);
 
  983 void *TDirectoryFile::GetObjectChecked(
const char *namecycle, 
const char* classname)
 
  985    return GetObjectChecked(namecycle,TClass::GetClass(classname));
 
 1010 void *TDirectoryFile::GetObjectChecked(
const char *namecycle, 
const TClass* expectedClass)
 
 1014    if (!namecycle || 
'\0' == namecycle[0]) {
 
 1015       Error(
"GetObjectChecked", 
"The provided key name is invalid.");
 
 1022    DecodeNameCycle(namecycle, name, cycle, kMaxLen);
 
 1023    Int_t nch = strlen(name);
 
 1024    for (Int_t i = nch-1; i > 0; i--) {
 
 1025       if (name[i] == 
'/') {
 
 1027          TDirectory* dirToSearch=GetDirectory(name);
 
 1028          const char *subnamecycle = namecycle + i + 1;
 
 1031             return dirToSearch->GetObjectChecked(subnamecycle, expectedClass);
 
 1037    const char *namobj = name;
 
 1041    if (expectedClass==0 || expectedClass->IsTObject()) {
 
 1042       TObject *objcur = fList ? fList->FindObject(namobj) : 
nullptr;
 
 1044          if (objcur==
this && strlen(namobj)!=0) {
 
 1049          } 
else if (cycle == 9999) {
 
 1051             if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) 
return nullptr;
 
 1054             if (objcur->InheritsFrom(TCollection::Class()))
 
 1064    void *idcur = 
nullptr;
 
 1066    TIter nextkey(GetListOfKeys());
 
 1067    while ((key = (TKey *) nextkey())) {
 
 1068       if (strcmp(namobj,key->GetName()) == 0) {
 
 1069          if ((cycle == 9999) || (cycle == key->GetCycle())) {
 
 1070             TDirectory::TContext ctxt(
this);
 
 1071             idcur = key->ReadObjectAny(expectedClass);
 
 1086 Int_t TDirectoryFile::GetBufferSize()
 const 
 1088    if (fBufferSize <= 0) 
return fFile->GetBestBuffer();
 
 1089    else                  return fBufferSize;
 
 1098 TKey *TDirectoryFile::GetKey(
const char *name, Short_t cycle)
 const 
 1100    if (!fKeys) 
return nullptr;
 
 1103    TIter next( ((THashList *)(GetListOfKeys()))->GetListForObject(name) );
 
 1106    while (( key = (TKey *)next() )) {
 
 1107       if (!strcmp(name, key->GetName())) {
 
 1108          if ((cycle == 9999) || (cycle >= key->GetCycle()))
 
 1129 void TDirectoryFile::ls(Option_t *option)
 const 
 1131    TROOT::IndentLevel();
 
 1132    std::cout <<ClassName()<<
"*\t\t"<<GetName()<<
"\t"<<GetTitle()<<std::endl;
 
 1133    TROOT::IncreaseDirLevel();
 
 1135    TString opta = option;
 
 1136    TString opt  = opta.Strip(TString::kBoth);
 
 1137    Bool_t memobj  = kTRUE;
 
 1138    Bool_t diskobj = kTRUE;
 
 1140    if (opt.BeginsWith(
"-m")) {
 
 1142       if (opt.Length() > 2)
 
 1143          reg = opt(2,opt.Length());
 
 1144    } 
else if (opt.BeginsWith(
"-d")) {
 
 1146       if (opt.Length() > 2)
 
 1147          reg = opt(2,opt.Length());
 
 1148    } 
else if (!opt.IsNull())
 
 1151    TRegexp re(reg, kTRUE);
 
 1155       TIter nextobj(fList);
 
 1156       while ((obj = (TObject *) nextobj())) {
 
 1157          TString s = obj->GetName();
 
 1158          if (s.Index(re) == kNPOS) 
continue;
 
 1165       TIter next(GetListOfKeys());
 
 1166       while ((key = (TKey *) next())) {
 
 1167          TString s = key->GetName();
 
 1168          if (s.Index(re) == kNPOS) 
continue;
 
 1172    TROOT::DecreaseDirLevel();
 
 1178 TFile *TDirectoryFile::OpenFile(
const char *name, Option_t *option,
const char *ftitle, Int_t compress, Int_t netopt)
 
 1180    return TFile::Open(name,option,ftitle,compress,netopt);
 
 1194 TDirectory *TDirectoryFile::mkdir(
const char *name, 
const char *title, Bool_t returnExistingDirectory)
 
 1196    if (!name || !title || !name[0]) 
return nullptr;
 
 1197    if (!title[0]) title = name;
 
 1199       if (returnExistingDirectory)
 
 1200          return (TDirectoryFile*) GetDirectory(name);
 
 1202         Error(
"mkdir",
"An object with name %s exists already",name);
 
 1206    TDirectoryFile *newdir = 
nullptr;
 
 1207    if (
const char *slash = strchr(name,
'/')) {
 
 1208       TString workname(name, Long_t(slash-name));
 
 1209       TDirectoryFile *tmpdir = 
nullptr;
 
 1210       GetObject(workname.Data(), tmpdir);
 
 1212          tmpdir = (TDirectoryFile*)mkdir(workname.Data(),title);
 
 1213          if (!tmpdir) 
return nullptr;
 
 1215       if (!newdir) newdir = tmpdir;
 
 1216       tmpdir->mkdir(slash+1);
 
 1220    TDirectory::TContext ctxt(
this);
 
 1222    newdir = 
new TDirectoryFile(name, title, 
"", 
this);
 
 1233 void TDirectoryFile::Purge(Short_t)
 
 1235    if (!IsWritable()) 
return;
 
 1237    TDirectory::TContext ctxt(
this);
 
 1240    TIter  prev(GetListOfKeys(), kIterBackward);
 
 1242    while ((key = (TKey*)prev())) {      
 
 1243       TKey *keyprev = (TKey*)GetListOfKeys()->Before(key);
 
 1244       if (!keyprev) 
break;
 
 1245       if (key->GetKeep() == 0) {
 
 1246          if (strcmp(key->GetName(), keyprev->GetName()) == 0) {
 
 1252    TFile *f = GetFile();
 
 1253    if (fModified && f) {
 
 1269 void TDirectoryFile::ReadAll(Option_t* opt)
 
 1271    TDirectory::TContext ctxt(
this);
 
 1274    TIter next(GetListOfKeys());
 
 1276    Bool_t readdirs = ((opt!=0) && ((strcmp(opt,
"dirs")==0) || (strcmp(opt,
"dirs*")==0)));
 
 1279       while ((key = (TKey *) next())) {
 
 1282          if (strstr(key->GetClassName(),
"TDirectory")==0) 
continue;
 
 1284          TDirectory *dir = GetDirectory(key->GetName(), kTRUE, 
"ReadAll");
 
 1286          if ((dir!=0) && (strcmp(opt,
"dirs*")==0)) dir->ReadAll(
"dirs*");
 
 1289       while ((key = (TKey *) next())) {
 
 1290          TObject *thing = GetList()->FindObject(key->GetName());
 
 1291          if (thing) { 
delete thing; }
 
 1322 Int_t TDirectoryFile::ReadKeys(Bool_t forceRead)
 
 1324    if (!fFile || !fKeys) 
return 0;
 
 1326    if (!fFile->IsBinary())
 
 1327       return fFile->DirReadKeys(
this);
 
 1329    TDirectory::TContext ctxt(
this);
 
 1336       Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof();
 
 1337       char *header = 
new char[nbytes];
 
 1339       fFile->Seek(fSeekDir);
 
 1340       if ( fFile->ReadBuffer(buffer,nbytes) ) {
 
 1345       buffer += fNbytesName;
 
 1346       Version_t versiondir;
 
 1347       frombuf(buffer,&versiondir);
 
 1348       fDatimeC.ReadBuffer(buffer);
 
 1349       fDatimeM.ReadBuffer(buffer);
 
 1350       frombuf(buffer, &fNbytesKeys);
 
 1351       frombuf(buffer, &fNbytesName);
 
 1352       if (versiondir > 1000) {
 
 1353          frombuf(buffer, &fSeekDir);
 
 1354          frombuf(buffer, &fSeekParent);
 
 1355          frombuf(buffer, &fSeekKeys);
 
 1357          Int_t sdir,sparent,skeys;
 
 1358          frombuf(buffer, &sdir);    fSeekDir    = (Long64_t)sdir;
 
 1359          frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
 
 1360          frombuf(buffer, &skeys);   fSeekKeys   = (Long64_t)skeys;
 
 1366    Long64_t fsize = fFile->GetSize();
 
 1367    if ( fSeekKeys >  0) {
 
 1368       TKey *headerkey    = 
new TKey(fSeekKeys, fNbytesKeys, 
this);
 
 1369       headerkey->ReadFile();
 
 1370       buffer = headerkey->GetBuffer();
 
 1371       headerkey->ReadKeyBuffer(buffer);
 
 1374       frombuf(buffer, &nkeys);
 
 1375       for (Int_t i = 0; i < nkeys; i++) {
 
 1376          key = 
new TKey(
this);
 
 1377          key->ReadKeyBuffer(buffer);
 
 1378          if (key->GetSeekKey() < 64 || key->GetSeekKey() > fsize) {
 
 1379             Error(
"ReadKeys",
"reading illegal key, exiting after %d keys",i);
 
 1384          if (key->GetSeekPdir() < 64 || key->GetSeekPdir() > fsize) {
 
 1385             Error(
"ReadKeys",
"reading illegal key, exiting after %d keys",i);
 
 1408 Int_t TDirectoryFile::ReadTObject(TObject *obj, 
const char *keyname)
 
 1410    if (!fFile) { Error(
"Read",
"No file open"); 
return 0; }
 
 1411    TKey *key = 
nullptr;
 
 1412    TIter nextkey(GetListOfKeys());
 
 1413    while ((key = (TKey *) nextkey())) {
 
 1414       if (strcmp(keyname,key->GetName()) == 0) {
 
 1415          return key->Read(obj);
 
 1418    Error(
"Read",
"Key not found");
 
 1430 void TDirectoryFile::ResetAfterMerge(TFileMergeInfo *info)
 
 1445    TKey *key = fKeys ? (TKey*)fKeys->FindObject(fName) : 
nullptr;
 
 1448       cl = TClass::GetClass(key->GetClassName());
 
 1453       fKeys->Delete(
"slow");
 
 1456    InitDirectoryFile(cl);
 
 1459    TIter   next(GetList());
 
 1461    while ((idcur = next())) {
 
 1462       if (idcur->IsA() == TDirectoryFile::Class()) {
 
 1463          ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
 
 1476 void TDirectoryFile::rmdir(
const char *name)
 
 1478    if (!name || (*name==0)) 
return;
 
 1488 void TDirectoryFile::Save()
 
 1490    TDirectory::TContext ctxt(
this);
 
 1495    if (fList && fList->FirstLink()) {
 
 1496       auto lnk = fList->FirstLink()->shared_from_this();
 
 1498          TObject *idcur = lnk->GetObject();
 
 1499          if (idcur && idcur->InheritsFrom(TDirectoryFile::Class())) {
 
 1500             TDirectoryFile *dir = (TDirectoryFile *)idcur;
 
 1503          lnk = lnk->NextSP();
 
 1521 Int_t TDirectoryFile::SaveObjectAs(
const TObject *obj, 
const char *filename, Option_t *option)
 const 
 1524    TDirectory *dirsav = gDirectory;
 
 1525    TString fname = filename;
 
 1526    if (!filename || !filename[0]) {
 
 1527       fname.Form(
"%s.root",obj->GetName());
 
 1530    if (fname.Index(
".json") > 0) {
 
 1531       nbytes = TBufferJSON::ExportToFile(fname, obj, option);
 
 1533       TFile *local = TFile::Open(fname.Data(),
"recreate");
 
 1534       if (!local) 
return 0;
 
 1535       nbytes = obj->Write();
 
 1537       if (dirsav) dirsav->cd();
 
 1539    TString opt = option;
 
 1541    if (!opt.Contains(
"q")) {
 
 1542       if (!gSystem->AccessPathName(fname.Data())) obj->Info(
"SaveAs", 
"ROOT file %s has been created", fname.Data());
 
 1562 void TDirectoryFile::SaveSelf(Bool_t force)
 
 1564    if (IsWritable() && (fModified || force) && fFile) {
 
 1565       Bool_t dowrite = kTRUE;
 
 1566       if (fFile->GetListOfFree())
 
 1567         dowrite = fFile->GetListOfFree()->First() != 
nullptr;
 
 1569          TDirectory *dirsav = gDirectory;
 
 1570          if (dirsav != 
this) cd();
 
 1573          if (dirsav && dirsav != 
this) dirsav->cd();
 
 1583 void TDirectoryFile::SetBufferSize(Int_t bufsize)
 
 1585    fBufferSize = bufsize;
 
 1598 void TDirectoryFile::SetTRefAction(TObject *ref, TObject *parent)
 
 1600    Int_t offset = (
char*)ref - (
char*)parent;
 
 1601    TClass *cl = parent->IsA();
 
 1602    cl->BuildRealData(parent);
 
 1603    TStreamerInfo *info = (TStreamerInfo*)cl->GetStreamerInfo();
 
 1604    TIter next(info->GetElements());
 
 1605    TStreamerElement *element;
 
 1606    while((element = (TStreamerElement*)next())) {
 
 1607       if (element->GetOffset() != offset) 
continue;
 
 1608       Int_t execid = element->GetExecID();
 
 1609       if (execid > 0) ref->SetBit(execid << 8);
 
 1617 void TDirectoryFile::SetWritable(Bool_t writable)
 
 1619    TDirectory::TContext ctxt(
this);
 
 1621    fWritable = writable;
 
 1627       while ((idcur = next())) {
 
 1628          if (idcur->InheritsFrom(TDirectoryFile::Class())) {
 
 1629             TDirectoryFile *dir = (TDirectoryFile*)idcur;
 
 1630             dir->SetWritable(writable);
 
 1640 Int_t TDirectoryFile::Sizeof()
 const 
 1644    nbytes     += fDatimeC.Sizeof();
 
 1645    nbytes     += fDatimeM.Sizeof();
 
 1646    nbytes     += fUUID.Sizeof();
 
 1648    if (fFile && fFile->GetVersion() >= 40000) nbytes += 12;
 
 1656 void TDirectoryFile::Streamer(TBuffer &b)
 
 1658    Version_t v,version;
 
 1659    if (b.IsReading()) {
 
 1660       BuildDirectoryFile((TFile*)b.GetParent(), 
nullptr);
 
 1661       if (fFile && fFile->IsWritable()) fWritable = kTRUE;
 
 1663       if (fFile && !fFile->IsBinary()) {
 
 1664          Version_t R__v = b.ReadVersion(0, 0);
 
 1666          TClass* dirclass = (R__v < 5) ? TDirectory::Class() : TDirectoryFile::Class();
 
 1668          b.ClassBegin(dirclass, R__v);
 
 1672          b.ClassMember(
"CreateTime",
"TString");
 
 1674          TDatime timeC(sbuf.Data());
 
 1677          b.ClassMember(
"ModifyTime",
"TString");
 
 1679          TDatime timeM(sbuf.Data());
 
 1682          b.ClassMember(
"UUID",
"TString");
 
 1684          TUUID id(sbuf.Data());
 
 1687          b.ClassEnd(dirclass);
 
 1692          fDatimeC.Streamer(b);
 
 1693          fDatimeM.Streamer(b);
 
 1696          if (version > 1000) {
 
 1702             Int_t sdir,sparent,skeys;
 
 1703             b >> sdir;    fSeekDir    = (Long64_t)sdir;
 
 1704             b >> sparent; fSeekParent = (Long64_t)sparent;
 
 1705             b >> skeys;   fSeekKeys   = (Long64_t)skeys;
 
 1709             fUUID.StreamerV1(b);
 
 1715       R__LOCKGUARD(gROOTMutex);
 
 1716       gROOT->GetUUIDs()->AddUUID(fUUID,
this);
 
 1717       if (fSeekKeys) ReadKeys();
 
 1719       if (fFile && !fFile->IsBinary()) {
 
 1720          b.WriteVersion(TDirectoryFile::Class());
 
 1724          b.ClassBegin(TDirectoryFile::Class());
 
 1726          b.ClassMember(
"CreateTime",
"TString");
 
 1727          sbuf = fDatimeC.AsSQLString();
 
 1730          b.ClassMember(
"ModifyTime",
"TString");
 
 1732          sbuf = fDatimeM.AsSQLString();
 
 1735          b.ClassMember(
"UUID",
"TString");
 
 1736          sbuf = fUUID.AsString();
 
 1739          b.ClassEnd(TDirectoryFile::Class());
 
 1741          version = TDirectoryFile::Class_Version();
 
 1742          if (fFile && fFile->GetEND() > TFile::kStartBigFile) version += 1000;
 
 1744          fDatimeC.Streamer(b);
 
 1745          fDatimeM.Streamer(b);
 
 1748          if (version > 1000) {
 
 1753             b << (Int_t)fSeekDir;
 
 1754             b << (Int_t)fSeekParent;
 
 1755             b << (Int_t)fSeekKeys;
 
 1758          if (version <=1000) 
for (Int_t i=0;i<3;i++) b << Int_t(0);
 
 1771 Int_t TDirectoryFile::Write(
const char *, Int_t opt, Int_t bufsize)
 
 1773    if (!IsWritable()) 
return 0;
 
 1774    TDirectory::TContext ctxt(
this);
 
 1780    while ((obj=next())) {
 
 1781       nbytes += obj->Write(0,opt,bufsize);
 
 1791 Int_t TDirectoryFile::Write(
const char *n, Int_t opt, Int_t bufsize)
 const 
 1793    Error(
"Write const",
"A const TDirectory object should not be saved. We try to proceed anyway.");
 
 1794    return const_cast<TDirectoryFile*
>(
this)->Write(n, opt, bufsize);
 
 1841 Int_t TDirectoryFile::WriteTObject(
const TObject *obj, 
const char *name, Option_t *option, Int_t bufsize)
 
 1843    TDirectory::TContext ctxt(
this);
 
 1846       const char *objname = 
"no name specified";
 
 1847       if (name) objname = name;
 
 1848       else if (obj) objname = obj->GetName();
 
 1849       Error(
"WriteTObject",
"The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
 
 1853    if (!fFile->IsWritable()) {
 
 1854       if (!fFile->TestBit(TFile::kWriteError)) {
 
 1856          Error(
"WriteTObject",
"Directory %s is not writable", fFile->GetName());
 
 1863    TString opt = option;
 
 1866    TKey *key=0, *oldkey=0;
 
 1867    Int_t bsize = GetBufferSize();
 
 1868    if (bufsize > 0) bsize = bufsize;
 
 1874       oname = obj->GetName();
 
 1877    Int_t nch = strlen(oname);
 
 1878    char *newName = 
nullptr;
 
 1879    if (nch && oname[nch-1] == 
' ') {
 
 1880       newName = 
new char[nch+1];
 
 1881       strlcpy(newName,oname,nch+1);
 
 1882       for (Int_t i=0;i<nch;i++) {
 
 1883          if (newName[nch-i-1] != 
' ') 
break;
 
 1884          newName[nch-i-1] = 0;
 
 1889    if (opt.Contains(
"overwrite")) {
 
 1892       key = GetKey(oname);
 
 1898    if (opt.Contains(
"writedelete")) {
 
 1899       oldkey = GetKey(oname);
 
 1901    key = fFile->CreateKey(
this, obj, oname, bsize);
 
 1902    if (newName) 
delete [] newName;
 
 1904    if (!key->GetSeekKey()) {
 
 1907       if (bufsize) fFile->SetBufferSize(bufsize);
 
 1910    fFile->SumBuffer(key->GetObjlen());
 
 1911    Int_t nbytes = key->WriteFile(0);
 
 1912    if (fFile->TestBit(TFile::kWriteError)) {
 
 1913       if (bufsize) fFile->SetBufferSize(bufsize);
 
 1920    if (bufsize) fFile->SetBufferSize(bufsize);
 
 1954 Int_t TDirectoryFile::WriteObjectAny(
const void *obj, 
const char *classname, 
const char *name, Option_t *option, Int_t bufsize)
 
 1956    TClass *cl = TClass::GetClass(classname);
 
 1958       TObject *info_obj = *(TObject**)obj;
 
 1959       TVirtualStreamerInfo *info = 
dynamic_cast<TVirtualStreamerInfo*
>(info_obj);
 
 1961          Error(
"WriteObjectAny",
"Unknown class: %s",classname);
 
 1964          cl = info->GetClass();
 
 1967    return WriteObjectAny(obj,cl,name,option,bufsize);
 
 1981 Int_t TDirectoryFile::WriteObjectAny(
const void *obj, 
const TClass *cl, 
const char *name, Option_t *option, Int_t bufsize)
 
 1983    TDirectory::TContext ctxt(
this);
 
 1985    if (!fFile) 
return 0;
 
 1988       Error(
"WriteObject",
"Unknown type for %s, it can not be written.",name);
 
 1992    if (!fFile->IsWritable()) {
 
 1993       if (!fFile->TestBit(TFile::kWriteError)) {
 
 1995          Error(
"WriteObject",
"File %s is not writable", fFile->GetName());
 
 2002    const char *className = cl->GetName();
 
 2009    if (cl && cl->GetCollectionProxy() && 
dynamic_cast<TEmulatedCollectionProxy*
>(cl->GetCollectionProxy())) {
 
 2010       Error(
"WriteObjectAny",
 
 2011             "The class requested (%s) for the key name \"%s\"" 
 2012             " is an instance of an stl collection and does not have a compiled CollectionProxy." 
 2013             " Please generate the dictionary for this collection (%s). No data will be written.",
 
 2014             className, oname, className);
 
 2018    TKey *key, *oldkey = 
nullptr;
 
 2019    Int_t bsize = GetBufferSize();
 
 2020    if (bufsize > 0) bsize = bufsize;
 
 2022    TString opt = option;
 
 2026    Int_t nch = strlen(oname);
 
 2027    char *newName = 
nullptr;
 
 2028    if (nch && oname[nch-1] == 
' ') {
 
 2029       newName = 
new char[nch+1];
 
 2030       strlcpy(newName,oname,nch+1);
 
 2031       for (Int_t i=0;i<nch;i++) {
 
 2032          if (newName[nch-i-1] != 
' ') 
break;
 
 2033          newName[nch-i-1] = 0;
 
 2038    if (opt.Contains(
"overwrite")) {
 
 2041       key = GetKey(oname);
 
 2047    if (opt.Contains(
"writedelete")) {
 
 2048       oldkey = GetKey(oname);
 
 2050    key = fFile->CreateKey(
this, obj, cl, oname, bsize);
 
 2051    if (newName) 
delete [] newName;
 
 2053    if (!key->GetSeekKey()) {
 
 2058    fFile->SumBuffer(key->GetObjlen());
 
 2059    Int_t nbytes = key->WriteFile(0);
 
 2060    if (fFile->TestBit(TFile::kWriteError)) 
return 0;
 
 2073 void TDirectoryFile::WriteDirHeader()
 
 2075    TFile* f = GetFile();
 
 2078    if (!f->IsBinary()) {
 
 2080       f->DirWriteHeader(
this);
 
 2084    Int_t nbytes  = TDirectoryFile::Sizeof();  
 
 2085    char *header = 
new char[nbytes];
 
 2086    char *buffer = header;
 
 2088    TDirectoryFile::FillBuffer(buffer);
 
 2089    Long64_t pointer = fSeekDir + fNbytesName; 
 
 2092    f->WriteBuffer(header, nbytes);
 
 2093    if (f->MustFlush()) f->Flush();
 
 2102 void TDirectoryFile::WriteKeys()
 
 2104    TFile* f = GetFile();
 
 2107    if (!f->IsBinary()) {
 
 2108       f->DirWriteKeys(
this);
 
 2113    if (fSeekKeys != 0) {
 
 2114       f->MakeFree(fSeekKeys, fSeekKeys + fNbytesKeys -1);
 
 2119    Int_t nkeys  = fKeys->GetSize();
 
 2120    Int_t nbytes = 
sizeof nkeys;          
 
 2121    if (f->GetEND() > TFile::kStartBigFile) nbytes += 8;
 
 2122    while ((key = (TKey*)next())) {
 
 2123       nbytes += key->Sizeof();
 
 2125    TKey *headerkey  = 
new TKey(fName,fTitle,IsA(),nbytes,
this);
 
 2126    if (headerkey->GetSeekKey() == 0) {
 
 2130    char *buffer = headerkey->GetBuffer();
 
 2132    tobuf(buffer, nkeys);
 
 2133    while ((key = (TKey*)next())) {
 
 2134       key->FillBuffer(buffer);
 
 2137    fSeekKeys     = headerkey->GetSeekKey();
 
 2138    fNbytesKeys   = headerkey->GetNbytes();
 
 2139    headerkey->WriteFile();