Logo ROOT   6.12/07
Reference Guide
TDirectory.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id: 65b4f3646f4e5b2fa77218ba786b7fe4e16e27be $
2 // Author: Rene Brun 28/11/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 #include <stdlib.h>
12 
13 #include "Riostream.h"
14 #include "Strlen.h"
15 #include "TDirectory.h"
16 #include "TClassTable.h"
17 #include "TInterpreter.h"
18 #include "THashList.h"
19 #include "TBrowser.h"
20 #include "TROOT.h"
21 #include "TError.h"
22 #include "TClass.h"
23 #include "TRegexp.h"
24 #include "TSystem.h"
25 #include "TVirtualMutex.h"
26 #include "TThreadSlots.h"
27 #include "TMethod.h"
28 
29 #include "TSpinLockGuard.h"
30 
32 
33 const Int_t kMaxLen = 2048;
34 
35 /** \class TDirectory
36 \ingroup Base
37 
38 Describe directory structure in memory.
39 */
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Directory default constructor.
45 
46 TDirectory::TDirectory() : TNamed(), fMother(0),fList(0),fContext(0)
47 {
48  // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
49  std::atomic_flag_clear( &fSpinLock );
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Create a new Directory.
54 ///
55 /// A new directory with name,title is created in the current directory
56 /// The directory header information is immediately saved in the file
57 /// A new key is added in the parent directory
58 ///
59 /// When this constructor is called from a class directly derived
60 /// from TDirectory, the third argument classname MUST be specified.
61 /// In this case, classname must be the name of the derived class.
62 ///
63 /// Note that the directory name cannot contain slashes.
64 
65 TDirectory::TDirectory(const char *name, const char *title, Option_t * /*classname*/, TDirectory* initMotherDir)
66  : TNamed(name, title), fMother(0), fList(0),fContext(0)
67 {
68  // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
69  std::atomic_flag_clear( &fSpinLock );
70 
71  if (initMotherDir==0) initMotherDir = gDirectory;
72 
73  if (strchr(name,'/')) {
74  ::Error("TDirectory::TDirectory","directory name (%s) cannot contain a slash", name);
75  gDirectory = 0;
76  return;
77  }
78  if (strlen(GetName()) == 0) {
79  ::Error("TDirectory::TDirectory","directory name cannot be \"\"");
80  gDirectory = 0;
81  return;
82  }
83 
84  Build(initMotherDir ? initMotherDir->GetFile() : 0, initMotherDir);
85 }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Copy constructor.
89 
90 TDirectory::TDirectory(const TDirectory &directory) : TNamed(directory)
91 {
92  // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
93  std::atomic_flag_clear( &fSpinLock );
94 
95  directory.Copy(*this);
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// Destructor.
100 
102 {
103  if (!gROOT) {
104  delete fList;
105  return; //when called by TROOT destructor
106  }
107 
108  if (fList) {
109  if (!fList->IsUsingRWLock())
110  Fatal("~TDirectory","In %s:%p the fList (%p) is not using the RWLock\n",
111  GetName(),this,fList);
112  fList->Delete("slow");
113  SafeDelete(fList);
114  }
115 
116  CleanTargets();
117 
118  TDirectory* mom = GetMotherDir();
119 
120  if (mom) {
121  mom->Remove(this);
122  }
123 
124  if (gDebug) {
125  Info("~TDirectory", "dtor called for %s", GetName());
126  }
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 /// Destructor.
131 ///
132 /// Reset the current directory to its previous state.
133 
135 {
136  fActiveDestructor = true;
137  if (fDirectory) {
138  // UnregisterContext must not be virtual to allow
139  // this to work even with fDirectory set to nullptr.
140  (*fDirectory).UnregisterContext(this);
141  // While we were waiting for the lock, the TDirectory
142  // may have been deleted by another thread, so
143  // we need to recheck the value of fDirectory.
144  if (fDirectory)
145  (*fDirectory).cd();
146  else
147  CdNull();
148  } else {
149  CdNull();
150  }
151  fActiveDestructor = false;
152  while(fDirectoryWait);
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Sets the flag controlling the automatic add objects like histograms, TGraph2D, etc
157 /// in memory
158 ///
159 /// By default (fAddDirectory = kTRUE), these objects are automatically added
160 /// to the list of objects in memory.
161 /// Note that in the classes like TH1, TGraph2D supporting this facility,
162 /// one object can be removed from its support directory
163 /// by calling object->SetDirectory(0) or object->SetDirectory(dir) to add it
164 /// to the list of objects in the directory dir.
165 ///
166 /// NOTE that this is a static function. To call it, use:
167 /// ~~~ {.cpp}
168 /// TDirectory::AddDirectory
169 /// ~~~
170 
172 {
173  fgAddDirectory = add;
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Static function: see TDirectory::AddDirectory for more comments.
178 
180 {
181  return fgAddDirectory;
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Append object to this directory.
186 ///
187 /// If `replace` is true:
188 /// remove any existing objects with the same name (if the name is not "")
189 
190 void TDirectory::Append(TObject *obj, Bool_t replace /* = kFALSE */)
191 {
192  if (obj == 0 || fList == 0) return;
193 
194  if (replace && obj->GetName() && obj->GetName()[0]) {
195  TObject *old;
196  while (0!=(old = GetList()->FindObject(obj->GetName()))) {
197  Warning("Append","Replacing existing %s: %s (Potential memory leak).",
198  obj->IsA()->GetName(),obj->GetName());
199  ROOT::DirAutoAdd_t func = old->IsA()->GetDirectoryAutoAdd();
200  if (func) {
201  func(old,0);
202  } else {
203  Remove(old);
204  }
205  }
206  }
207 
208  fList->Add(obj);
209  obj->SetBit(kMustCleanup);
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Browse the content of the directory.
214 
216 {
217  if (b) {
218  TObject *obj = 0;
219  TIter nextin(fList);
220 
221  cd();
222 
223  //Add objects that are only in memory
224  while ((obj = nextin())) {
225  b->Add(obj, obj->GetName());
226  }
227  }
228 }
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Initialise directory to defaults.
232 ///
233 /// If directory is created via default ctor (when dir is read from file)
234 /// don't add it here to the directory since its name is not yet known.
235 /// It will be added to the directory in TKey::ReadObj().
236 
237 void TDirectory::Build(TFile* /*motherFile*/, TDirectory* motherDir)
238 {
239  fList = new THashList(100,50);
240  fList->UseRWLock();
241  fMother = motherDir;
243 
244  // Build is done and is the last part of the constructor (and is not
245  // being called from the derived classes) so we can publish.
246  if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Clean the pointers to this object (gDirectory, TContext, etc.).
251 
253 {
254  std::vector<TContext*> extraWait;
255 
256  {
258 
259  while (fContext) {
260  const auto next = fContext->fNext;
261  const auto ctxt = fContext;
262  ctxt->fDirectoryWait = true;
263 
264  ctxt->fDirectory = nullptr;
265 
266  if (ctxt->fActiveDestructor) {
267  extraWait.push_back(fContext);
268  } else {
269  ctxt->fDirectoryWait = false;
270  }
271  fContext = next;
272  }
273  }
274  for(auto &&context : extraWait) {
275  // Wait until the TContext is done spinning
276  // over the lock.
277  while(context->fActiveDestructor);
278  context->fDirectoryWait = false;
279  }
280 
281  if (gDirectory == this) {
282  TDirectory *cursav = GetMotherDir();
283  if (cursav && cursav != this) {
284  cursav->cd();
285  } else {
286  if (this == gROOT) {
287  gDirectory = 0;
288  } else {
289  gROOT->cd();
290  }
291  }
292  }
293 }
294 
295 ////////////////////////////////////////////////////////////////////////////////
296 /// Fast execution of 'new TBufferFile(TBuffer::kWrite,10000), without having
297 /// a compile time circular dependency ... alternatively we could (should?)
298 /// introduce yet another abstract interface.
299 
301 {
302  typedef void (*tcling_callfunc_Wrapper_t)(void*, int, void**, void*);
303  static tcling_callfunc_Wrapper_t creator = 0;
304  if (creator == 0) {
306  TClass *c = TClass::GetClass("TBufferFile");
307  TMethod *m = c->GetMethodWithPrototype("TBufferFile","TBuffer::EMode,Int_t",kFALSE,ROOT::kExactMatch);
308  creator = (tcling_callfunc_Wrapper_t)( m->InterfaceMethod() );
309  }
311  Int_t size = 10000;
312  void *args[] = { &mode, &size };
313  TBuffer *result;
314  creator(0,2,args,&result);
315  return result;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Clone an object.
320 /// This function is called when the directory is not a TDirectoryFile.
321 /// This version has to load the I/O package, hence via Cling.
322 ///
323 /// If autoadd is true and if the object class has a
324 /// DirectoryAutoAdd function, it will be called at the end of the
325 /// function with the parameter gDirector. This usually means that
326 /// the object will be appended to the current ROOT directory.
327 
328 TObject *TDirectory::CloneObject(const TObject *obj, Bool_t autoadd /* = kTRUE */)
329 {
330  // if no default ctor return immediately (error issued by New())
331  char *pobj = (char*)obj->IsA()->New();
332  if (!pobj) {
333  Fatal("CloneObject","Failed to create new object");
334  return 0;
335  }
336 
337  Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
338  if (baseOffset==-1) {
339  // cl does not inherit from TObject.
340  // Since this is not supported in this function, the only reason we could reach this code
341  // is because something is screwed up in the ROOT code.
342  Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
343  obj->IsA()->GetName());
344  }
345  TObject *newobj = (TObject*)(pobj+baseOffset);
346 
347  //create a buffer where the object will be streamed
348  //We are forced to go via the I/O package (ie TBufferFile).
349  //Invoking TBufferFile via CINT will automatically load the I/O library
350  TBuffer *buffer = R__CreateBuffer();
351  if (!buffer) {
352  Fatal("CloneObject","Not able to create a TBuffer!");
353  return 0;
354  }
355  buffer->MapObject(obj); //register obj in map to handle self reference
356  const_cast<TObject*>(obj)->Streamer(*buffer);
357 
358  // read new object from buffer
359  buffer->SetReadMode();
360  buffer->ResetMap();
361  buffer->SetBufferOffset(0);
362  buffer->MapObject(newobj); //register obj in map to handle self reference
363  newobj->Streamer(*buffer);
364  newobj->ResetBit(kIsReferenced);
365  newobj->ResetBit(kCanDelete);
366 
367  delete buffer;
368  if (autoadd) {
369  ROOT::DirAutoAdd_t func = obj->IsA()->GetDirectoryAutoAdd();
370  if (func) {
371  func(newobj,this);
372  }
373  }
374  return newobj;
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// Return the current directory for the current thread.
379 
381 {
382  static TDirectory *currentDirectory = 0;
383  if (!gThreadTsd)
384  return currentDirectory;
385  else
386  return *(TDirectory**)(*gThreadTsd)(&currentDirectory,ROOT::kDirectoryThreadSlot);
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Find a directory using apath.
391 /// It apath is null or empty, returns "this" directory.
392 /// Otherwise use apath to find a directory.
393 /// The absolute path syntax is: `file.root:/dir1/dir2`
394 ///
395 /// where file.root is the file and /dir1/dir2 the desired subdirectory
396 /// in the file. Relative syntax is relative to "this" directory. E.g: `../aa`.
397 /// Returns 0 in case path does not exist.
398 /// If printError is true, use Error with 'funcname' to issue an error message.
399 
401  Bool_t printError, const char *funcname)
402 {
403  Int_t nch = 0;
404  if (apath) nch = strlen(apath);
405  if (!nch) {
406  return this;
407  }
408 
409  if (funcname==0 || strlen(funcname)==0) funcname = "GetDirectory";
410 
411  TDirectory *result = this;
412 
413  char *path = new char[nch+1]; path[0] = 0;
414  if (nch) strlcpy(path,apath,nch+1);
415  char *s = (char*)strrchr(path, ':');
416  if (s) {
417  *s = '\0';
419  TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
420  if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
421  if (s) *s = ':';
422  if (f) {
423  result = f;
424  if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
425  delete [] path; return result;
426  } else {
427  if (printError) Error(funcname, "No such file %s", path);
428  delete [] path; return 0;
429  }
430  }
431 
432  // path starts with a slash (assumes current file)
433  if (path[0] == '/') {
434  TDirectory *td = gROOT;
435  result = td->GetDirectory(path+1,printError,funcname);
436  delete [] path; return result;
437  }
438 
439  TObject *obj;
440  char *slash = (char*)strchr(path,'/');
441  if (!slash) { // we are at the lowest level
442  if (!strcmp(path, "..")) {
443  result = GetMotherDir();
444  delete [] path; return result;
445  }
446  obj = Get(path);
447  if (!obj) {
448  if (printError) Error(funcname,"Unknown directory %s", path);
449  delete [] path; return 0;
450  }
451 
452  //Check return object is a directory
453  if (!obj->InheritsFrom(TDirectory::Class())) {
454  if (printError) Error(funcname,"Object %s is not a directory", path);
455  delete [] path; return 0;
456  }
457  delete [] path; return (TDirectory*)obj;
458  }
459 
460  TString subdir(path);
461  slash = (char*)strchr(subdir.Data(),'/');
462  *slash = 0;
463  //Get object with path from current directory/file
464  if (!strcmp(subdir, "..")) {
465  TDirectory* mom = GetMotherDir();
466  if (mom)
467  result = mom->GetDirectory(slash+1,printError,funcname);
468  delete [] path; return result;
469  }
470  obj = Get(subdir);
471  if (!obj) {
472  if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
473  delete [] path; return 0;
474  }
475 
476  //Check return object is a directory
477  if (!obj->InheritsFrom(TDirectory::Class())) {
478  if (printError) Error(funcname,"Object %s is not a directory", subdir.Data());
479  delete [] path; return 0;
480  }
481  result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
482  delete [] path; return result;
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// Change current directory to "this" directory.
487 ///
488 /// Using path one can change the current directory to "path". The absolute path
489 /// syntax is: `file.root:/dir1/dir2`
490 /// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
491 /// in the file.
492 ///
493 /// Relative syntax is relative to "this" directory. E.g: `../aa`.
494 ///
495 /// Returns kTRUE in case of success.
496 
497 Bool_t TDirectory::cd(const char *path)
498 {
499  return cd1(path);
500 }
501 
502 ////////////////////////////////////////////////////////////////////////////////
503 /// Change current directory to "this" directory.
504 ///
505 /// Using path one can
506 /// change the current directory to "path". The absolute path syntax is:
507 /// `file.root:/dir1/dir2`
508 /// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
509 /// in the file.
510 ///
511 /// Relative syntax is relative to "this" directory. E.g: `../aa`.
512 ///
513 /// Returns kFALSE in case path does not exist.
514 
515 Bool_t TDirectory::cd1(const char *apath)
516 {
517  Int_t nch = 0;
518  if (apath) nch = strlen(apath);
519  if (!nch) {
520  gDirectory = this;
521  return kTRUE;
522  }
523 
524  TDirectory *where = GetDirectory(apath,kTRUE,"cd");
525  if (where) {
526  where->cd();
527  return kTRUE;
528  }
529  return kFALSE;
530 }
531 
532 ////////////////////////////////////////////////////////////////////////////////
533 /// Change current directory to "path". The absolute path syntax is:
534 /// `file.root:/dir1/dir2`
535 /// where file.root is the file and `/dir1/dir2 the desired subdirectory
536 /// in the file.
537 /// Relative syntax is relative to the current directory `gDirectory`, e.g.: `../aa`.
538 ///
539 /// Returns kTRUE in case of success.
540 
541 Bool_t TDirectory::Cd(const char *path)
542 {
543  return Cd1(path);
544 }
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 /// Change current directory to "path". The path syntax is:
548 /// `file.root:/dir1/dir2`
549 /// where file.root is the file and `/dir1/dir2` the desired subdirectory
550 /// in the file.
551 ///
552 /// Returns kFALSE in case path does not exist.
553 
554 Bool_t TDirectory::Cd1(const char *apath)
555 {
556  // null path is always true (i.e. stay in the current directory)
557  Int_t nch = 0;
558  if (apath) nch = strlen(apath);
559  if (!nch) return kTRUE;
560 
561  TDirectory *where = gDirectory->GetDirectory(apath,kTRUE,"Cd");
562  if (where) {
563  where->cd();
564  return kTRUE;
565  }
566  return kFALSE;
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Delete all objects from a Directory list.
571 
573 {
574  if (fList) fList->Clear();
575 
576 }
577 
578 ////////////////////////////////////////////////////////////////////////////////
579 /// Delete all objects from memory and directory structure itself.
580 /// if option is "slow", iterate through the containers in a way to can handle
581 /// 'external' modification (induced by recursions)
582 /// if option is "nodelete", write the TDirectory but do not delete the contained
583 /// objects.
585 {
586  if (!fList) {
587  return;
588  }
589 
590  // Save the directory key list and header
591  Save();
592 
593  Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
594 
595  if (!nodelete) {
596  Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE;
597  if (!slow) {
598  // Check if it is wise to use the fast deletion path.
599  TObjLink *lnk = fList->FirstLink();
600  while (lnk) {
601  if (lnk->GetObject()->IsA() == TDirectory::Class()) {
602  slow = kTRUE;
603  break;
604  }
605  lnk = lnk->Next();
606  }
607  }
608 
609  // Delete objects from directory list, this in turn, recursively closes all
610  // sub-directories (that were allocated on the heap)
611  // if this dir contains subdirs, we must use the slow option for Delete!
612  // we must avoid "slow" as much as possible, in particular Delete("slow")
613  // with a large number of objects (eg >10^5) would take for ever.
614  if (slow) fList->Delete("slow");
615  else fList->Delete();
616  }
617 
618  CleanTargets();
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Delete all objects from memory.
623 
625 {
626  fList->Delete("slow");
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 /// Delete Objects or/and keys in a directory.
631 ///
632 /// - namecycle has the format name;cycle
633 /// - namecycle = "" same as namecycle ="T*"
634 /// - name = * means all
635 /// - cycle = * means all cycles (memory and keys)
636 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
637 /// When name=* use T* to delete subdirectories also
638 ///
639 /// To delete one directory, you must specify the directory cycle,
640 /// eg. `file.Delete("dir1;1");`
641 ///
642 /// examples:
643 /// - foo : delete object named foo in memory
644 /// - foo* : delete all objects with a name starting with foo
645 /// - foo;1 : delete cycle 1 of foo on file
646 /// - foo;* : delete all cycles of foo on file and also from memory
647 /// - *;2 : delete all objects on file having the cycle 2
648 /// - *;* : delete all objects from memory and file
649 /// - T*;* : delete all objects from memory and file and all subdirectories
650 
651 void TDirectory::Delete(const char *namecycle)
652 {
653  if (gDebug)
654  Info("Delete","Call for this = %s namecycle = %s",
655  GetName(), (namecycle ? namecycle : "null"));
656 
657  TDirectory::TContext ctxt(this);
658  Short_t cycle;
659  char name[kMaxLen];
660  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
661 
662  Int_t deleteall = 0;
663  Int_t deletetree = 0;
664  if(strcmp(name,"*") == 0) deleteall = 1;
665  if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
666  if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
667  if(namecycle==0 || !namecycle[0]){ deleteall = 1; deletetree = 1;}
668  TRegexp re(name,kTRUE);
669  TString s;
670  Int_t deleteOK = 0;
671 
672 //*-*---------------------Case of Object in memory---------------------
673 // ========================
674  if (cycle >= 9999 ) {
675  TNamed *idcur;
676  TIter next(fList);
677  while ((idcur = (TNamed *) next())) {
678  deleteOK = 0;
679  s = idcur->GetName();
680  if (deleteall || s.Index(re) != kNPOS) {
681  deleteOK = 1;
682  if (idcur->IsA() == TDirectory::Class()) {
683  deleteOK = 2;
684  if (!deletetree && deleteall) deleteOK = 0;
685  }
686  }
687  if (deleteOK != 0) {
688  fList->Remove(idcur);
689  if (deleteOK==2) {
690  // read subdirectories to correctly delete them
691  if (deletetree)
692  ((TDirectory*) idcur)->ReadAll("dirs");
693  idcur->Delete(deletetree ? "T*;*" : "*");
694  delete idcur;
695  } else
696  idcur->Delete(name);
697  }
698  }
699  }
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Fill Graphics Structure and Paint.
704 ///
705 /// Loop on all objects (memory or file) and all subdirectories
706 
708 {
709  fList->R__FOR_EACH(TObject,Draw)(option);
710 }
711 
712 ////////////////////////////////////////////////////////////////////////////////
713 /// Find object in the list of memory objects.
714 
716 {
717  return fList->FindObject(obj);
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Find object by name in the list of memory objects.
722 
724 {
725  return fList->FindObject(name);
726 }
727 
728 ////////////////////////////////////////////////////////////////////////////////
729 /// Find object by name in the list of memory objects of the current
730 /// directory or its sub-directories.
731 /// After this call the current directory is not changed.
732 /// To automatically set the current directory where the object is found,
733 /// use FindKeyAny(aname)->ReadObj().
734 
735 TObject *TDirectory::FindObjectAny(const char *aname) const
736 {
737  //object may be already in the list of objects in memory
738  TObject *obj = fList->FindObject(aname);
739  if (obj) return obj;
740 
741  //try with subdirectories
742  TIter next(fList);
743  while( (obj = next()) ) {
744  if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
745  TDirectory* subdir = static_cast<TDirectory*>(obj);
746  TObject *subobj = subdir->TDirectory::FindObjectAny(aname); // Explicitly recurse into _this_ exact function.
747  if (subobj) {
748  return subobj;
749  }
750  }
751  }
752  return 0;
753 }
754 
755 ////////////////////////////////////////////////////////////////////////////////
756 /// Return pointer to object identified by namecycle.
757 ///
758 /// namecycle has the format name;cycle
759 /// - name = * is illegal, cycle = * is illegal
760 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
761 ///
762 /// examples:
763 /// - foo : get object named foo in memory
764 /// if object is not in memory, try with highest cycle from file
765 /// - foo;1 : get cycle 1 of foo on file
766 ///
767 /// The retrieved object should in principle derive from TObject.
768 /// If not, the function TDirectory::GetObject should be called.
769 /// However, this function will still work for a non-TObject, providing that
770 /// the calling application cast the return type to the correct type (which
771 /// is the actual type of the object).
772 ///
773 /// NOTE:
774 ///
775 /// The method GetObject offer better protection and avoid the need
776 /// for any cast:
777 /// ~~~ {.cpp}
778 /// MyClass *obj;
779 /// directory->GetObject("some object",obj);
780 /// if (obj) { ... the object exist and inherits from MyClass ... }
781 /// ~~~
782 ///
783 /// VERY IMPORTANT NOTE:
784 ///
785 /// In case the class of this object derives from TObject but not
786 /// as a first inheritance, one must use dynamic_cast<>().
787 /// #### Example 1: Normal case:
788 /// ~~~ {.cpp}
789 /// class MyClass : public TObject, public AnotherClass
790 /// ~~~
791 /// then on return, one can do:
792 /// ~~~ {.cpp}
793 /// MyClass *obj = (MyClass*)directory->Get("some object of MyClass");
794 /// ~~~
795 /// #### Example 2: Special case:
796 /// ~~~ {.cpp}
797 /// class MyClass : public AnotherClass, public TObject
798 /// ~~~
799 /// then on return, one must do:
800 /// ~~~ {.cpp}
801 /// MyClass *obj = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
802 /// ~~~
803 /// Of course, dynamic_cast<> can also be used in the example 1.
804 
805 TObject *TDirectory::Get(const char *namecycle)
806 {
807  Short_t cycle;
808  char name[kMaxLen];
809 
810  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
811  char *namobj = name;
812  Int_t nch = strlen(name);
813  for (Int_t i = nch-1; i > 0; i--) {
814  if (name[i] == '/') {
815  name[i] = 0;
816  TDirectory* dirToSearch=GetDirectory(name);
817  namobj = name + i + 1;
818  name[i] = '/';
819  return dirToSearch?dirToSearch->Get(namobj):0;
820  }
821  }
822 
823 //*-*---------------------Case of Object in memory---------------------
824 // ========================
825  TObject *idcur = fList->FindObject(namobj);
826  if (idcur) {
827  if (idcur==this && strlen(namobj)!=0) {
828  // The object has the same name has the directory and
829  // that's what we picked-up! We just need to ignore
830  // it ...
831  idcur = 0;
832  } else if (cycle == 9999) {
833  return idcur;
834  } else {
835  if (idcur->InheritsFrom(TCollection::Class()))
836  idcur->Delete(); // delete also list elements
837  delete idcur;
838  idcur = 0;
839  }
840  }
841  return idcur;
842 }
843 
844 ////////////////////////////////////////////////////////////////////////////////
845 /// Return pointer to object identified by namecycle.
846 /// The returned object may or may not derive from TObject.
847 ///
848 /// - namecycle has the format name;cycle
849 /// - name = * is illegal, cycle = * is illegal
850 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
851 ///
852 /// VERY IMPORTANT NOTE:
853 ///
854 /// The calling application must cast the returned object to
855 /// the final type, e.g.
856 /// ~~~ {.cpp}
857 /// MyClass *obj = (MyClass*)directory->GetObject("some object of MyClass");
858 /// ~~~
859 
860 void *TDirectory::GetObjectUnchecked(const char *namecycle)
861 {
862  return GetObjectChecked(namecycle,(TClass*)0);
863 }
864 
865 ////////////////////////////////////////////////////////////////////////////////
866 /// See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
867 
868 void *TDirectory::GetObjectChecked(const char *namecycle, const char* classname)
869 {
870  return GetObjectChecked(namecycle,TClass::GetClass(classname));
871 }
872 
873 
874 ////////////////////////////////////////////////////////////////////////////////
875 /// Return pointer to object identified by namecycle if and only if the actual
876 /// object is a type suitable to be stored as a pointer to a "expectedClass"
877 /// If expectedClass is null, no check is performed.
878 ///
879 /// namecycle has the format `name;cycle`
880 /// - name = * is illegal, cycle = * is illegal
881 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
882 ///
883 /// VERY IMPORTANT NOTE:
884 ///
885 /// The calling application must cast the returned pointer to
886 /// the type described by the 2 arguments (i.e. cl):
887 /// ~~~ {.cpp}
888 /// MyClass *obj = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
889 /// ~~~
890 /// Note: We recommend using the method TDirectory::GetObject:
891 /// ~~~ {.cpp}
892 /// MyClass *obj = 0;
893 /// directory->GetObject("some object inheriting from MyClass",obj);
894 /// if (obj) { ... we found what we are looking for ... }
895 /// ~~~
896 
897 void *TDirectory::GetObjectChecked(const char *namecycle, const TClass* expectedClass)
898 {
899  Short_t cycle;
900  char name[kMaxLen];
901 
902  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
903  char *namobj = name;
904  Int_t nch = strlen(name);
905  for (Int_t i = nch-1; i > 0; i--) {
906  if (name[i] == '/') {
907  name[i] = 0;
908  TDirectory* dirToSearch=GetDirectory(name);
909  namobj = name + i + 1;
910  name[i] = '/';
911  if (dirToSearch) {
912  return dirToSearch->GetObjectChecked(namobj, expectedClass);
913  } else {
914  return 0;
915  }
916  }
917  }
918 
919 //*-*---------------------Case of Object in memory---------------------
920 // ========================
921  if (expectedClass==0 || expectedClass->IsTObject()) {
922  TObject *objcur = fList->FindObject(namobj);
923  if (objcur) {
924  if (objcur==this && strlen(namobj)!=0) {
925  // The object has the same name has the directory and
926  // that's what we picked-up! We just need to ignore
927  // it ...
928  objcur = 0;
929  } else if (cycle == 9999) {
930  // Check type
931  if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return 0;
932  else return objcur;
933  } else {
934  if (objcur->InheritsFrom(TCollection::Class()))
935  objcur->Delete(); // delete also list elements
936  delete objcur;
937  objcur = 0;
938  }
939  }
940  }
941 
942  return 0;
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
947 /// The returned path will be re-used by the next call to GetPath().
948 
949 const char *TDirectory::GetPathStatic() const
950 {
951  static char *path = 0;
952  const int kMAXDEPTH = 128;
953  const TDirectory *d[kMAXDEPTH];
954  const TDirectory *cur = this;
955  int depth = 0, len = 0;
956 
957  d[depth++] = cur;
958  len = strlen(cur->GetName()) + 1; // +1 for the /
959 
960  while (cur->fMother && depth < kMAXDEPTH) {
961  cur = (TDirectory *)cur->fMother;
962  d[depth++] = cur;
963  len += strlen(cur->GetName()) + 1;
964  }
965 
966  if (path) delete [] path;
967  path = new char[len+2];
968 
969  for (int i = depth-1; i >= 0; i--) {
970  if (i == depth-1) { // file or TROOT name
971  strlcpy(path, d[i]->GetName(),len+2);
972  strlcat(path, ":",len+2);
973  if (i == 0) strlcat(path, "/",len+2);
974  } else {
975  strlcat(path, "/",len+2);
976  strlcat(path, d[i]->GetName(),len+2);
977  }
978  }
979 
980  return path;
981 }
982 
983 ////////////////////////////////////////////////////////////////////////////////
984 /// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
985 /// The returned path will be re-used by the next call to GetPath().
986 
987 const char *TDirectory::GetPath() const
988 {
989  //
990  TString* buf = &(const_cast<TDirectory*>(this)->fPathBuffer);
991 
992  FillFullPath(*buf);
993  if (GetMotherDir()==0) // case of file
994  buf->Append("/");
995 
996  return buf->Data();
997 }
998 
999 ////////////////////////////////////////////////////////////////////////////////
1000 /// Recursive method to fill full path for directory.
1001 
1003 {
1004  TDirectory* mom = GetMotherDir();
1005  if (mom!=0) {
1006  mom->FillFullPath(buf);
1007  buf += "/";
1008  buf += GetName();
1009  } else {
1010  buf = GetName();
1011  buf +=":";
1012  }
1013 }
1014 
1015 ////////////////////////////////////////////////////////////////////////////////
1016 /// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1017 ///
1018 /// Returns 0 in case of error or if a sub-directory (hierarchy) with the requested
1019 /// name already exists.
1020 /// Returns a pointer to the created sub-directory or to the top sub-directory of
1021 /// the hierarchy (in the above example, the returned TDirectory * always points
1022 /// to "a").
1023 /// In particular, the steps to create first a/b/c and then a/b/d without receiving
1024 /// errors are:
1025 /// ~~~ {.cpp}
1026 /// TFile * file = new TFile("afile","RECREATE");
1027 /// file->mkdir("a");
1028 /// file->cd("a");
1029 /// gDirectory->mkdir("b/c");
1030 /// gDirectory->cd("b");
1031 /// gDirectory->mkdir("d");
1032 /// ~~~
1033 
1034 TDirectory *TDirectory::mkdir(const char *name, const char *title)
1035 {
1036  if (!name || !title || !name[0]) return 0;
1037  if (!title[0]) title = name;
1038  TDirectory *newdir = 0;
1039  if (const char *slash = strchr(name,'/')) {
1040  Long_t size = Long_t(slash-name);
1041  char *workname = new char[size+1];
1042  strncpy(workname, name, size);
1043  workname[size] = 0;
1044  TDirectory *tmpdir;
1045  GetObject(workname,tmpdir);
1046  if (!tmpdir) {
1047  tmpdir = mkdir(workname,title);
1048  if (!tmpdir) return 0;
1049  }
1050  delete[] workname;
1051  if (!tmpdir) return 0;
1052  if (!newdir) newdir = tmpdir;
1053  tmpdir->mkdir(slash+1);
1054  return newdir;
1055  }
1056 
1057  TDirectory::TContext ctxt(this);
1058 
1059  newdir = new TDirectory(name, title, "", this);
1060 
1061  return newdir;
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// List Directory contents.
1066 ///
1067 /// Indentation is used to identify the directory tree
1068 /// Subdirectories are listed first, then objects in memory.
1069 ///
1070 /// The option can has the following format:
1071 ///
1072 /// [<regexp>]
1073 ///
1074 /// The `<regexp>` will be used to match the name of the objects.
1075 /// By default memory and disk objects are listed.
1076 
1077 void TDirectory::ls(Option_t *option) const
1078 {
1081 
1082  TString opta = option;
1083  TString opt = opta.Strip(TString::kBoth);
1084  Bool_t memobj = kTRUE;
1085  TString reg = "*";
1086  if (opt.BeginsWith("-m")) {
1087  if (opt.Length() > 2)
1088  reg = opt(2,opt.Length());
1089  } else if (opt.BeginsWith("-d")) {
1090  memobj = kFALSE;
1091  if (opt.Length() > 2)
1092  reg = opt(2,opt.Length());
1093  } else if (!opt.IsNull())
1094  reg = opt;
1095 
1096  TRegexp re(reg, kTRUE);
1097 
1098  if (memobj) {
1099  TObject *obj;
1100  TIter nextobj(fList);
1101  while ((obj = (TObject *) nextobj())) {
1102  TString s = obj->GetName();
1103  if (s.Index(re) == kNPOS) continue;
1104  obj->ls(option); //*-* Loop on all the objects in memory
1105  }
1106  }
1108 }
1109 
1110 ////////////////////////////////////////////////////////////////////////////////
1111 /// Paint all objects in the directory.
1112 
1114 {
1115  fList->R__FOR_EACH(TObject,Paint)(option);
1116 }
1117 
1118 ////////////////////////////////////////////////////////////////////////////////
1119 /// Print all objects in the directory.
1120 
1121 void TDirectory::Print(Option_t *option) const
1122 {
1123  fList->R__FOR_EACH(TObject,Print)(option);
1124 }
1125 
1126 ////////////////////////////////////////////////////////////////////////////////
1127 /// Print the path of the directory.
1128 
1129 void TDirectory::pwd() const
1130 {
1131  Printf("%s", GetPath());
1132 }
1133 
1134 ////////////////////////////////////////////////////////////////////////////////
1135 /// Recursively remove object from a Directory.
1136 
1138 {
1139  fList->RecursiveRemove(obj);
1140 }
1141 
1142 ////////////////////////////////////////////////////////////////////////////////
1143 /// Remove an object from the in-memory list.
1144 
1146 {
1147  TObject *p = 0;
1148  if (fList) {
1149  p = fList->Remove(obj);
1150  }
1151  return p;
1152 }
1153 
1154 ////////////////////////////////////////////////////////////////////////////////
1155 /// Removes subdirectory from the directory
1156 /// When directory is deleted, all keys in all subdirectories will be
1157 /// read first and deleted from file (if exists)
1158 /// Equivalent call is Delete("name;*");
1159 
1160 void TDirectory::rmdir(const char *name)
1161 {
1162  if ((name==0) || (*name==0)) return;
1163 
1164  TString mask(name);
1165  mask+=";*";
1166  Delete(mask);
1167 }
1168 
1169 ////////////////////////////////////////////////////////////////////////////////
1170 /// Save object in filename,
1171 /// if filename is 0 or "", a file with "objectname.root" is created.
1172 /// The name of the key is the object name.
1173 /// If the operation is successful, it returns the number of bytes written to the file
1174 /// otherwise it returns 0.
1175 /// By default a message is printed. Use option "q" to not print the message.
1176 /// If filename contains ".json" extension, JSON representation of the object
1177 /// will be created and saved in the text file. Such file can be used in
1178 /// JavaScript ROOT (https://root.cern.ch/js/) to display object in web browser
1179 /// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1180 
1181 Int_t TDirectory::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) const
1182 {
1183  if (!obj) return 0;
1184  Int_t nbytes = 0;
1185  TString fname = filename;
1186  if (!filename || !filename[0]) {
1187  fname.Form("%s.root",obj->GetName());
1188  }
1189  TString cmd;
1190  if (fname.Index(".json") > 0) {
1191  cmd.Form("TBufferJSON::ExportToFile(\"%s\",(TObject*) %s, \"%s\");", fname.Data(), TString::LLtoa((Long_t)obj, 10).Data(), (option ? option : ""));
1192  nbytes = gROOT->ProcessLine(cmd);
1193  } else {
1194  cmd.Form("TFile::Open(\"%s\",\"recreate\");",fname.Data());
1195  TContext ctxt; // The TFile::Open will change the current directory.
1196  TDirectory *local = (TDirectory*)gROOT->ProcessLine(cmd);
1197  if (!local) return 0;
1198  nbytes = obj->Write();
1199  delete local;
1200  }
1201  TString opt(option);
1202  opt.ToLower();
1203  if (!opt.Contains("q")) {
1204  if (!gSystem->AccessPathName(fname.Data())) obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1205  }
1206  return nbytes;
1207 }
1208 
1209 ////////////////////////////////////////////////////////////////////////////////
1210 /// Set the name for directory
1211 /// If the directory name is changed after the directory was written once,
1212 /// ROOT currently would NOT change the name of correspondent key in the
1213 /// mother directory.
1214 /// DO NOT use this method to 'rename a directory'.
1215 /// Renaming a directory is currently NOT supported.
1216 
1217 void TDirectory::SetName(const char* newname)
1218 {
1219  TNamed::SetName(newname);
1220 }
1221 
1222 ////////////////////////////////////////////////////////////////////////////////
1223 /// Encode the name and cycle into buffer like: "aap;2".
1224 
1225 void TDirectory::EncodeNameCycle(char *buffer, const char *name, Short_t cycle)
1226 {
1227  if (cycle == 9999)
1228  strcpy(buffer, name);
1229  else
1230  sprintf(buffer, "%s;%d", name, cycle);
1231 }
1232 
1233 ////////////////////////////////////////////////////////////////////////////////
1234 /// Decode a namecycle "aap;2" into name "aap" and cycle "2". Destination
1235 /// buffer size for name (including string terminator) should be specified in
1236 /// namesize.
1237 
1238 void TDirectory::DecodeNameCycle(const char *buffer, char *name, Short_t &cycle,
1239  const size_t namesize)
1240 {
1241  size_t len = 0;
1242  const char *ni = strchr(buffer, ';');
1243 
1244  if (ni) {
1245  // Found ';'
1246  len = ni - buffer;
1247  ++ni;
1248  } else {
1249  // No ';' found
1250  len = strlen(buffer);
1251  ni = &buffer[len];
1252  }
1253 
1254  if (namesize) {
1255  if (len > namesize-1ul) len = namesize-1; // accommodate string terminator
1256  } else {
1257  ::Warning("TDirectory::DecodeNameCycle",
1258  "Using unsafe version: invoke this metod by specifying the buffer size");
1259  }
1260 
1261  strncpy(name, buffer, len);
1262  name[len] = '\0';
1263 
1264  if (*ni == '*')
1265  cycle = 10000;
1266  else if (isdigit(*ni)) {
1267  long parsed = strtol(ni,nullptr,10);
1268  if (parsed >= (long) std::numeric_limits<Short_t>::max())
1269  cycle = 0;
1270  else
1271  cycle = (Short_t)parsed;
1272  } else
1273  cycle = 9999;
1274 }
1275 
1276 ////////////////////////////////////////////////////////////////////////////////
1277 /// Register a TContext pointing to this TDirectory object
1278 
1281 
1282  if (fContext) {
1283  TContext *current = fContext;
1284  while(current->fNext) {
1285  current = current->fNext;
1286  }
1287  current->fNext = ctxt;
1288  ctxt->fPrevious = current;
1289  } else {
1290  fContext = ctxt;
1291  }
1292 }
1293 
1294 ////////////////////////////////////////////////////////////////////////////////
1295 /// See TDirectoryFile::WriteTObject for details
1296 
1297 Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Int_t /*bufsize*/)
1298 {
1299  const char *objname = "no name specified";
1300  if (name) objname = name;
1301  else if (obj) objname = obj->GetName();
1302  Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1303  return 0;
1304 }
1305 
1306 ////////////////////////////////////////////////////////////////////////////////
1307 /// UnRegister a TContext pointing to this TDirectory object
1308 
1310 
1312 
1313  // Another thread already unregistered the TContext.
1314  if (ctxt->fDirectory == nullptr)
1315  return;
1316 
1317  if (ctxt==fContext) {
1318  fContext = ctxt->fNext;
1319  if (fContext) fContext->fPrevious = 0;
1320  ctxt->fPrevious = ctxt->fNext = 0;
1321  } else {
1322  TContext *next = ctxt->fNext;
1323  ctxt->fPrevious->fNext = next;
1324  if (next) next->fPrevious = ctxt->fPrevious;
1325  ctxt->fPrevious = ctxt->fNext = 0;
1326  }
1327 }
1328 
1329 ////////////////////////////////////////////////////////////////////////////////
1330 /// Set the current directory to null.
1331 /// This is called from the TContext destructor. Since the destructor is
1332 /// inline, we do not want to have it directly use a global variable.
1333 
1335 {
1336  gDirectory = 0;
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////////////////
1340 /// TDirectory Streamer.
1341 void TDirectory::Streamer(TBuffer &R__b)
1342 {
1343  // Stream an object of class TDirectory.
1344 
1345  UInt_t R__s, R__c;
1346  if (R__b.IsReading()) {
1347  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1348  TNamed::Streamer(R__b);
1349  R__b >> fMother;
1350  R__b >> fList;
1351  fList->UseRWLock();
1352  fUUID.Streamer(R__b);
1353  R__b.StreamObject(&(fSpinLock),typeid(fSpinLock));
1354  R__b.CheckByteCount(R__s, R__c, TDirectory::IsA());
1355  } else {
1356  R__c = R__b.WriteVersion(TDirectory::IsA(), kTRUE);
1357  TNamed::Streamer(R__b);
1358  R__b << fMother;
1359  R__b << fList;
1360  fUUID.Streamer(R__b);
1361  R__b.StreamObject(&(fSpinLock),typeid(fSpinLock));
1362  R__b.SetByteCount(R__c, kTRUE);
1363  }
1364 }
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:261
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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:785
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:1276
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
virtual void Draw(Option_t *option="")
Fill Graphics Structure and Paint.
Definition: TDirectory.cxx:707
virtual void Copy(TObject &) const
Copy this to obj.
Definition: TDirectory.h:126
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual ~TDirectory()
Destructor.
Definition: TDirectory.cxx:101
std::atomic_flag fSpinLock
Counter delaying the TDirectory destructor from finishing.
Definition: TDirectory.h:93
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2683
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
auto * m
Definition: textangle.C:8
virtual void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
Definition: TDirectory.cxx:237
short Version_t
Definition: RtypesCore.h:61
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:805
const char Option_t
Definition: RtypesCore.h:62
virtual TDirectory * GetMotherDir() const
Definition: TDirectory.h:152
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:139
virtual void Print(Option_t *option="") const
Print all objects in the directory.
TList * fList
Definition: TDirectory.h:87
virtual TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE)
Clone an object.
Definition: TDirectory.cxx:328
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetPathStatic() const
Returns the full path of the directory.
Definition: TDirectory.cxx:949
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
virtual TObject * FindObject(const char *name) const
Find object by name in the list of memory objects.
Definition: TDirectory.cxx:723
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Regular expression class.
Definition: TRegexp.h:31
void FillFullPath(TString &buf) const
Recursive method to fill full path for directory.
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:402
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
Basic string class.
Definition: TString.h:125
std::atomic< bool > fDirectoryWait
Set to true during the destructor execution.
Definition: TDirectory.h:45
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
int Int_t
Definition: RtypesCore.h:41
virtual TDirectory * mkdir(const char *name, const char *title="")
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
TContext * fPrevious
Set to true if a TDirectory might still access this object.
Definition: TDirectory.h:47
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual Int_t SaveObjectAs(const TObject *, const char *="", Option_t *="") const
Save object in filename, if filename is 0 or "", a file with "objectname.root" is created...
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
Definition: TThreadSlots.h:40
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl) ...
Definition: TDirectory.cxx:868
if object in a list can be deleted
Definition: TObject.h:58
TString fPathBuffer
Definition: TDirectory.h:89
#define SafeDelete(p)
Definition: RConfig.h:509
std::atomic< TDirectory * > fDirectory
Definition: TDirectory.h:43
void Class()
Definition: Class.C:29
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
void * InterfaceMethod() const
Return pointer to the interface method.
Definition: TFunction.cxx:208
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void Save()
Definition: TDirectory.h:179
virtual void Paint(Option_t *option="")
Paint all objects in the directory.
Bool_t cd1(const char *path)
flag to add histograms, graphs,etc to the directory
Definition: TDirectory.cxx:515
TString & Append(const char *cs)
Definition: TString.h:495
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
Definition: TDirectory.cxx:584
virtual void rmdir(const char *name)
Removes subdirectory from the directory When directory is deleted, all keys in all subdirectories wil...
virtual bool UseRWLock()
Set this collection to use a RW lock upon access, making it thread safe.
virtual TList * GetList() const
Definition: TDirectory.h:149
virtual TFile * GetFile() const
Definition: TDirectory.h:147
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:492
virtual void pwd() const
Print the path of the directory.
const Int_t kMaxLen
Definition: TDirectory.cxx:33
virtual void Delete(const char *namecycle="")
Delete Objects or/and keys in a directory.
Definition: TDirectory.cxx:651
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add objects like histograms, TGraph2D, etc in memory...
Definition: TDirectory.cxx:171
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
TContext * fNext
Pointer to the next TContext in the implied list of context pointing to fPrevious.
Definition: TDirectory.h:48
virtual void Browse(TBrowser *b)
Browse the content of the directory.
Definition: TDirectory.cxx:215
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const
Definition: TCollection.h:208
TContext * fContext
Buffer for GetPath() function.
Definition: TDirectory.h:90
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
TUUID fUUID
Definition: TDirectory.h:88
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:561
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2343
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void * GetObjectUnchecked(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:860
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
static Bool_t Cd1(const char *path)
Change current directory to "path".
Definition: TDirectory.cxx:554
Ssiz_t Length() const
Definition: TString.h:386
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:281
short Short_t
Definition: RtypesCore.h:35
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2746
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:987
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual TObjLink * FirstLink() const
Definition: TList.h:108
#define Printf
Definition: TGeoToOCC.h:18
virtual void Clear(Option_t *option="")
Delete all objects from a Directory list.
Definition: TDirectory.cxx:572
TObject * fMother
Definition: TDirectory.h:86
virtual void StreamObject(void *obj, const std::type_info &typeinfo, const TClass *onFileClass=0)=0
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
virtual void SetName(const char *newname)
Set the name for directory If the directory name is changed after the directory was written once...
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
static Bool_t Cd(const char *path)
Change current directory to "path".
Definition: TDirectory.cxx:541
#define ClassImp(name)
Definition: Rtypes.h:359
static void EncodeNameCycle(char *buffer, const char *name, Short_t cycle)
Encode the name and cycle into buffer like: "aap;2".
Describe directory structure in memory.
Definition: TDirectory.h:34
static TDirectory *& CurrentDirectory()
Return the current directory for the current thread.
Definition: TDirectory.cxx:380
static Bool_t AddDirectoryStatus()
Static function: see TDirectory::AddDirectory for more comments.
Definition: TDirectory.cxx:179
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
static constexpr double s
#define R__LOCKGUARD(mutex)
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".
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:2887
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
TCanvas * slash()
Definition: slash.C:1
Bool_t IsNull() const
Definition: TString.h:383
Mother of all ROOT objects.
Definition: TObject.h:37
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2738
typedef void((*Func_t)())
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5668
static TBuffer * R__CreateBuffer()
Fast execution of &#39;new TBufferFile(TBuffer::kWrite,10000), without having a compile time circular dep...
Definition: TDirectory.cxx:300
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
virtual void Add(TObject *obj)
Definition: TList.h:87
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:110
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:760
virtual void DeleteAll(Option_t *option="")
Delete all objects from memory.
Definition: TDirectory.cxx:624
virtual void ls(Option_t *option="") const
List Directory contents.
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
Definition: TDirectory.cxx:400
TDirectory()
Directory default constructor.
Definition: TDirectory.cxx:46
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
static TString LLtoa(Long64_t value, Int_t base)
Converts a Long64_t to a TString with respect to the base specified (2-36).
Definition: TString.cxx:2131
virtual void ResetMap()=0
#define gDirectory
Definition: TDirectory.h:213
~TContext()
Destructor.
Definition: TDirectory.cxx:134
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
void RegisterContext(TContext *ctxt)
Register a TContext pointing to this TDirectory object.
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition: TClass.cxx:4277
virtual void RecursiveRemove(TObject *obj)
Recursively remove object from a Directory.
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
virtual void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
Definition: TDirectory.cxx:252
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
A spin mutex-as-code-guard class.
void UnregisterContext(TContext *ctxt)
UnRegister a TContext pointing to this TDirectory object.
static Bool_t fgAddDirectory
MSVC doesn&#39;t support = ATOMIC_FLAG_INIT;.
Definition: TDirectory.h:95
void CdNull()
Set the current directory to null.
const char * Data() const
Definition: TString.h:345
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:735