Logo ROOT  
Reference Guide
TDirectoryFile.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Rene Brun 22/01/2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 /**
13  \class TDirectoryFile
14  \ingroup IO
15 
16  A ROOT file is structured in Directories (like a file system).
17  Each Directory has a list of Keys (see TKeys) and a list of objects
18  in memory. A Key is a small object that describes the type and location
19  of a persistent object in a file. The persistent object may be a directory.
20 Begin_Macro
21 ../../../tutorials/io/fildir.C
22 End_Macro
23  The structure of a file is shown in TFile::TFile
24 */
25 
26 #include <iostream>
27 #include "Strlen.h"
28 #include "strlcpy.h"
29 #include "TDirectoryFile.h"
30 #include "TFile.h"
31 #include "TBufferFile.h"
32 #include "TBufferJSON.h"
33 #include "TMapFile.h"
34 #include "TClassTable.h"
35 #include "TInterpreter.h"
36 #include "THashList.h"
37 #include "TBrowser.h"
38 #include "TFree.h"
39 #include "TKey.h"
40 #include "TStreamerInfo.h"
41 #include "TROOT.h"
42 #include "TError.h"
43 #include "Bytes.h"
44 #include "TClass.h"
45 #include "TRegexp.h"
46 #include "TSystem.h"
47 #include "TStreamerElement.h"
48 #include "TProcessUUID.h"
49 #include "TVirtualMutex.h"
51 
52 const UInt_t kIsBigFile = BIT(16);
53 const Int_t kMaxLen = 2048;
54 
56 
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Default TDirectoryFile constructor
60 
62 {
63  /// Intentionally placed here
64  /// when TDirectoryFile() = default; used, mac1014/cxx17 fails on some tests
65  /// Problem with TObject::IsOnHeap() failing
66 }
67 
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 /// Create a new TDirectoryFile
71 ///
72 /// A new directory with a name and a title is created in the current directory.
73 /// The directory header information is immediately saved on the file
74 /// A new key is added in the parent directory.
75 /// When this constructor is called from a class directly derived
76 /// from TDirectoryFile, the third argument, classname, MUST be specified.
77 /// In this case, classname must be the name of the derived class.
78 ///
79 /// Note that the directory name cannot contain slashes.
80 
81 TDirectoryFile::TDirectoryFile(const char *name, const char *title, Option_t *classname, TDirectory* initMotherDir)
82 {
83  // We must not publish this objects to the list of RecursiveRemove (indirectly done
84  // by 'Appending' this object to it's mother) before the object is completely
85  // initialized.
86  // However a better option would be to delay the publishing until the very end,
87  // but it is currently done in the middle of the initialization (by Build which
88  // is a public interface) ....
90 
91  fName = name;
92  fTitle = title;
93 
94  if (!initMotherDir) initMotherDir = gDirectory;
95 
96  if (strchr(name,'/')) {
97  ::Error("TDirectoryFile","directory name (%s) cannot contain a slash", name);
98  gDirectory = nullptr;
99  return;
100  }
101  if (strlen(GetName()) == 0) {
102  ::Error("TDirectoryFile","directory name cannot be \"\"");
103  gDirectory = nullptr;
104  return;
105  }
106 
107  BuildDirectoryFile(initMotherDir ? initMotherDir->GetFile() : nullptr, initMotherDir);
108 
109  TDirectory* motherdir = GetMotherDir();
111 
112  if (!motherdir || !f) return;
113  if (!f->IsWritable()) return; //*-* in case of a directory in memory
114  if (motherdir->GetKey(name)) {
115  Error("TDirectoryFile","An object with name %s exists already", name);
116  return;
117  }
118  TClass *cl = nullptr;
119  if (classname[0]) {
120  cl = TClass::GetClass(classname);
121  if (!cl) {
122  Error("TDirectoryFile","Invalid class name: %s",classname);
123  return;
124  }
125  } else {
126  cl = TDirectoryFile::IsA();
127  }
128 
129  fBufferSize = 0;
130  fWritable = kTRUE;
131 
132  InitDirectoryFile(cl);
133 
134  fModified = kFALSE;
135 
136  // Temporarily redundant, see comment on lock early in the function.
137  // R__LOCKGUARD(gROOTMutex);
138  gROOT->GetUUIDs()->AddUUID(fUUID,this);
139  // We should really be doing this now rather than in Build, see
140  // comment at the start of the function.
141  // if (initMotherDir && strlen(GetName()) != 0) initMotherDir->Append(this);
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 /// Initialize the key associated with this directory (and the related
146 /// data members.
147 
149 {
150  TFile* f = GetFile(); // NOLINT: silence clang-tidy warnings
151  if (f->IsBinary()) {
152  if (!cl) {
153  cl = IsA(); // NOLINT: silence clang-tidy warnings
154  }
155  TDirectory* motherdir = GetMotherDir();
156  fSeekParent = f->GetSeekDir();
157  Int_t nbytes = TDirectoryFile::Sizeof();
158  TKey *key = new TKey(fName,fTitle,cl,nbytes,motherdir);
159  fNbytesName = key->GetKeylen();
160  fSeekDir = key->GetSeekKey();
161  if (fSeekDir == 0) return;
162  char *buffer = key->GetBuffer();
164  Int_t cycle = motherdir ? motherdir->AppendKey(key) : 0;
165  key->WriteFile(cycle);
166  } else {
167  fSeekParent = 0;
168  fNbytesName = 0;
169  fSeekDir = f->DirCreateEntry(this);
170  if (fSeekDir == 0) return;
171  }
172 
173 }
174 
175 ////////////////////////////////////////////////////////////////////////////////
176 /// Destructor.
177 
179 {
180  if (fKeys) {
181  fKeys->Delete("slow");
182  SafeDelete(fKeys);
183  }
184 
186 
187  // Delete our content before we become somewhat invalid
188  // since some those objects (TTree for example) needs information
189  // from this object. Note that on some platform after the end
190  // of the body (i.e. thus during ~TDirectory which is also
191  // contains this code) the execution of 'this->GetFile()' fails
192  // to return the 'proper' value (because it uses the wrong
193  // virtual function).
194  if (fList) {
195  fList->Delete("slow");
196  SafeDelete(fList);
197  }
198 
199  if (gDebug) {
200  Info("~TDirectoryFile", "dtor called for %s", GetName());
201  }
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Append object to this directory.
206 ///
207 /// If replace is true:
208 /// remove any existing objects with the same same (if the name is not ""
209 
210 void TDirectoryFile::Append(TObject *obj, Bool_t replace /* = kFALSE */)
211 {
212  if (!obj || !fList) return;
213 
214  TDirectory::Append(obj,replace);
215 
216  if (!fMother) return;
217  if (fMother->IsA() == TMapFile::Class()) {
218  TMapFile *mfile = (TMapFile*)fMother;
219  mfile->Add(obj);
220  }
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 /// Insert key in the linked list of keys of this directory.
225 
227 {
228  if (!fKeys) {
229  Error("AppendKey","TDirectoryFile not initialized yet.");
230  return 0;
231  }
232 
233  fModified = kTRUE;
234 
235  key->SetMotherDir(this);
236 
237  // This is a fast hash lookup in case the key does not already exist
238  TKey *oldkey = (TKey*)fKeys->FindObject(key->GetName());
239  if (!oldkey) {
240  fKeys->Add(key);
241  return 1;
242  }
243 
244  // If the key name already exists we have to make a scan for it
245  // and insert the new key ahead of the current one
246  TObjLink *lnk = fKeys->FirstLink();
247  while (lnk) {
248  oldkey = (TKey*)lnk->GetObject();
249  if (!strcmp(oldkey->GetName(), key->GetName()))
250  break;
251  lnk = lnk->Next();
252  }
253 
254  fKeys->AddBefore(lnk, key);
255  return oldkey->GetCycle() + 1;
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Browse the content of the directory.
260 
262 {
263  TString name;
264 
265  if (b) {
266  TObject *obj = nullptr;
267  TIter nextin(fList);
268  TKey *key = nullptr, *keyo = nullptr;
269  TIter next(fKeys);
270 
271  cd();
272 
273  //Add objects that are only in memory
274  while ((obj = nextin())) {
275  if (fKeys->FindObject(obj->GetName())) continue;
276  b->Add(obj, obj->GetName());
277  }
278 
279  //Add keys
280  while ((key = (TKey *) next())) {
281  int skip = 0;
282  if (!keyo || (keyo && strcmp(keyo->GetName(), key->GetName()))) {
283  skip = 0;
284  obj = fList->FindObject(key->GetName());
285 
286  if (obj) {
287  b->Add(obj, obj->GetName());
288  if (obj->IsFolder() && !obj->InheritsFrom("TTree"))
289  skip = 1;
290  }
291  }
292 
293  if (!skip) {
294  name.Form("%s;%d", key->GetName(), key->GetCycle());
295  b->Add(key, name);
296  }
297 
298  keyo = key;
299  }
300  }
301 }
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 /// Initialise directory to defaults.
305 
306 void TDirectoryFile::BuildDirectoryFile(TFile* motherFile, TDirectory* motherDir)
307 {
308  // If directory is created via default ctor (when dir is read from file)
309  // don't add it here to the directory since its name is not yet known.
310  // It will be added to the directory in TKey::ReadObj().
311 
312  if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
313 
314  fModified = kTRUE;
315  fWritable = kFALSE;
316  fDatimeC.Set();
317  fDatimeM.Set();
318  fNbytesKeys = 0;
319  fSeekDir = 0;
320  fSeekParent = 0;
321  fSeekKeys = 0;
322  fList = new THashList(100,50);
323  fKeys = new THashList(100,50);
324  fList->UseRWLock();
325  fMother = motherDir;
326  fFile = motherFile ? motherFile : TFile::CurrentFile();
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Change current directory to "this" directory.
332 /// Using path one can
333 /// change the current directory to "path". The absolute path syntax is:
334 ///
335 /// file.root:/dir1/dir2
336 ///
337 /// where file.root is the file and /dir1/dir2 the desired subdirectory
338 /// in the file. Relative syntax is relative to "this" directory. E.g:
339 /// ../aa. Returns kTRUE in case of success.
340 
341 Bool_t TDirectoryFile::cd(const char *path)
342 {
343  Bool_t ok = TDirectory::cd(path);
344  if (ok) TFile::CurrentFile() = fFile;
345  return ok;
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 /// Clean the pointers to this object (gDirectory, TContext, etc.)
350 
352 {
353  // After CleanTargets either gFile was changed appropriately
354  // by a cd() or needs to be set to zero.
355  if (gFile == this) {
356  gFile = nullptr;
357  }
358 
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 /// Make a clone of an object using the Streamer facility.
364 ///
365 /// If the object derives from TNamed, this function is called
366 /// by TNamed::Clone. TNamed::Clone uses the optional argument newname to set
367 /// a new name to the newly created object.
368 ///
369 /// If autoadd is true and if the object class has a
370 /// DirectoryAutoAdd function, it will be called at the end of the
371 /// function with the parameter gDirectory. This usually means that
372 /// the object will be appended to the current ROOT directory.
373 
374 TObject *TDirectoryFile::CloneObject(const TObject *obj, Bool_t autoadd /* = kTRUE */)
375 {
376  // if no default ctor return immediately (error issued by New())
377  char *pobj = (char*)obj->IsA()->New();
378  if (!pobj) return nullptr;
379 
380  Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
381  if (baseOffset==-1) {
382  // cl does not inherit from TObject.
383  // Since this is not supported in this function, the only reason we could reach this code
384  // is because something is screwed up in the ROOT code.
385  Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
386  obj->IsA()->GetName());
387  }
388  TObject *newobj = (TObject*)(pobj+baseOffset);
389 
390  //create a buffer where the object will be streamed
391  {
392  // NOTE: do we still need to make this change to gFile?
393  // NOTE: This can not be 'gDirectory=0' as at least roofit expect gDirectory to not be null
394  // during the streaming ....
395  TFile *filsav = gFile;
396  gFile = nullptr;
397  const Int_t bufsize = 10000;
398  TBufferFile buffer(TBuffer::kWrite,bufsize);
399  buffer.MapObject(obj); //register obj in map to handle self reference
400  {
401  Bool_t isRef = obj->TestBit(kIsReferenced);
402  ((TObject*)obj)->ResetBit(kIsReferenced);
403 
404  ((TObject*)obj)->Streamer(buffer);
405 
406  if (isRef) ((TObject*)obj)->SetBit(kIsReferenced);
407  }
408 
409  // read new object from buffer
410  buffer.SetReadMode();
411  buffer.ResetMap();
412  buffer.SetBufferOffset(0);
413  buffer.MapObject(newobj); //register obj in map to handle self reference
414  newobj->Streamer(buffer);
415  newobj->ResetBit(kIsReferenced);
416  newobj->ResetBit(kCanDelete);
417  gFile = filsav;
418  }
419 
420  if (autoadd) {
421  ROOT::DirAutoAdd_t func = obj->IsA()->GetDirectoryAutoAdd();
422  if (func) {
423  func(newobj,this);
424  }
425  }
426  return newobj;
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Scan the memory lists of all files for an object with name
431 
433 {
434  TFile *f;
436  TIter next(gROOT->GetListOfFiles());
437  while ((f = (TFile*)next())) {
438  TObject *obj = f->GetList()->FindObject(name);
439  if (obj) return obj;
440  }
441  return nullptr;
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// Find a directory named "apath".
446 ///
447 /// It apath is null or empty, returns "this" directory.
448 /// Otherwise use the name "apath" to find a directory.
449 /// The absolute path syntax is:
450 ///
451 /// file.root:/dir1/dir2
452 ///
453 /// where file.root is the file and /dir1/dir2 the desired subdirectory
454 /// in the file. Relative syntax is relative to "this" directory. E.g:
455 /// ../aa.
456 /// Returns 0 in case path does not exist.
457 /// If printError is true, use Error with 'funcname' to issue an error message.
458 
459 TDirectory *TDirectoryFile::GetDirectory(const char *apath,
460  Bool_t printError, const char *funcname)
461 {
462  Int_t nch = 0;
463  if (apath) nch = strlen(apath);
464  if (!nch) {
465  return this;
466  }
467 
468  if (funcname==0 || strlen(funcname)==0) funcname = "GetDirectory";
469 
470  TDirectory *result = this;
471 
472  char *path = new char[nch+1]; path[0] = 0;
473  if (nch) strlcpy(path,apath,nch+1);
474  char *s = (char*)strchr(path, ':');
475  if (s) {
476  *s = '\0';
478  TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
479  // Check if this is a duplicate (2nd opening) on this file and prefer
480  // this file.
481  if (GetFile()) {
482  auto url = GetFile()->GetEndpointUrl();
483  if (f && 0 == url->Compare(f->GetFile()->GetEndpointUrl())) {
484  result = GetDirectory(s+1,printError,funcname);
485  delete [] path;
486  return result;
487  }
488  }
489  if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
490  if (s) *s = ':';
491  if (f) {
492  result = f;
493  if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
494  delete [] path; return result;
495  } else {
496  if (printError) Error(funcname, "No such file %s", path);
497  delete [] path; return nullptr;
498  }
499  }
500 
501  // path starts with a slash (assumes current file)
502  if (path[0] == '/') {
503  TDirectory *td = fFile;
504  if (!fFile) td = gROOT;
505  result = td->GetDirectory(path+1,printError,funcname);
506  delete [] path; return result;
507  }
508 
509  TDirectoryFile *obj;
510  char *slash = (char*)strchr(path,'/');
511  if (!slash) { // we are at the lowest level
512  if (!strcmp(path, "..")) {
513  result = GetMotherDir();
514  delete [] path; return result;
515  }
516  GetObject(path,obj);
517  if (!obj) {
518  if (printError) Error(funcname,"Unknown directory %s", path);
519  delete [] path; return nullptr;
520  }
521 
522  delete [] path; return obj;
523  }
524 
525  TString subdir(path);
526  slash = (char*)strchr(subdir.Data(),'/');
527  *slash = 0;
528  //Get object with path from current directory/file
529  if (!strcmp(subdir, "..")) {
530  TDirectory* mom = GetMotherDir();
531  if (mom)
532  result = mom->GetDirectory(slash+1,printError,funcname);
533  delete [] path; return result;
534  }
535  GetObject(subdir,obj);
536  if (!obj) {
537  if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
538  delete [] path; return nullptr;
539  }
540 
541  result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
542  delete [] path; return result;
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// Delete all objects from memory and directory structure itself.
547 
548 void TDirectoryFile::Close(Option_t *option)
549 {
550  if (!fList || !fSeekDir) {
551  return;
552  }
553 
554  // Save the directory key list and header
555  Save();
556 
557  Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
558 
559  if (!nodelete) {
560  Bool_t fast = kTRUE;
561  TObjLink *lnk = fList->FirstLink();
562  while (lnk) {
563  if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;}
564  lnk = lnk->Next();
565  }
566  // Delete objects from directory list, this in turn, recursively closes all
567  // sub-directories (that were allocated on the heap)
568  // if this dir contains subdirs, we must use the slow option for Delete!
569  // we must avoid "slow" as much as possible, in particular Delete("slow")
570  // with a large number of objects (eg >10^5) would take for ever.
571  {
572  if (fast) fList->Delete();
573  else fList->Delete("slow");
574  }
575  }
576 
577  // Delete keys from key list (but don't delete the list header)
578  if (fKeys) {
579  fKeys->Delete("slow");
580  }
581 
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Delete Objects or/and keys in a directory
587 ///
588 /// Properties of the namecycle string:
589 /// - namecycle has the format name;cycle
590 /// - namecycle = "" is same as namecycle ="T*"
591 /// - name = * means all
592 /// - cycle = * means all cycles (memory and keys)
593 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
594 /// When name=* use T* to delete subdirectories also
595 ///
596 /// To delete one directory, you must specify the directory cycle,
597 /// eg. file.Delete("dir1;1");
598 ///
599 /// Examples:
600 /// | Pattern | Description |
601 /// |---------|-------------|
602 /// | foo | delete object named foo in memory |
603 /// | foo* | delete all objects with a name starting with foo |
604 /// | foo;1 | delete cycle 1 of foo on file |
605 /// | foo;* | delete all cycles of foo on file and also from memory |
606 /// | *;2 | delete all objects on file having the cycle 2 |
607 /// | *;* | delete all objects from memory and file |
608 /// | T*;* | delete all objects from memory and file and all subdirectories |
609 ///
610 /// ## WARNING
611 /// If the key to be deleted contains special characters ("+","^","?", etc
612 /// that have a special meaning for the regular expression parser (see TRegexp)
613 /// then you must specify 2 backslash characters to escape the regular expression.
614 /// For example, if the key to be deleted is namecycle = "C++", you must call
615 ///
616 /// mydir.Delete("C\\+\\+"));
617 ///
618 
619 void TDirectoryFile::Delete(const char *namecycle)
620 {
621  if (gDebug)
622  Info("Delete","Call for this = %s namecycle = %s",
623  GetName(), (namecycle ? namecycle : "null"));
624 
625  TDirectory::TContext ctxt(this);
626  Short_t cycle;
627  char name[kMaxLen];
628  const char *nmcy = (namecycle) ? namecycle : "";
629  DecodeNameCycle(nmcy, name, cycle, kMaxLen);
630 
631  Int_t deleteall = 0;
632  Int_t deletetree = 0;
633  if(strcmp(name,"*") == 0) deleteall = 1;
634  if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
635  if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
636  if(namecycle==0 || !namecycle[0]){ deleteall = 1; deletetree = 1;}
637  TRegexp re(name,kTRUE);
638  TString s;
639  Int_t deleteOK = 0;
640 
641 //*-*---------------------Case of Object in memory---------------------
642 // ========================
643  if (cycle >= 9999 ) {
644  TNamed *idcur;
645  TIter next(fList);
646  while ((idcur = (TNamed *) next())) {
647  deleteOK = 0;
648  s = idcur->GetName();
649  if (deleteall || s.Index(re) != kNPOS) {
650  deleteOK = 1;
651  if (idcur->IsA() == TDirectoryFile::Class()) {
652  deleteOK = 2;
653  if (!deletetree && deleteall) deleteOK = 0;
654  }
655  }
656  if (deleteOK != 0) {
657  fList->Remove(idcur);
658  if (deleteOK==2) {
659  // read subdirectories to correctly delete them
660  if (deletetree)
661  ((TDirectory*) idcur)->ReadAll("dirs");
662  idcur->Delete(deletetree ? "T*;*" : "*");
663  delete idcur;
664  } else
665  idcur->Delete(name);
666  }
667  }
668 // if (deleteOK == 2) {
669 // Info("Delete","Dir:%lx %s", fList->FindObject(name), name);
670 // delete fList->FindObject(name); //deleting a TDirectory
671 // }
672  }
673 //*-*---------------------Case of Key---------------------
674 // ===========
675  if (cycle != 9999 ) {
676  if (IsWritable()) {
677  TKey *key;
678  TIter nextkey(GetListOfKeys());
679  while ((key = (TKey *) nextkey())) {
680  deleteOK = 0;
681  s = key->GetName();
682  if (deleteall || s.Index(re) != kNPOS) {
683  if (cycle == key->GetCycle()) deleteOK = 1;
684  if (cycle > 9999) deleteOK = 1;
685  //if (!strcmp(key->GetClassName(),"TDirectory")) {
686  if (strstr(key->GetClassName(),"TDirectory")) {
687  deleteOK = 2;
688  if (!deletetree && deleteall) deleteOK = 0;
689  if (cycle == key->GetCycle()) deleteOK = 2;
690  }
691  }
692  if (deleteOK) {
693  if (deleteOK==2) {
694  // read directory with subdirectories to correctly delete and free key structure
695  TDirectory* dir = GetDirectory(key->GetName(), kTRUE, "Delete");
696  if (dir!=0) {
697  dir->Delete("T*;*");
698  fList->Remove(dir);
699  delete dir;
700  }
701  }
702 
703  key->Delete();
704  fKeys->Remove(key);
705  fModified = kTRUE;
706  delete key;
707  }
708  }
709  TFile* f = GetFile();
710  if (fModified && (f!=0)) {
711  WriteKeys(); //*-* Write new keys structure
712  WriteDirHeader(); //*-* Write new directory header
713  f->WriteFree(); //*-* Write new free segments list
714  f->WriteHeader(); //*-* Write new file header
715  }
716  }
717  }
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Encode directory header into output buffer
722 
723 void TDirectoryFile::FillBuffer(char *&buffer)
724 {
725  Version_t version = TDirectoryFile::Class_Version();
729  {
730  // One of the address is larger than 2GB we need to use longer onfile
731  // integer, thus we increase the version number.
732  // Note that fSeekDir and fSeekKey are not necessarily correlated, if
733  // some object are 'removed' from the file and the holes are reused.
734  version += 1000;
735  }
736  tobuf(buffer, version);
737  const bool reproducible = TestBit(TFile::kReproducible) || (fFile && fFile->TestBit(TFile::kReproducible));
738  if (reproducible) {
739  TDatime((UInt_t) 1).FillBuffer(buffer);
740  TDatime((UInt_t) 1).FillBuffer(buffer);
741  } else {
742  fDatimeC.FillBuffer(buffer);
743  fDatimeM.FillBuffer(buffer);
744  }
745  tobuf(buffer, fNbytesKeys);
746  tobuf(buffer, fNbytesName);
747  if (version > 1000) {
748  tobuf(buffer, fSeekDir);
749  tobuf(buffer, fSeekParent);
750  tobuf(buffer, fSeekKeys);
751  } else {
752  tobuf(buffer, (Int_t)fSeekDir);
753  tobuf(buffer, (Int_t)fSeekParent);
754  tobuf(buffer, (Int_t)fSeekKeys);
755  }
756  if (reproducible)
757  TUUID("00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
758  else
759  fUUID.FillBuffer(buffer);
760  if (fFile && fFile->GetVersion() < 40000) return;
761  if (version <=1000) for (Int_t i=0;i<3;i++) tobuf(buffer,Int_t(0));
762 }
763 
764 ////////////////////////////////////////////////////////////////////////////////
765 /// Find key with name keyname in the current directory
766 
767 TKey *TDirectoryFile::FindKey(const char *keyname) const
768 {
769  Short_t cycle;
770  char name[kMaxLen];
771 
772  DecodeNameCycle(keyname, name, cycle, kMaxLen);
773  return GetKey(name,cycle);
774 }
775 
776 ////////////////////////////////////////////////////////////////////////////////
777 /// Find key with name keyname in the current directory or
778 /// its subdirectories.
779 ///
780 /// NOTE: that If a key is found, the directory containing the key becomes
781 /// the current directory
782 
783 TKey *TDirectoryFile::FindKeyAny(const char *keyname) const
784 {
785  TDirectory *dirsav = gDirectory;
786  Short_t cycle;
787  char name[kMaxLen];
788 
789  DecodeNameCycle(keyname, name, cycle, kMaxLen);
790 
791  TIter next(GetListOfKeys());
792  TKey *key;
793  while ((key = (TKey *) next())) {
794  if (!strcmp(name, key->GetName()))
795  if ((cycle == 9999) || (cycle >= key->GetCycle())) {
796  const_cast<TDirectoryFile*>(this)->cd(); // may be we should not make cd ???
797  return key;
798  }
799  }
800  //try with subdirectories
801  next.Reset();
802  while ((key = (TKey *) next())) {
803  //if (!strcmp(key->GetClassName(),"TDirectory")) {
804  if (strstr(key->GetClassName(),"TDirectory")) {
805  TDirectory* subdir =
806  const_cast<TDirectoryFile*>(this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
807  TKey *k = subdir ? subdir->FindKeyAny(keyname) : nullptr;
808  if (k) return k;
809  }
810  }
811  if (dirsav) dirsav->cd();
812  return nullptr;
813 }
814 
815 ////////////////////////////////////////////////////////////////////////////////
816 /// Find object by name in the list of memory objects of the current
817 /// directory or its sub-directories.
818 ///
819 /// After this call the current directory is not changed.
820 /// To automatically set the current directory where the object is found,
821 /// use FindKeyAny(aname)->ReadObj().
822 
823 TObject *TDirectoryFile::FindObjectAny(const char *aname) const
824 {
825  //object may be already in the list of objects in memory
826  TObject *obj = TDirectory::FindObjectAny(aname);
827  if (obj) return obj;
828 
829  TDirectory *dirsav = gDirectory;
830  Short_t cycle;
831  char name[kMaxLen];
832 
833  DecodeNameCycle(aname, name, cycle, kMaxLen);
834 
835  TIter next(GetListOfKeys());
836  TKey *key;
837  //may be a key in the current directory
838  while ((key = (TKey *) next())) {
839  if (!strcmp(name, key->GetName())) {
840  if (cycle == 9999) return key->ReadObj();
841  if (cycle >= key->GetCycle()) return key->ReadObj();
842  }
843  }
844  //try with subdirectories
845  next.Reset();
846  while ((key = (TKey *) next())) {
847  //if (!strcmp(key->GetClassName(),"TDirectory")) {
848  if (strstr(key->GetClassName(),"TDirectory")) {
849  TDirectory* subdir =
850  ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
851  TKey *k = subdir ? subdir->FindKeyAny(aname) : nullptr;
852  if (k) { if (dirsav) dirsav->cd(); return k->ReadObj();}
853  }
854  }
855  if (dirsav) dirsav->cd();
856  return nullptr;
857 }
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 /// Return pointer to object identified by namecycle.
861 ///
862 /// Properties:
863 /// - namecycle has the format name;cycle
864 /// - name = * is illegal, cycle = * is illegal
865 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
866 ///
867 /// Examples:
868 /// | %Pattern | Explanation |
869 /// |----------|-------------|
870 /// | foo | get object named foo in memory if object is not in memory, try with highest cycle from file |
871 /// | foo;1 | get cycle 1 of foo on file |
872 ///
873 /// The retrieved object should in principle derive from TObject.
874 /// If not, the function TDirectoryFile::Get<T> should be called.
875 /// However, this function will still work for a non-TObject, provided that
876 /// the calling application cast the return type to the correct type (which
877 /// is the actual type of the object).
878 ///
879 /// ### The Get<T> Method
880 /// The method Get<T> offers better protection and avoids the need for any
881 /// cast:
882 /// ~~~{.cpp}
883 /// auto objPtr = directory->Get<MyClass>("some object");
884 /// if (objPtr) { ... the object exist and inherits from MyClass ... }
885 /// ~~~
886 ///
887 /// ### Very important note about inheritance
888 /// In case the class of this object derives from TObject but not
889 /// as a first inheritance, one must use dynamic_cast<>().
890 ///
891 /// #### Example 1 - Normal case:
892 ///
893 /// class MyClass : public TObject, public AnotherClass
894 ///
895 /// then on return, one can adopt a C style cast:
896 ///
897 /// auto objPtr = (MyClass*)directory->Get("some object of MyClass");
898 ///
899 /// #### Example 2 - Special case:
900 ///
901 /// class MyClass : public AnotherClass, public TObject
902 ///
903 /// then on return, one must do:
904 ///
905 /// auto objPtr = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
906 ///
907 /// Of course, dynamic_cast<> can also be used in the example 1.
908 ///
909 
910 TObject *TDirectoryFile::Get(const char *namecycle)
911 {
912  Short_t cycle;
913  char name[kMaxLen];
914 
915  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
916  Int_t nch = strlen(name);
917  for (Int_t i = nch-1; i > 0; i--) {
918  if (name[i] == '/') {
919  name[i] = 0;
920  TDirectory* dirToSearch=GetDirectory(name);
921  const char *subnamecycle = namecycle + i + 1;
922  name[i] = '/';
923  return dirToSearch?dirToSearch->Get(subnamecycle):0;
924  }
925  }
926  const char *namobj = name;
927 
928 //*-*---------------------Case of Object in memory---------------------
929 // ========================
930  TObject *idcur = fList ? fList->FindObject(namobj) : nullptr;
931  if (idcur) {
932  if (idcur==this && strlen(namobj)!=0) {
933  // The object has the same name has the directory and
934  // that's what we picked-up! We just need to ignore
935  // it ...
936  idcur = nullptr;
937  } else if (cycle == 9999) {
938  return idcur;
939  } else {
940  if (idcur->InheritsFrom(TCollection::Class()))
941  idcur->Delete(); // delete also list elements
942  delete idcur;
943  idcur = nullptr;
944  }
945  }
946 
947 //*-*---------------------Case of Key---------------------
948 // ===========
949  TKey *key;
950  TIter nextkey(GetListOfKeys());
951  while ((key = (TKey *) nextkey())) {
952  if (strcmp(namobj,key->GetName()) == 0) {
953  if ((cycle == 9999) || (cycle == key->GetCycle())) {
954  TDirectory::TContext ctxt(this);
955  idcur = key->ReadObj();
956  break;
957  }
958  }
959  }
960 
961  return idcur;
962 }
963 
964 ////////////////////////////////////////////////////////////////////////////////
965 /// Return pointer to object identified by namecycle.
966 ///
967 /// The returned object may or may not derive from TObject.
968 ///
969 /// - namecycle has the format name;cycle
970 /// - name = * is illegal, cycle = * is illegal
971 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
972 ///
973 /// ## Very important note
974 /// The calling application must cast the returned object to
975 /// the final type, e.g.
976 ///
977 /// auto objPtr = (MyClass*)directory->GetObject("some object of MyClass");
978 
979 void *TDirectoryFile::GetObjectUnchecked(const char *namecycle)
980 {
981  return GetObjectChecked(namecycle,(TClass*)nullptr);
982 }
983 
984 ////////////////////////////////////////////////////////////////////////////////
985 /// See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl)
986 
987 void *TDirectoryFile::GetObjectChecked(const char *namecycle, const char* classname)
988 {
989  return GetObjectChecked(namecycle,TClass::GetClass(classname));
990 }
991 
992 
993 ////////////////////////////////////////////////////////////////////////////////
994 /// Return pointer to object identified by namecycle if and only if the actual
995 /// object is a type suitable to be stored as a pointer to a "expectedClass"
996 /// If expectedClass is null, no check is performed.
997 ///
998 /// - namecycle has the format name;cycle
999 /// - name = * is illegal, cycle = * is illegal
1000 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
1001 ///
1002 /// ### Very important note
1003 /// The calling application must cast the returned pointer to
1004 /// the type described by the 2 arguments (i.e. cl):
1005 ///
1006 /// auto objPtr = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
1007 ///
1008 /// Note: We recommend using the method TDirectoryFile::Get<T>:
1009 /// ~~~{.cpp}
1010 /// auto objPtr = directory->Get<MyClass>("some object inheriting from MyClass");
1011 /// if (objPtr) { ... we found what we are looking for ... }
1012 /// ~~~
1014 void *TDirectoryFile::GetObjectChecked(const char *namecycle, const TClass* expectedClass)
1015 {
1016 
1017  // If the name is invalid, issue an error message and return a nullptr
1018  if (!namecycle || '\0' == namecycle[0]) {
1019  Error("GetObjectChecked", "The provided key name is invalid.");
1020  return nullptr;
1021  }
1022 
1023  Short_t cycle;
1024  char name[kMaxLen];
1025 
1026  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
1027  Int_t nch = strlen(name);
1028  for (Int_t i = nch-1; i > 0; i--) {
1029  if (name[i] == '/') {
1030  name[i] = 0;
1031  TDirectory* dirToSearch=GetDirectory(name);
1032  const char *subnamecycle = namecycle + i + 1;
1033  name[i] = '/';
1034  if (dirToSearch) {
1035  return dirToSearch->GetObjectChecked(subnamecycle, expectedClass);
1036  } else {
1037  return nullptr;
1038  }
1039  }
1040  }
1041  const char *namobj = name;
1042 
1043 //*-*---------------------Case of Object in memory---------------------
1044 // ========================
1045  if (expectedClass==0 || expectedClass->IsTObject()) {
1046  TObject *objcur = fList ? fList->FindObject(namobj) : nullptr;
1047  if (objcur) {
1048  if (objcur==this && strlen(namobj)!=0) {
1049  // The object has the same name has the directory and
1050  // that's what we picked-up! We just need to ignore
1051  // it ...
1052  objcur = nullptr;
1053  } else if (cycle == 9999) {
1054  // Check type
1055  if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return nullptr;
1056  else return objcur;
1057  } else {
1058  if (objcur->InheritsFrom(TCollection::Class()))
1059  objcur->Delete(); // delete also list elements
1060  delete objcur;
1061  objcur = nullptr;
1062  }
1063  }
1064  }
1065 
1066 //*-*---------------------Case of Key---------------------
1067 // ===========
1068  void *idcur = nullptr;
1069  TKey *key;
1070  TIter nextkey(GetListOfKeys());
1071  while ((key = (TKey *) nextkey())) {
1072  if (strcmp(namobj,key->GetName()) == 0) {
1073  if ((cycle == 9999) || (cycle == key->GetCycle())) {
1074  TDirectory::TContext ctxt(this);
1075  idcur = key->ReadObjectAny(expectedClass);
1076  break;
1077  }
1078  }
1079  }
1080 
1081  return idcur;
1082 }
1083 
1084 ////////////////////////////////////////////////////////////////////////////////
1085 /// Return the buffer size to create new TKeys.
1086 ///
1087 /// If the stored fBufferSize is null, the value returned is the average
1088 /// buffer size of objects in the file so far.
1091 {
1092  if (fBufferSize <= 0) return fFile->GetBestBuffer();
1093  else return fBufferSize;
1094 }
1095 
1096 
1097 ////////////////////////////////////////////////////////////////////////////////
1098 /// Return pointer to key with name,cycle
1099 ///
1100 /// if cycle = 9999 returns highest cycle
1102 TKey *TDirectoryFile::GetKey(const char *name, Short_t cycle) const
1103 {
1104  if (!fKeys) return nullptr;
1105 
1106  // TIter::TIter() already checks for null pointers
1107  TIter next( ((THashList *)(GetListOfKeys()))->GetListForObject(name) );
1108 
1109  TKey *key;
1110  while (( key = (TKey *)next() )) {
1111  if (!strcmp(name, key->GetName())) {
1112  if ((cycle == 9999) || (cycle >= key->GetCycle()))
1113  return key;
1114  }
1115  }
1116 
1117  return nullptr;
1118 }
1119 
1120 ////////////////////////////////////////////////////////////////////////////////
1121 /// List Directory contents
1122 ///
1123 /// Indentation is used to identify the directory tree
1124 /// Subdirectories are listed first, then objects in memory, then objects on the file
1125 ///
1126 /// The option can has the following format: <b>[-d |-m][<regexp>]</b>
1127 /// Options:
1128 /// - -d: only list objects in the file
1129 /// - -m: only list objects in memory
1130 /// The <regexp> will be used to match the name of the objects.
1131 /// By default memory and disk objects are listed.
1133 void TDirectoryFile::ls(Option_t *option) const
1134 {
1136  std::cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1138 
1139  TString opta = option;
1140  TString opt = opta.Strip(TString::kBoth);
1141  Bool_t memobj = kTRUE;
1142  Bool_t diskobj = kTRUE;
1143  TString reg = "*";
1144  if (opt.BeginsWith("-m")) {
1145  diskobj = kFALSE;
1146  if (opt.Length() > 2)
1147  reg = opt(2,opt.Length());
1148  } else if (opt.BeginsWith("-d")) {
1149  memobj = kFALSE;
1150  if (opt.Length() > 2)
1151  reg = opt(2,opt.Length());
1152  } else if (!opt.IsNull())
1153  reg = opt;
1154 
1155  TRegexp re(reg, kTRUE);
1156 
1157  if (memobj) {
1158  TObject *obj;
1159  TIter nextobj(fList);
1160  while ((obj = (TObject *) nextobj())) {
1161  TString s = obj->GetName();
1162  if (s.Index(re) == kNPOS) continue;
1163  obj->ls(option); //*-* Loop on all the objects in memory
1164  }
1165  }
1166 
1167  if (diskobj && fKeys) {
1168  //*-* Loop on all the keys
1169  TObjLink *lnk = fKeys->FirstLink();
1170  while (lnk) {
1171  TKey *key = (TKey*)lnk->GetObject();
1172  TString s = key->GetName();
1173  if (s.Index(re) == kNPOS) continue;
1174  bool first = (lnk->Prev() == nullptr) || (s != lnk->Prev()->GetObject()->GetName());
1175  bool hasbackup = (lnk->Next() != nullptr) && (s == lnk->Next()->GetObject()->GetName());
1176  if (first)
1177  if (hasbackup)
1178  key->ls(true);
1179  else
1180  key->ls();
1181  else
1182  key->ls(false);
1183  lnk = lnk->Next();
1184  }
1185  }
1187 }
1188 
1189 ////////////////////////////////////////////////////////////////////////////////
1190 /// Interface to TFile::Open
1192 TFile *TDirectoryFile::OpenFile(const char *name, Option_t *option,const char *ftitle, Int_t compress, Int_t netopt)
1193 {
1194  return TFile::Open(name,option,ftitle,compress,netopt);
1195 
1196 }
1197 
1198 ////////////////////////////////////////////////////////////////////////////////
1199 /// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1200 ///
1201 /// Returns 0 in case of error or if a sub-directory (hierarchy) with the requested
1202 /// name already exists.
1203 /// returnExistingDirectory returns a pointer to an already existing sub-directory instead of 0.
1204 /// Returns a pointer to the created sub-directory or to the top sub-directory of
1205 /// the hierarchy (in the above example, the returned TDirectory * always points
1206 /// to "a").
1208 TDirectory *TDirectoryFile::mkdir(const char *name, const char *title, Bool_t returnExistingDirectory)
1209 {
1210  if (!name || !title || !name[0]) return nullptr;
1211  if (!title[0]) title = name;
1212  if (GetKey(name)) {
1213  if (returnExistingDirectory)
1214  return (TDirectoryFile*) GetDirectory(name);
1215  else {
1216  Error("mkdir","An object with name %s exists already",name);
1217  return nullptr;
1218  }
1219  }
1220  TDirectoryFile *newdir = nullptr;
1221  if (const char *slash = strchr(name,'/')) {
1222  TString workname(name, Long_t(slash-name));
1223  TDirectoryFile *tmpdir = nullptr;
1224  GetObject(workname.Data(), tmpdir);
1225  if (!tmpdir) {
1226  tmpdir = (TDirectoryFile*)mkdir(workname.Data(),title);
1227  if (!tmpdir) return nullptr;
1228  }
1229  if (!newdir) newdir = tmpdir;
1230  tmpdir->mkdir(slash+1);
1231  return newdir;
1232  }
1233 
1234  TDirectory::TContext ctxt(this);
1235 
1236  newdir = new TDirectoryFile(name, title, "", this);
1237 
1238  return newdir;
1239 }
1240 
1241 ////////////////////////////////////////////////////////////////////////////////
1242 /// Purge lowest key cycles in a directory.
1243 ///
1244 /// By default, only the highest cycle of a key is kept. Keys for which
1245 /// the "KEEP" flag has been set are not removed. See TKey::Keep().
1246 /// NOTE: This does not reduce the size of a TFile--
1247 /// the space is simply freed up to be overwritten.
1250 {
1251  if (!IsWritable()) return;
1252 
1253  TDirectory::TContext ctxt(this);
1254 
1255  TKey *key;
1257 
1258  while ((key = (TKey*)prev())) { // reverse loop on keys
1259  TKey *keyprev = (TKey*)GetListOfKeys()->Before(key);
1260  if (!keyprev) break;
1261  if (key->GetKeep() == 0) {
1262  if (strcmp(key->GetName(), keyprev->GetName()) == 0) {
1263  key->Delete(); // Remove from the file.
1264  delete key; // Remove from memory.
1265  }
1266  }
1267  }
1268  TFile *f = GetFile();
1269  if (fModified && f) {
1270  WriteKeys(); // Write new keys structure
1271  WriteDirHeader(); // Write new directory header
1272  f->WriteFree(); // Write new free segments list
1273  f->WriteHeader(); // Write new file header
1274  }
1275 }
1276 
1277 ////////////////////////////////////////////////////////////////////////////////
1278 /// Read objects from a ROOT file directory into memory.
1279 ///
1280 /// If an object is already in memory, the memory copy is deleted
1281 /// and the object is again read from the file.
1282 /// If opt=="dirs", only subdirectories will be read
1283 /// If opt=="dirs*" complete directory tree will be read
1286 {
1287  TDirectory::TContext ctxt(this);
1288 
1289  TKey *key;
1290  TIter next(GetListOfKeys());
1291 
1292  Bool_t readdirs = ((opt!=0) && ((strcmp(opt,"dirs")==0) || (strcmp(opt,"dirs*")==0)));
1293 
1294  if (readdirs)
1295  while ((key = (TKey *) next())) {
1296 
1297  //if (strcmp(key->GetClassName(),"TDirectory")!=0) continue;
1298  if (strstr(key->GetClassName(),"TDirectory")==0) continue;
1299 
1300  TDirectory *dir = GetDirectory(key->GetName(), kTRUE, "ReadAll");
1301 
1302  if ((dir!=0) && (strcmp(opt,"dirs*")==0)) dir->ReadAll("dirs*");
1303  }
1304  else
1305  while ((key = (TKey *) next())) {
1306  TObject *thing = GetList()->FindObject(key->GetName());
1307  if (thing) { delete thing; }
1308  key->ReadObj();
1309  }
1310 }
1311 
1312 ////////////////////////////////////////////////////////////////////////////////
1313 /// Read the linked list of keys.
1314 ///
1315 /// Every directory has a linked list (fKeys). This linked list has been
1316 /// written on the file via WriteKeys as a single data record.
1317 ///
1318 /// It is interesting to call this function in the following situation.
1319 /// Assume another process1 is connecting this directory in Update mode
1320 /// - Process1 is adding/updating objects in this directory
1321 /// - You want to see the latest status from process1.
1322 /// Example Process1:
1323 /// ~~~{.cpp}
1324 /// obj1.Write();
1325 /// obj2.Write();
1326 /// gDirectory->SaveSelf();
1327 /// ~~~
1328 ///
1329 /// Example Process2:
1330 /// ~~~{.cpp}
1331 /// gDirectory->ReadKeys();
1332 /// obj1->Draw();
1333 /// ~~~
1334 /// This is an efficient way (without opening/closing files) to view
1335 /// the latest updates of a file being modified by another process
1336 /// as it is typically the case in a data acquisition system.
1339 {
1340  if (!fFile || !fKeys) return 0;
1341 
1342  if (!fFile->IsBinary())
1343  return fFile->DirReadKeys(this);
1344 
1345  TDirectory::TContext ctxt(this);
1346 
1347  char *buffer;
1348  if (forceRead) {
1349  fKeys->Delete();
1350  //In case directory was updated by another process, read new
1351  //position for the keys
1353  char *header = new char[nbytes];
1354  buffer = header;
1355  fFile->Seek(fSeekDir);
1356  if ( fFile->ReadBuffer(buffer,nbytes) ) {
1357  // ReadBuffer return kTRUE in case of failure.
1358  delete [] header;
1359  return 0;
1360  }
1361  buffer += fNbytesName;
1362  Version_t versiondir;
1363  frombuf(buffer,&versiondir);
1364  fDatimeC.ReadBuffer(buffer);
1365  fDatimeM.ReadBuffer(buffer);
1366  frombuf(buffer, &fNbytesKeys);
1367  frombuf(buffer, &fNbytesName);
1368  if (versiondir > 1000) {
1369  frombuf(buffer, &fSeekDir);
1370  frombuf(buffer, &fSeekParent);
1371  frombuf(buffer, &fSeekKeys);
1372  } else {
1373  Int_t sdir,sparent,skeys;
1374  frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
1375  frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
1376  frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
1377  }
1378  delete [] header;
1379  }
1380 
1381  Int_t nkeys = 0;
1382  Long64_t fsize = fFile->GetSize();
1383  if ( fSeekKeys > 0) {
1384  TKey *headerkey = new TKey(fSeekKeys, fNbytesKeys, this);
1385  headerkey->ReadFile();
1386  buffer = headerkey->GetBuffer();
1387  headerkey->ReadKeyBuffer(buffer);
1388 
1389  TKey *key;
1390  frombuf(buffer, &nkeys);
1391  for (Int_t i = 0; i < nkeys; i++) {
1392  key = new TKey(this);
1393  key->ReadKeyBuffer(buffer);
1394  if (key->GetSeekKey() < 64 || key->GetSeekKey() > fsize) {
1395  Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1396  fKeys->Remove(key);
1397  nkeys = i;
1398  break;
1399  }
1400  if (key->GetSeekPdir() < 64 || key->GetSeekPdir() > fsize) {
1401  Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1402  fKeys->Remove(key);
1403  nkeys = i;
1404  break;
1405  }
1406  fKeys->Add(key);
1407  }
1408  delete headerkey;
1409  }
1410 
1411  return nkeys;
1412 }
1413 
1414 
1415 ////////////////////////////////////////////////////////////////////////////////
1416 /// Read object with keyname from the current directory
1417 ///
1418 /// Read contents of object with specified name from the current directory.
1419 /// First the key with keyname is searched in the current directory,
1420 /// next the key buffer is deserialized into the object.
1421 /// The object must have been created before via the default constructor.
1422 /// See TObject::Write().
1424 Int_t TDirectoryFile::ReadTObject(TObject *obj, const char *keyname)
1425 {
1426  if (!fFile) { Error("Read","No file open"); return 0; }
1427  TKey *key = nullptr;
1428  TIter nextkey(GetListOfKeys());
1429  while ((key = (TKey *) nextkey())) {
1430  if (strcmp(keyname,key->GetName()) == 0) {
1431  return key->Read(obj);
1432  }
1433  }
1434  Error("Read","Key not found");
1435  return 0;
1436 }
1437 
1438 ////////////////////////////////////////////////////////////////////////////////
1439 /// Reset the TDirectory after its content has been merged into another
1440 /// Directory.
1441 ///
1442 /// This returns the TDirectoryFile object back to its state
1443 /// before any data has been written to the file.
1444 /// The object in the in-memory list are assumed to also have been reset.
1447 {
1448  // There is nothing to reset in the base class (TDirectory) since
1449  // we do want to key the list of in-memory object as is.
1450  fModified = kFALSE;
1451  // Does not change: fWritable
1452  fDatimeC.Set();
1453  fDatimeM.Set();
1454  fNbytesKeys = 0; // updated when the keys are written
1455  fNbytesName = 0; // updated by Init
1456  // Does not change (user customization): fBufferSize;
1457  fSeekDir = 0; // updated by Init
1458  fSeekParent = 0; // updated by Init
1459  fSeekKeys = 0; // updated by Init
1460  // Does not change: fFile
1461  TKey *key = fKeys ? (TKey*)fKeys->FindObject(fName) : nullptr;
1462  TClass *cl = IsA();
1463  if (key) {
1464  cl = TClass::GetClass(key->GetClassName());
1465  }
1466  // NOTE: We should check that the content is really mergeable and in
1467  // the in-mmeory list, before deleting the keys.
1468  if (fKeys) {
1469  fKeys->Delete("slow");
1470  }
1471 
1472  InitDirectoryFile(cl);
1473 
1474  // Do the same with the sub-directories.
1475  TIter next(GetList());
1476  TObject *idcur;
1477  while ((idcur = next())) {
1478  if (idcur->IsA() == TDirectoryFile::Class()) {
1479  ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
1480  }
1481  }
1482 
1483 }
1484 
1485 ////////////////////////////////////////////////////////////////////////////////
1486 /// Removes subdirectory from the directory
1487 ///
1488 /// When directory is deleted, all keys in all subdirectories will be
1489 /// read first and deleted from file (if exists)
1490 /// Equivalent call is Delete("name;*");
1492 void TDirectoryFile::rmdir(const char *name)
1493 {
1494  if (!name || (*name==0)) return;
1495 
1496  TString mask(name);
1497  mask += ";*";
1498  Delete(mask);
1499 }
1500 
1501 ////////////////////////////////////////////////////////////////////////////////
1502 /// Save recursively all directory keys and headers
1504 void TDirectoryFile::Save()
1505 {
1506  TDirectory::TContext ctxt(this);
1507 
1508  SaveSelf();
1509 
1510  // recursively save all sub-directories
1511  if (fList && fList->FirstLink()) {
1512  auto lnk = fList->FirstLink()->shared_from_this();
1513  while (lnk) {
1514  TObject *idcur = lnk->GetObject();
1515  if (idcur && idcur->InheritsFrom(TDirectoryFile::Class())) {
1516  TDirectoryFile *dir = (TDirectoryFile *)idcur;
1517  dir->Save();
1518  }
1519  lnk = lnk->NextSP();
1520  }
1521  }
1522 }
1523 
1524 ////////////////////////////////////////////////////////////////////////////////
1525 /// Save object in filename.
1526 ///
1527 /// If filename is 0 or "", a file with "objectname.root" is created.
1528 /// The name of the key is the object name.
1529 /// If the operation is successful, it returns the number of bytes written to the file
1530 /// otherwise it returns 0.
1531 /// By default a message is printed. Use option "q" to not print the message.
1532 /// If filename contains ".json" extension, JSON representation of the object
1533 /// will be created and saved in the text file. Such file can be used in
1534 /// JavaScript ROOT (https://root.cern.ch/js/) to display object in web browser
1535 /// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1537 Int_t TDirectoryFile::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) const
1538 {
1539  if (!obj) return 0;
1540  TDirectory *dirsav = gDirectory;
1541  TString fname = filename;
1542  if (!filename || !filename[0]) {
1543  fname.Form("%s.root",obj->GetName());
1544  }
1545  Int_t nbytes = 0;
1546  if (fname.Index(".json") > 0) {
1547  nbytes = TBufferJSON::ExportToFile(fname, obj, option);
1548  } else {
1549  TFile *local = TFile::Open(fname.Data(),"recreate");
1550  if (!local) return 0;
1551  nbytes = obj->Write();
1552  delete local;
1553  if (dirsav) dirsav->cd();
1554  }
1555  TString opt = option;
1556  opt.ToLower();
1557  if (!opt.Contains("q")) {
1558  if (!gSystem->AccessPathName(fname.Data())) obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1559  }
1560  return nbytes;
1561 }
1562 
1563 ////////////////////////////////////////////////////////////////////////////////
1564 /// Save Directory keys and header
1565 ///
1566 /// If the directory has been modified (fModified set), write the keys
1567 /// and the directory header. This function assumes the cd is correctly set.
1568 ///
1569 /// It is recommended to use this function in the following situation:
1570 /// Assume a process1 using a directory in Update mode
1571 /// - New objects or modified objects have been written to the directory.
1572 /// - You do not want to close the file.
1573 /// - You want your changes be visible from another process2 already connected
1574 /// to this directory in read mode.
1575 /// - Call this function.
1576 /// - In process2, use TDirectoryFile::ReadKeys to refresh the directory.
1578 void TDirectoryFile::SaveSelf(Bool_t force)
1579 {
1580  if (IsWritable() && (fModified || force) && fFile) {
1581  Bool_t dowrite = kTRUE;
1582  if (fFile->GetListOfFree())
1583  dowrite = fFile->GetListOfFree()->First() != nullptr;
1584  if (dowrite) {
1585  TDirectory *dirsav = gDirectory;
1586  if (dirsav != this) cd();
1587  WriteKeys(); //*-*- Write keys record
1588  WriteDirHeader(); //*-*- Update directory record
1589  if (dirsav && dirsav != this) dirsav->cd();
1590  }
1591  }
1592 }
1593 
1594 ////////////////////////////////////////////////////////////////////////////////
1595 /// Set the default buffer size when creating new TKeys.
1596 ///
1597 /// See also TDirectoryFile::GetBufferSize
1600 {
1601  fBufferSize = bufsize;
1602 }
1603 
1604 ////////////////////////////////////////////////////////////////////////////////
1605 /// Find the action to be executed in the dictionary of the parent class
1606 /// and store the corresponding exec number into fBits.
1607 ///
1608 /// This function searches a data member in the class of parent with an
1609 /// offset corresponding to this.
1610 /// If a comment "TEXEC:" is found in the comment field of the data member,
1611 /// the function stores the exec identifier of the exec statement
1612 /// following this keyword.
1614 void TDirectoryFile::SetTRefAction(TObject *ref, TObject *parent)
1615 {
1616  Int_t offset = (char*)ref - (char*)parent;
1617  TClass *cl = parent->IsA();
1618  cl->BuildRealData(parent);
1620  TIter next(info->GetElements());
1621  TStreamerElement *element;
1622  while((element = (TStreamerElement*)next())) {
1623  if (element->GetOffset() != offset) continue;
1624  Int_t execid = element->GetExecID();
1625  if (execid > 0) ref->SetBit(execid << 8);
1626  return;
1627  }
1628 }
1629 
1630 ////////////////////////////////////////////////////////////////////////////////
1631 /// Set the new value of fWritable recursively
1633 void TDirectoryFile::SetWritable(Bool_t writable)
1634 {
1635  TDirectory::TContext ctxt(this);
1636 
1637  fWritable = writable;
1638 
1639  // recursively set all sub-directories
1640  if (fList) {
1641  TObject *idcur;
1642  TIter next(fList);
1643  while ((idcur = next())) {
1644  if (idcur->InheritsFrom(TDirectoryFile::Class())) {
1645  TDirectoryFile *dir = (TDirectoryFile*)idcur;
1646  dir->SetWritable(writable);
1647  }
1648  }
1649  }
1650 }
1651 
1652 
1653 ////////////////////////////////////////////////////////////////////////////////
1654 /// Return the size in bytes of the directory header
1657 {
1658  Int_t nbytes = 22;
1659 
1660  nbytes += fDatimeC.Sizeof();
1661  nbytes += fDatimeM.Sizeof();
1662  nbytes += fUUID.Sizeof();
1663  //assume that the file may be above 2 Gbytes if file version is > 4
1664  if (fFile && fFile->GetVersion() >= 40000) nbytes += 12;
1665  return nbytes;
1666 }
1667 
1668 
1669 ////////////////////////////////////////////////////////////////////////////////
1670 /// Stream a class object
1671 
1672 void TDirectoryFile::Streamer(TBuffer &b)
1673 {
1674  Version_t v,version;
1675  if (b.IsReading()) {
1676  BuildDirectoryFile((TFile*)b.GetParent(), nullptr);
1677  if (fFile && fFile->IsWritable()) fWritable = kTRUE;
1678 
1679  if (fFile && !fFile->IsBinary()) {
1680  Version_t R__v = b.ReadVersion(0, 0);
1681 
1682  TClass* dirclass = (R__v < 5) ? TDirectory::Class() : TDirectoryFile::Class();
1683 
1684  b.ClassBegin(dirclass, R__v);
1685 
1686  TString sbuf;
1687 
1688  b.ClassMember("CreateTime","TString");
1689  sbuf.Streamer(b);
1690  TDatime timeC(sbuf.Data());
1691  fDatimeC = timeC;
1692 
1693  b.ClassMember("ModifyTime","TString");
1694  sbuf.Streamer(b);
1695  TDatime timeM(sbuf.Data());
1696  fDatimeM = timeM;
1697 
1698  b.ClassMember("UUID","TString");
1699  sbuf.Streamer(b);
1700  TUUID id(sbuf.Data());
1701  fUUID = id;
1702 
1703  b.ClassEnd(dirclass);
1704 
1705  fSeekKeys = 0; // read keys later in the TKeySQL class
1706  } else {
1707  b >> version;
1708  fDatimeC.Streamer(b);
1709  fDatimeM.Streamer(b);
1710  b >> fNbytesKeys;
1711  b >> fNbytesName;
1712  if (version > 1000) {
1713  SetBit(kIsBigFile);
1714  b >> fSeekDir;
1715  b >> fSeekParent;
1716  b >> fSeekKeys;
1717  } else {
1718  Int_t sdir,sparent,skeys;
1719  b >> sdir; fSeekDir = (Long64_t)sdir;
1720  b >> sparent; fSeekParent = (Long64_t)sparent;
1721  b >> skeys; fSeekKeys = (Long64_t)skeys;
1722  }
1723  v = version%1000;
1724  if (v == 2) {
1725  fUUID.StreamerV1(b);
1726  } else if (v > 2) {
1727  fUUID.Streamer(b);
1728  }
1729  }
1730  fList->UseRWLock();
1732  gROOT->GetUUIDs()->AddUUID(fUUID,this);
1733  if (fSeekKeys) ReadKeys();
1734  } else {
1735  if (fFile && !fFile->IsBinary()) {
1736  b.WriteVersion(TDirectoryFile::Class());
1737 
1738  TString sbuf;
1739 
1740  b.ClassBegin(TDirectoryFile::Class());
1741 
1742  b.ClassMember("CreateTime","TString");
1743  sbuf = fDatimeC.AsSQLString();
1744  sbuf.Streamer(b);
1745 
1746  b.ClassMember("ModifyTime","TString");
1747  fDatimeM.Set();
1748  sbuf = fDatimeM.AsSQLString();
1749  sbuf.Streamer(b);
1750 
1751  b.ClassMember("UUID","TString");
1752  sbuf = fUUID.AsString();
1753  sbuf.Streamer(b);
1754 
1755  b.ClassEnd(TDirectoryFile::Class());
1756  } else {
1757  version = TDirectoryFile::Class_Version();
1758  if (fFile && fFile->GetEND() > TFile::kStartBigFile) version += 1000;
1759  b << version;
1760  fDatimeC.Streamer(b);
1761  fDatimeM.Streamer(b);
1762  b << fNbytesKeys;
1763  b << fNbytesName;
1764  if (version > 1000) {
1765  b << fSeekDir;
1766  b << fSeekParent;
1767  b << fSeekKeys;
1768  } else {
1769  b << (Int_t)fSeekDir;
1770  b << (Int_t)fSeekParent;
1771  b << (Int_t)fSeekKeys;
1772  }
1773  fUUID.Streamer(b);
1774  if (version <=1000) for (Int_t i=0;i<3;i++) b << Int_t(0);
1775  }
1776  }
1777 }
1778 
1779 ////////////////////////////////////////////////////////////////////////////////
1780 /// Write all objects in memory to disk.
1781 ///
1782 /// Loop on all objects in memory (including subdirectories).
1783 /// A new key is created in the keys linked list for each object.
1784 /// For allowed options see TObject::Write().
1785 /// The directory header info is rewritten on the directory header record.
1787 Int_t TDirectoryFile::Write(const char *, Int_t opt, Int_t bufsize)
1788 {
1789  if (!IsWritable()) return 0;
1790  TDirectory::TContext ctxt(this);
1791 
1792  // Loop on all objects (including subdirs)
1793  TIter next(fList);
1794  TObject *obj;
1795  Int_t nbytes = 0;
1796  while ((obj=next())) {
1797  nbytes += obj->Write(0,opt,bufsize);
1798  }
1799  SaveSelf(kTRUE); // force save itself
1800 
1801  return nbytes;
1802 }
1803 
1804 ////////////////////////////////////////////////////////////////////////////////
1805 /// One can not save a const TDirectory object.
1807 Int_t TDirectoryFile::Write(const char *n, Int_t opt, Int_t bufsize) const
1808 {
1809  Error("Write const","A const TDirectory object should not be saved. We try to proceed anyway.");
1810  return const_cast<TDirectoryFile*>(this)->Write(n, opt, bufsize);
1811 }
1812 
1813 ////////////////////////////////////////////////////////////////////////////////
1814 /// Write object obj to this directory.
1815 ///
1816 /// The data structure corresponding to this object is serialized.
1817 /// The corresponding buffer is written to this directory
1818 /// with an associated key with name "name".
1819 ///
1820 /// Writing an object to a file involves the following steps:
1821 /// - Creation of a support TKey object in the directory. The TKey object
1822 /// creates a TBuffer object.
1823 /// - The TBuffer object is filled via the class::Streamer function.
1824 /// - If the file is compressed (default) a second buffer is created to hold
1825 /// the compressed buffer.
1826 /// - Reservation of the corresponding space in the file by looking in the
1827 /// TFree list of free blocks of the file.
1828 /// - The buffer is written to the file.
1829 ///
1830 /// By default, the buffersize will be taken from the average buffer size
1831 /// of all objects written to the current file so far.
1832 /// Use TDirectoryFile::SetBufferSize to force a given buffer size.
1833 ///
1834 /// If a name is specified, it will be the name of the key.
1835 /// If name is not given, the name of the key will be the name as returned
1836 /// by obj->GetName().
1837 ///
1838 /// The option can be a combination of:
1839 /// - "SingleKey"
1840 /// - "Overwrite"
1841 /// - "WriteDelete"
1842 /// Using the "Overwrite" option a previous key with the same name is
1843 /// overwritten. The previous key is deleted before writing the new object.
1844 /// Using the "WriteDelete" option a previous key with the same name is
1845 /// deleted only after the new object has been written. This option
1846 /// is safer than kOverwrite but it is slower.
1847 /// The "SingleKey" option is only used by TCollection::Write() to write
1848 /// a container with a single key instead of each object in the container
1849 /// with its own key.
1850 /// An object is read from this directory via TDirectoryFile::Get.
1851 /// The function returns the total number of bytes written to the directory.
1852 /// It returns 0 if the object cannot be written.
1853 ///
1854 /// WARNING: avoid special characters like '^','$','.' in the name as they
1855 /// are used by the regular expression parser (see TRegexp).
1857 Int_t TDirectoryFile::WriteTObject(const TObject *obj, const char *name, Option_t *option, Int_t bufsize)
1858 {
1859  TDirectory::TContext ctxt(this);
1860 
1861  if (fFile==0) {
1862  const char *objname = "no name specified";
1863  if (name) objname = name;
1864  else if (obj) objname = obj->GetName();
1865  Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1866  return 0;
1867  }
1868 
1869  if (!fFile->IsWritable()) {
1870  if (!fFile->TestBit(TFile::kWriteError)) {
1871  // Do not print the error if the file already had a SysError.
1872  Error("WriteTObject","Directory %s is not writable", fFile->GetName());
1873  }
1874  return 0;
1875  }
1876 
1877  if (!obj) return 0;
1878 
1879  TString opt = option;
1880  opt.ToLower();
1881 
1882  TKey *key=0, *oldkey=0;
1883  Int_t bsize = GetBufferSize();
1884  if (bufsize > 0) bsize = bufsize;
1885 
1886  const char *oname;
1887  if (name && *name)
1888  oname = name;
1889  else
1890  oname = obj->GetName();
1891 
1892  // Remove trailing blanks in object name
1893  Int_t nch = strlen(oname);
1894  char *newName = nullptr;
1895  if (nch && oname[nch-1] == ' ') {
1896  newName = new char[nch+1];
1897  strlcpy(newName,oname,nch+1);
1898  for (Int_t i=0;i<nch;i++) {
1899  if (newName[nch-i-1] != ' ') break;
1900  newName[nch-i-1] = 0;
1901  }
1902  oname = newName;
1903  }
1904 
1905  if (opt.Contains("overwrite")) {
1906  //One must use GetKey. FindObject would return the lowest cycle of the key!
1907  //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
1908  key = GetKey(oname);
1909  if (key) {
1910  key->Delete();
1911  delete key;
1912  }
1913  }
1914  if (opt.Contains("writedelete")) {
1915  oldkey = GetKey(oname);
1916  }
1917  key = fFile->CreateKey(this, obj, oname, bsize);
1918  if (newName) delete [] newName;
1919 
1920  if (!key->GetSeekKey()) {
1921  fKeys->Remove(key);
1922  delete key;
1923  if (bufsize) fFile->SetBufferSize(bufsize);
1924  return 0;
1925  }
1926  fFile->SumBuffer(key->GetObjlen());
1927  Int_t nbytes = key->WriteFile(0);
1929  if (bufsize) fFile->SetBufferSize(bufsize);
1930  return 0;
1931  }
1932  if (oldkey) {
1933  oldkey->Delete();
1934  delete oldkey;
1935  }
1936  if (bufsize) fFile->SetBufferSize(bufsize);
1937 
1938  return nbytes;
1939 }
1940 
1941 ////////////////////////////////////////////////////////////////////////////////
1942 /// Write object from pointer of class classname in this directory.
1943 ///
1944 /// obj may not derive from TObject. See TDirectoryFile::WriteTObject for comments
1945 ///
1946 /// ## Very important note
1947 /// The value passed as 'obj' needs to be from a pointer to the type described by classname.
1948 /// For example:
1949 /// ~~~{.cpp}
1950 /// TopClass *top;
1951 /// BottomClass *bottom;
1952 /// top = bottom;
1953 /// ~~~
1954 /// you can do:
1955 /// ~~~{.cpp}
1956 /// directory->WriteObjectAny(top,"top","name of object");
1957 /// directory->WriteObjectAny(bottom,"bottom","name of object");
1958 /// ~~~
1959 /// <b>BUT YOU CAN NOT DO</b> the following since it will fail with multiple inheritance:
1960 /// ~~~{.cpp}
1961 /// directory->WriteObjectAny(top,"bottom","name of object");
1962 /// ~~~
1963 /// We <b>STRONGLY</b> recommend to use
1964 /// ~~~{.cpp}
1965 /// TopClass *top = ....;
1966 /// directory->WriteObject(top,"name of object")
1967 /// ~~~
1968 /// See also remarks in TDirectoryFile::WriteTObject
1970 Int_t TDirectoryFile::WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option, Int_t bufsize)
1971 {
1972  TClass *cl = TClass::GetClass(classname);
1973  if (!cl) {
1974  TObject *info_obj = *(TObject**)obj;
1975  TVirtualStreamerInfo *info = dynamic_cast<TVirtualStreamerInfo*>(info_obj);
1976  if (!info) {
1977  Error("WriteObjectAny","Unknown class: %s",classname);
1978  return 0;
1979  } else {
1980  cl = info->GetClass();
1981  }
1982  }
1983  return WriteObjectAny(obj,cl,name,option,bufsize);
1984 }
1985 
1986 ////////////////////////////////////////////////////////////////////////////////
1987 /// Write object of class with dictionary cl in this directory.
1988 ///
1989 /// obj may not derive from TObject
1990 /// To get the TClass* cl pointer, one can use
1991 ///
1992 /// TClass *cl = TClass::GetClass("classname");
1993 ///
1994 /// An alternative is to call the function WriteObjectAny above.
1995 /// see TDirectoryFile::WriteTObject for comments
1997 Int_t TDirectoryFile::WriteObjectAny(const void *obj, const TClass *cl, const char *name, Option_t *option, Int_t bufsize)
1998 {
1999  TDirectory::TContext ctxt(this);
2000 
2001  if (!fFile) return 0;
2002 
2003  if (!cl) {
2004  Error("WriteObject","Unknown type for %s, it can not be written.",name);
2005  return 0;
2006  }
2007 
2008  if (!fFile->IsWritable()) {
2009  if (!fFile->TestBit(TFile::kWriteError)) {
2010  // Do not print the error if the file already had a SysError.
2011  Error("WriteObject","File %s is not writable", fFile->GetName());
2012  }
2013  return 0;
2014  }
2015 
2016  if (!obj) return 0;
2017 
2018  const char *className = cl->GetName();
2019  const char *oname;
2020  if (name && *name)
2021  oname = name;
2022  else
2023  oname = className;
2024 
2025  if (cl && cl->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(cl->GetCollectionProxy())) {
2026  Error("WriteObjectAny",
2027  "The class requested (%s) for the key name \"%s\""
2028  " is an instance of an stl collection and does not have a compiled CollectionProxy."
2029  " Please generate the dictionary for this collection (%s). No data will be written.",
2030  className, oname, className);
2031  return 0;
2032  }
2033 
2034  TKey *key, *oldkey = nullptr;
2035  Int_t bsize = GetBufferSize();
2036  if (bufsize > 0) bsize = bufsize;
2037 
2038  TString opt = option;
2039  opt.ToLower();
2040 
2041  // Remove trailing blanks in object name
2042  Int_t nch = strlen(oname);
2043  char *newName = nullptr;
2044  if (nch && oname[nch-1] == ' ') {
2045  newName = new char[nch+1];
2046  strlcpy(newName,oname,nch+1);
2047  for (Int_t i=0;i<nch;i++) {
2048  if (newName[nch-i-1] != ' ') break;
2049  newName[nch-i-1] = 0;
2050  }
2051  oname = newName;
2052  }
2053 
2054  if (opt.Contains("overwrite")) {
2055  //One must use GetKey. FindObject would return the lowest cycle of the key!
2056  //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
2057  key = GetKey(oname);
2058  if (key) {
2059  key->Delete();
2060  delete key;
2061  }
2062  }
2063  if (opt.Contains("writedelete")) {
2064  oldkey = GetKey(oname);
2065  }
2066  key = fFile->CreateKey(this, obj, cl, oname, bsize);
2067  if (newName) delete [] newName;
2068 
2069  if (!key->GetSeekKey()) {
2070  fKeys->Remove(key);
2071  delete key;
2072  return 0;
2073  }
2074  fFile->SumBuffer(key->GetObjlen());
2075  Int_t nbytes = key->WriteFile(0);
2076  if (fFile->TestBit(TFile::kWriteError)) return 0;
2077 
2078  if (oldkey) {
2079  oldkey->Delete();
2080  delete oldkey;
2081  }
2082 
2083  return nbytes;
2084 }
2085 
2086 ////////////////////////////////////////////////////////////////////////////////
2087 /// Overwrite the Directory header record.
2090 {
2091  TFile* f = GetFile();
2092  if (!f) return;
2093 
2094  if (!f->IsBinary()) {
2095  fDatimeM.Set();
2096  f->DirWriteHeader(this);
2097  return;
2098  }
2099 
2100  Int_t nbytes = TDirectoryFile::Sizeof(); //Warning ! TFile has a Sizeof()
2101  char *header = new char[nbytes];
2102  char *buffer = header;
2103  fDatimeM.Set();
2105  Long64_t pointer = fSeekDir + fNbytesName; // do not overwrite the name/title part
2106  fModified = kFALSE;
2107  f->Seek(pointer);
2108  f->WriteBuffer(header, nbytes);
2109  if (f->MustFlush()) f->Flush();
2110  delete [] header;
2111 }
2112 
2113 ////////////////////////////////////////////////////////////////////////////////
2114 /// Write Keys linked list on the file.
2115 ///
2116 /// The linked list of keys (fKeys) is written as a single data record
2119 {
2120  TFile* f = GetFile();
2121  if (!f) return;
2122 
2123  if (!f->IsBinary()) {
2124  f->DirWriteKeys(this);
2125  return;
2126  }
2127 
2128 //*-* Delete the old keys structure if it exists
2129  if (fSeekKeys != 0) {
2130  f->MakeFree(fSeekKeys, fSeekKeys + fNbytesKeys -1);
2131  }
2132 //*-* Write new keys record
2133  TIter next(fKeys);
2134  TKey *key;
2135  Int_t nkeys = fKeys->GetSize();
2136  Int_t nbytes = sizeof nkeys; //*-* Compute size of all keys
2137  if (f->GetEND() > TFile::kStartBigFile) nbytes += 8;
2138  while ((key = (TKey*)next())) {
2139  nbytes += key->Sizeof();
2140  }
2141  TKey *headerkey = new TKey(fName,fTitle,IsA(),nbytes,this);
2142  if (headerkey->GetSeekKey() == 0) {
2143  delete headerkey;
2144  return;
2145  }
2146  char *buffer = headerkey->GetBuffer();
2147  next.Reset();
2148  tobuf(buffer, nkeys);
2149  while ((key = (TKey*)next())) {
2150  key->FillBuffer(buffer);
2151  }
2152 
2153  fSeekKeys = headerkey->GetSeekKey();
2154  fNbytesKeys = headerkey->GetNbytes();
2155  headerkey->WriteFile();
2156  delete headerkey;
2157 }
TClass::GetStreamerInfo
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4504
TDirectoryFile::ReadKeys
Int_t ReadKeys(Bool_t forceRead=kTRUE) override
Read the linked list of keys.
Definition: TDirectoryFile.cxx:1337
TDirectory::ReadAll
virtual void ReadAll(Option_t *="")
Definition: TDirectory.h:191
n
const Int_t n
Definition: legend1.C:16
TDirectoryFile::GetObjectChecked
void * GetObjectChecked(const char *namecycle, const char *classname) override
See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl)
Definition: TDirectoryFile.cxx:986
TFileMergeInfo
Definition: TFileMergeInfo.h:42
TUUID::FillBuffer
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
Definition: TUUID.cxx:266
TKey::GetKeylen
Int_t GetKeylen() const
Definition: TKey.h:85
TMapFile
Definition: TMapFile.h:25
first
Definition: first.py:1
TClass::GetCollectionProxy
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2854
TBrowser
Definition: TBrowser.h:37
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TDirectory::Delete
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
Definition: TDirectory.cxx:652
TDirectory::GetList
virtual TList * GetList() const
Definition: TDirectory.h:167
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
TFree.h
Version_t
short Version_t
Definition: RtypesCore.h:65
TDirectoryFile::CleanTargets
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.)
Definition: TDirectoryFile.cxx:350
TDirectory::GetKey
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:166
TKey::ls
virtual void ls(Bool_t current) const
List Key contents.
Definition: TKey.cxx:694
f
#define f(i)
Definition: RSha256.hxx:122
TDirectory::GetMotherDir
TDirectory * GetMotherDir() const
Definition: TDirectory.h:170
kIsBigFile
const UInt_t kIsBigFile
Definition: TDirectoryFile.cxx:51
TROOT::DecreaseDirLevel
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2696
TVirtualStreamerInfo::GetClass
virtual TClass * GetClass() const =0
TStreamerInfo.h
TFile::Seek
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition: TFile.cxx:2138
TString::Strip
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
kNPOS
const Ssiz_t kNPOS
Definition: RtypesCore.h:115
TMapFile::Add
void Add(const TObject *obj, const char *name="")
Add an object to the list of objects to be stored in shared memory.
Definition: TMapFile.cxx:597
TKey::GetKeep
Short_t GetKeep() const
Returns the "KEEP" status.
Definition: TKey.cxx:593
TDirectory::DecodeNameCycle
static void DecodeNameCycle(const char *namecycle, char *name, Short_t &cycle, const size_t namesize=0)
Decode a namecycle "aap;2" into name "aap" and cycle "2".
Definition: TDirectory.cxx:1248
TFile::GetBestBuffer
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition: TFile.cxx:1100
TList::FindObject
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
TList::Delete
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
TDirectoryFile::Save
void Save() override
Save recursively all directory keys and headers.
Definition: TDirectoryFile.cxx:1503
TBufferIO::ResetMap
void ResetMap() override
Delete existing fMap and reset map counter.
Definition: TBufferIO.cxx:288
TString::Data
const char * Data() const
Definition: TString.h:369
TDirectory::GetObject
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition: TDirectory.h:157
TEmulatedCollectionProxy.h
TKey::ReadObjectAny
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition: TKey.cxx:1015
TDirectoryFile::GetKey
TKey * GetKey(const char *name, Short_t cycle=9999) const override
Return pointer to key with name,cycle.
Definition: TDirectoryFile.cxx:1101
TDirectoryFile::ResetAfterMerge
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset the TDirectory after its content has been merged into another Directory.
Definition: TDirectoryFile.cxx:1445
TDatime::ReadBuffer
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition: TDatime.cxx:278
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TDirectoryFile::SetTRefAction
void SetTRefAction(TObject *ref, TObject *parent) override
Find the action to be executed in the dictionary of the parent class and store the corresponding exec...
Definition: TDirectoryFile.cxx:1613
TKey::GetBuffer
virtual char * GetBuffer() const
Definition: TKey.h:79
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:54
TDirectoryFile::fDatimeM
TDatime fDatimeM
Date and time of last modification.
Definition: TDirectoryFile.h:38
tobuf
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:55
TStreamerElement.h
TDirectoryFile::Append
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
Definition: TDirectoryFile.cxx:209
TObject::Info
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:864
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:890
TFile::CreateKey
virtual TKey * CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t bufsize)
Creates key for object and converts data to buffer.
Definition: TFile.cxx:973
TDirectoryFile::Write
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write all objects in memory to disk.
Definition: TDirectoryFile.cxx:1786
TBufferJSON::ExportToFile
static Int_t ExportToFile(const char *filename, const TObject *obj, const char *option=nullptr)
Convert object into JSON and store in text file Returns size of the produce file Used in TObject::Sav...
Definition: TBufferJSON.cxx:753
gFile
#define gFile
Definition: TFile.h:343
TDirectoryFile::fNbytesName
Int_t fNbytesName
Number of bytes in TNamed at creation time.
Definition: TDirectoryFile.h:40
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:168
TFile::Open
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3946
TObject::Fatal
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:918
TDatime::Sizeof
Int_t Sizeof() const
Definition: TDatime.h:87
TKey::GetObjlen
Int_t GetObjlen() const
Definition: TKey.h:88
Int_t
int Int_t
Definition: RtypesCore.h:45
TDirectoryFile::cd
Bool_t cd(const char *path=nullptr) override
Change current directory to "this" directory.
Definition: TDirectoryFile.cxx:340
TBrowser.h
TNamed::fName
TString fName
Definition: TNamed.h:38
TString::Contains
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
SafeDelete
#define SafeDelete(p)
Definition: RConfig.hxx:543
Strlen.h
TDirectoryFile::fDatimeC
TDatime fDatimeC
Date and time when directory is created.
Definition: TDirectoryFile.h:37
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
TKey::WriteFile
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1450
TFile::IsBinary
Bool_t IsBinary() const
Definition: TFile.h:251
TDirectory::TContext
Definition: TDirectory.h:47
TClass.h
TBufferIO::MapObject
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
Definition: TBufferIO.cxx:163
TDirectoryFile::SaveSelf
void SaveSelf(Bool_t force=kFALSE) override
Save Directory keys and header.
Definition: TDirectoryFile.cxx:1577
TIter::Reset
void Reset()
Definition: TCollection.h:252
TDirectory::cd
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:498
TFile::GetVersion
Int_t GetVersion() const
Definition: TFile.h:237
TBuffer
Definition: TBuffer.h:43
TKey::FillBuffer
virtual void FillBuffer(char *&buffer)
Encode key header into output buffer.
Definition: TKey.cxx:601
TDirectoryFile::fFile
TFile * fFile
Pointer to current file in memory.
Definition: TDirectoryFile.h:45
TDirectoryFile::SetBufferSize
void SetBufferSize(Int_t bufsize) override
Set the default buffer size when creating new TKeys.
Definition: TDirectoryFile.cxx:1598
TDirectory::fUUID
TUUID fUUID
Definition: TDirectory.h:97
TKey::GetSeekPdir
virtual Long64_t GetSeekPdir() const
Definition: TKey.h:91
TFile::ReadBuffer
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition: TFile.cxx:1634
TString
Definition: TString.h:136
TDirectoryFile::OpenFile
TFile * OpenFile(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0) override
Interface to TFile::Open.
Definition: TDirectoryFile.cxx:1191
TSystem::AccessPathName
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1294
TKey::ReadFile
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition: TKey.cxx:1265
TDirectoryFile::Delete
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
Definition: TDirectoryFile.cxx:618
TFile::kWriteError
@ kWriteError
Definition: TFile.h:186
TBuffer::SetBufferOffset
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:93
TDirectoryFile::Sizeof
Int_t Sizeof() const override
Return the size in bytes of the directory header.
Definition: TDirectoryFile.cxx:1655
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
v
@ v
Definition: rootcling_impl.cxx:3635
b
#define b(i)
Definition: RSha256.hxx:118
TFile.h
TDirectory::Get
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:806
TVirtualStreamerInfo
Definition: TVirtualStreamerInfo.h:37
bool
kMaxLen
const Int_t kMaxLen
Definition: TDirectoryFile.cxx:52
TDirectoryFile::fModified
Bool_t fModified
True if directory has been modified.
Definition: TDirectoryFile.h:35
TDatime::Set
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:289
kIterBackward
const Bool_t kIterBackward
Definition: TCollection.h:41
TStreamerElement::GetOffset
Int_t GetOffset() const
Definition: TStreamerElement.h:120
id
XFontStruct * id
Definition: TGX11.cxx:109
ROOT::DirAutoAdd_t
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:113
TNamed::fTitle
TString fTitle
Definition: TNamed.h:39
TString::kBoth
@ kBoth
Definition: TString.h:267
TDirectory::FindKeyAny
virtual TKey * FindKeyAny(const char *) const
Definition: TDirectory.h:143
TROOT.h
TDirectoryFile::GetFile
TFile * GetFile() const override
Definition: TDirectoryFile.h:91
TKey::Sizeof
virtual Int_t Sizeof() const
Return the size in bytes of the key header structure.
Definition: TKey.cxx:1336
TFile::kReproducible
@ kReproducible
Definition: TFile.h:189
TDirectoryFile::GetObjectUnchecked
void * GetObjectUnchecked(const char *namecycle) override
Return pointer to object identified by namecycle.
Definition: TDirectoryFile.cxx:978
TObject::ls
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:494
TDirectoryFile::WriteTObject
Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *option="", Int_t bufsize=0) override
Write object obj to this directory.
Definition: TDirectoryFile.cxx:1856
TKey::SetMotherDir
void SetMotherDir(TDirectory *dir)
Definition: TKey.h:113
TList::First
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:658
TDirectoryFile::Close
void Close(Option_t *option="") override
Delete all objects from memory and directory structure itself.
Definition: TDirectoryFile.cxx:547
TObject::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:359
TRegexp.h
TString::Form
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
TDirectoryFile::GetListOfKeys
TList * GetListOfKeys() const override
Definition: TDirectoryFile.h:93
TDirectoryFile::~TDirectoryFile
virtual ~TDirectoryFile()
Destructor.
Definition: TDirectoryFile.cxx:177
TFile::SumBuffer
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition: TFile.cxx:2281
TDirectoryFile::Get
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
Definition: TDirectoryFile.cxx:909
TDirectoryFile::FindKeyAny
TKey * FindKeyAny(const char *keyname) const override
Find key with name keyname in the current directory or its subdirectories.
Definition: TDirectoryFile.cxx:782
TDirectoryFile::fKeys
TList * fKeys
Pointer to keys list in memory.
Definition: TDirectoryFile.h:46
Option_t
const typedef char Option_t
Definition: RtypesCore.h:66
TDirectory::Append
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:191
TCollection::UseRWLock
virtual bool UseRWLock()
Set this collection to use a RW lock upon access, making it thread safe.
Definition: TCollection.cxx:761
TDirectoryFile::Browse
void Browse(TBrowser *b) override
Browse the content of the directory.
Definition: TDirectoryFile.cxx:260
TBuffer::SetReadMode
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:302
TClassTable.h
TList::FirstLink
virtual TObjLink * FirstLink() const
Definition: TList.h:108
TDirectoryFile::CloneObject
TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE) override
Make a clone of an object using the Streamer facility.
Definition: TDirectoryFile.cxx:373
TDirectoryFile::fBufferSize
Int_t fBufferSize
Default buffer size to create new TKeys.
Definition: TDirectoryFile.h:41
TObject::ResetBit
void ResetBit(UInt_t f)
Definition: TObject.h:171
TDirectory::fList
TList * fList
Definition: TDirectory.h:96
slash
TCanvas * slash()
Definition: slash.C:1
TSystem.h
TKey::GetClassName
virtual const char * GetClassName() const
Definition: TKey.h:76
TStreamerInfo::GetElements
TObjArray * GetElements() const
Definition: TStreamerInfo.h:210
TStreamerInfo
Definition: TStreamerInfo.h:44
THashList
Definition: THashList.h:34
gROOTMutex
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:61
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TDatime::AsSQLString
const char * AsSQLString() const
Return the date & time in SQL compatible string format, like: 1997-01-15 20:16:28.
Definition: TDatime.cxx:152
TList::Before
virtual TObject * Before(const TObject *obj) const
Returns the object before object obj.
Definition: TList.cxx:370
TDirectoryFile::WriteObjectAny
Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0) override
Write object from pointer of class classname in this directory.
Definition: TDirectoryFile.cxx:1969
TEmulatedCollectionProxy
Definition: TEmulatedCollectionProxy.h:18
TDirectoryFile::AppendKey
Int_t AppendKey(TKey *key) override
Insert key in the linked list of keys of this directory.
Definition: TDirectoryFile.cxx:225
TNamed
Definition: TNamed.h:29
TList::AddBefore
virtual void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: TList.cxx:195
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TDirectory::AppendKey
virtual Int_t AppendKey(TKey *)
Definition: TDirectory.h:130
gDebug
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:119
Long_t
long Long_t
Definition: RtypesCore.h:54
TDirectoryFile::TDirectoryFile
TDirectoryFile()
Default TDirectoryFile constructor.
Definition: TDirectoryFile.cxx:60
TDirectory::GetObjectChecked
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
Definition: TDirectory.cxx:869
TKey::Delete
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:538
gDirectory
#define gDirectory
Definition: TDirectory.h:236
TFile::GetSize
virtual Long64_t GetSize() const
Returns the current file size.
Definition: TFile.cxx:1262
TDirectoryFile::SaveObjectAs
Int_t SaveObjectAs(const TObject *obj, const char *filename="", Option_t *option="") const override
Save object in filename.
Definition: TDirectoryFile.cxx:1536
TDirectoryFile.h
BIT
#define BIT(n)
Definition: Rtypes.h:85
R__LOCKGUARD
#define R__LOCKGUARD(mutex)
Definition: TVirtualMutex.h:104
TDirectory::GetDirectory
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
Definition: TDirectory.cxx:401
TFile::CurrentFile
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition: TFile.cxx:993
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
TString::BeginsWith
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
TClass::GetClass
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:2925
TDirectoryFile::Purge
void Purge(Short_t nkeep=1) override
Purge lowest key cycles in a directory.
Definition: TDirectoryFile.cxx:1248
TUUID
Definition: TUUID.h:42
Short_t
short Short_t
Definition: RtypesCore.h:39
TDirectoryFile::ReadTObject
Int_t ReadTObject(TObject *obj, const char *keyname) override
Read object with keyname from the current directory.
Definition: TDirectoryFile.cxx:1423
TDirectoryFile::fSeekKeys
Long64_t fSeekKeys
Location of Keys record on file.
Definition: TDirectoryFile.h:44
TDirectoryFile::IsWritable
Bool_t IsWritable() const override
Definition: TDirectoryFile.h:101
TBufferJSON.h
TDirectoryFile::FindKey
TKey * FindKey(const char *keyname) const override
Find key with name keyname in the current directory.
Definition: TDirectoryFile.cxx:766
TDirectory::fMother
TObject * fMother
Definition: TDirectory.h:95
TVirtualMutex.h
TClass::BuildRealData
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1980
TROOT::IncreaseDirLevel
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2792
TClass::IsTObject
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5752
TObject::kCanDelete
@ kCanDelete
if object in a list can be deleted
Definition: TObject.h:58
TFile
Definition: TFile.h:54
TROOT::IndentLevel
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2800
TMapFile.h
unsigned int
TUUID::Sizeof
Int_t Sizeof() const
Definition: TUUID.h:85
TDirectoryFile::ls
void ls(Option_t *option="") const override
List Directory contents.
Definition: TDirectoryFile.cxx:1132
TRegexp
Definition: TRegexp.h:31
TUUID::StreamerV1
void StreamerV1(TBuffer &b)
Stream UUID from input buffer.
Definition: TUUID.cxx:300
THashList.h
TString::Index
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TKey
Definition: TKey.h:28
TKey::GetSeekKey
virtual Long64_t GetSeekKey() const
Definition: TKey.h:90
TKey::ReadObj
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:750
TDirectoryFile::GetDirectory
TDirectory * GetDirectory(const char *apath, Bool_t printError=false, const char *funcname="GetDirectory") override
Find a directory named "apath".
Definition: TDirectoryFile.cxx:458
TDirectoryFile::fSeekParent
Long64_t fSeekParent
Location of parent directory on file.
Definition: TDirectoryFile.h:43
TDirectoryFile::FindObjectAny
TObject * FindObjectAny(const char *name) const override
Find object by name in the list of memory objects of the current directory or its sub-directories.
Definition: TDirectoryFile.cxx:822
TDirectoryFile::FindObjectAnyFile
TObject * FindObjectAnyFile(const char *name) const override
Scan the memory lists of all files for an object with name.
Definition: TDirectoryFile.cxx:431
TDatime::FillBuffer
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition: TDatime.cxx:229
TString::IsNull
Bool_t IsNull() const
Definition: TString.h:407
TObject::kIsReferenced
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
TList::Remove
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:821
TFile::DirReadKeys
virtual Int_t DirReadKeys(TDirectory *)
Definition: TFile.h:167
TCollection::GetSize
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
TInterpreter.h
TClass
Definition: TClass.h:80
TDirectoryFile::fWritable
Bool_t fWritable
True if directory is writable.
Definition: TDirectoryFile.h:36
frombuf
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:278
TDirectoryFile::FillBuffer
void FillBuffer(char *&buffer) override
Encode directory header into output buffer.
Definition: TDirectoryFile.cxx:722
TDirectoryFile::WriteDirHeader
void WriteDirHeader() override
Overwrite the Directory header record.
Definition: TDirectoryFile.cxx:2088
TObject::Write
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:795
TDirectoryFile::fNbytesKeys
Int_t fNbytesKeys
Number of bytes for the keys.
Definition: TDirectoryFile.h:39
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TObject
Definition: TObject.h:37
TBufferFile.h
TKey::GetCycle
Short_t GetCycle() const
Return cycle number associated to this key.
Definition: TKey.cxx:577
Bytes.h
TDirectoryFile::rmdir
void rmdir(const char *name) override
Removes subdirectory from the directory.
Definition: TDirectoryFile.cxx:1491
TDirectory::GetFile
virtual TFile * GetFile() const
Definition: TDirectory.h:165
name
char name[80]
Definition: TGX11.cxx:110
TObject::Delete
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:171
TDirectory
Definition: TDirectory.h:40
TUUID::AsString
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition: TUUID.cxx:562
TDirectoryFile::SetWritable
void SetWritable(Bool_t writable=kTRUE) override
Set the new value of fWritable recursively.
Definition: TDirectoryFile.cxx:1632
TIter
Definition: TCollection.h:233
TFile::GetEND
virtual Long64_t GetEND() const
Definition: TFile.h:223
TDirectory::CleanTargets
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
Definition: TDirectory.cxx:253
TDirectoryFile::GetBufferSize
Int_t GetBufferSize() const override
Return the buffer size to create new TKeys.
Definition: TDirectoryFile.cxx:1089
TDatime
Definition: TDatime.h:37
TDirectoryFile::fSeekDir
Long64_t fSeekDir
Location of directory on file.
Definition: TDirectoryFile.h:42
TFile::kStartBigFile
@ kStartBigFile
Definition: TFile.h:192
TDirectory::FindObjectAny
virtual TObject * FindObjectAny(const char *name) const
Find object by name in the list of memory objects of the current directory or its sub-directories.
Definition: TDirectory.cxx:736
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:53
TDirectoryFile::BuildDirectoryFile
void BuildDirectoryFile(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
Definition: TDirectoryFile.cxx:305
TFile::GetListOfFree
TList * GetListOfFree() const
Definition: TFile.h:229
TKey::Read
virtual Int_t Read(const char *name)
Read contents of object with specified name from the current directory.
Definition: TKey.h:54
TKey.h
Class
void Class()
Definition: Class.C:29
TString::ToLower
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
TDirectoryFile
Definition: TDirectoryFile.h:32
TObject::ClassName
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:130
TDirectoryFile::InitDirectoryFile
void InitDirectoryFile(TClass *cl=nullptr)
Initialize the key associated with this directory (and the related data members.
Definition: TDirectoryFile.cxx:147
TObject::IsFolder
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition: TObject.cxx:475
TBufferFile
Definition: TBufferFile.h:47
TStreamerElement
Definition: TStreamerElement.h:33
TKey::ReadKeyBuffer
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1222
TProcessUUID.h
TFile::GetEndpointUrl
virtual const TUrl * GetEndpointUrl() const
Definition: TFile.h:227
TDirectoryFile::WriteKeys
void WriteKeys() override
Write Keys linked list on the file.
Definition: TDirectoryFile.cxx:2117
TBuffer::kWrite
@ kWrite
Definition: TBuffer.h:73
TDirectoryFile::mkdir
TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE) override
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
Definition: TDirectoryFile.cxx:1207
gROOT
#define gROOT
Definition: TROOT.h:406
TStreamerElement::GetExecID
virtual Int_t GetExecID() const
Returns the TExec id for the EXEC instruction in the comment field of a TRef data member.
Definition: TStreamerElement.cxx:306
int
TError.h
TKey::GetNbytes
Int_t GetNbytes() const
Definition: TKey.h:87
TDirectoryFile::ReadAll
void ReadAll(Option_t *option="") override
Read objects from a ROOT file directory into memory.
Definition: TDirectoryFile.cxx:1284