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