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 "strlcpy.h"
12#include "TDirectory.h"
13#include "TBuffer.h"
14#include "TClassTable.h"
15#include "TInterpreter.h"
16#include "THashList.h"
17#include "TBrowser.h"
18#include "TROOT.h"
19#include "TError.h"
20#include "TClass.h"
21#include "TRegexp.h"
22#include "TSystem.h"
23#include "TVirtualMutex.h"
24#include "TThreadSlots.h"
25#include "TMethod.h"
26
27#include "TSpinLockGuard.h"
28
29#include <algorithm>
30#include <limits>
31#include <cstdlib>
32#include <cstring>
33
34const Int_t kMaxLen = 2048;
35
36static std::atomic_flag *GetCurrentDirectoryLock()
37{
38 thread_local std::atomic_flag gDirectory_lock = ATOMIC_FLAG_INIT;
39 return &gDirectory_lock;
40}
41
42/** \class TDirectory
43\ingroup Base
44
45Describe directory structure in memory.
46*/
47
48
49////////////////////////////////////////////////////////////////////////////////
50/// Directory default constructor.
51
53{
54 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
55 std::atomic_flag_clear( &fSpinLock );
56}
57
58////////////////////////////////////////////////////////////////////////////////
59/// Create a new Directory.
60///
61/// A new directory with name,title is created in the current directory
62/// The directory header information is immediately saved in the file
63/// A new key is added in the parent directory
64///
65/// When this constructor is called from a class directly derived
66/// from TDirectory, the third argument classname MUST be specified.
67/// In this case, classname must be the name of the derived class.
68///
69/// Note that the directory name cannot contain slashes.
70
71TDirectory::TDirectory(const char *name, const char *title, Option_t * /*classname*/, TDirectory* initMotherDir)
72 : TNamed(name, title)
73{
74 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
75 std::atomic_flag_clear( &fSpinLock );
76
78
79 if (strchr(name,'/')) {
80 ::Error("TDirectory::TDirectory","directory name (%s) cannot contain a slash", name);
81 gDirectory = nullptr;
82 return;
83 }
84 if (strlen(GetName()) == 0) {
85 ::Error("TDirectory::TDirectory","directory name cannot be \"\"");
86 gDirectory = nullptr;
87 return;
88 }
89
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Destructor.
95
97{
98 // Use gROOTLocal to avoid triggering undesired initialization of gROOT.
99 // For example in compiled C++ programs that don't use it directly.
101 delete fList;
102 return; //when called by TROOT destructor
103 }
104
105 if (fList) {
106 if (!fList->IsUsingRWLock())
107 Fatal("~TDirectory","In %s:%p the fList (%p) is not using the RWLock\n",
108 GetName(),this,fList);
109 fList->Delete("slow");
111 }
112
114
116
117 if (mom) {
118 mom->Remove(this);
119 }
120
121 if (gDebug) {
122 Info("~TDirectory", "dtor called for %s", GetName());
123 }
124}
125
126
127////////////////////////////////////////////////////////////////////////////////
128/// Set the current directory to null.
129/// This is called from the TContext destructor. Since the destructor is
130/// inline, we do not want to have it directly use a global variable.
131
133{
134 gDirectory = nullptr;
135}
136
137////////////////////////////////////////////////////////////////////////////////
138/// Destructor.
139///
140/// Reset the current directory to its previous state.
141
143{
144 fActiveDestructor = true;
145 if (fDirectory) {
146 // UnregisterContext must not be virtual to allow
147 // this to work even with fDirectory set to nullptr.
148 (*fDirectory).UnregisterContext(this);
149 // While we were waiting for the lock, the TDirectory
150 // may have been deleted by another thread, so
151 // we need to recheck the value of fDirectory.
152 if (fDirectory)
153 (*fDirectory).cd();
154 else
155 CdNull();
156 } else {
157 CdNull();
158 }
159 fActiveDestructor = false;
160 while(fDirectoryWait);
161}
162
163// Mask deprecation warnings to allow for deprecating the fgAddDirectory bit.
164#ifdef _MSC_VER
165#pragma warning(push)
166#pragma warning(disable : 4996)
167#else
168#pragma GCC diagnostic push
169#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
170#endif
171
172////////////////////////////////////////////////////////////////////////////////
173/// Set the value returned by TDirectory::AddDirectoryStatus().
174/// \deprecated This function is not used in ROOT.
175
176void TDirectory::AddDirectory(Bool_t add)
177{
178 fgAddDirectory = add;
179}
180
181////////////////////////////////////////////////////////////////////////////////
182/// Return the value set by TDirectory::AddDirectory.
183/// \deprecated This function is not used in ROOT.
184
185Bool_t TDirectory::AddDirectoryStatus()
186{
187 return fgAddDirectory;
188}
189
190#ifdef _MSC_VER
191#pragma warning(pop)
192#else
193#pragma GCC diagnostic pop
194#endif
195
196////////////////////////////////////////////////////////////////////////////////
197/// Append object to this directory.
198///
199/// If `replace` is true:
200/// remove any existing objects with the same name (if the name is not "")
201
202void TDirectory::Append(TObject *obj, Bool_t replace /* = kFALSE */)
203{
204 if (!obj || !fList) return;
205
206 if (replace && obj->GetName() && obj->GetName()[0]) {
207 TObject *old;
208 while (nullptr != (old = GetList()->FindObject(obj->GetName()))) {
209 if (obj != old) {
210 Warning("Append", "Replacing existing %s: %s (Potential memory leak).", obj->IsA()->GetName(),
211 obj->GetName());
212 }
213 ROOT::DirAutoAdd_t func = old->IsA()->GetDirectoryAutoAdd();
214 if (func) {
215 func(old,nullptr);
216 } else {
217 Remove(old);
218 }
219 }
220 }
221
222 fList->Add(obj);
223 // A priori, a `TDirectory` object is assumed to not have shared ownership.
224 // If it is, let's rely on the user to update the bit.
225 if (!dynamic_cast<TDirectory*>(obj))
226 obj->SetBit(kMustCleanup);
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Browse the content of the directory.
231
233{
234 if (b) {
235 TObject *obj = nullptr;
237
238 cd();
239
240 //Add objects that are only in memory
241 while ((obj = nextin())) {
242 b->Add(obj, obj->GetName());
243 }
244 }
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Initialise directory to defaults.
249///
250/// If directory is created via default ctor (when dir is read from file)
251/// don't add it here to the directory since its name is not yet known.
252/// It will be added to the directory in TKey::ReadObj().
253
255{
256 fList = new THashList(100,50);
257 fList->UseRWLock();
260
261 // Build is done and is the last part of the constructor (and is not
262 // being called from the derived classes) so we can publish.
263 if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// Clean the pointers to this object (gDirectory, TContext, etc.).
268
270{
271 std::vector<TContext*> extraWait;
272
273 {
275
276 while (fContext) {
277 const auto next = fContext->fNext;
278 const auto ctxt = fContext;
279 ctxt->fDirectoryWait = true;
280
281 // If fDirectory is assigned to gROOT but we do not unregister ctxt
282 // (and/or stop unregister for gROOT) then ~TContext will call Unregister on gROOT.
283 // Then unregister of this ctxt and its Previous context can actually be run
284 // in parallel (this takes the gROOT lock, Previous takes the lock of fDirectory)
285 // and thus step on each other.
286 ctxt->fDirectory = nullptr; // Can not be gROOT
287
288 if (ctxt->fActiveDestructor) {
289 extraWait.push_back(fContext);
290 } else {
291 ctxt->fDirectoryWait = false;
292 }
293 fContext = next;
294 }
295
296 // Now loop through the set of thread local 'gDirectory' that
297 // have a one point or another pointed to this directory.
298 for (auto &ptr : fGDirectories) {
299 // If the thread local gDirectory still point to this directory
300 // we need to reset it using the following sematic:
301 // we fall back to the mother/owner of this directory or gROOTLocal
302 // if there is no parent or nullptr if the current object is gROOTLocal.
303 if (ptr->load() == this) {
304 TDirectory *next = GetMotherDir();
305 if (!next || next == this) {
306 if (this == ROOT::Internal::gROOTLocal) { /// in that case next == this.
307 next = nullptr;
308 } else {
310 }
311 } else {
312 // We can not use 'cd' as this would access the current thread
313 // rather than the thread corresponding to that gDirectory.
314 next->RegisterGDirectory(ptr);
315 }
316 // Actually do the update of the thread local gDirectory
317 // using its object specific lock.
318 auto This = this;
319 ptr->compare_exchange_strong(This, next);
320 }
321 }
322 }
323 for(auto &&context : extraWait) {
324 // Wait until the TContext is done spinning
325 // over the lock.
326 while(context->fActiveDestructor);
327 // And now let the TContext destructor finish.
328 context->fDirectoryWait = false;
329 }
330
331 // Wait until all register attempts are done.
332 while(fContextPeg) {}
333
334}
335
336////////////////////////////////////////////////////////////////////////////////
337/// Fast execution of 'new TBufferFile(TBuffer::kWrite,10000), without having
338/// a compile time circular dependency ... alternatively we could (should?)
339/// introduce yet another abstract interface.
340
342{
343 typedef void (*tcling_callfunc_Wrapper_t)(void*, int, void**, void*);
344 static tcling_callfunc_Wrapper_t creator = nullptr;
345 if (!creator) {
347 TClass *c = TClass::GetClass("TBufferFile");
348 TMethod *m = c->GetMethodWithPrototype("TBufferFile","TBuffer::EMode,Int_t",kFALSE,ROOT::kExactMatch);
349 creator = (tcling_callfunc_Wrapper_t)( m->InterfaceMethod() );
350 }
352 Int_t size = 10000;
353 void *args[] = { &mode, &size };
355 creator(nullptr,2,args,&result);
356 return result;
357}
358
359////////////////////////////////////////////////////////////////////////////////
360/// Clone an object.
361/// This function is called when the directory is not a TDirectoryFile.
362/// This version has to load the I/O package, hence via Cling.
363///
364/// If autoadd is true and if the object class has a
365/// DirectoryAutoAdd function, it will be called at the end of the
366/// function with the parameter gDirectory. This usually means that
367/// the object will be appended to the current ROOT directory.
368
370{
371 // if no default ctor return immediately (error issued by New())
372 char *pobj = (char*)obj->IsA()->New();
373 if (!pobj) {
374 Fatal("CloneObject","Failed to create new object");
375 return nullptr;
376 }
377
378 Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
379 if (baseOffset==-1) {
380 // cl does not inherit from TObject.
381 // Since this is not supported in this function, the only reason we could reach this code
382 // is because something is screwed up in the ROOT code.
383 Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
384 obj->IsA()->GetName());
385 }
387
388 //create a buffer where the object will be streamed
389 //We are forced to go via the I/O package (ie TBufferFile).
390 //Invoking TBufferFile via CINT will automatically load the I/O library
391 TBuffer *buffer = R__CreateBuffer();
392 if (!buffer) {
393 Fatal("CloneObject","Not able to create a TBuffer!");
394 return nullptr;
395 }
396 buffer->MapObject(obj); //register obj in map to handle self reference
397 const_cast<TObject*>(obj)->Streamer(*buffer);
398
399 // read new object from buffer
400 buffer->SetReadMode();
401 buffer->ResetMap();
402 buffer->SetBufferOffset(0);
403 buffer->MapObject(newobj); //register obj in map to handle self reference
404 newobj->Streamer(*buffer);
405 newobj->ResetBit(kIsReferenced);
406 newobj->ResetBit(kCanDelete);
407
408 delete buffer;
409 if (autoadd) {
410 ROOT::DirAutoAdd_t func = obj->IsA()->GetDirectoryAutoAdd();
411 if (func) {
412 func(newobj,this);
413 }
414 }
415 return newobj;
416}
417
418////////////////////////////////////////////////////////////////////////////////
419/// Return the (address of) a shared pointer to the struct holding the
420/// actual thread local gDirectory pointer and the atomic_flag for its lock.
422{
424
425 // Note in previous implementation every time gDirectory was lookup in
426 // a thread, if it was set to nullptr it would be reset to gROOT. This
427 // was unexpected and this routine is not re-introducing this issue.
428 thread_local shared_ptr_type currentDirectory =
429 std::make_shared<shared_ptr_type::element_type>(ROOT::Internal::gROOTLocal);
430
431 return currentDirectory;
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// Return the current directory for the current thread.
436
437std::atomic<TDirectory*> &TDirectory::CurrentDirectory()
438{
439 return *GetSharedLocalCurrentDirectory().get();
440}
441
442////////////////////////////////////////////////////////////////////////////////
443/// Find a directory using apath.
444/// It apath is null or empty, returns "this" directory.
445/// Otherwise use apath to find a directory.
446/// The absolute path syntax is: `file.root:/dir1/dir2`
447///
448/// where file.root is the file and /dir1/dir2 the desired subdirectory
449/// in the file. Relative syntax is relative to "this" directory. E.g: `../aa`.
450/// Returns 0 in case path does not exist.
451/// If printError is true, use Error with 'funcname' to issue an error message.
452
454 Bool_t printError, const char *funcname)
455{
456 Int_t nch = 0;
457 if (apath) nch = strlen(apath);
458 if (!nch) {
459 return this;
460 }
461
462 if (funcname==nullptr || strlen(funcname)==0) funcname = "GetDirectory";
463
464 TDirectory *result = this;
465
466 char *path = new char[nch+1]; path[0] = 0;
467 if (nch) strlcpy(path,apath,nch+1);
468 char *s = (char*)strrchr(path, ':');
469 if (s) {
470 *s = '\0';
472 TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
473 if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
474 if (s) *s = ':';
475 if (f) {
476 result = f;
477 if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
478 delete [] path; return result;
479 } else {
480 if (printError) Error(funcname, "No such file %s", path);
481 delete [] path; return nullptr;
482 }
483 }
484
485 // path starts with a slash (assumes current file)
486 if (path[0] == '/') {
488 result = td->GetDirectory(path+1,printError,funcname);
489 delete [] path; return result;
490 }
491
492 TObject *obj;
493 char *slash = (char*)strchr(path,'/');
494 if (!slash) { // we are at the lowest level
495 if (!strcmp(path, "..")) {
497 delete [] path; return result;
498 }
499 obj = Get(path);
500 if (!obj) {
501 if (printError) Error(funcname,"Unknown directory %s", path);
502 delete [] path; return nullptr;
503 }
504
505 //Check return object is a directory
506 if (!obj->InheritsFrom(TDirectory::Class())) {
507 if (printError) Error(funcname,"Object %s is not a directory", path);
508 delete [] path; return nullptr;
509 }
510 delete [] path; return (TDirectory*)obj;
511 }
512
513 TString subdir(path);
514 slash = (char*)strchr(subdir.Data(),'/');
515 *slash = 0;
516 //Get object with path from current directory/file
517 if (!strcmp(subdir, "..")) {
519 if (mom)
520 result = mom->GetDirectory(slash+1,printError,funcname);
521 delete [] path; return result;
522 }
523 obj = Get(subdir);
524 if (!obj) {
525 if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
526 delete [] path; return nullptr;
527 }
528
529 //Check return object is a directory
530 if (!obj->InheritsFrom(TDirectory::Class())) {
531 if (printError) Error(funcname,"Object %s is not a directory", subdir.Data());
532 delete [] path; return nullptr;
533 }
534 result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
535 delete [] path; return result;
536}
537
538////////////////////////////////////////////////////////////////////////////////
539/// Change current directory to "this" directory.
540///
541/// Returns kTRUE (it's guaranteed to succeed).
542
553
554////////////////////////////////////////////////////////////////////////////////
555/// Change current directory to "this" directory or to the directory described
556/// by the path if given one.
557///
558/// Using path one can change the current directory to "path". The absolute path
559/// syntax is: `file.root:/dir1/dir2`
560/// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
561/// in the file.
562///
563/// Relative syntax is relative to "this" directory. E.g: `../aa`.
564///
565/// Returns kTRUE in case of success.
566
567Bool_t TDirectory::cd(const char *path)
568{
569 return cd1(path);
570}
571
572////////////////////////////////////////////////////////////////////////////////
573/// Change current directory to "this" directory or to the directory described
574/// by the path if given one.
575///
576/// Using path one can
577/// change the current directory to "path". The absolute path syntax is:
578/// `file.root:/dir1/dir2`
579/// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
580/// in the file.
581///
582/// Relative syntax is relative to "this" directory. E.g: `../aa`.
583///
584/// Returns kFALSE in case path does not exist.
585
587{
588 if (!apath || !apath[0])
589 return this->cd();
590
592 if (where) {
593 where->cd();
594 return kTRUE;
595 }
596 return kFALSE;
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Change current directory to "path". The absolute path syntax is:
601/// `file.root:/dir1/dir2`
602/// where file.root is the file and `/dir1/dir2 the desired subdirectory
603/// in the file.
604/// Relative syntax is relative to the current directory `gDirectory`, e.g.: `../aa`.
605///
606/// Returns kTRUE in case of success.
607
608Bool_t TDirectory::Cd(const char *path)
609{
610 return Cd1(path);
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Change current directory to "path". The path syntax is:
615/// `file.root:/dir1/dir2`
616/// where file.root is the file and `/dir1/dir2` the desired subdirectory
617/// in the file.
618/// Relative syntax is relative to the current directory `gDirectory`, e.g.: `../aa`.
619///
620/// Returns kFALSE in case path does not exist.
621
623{
624 // null path is always true (i.e. stay in the current directory)
625 if (!apath || !apath[0])
626 return kTRUE;
627
628 TDirectory *where = gDirectory->GetDirectory(apath, kTRUE, "Cd");
629 if (where) {
630 where->cd();
631 return kTRUE;
632 }
633 return kFALSE;
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Delete all objects from a Directory list.
638
640{
641 if (fList) fList->Clear();
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Delete all objects from memory and directory structure itself.
646/// if option is "slow", iterate through the containers in a way to can handle
647/// 'external' modification (induced by recursions)
648/// if option is "nodelete", write the TDirectory but do not delete the contained
649/// objects.
651{
652 if (!fList) {
653 return;
654 }
655
656 // Save the directory key list and header
657 Save();
658
659 Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
660
661 if (!nodelete) {
662 Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE;
663 if (!slow) {
664 // Check if it is wise to use the fast deletion path.
666 while (lnk) {
667 if (lnk->GetObject()->IsA() == TDirectory::Class()) {
668 slow = kTRUE;
669 break;
670 }
671 lnk = lnk->Next();
672 }
673 }
674
675 // Delete objects from directory list, this in turn, recursively closes all
676 // sub-directories (that were allocated on the heap)
677 // if this dir contains subdirs, we must use the slow option for Delete!
678 // we must avoid "slow" as much as possible, in particular Delete("slow")
679 // with a large number of objects (eg >10^5) would take for ever.
680 if (slow) fList->Delete("slow");
681 else fList->Delete();
682 }
683
685}
686
687////////////////////////////////////////////////////////////////////////////////
688/// Delete all objects from memory.
689
691{
692 fList->Delete("slow");
693}
694
695////////////////////////////////////////////////////////////////////////////////
696/// Delete Objects or/and keys in a directory.
697///
698/// - namecycle has the format name;cycle
699/// - namecycle = "" same as namecycle ="T*"
700/// - name = * means all
701/// - cycle = * means all cycles (memory and keys)
702/// - cycle = "" or cycle = 9999 ==> apply to a memory object
703/// When name=* use T* to delete subdirectories also
704///
705/// To delete one directory, you must specify the directory cycle,
706/// eg. `file.Delete("dir1;1");`
707///
708/// examples:
709/// - foo : delete object named foo in memory
710/// - foo* : delete all objects with a name starting with foo
711/// - foo;1 : delete cycle 1 of foo on file
712/// - foo;* : delete all cycles of foo on file and also from memory
713/// - *;2 : delete all objects on file having the cycle 2
714/// - *;* : delete all objects from memory and file
715/// - T*;* : delete all objects from memory and file and all subdirectories
716
718{
719 if (gDebug)
720 Info("Delete","Call for this = %s namecycle = %s",
721 GetName(), (namecycle ? namecycle : "null"));
722
724 Short_t cycle;
725 char name[kMaxLen];
727
728 Int_t deleteall = 0;
729 Int_t deletetree = 0;
730 if(strcmp(name,"*") == 0) deleteall = 1;
731 if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
732 if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
733 if(namecycle==nullptr || !namecycle[0]){ deleteall = 1; deletetree = 1;}
734 TRegexp re(name,kTRUE);
735 TString s;
736 Int_t deleteOK = 0;
737
738//*-*---------------------Case of Object in memory---------------------
739// ========================
740 if (cycle >= 9999 ) {
741 TNamed *idcur;
742 TIter next(fList);
743 while ((idcur = (TNamed *) next())) {
744 deleteOK = 0;
745 s = idcur->GetName();
746 if (deleteall || s.Index(re) != kNPOS) {
747 deleteOK = 1;
748 if (idcur->IsA() == TDirectory::Class()) {
749 deleteOK = 2;
750 if (!deletetree && deleteall) deleteOK = 0;
751 }
752 }
753 if (deleteOK != 0) {
755 if (deleteOK==2) {
756 // read subdirectories to correctly delete them
757 if (deletetree)
758 ((TDirectory*) idcur)->ReadAll("dirs");
759 idcur->Delete(deletetree ? "T*;*" : "*");
760 delete idcur;
761 } else
762 idcur->Delete(name);
763 }
764 }
765 }
766}
767
768////////////////////////////////////////////////////////////////////////////////
769/// Fill Graphics Structure and Paint.
770///
771/// Loop on all objects (memory or file) and all subdirectories
772
774{
775 fList->R__FOR_EACH(TObject,Draw)(option);
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Find object in the list of memory objects.
780
782{
783 return fList->FindObject(obj);
784}
785
786////////////////////////////////////////////////////////////////////////////////
787/// Find object by name in the list of memory objects.
788
790{
791 return fList->FindObject(name);
792}
793
794////////////////////////////////////////////////////////////////////////////////
795/// Find object by name in the list of memory objects of the current
796/// directory or its sub-directories.
797/// After this call the current directory is not changed.
798/// To automatically set the current directory where the object is found,
799/// use FindKeyAny(aname)->ReadObj().
800
802{
803 //object may be already in the list of objects in memory
804 TObject *obj = fList->FindObject(aname);
805 if (obj) return obj;
806
807 //try with subdirectories
808 TIter next(fList);
809 while( (obj = next()) ) {
810 if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
811 TDirectory* subdir = static_cast<TDirectory*>(obj);
812 TObject *subobj = subdir->TDirectory::FindObjectAny(aname); // Explicitly recurse into _this_ exact function.
813 if (subobj) {
814 return subobj;
815 }
816 }
817 }
818 return nullptr;
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// Return pointer to object identified by namecycle.
823///
824/// namecycle has the format name;cycle
825/// - name = * is illegal, cycle = * is illegal
826/// - cycle = "" or cycle = 9999 ==> apply to a memory object
827///
828/// examples:
829/// - foo : get object named foo in memory
830/// if object is not in memory, try with highest cycle from file
831/// - foo;1 : get cycle 1 of foo on file
832///
833/// The retrieved object should in principle derive from TObject.
834/// If not, the function TDirectory::GetObject should be called.
835/// However, this function will still work for a non-TObject, providing that
836/// the calling application cast the return type to the correct type (which
837/// is the actual type of the object).
838///
839/// NOTE:
840///
841/// The method GetObject offer better protection and avoid the need
842/// for any cast:
843/// ~~~ {.cpp}
844/// MyClass *obj;
845/// directory->GetObject("some object",obj);
846/// if (obj) { ... the object exist and inherits from MyClass ... }
847/// ~~~
848///
849/// VERY IMPORTANT NOTE:
850///
851/// In case the class of this object derives from TObject but not
852/// as a first inheritance, one must use dynamic_cast<>().
853/// #### Example 1: Normal case:
854/// ~~~ {.cpp}
855/// class MyClass : public TObject, public AnotherClass
856/// ~~~
857/// then on return, one can do:
858/// ~~~ {.cpp}
859/// MyClass *obj = (MyClass*)directory->Get("some object of MyClass");
860/// ~~~
861/// #### Example 2: Special case:
862/// ~~~ {.cpp}
863/// class MyClass : public AnotherClass, public TObject
864/// ~~~
865/// then on return, one must do:
866/// ~~~ {.cpp}
867/// MyClass *obj = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
868/// ~~~
869/// Of course, dynamic_cast<> can also be used in the example 1.
870
872{
873 Short_t cycle;
874 char name[kMaxLen];
875
877 char *namobj = name;
878 Int_t nch = strlen(name);
879 for (Int_t i = nch-1; i > 0; i--) {
880 if (name[i] == '/') {
881 name[i] = 0;
883 namobj = name + i + 1;
884 name[i] = '/';
885 return dirToSearch ? dirToSearch->Get(namobj) : nullptr;
886 }
887 }
888
889//*-*---------------------Case of Object in memory---------------------
890// ========================
892 if (idcur) {
893 if (idcur==this && strlen(namobj)!=0) {
894 // The object has the same name has the directory and
895 // that's what we picked-up! We just need to ignore
896 // it ...
897 idcur = nullptr;
898 } else if (cycle == 9999) {
899 return idcur;
900 } else {
901 if (idcur->InheritsFrom(TCollection::Class()))
902 idcur->Delete(); // delete also list elements
903 delete idcur;
904 idcur = nullptr;
905 }
906 }
907 return idcur;
908}
909
910////////////////////////////////////////////////////////////////////////////////
911/// Return pointer to object identified by namecycle.
912/// The returned object may or may not derive from TObject.
913///
914/// - namecycle has the format name;cycle
915/// - name = * is illegal, cycle = * is illegal
916/// - cycle = "" or cycle = 9999 ==> apply to a memory object
917///
918/// VERY IMPORTANT NOTE:
919///
920/// The calling application must cast the returned object to
921/// the final type, e.g.
922/// ~~~ {.cpp}
923/// MyClass *obj = (MyClass*)directory->GetObject("some object of MyClass");
924/// ~~~
925
927{
928 return GetObjectChecked(namecycle,(TClass *)nullptr);
929}
930
931////////////////////////////////////////////////////////////////////////////////
932/// See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
933
934void *TDirectory::GetObjectChecked(const char *namecycle, const char* classname)
935{
936 return GetObjectChecked(namecycle, TClass::GetClass(classname));
937}
938
939
940////////////////////////////////////////////////////////////////////////////////
941/// Return pointer to object identified by namecycle if and only if the actual
942/// object is a type suitable to be stored as a pointer to a "expectedClass"
943/// If expectedClass is null, no check is performed.
944///
945/// namecycle has the format `name;cycle`
946/// - name = * is illegal, cycle = * is illegal
947/// - cycle = "" or cycle = 9999 ==> apply to a memory object
948///
949/// VERY IMPORTANT NOTE:
950///
951/// The calling application must cast the returned pointer to
952/// the type described by the 2 arguments (i.e. cl):
953/// ~~~ {.cpp}
954/// MyClass *obj = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
955/// ~~~
956/// Note: We recommend using the method TDirectory::GetObject:
957/// ~~~ {.cpp}
958/// MyClass *obj = nullptr;
959/// directory->GetObject("some object inheriting from MyClass",obj);
960/// if (obj) { ... we found what we are looking for ... }
961/// ~~~
962
964{
965 Short_t cycle;
966 char name[kMaxLen];
967
969 char *namobj = name;
970 Int_t nch = strlen(name);
971 for (Int_t i = nch-1; i > 0; i--) {
972 if (name[i] == '/') {
973 name[i] = 0;
975 namobj = name + i + 1;
976 name[i] = '/';
977 if (dirToSearch) {
978 return dirToSearch->GetObjectChecked(namobj, expectedClass);
979 } else {
980 return nullptr;
981 }
982 }
983 }
984
985//*-*---------------------Case of Object in memory---------------------
986// ========================
987 if (!expectedClass || expectedClass->IsTObject()) {
989 if (objcur) {
990 if (objcur==this && strlen(namobj)!=0) {
991 // The object has the same name has the directory and
992 // that's what we picked-up! We just need to ignore
993 // it ...
994 objcur = nullptr;
995 } else if (cycle == 9999) {
996 // Check type
997 if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return nullptr;
998 else return objcur;
999 } else {
1000 if (objcur->InheritsFrom(TCollection::Class()))
1001 objcur->Delete(); // delete also list elements
1002 delete objcur;
1003 objcur = nullptr;
1004 }
1005 }
1006 }
1007
1008 return nullptr;
1009}
1010
1011////////////////////////////////////////////////////////////////////////////////
1012/// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
1013/// The returned path will be re-used by the next call to GetPath().
1014
1015const char *TDirectory::GetPathStatic() const
1016{
1017 static char *path = nullptr;
1018 const int kMAXDEPTH = 128;
1019 const TDirectory *d[kMAXDEPTH];
1020 const TDirectory *cur = this;
1021 int depth = 0, len = 0;
1022
1023 d[depth++] = cur;
1024 len = strlen(cur->GetName()) + 1; // +1 for the /
1025
1026 while (cur->fMother && depth < kMAXDEPTH) {
1027 cur = (TDirectory *)cur->fMother;
1028 d[depth++] = cur;
1029 len += strlen(cur->GetName()) + 1;
1030 }
1031
1032 if (path) delete [] path;
1033 path = new char[len+2];
1034
1035 for (int i = depth-1; i >= 0; i--) {
1036 if (i == depth-1) { // file or TROOT name
1037 strlcpy(path, d[i]->GetName(),len+2);
1038 strlcat(path, ":",len+2);
1039 if (i == 0) strlcat(path, "/",len+2);
1040 } else {
1041 strlcat(path, "/",len+2);
1042 strlcat(path, d[i]->GetName(),len+2);
1043 }
1044 }
1045
1046 return path;
1047}
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
1051/// The returned path will be re-used by the next call to GetPath().
1052
1053const char *TDirectory::GetPath() const
1054{
1056
1057 if (!GetMotherDir()) // case of file
1058 fPathBuffer.Append("/");
1059
1060 return fPathBuffer.Data();
1061}
1062
1063////////////////////////////////////////////////////////////////////////////////
1064/// Recursive method to fill full path for directory.
1065
1067{
1069 if (mom) {
1070 mom->FillFullPath(buf);
1071 buf += "/";
1072 buf += GetName();
1073 } else {
1074 buf = GetName();
1075 buf += ":";
1076 }
1077}
1078
1079////////////////////////////////////////////////////////////////////////////////
1080/// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1081///
1082/// @param name the name or hierarchy of the subdirectory ("a" or "a/b/c")
1083/// @param title the title
1084/// @param returnExistingDirectory if key-name is already existing, the returned
1085/// value points to preexisting sub-directory if true and to `nullptr` if false.
1086/// @return a pointer to the created sub-directory, not to the top sub-directory
1087/// of the hierarchy (in the above example, the returned TDirectory * points
1088/// to "c"). In case of an error, it returns `nullptr`. In case of a preexisting
1089/// sub-directory (hierarchy) with the requested name, the return value depends
1090/// on the parameter returnExistingDirectory.
1091///
1092/// In particular, the steps to create first a/b/c and then a/b/d without receiving
1093/// errors are:
1094/// ~~~ {.cpp}
1095/// TFile * file = new TFile("afile","RECREATE");
1096/// file->mkdir("a");
1097/// file->cd("a");
1098/// gDirectory->mkdir("b/c");
1099/// gDirectory->cd("b");
1100/// gDirectory->mkdir("d");
1101/// ~~~
1102/// or
1103/// ~~~ {.cpp}
1104/// TFile * file = new TFile("afile","RECREATE");
1105/// file->mkdir("a");
1106/// file->cd("a");
1107/// gDirectory->mkdir("b/c");
1108/// gDirectory->mkdir("b/d", "", true);
1109/// ~~~
1110
1112{
1115 if (existingdir)
1116 return existingdir;
1117 }
1118 if (!name || !title || !name[0]) return nullptr;
1119 if (!title[0]) title = name;
1120 if (const char *slash = strchr(name,'/')) {
1122 char *workname = new char[size+1];
1124 workname[size] = 0;
1127 if (!tmpdir)
1128 tmpdir = mkdir(workname,title);
1129 delete[] workname;
1130 if (!tmpdir) return nullptr;
1131 return tmpdir->mkdir(slash+1);
1132 }
1133
1135
1136 return new TDirectory(name, title, "", this);
1137}
1138
1139////////////////////////////////////////////////////////////////////////////////
1140/// List Directory contents.
1141///
1142/// Indentation is used to identify the directory tree
1143/// Subdirectories are listed first, then objects in memory.
1144///
1145/// The option can has the following format:
1146///
1147/// [<regexp>]
1148///
1149/// The `<regexp>` will be used to match the name of the objects.
1150/// By default memory and disk objects are listed.
1151
1153{
1156
1158 TString opt = opta.Strip(TString::kBoth);
1160 TString reg = "*";
1161 if (opt.BeginsWith("-m")) {
1162 if (opt.Length() > 2)
1163 reg = opt(2,opt.Length());
1164 } else if (opt.BeginsWith("-d")) {
1165 memobj = kFALSE;
1166 if (opt.Length() > 2)
1167 reg = opt(2,opt.Length());
1168 } else if (!opt.IsNull())
1169 reg = opt;
1170
1171 TRegexp re(reg, kTRUE);
1172
1173 if (memobj) {
1174 TObject *obj;
1176 while ((obj = (TObject *) nextobj())) {
1177 TString s = obj->GetName();
1178 if (s.Index(re) == kNPOS) continue;
1179 obj->ls(option); //*-* Loop on all the objects in memory
1180 }
1181 }
1183}
1184
1185////////////////////////////////////////////////////////////////////////////////
1186/// Paint all objects in the directory.
1187
1189{
1190 fList->R__FOR_EACH(TObject,Paint)(option);
1191}
1192
1193////////////////////////////////////////////////////////////////////////////////
1194/// Print all objects in the directory.
1195
1197{
1198 fList->R__FOR_EACH(TObject,Print)(option);
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// Print the path of the directory.
1203
1205{
1206 Printf("%s", GetPath());
1207}
1208
1209////////////////////////////////////////////////////////////////////////////////
1210/// Recursively remove object from a Directory.
1211
1213{
1214 if (fList)
1215 fList->RecursiveRemove(obj);
1216}
1217
1218////////////////////////////////////////////////////////////////////////////////
1219/// Remove an object from the in-memory list.
1220
1222{
1223 TObject *p = nullptr;
1224 if (fList) {
1225 p = fList->Remove(obj);
1226 }
1227 return p;
1228}
1229
1230////////////////////////////////////////////////////////////////////////////////
1231/// Removes subdirectory from the directory
1232/// When directory is deleted, all keys in all subdirectories will be
1233/// read first and deleted from file (if exists)
1234/// Equivalent call is Delete("name;*");
1235
1236void TDirectory::rmdir(const char *name)
1237{
1238 if ((name==nullptr) || (*name==0)) return;
1239
1240 TString mask(name);
1241 mask+=";*";
1242 Delete(mask);
1243}
1244
1245////////////////////////////////////////////////////////////////////////////////
1246/// Save object in filename,
1247/// if filename is `nullptr` or "", a file with "<objectname>.root" is created.
1248/// The name of the key is the object name.
1249/// By default new file will be created. Using option "a", one can append object
1250/// to the existing ROOT file.
1251/// If the operation is successful, it returns the number of bytes written to the file
1252/// otherwise it returns 0.
1253/// By default a message is printed. Use option "q" to not print the message.
1254/// If filename contains ".json" extension, JSON representation of the object
1255/// will be created and saved in the text file. Such file can be used in
1256/// JavaScript ROOT (https://root.cern/js/) to display object in web browser
1257/// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1258
1260{
1261 // option can contain single letter args: "a" for append, "q" for quiet in any combinations
1262
1263 if (!obj) return 0;
1264 Int_t nbytes = 0;
1265 TString fname, opt = option, cmd;
1266 if (filename && *filename)
1267 fname = filename;
1268 else
1269 fname.Form("%s.root", obj->GetName());
1270 opt.ToLower();
1271
1272 if (fname.Index(".json") > 0) {
1273 cmd.Form("TBufferJSON::ExportToFile(\"%s\", (TObject *) 0x%zx, \"%s\");", fname.Data(), (size_t) obj, (option ? option : ""));
1274 nbytes = gROOT->ProcessLine(cmd);
1275 } else {
1276 cmd.Form("TFile::Open(\"%s\",\"%s\");", fname.Data(), opt.Contains("a") ? "update" : "recreate");
1277 TContext ctxt; // The TFile::Open will change the current directory.
1278 TDirectory *local = (TDirectory*)gROOT->ProcessLine(cmd);
1279 if (!local) return 0;
1280 nbytes = obj->Write();
1281 delete local;
1282 }
1283 if (!opt.Contains("q") && !gSystem->AccessPathName(fname.Data()))
1284 obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1285 return nbytes;
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// Set the name for directory
1290/// If the directory name is changed after the directory was written once,
1291/// ROOT currently would NOT change the name of correspondent key in the
1292/// mother directory.
1293/// DO NOT use this method to 'rename a directory'.
1294/// Renaming a directory is currently NOT supported.
1295
1297{
1299}
1300
1301////////////////////////////////////////////////////////////////////////////////
1302/// Decode a namecycle `"aap;2"` contained in the null-terminated string `buffer` into name `"aap"` and cycle `2`.
1303/// The destination buffer size for `name` (including the string terminator) should be specified in
1304/// `namesize`. If `namesize` is too small to contain the full name, the name will be truncated to `namesize`.
1305/// If `namesize == 0` but `name` is not nullptr, this method will assume that `name` points
1306/// to a large enough buffer to hold the name. THIS IS UNSAFE, so you should **always** pass the proper `namesize`!
1307/// If `name` is nullptr, only the cycle will be returned and `namesize` will be ignored.
1308/// @note Edge cases:
1309/// - If the number after the `;` is larger than `SHORT_MAX`, cycle is set to `0`.
1310/// - If name ends with `;*`, cycle is set to 10000`.
1311/// - In all other cases, i.e. when number is not a digit, buffer is a nullptr or buffer does not contain a cycle,
1312/// `cycle` is set to `9999`.
1313/// @return The actual name length, or 0 if `buffer` was a nullptr.
1314
1315size_t TDirectory::DecodeNameCycle(const char *buffer, char *name, Short_t &cycle, const size_t namesize)
1316{
1317 if (!buffer) {
1318 cycle = 9999;
1319 return 0;
1320 }
1321
1322 // Scan the string to find the name length and the semicolon
1323 size_t nameLen = 0;
1324 int semicolonIdx = -1;
1325 {
1326 char ch = buffer[nameLen];
1327 while (ch) {
1328 if (ch == ';') {
1330 break;
1331 }
1332 ++nameLen;
1333 ch = buffer[nameLen];
1334 }
1335 }
1336 assert(semicolonIdx == -1 || semicolonIdx == static_cast<int>(nameLen));
1337
1338 if (name) {
1339 size_t truncatedNameLen = nameLen;
1340 if (namesize) {
1341 // accommodate string terminator
1343 } else {
1344 ::Error("TDirectory::DecodeNameCycle",
1345 "Using unsafe version: invoke this method by specifying the buffer size");
1346 }
1347
1348 strncpy(name, buffer, truncatedNameLen);
1349 name[truncatedNameLen] = '\0';
1350 }
1351
1352 if (semicolonIdx < 0) {
1353 // namecycle didn't contain a cycle
1354 cycle = 9999;
1355 return nameLen;
1356 }
1357
1358 const char *cycleStr = buffer + semicolonIdx + 1;
1359
1360 if (cycleStr[0] == '*') {
1361 cycle = 10000;
1362 } else if (isdigit(cycleStr[0])) {
1363 long parsed = strtol(cycleStr, nullptr, 10);
1364 if (parsed >= static_cast<long>(std::numeric_limits<Short_t>::max()))
1365 cycle = 0;
1366 else
1367 cycle = static_cast<Short_t>(parsed);
1368 } else {
1369 // Either `;` was the last character of the string, or the character following it was invalid.
1370 cycle = 9999;
1371 }
1372
1373 return nameLen;
1374}
1375
1377{
1378 // peg the current directory
1379 TDirectory *current;
1380 {
1382 current = TDirectory::CurrentDirectory().load();
1383 // Don't peg if there is no current directory or if the current
1384 // directory's destruction has already started (in another thread)
1385 // and is waiting for this thread to leave the critical section.
1386 if (!current || !current->IsBuilt())
1387 return;
1388 ++(current->fContextPeg);
1389 }
1390 current->RegisterContext(this);
1391 --(current->fContextPeg);
1392}
1393
1394///////////////////////////////////////////////////////////////////////////////
1395/// Register a TContext pointing to this TDirectory object
1396
1399
1400 if (!IsBuilt() || this == ROOT::Internal::gROOTLocal)
1401 return;
1402 if (fContext) {
1403 TContext *current = fContext;
1404 while(current->fNext) {
1405 current = current->fNext;
1406 }
1407 current->fNext = ctxt;
1408 ctxt->fPrevious = current;
1409 } else {
1410 fContext = ctxt;
1411 }
1412}
1413
1414////////////////////////////////////////////////////////////////////////////////
1415/// Register a std::atomic<TDirectory*> that will soon be pointing to this TDirectory object
1416
1418{
1420 if (std::find(fGDirectories.begin(), fGDirectories.end(), gdirectory_ptr) == fGDirectories.end()) {
1421 fGDirectories.emplace_back(gdirectory_ptr);
1422 }
1423 // FIXME:
1424 // globalptr->load()->fGDirectories will still contain globalptr, but we cannot
1425 // know whether globalptr->load() has been deleted by another thread in the meantime.
1426}
1427
1428////////////////////////////////////////////////////////////////////////////////
1429/// \copydoc TDirectoryFile::WriteObject(const T*,const char*,Option_t*,Int_t).
1430
1431Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Int_t /*bufsize*/)
1432{
1433 const char *objname = "no name specified";
1434 if (name) objname = name;
1435 else if (obj) objname = obj->GetName();
1436 Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1437 return 0;
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// UnRegister a TContext pointing to this TDirectory object
1442
1444
1446
1447 // Another thread already unregistered the TContext.
1448 if (ctxt->fDirectory == nullptr || ctxt->fDirectory == ROOT::Internal::gROOTLocal)
1449 return;
1450
1451 if (ctxt==fContext) {
1452 fContext = ctxt->fNext;
1453 if (fContext) fContext->fPrevious = nullptr;
1454 ctxt->fPrevious = ctxt->fNext = nullptr;
1455 } else {
1456 TContext *next = ctxt->fNext;
1457 ctxt->fPrevious->fNext = next;
1458 if (next) next->fPrevious = ctxt->fPrevious;
1459 ctxt->fPrevious = ctxt->fNext = nullptr;
1460 }
1461}
1462
1463////////////////////////////////////////////////////////////////////////////////
1464/// TDirectory Streamer.
1466{
1467 // Stream an object of class TDirectory.
1468
1469 UInt_t R__s, R__c;
1470 if (R__b.IsReading()) {
1471 Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1473 R__b >> fMother;
1474 R__b >> fList;
1475 fList->UseRWLock();
1477 R__b.CheckByteCount(R__s, R__c, TDirectory::IsA());
1478 } else {
1479 R__c = R__b.WriteVersion(TDirectory::IsA(), kTRUE);
1481 R__b << fMother;
1482 R__b << fList;
1484 R__b.SetByteCount(R__c, kTRUE);
1485 }
1486}
#define SafeDelete(p)
Definition RConfig.hxx:507
#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
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:132
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
static std::atomic_flag * GetCurrentDirectoryLock()
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:385
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
char name[80]
Definition TGX11.cxx:142
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:417
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2585
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#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
@ kWrite
Definition TBuffer.h:73
virtual void ResetMap()=0
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
void SetReadMode()
Set buffer in read mode.
Definition TBuffer.cxx:301
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:84
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:2999
static TClass * Class()
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
void CdNull()
Set the current directory to null.
~TContext()
Destructor.
TContext * fPrevious
! Pointer to the next TContext in the implied list of context pointing to fPrevious.
Definition TDirectory.h:94
TContext * fNext
! Pointer to the next TContext in the implied list of context pointing to fPrevious.
Definition TDirectory.h:95
Describe directory structure in memory.
Definition TDirectory.h:45
Bool_t cd1(const char *path)
Change current directory to "this" directory or to the directory described by the path if given one.
static TClass * Class()
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:254
virtual TList * GetList() const
Definition TDirectory.h:223
std::shared_ptr< std::atomic< TDirectory * > > SharedGDirectory_t
Definition TDirectory.h:147
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual const char * GetPath() const
Returns the full path of the directory.
std::atomic_flag fSpinLock
! MSVC doesn't support = ATOMIC_FLAG_INIT;
Definition TDirectory.h:154
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.
static size_t DecodeNameCycle(const char *namecycle, char *name, Short_t &cycle, const size_t namesize=0)
Decode a namecycle "aap;2" contained in the null-terminated string buffer into name "aap" and cycle 2...
virtual void DeleteAll(Option_t *option="")
Delete all objects from memory.
std::atomic< size_t > fContextPeg
! Counter delaying the TDirectory destructor from finishing.
Definition TDirectory.h:153
std::vector< SharedGDirectory_t > fGDirectories
! thread local gDirectory pointing to this object.
Definition TDirectory.h:151
virtual void rmdir(const char *name)
Removes subdirectory from the directory When directory is deleted, all keys in all subdirectories wil...
void FillFullPath(TString &buf) const
Recursive method to fill full path for directory.
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
void ls(Option_t *option="") const override
List Directory contents.
TContext * fContext
! Pointer to a list of TContext object pointing to this TDirectory
Definition TDirectory.h:145
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
void RegisterGDirectory(SharedGDirectory_t &ptr)
Register a std::atomic<TDirectory*> that will soon be pointing to this TDirectory object.
TDirectory()
Directory default constructor.
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)
Write an object with proper type checking.
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 Bool_t cd()
Change current directory to "this" 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 Streamer(TBuffer &) override
TDirectory Streamer.
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 nullptr or "", a file with "<objectname>.root" is created.
TString fPathBuffer
! Buffer for GetPath() function
Definition TDirectory.h:144
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.
static SharedGDirectory_t & GetSharedLocalCurrentDirectory()
Return the (address of) a shared pointer to the struct holding the actual thread local gDirectory poi...
TUUID fUUID
Unique identifier.
Definition TDirectory.h:143
static Bool_t fgAddDirectory
!
Definition TDirectory.h:157
TDirectory * GetMotherDir() const
Definition TDirectory.h:226
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.
TClass * IsA() const override
Definition TDirectory.h:309
TObject * fMother
pointer to mother of the directory
Definition TDirectory.h:141
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:213
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.
Bool_t IsBuilt() const
Definition TDirectory.h:235
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
List of objects in memory.
Definition TDirectory.h:142
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 file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:532
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:894
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
virtual TObjLink * FirstLink() const
Definition TList.h:107
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
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
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
void Streamer(TBuffer &) override
Stream an object of class TObject.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
static TClass * Class()
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:987
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
virtual TClass * IsA() const
Definition TObject.h:248
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:597
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:74
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1070
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:3059
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3067
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2916
Regular expression class.
Definition TRegexp.h:31
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
@ kBoth
Definition TString.h:283
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
Bool_t IsNull() const
Definition TString.h:423
TString & Append(const char *cs)
Definition TString.h:582
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
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:1311
virtual void Streamer(TBuffer &)
R__EXTERN TROOT * gROOTLocal
Definition TROOT.h:390
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:119
@ kExactMatch
TCanvas * slash()
Definition slash.C:1
th1 Draw()
TMarker m
Definition textangle.C:8