Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

vul_file_iterator.cxx

Go to the documentation of this file.
00001 // This is core/vul/vul_file_iterator.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vul_file_iterator.h"
00007 #include <vcl_string.h>
00008 #include <vcl_cassert.h>
00009 
00010 #include <vul/vul_file.h>
00011 #include <vul/vul_reg_exp.h>
00012 //:
00013 // \file
00014 // \verbatim
00015 //  Modifications:
00016 //   Ian Scott 09/06/2003 Add filename general globbing support
00017 // \endverbatim
00018 
00019 //: Declare pimpl, reset, and iteration routines for each OS
00020 #if defined(VCL_WIN32) && !defined(__CYGWIN__)
00021 
00022 #if defined(VCL_BORLAND_56)
00023 # include <stdint.h> /* for intptr_t on Borland 5.6. */
00024 #endif
00025 
00026 #include <io.h>
00027 
00028 struct vul_file_iterator_data
00029 {
00030   struct _finddata_t data_;
00031 # if defined VCL_VC_6 || defined VCL_VC_5 || defined VCL_BORLAND_55 || defined __MINGW32__
00032   typedef long handle_type;      // works with msvc6
00033 # else
00034   typedef intptr_t handle_type;  // not found by msvc6
00035 #endif
00036   handle_type handle_;
00037 
00038   vcl_string found_;
00039   char const* name_;
00040   vul_reg_exp reg_exp_;
00041   vcl_string original_dirname_;
00042 
00043   handle_type find_first(const char* dirname, struct _finddata_t* data)
00044   {
00045     return _findfirst(const_cast<char*>(dirname), data);
00046   }
00047 
00048   vul_file_iterator_data(char const* glob);
00049 
00050   void mkname() {
00051     // Remember full path
00052     found_ = original_dirname_ + "\\" + data_.name;
00053     name_ = found_.c_str();
00054     // no need to remember filename, it's in data_.name
00055   }
00056 
00057 
00058   void next() {
00059     assert(handle_ != 0);
00060     do
00061     {
00062       if (_findnext(handle_, &data_) != 0) {
00063         _findclose(handle_);
00064         handle_ = -1L;
00065         return;
00066       }
00067     } while ( ! reg_exp_.find(data_.name) );
00068     mkname();
00069   }
00070 
00071 
00072   // should be constish, and ret 0 when nuffink
00073   char const* value() {
00074     if (handle_ == -1L) return 0;
00075     return name_;
00076   }
00077 
00078   // Return non-dir part of fn
00079   char const* value_filename() {
00080     if (handle_ == -1L) return 0;
00081     return data_.name;
00082   }
00083 
00084   ~vul_file_iterator_data() {
00085     if (handle_ != -1L)
00086       _findclose(handle_);
00087   }
00088 };
00089 
00090 vul_file_iterator_data::vul_file_iterator_data(char const* glob)
00091 {
00092   original_dirname_ = vul_file::dirname(glob);
00093   handle_ = find_first((original_dirname_ + "\\*").c_str(), &data_);
00094 
00095   vcl_string baseglob = vul_file::basename(glob);
00096   vcl_string::iterator i = baseglob.begin();
00097   bool prev_slash=false, in_sqr_brackets=false;
00098   //assemble the Regexp string
00099   vcl_string re = "^"; // match the start of the string
00100   while (i != baseglob.end())
00101   {
00102     if (*i=='\\' && !prev_slash)
00103       prev_slash = true;
00104     else if (prev_slash)
00105     {
00106       prev_slash = false;
00107       re.append(1,('\\'));
00108       re.append(1,*i);
00109     }
00110     else if (*i=='[' && !in_sqr_brackets)
00111     {
00112       in_sqr_brackets = true;
00113       re.append(1,'[');
00114     }
00115     else if (*i==']' && in_sqr_brackets)
00116     {
00117       in_sqr_brackets = false;
00118       re.append(1,']');
00119     }
00120     else if (*i=='?' && !in_sqr_brackets)
00121       re.append(1,'.');
00122     else if (*i=='*' && !in_sqr_brackets)
00123       re.append(".*");
00124     else
00125       re.append(vul_reg_exp::protect(*i));
00126 
00127     ++i;
00128   }
00129   // match the end of the string
00130   re += '$';
00131 
00132   reg_exp_.compile(re.c_str());
00133 
00134 
00135   if (handle_ != -1L)
00136   {
00137     while ( ! reg_exp_.find(data_.name) )
00138     {
00139       if (_findnext(handle_, &data_) != 0) {
00140         _findclose(handle_);
00141         handle_ = -1L;
00142         return;
00143       }
00144     }
00145     mkname();
00146   }
00147 }
00148 
00149 #else // !defined(VCL_WIN32) || defined(__CYGWIN__)
00150 
00151 #include <dirent.h>
00152 
00153 struct vul_file_iterator_data
00154 {
00155   vcl_string original_dirname_;
00156   DIR* dir_handle_;
00157   dirent* de_;
00158   vcl_string found_;
00159   char const* name_;
00160   vul_reg_exp reg_exp_;
00161 
00162   vul_file_iterator_data(char const* glob);
00163 
00164   void mkname() {
00165     // Remember full path
00166     found_ = original_dirname_ + de_->d_name;
00167     name_ = found_.c_str();
00168     // no need to remember filename, it's in data_.name
00169   }
00170 
00171   void next() {
00172     assert(dir_handle_ != 0);
00173     do
00174     {
00175       de_ = readdir(dir_handle_);
00176       if (de_==0) {
00177         closedir(dir_handle_);
00178         dir_handle_ = 0;
00179         return;
00180       }
00181     } while ( ! reg_exp_.find(de_->d_name) );
00182     mkname();
00183   }
00184 
00185   // should be constish, and ret 0 when nuffink
00186   char const* value() {
00187     if (!dir_handle_) return 0;
00188     return name_;
00189   }
00190 
00191   // Return non-dir part of fn
00192   char const* value_filename() {
00193     if (!dir_handle_) return 0;
00194     return de_->d_name;
00195   }
00196 
00197   ~vul_file_iterator_data() {
00198     if (dir_handle_)
00199       closedir(dir_handle_);
00200   }
00201 };
00202 
00203 vul_file_iterator_data::vul_file_iterator_data(char const* glob)
00204 {
00205   original_dirname_ = vul_file::dirname(glob) + "/";
00206 
00207   vcl_string baseglob = vul_file::basename(glob);
00208   vcl_string::iterator i = baseglob.begin();
00209   bool prev_slash=false, in_sqr_brackets=false;
00210   //assemble the Regexp string
00211   vcl_string re = "^"; // match the start of the string
00212   while (i != baseglob.end())
00213   {
00214     if (*i=='\\' && !prev_slash)
00215       prev_slash = true;
00216     else if (prev_slash)
00217     {
00218       prev_slash = false;
00219       re += '\\';
00220       re += *i;
00221     }
00222     else if (*i=='[' && !in_sqr_brackets)
00223     {
00224       in_sqr_brackets = true;
00225       re += '[';
00226     }
00227     else if (*i==']' && in_sqr_brackets)
00228     {
00229       in_sqr_brackets = false;
00230       re += ']';
00231     }
00232     else if (*i=='?' && !in_sqr_brackets)
00233       re += '.';
00234     else if (*i=='*' && !in_sqr_brackets)
00235       re += ".*";
00236     else
00237       re += vul_reg_exp::protect(*i);
00238 
00239     ++i;
00240   }
00241   // match the end of the string
00242   re += '$';
00243 
00244   reg_exp_.compile(re.c_str());
00245 
00246   dir_handle_ = opendir(original_dirname_.c_str());
00247 
00248   next();
00249 }
00250 
00251 #endif // !defined(VCL_WIN32) || defined(__CYGWIN__)
00252 
00253 // -----------------------------------------------------------------------------
00254 
00255 vul_file_iterator::vul_file_iterator(char const* glob)
00256 {
00257   p = 0;
00258   reset(glob);
00259 }
00260 
00261 vul_file_iterator::vul_file_iterator(vcl_string const& glob)
00262 {
00263   p = 0;
00264   reset(glob.c_str());
00265 }
00266 
00267 vul_file_iterator::~vul_file_iterator()
00268 {
00269   delete p;
00270 }
00271 
00272 void vul_file_iterator::reset(char const* glob)
00273 {
00274   delete p;
00275   p = new vul_file_iterator_data(glob);
00276 }
00277 
00278 char const* vul_file_iterator::operator()()
00279 {
00280   return p->value();
00281 }
00282 
00283 char const* vul_file_iterator::filename()
00284 {
00285   return p->value_filename();
00286 }
00287 
00288 vul_file_iterator::operator vul_file_iterator::safe_bool() const
00289 {
00290   return (p->value() != 0)? VCL_SAFE_BOOL_TRUE : 0;
00291 }
00292 
00293 bool vul_file_iterator::operator!() const
00294 {
00295   return (p->value() != 0)? false : true;
00296 }
00297 
00298 vul_file_iterator& vul_file_iterator::operator++()
00299 {
00300   p->next();
00301   return *this;
00302 }

Generated on Thu Jan 10 14:41:00 2008 for core/vul by  doxygen 1.4.4