TFolder.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TFolder.cxx 37531 2010-12-10 20:38:06Z pcanal $
00002 // Author: Rene Brun   02/09/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 //______________________________________________________________________________
00014 //
00015 // A TFolder object is a collection of objects and folders.
00016 // Folders have a name and a title and are identified in the folder hierarchy
00017 // by a "Unix-like" naming mechanism. The root of all folders is //root.
00018 // New folders can be dynamically added or removed to/from a folder.
00019 // The folder hierarchy can be visualized via the TBrowser.
00020 //
00021 // The Root folders hierarchy can be seen as a whiteboard where objects
00022 // are posted. Other classes/tasks can access these objects by specifying
00023 // only a string pathname. This whiteboard facility greatly improves the
00024 // modularity of an application, minimizing the class relationship problem
00025 // that penalizes large applications.
00026 //
00027 // Pointers are efficient to communicate between classes.
00028 // However, one has interest to minimize direct coupling between classes
00029 // in the form of direct pointers. One better uses the naming and search
00030 // service provided by the Root folders hierarchy. This makes the classes
00031 // loosely coupled and also greatly facilitates I/O operations.
00032 // In a client/server environment, this mechanism facilitates the access
00033 // to any kind of object in //root stores running on different processes.
00034 //
00035 // A TFolder is created by invoking the TFolder constructor. It is placed
00036 // inside an existing folder via the TFolder::AddFolder method.
00037 // One can search for a folder or an object in a folder using the FindObject
00038 // method. FindObject analyzes the string passed as its argument and searches
00039 // in the hierarchy until it finds an object or folder matching the name.
00040 //
00041 // When a folder is deleted, its reference from the parent folder and
00042 // possible other folders is deleted.
00043 //
00044 // If a folder has been declared the owner of its objects/folders via
00045 // TFolder::SetOwner, then the contained objects are deleted when the
00046 // folder is deleted. By default, a folder does not own its contained objects.
00047 // NOTE that folder ownership can be set
00048 //   - via TFolder::SetOwner
00049 //   - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
00050 //
00051 // Standard Root objects are automatically added to the folder hierarchy.
00052 // For example, the following folders exist:
00053 //   //root/Files      with the list of currently connected Root files
00054 //   //root/Classes    with the list of active classes
00055 //   //root/Geometries with active geometries
00056 //   //root/Canvases   with the list of active canvases
00057 //   //root/Styles     with the list of graphics styles
00058 //   //root/Colors     with the list of active colors
00059 //
00060 // For example, if a file "myFile.root" is added to the list of files, one can
00061 // retrieve a pointer to the corresponding TFile object with a statement like:
00062 //   TFile *myFile = (TFile*)gROOT->FindObject("//root/Files/myFile.root");
00063 // The above statement can be abbreviated to:
00064 //   TFile *myFile = (TFile*)gROOT->FindObject("/Files/myFile.root");
00065 // or even to:
00066 //   TFile *myFile = (TFile*)gROOT->FindObjectAny("myFile.root");
00067 // In this last case, the TROOT::FindObjectAny function will scan the folder hierarchy
00068 // starting at //root and will return the first object named "myFile.root".
00069 //
00070 // Because a string-based search mechanism is expensive, it is recommended
00071 // to save the pointer to the object as a class member or local variable
00072 // if this pointer is used frequently or inside loops.
00073 //
00074 //Begin_Html
00075 /*
00076 <img src="gif/folder.gif">
00077 */
00078 //End_Html
00079 
00080 #include "Riostream.h"
00081 #include "Strlen.h"
00082 #include "TFolder.h"
00083 #include "TBrowser.h"
00084 #include "TROOT.h"
00085 #include "TClass.h"
00086 #include "TError.h"
00087 #include "TRegexp.h"
00088 
00089 static const char *gFolderD[64];
00090 static Int_t gFolderLevel = -1;
00091 static char  gFolderPath[512];
00092 
00093 enum { kOwnFolderList = BIT(15) };
00094 
00095 ClassImp(TFolder)
00096 
00097 //______________________________________________________________________________
00098 TFolder::TFolder() : TNamed()
00099 {
00100    // Default constructor used by the Input functions.
00101    //
00102    // This constructor should not be called by a user directly.
00103    // The normal way to create a folder is by calling TFolder::AddFolder.
00104 
00105    fFolders = 0;
00106    fIsOwner = kFALSE;
00107 }
00108 
00109 //______________________________________________________________________________
00110 TFolder::TFolder(const char *name, const char *title) : TNamed(name,title)
00111 {
00112    // Create a normal folder.
00113    // Use Add or AddFolder to add objects or folders to this folder.
00114 
00115    fFolders = new TList();
00116    SetBit(kOwnFolderList);
00117    fIsOwner = kFALSE;
00118 }
00119 
00120 //______________________________________________________________________________
00121 TFolder::TFolder(const TFolder &folder) : TNamed(folder),fFolders(0),fIsOwner(kFALSE)
00122 {
00123    // Copy constructor.
00124 
00125    ((TFolder&)folder).Copy(*this);
00126 }
00127 
00128 //______________________________________________________________________________
00129 TFolder::~TFolder()
00130 {
00131    // Folder destructor. Remove all objects from its lists and delete
00132    // all its sub folders.
00133 
00134    TCollection::StartGarbageCollection();
00135    
00136    if (fFolders) {
00137       if (fFolders->IsOwner()) {
00138          fFolders->Delete();
00139       }
00140       if (TestBit(kOwnFolderList)) {
00141          TObjLink *iter = ((TList*)fFolders)->FirstLink();
00142          while (iter) {
00143             TObject *obj = iter->GetObject();
00144             TObjLink *next = iter->Next();
00145             if (obj && obj->IsA() == TFolder::Class()) {
00146                ((TList*)fFolders)->Remove(iter);
00147                delete obj;
00148             }
00149             iter = next;
00150          }
00151          fFolders->Clear("nodelete");
00152          SafeDelete(fFolders);
00153       }
00154    }
00155 
00156    TCollection::EmptyGarbageCollection();
00157    
00158    if (gDebug)
00159       cerr << "TFolder dtor called for "<< GetName() << endl;
00160 }
00161 
00162 //______________________________________________________________________________
00163 void TFolder::Add(TObject *obj)
00164 {
00165    // Add object to this folder. obj must be a TObject or a TFolder.
00166 
00167    if (obj == 0 || fFolders == 0) return;
00168    obj->SetBit(kMustCleanup);
00169    fFolders->Add(obj);
00170 }
00171 
00172 //______________________________________________________________________________
00173 TFolder *TFolder::AddFolder(const char *name, const char *title, TCollection *collection)
00174 {
00175    // Create a new folder and add it to the list of folders of this folder,
00176    // return a pointer to the created folder.
00177    // Note that a folder can be added to several folders.
00178    //
00179    // If collection is non NULL, the pointer fFolders is set to the existing
00180    // collection, otherwise a default collection (Tlist) is created.
00181    // Note that the folder name cannot contain slashes.
00182 
00183    if (strchr(name,'/')) {
00184       ::Error("TFolder::TFolder","folder name cannot contain a slash: %s", name);
00185       return 0;
00186    }
00187    if (strlen(GetName()) == 0) {
00188       ::Error("TFolder::TFolder","folder name cannot be \"\"");
00189       return 0;
00190    }
00191    TFolder *folder = new TFolder();
00192    folder->SetName(name);
00193    folder->SetTitle(title);
00194    if (!fFolders) {
00195       fFolders = new TList(); //only true when gROOT creates its 1st folder
00196       SetBit(kOwnFolderList);
00197    }
00198    fFolders->Add(folder);
00199 
00200    if (collection) {
00201       folder->fFolders = collection;
00202    } else {
00203       folder->fFolders = new TList();
00204       folder->SetBit(kOwnFolderList);
00205    }
00206    return folder;
00207 }
00208 
00209 //______________________________________________________________________________
00210 void TFolder::Browse(TBrowser *b)
00211 {
00212    // Browse this folder.
00213 
00214    if (fFolders) fFolders->Browse(b);
00215 }
00216 
00217 //______________________________________________________________________________
00218 void TFolder::Clear(Option_t *option)
00219 {
00220    // Delete all objects from a folder list.
00221 
00222    if (fFolders) fFolders->Clear(option);
00223 }
00224 
00225 //______________________________________________________________________________
00226 const char *TFolder::FindFullPathName(const char *name) const
00227 {
00228    // Return the full pathname corresponding to subpath name.
00229    // The returned path will be re-used by the next call to GetPath().
00230 
00231    TObject *obj = FindObject(name);
00232    if (obj || !fFolders) {
00233       gFolderLevel++;
00234       gFolderD[gFolderLevel] = GetName();
00235       gFolderPath[0] = '/';
00236       gFolderPath[1] = 0;
00237       for (Int_t l=0;l<=gFolderLevel;l++) {
00238          strlcat(gFolderPath, "/", sizeof(gFolderPath));
00239          strlcat(gFolderPath, gFolderD[l], sizeof(gFolderPath));
00240       }
00241       strlcat(gFolderPath, "/", sizeof(gFolderPath));
00242       strlcat(gFolderPath,name, sizeof(gFolderPath));
00243       gFolderLevel = -1;
00244       return gFolderPath;
00245    }
00246    if (name[0] == '/') return 0;
00247    TIter next(fFolders);
00248    TFolder *folder;
00249    const char *found;
00250    gFolderLevel++;
00251    gFolderD[gFolderLevel] = GetName();
00252    while ((obj=next())) {
00253       if (!obj->InheritsFrom(TFolder::Class())) continue;
00254       if (obj->InheritsFrom(TClass::Class())) continue;
00255       folder = (TFolder*)obj;
00256       found = folder->FindFullPathName(name);
00257       if (found) return found;
00258    }
00259    gFolderLevel--;
00260    return 0;
00261 }
00262 
00263 
00264 //______________________________________________________________________________
00265 const char *TFolder::FindFullPathName(const TObject *) const
00266 {
00267    // Return the full pathname corresponding to subpath name.
00268    // The returned path will be re-used by the next call to GetPath().
00269 
00270    Error("FindFullPathname","Not yet implemented");
00271    return 0;
00272 }
00273 
00274 //______________________________________________________________________________
00275 TObject *TFolder::FindObject(const TObject *) const
00276 {
00277    // Find object in an folder.
00278 
00279    Error("FindObject","Not yet implemented");
00280    return 0;
00281 }
00282 
00283 //______________________________________________________________________________
00284 TObject *TFolder::FindObject(const char *name) const
00285 {
00286    // Search object identified by name in the tree of folders inside
00287    // this folder.
00288    // Name may be of the forms:
00289    //   A, Specify a full pathname starting at the top ROOT folder
00290    //     //root/xxx/yyy/name
00291    //
00292    //   B, Specify a pathname starting with a single slash. //root is assumed
00293    //     /xxx/yyy/name
00294    //
00295    //   C, Specify a pathname relative to this folder
00296    //     xxx/yyy/name
00297    //     name
00298 
00299    if (!fFolders) return 0;
00300    if (name == 0) return 0;
00301    if (name[0] == '/') {
00302       if (name[1] == '/') {
00303          if (!strstr(name,"//root/")) return 0;
00304          return gROOT->GetRootFolder()->FindObject(name+7);
00305       } else {
00306          return gROOT->GetRootFolder()->FindObject(name+1);
00307       }
00308    }
00309    Int_t nch = strlen(name);
00310    char *cname;
00311    char csname[128];
00312    if (nch < (int)sizeof(csname))
00313       cname = csname;
00314    else
00315       cname = new char[nch+1];
00316    strcpy(cname, name);
00317    TObject *obj;
00318    char *slash = strchr(cname,'/');
00319    if (slash) {
00320       *slash = 0;
00321       obj = fFolders->FindObject(cname);
00322       if (!obj) {
00323          if (nch >= (int)sizeof(csname)) delete [] cname;
00324          return 0;
00325       }
00326       TObject *ret = obj->FindObject(slash+1);
00327       if (nch >= (int)sizeof(csname)) delete [] cname;
00328       return ret;
00329    } else {
00330       TObject *ret = fFolders->FindObject(cname);
00331       if (nch >= (int)sizeof(csname)) delete [] cname;
00332       return ret;
00333    }
00334 }
00335 
00336 //______________________________________________________________________________
00337 TObject *TFolder::FindObjectAny(const char *name) const
00338 {
00339    // Return a pointer to the first object with name starting at this folder.
00340 
00341    TObject *obj = FindObject(name);
00342    if (obj || !fFolders) return obj;
00343 
00344    //if (!obj->InheritsFrom(TFolder::Class())) continue;
00345    if (name[0] == '/') return 0;
00346    TIter next(fFolders);
00347    TFolder *folder;
00348    TObject *found;
00349    if (gFolderLevel >= 0) gFolderD[gFolderLevel] = GetName();
00350    while ((obj=next())) {
00351       if (!obj->InheritsFrom(TFolder::Class())) continue;
00352       if (obj->IsA() == TClass::Class()) continue;
00353       folder = (TFolder*)obj;
00354       found = folder->FindObjectAny(name);
00355       if (found) return found;
00356    }
00357    return 0;
00358 }
00359 
00360 //______________________________________________________________________________
00361 Bool_t TFolder::IsOwner()  const
00362 {
00363    // Folder ownership has been set via
00364    //   - TFolder::SetOwner
00365    //   - TCollection::SetOwner on the collection specified to TFolder::AddFolder
00366 
00367    if (!fFolders) return kFALSE;
00368    return fFolders->IsOwner();
00369 }
00370 
00371 //______________________________________________________________________________
00372 void TFolder::ls(Option_t *option) const
00373 {
00374    // List folder contents
00375    //   If option contains "dump",  the Dump function of contained objects is called.
00376    //   If option contains "print", the Print function of contained objects is called.
00377    //   By default the ls function of contained objects is called.
00378    // Indentation is used to identify the folder tree.
00379    //
00380    // The if option contains a <regexp> it be used to match the name of the objects.
00381 
00382    if (!fFolders) return;
00383    TROOT::IndentLevel();
00384    cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<endl;
00385    TROOT::IncreaseDirLevel();
00386 
00387    TString opt = option;
00388    Ssiz_t dump = opt.Index("dump", 0, TString::kIgnoreCase);
00389    if (dump != kNPOS)
00390       opt.Remove(dump, 4);
00391    Ssiz_t print = opt.Index("print", 0, TString::kIgnoreCase);
00392    if (print != kNPOS)
00393       opt.Remove(print, 5);
00394    opt = opt.Strip(TString::kBoth);
00395    if (opt == "")
00396       opt = "*";
00397    TRegexp re(opt, kTRUE);
00398 
00399    TObject *obj;
00400    TIter nextobj(fFolders);
00401    while ((obj = (TObject *) nextobj())) {
00402       TString s = obj->GetName();
00403       if (s.Index(re) == kNPOS) continue;
00404       if (dump != kNPOS)
00405          obj->Dump();
00406       if (print != kNPOS)
00407          obj->Print(option);
00408       obj->ls(option);
00409    }
00410    TROOT::DecreaseDirLevel();
00411 }
00412 
00413 //______________________________________________________________________________
00414 Int_t TFolder::Occurence(const TObject *object) const
00415 {
00416    // Return occurence number of object in the list of objects of this folder.
00417    // The function returns the number of objects with the same name as object
00418    // found in the list of objects in this folder before object itself.
00419    // If only one object is found, return 0.
00420 
00421    Int_t n = 0;
00422    if (!fFolders) return 0;
00423    TIter next(fFolders);
00424    TObject *obj;
00425    while ((obj=next())) {
00426       if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
00427    }
00428    if (n <=1) return n-1;
00429    n = 0;
00430    next.Reset();
00431    while ((obj=next())) {
00432       if (strcmp(obj->GetName(),object->GetName()) == 0) n++;
00433       if (obj == object) return n;
00434    }
00435    return 0;
00436 }
00437 
00438 //______________________________________________________________________________
00439 void TFolder::RecursiveRemove(TObject *obj)
00440 {
00441    // Recursively remove object from a folder.
00442 
00443    if (fFolders) fFolders->RecursiveRemove(obj);
00444 }
00445 
00446 //______________________________________________________________________________
00447 void TFolder::Remove(TObject *obj)
00448 {
00449    // Remove object from this folder. obj must be a TObject or a TFolder.
00450 
00451    if (obj == 0 || fFolders == 0) return;
00452    fFolders->Remove(obj);
00453 }
00454 
00455 //______________________________________________________________________________
00456 void TFolder::SaveAs(const char *filename, Option_t *option) const
00457 {
00458    // Save all objects in this folder in filename.
00459    // Each object in this folder will have a key in the file where the name of
00460    // the key will be the name of the object.
00461 
00462    if (gDirectory) gDirectory->SaveObjectAs(this,filename,option);
00463 }
00464 
00465 //______________________________________________________________________________
00466 void TFolder::SetOwner(Bool_t owner)
00467 {
00468    // Set ownership.
00469    // If the folder is declared owner, when the folder is deleted, all
00470    // the objects added via TFolder::Add are deleted via TObject::Delete,
00471    // otherwise TObject::Clear is called.
00472    //
00473    // NOTE that folder ownership can be set:
00474    //   - via TFolder::SetOwner
00475    //   - or via TCollection::SetOwner on the collection specified to TFolder::AddFolder
00476 
00477    if (!fFolders) fFolders = new TList();
00478    fFolders->SetOwner(owner);
00479 }

Generated on Tue Jul 5 14:11:21 2011 for ROOT_528-00b_version by  doxygen 1.5.1