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