Logo ROOT  
Reference Guide
TFolder.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Rene Brun 02/09/2000
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
12
13/** \class TFolder
14\ingroup Base
15
16A TFolder object is a collection of objects and folders.
17Folders have a name and a title and are identified in the folder hierarchy
18by a "Unix-like" naming mechanism. The root of all folders is //root.
19New folders can be dynamically added or removed to/from a folder.
20The folder hierarchy can be visualized via the TBrowser.
21
22\image html base_browser.png
23
24The Root folders hierarchy can be seen as a whiteboard where objects
25are posted. Other classes/tasks can access these objects by specifying
26only a string pathname. This whiteboard facility greatly improves the
27modularity of an application, minimizing the class relationship problem
28that penalizes large applications.
29
30Pointers are efficient to communicate between classes.
31However, one has interest to minimize direct coupling between classes
32in the form of direct pointers. One better uses the naming and search
33service provided by the Root folders hierarchy. This makes the classes
34loosely coupled and also greatly facilitates I/O operations.
35In a client/server environment, this mechanism facilitates the access
36to any kind of object in //root stores running on different processes.
37
38A TFolder is created by invoking the TFolder constructor. It is placed
39inside an existing folder via the TFolder::AddFolder method.
40One can search for a folder or an object in a folder using the FindObject
41method. FindObject analyses the string passed as its argument and searches
42in the hierarchy until it finds an object or folder matching the name.
43
44When a folder is deleted, its reference from the parent folder and
45possible other folders is deleted.
46
47If a folder has been declared the owner of its objects/folders via
48TFolder::SetOwner, then the contained objects are deleted when the
49folder is deleted. By default, a folder does not own its contained objects.
50
51NOTE that folder ownership can be set
52 - via TFolder::SetOwner
53 - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
54
55Standard Root objects are automatically added to the folder hierarchy.
56For example, the following folders exist:
57 //root/Files with the list of currently connected Root files
58 //root/Classes with the list of active classes
59 //root/Geometries with active geometries
60 //root/Canvases with the list of active canvases
61 //root/Styles with the list of graphics styles
62 //root/Colors with the list of active colors
63
64For example, if a file "myFile.root" is added to the list of files, one can
65retrieve a pointer to the corresponding TFile object with a statement like:
66~~~ {.cpp}
67 TFile *myFile = (TFile*)gROOT->FindObject("//root/Files/myFile.root");
68~~~
69The above statement can be abbreviated to:
70~~~ {.cpp}
71 TFile *myFile = (TFile*)gROOT->FindObject("/Files/myFile.root");
72~~~
73or even to:
74~~~ {.cpp}
75 TFile *myFile = (TFile*)gROOT->FindObjectAny("myFile.root");
76~~~
77In this last case, the TROOT::FindObjectAny function will scan the folder hierarchy
78starting at //root and will return the first object named "myFile.root".
79
80Because a string-based search mechanism is expensive, it is recommended
81to save the pointer to the object as a class member or local variable
82if this pointer is used frequently or inside loops.
83*/
84
85#include "Riostream.h"
86#include "Strlen.h"
87#include "TFolder.h"
88#include "TBrowser.h"
89#include "TROOT.h"
90#include "TClass.h"
91#include "TError.h"
92#include "TRegexp.h"
93
94static const char *gFolderD[64];
95static Int_t gFolderLevel = -1;
96static char gFolderPath[512];
97
98enum { kOwnFolderList = BIT(15) };
99
101
102////////////////////////////////////////////////////////////////////////////////
103/// Default constructor used by the Input functions.
104///
105/// This constructor should not be called by a user directly.
106/// The normal way to create a folder is by calling TFolder::AddFolder.
107
109{
110 fFolders = 0;
112}
113
114////////////////////////////////////////////////////////////////////////////////
115/// Create a normal folder.
116/// Use Add or AddFolder to add objects or folders to this folder.
117
118TFolder::TFolder(const char *name, const char *title) : TNamed(name,title)
119{
120 fFolders = new TList();
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Copy constructor.
127
128TFolder::TFolder(const TFolder &folder) : TNamed(folder),fFolders(0),fIsOwner(kFALSE)
129{
130 ((TFolder&)folder).Copy(*this);
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// Folder destructor. Remove all objects from its lists and delete
135/// all its sub folders.
136
138{
140
141 if (fFolders) {
142 if (fFolders->IsOwner()) {
143 fFolders->Delete();
144 }
145 if (TestBit(kOwnFolderList)) {
146 TObjLink *iter = ((TList*)fFolders)->FirstLink();
147 while (iter) {
148 TObject *obj = iter->GetObject();
149 TObjLink *next = iter->Next();
150 if (obj && obj->IsA() == TFolder::Class()) {
151 ((TList*)fFolders)->Remove(iter);
152 delete obj;
153 }
154 iter = next;
155 }
156 fFolders->Clear("nodelete");
158 }
159 }
160
162
163 if (gDebug)
164 std::cerr << "TFolder dtor called for "<< GetName() << std::endl;
165}
166
167////////////////////////////////////////////////////////////////////////////////
168/// Add object to this folder. obj must be a TObject or a TFolder.
169
171{
172 if (obj == 0 || fFolders == 0) return;
173 obj->SetBit(kMustCleanup);
174 fFolders->Add(obj);
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Create a new folder and add it to the list of folders of this folder,
179/// return a pointer to the created folder.
180/// Note that a folder can be added to several folders.
181///
182/// If collection is non NULL, the pointer fFolders is set to the existing
183/// collection, otherwise a default collection (Tlist) is created.
184/// Note that the folder name cannot contain slashes.
185
186TFolder *TFolder::AddFolder(const char *name, const char *title, TCollection *collection)
187{
188 if (strchr(name,'/')) {
189 ::Error("TFolder::TFolder","folder name cannot contain a slash: %s", name);
190 return 0;
191 }
192 if (strlen(GetName()) == 0) {
193 ::Error("TFolder::TFolder","folder name cannot be \"\"");
194 return 0;
195 }
196 TFolder *folder = new TFolder();
197 folder->SetName(name);
198 folder->SetTitle(title);
199 if (!fFolders) {
200 fFolders = new TList(); //only true when gROOT creates its 1st folder
202 }
203 fFolders->Add(folder);
204
205 if (collection) {
206 folder->fFolders = collection;
207 } else {
208 folder->fFolders = new TList();
209 folder->SetBit(kOwnFolderList);
210 }
211 return folder;
212}
213
214////////////////////////////////////////////////////////////////////////////////
215/// Browse this folder.
216
218{
219 if (fFolders) fFolders->Browse(b);
220}
221
222////////////////////////////////////////////////////////////////////////////////
223/// Delete all objects from a folder list.
224
226{
227 if (fFolders) fFolders->Clear(option);
228}
229
230////////////////////////////////////////////////////////////////////////////////
231/// Return the full pathname corresponding to subpath name if the node is
232/// gROOT->GetRootFolder() and return a relative path otherwise.
233/// The returned path will be re-used by the next call to FindFullPathName().
234
235const char *TFolder::FindFullPathName(const char *name) const
236{
237 TObject *obj = FindObject(name);
238 if (obj || !fFolders) {
239 gFolderLevel++;
241 if (strcmp(gFolderD[0],"root")==0) {
242 strlcpy(gFolderPath,"//root/", sizeof(gFolderPath));
243 } else {
244 gFolderPath[0] = '\0';
245 }
246 for (Int_t l = 1; l<=gFolderLevel;l++) {
247 strlcat(gFolderPath, gFolderD[l], sizeof(gFolderPath));
248 strlcat(gFolderPath, "/", sizeof(gFolderPath));
249 }
250 strlcat(gFolderPath,name, sizeof(gFolderPath));
251 gFolderLevel = -1;
252 return gFolderPath;
253 }
254 if (name[0] == '/') return 0;
255 TIter next(fFolders);
256 TFolder *folder;
257 const char *found;
258 gFolderLevel++;
260 while ((obj=next())) {
261 // For a TClass object, InheritsFrom does not check the inheritance of
262 // the object but the inheritance of the class described by the object,
263 // so we need to explicitly call IsA
264 if (obj->IsA()->InheritsFrom(TClass::Class())) continue;
265 // For any other object IsA is called by InheritsFrom
266 if (!obj->InheritsFrom(TFolder::Class())) continue;
267 folder = (TFolder*)obj;
268 found = folder->FindFullPathName(name);
269 if (found) return found;
270 }
271 gFolderLevel--;
272 return 0;
273}
274
275
276////////////////////////////////////////////////////////////////////////////////
277/// Return the full pathname corresponding to subpath name.
278/// The returned path will be re-used by the next call to FindFullPathName().
279
280const char *TFolder::FindFullPathName(const TObject *) const
281{
282 Error("FindFullPathname","Not yet implemented");
283 return 0;
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// Find object in an folder.
288
290{
291 Error("FindObject","Not yet implemented");
292 return 0;
293}
294
295////////////////////////////////////////////////////////////////////////////////
296/// Search object identified by name in the tree of folders inside
297/// this folder.
298/// Name may be of the forms:
299///
300/// A. Specify a full pathname starting at the top ROOT folder
301/// //root/xxx/yyy/name
302///
303/// B. Specify a pathname starting with a single slash. //root is assumed
304/// /xxx/yyy/name
305///
306/// C. Specify a pathname relative to this folder
307/// xxx/yyy/name
308/// name
309
311{
312 if (!fFolders) return 0;
313 if (name == 0) return 0;
314 if (name[0] == '/') {
315 if (name[1] == '/') {
316 if (!strstr(name,"//root/")) return 0;
317 return gROOT->GetRootFolder()->FindObject(name+7);
318 } else {
319 return gROOT->GetRootFolder()->FindObject(name+1);
320 }
321 }
322 Int_t nch = strlen(name);
323 char *cname;
324 char csname[128];
325 if (nch < (int)sizeof(csname))
326 cname = csname;
327 else
328 cname = new char[nch+1];
329 strcpy(cname, name);
330 TObject *obj;
331 char *slash = strchr(cname,'/');
332 if (slash) {
333 *slash = 0;
334 obj = fFolders->FindObject(cname);
335 if (!obj) {
336 if (nch >= (int)sizeof(csname)) delete [] cname;
337 return 0;
338 }
339 TObject *ret = obj->FindObject(slash+1);
340 if (nch >= (int)sizeof(csname)) delete [] cname;
341 return ret;
342 } else {
343 TObject *ret = fFolders->FindObject(cname);
344 if (nch >= (int)sizeof(csname)) delete [] cname;
345 return ret;
346 }
347}
348
349////////////////////////////////////////////////////////////////////////////////
350/// Return a pointer to the first object with name starting at this folder.
351
353{
354 TObject *obj = FindObject(name);
355 if (obj || !fFolders) return obj;
356
357 //if (!obj->InheritsFrom(TFolder::Class())) continue;
358 if (name[0] == '/') return 0;
359 TIter next(fFolders);
360 TFolder *folder;
361 TObject *found;
363 while ((obj=next())) {
364 if (!obj->InheritsFrom(TFolder::Class())) continue;
365 if (obj->IsA() == TClass::Class()) continue;
366 folder = (TFolder*)obj;
367 found = folder->FindObjectAny(name);
368 if (found) return found;
369 }
370 return 0;
371}
372
373////////////////////////////////////////////////////////////////////////////////
374/// Folder ownership has been set via
375/// - TFolder::SetOwner
376/// - TCollection::SetOwner on the collection specified to TFolder::AddFolder
377
379{
380 if (!fFolders) return kFALSE;
381 return fFolders->IsOwner();
382}
383
384////////////////////////////////////////////////////////////////////////////////
385/// List folder contents.
386///
387/// If option contains "dump", the Dump function of contained objects is called.
388///
389/// If option contains "print", the Print function of contained objects is called.
390///
391/// By default the ls function of contained objects is called.
392///
393/// Indentation is used to identify the folder tree.
394///
395/// The if option contains a `<regexp>` it be used to match the name of the objects.
396
397void TFolder::ls(Option_t *option) const
398{
399 if (!fFolders) return;
401 std::cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
403
404 TString opt = option;
405 Ssiz_t dump = opt.Index("dump", 0, TString::kIgnoreCase);
406 if (dump != kNPOS)
407 opt.Remove(dump, 4);
408 Ssiz_t print = opt.Index("print", 0, TString::kIgnoreCase);
409 if (print != kNPOS)
410 opt.Remove(print, 5);
411 opt = opt.Strip(TString::kBoth);
412 if (opt == "")
413 opt = "*";
414 TRegexp re(opt, kTRUE);
415
416 TObject *obj;
417 TIter nextobj(fFolders);
418 while ((obj = (TObject *) nextobj())) {
419 TString s = obj->GetName();
420 if (s.Index(re) == kNPOS) continue;
421 if (dump != kNPOS)
422 obj->Dump();
423 if (print != kNPOS)
424 obj->Print(option);
425 obj->ls(option);
426 }
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// Return occurence number of object in the list of objects of this folder.
432/// The function returns the number of objects with the same name as object
433/// found in the list of objects in this folder before object itself.
434/// If only one object is found, return 0.
435
436Int_t TFolder::Occurence(const TObject *object) const
437{
438 Int_t n = 0;
439 if (!fFolders) return 0;
440 TIter next(fFolders);
441 TObject *obj;
442 while ((obj=next())) {
443 if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
444 }
445 if (n <=1) return n-1;
446 n = 0;
447 next.Reset();
448 while ((obj=next())) {
449 if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
450 if (obj == object) return n;
451 }
452 return 0;
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Recursively remove object from a folder.
457
459{
461}
462
463////////////////////////////////////////////////////////////////////////////////
464/// Remove object from this folder. obj must be a TObject or a TFolder.
465
467{
468 if (obj == 0 || fFolders == 0) return;
469 fFolders->Remove(obj);
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Save all objects in this folder in filename.
474/// Each object in this folder will have a key in the file where the name of
475/// the key will be the name of the object.
476
477void TFolder::SaveAs(const char *filename, Option_t *option) const
478{
479 if (gDirectory) gDirectory->SaveObjectAs(this,filename,option);
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// Set ownership.
484/// If the folder is declared owner, when the folder is deleted, all
485/// the objects added via TFolder::Add are deleted via TObject::Delete,
486/// otherwise TObject::Clear is called.
487///
488/// NOTE that folder ownership can be set:
489/// - via TFolder::SetOwner
490/// - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
491
493{
494 if (!fFolders) fFolders = new TList();
495 fFolders->SetOwner(owner);
496}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:543
#define b(i)
Definition: RSha256.hxx:100
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define BIT(n)
Definition: Rtypes.h:83
#define ClassImp(name)
Definition: Rtypes.h:361
#define gDirectory
Definition: TDirectory.h:229
@ kOwnFolderList
Definition: TFolder.cxx:98
static const char * gFolderD[64]
Definition: TFolder.cxx:94
static Int_t gFolderLevel
Definition: TFolder.cxx:95
static char gFolderPath[512]
Definition: TFolder.cxx:96
char name[80]
Definition: TGX11.cxx:109
#define gROOT
Definition: TROOT.h:406
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Collection abstract base class.
Definition: TCollection.h:63
virtual TObject * Remove(TObject *obj)=0
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
virtual void Clear(Option_t *option="")=0
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
static void EmptyGarbageCollection()
Do the garbage collection.
virtual void Delete(Option_t *option="")=0
Delete this object.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void Add(TObject *obj)=0
Bool_t IsOwner() const
Definition: TCollection.h:188
static void StartGarbageCollection()
Set up for garbage collection.
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
virtual void SaveAs(const char *filename="", Option_t *option="") const
Save all objects in this folder in filename.
Definition: TFolder.cxx:477
TFolder * AddFolder(const char *name, const char *title, TCollection *collection=0)
Create a new folder and add it to the list of folders of this folder, return a pointer to the created...
Definition: TFolder.cxx:186
TFolder()
Default constructor used by the Input functions.
Definition: TFolder.cxx:108
virtual TObject * FindObjectAny(const char *name) const
Return a pointer to the first object with name starting at this folder.
Definition: TFolder.cxx:352
virtual void Add(TObject *obj)
Add object to this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:170
virtual void Browse(TBrowser *b)
Browse this folder.
Definition: TFolder.cxx:217
virtual ~TFolder()
Folder destructor.
Definition: TFolder.cxx:137
virtual void Clear(Option_t *option="")
Delete all objects from a folder list.
Definition: TFolder.cxx:225
virtual const char * FindFullPathName(const char *name) const
Return the full pathname corresponding to subpath name if the node is gROOT->GetRootFolder() and retu...
Definition: TFolder.cxx:235
Bool_t fIsOwner
Definition: TFolder.h:34
virtual void SetOwner(Bool_t owner=kTRUE)
Set ownership.
Definition: TFolder.cxx:492
virtual TObject * FindObject(const char *name) const
Search object identified by name in the tree of folders inside this folder.
Definition: TFolder.cxx:310
Bool_t IsOwner() const
Folder ownership has been set via.
Definition: TFolder.cxx:378
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
TCollection * fFolders
Definition: TFolder.h:33
virtual void ls(Option_t *option="") const
List folder contents.
Definition: TFolder.cxx:397
virtual void RecursiveRemove(TObject *obj)
Recursively remove object from a folder.
Definition: TFolder.cxx:458
virtual void Remove(TObject *obj)
Remove object from this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:466
void Reset()
Definition: TCollection.h:252
A doubly linked list.
Definition: TList.h:44
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void Copy(TObject &named) const
Copy this to obj.
Definition: TNamed.cxx:94
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual void Dump() const
Dump contents of object on stdout.
Definition: TObject.cxx:266
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:550
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:492
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2773
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2781
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2677
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:131
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
@ kBoth
Definition: TString.h:262
@ kIgnoreCase
Definition: TString.h:263
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
const Int_t n
Definition: legend1.C:16
static constexpr double s
TCanvas * slash()
Definition: slash.C:1
auto * l
Definition: textangle.C:4