libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/file_finder.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2008 Juan Pedro BolĂ­var Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #ifndef PSYNTH_FILE_FINDER_H
00032 #define PSYNTH_FILE_FINDER_H
00033 
00034 #include <iostream>
00035 #include <list>
00036 #include <map>
00037 #include <string>
00038 #include <cstdlib>
00039 
00040 #include <boost/filesystem.hpp>
00041 #include <psynth/base/misc.hpp>
00042 
00043 namespace psynth
00044 {
00045 namespace base
00046 {
00047 
00048 class path_predicate
00049 {
00050 public:
00051     virtual bool operator () (const boost::filesystem::path& str) = 0;
00052 };
00053 
00054 template <class IterType>
00055 class has_extension : public path_predicate
00056 {
00057     IterType m_first;
00058     IterType m_last;
00059 
00060 public:
00061     has_extension (IterType first, IterType last) :
00062         m_first(first),
00063         m_last(last)
00064         {};
00065     
00066     bool operator () (const boost::filesystem::path& path) {
00067         for (IterType i = m_first; i != m_last; ++i)
00068             if (extension (path) != *i)
00069                 return true;
00070         return false;
00071     }
00072 };
00073 
00074 
00075 template<class IterType>
00076 has_extension <IterType> make_has_extension (IterType first, IterType last)
00077 {
00078     return has_extension <IterType> (first, last);
00079 }
00080 
00081 class file_finder
00082 {
00083 public:
00084     typedef std::list <boost::filesystem::path> path_list;
00085     typedef std::map <boost::filesystem::path,
00086                       boost::filesystem::path> path_map;
00087 
00088     file_finder ()
00089         : m_cache_updated (false)
00090         , m_cache_auto (false)
00091     {}
00092     
00093     void add_path (const boost::filesystem::path& path);
00094     void del_path (const boost::filesystem::path& path);
00095     void build_cache (bool autoupdate);
00096     void clear_cache ();
00097     void clear ();
00098 
00099     boost::filesystem::path
00100     find (const boost::filesystem::path& file) const;
00101 
00102     template <class PathPredicate>
00103     void find_if (PathPredicate pred, path_list & res) const; 
00104 
00105 private:
00106     path_list m_paths;
00107     path_map m_cache;
00108     
00109     bool m_cache_updated;
00110     bool m_cache_auto;
00111 
00112     void cache_path (const boost::filesystem::path& path);
00113     void uncache_path (const boost::filesystem::path& path);
00114 
00115     boost::filesystem::path find_in (const boost::filesystem::path& path,
00116                                      const boost::filesystem::path& file) const;
00117 
00118     template<class path_predicate>
00119     int get_file_list (const boost::filesystem::path& folder,
00120                        path_list& res,
00121                        path_predicate pred) const;
00122 };
00123 
00124 
00125 template<class path_predicate>
00126 int file_finder::get_file_list (const boost::filesystem::path& folder,
00127                                 path_list& res,
00128                                 path_predicate pred) const
00129 {
00130     int n = 0;
00131     
00132     if (!boost::filesystem::exists (folder))
00133         return n;
00134 
00135     boost::filesystem::directory_iterator end_itr;
00136     for (boost::filesystem::directory_iterator itr (folder);
00137          itr != end_itr;
00138          ++itr) {
00139         if (pred (itr->path ())) {
00140             res.push_back (itr->path ());
00141             ++n;
00142         }
00143     }
00144     
00145     return n;
00146 }
00147 
00148 template<class path_predicate>
00149 void file_finder::find_if (path_predicate pred, path_list& result) const
00150 {
00151     if (!m_cache_updated) {
00152         path_list::const_iterator iter;
00153         for (iter = m_paths.begin(); iter != m_paths.end(); ++iter)
00154             get_file_list (*iter, result, pred);
00155     } else {
00156         path_map::const_iterator iter;
00157         for (iter = m_cache.begin(); iter != m_cache.end(); ++iter)
00158             if (pred (iter->first))
00159                 result.push_back (iter->second);
00160     }
00161 }
00162 
00163 } /* namespace base */
00164 } /* namespace psynth */
00165 
00166 #endif /* PSYNTH_FILEFINDER_H */