vul_file_iterator.cxx
Go to the documentation of this file.
1 // This is core/vul/vul_file_iterator.cxx
2 
3 #include <string>
4 #include "vul_file_iterator.h"
5 #ifdef _MSC_VER
6 # include <vcl_msvc_warnings.h>
7 #endif
8 #include <cassert>
9 
10 #include <vul/vul_file.h>
11 #include <vul/vul_reg_exp.h>
12 //:
13 // \file
14 // \verbatim
15 // Modifications:
16 // Ian Scott 09/06/2003 Add filename general globbing support
17 // \endverbatim
18 
19 //: Declare pimpl, reset, and iteration routines for each OS
20 #if defined(_WIN32) && !defined(__CYGWIN__)
21 
22 #include <io.h>
23 
25 {
26  struct _finddata_t data_;
27 # if defined __MINGW32__
28  typedef long handle_type; // works with msvc6
29 # else
30  typedef intptr_t handle_type; // not found by msvc6
31 #endif
32  handle_type handle_;
33 
34  std::string found_;
35  char const* name_;
37  std::string original_dirname_;
38 
39  handle_type find_first(const char* dirname, struct _finddata_t* data)
40  {
41  return _findfirst(const_cast<char*>(dirname), data);
42  }
43 
44  vul_file_iterator_data(char const* glob);
45 
46  void mkname() {
47  // Remember full path
48  found_ = original_dirname_ + "\\" + data_.name;
49  name_ = found_.c_str();
50  // no need to remember filename, it's in data_.name
51  }
52 
53 
54  void next() {
55  assert(handle_ != 0);
56  do
57  {
58  if (_findnext(handle_, &data_) != 0) {
59  _findclose(handle_);
60  handle_ = -1L;
61  return;
62  }
63  } while ( ! reg_exp_.find(data_.name) );
64  mkname();
65  }
66 
67 
68  // should be constish, and ret 0 when nuffink
69  char const* value() {
70  if (handle_ == -1L) return 0;
71  return name_;
72  }
73 
74  // Return non-dir part of fn
75  char const* value_filename() {
76  if (handle_ == -1L) return 0;
77  return data_.name;
78  }
79 
81  if (handle_ != -1L)
82  _findclose(handle_);
83  }
84 };
85 
87 {
89  handle_ = find_first((original_dirname_ + "\\*").c_str(), &data_);
90 
91  std::string baseglob = vul_file::basename(glob);
92  std::string::iterator i = baseglob.begin();
93  bool prev_slash=false, in_sqr_brackets=false;
94  //assemble the Regexp string
95  std::string re = "^"; // match the start of the string
96  while (i != baseglob.end())
97  {
98  if (*i=='\\' && !prev_slash)
99  prev_slash = true;
100  else if (prev_slash)
101  {
102  prev_slash = false;
103  re.append(1,('\\'));
104  re.append(1,*i);
105  }
106  else if (*i=='[' && !in_sqr_brackets)
107  {
108  in_sqr_brackets = true;
109  re.append(1,'[');
110  }
111  else if (*i==']' && in_sqr_brackets)
112  {
113  in_sqr_brackets = false;
114  re.append(1,']');
115  }
116  else if (*i=='?' && !in_sqr_brackets)
117  re.append(1,'.');
118  else if (*i=='*' && !in_sqr_brackets)
119  re.append(".*");
120  else
121  re.append(vul_reg_exp::protect(*i));
122 
123  ++i;
124  }
125  // match the end of the string
126  re += '$';
127 
128  reg_exp_.compile(re.c_str());
129 
130 
131  if (handle_ != -1L)
132  {
133  while ( ! reg_exp_.find(data_.name) )
134  {
135  if (_findnext(handle_, &data_) != 0) {
136  _findclose(handle_);
137  handle_ = -1L;
138  return;
139  }
140  }
141  mkname();
142  }
143 }
144 
145 #else // !defined(_WIN32) || defined(__CYGWIN__)
146 
147 #include <dirent.h>
148 
150 {
151  std::string original_dirname_;
153  dirent* de_;
154  std::string found_;
155  char const* name_;
157 
158  vul_file_iterator_data(char const* glob);
159 
160  void mkname() {
161  // Remember full path
162  found_ = original_dirname_ + de_->d_name;
163  name_ = found_.c_str();
164  // no need to remember filename, it's in data_.name
165  }
166 
167  void next() {
168  // if dir_handle_ is NULL, then the directory probably doesn't
169  // exist.
170  if(dir_handle_ == nullptr) {
171  return;
172  }
173  do
174  {
175  de_ = readdir(dir_handle_);
176  if (de_==nullptr) {
177  closedir(dir_handle_);
178  dir_handle_ = nullptr;
179  return;
180  }
181  } while ( ! reg_exp_.find(de_->d_name) );
182  mkname();
183  }
184 
185  // should be constish, and ret 0 when nuffink
186  char const* value() {
187  if (!dir_handle_) return nullptr;
188  return name_;
189  }
190 
191  // Return non-dir part of fn
192  char const* value_filename() {
193  if (!dir_handle_) return nullptr;
194  return de_->d_name;
195  }
196 
198  if (dir_handle_)
199  closedir(dir_handle_);
200  }
201 };
202 
204 {
205  original_dirname_ = vul_file::dirname(glob) + "/";
206 
207  std::string baseglob = vul_file::basename(glob);
208  std::string::iterator i = baseglob.begin();
209  bool prev_slash=false, in_sqr_brackets=false;
210  //assemble the Regexp string
211  std::string re = "^"; // match the start of the string
212  while (i != baseglob.end())
213  {
214  if (*i=='\\' && !prev_slash)
215  prev_slash = true;
216  else if (prev_slash)
217  {
218  prev_slash = false;
219  re += '\\';
220  re += *i;
221  }
222  else if (*i=='[' && !in_sqr_brackets)
223  {
224  in_sqr_brackets = true;
225  re += '[';
226  }
227  else if (*i==']' && in_sqr_brackets)
228  {
229  in_sqr_brackets = false;
230  re += ']';
231  }
232  else if (*i=='?' && !in_sqr_brackets)
233  re += '.';
234  else if (*i=='*' && !in_sqr_brackets)
235  re += ".*";
236  else
237  re += vul_reg_exp::protect(*i);
238 
239  ++i;
240  }
241  // match the end of the string
242  re += '$';
243 
244  reg_exp_.compile(re.c_str());
245 
246  dir_handle_ = opendir(original_dirname_.c_str());
247 
248  next();
249 }
250 
251 #endif // !defined(_WIN32) || defined(__CYGWIN__)
252 
253 // -----------------------------------------------------------------------------
254 
256 {
257  p = nullptr;
258  reset(glob);
259 }
260 
261 vul_file_iterator::vul_file_iterator(std::string const& glob)
262 {
263  p = nullptr;
264  reset(glob.c_str());
265 }
266 
268 {
269  delete p;
270 }
271 
272 void vul_file_iterator::reset(char const* glob)
273 {
274  delete p;
275  p = new vul_file_iterator_data(glob);
276 }
277 
279 {
280  return p->value();
281 }
282 
284 {
285  return p->value_filename();
286 }
287 
288 vul_file_iterator::operator bool() const
289 {
290  return (p->value() != nullptr)? true : false;
291 }
292 
294 {
295  return (p->value() != nullptr)? false : true;
296 }
297 
299 {
300  p->next();
301  return *this;
302 }
static std::string basename(char const *filename, char const *suffix=nullptr)
Return basename.
Definition: vul_file.cxx:177
Pattern matching with regular expressions.
Definition: vul_reg_exp.h:82
bool find(char const *)
true if regexp in char* arg.
char const * filename()
Return the non-directory part of the current pathname.
Declare pimpl, reset, and iteration routines for each OS.
bool operator!() const
Inverse boolean value.
A collection of miscellaneous filesystem-type utilities.
static const char * protect(char c)
Return an expression that will match precisely c.
class to iterate through directories and/or "glob" patterns (*.
Iterate through directories and/or "glob" patterns (*.
contains class for pattern matching with regular expressions
vul_file_iterator_data * p
vul_file_iterator & operator++()
Increment to the next file.
vul_file_iterator_data(char const *glob)
void compile(char const *)
Compiles char* --> regexp.
void reset(char const *glob)
Run a new match.
static std::string dirname(char const *filename)
Return dirname.
Definition: vul_file.cxx:124
char const * operator()()
Return the currently pointed-to pathname.