libmoost
/home/mhx/git/github/libmoost/include/moost/iterator/glob_iterator.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00058 #ifndef MOOST_ITERATOR_GLOB_ITERATOR_HPP__
00059 #define MOOST_ITERATOR_GLOB_ITERATOR_HPP__
00060 
00061 #include <string>
00062 #include <sstream>
00063 
00064 #include <boost/filesystem.hpp>
00065 #include <boost/iterator/filter_iterator.hpp>
00066 #include <boost/regex.hpp>
00067 
00071 namespace moost { namespace iterator {
00072 
00082 class glob_predicate
00083 {
00084 public:
00092    glob_predicate()
00093       : glob_(false)
00094    {
00095    }
00096 
00104    glob_predicate(boost::regex const & re)
00105       : filter_(re)
00106       , glob_(false)
00107    {
00108    }
00109 
00117    glob_predicate(std::string const & glob)
00118       : filter_(glob2re(glob))
00119       , glob_(true)
00120    {
00121    }
00122 
00131    bool operator()(boost::filesystem::path p) const
00132    {
00133       return glob_ ?
00134          // when we're globbing we want to force an exact match
00135          boost::regex_match(p.string(), filter_) :
00136          // when we're pattern matching use search for flexibility
00137          boost::regex_search(p.string(), filter_);
00138    }
00139 
00140 private:
00141    boost::regex glob2re(std::string const & glob)
00142    {
00143       std::ostringstream oss;
00144       bool lesc = false;
00145 
00146       // iterate glob and convert to regex
00147       for(std::string::const_iterator itr = glob.begin() ;
00148           itr != glob.end(); ++itr)
00149       {
00150          bool oesc = false;
00151 
00152          switch(*itr)
00153          {
00154             // slash is an esc-char unless it's the 2nd one else its a literal
00155             case '\\':
00156                if(lesc) { oss << "\\\\"; }
00157                oesc = !lesc;
00158                break;
00159             // match 0 or more chars
00160             case '*':
00161                oss << (lesc ? "\\*" : ".*");
00162                break;
00163             // match 1 char
00164             case '?':
00165                oss << (lesc ? "\\?" : ".");
00166                break;
00167             // literal dot
00168             case '.':
00169                oss << "\\.";
00170                break;
00171             // everything else
00172             default:
00173                oss << *itr;
00174                break;
00175          };
00176 
00177          lesc = oesc;
00178       }
00179 
00180       return boost::regex(oss.str());
00181    }
00182 
00183    boost::regex filter_;
00184    bool glob_;
00185 };
00186 
00202 typedef boost::filter_iterator<
00203    glob_predicate,
00204    boost::filesystem::directory_iterator
00205    > glob_iterator;
00206 
00207 }}
00208 
00209 
00210 #endif // MOOST_ITERATOR_GLOB_ITERATOR_HPP__