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