Logo ROOT   6.21/01
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 
16 A TFolder object is a collection of objects and folders.
17 Folders have a name and a title and are identified in the folder hierarchy
18 by a "Unix-like" naming mechanism. The root of all folders is //root.
19 New folders can be dynamically added or removed to/from a folder.
20 The folder hierarchy can be visualized via the TBrowser.
21 
22 \image html base_browser.png
23 
24 The Root folders hierarchy can be seen as a whiteboard where objects
25 are posted. Other classes/tasks can access these objects by specifying
26 only a string pathname. This whiteboard facility greatly improves the
27 modularity of an application, minimizing the class relationship problem
28 that penalizes large applications.
29 
30 Pointers are efficient to communicate between classes.
31 However, one has interest to minimize direct coupling between classes
32 in the form of direct pointers. One better uses the naming and search
33 service provided by the Root folders hierarchy. This makes the classes
34 loosely coupled and also greatly facilitates I/O operations.
35 In a client/server environment, this mechanism facilitates the access
36 to any kind of object in //root stores running on different processes.
37 
38 A TFolder is created by invoking the TFolder constructor. It is placed
39 inside an existing folder via the TFolder::AddFolder method.
40 One can search for a folder or an object in a folder using the FindObject
41 method. FindObject analyses the string passed as its argument and searches
42 in the hierarchy until it finds an object or folder matching the name.
43 
44 When a folder is deleted, its reference from the parent folder and
45 possible other folders is deleted.
46 
47 If a folder has been declared the owner of its objects/folders via
48 TFolder::SetOwner, then the contained objects are deleted when the
49 folder is deleted. By default, a folder does not own its contained objects.
50 
51 NOTE that folder ownership can be set
52  - via TFolder::SetOwner
53  - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
54 
55 Standard Root objects are automatically added to the folder hierarchy.
56 For 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 
64 For example, if a file "myFile.root" is added to the list of files, one can
65 retrieve a pointer to the corresponding TFile object with a statement like:
66 ~~~ {.cpp}
67  TFile *myFile = (TFile*)gROOT->FindObject("//root/Files/myFile.root");
68 ~~~
69 The above statement can be abbreviated to:
70 ~~~ {.cpp}
71  TFile *myFile = (TFile*)gROOT->FindObject("/Files/myFile.root");
72 ~~~
73 or even to:
74 ~~~ {.cpp}
75  TFile *myFile = (TFile*)gROOT->FindObjectAny("myFile.root");
76 ~~~
77 In this last case, the TROOT::FindObjectAny function will scan the folder hierarchy
78 starting at //root and will return the first object named "myFile.root".
79 
80 Because a string-based search mechanism is expensive, it is recommended
81 to save the pointer to the object as a class member or local variable
82 if 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 
94 static const char *gFolderD[64];
95 static Int_t gFolderLevel = -1;
96 static char gFolderPath[512];
97 
98 enum { 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;
111  fIsOwner = kFALSE;
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Create a normal folder.
116 /// Use Add or AddFolder to add objects or folders to this folder.
117 
118 TFolder::TFolder(const char *name, const char *title) : TNamed(name,title)
119 {
120  fFolders = new TList();
122  fIsOwner = kFALSE;
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Copy constructor.
127 
128 TFolder::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 
186 TFolder *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 
235 const 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 
280 const 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 
310 TObject *TFolder::FindObject(const char *name) const
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;
362  if (gFolderLevel >= 0) gFolderD[gFolderLevel] = GetName();
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 
397 void 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 
436 Int_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 {
460  if (fFolders) fFolders->RecursiveRemove(obj);
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 
477 void 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 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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
virtual TObject * Remove(TObject *obj)=0
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
virtual void Clear(Option_t *option="")=0
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2741
virtual void SetOwner(Bool_t owner=kTRUE)
Set ownership.
Definition: TFolder.cxx:492
const char Option_t
Definition: RtypesCore.h:62
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
#define BIT(n)
Definition: Rtypes.h:83
virtual void Remove(TObject *obj)
Remove object from this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:466
static Int_t gFolderLevel
Definition: TFolder.cxx:95
Regular expression class.
Definition: TRegexp.h:31
#define gROOT
Definition: TROOT.h:415
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
Basic string class.
Definition: TString.h:131
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TFolder()
Default constructor used by the Input functions.
Definition: TFolder.cxx:108
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:550
virtual TObject * FindObjectAny(const char *name) const
Return a pointer to the first object with name starting at this folder.
Definition: TFolder.cxx:352
Bool_t fIsOwner
Definition: TFolder.h:34
static const char * gFolderD[64]
Definition: TFolder.cxx:94
void Reset()
Definition: TCollection.h:252
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Delete(Option_t *option="")=0
Delete this object.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
void Class()
Definition: Class.C:29
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void Add(TObject *obj)
Add object to this folder. obj must be a TObject or a TFolder.
Definition: TFolder.cxx:170
Bool_t IsOwner() const
Folder ownership has been set via.
Definition: TFolder.cxx:378
virtual void RecursiveRemove(TObject *obj)
Recursively remove object from a folder.
Definition: TFolder.cxx:458
Bool_t IsOwner() const
Definition: TCollection.h:188
static constexpr double s
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
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:492
A doubly linked list.
Definition: TList.h:44
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
virtual void ls(Option_t *option="") const
List folder contents.
Definition: TFolder.cxx:397
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
TCollection * fFolders
Definition: TFolder.h:33
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Collection abstract base class.
Definition: TCollection.h:63
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2845
static void StartGarbageCollection()
Set up for garbage collection.
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
const Bool_t kFALSE
Definition: RtypesCore.h:88
#define SafeDelete(p)
Definition: RConfig.hxx:543
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
int Ssiz_t
Definition: RtypesCore.h:63
virtual void SaveAs(const char *filename="", Option_t *option="") const
Save all objects in this folder in filename.
Definition: TFolder.cxx:477
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
#define ClassImp(name)
Definition: Rtypes.h:365
virtual void Dump() const
Dump contents of object on stdout.
Definition: TObject.cxx:266
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual void Add(TObject *obj)=0
static void EmptyGarbageCollection()
Do the garbage collection.
TCanvas * slash()
Definition: slash.C:1
virtual TObject * FindObject(const char *name) const
Search object identified by name in the tree of folders inside this folder.
Definition: TFolder.cxx:310
virtual ~TFolder()
Folder destructor.
Definition: TFolder.cxx:137
static char gFolderPath[512]
Definition: TFolder.cxx:96
Mother of all ROOT objects.
Definition: TObject.h:37
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2837
virtual void Copy(TObject &named) const
Copy this to obj.
Definition: TNamed.cxx:94
auto * l
Definition: textangle.C:4
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
#define gDirectory
Definition: TDirectory.h:223
virtual void Clear(Option_t *option="")
Delete all objects from a folder list.
Definition: TFolder.cxx:225
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
const Bool_t kTRUE
Definition: RtypesCore.h:87
const Int_t n
Definition: legend1.C:16
char name[80]
Definition: TGX11.cxx:109
virtual void Browse(TBrowser *b)
Browse this folder.
Definition: TFolder.cxx:217
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48