00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef ASTL_DIR_CURSOR_H
00023 #define ASTL_DIR_CURSOR_H
00024
00025
00026 #ifndef _MSC_VER
00027
00028 #include <astl.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <unistd.h>
00032 #include <dirent.h>
00033 #include <string>
00034 #include <cstring>
00035 #include <climits>
00036 #include <functional>
00037
00038 using namespace std;
00039
00040 namespace astl {
00041
00042
00043
00044
00045
00046 struct default_predicate
00047 : public binary_function<string, struct stat *, bool>
00048 {
00049 bool operator()(const string &, const struct stat *s) const {
00050 return !S_ISDIR(s->st_mode);
00051 }
00052 };
00053
00054 template <class Predicate = default_predicate>
00055 class directory_cursor : public forward_cursor_concept
00056 {
00057 protected:
00058 string state, transition;
00059 DIR *dir;
00060
00061 public:
00062 typedef directory_cursor self;
00063 typedef time_t tag_type;
00064 typedef string state_type;
00065 typedef string char_type;
00066
00067 typedef std::char_traits<string> char_traits;
00068
00069 directory_cursor()
00070 : dir(NULL)
00071 { }
00072
00073 directory_cursor(const string &dir_)
00074 : state(dir_) {
00075 dir = opendir(state.c_str());
00076 }
00077
00078 directory_cursor(const self &x)
00079 : state(x.state), transition(x.transition), dir(x.dir) {
00080 if (x.dir) {
00081 dir = opendir(state.c_str());
00082 if (!transition.empty())
00083 seekdir(dir, telldir(x.dir));
00084 }
00085 }
00086
00087 ~directory_cursor() { if (dir) closedir(dir); }
00088
00089 state_type src() const { return state; }
00090
00091 self& operator=(const state_type& p)
00092 {
00093 state = p;
00094 if (dir) closedir(dir);
00095 dir = opendir(state.c_str());
00096 return *this;
00097 }
00098
00099 bool sink() const { return state.empty(); }
00100
00101 bool forward(const char_type &a)
00102 {
00103 struct dirent *entry;
00104 for(rewinddir(dir); (entry = readdir(dir)) != NULL; )
00105 if (strcmp(a.c_str(), entry->d_name)) {
00106 state += '/';
00107 state += entry->d_name;
00108 closedir(dir);
00109 dir = opendir(state.c_str());
00110 return true;
00111 }
00112 closedir(dir);
00113 dir = NULL;
00114 state.clear();
00115 return false;
00116 }
00117
00118 bool src_final() const
00119 {
00120 struct stat s;
00121 stat(state.c_str(), &s);
00122 return Predicate()(state, &s);
00123 }
00124
00125 tag_type src_tag() const {
00126 struct stat s;
00127 stat(state.c_str(), &s);
00128 return s.st_mtime;
00129 }
00130
00131 bool exists(const char_type &a) const {
00132 struct dirent *tmp_entry = NULL;
00133 DIR *d = opendir(state.c_str());
00134 if (d) {
00135 for(rewinddir(d); (tmp_entry = readdir(d)) != NULL; )
00136 if (strcmp(a.c_str(), tmp_entry->d_name)) break;
00137
00138 closedir(d);
00139 }
00140 return tmp_entry != NULL;
00141 }
00142
00143 self& operator=(const self &x) {
00144 if (dir) closedir(dir);
00145 state = x.state;
00146 transition = x.transition;
00147 dir = opendir(state.c_str());
00148 if (dir && !transition.empty()) seekdir(dir, telldir(x.dir));
00149 return *this;
00150 }
00151
00152 bool operator==(const self &x) const {
00153 return state == x.state && transition == x.transition;
00154 }
00155
00156 char_type letter() const { return transition; }
00157
00158 bool first() {
00159 if (dir == NULL) return false;
00160 struct dirent *entry;
00161 for(rewinddir(dir); (entry = readdir(dir)) != NULL; )
00162 if (strcmp(".", entry->d_name) != 0 && strcmp("..", entry->d_name) != 0) {
00163 transition = entry->d_name;
00164 return true;
00165 }
00166 return false;
00167 }
00168
00169 bool next() {
00170 struct dirent *entry;
00171 for(; (entry = readdir(dir)) != NULL; )
00172 if (strcmp(".", entry->d_name) != 0 || strcmp("..", entry->d_name) != 0) {
00173 transition = entry->d_name;
00174 return true;
00175 }
00176 return false;
00177 }
00178
00179 void forward() {
00180 state += '/';
00181 state += transition;
00182 closedir(dir);
00183 dir = opendir(state.c_str());
00184 }
00185
00186 bool find(const char_type &a) {
00187 if (dir == NULL) return false;
00188 struct dirent *entry;
00189 for(rewinddir(dir); (entry = readdir(dir)) != NULL; )
00190 if (strcmp(a.c_str(), entry->d_name)) {
00191 transition = entry->d_name;
00192 return true;
00193 }
00194 return false;
00195 }
00196
00197 state_type aim() const {
00198 return state + "/" + transition;
00199 }
00200
00201 bool aim_final() const {
00202 struct stat s;
00203 string path = aim();
00204 stat(path.c_str(), &s);
00205 return Predicate()(path, &s);
00206 }
00207
00208 tag_type aim_tag() const {
00209 struct stat s;
00210 string path = aim();
00211 stat(path.c_str(), &s);
00212 return s.st_mtime;
00213 }
00214 };
00215
00216 inline
00217 directory_cursor<> directoryc(const string &d = ".") {
00218 return directory_cursor<>(d);
00219 }
00220
00221 template <typename Predicate>
00222 inline
00223 directory_cursor<Predicate>
00224 directoryc(const Predicate&, const string &d = ".") {
00225 return directory_cursor<Predicate>(d);
00226 }
00227
00228 #endif
00229
00230 }
00231
00232 #endif