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 <iostream>
86#include "Strlen.h"
87#include "strlcpy.h"
88#include "TFolder.h"
89#include "TBrowser.h"
90#include "TList.h"
91#include "TROOT.h"
92#include "TClass.h"
93#include "TError.h"
94#include "TRegexp.h"
95
96static const char *gFolderD[64];
97static Int_t gFolderLevel = -1;
98static char gFolderPath[512];
99
100enum { kOwnFolderList = BIT(15) };
101
103
104////////////////////////////////////////////////////////////////////////////////
105/// Default constructor used by the Input functions.
106///
107/// This constructor should not be called by a user directly.
108/// The normal way to create a folder is by calling TFolder::AddFolder.
109
111{
112 fFolders = nullptr;
114}
115
116////////////////////////////////////////////////////////////////////////////////
117/// Create a normal folder.
118/// Use Add or AddFolder to add objects or folders to this folder.
119
120TFolder::TFolder(const char *name, const char *title) : TNamed(name,title)
121{
122 fFolders = new TList();
125}
126
127////////////////////////////////////////////////////////////////////////////////
128/// Copy constructor.
129
130TFolder::TFolder(const TFolder &folder) : TNamed(folder),fFolders(nullptr),fIsOwner(kFALSE)
131{
132 ((TFolder&)folder).Copy(*this);
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Folder destructor. Remove all objects from its lists and delete
137/// all its sub folders.
138
140{
142
143 if (fFolders) {
144 if (fFolders->IsOwner()) {
145 fFolders->Delete();
146 }
147 if (TestBit(kOwnFolderList)) {
148 TObjLink *iter = ((TList*)fFolders)->FirstLink();
149 while (iter) {
150 TObject *obj = iter->GetObject();
151 TObjLink *next = iter->Next();
152 if (obj && obj->IsA() == TFolder::Class()) {
153 ((TList*)fFolders)->Remove(iter);
154 delete obj;
155 }
156 iter = next;
157 }
158 fFolders->Clear("nodelete");
160 }
161 }
162
164
165 if (gDebug)
166 std::cerr << "TFolder dtor called for "<< GetName() << std::endl;
167}
168
169////////////////////////////////////////////////////////////////////////////////
170/// Add object to this folder. obj must be a TObject or a TFolder.
171
173{
174 if (obj == nullptr || fFolders == nullptr) return;
175 obj->SetBit(kMustCleanup);
176 fFolders->Add(obj);
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Create a new folder and add it to the list of folders of this folder,
181/// return a pointer to the created folder.
182/// Note that a folder can be added to several folders.
183///
184/// If collection is non NULL, the pointer fFolders is set to the existing
185/// collection, otherwise a default collection (Tlist) is created.
186/// Note that the folder name cannot contain slashes.
187
188TFolder *TFolder::AddFolder(const char *name, const char *title, TCollection *collection)
189{
190 if (strchr(name,'/')) {
191 ::Error("TFolder::TFolder","folder name cannot contain a slash: %s", name);
192 return nullptr;
193 }
194 if (strlen(GetName()) == 0) {
195 ::Error("TFolder::TFolder","folder name cannot be \"\"");
196 return nullptr;
197 }
198 TFolder *folder = new TFolder();
199 folder->SetName(name);
200 folder->SetTitle(title);
201 if (!fFolders) {
202 fFolders = new TList(); //only true when gROOT creates its 1st folder
204 }
205 fFolders->Add(folder);
206
207 if (collection) {
208 folder->fFolders = collection;
209 } else {
210 folder->fFolders = new TList();
211 folder->SetBit(kOwnFolderList);
212 }
213 return folder;
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Browse this folder.
218
220{
221 if (fFolders) fFolders->Browse(b);
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Delete all objects from a folder list.
226
228{
229 if (fFolders) fFolders->Clear(option);
230}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Return the full pathname corresponding to subpath name if the node is
234/// gROOT->GetRootFolder() and return a relative path otherwise.
235/// The returned path will be re-used by the next call to FindFullPathName().
236
237const char *TFolder::FindFullPathName(const char *name) const
238{
239 TObject *obj = FindObject(name);
240 if (obj || !fFolders) {
241 gFolderLevel++;
243 if (strcmp(gFolderD[0],"root")==0) {
244 strlcpy(gFolderPath,"//root/", sizeof(gFolderPath));
245 } else {
246 gFolderPath[0] = '\0';
247 }
248 for (Int_t l = 1; l<=gFolderLevel;l++) {
249 strlcat(gFolderPath, gFolderD[l], sizeof(gFolderPath));
250 strlcat(gFolderPath, "/", sizeof(gFolderPath));
251 }
252 strlcat(gFolderPath,name, sizeof(gFolderPath));
253 gFolderLevel = -1;
254 return gFolderPath;
255 }
256 if (name[0] == '/') return nullptr;
257 TIter next(fFolders);
258 TFolder *folder;
259 const char *found;
260 gFolderLevel++;
262 while ((obj=next())) {
263 // For a TClass object, InheritsFrom does not check the inheritance of
264 // the object but the inheritance of the class described by the object,
265 // so we need to explicitly call IsA
266 if (obj->IsA()->InheritsFrom(TClass::Class())) continue;
267 // For any other object IsA is called by InheritsFrom
268 if (!obj->InheritsFrom(TFolder::Class())) continue;
269 folder = (TFolder*)obj;
270 found = folder->FindFullPathName(name);
271 if (found) return found;
272 }
273 gFolderLevel--;
274 return nullptr;
275}
276
277
278////////////////////////////////////////////////////////////////////////////////
279/// Return the full pathname corresponding to subpath name.
280/// The returned path will be re-used by the next call to FindFullPathName().
281
282const char *TFolder::FindFullPathName(const TObject *) const
283{
284 Error("FindFullPathname","Not yet implemented");
285 return nullptr;
286}
287
288////////////////////////////////////////////////////////////////////////////////
289/// Find object in an folder.
290
292{
293 Error("FindObject","Not yet implemented");
294 return nullptr;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Search object identified by name in the tree of folders inside
299/// this folder.
300/// Name may be of the forms:
301///
302/// A. Specify a full pathname starting at the top ROOT folder
303/// //root/xxx/yyy/name
304///
305/// B. Specify a pathname starting with a single slash. //root is assumed
306/// /xxx/yyy/name
307///
308/// C. Specify a pathname relative to this folder
309/// xxx/yyy/name
310/// name
311
313{
314 if (!fFolders || !name) return nullptr;
315 if (name[0] == '/') {
316 if (name[1] == '/') {
317 if (!strstr(name,"//root/")) return nullptr;
318 return gROOT->GetRootFolder()->FindObject(name+7);
319 } else {
320 return gROOT->GetRootFolder()->FindObject(name+1);
321 }
322 }
323 Int_t nch = strlen(name);
324 char csname[128];
325 char *cname = csname;
326 Int_t len = sizeof(csname);
327 if (nch >= len) {
328 len = nch+1;
329 cname = new char[len];
330 }
331 strlcpy(cname, name, len);
332 TObject *ret = nullptr;
333 char *slash = strchr(cname,'/');
334 if (slash) {
335 *slash = 0;
336 if (TObject *obj = fFolders->FindObject(cname))
337 ret = obj->FindObject(slash+1);
338 } else {
339 ret = fFolders->FindObject(cname);
340 }
341 if (cname != csname)
342 delete [] cname;
343 return ret;
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Return a pointer to the first object with name starting at this folder.
348
350{
351 TObject *obj = FindObject(name);
352 if (obj || !fFolders) return obj;
353
354 //if (!obj->InheritsFrom(TFolder::Class())) continue;
355 if (name[0] == '/') return nullptr;
356 TIter next(fFolders);
357 TFolder *folder;
358 TObject *found;
360 while ((obj=next())) {
361 if (!obj->InheritsFrom(TFolder::Class())) continue;
362 if (obj->IsA() == TClass::Class()) continue;
363 folder = (TFolder*)obj;
364 found = folder->FindObjectAny(name);
365 if (found) return found;
366 }
367 return nullptr;
368}
369
370////////////////////////////////////////////////////////////////////////////////
371/// Folder ownership has been set via
372/// - TFolder::SetOwner
373/// - TCollection::SetOwner on the collection specified to TFolder::AddFolder
374
376{
377 if (!fFolders) return kFALSE;
378 return fFolders->IsOwner();
379}
380
381////////////////////////////////////////////////////////////////////////////////
382/// List folder contents.
383///
384/// If option contains "dump", the Dump function of contained objects is called.
385///
386/// If option contains "print", the Print function of contained objects is called.
387///
388/// By default the ls function of contained objects is called.
389///
390/// Indentation is used to identify the folder tree.
391///
392/// The if option contains a `<regexp>` it be used to match the name of the objects.
393
394void TFolder::ls(Option_t *option) const
395{
396 if (!fFolders) return;
398 std::cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
400
401 TString opt = option;
402 Ssiz_t dump = opt.Index("dump", 0, TString::kIgnoreCase);
403 if (dump != kNPOS)
404 opt.Remove(dump, 4);
405 Ssiz_t print = opt.Index("print", 0, TString::kIgnoreCase);
406 if (print != kNPOS)
407 opt.Remove(print, 5);
408 opt = opt.Strip(TString::kBoth);
409 if (opt == "")
410 opt = "*";
411 TRegexp re(opt, kTRUE);
412
413 TObject *obj;
414 TIter nextobj(fFolders);
415 while ((obj = (TObject *) nextobj())) {
416 TString s = obj->GetName();
417 if (s.Index(re) == kNPOS) continue;
418 if (dump != kNPOS)
419 obj->Dump();
420 if (print != kNPOS)
421 obj->Print(option);
422 obj->ls(option);
423 }
425}
426
427////////////////////////////////////////////////////////////////////////////////
428/// Return occurence number of object in the list of objects of this folder.
429/// The function returns the number of objects with the same name as object
430/// found in the list of objects in this folder before object itself.
431/// If only one object is found, return 0.
432
433Int_t TFolder::Occurence(const TObject *object) const
434{
435 Int_t n = 0;
436 if (!fFolders) return 0;
437 TIter next(fFolders);
438 TObject *obj;
439 while ((obj=next())) {
440 if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
441 }
442 if (n <=1) return n-1;
443 n = 0;
444 next.Reset();
445 while ((obj=next())) {
446 if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
447 if (obj == object) return n;
448 }
449 return 0;
450}
451
452////////////////////////////////////////////////////////////////////////////////
453/// Recursively remove object from a folder.
454
456{
458}
459
460////////////////////////////////////////////////////////////////////////////////
461/// Remove object from this folder. obj must be a TObject or a TFolder.
462
464{
465 if (obj == nullptr || fFolders == nullptr) return;
466 fFolders->Remove(obj);
467}
468
469////////////////////////////////////////////////////////////////////////////////
470/// Save all objects in this folder in filename.
471/// Each object in this folder will have a key in the file where the name of
472/// the key will be the name of the object.
473
474void TFolder::SaveAs(const char *filename, Option_t *option) const
475{
476 if (gDirectory) gDirectory->SaveObjectAs(this,filename,option);
477}
478
479////////////////////////////////////////////////////////////////////////////////
480/// Set ownership.
481/// If the folder is declared owner, when the folder is deleted, all
482/// the objects added via TFolder::Add are deleted via TObject::Delete,
483/// otherwise TObject::Clear is called.
484///
485/// NOTE that folder ownership can be set:
486/// - via TFolder::SetOwner
487/// - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
488
490{
491 if (!fFolders) fFolders = new TList();
492 fFolders->SetOwner(owner);
493}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:534
#define b(i)
Definition: RSha256.hxx:100
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
int Ssiz_t
Definition: RtypesCore.h:67
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define BIT(n)
Definition: Rtypes.h:85
#define ClassImp(name)
Definition: Rtypes.h:364
#define gDirectory
Definition: TDirectory.h:348
@ kOwnFolderList
Definition: TFolder.cxx:100
static const char * gFolderD[64]
Definition: TFolder.cxx:96
static Int_t gFolderLevel
Definition: TFolder.cxx:97
static char gFolderPath[512]
Definition: TFolder.cxx:98
char name[80]
Definition: TGX11.cxx:110
Int_t gDebug
Definition: TROOT.cxx:592
#define gROOT
Definition: TROOT.h:404
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Collection abstract base class.
Definition: TCollection.h:65
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:190
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:474
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:188
TFolder()
Default constructor used by the Input functions.
Definition: TFolder.cxx:110
virtual TObject * FindObjectAny(const char *name) const
Return a pointer to the first object with name starting at this folder.
Definition: TFolder.cxx:349
virtual void Add(TObject *obj)
Add object to this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:172
virtual void Browse(TBrowser *b)
Browse this folder.
Definition: TFolder.cxx:219
virtual ~TFolder()
Folder destructor.
Definition: TFolder.cxx:139
virtual void Clear(Option_t *option="")
Delete all objects from a folder list.
Definition: TFolder.cxx:227
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:237
Bool_t fIsOwner
Definition: TFolder.h:34
virtual void SetOwner(Bool_t owner=kTRUE)
Set ownership.
Definition: TFolder.cxx:489
virtual TObject * FindObject(const char *name) const
Search object identified by name in the tree of folders inside this folder.
Definition: TFolder.cxx:312
Bool_t IsOwner() const
Folder ownership has been set via.
Definition: TFolder.cxx:375
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:433
TCollection * fFolders
Definition: TFolder.h:33
virtual void ls(Option_t *option="") const
List folder contents.
Definition: TFolder.cxx:394
virtual void RecursiveRemove(TObject *obj)
Recursively remove object from a folder.
Definition: TFolder.cxx:455
virtual void Remove(TObject *obj)
Remove object from this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:463
void Reset()
Definition: TCollection.h:254
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:359
virtual void Dump() const
Dump contents of object on stdout.
Definition: TObject.cxx:268
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:130
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:323
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:552
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:494
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2795
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2803
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2699
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:136
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1131
@ kBoth
Definition: TString.h:267
@ kIgnoreCase
Definition: TString.h:268
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
const Int_t n
Definition: legend1.C:16
static constexpr double s
TCanvas * slash()
Definition: slash.C:1
auto * l
Definition: textangle.C:4