Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:38:19

0001 // -*- C++ -*-
0002 //
0003 // Tree.h is a part of ThePEG - Toolkit for HEP Event Generation
0004 // Copyright (C) 1999-2019 Leif Lonnblad
0005 //
0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 #ifndef LWH_Tree_H
0010 #define LWH_Tree_H
0011 //
0012 // This is the declaration of the Tree class.
0013 //
0014 
0015 #include "AITree.h"
0016 #include "ManagedObject.h"
0017 #include <fstream>
0018 #include <iostream>
0019 #include <vector>
0020 #include <set>
0021 #include <map>
0022 #include <string>
0023 
0024 namespace LWH {
0025 
0026 using namespace AIDA;
0027 
0028 /**
0029  * The Tree class is a simple implementation of the AIDA::ITree
0030  * interface.
0031  */
0032 class Tree: public ITree {
0033 
0034 public:
0035 
0036   /** The AnalysisFactory is a friend. */
0037   friend class AnalysisFactory;
0038 
0039   /** A path is a vector of directory names. */
0040   typedef std::vector<std::string> Path;
0041 
0042   /** A set of paths */
0043   typedef std::set<Path> PathSet;
0044 
0045   /** Map of paths to objects. */
0046   typedef std::map<std::string, IManagedObject *> ObjMap;
0047 
0048 public:
0049 
0050   /**
0051    * The standard constructor.
0052    */
0053   Tree(std::string storename, bool xml = true)
0054     : name(storename), flat(!xml), cwd("/"), overwrite(true) {
0055     dirs.insert(Path());
0056   }
0057 
0058   /**
0059    * The default constructor.
0060    */
0061   Tree(): name(""), flat(false), cwd("/") {
0062     dirs.insert(Path());
0063   }
0064 
0065   /**
0066    * The copy constructor.
0067    */
0068   Tree(const Tree & dt)
0069     : ITree(dt), name(dt.name), flat(dt.flat), dirs(dt.dirs),
0070       objs(dt.objs), cwd(dt.cwd), overwrite(true) {}
0071 
0072   /// Destructor.
0073   virtual ~Tree() {
0074     for ( ObjMap::iterator it = objs.begin(); it != objs.end(); ++it )
0075       delete it->second;
0076   }
0077 
0078   /**
0079    * Get the name of the store.
0080    * @return The store's name.
0081    */
0082   std::string storeName() const {
0083     return name;
0084   }
0085 
0086   /**
0087    * Get the IManagedObject at a given path in the ITree. The path can either be
0088    * absolute or relative to the current working directory.
0089    * @param path The path.
0090    * @return     The corresponding IManagedObject.
0091    */
0092   IManagedObject * find(const std::string & path) {
0093     ObjMap::const_iterator it = objs.find(path);
0094     return it == objs.end()? (IManagedObject *)0: it->second;
0095   }
0096 
0097   /**
0098    * LWH cannot get a mounted ITree at a given path in the current ITree.
0099    * @return     0 always.
0100    */
0101   ITree * findTree(const std::string &) {
0102     return 0;
0103   }
0104 
0105   /**
0106    * Change to a given directory.
0107    * @param dir The absolute or relative path of the directory we are
0108    * changing to.
0109    * @return false If the path does not exist.
0110    */
0111   bool cd(const std::string & dir) {
0112     PathSet::iterator it = dirs.find(purgepath(str2pth(fullpath(sts(dir)))));
0113     if ( it == dirs.end() ) return false;
0114     cwd = pth2str(*it);
0115     return true;
0116   }
0117 
0118   /**
0119    * Insert the ManagedObject \a o in the tree with the path \a str.
0120    */
0121   bool insert(std::string str, IManagedObject * o) {
0122     Path path = purgepath(str2pth(fullpath(str)));
0123     if ( dirs.find(path) == dirs.end() ) {
0124       std::string fullname = pth2str(path);
0125       path.pop_back();
0126       if ( dirs.find(path) != dirs.end() ) {
0127     ObjMap::iterator old = objs.find(fullname);
0128     if ( old == objs.end() || overwrite ) {
0129       if ( old != objs.end() ) {
0130         delete old->second;
0131         objs.erase(old);
0132       }
0133       objs[fullname] = o;
0134       return true;
0135     }
0136       }
0137     }
0138     return false;
0139   }
0140 
0141   /**
0142    * Get the path of the current working directory.
0143    * @return The path of the current working directory.
0144    */
0145   std::string pwd() const {
0146     return cwd;
0147   }
0148 
0149   /** 
0150    * Not implemented in LWH.
0151    * @return false always.
0152    *
0153    */
0154   bool ls(const std::string & = ".", bool = false,
0155       std::ostream & = std::cout) const {
0156     return false;
0157   }
0158 
0159   /**
0160    * Not implemented in LWH.
0161    */
0162   std::vector<std::string> listObjectNames(const std::string & = ".",
0163                        bool = false) const {
0164     return std::vector<std::string>();
0165   }
0166 
0167   /**
0168    * Not implemented in LWH.
0169    */
0170   std::vector<std::string> listObjectTypes(const std::string & = ".",
0171                        bool = false) const {
0172     return std::vector<std::string>();
0173   }
0174 
0175   /**
0176    * Create a new directory. Given a path only the last directory
0177    * in it is created if all the intermediate subdirectories already exist.
0178    * @param dir The absolute or relative path of the new directory.
0179    * @return false If a subdirectory within the path does
0180    * not exist or it is not a directory. Also if the directory already exists.
0181    */   
0182   bool mkdir(const std::string & dir) {
0183     Path p = purgepath(str2pth(fullpath(sts(dir))));
0184     Path base = p;
0185     base.pop_back();
0186     if ( dirs.find(base) == dirs.end() ) return false;
0187     dirs.insert(p);
0188     return true;
0189   }
0190 
0191   /**
0192    * Create a directory recursively. Given a path the last directory
0193    * and all the intermediate non-existing subdirectories are created.
0194    * @param dir The absolute or relative path of the new directory.
0195    * @return false If an intermediate subdirectory
0196    *             is not a directory, or if the directory already exists.
0197    */
0198   bool mkdirs(const std::string & dir) {
0199     return mkdirs(purgepath(str2pth(fullpath(sts(dir)))));
0200   }
0201 
0202   /**
0203    * Create a directory recursively. Given a Path the last directory
0204    * and all the intermediate non-existing subdirectories are created.
0205    * @param p The full Path of the new directory.
0206    * @return false If an intermediate subdirectory
0207    *             is not a directory, or if the directory already exists.
0208    */
0209   bool mkdirs(Path p) {
0210     if ( dirs.find(p) != dirs.end() ) return true;
0211     dirs.insert(p);
0212     p.pop_back();
0213     return mkdirs(p);
0214   }
0215 
0216   /**
0217    * Remove a directory and all the contents underneeth.
0218    * @param dir The absolute or relative path of the directory to be removed.
0219    * @return false If path does not exist or if it is not
0220    *             a directory or if the directory is not empty.
0221    */
0222   bool rmdir(const std::string & dir) {
0223     Path path = purgepath(str2pth(fullpath(sts(dir))));
0224     if ( dirs.find(path) == dirs.end() ) return false;
0225     for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
0226       if ( it->first.substr(0, dir.length()) == dir ) return false;
0227     dirs.erase(path);
0228     return true;
0229   }
0230 
0231   /**
0232    * Remove and delete an IManagedObject by specifying its path.
0233    * @param path The absolute or relative path of the IManagedObject to be
0234    * removed.
0235    * @return false If path does not exist.
0236    */
0237   bool rm(const std::string & path) {
0238     ObjMap::iterator it = objs.find(fullpath(path));
0239     if ( it == objs.end() ) return false;
0240     delete it->second;
0241     objs.erase(it);
0242     return true;
0243   }
0244 
0245   /**
0246    * Get the full path of an IManagedObject.
0247    * @param o The IManagedObject whose path is to be returned.
0248    * @return  The object's absolute path.
0249    *          If the object does not exist, an empty string is returned.
0250    */
0251   std::string findPath(const IManagedObject & o) const {
0252     for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
0253       if ( it->second == &o ) return it->first;
0254     return "";
0255   }
0256 
0257   /**
0258    * Move an IManagedObject or a directory from one directory to another.
0259    * @param oldp The path of the IManagedObject [not direcoty] to be moved.
0260    * @param newp The path of the diretory in which the object has to be
0261    * moved to.
0262    * @return false If either path does not exist.
0263    */
0264   bool mv(const std::string & oldp, const std::string & newp) {
0265     Path newpath = purgepath(str2pth(fullpath(sts(newp))));
0266     std::string foldp = fullpath(oldp);
0267     Path oldpath = purgepath(str2pth(foldp));
0268     ObjMap::iterator it = objs.find(foldp);
0269     if ( it == objs.end() ) return false;
0270     if ( dirs.find(newpath) != dirs.end() ) return false;
0271     newpath.push_back(oldpath.back());
0272     if ( !insert(pth2str(newpath), it->second) ) return false;
0273     objs.erase(foldp);
0274     return true;
0275   }
0276 
0277   /**
0278    * Print all histograms to the current filename.
0279    * @return false if something went wrong.
0280    */
0281   bool commit() {
0282     std::ofstream of(name.c_str());
0283     if ( !of ) return false;
0284     if ( !flat ) of
0285       << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE aida SYSTEM "
0286       << "\"http://aida.freehep.org/schemas/3.0/aida.dtd\">\n"
0287       << "<aida version=\"3.0\">\n"
0288       << "<implementation version=\"1.0\" package=\"FreeHEP\"/>" << std::endl;
0289     for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) {
0290       ManagedObject * o = dynamic_cast<ManagedObject *>(it->second);
0291       if ( !o ) continue;
0292       std::string path = it->first.substr(0, it->first.rfind('/'));
0293       std::string name = it->first.substr(it->first.rfind('/') + 1);
0294       if ( flat )
0295     o->writeFLAT(of, path, name);
0296       else
0297     o->writeXML(of, path, name);
0298     }
0299     if ( !flat ) of << "</aida>" << std::endl;
0300     return of.good();
0301   }
0302 
0303   /**
0304    * Not implemented in LWH.
0305    */
0306   void setOverwrite(bool o = true) {
0307     overwrite = o;
0308   }
0309 
0310   /**
0311    * Not implemented in LWH.
0312    * @return false always.
0313    */
0314   bool cp(const std::string &, const std::string &, bool = false) {
0315     return false;
0316   }
0317 
0318   /**
0319    * Not implemented in LWH.
0320    * @return false always.
0321    */
0322   bool symlink(const std::string &, const std::string &) {
0323     return false;
0324   }
0325 
0326   /**
0327    * Not implemented in LWH.
0328    * @return false always.
0329    */
0330   bool mount(const std::string &, ITree &, const std::string &) {
0331     return false;
0332   }
0333 
0334   /**
0335    * Not implemented in LWH.
0336    * @return false always.
0337    */
0338   bool unmount(const std::string &) {
0339     return false;
0340   }
0341 
0342   /**
0343    * Calls commit().
0344    */
0345   bool close() {
0346     return commit();
0347   }
0348 
0349   /**
0350    * Not implemented in LWH.
0351    * @return null pointer always.
0352    */ 
0353   void * cast(const std::string &) const {
0354     return 0;
0355   }
0356 
0357 protected:
0358 
0359   /** Strip trailing slash. */
0360   std::string sts(std::string s) const {
0361     if ( s[s.length() - 1] == '/' ) s = s.substr(0, s.length() - 1);
0362     if ( s[s.length() - 1] == '/' ) return "";
0363     return s;
0364   }
0365 
0366   /** Strip trailing name */
0367   std::string stn(std::string s) const {
0368     std::string::size_type slash = s.rfind('/');
0369     return s.substr(0, slash);
0370   }
0371 
0372   /** Get proper full path from possibly relative path. */
0373   std::string fullpath(std::string d) const {
0374     if ( d[0] != '/' ) d = cwd + "/" + d;
0375     return pth2str(purgepath(str2pth(d)));
0376   }
0377 
0378   /** Convert a string containing a path to a Path object. */
0379   Path str2pth(std::string s) const {
0380     Path pth;
0381     std::string::size_type i = s.find_first_not_of("/");
0382     while ( i != std::string::npos ) {
0383       s = s.substr(i);
0384       i = s.find_first_of("/");
0385       pth.push_back(s.substr(0, i));
0386       if ( i == std::string::npos ) return pth;
0387       s = s.substr(i);
0388       i = s.find_first_not_of("/");
0389     }
0390     return pth;
0391   }
0392 
0393   /** Convert a Path object to a corresponding string. */
0394   std::string pth2str(const Path & pth) const {
0395     std::string str;
0396     for ( int i = 0, N = pth.size(); i < N; ++i ) str += "/" + pth[i];
0397     return str;
0398   }
0399 
0400   /** Remove '..' and '.' components of the given Path object. */
0401   Path purgepath(const Path & pth) const {
0402     Path p;
0403     for ( int i = 0, N = pth.size(); i < N; ++i ) {
0404       if ( pth[i] == ".." ) p.pop_back();
0405       else if ( pth[i] != "." ) p.push_back(pth[i]);
0406     }
0407     return p;
0408   }
0409 
0410 private:
0411 
0412   /** The filename to print histograms to. */
0413   std::string name;
0414 
0415   /** If true write histograms in FLAT format, otherwise in XML. */
0416   bool flat;
0417 
0418   /** The set of defined directories. */
0419   PathSet dirs;
0420 
0421   /** The set of defined objects. */
0422   ObjMap objs;
0423 
0424   /** The current working directory. */
0425   std::string cwd;
0426 
0427   /** Overwrite strategy. */
0428   bool overwrite;
0429 
0430 };
0431 
0432 }
0433 
0434 #endif /* LWH_Tree_H */