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