libmoost
|
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__