Logo ROOT  
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
33const Int_t kMaxLen = 2048;
34
35/** \class TDirectory
36\ingroup Base
37
38Describe directory structure in memory.
39*/
40
42
43////////////////////////////////////////////////////////////////////////////////
44/// Directory default constructor.
45
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
65TDirectory::TDirectory(const char *name, const char *title, Option_t * /*classname*/, TDirectory* initMotherDir)
66 : TNamed(name, title)
67{
68 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
69 std::atomic_flag_clear( &fSpinLock );
70
71 if (!initMotherDir) initMotherDir = gDirectory;
72
73 if (strchr(name,'/')) {
74 ::Error("TDirectory::TDirectory","directory name (%s) cannot contain a slash", name);
75 gDirectory = nullptr;
76 return;
77 }
78 if (strlen(GetName()) == 0) {
79 ::Error("TDirectory::TDirectory","directory name cannot be \"\"");
80 gDirectory = nullptr;
81 return;
82 }
83
84 BuildDirectory(initMotherDir ? initMotherDir->GetFile() : nullptr, initMotherDir);
85}
86
87////////////////////////////////////////////////////////////////////////////////
88/// Destructor.
89
91{
92 if (!gROOT) {
93 delete fList;
94 return; //when called by TROOT destructor
95 }
96
97 if (fList) {
98 if (!fList->IsUsingRWLock())
99 Fatal("~TDirectory","In %s:%p the fList (%p) is not using the RWLock\n",
100 GetName(),this,fList);
101 fList->Delete("slow");
103 }
104
106
107 TDirectory* mom = GetMotherDir();
108
109 if (mom) {
110 mom->Remove(this);
111 }
112
113 if (gDebug) {
114 Info("~TDirectory", "dtor called for %s", GetName());
115 }
116}
117
118
119////////////////////////////////////////////////////////////////////////////////
120/// Set the current directory to null.
121/// This is called from the TContext destructor. Since the destructor is
122/// inline, we do not want to have it directly use a global variable.
123
125{
126 gDirectory = nullptr;
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(nullptr) 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
190void TDirectory::Append(TObject *obj, Bool_t replace /* = kFALSE */)
191{
192 if (!obj || !fList) return;
193
194 if (replace && obj->GetName() && obj->GetName()[0]) {
195 TObject *old;
196 while (nullptr != (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,nullptr);
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 = nullptr;
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
237void TDirectory::BuildDirectory(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 = nullptr;
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 = nullptr;
304 if (!creator) {
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
328TObject *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 nullptr;
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 nullptr;
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 = nullptr;
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 nullptr;
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 nullptr;
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 nullptr;
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 nullptr;
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 nullptr;
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
497Bool_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
515Bool_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
541Bool_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
554Bool_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
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
651void 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
735TObject *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 nullptr;
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
805TObject *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) : nullptr;
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 = nullptr;
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 = nullptr;
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
860void *TDirectory::GetObjectUnchecked(const char *namecycle)
861{
862 return GetObjectChecked(namecycle,(TClass *)nullptr);
863}
864
865////////////////////////////////////////////////////////////////////////////////
866/// See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
867
868void *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 = nullptr;
893/// directory->GetObject("some object inheriting from MyClass",obj);
894/// if (obj) { ... we found what we are looking for ... }
895/// ~~~
896
897void *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 nullptr;
915 }
916 }
917 }
918
919//*-*---------------------Case of Object in memory---------------------
920// ========================
921 if (!expectedClass || 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 = nullptr;
929 } else if (cycle == 9999) {
930 // Check type
931 if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return nullptr;
932 else return objcur;
933 } else {
934 if (objcur->InheritsFrom(TCollection::Class()))
935 objcur->Delete(); // delete also list elements
936 delete objcur;
937 objcur = nullptr;
938 }
939 }
940 }
941
942 return nullptr;
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
949const char *TDirectory::GetPathStatic() const
950{
951 static char *path = nullptr;
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
987const char *TDirectory::GetPath() const
988{
990
991 if (!GetMotherDir()) // case of file
992 fPathBuffer.Append("/");
993
994 return fPathBuffer.Data();
995}
996
997////////////////////////////////////////////////////////////////////////////////
998/// Recursive method to fill full path for directory.
999
1001{
1002 TDirectory* mom = GetMotherDir();
1003 if (mom) {
1004 mom->FillFullPath(buf);
1005 buf += "/";
1006 buf += GetName();
1007 } else {
1008 buf = GetName();
1009 buf += ":";
1010 }
1011}
1012
1013////////////////////////////////////////////////////////////////////////////////
1014/// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1015///
1016/// Returns 0 in case of error or if a sub-directory (hierarchy) with the requested
1017/// name already exists.
1018/// returnExistingDirectory returns a pointer to an already existing sub-directory with the same name.
1019/// Returns a pointer to the created sub-directory or to the top sub-directory of
1020/// the hierarchy (in the above example, the returned TDirectory * always points
1021/// to "a").
1022/// In particular, the steps to create first a/b/c and then a/b/d without receiving
1023/// errors are:
1024/// ~~~ {.cpp}
1025/// TFile * file = new TFile("afile","RECREATE");
1026/// file->mkdir("a");
1027/// file->cd("a");
1028/// gDirectory->mkdir("b/c");
1029/// gDirectory->cd("b");
1030/// gDirectory->mkdir("d");
1031/// ~~~
1032/// or
1033/// ~~~ {.cpp}
1034/// TFile * file = new TFile("afile","RECREATE");
1035/// file->mkdir("a");
1036/// file->cd("a");
1037/// gDirectory->mkdir("b/c");
1038/// gDirectory->mkdir("b/d", "", true);
1039/// ~~~
1040
1041TDirectory *TDirectory::mkdir(const char *name, const char *title, Bool_t returnExistingDirectory)
1042{
1043 if (returnExistingDirectory) {
1044 auto existingdir = GetDirectory(name);
1045 if (existingdir)
1046 return existingdir;
1047 }
1048 if (!name || !title || !name[0]) return nullptr;
1049 if (!title[0]) title = name;
1050 TDirectory *newdir = nullptr;
1051 if (const char *slash = strchr(name,'/')) {
1052 Long_t size = Long_t(slash-name);
1053 char *workname = new char[size+1];
1054 strncpy(workname, name, size);
1055 workname[size] = 0;
1056 TDirectory *tmpdir;
1057 GetObject(workname,tmpdir);
1058 if (!tmpdir) {
1059 tmpdir = mkdir(workname,title);
1060 if (!tmpdir) return nullptr;
1061 }
1062 delete[] workname;
1063 if (!tmpdir) return nullptr;
1064 if (!newdir) newdir = tmpdir;
1065 tmpdir->mkdir(slash+1);
1066 return newdir;
1067 }
1068
1069 TDirectory::TContext ctxt(this);
1070
1071 newdir = new TDirectory(name, title, "", this);
1072
1073 return newdir;
1074}
1075
1076////////////////////////////////////////////////////////////////////////////////
1077/// List Directory contents.
1078///
1079/// Indentation is used to identify the directory tree
1080/// Subdirectories are listed first, then objects in memory.
1081///
1082/// The option can has the following format:
1083///
1084/// [<regexp>]
1085///
1086/// The `<regexp>` will be used to match the name of the objects.
1087/// By default memory and disk objects are listed.
1088
1089void TDirectory::ls(Option_t *option) const
1090{
1093
1094 TString opta = option;
1095 TString opt = opta.Strip(TString::kBoth);
1096 Bool_t memobj = kTRUE;
1097 TString reg = "*";
1098 if (opt.BeginsWith("-m")) {
1099 if (opt.Length() > 2)
1100 reg = opt(2,opt.Length());
1101 } else if (opt.BeginsWith("-d")) {
1102 memobj = kFALSE;
1103 if (opt.Length() > 2)
1104 reg = opt(2,opt.Length());
1105 } else if (!opt.IsNull())
1106 reg = opt;
1107
1108 TRegexp re(reg, kTRUE);
1109
1110 if (memobj) {
1111 TObject *obj;
1112 TIter nextobj(fList);
1113 while ((obj = (TObject *) nextobj())) {
1114 TString s = obj->GetName();
1115 if (s.Index(re) == kNPOS) continue;
1116 obj->ls(option); //*-* Loop on all the objects in memory
1117 }
1118 }
1120}
1121
1122////////////////////////////////////////////////////////////////////////////////
1123/// Paint all objects in the directory.
1124
1126{
1127 fList->R__FOR_EACH(TObject,Paint)(option);
1128}
1129
1130////////////////////////////////////////////////////////////////////////////////
1131/// Print all objects in the directory.
1132
1133void TDirectory::Print(Option_t *option) const
1134{
1135 fList->R__FOR_EACH(TObject,Print)(option);
1136}
1137
1138////////////////////////////////////////////////////////////////////////////////
1139/// Print the path of the directory.
1140
1142{
1143 Printf("%s", GetPath());
1144}
1145
1146////////////////////////////////////////////////////////////////////////////////
1147/// Recursively remove object from a Directory.
1148
1150{
1151 fList->RecursiveRemove(obj);
1152}
1153
1154////////////////////////////////////////////////////////////////////////////////
1155/// Remove an object from the in-memory list.
1156
1158{
1159 TObject *p = 0;
1160 if (fList) {
1161 p = fList->Remove(obj);
1162 }
1163 return p;
1164}
1165
1166////////////////////////////////////////////////////////////////////////////////
1167/// Removes subdirectory from the directory
1168/// When directory is deleted, all keys in all subdirectories will be
1169/// read first and deleted from file (if exists)
1170/// Equivalent call is Delete("name;*");
1171
1172void TDirectory::rmdir(const char *name)
1173{
1174 if ((name==0) || (*name==0)) return;
1175
1176 TString mask(name);
1177 mask+=";*";
1178 Delete(mask);
1179}
1180
1181////////////////////////////////////////////////////////////////////////////////
1182/// Save object in filename,
1183/// if filename is 0 or "", a file with "objectname.root" is created.
1184/// The name of the key is the object name.
1185/// If the operation is successful, it returns the number of bytes written to the file
1186/// otherwise it returns 0.
1187/// By default a message is printed. Use option "q" to not print the message.
1188/// If filename contains ".json" extension, JSON representation of the object
1189/// will be created and saved in the text file. Such file can be used in
1190/// JavaScript ROOT (https://root.cern.ch/js/) to display object in web browser
1191/// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1192
1193Int_t TDirectory::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) const
1194{
1195 if (!obj) return 0;
1196 Int_t nbytes = 0;
1197 TString fname = filename;
1198 if (!filename || !filename[0]) {
1199 fname.Form("%s.root",obj->GetName());
1200 }
1201 TString cmd;
1202 if (fname.Index(".json") > 0) {
1203 cmd.Form("TBufferJSON::ExportToFile(\"%s\",(TObject*) %s, \"%s\");", fname.Data(), TString::LLtoa((Long_t)obj, 10).Data(), (option ? option : ""));
1204 nbytes = gROOT->ProcessLine(cmd);
1205 } else {
1206 cmd.Form("TFile::Open(\"%s\",\"recreate\");",fname.Data());
1207 TContext ctxt; // The TFile::Open will change the current directory.
1208 TDirectory *local = (TDirectory*)gROOT->ProcessLine(cmd);
1209 if (!local) return 0;
1210 nbytes = obj->Write();
1211 delete local;
1212 }
1213 TString opt(option);
1214 opt.ToLower();
1215 if (!opt.Contains("q")) {
1216 if (!gSystem->AccessPathName(fname.Data())) obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1217 }
1218 return nbytes;
1219}
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Set the name for directory
1223/// If the directory name is changed after the directory was written once,
1224/// ROOT currently would NOT change the name of correspondent key in the
1225/// mother directory.
1226/// DO NOT use this method to 'rename a directory'.
1227/// Renaming a directory is currently NOT supported.
1228
1229void TDirectory::SetName(const char* newname)
1230{
1231 TNamed::SetName(newname);
1232}
1233
1234////////////////////////////////////////////////////////////////////////////////
1235/// Encode the name and cycle into buffer like: "aap;2".
1236
1237void TDirectory::EncodeNameCycle(char *buffer, const char *name, Short_t cycle)
1238{
1239 if (cycle == 9999)
1240 strcpy(buffer, name);
1241 else
1242 sprintf(buffer, "%s;%d", name, cycle);
1243}
1244
1245////////////////////////////////////////////////////////////////////////////////
1246/// Decode a namecycle "aap;2" into name "aap" and cycle "2". Destination
1247/// buffer size for name (including string terminator) should be specified in
1248/// namesize.
1249
1250void TDirectory::DecodeNameCycle(const char *buffer, char *name, Short_t &cycle,
1251 const size_t namesize)
1252{
1253 size_t len = 0;
1254 const char *ni = strchr(buffer, ';');
1255
1256 if (ni) {
1257 // Found ';'
1258 len = ni - buffer;
1259 ++ni;
1260 } else {
1261 // No ';' found
1262 len = strlen(buffer);
1263 ni = &buffer[len];
1264 }
1265
1266 if (namesize) {
1267 if (len > namesize-1ul) len = namesize-1; // accommodate string terminator
1268 } else {
1269 ::Warning("TDirectory::DecodeNameCycle",
1270 "Using unsafe version: invoke this metod by specifying the buffer size");
1271 }
1272
1273 strncpy(name, buffer, len);
1274 name[len] = '\0';
1275
1276 if (*ni == '*')
1277 cycle = 10000;
1278 else if (isdigit(*ni)) {
1279 long parsed = strtol(ni,nullptr,10);
1280 if (parsed >= (long) std::numeric_limits<Short_t>::max())
1281 cycle = 0;
1282 else
1283 cycle = (Short_t)parsed;
1284 } else
1285 cycle = 9999;
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// Register a TContext pointing to this TDirectory object
1290
1293
1294 if (fContext) {
1295 TContext *current = fContext;
1296 while(current->fNext) {
1297 current = current->fNext;
1298 }
1299 current->fNext = ctxt;
1300 ctxt->fPrevious = current;
1301 } else {
1302 fContext = ctxt;
1303 }
1304}
1305
1306////////////////////////////////////////////////////////////////////////////////
1307/// See TDirectoryFile::WriteTObject for details
1308
1309Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Int_t /*bufsize*/)
1310{
1311 const char *objname = "no name specified";
1312 if (name) objname = name;
1313 else if (obj) objname = obj->GetName();
1314 Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1315 return 0;
1316}
1317
1318////////////////////////////////////////////////////////////////////////////////
1319/// UnRegister a TContext pointing to this TDirectory object
1320
1322
1324
1325 // Another thread already unregistered the TContext.
1326 if (ctxt->fDirectory == nullptr)
1327 return;
1328
1329 if (ctxt==fContext) {
1330 fContext = ctxt->fNext;
1331 if (fContext) fContext->fPrevious = nullptr;
1332 ctxt->fPrevious = ctxt->fNext = nullptr;
1333 } else {
1334 TContext *next = ctxt->fNext;
1335 ctxt->fPrevious->fNext = next;
1336 if (next) next->fPrevious = ctxt->fPrevious;
1337 ctxt->fPrevious = ctxt->fNext = nullptr;
1338 }
1339}
1340
1341////////////////////////////////////////////////////////////////////////////////
1342/// TDirectory Streamer.
1343void TDirectory::Streamer(TBuffer &R__b)
1344{
1345 // Stream an object of class TDirectory.
1346
1347 UInt_t R__s, R__c;
1348 if (R__b.IsReading()) {
1349 Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1350 TNamed::Streamer(R__b);
1351 R__b >> fMother;
1352 R__b >> fList;
1353 fList->UseRWLock();
1354 fUUID.Streamer(R__b);
1355 R__b.CheckByteCount(R__s, R__c, TDirectory::IsA());
1356 } else {
1357 R__c = R__b.WriteVersion(TDirectory::IsA(), kTRUE);
1358 TNamed::Streamer(R__b);
1359 R__b << fMother;
1360 R__b << fList;
1361 fUUID.Streamer(R__b);
1362 R__b.SetByteCount(R__c, kTRUE);
1363 }
1364}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:550
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
short Short_t
Definition: RtypesCore.h:35
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
static TBuffer * R__CreateBuffer()
Fast execution of 'new TBufferFile(TBuffer::kWrite,10000), without having a compile time circular dep...
Definition: TDirectory.cxx:300
const Int_t kMaxLen
Definition: TDirectory.cxx:33
#define gDirectory
Definition: TDirectory.h:223
char name[80]
Definition: TGX11.cxx:109
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:59
#define gROOT
Definition: TROOT.h:415
void Printf(const char *fmt,...)
typedef void((*Func_t)())
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
Definition: TThreadSlots.h:40
#define R__LOCKGUARD(mutex)
A spin mutex-as-code-guard class.
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
@ kWrite
Definition: TBuffer.h:72
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Bool_t IsReading() const
Definition: TBuffer.h:85
virtual void ResetMap()=0
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:92
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:302
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5688
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:2906
virtual bool UseRWLock()
Set this collection to use a RW lock upon access, making it thread safe.
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const
Definition: TCollection.h:210
Small helper to keep current directory context.
Definition: TDirectory.h:41
std::atomic< bool > fDirectoryWait
Set to true during the destructor execution.
Definition: TDirectory.h:45
void CdNull()
Set the current directory to null.
Definition: TDirectory.cxx:124
~TContext()
Destructor.
Definition: TDirectory.cxx:134
TContext * fPrevious
Set to true if a TDirectory might still access this object.
Definition: TDirectory.h:46
TContext * fNext
Pointer to the next TContext in the implied list of context pointing to fPrevious.
Definition: TDirectory.h:47
std::atomic< TDirectory * > fDirectory
Definition: TDirectory.h:43
Describe directory structure in memory.
Definition: TDirectory.h:34
Bool_t cd1(const char *path)
flag to add histograms, graphs,etc to the directory
Definition: TDirectory.cxx:515
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
Definition: TDirectory.cxx:651
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
Definition: TDirectory.cxx:584
virtual void Save()
Definition: TDirectory.h:189
virtual TList * GetList() const
Definition: TDirectory.h:159
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
Definition: TDirectory.cxx:400
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:987
std::atomic_flag fSpinLock
Counter delaying the TDirectory destructor from finishing.
Definition: TDirectory.h:96
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:805
virtual void * GetObjectUnchecked(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:860
void Draw(Option_t *option="") override
Fill Graphics Structure and Paint.
Definition: TDirectory.cxx:707
virtual void DeleteAll(Option_t *option="")
Delete all objects from memory.
Definition: TDirectory.cxx:624
static TDirectory *& CurrentDirectory()
Return the current directory for the current thread.
Definition: TDirectory.cxx:380
virtual void rmdir(const char *name)
Removes subdirectory from the directory When directory is deleted, all keys in all subdirectories wil...
static Bool_t AddDirectoryStatus()
Static function: see TDirectory::AddDirectory for more comments.
Definition: TDirectory.cxx:179
void FillFullPath(TString &buf) const
Recursive method to fill full path for directory.
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
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
Definition: TDirectory.cxx:252
void ls(Option_t *option="") const override
List Directory contents.
TContext * fContext
Buffer for GetPath() function.
Definition: TDirectory.h:93
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
TDirectory()
Directory default constructor.
Definition: TDirectory.cxx:46
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 Bool_t Cd(const char *path)
Change current directory to "path".
Definition: TDirectory.cxx:541
void Clear(Option_t *option="") override
Delete all objects from a Directory list.
Definition: TDirectory.cxx:572
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
virtual TFile * GetFile() const
Definition: TDirectory.h:157
TObject * FindObject(const char *name) const override
Find object by name in the list of memory objects.
Definition: TDirectory.cxx:723
void Print(Option_t *option="") const override
Print all objects in the directory.
virtual ~TDirectory()
Destructor.
Definition: TDirectory.cxx:90
static Bool_t Cd1(const char *path)
Change current directory to "path".
Definition: TDirectory.cxx:554
void UnregisterContext(TContext *ctxt)
UnRegister a TContext pointing to this TDirectory object.
void RecursiveRemove(TObject *obj) override
Recursively remove object from a Directory.
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.
TString fPathBuffer
Definition: TDirectory.h:92
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
void BuildDirectory(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
Definition: TDirectory.cxx:237
TUUID fUUID
Definition: TDirectory.h:91
static Bool_t fgAddDirectory
MSVC doesn't support = ATOMIC_FLAG_INIT;.
Definition: TDirectory.h:98
TDirectory * GetMotherDir() const
Definition: TDirectory.h:162
static void EncodeNameCycle(char *buffer, const char *name, Short_t cycle)
Encode the name and cycle into buffer like: "aap;2".
virtual const char * GetPathStatic() const
Returns the full path of the directory.
Definition: TDirectory.cxx:949
TObject * fMother
Definition: TDirectory.h:89
void Browse(TBrowser *b) override
Browse the content of the directory.
Definition: TDirectory.cxx:215
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:149
virtual void pwd() const
Print the path of the directory.
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
Definition: TDirectory.cxx:868
virtual TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE)
Clone an object.
Definition: TDirectory.cxx:328
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
void RegisterContext(TContext *ctxt)
Register a TContext pointing to this TDirectory object.
TList * fList
Definition: TDirectory.h:90
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
void Paint(Option_t *option="") override
Paint all objects in the directory.
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
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:819
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:575
virtual TObjLink * FirstLink() const
Definition: TList.h:108
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:761
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
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 const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:492
void ResetBit(UInt_t f)
Definition: TObject.h:171
@ kCanDelete
if object in a list can be deleted
Definition: TObject.h:58
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2821
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2829
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2725
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
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:2077
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
const char * Data() const
Definition: TString.h:364
@ kBoth
Definition: TString.h:262
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Bool_t IsNull() const
Definition: TString.h:402
TString & Append(const char *cs)
Definition: TString.h:559
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
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:1287
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:115
@ kDirectoryThreadSlot
Definition: TThreadSlots.h:31
@ kExactMatch
Definition: TDictionary.h:156
static constexpr double s
TCanvas * slash()
Definition: slash.C:1
auto * m
Definition: textangle.C:8