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