3 * Copyright (c) 1998-2002
6 * Permission to use, copy, modify, distribute and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and
9 * that both that copyright notice and this permission notice appear
10 * in supporting documentation. Dr John Maddock makes no representations
11 * about the suitability of this software for any purpose.
12 * It is provided "as is" without express or implied warranty.
17 * LOCATION: see http://www.boost.org for most recent version.
19 * VERSION: see <boost/version.hpp>
20 * DESCRIPTION: Implements file io primitives + directory searching for class boost::RegEx.
24 #define BOOST_REGEX_SOURCE
28 #include <boost/regex/detail/fileiter.hpp>
30 #ifndef BOOST_REGEX_NO_FILEITER
32 #if defined(__CYGWIN__) || defined(__CYGWIN32__)
33 #include <sys/cygwin.h>
37 # pragma warning(disable: 4800)
42 // start with the operating system specific stuff:
44 #if (defined(__BORLANDC__) || defined(BOOST_REGEX_FI_WIN32_DIR) || defined(BOOST_MSVC)) && !defined(BOOST_RE_NO_WIN32)
46 // platform is DOS or Windows
47 // directories are separated with '\\'
48 // and names are insensitive of case
50 const char* _fi_sep = "\\";
51 const char* _fi_sep_alt = "/";
52 #define BOOST_REGEX_FI_TRANSLATE(c) std::tolower(c)
56 // platform is not DOS or Windows
57 // directories are separated with '/'
58 // and names are sensitive of case
60 const char* _fi_sep = "/";
61 const char* _fi_sep_alt = _fi_sep;
62 #define BOOST_REGEX_FI_TRANSLATE(c) c
66 #ifdef BOOST_REGEX_FI_WIN32_MAP
68 void mapfile::open(const char* file)
71 #if defined(__CYGWIN__)||defined(__CYGWIN32__)
72 char win32file[ MAX_PATH ];
73 cygwin_conv_to_win32_path( file, win32file );
74 hfile = CreateFileA(win32file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
76 hfile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
78 if(hfile != INVALID_HANDLE_VALUE)
80 hmap = CreateFileMapping(hfile, 0, PAGE_READONLY, 0, 0, 0);
81 if((hmap == INVALID_HANDLE_VALUE) || (hmap == NULL))
86 #ifndef BOOST_NO_EXCEPTIONS
87 throw std::runtime_error("Unable to create file mapping.");
89 BOOST_REGEX_NOEH_ASSERT(hmap != INVALID_HANDLE_VALUE);
92 _first = static_cast<const char*>(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0));
99 #ifndef BOOST_NO_EXCEPTIONS
100 throw std::runtime_error("Unable to create file mapping.");
102 BOOST_REGEX_NOEH_ASSERT(_first != 0);
105 _last = _first + GetFileSize(hfile, 0);
110 #ifndef BOOST_NO_EXCEPTIONS
111 throw std::runtime_error("Unable to open file.");
113 BOOST_REGEX_NOEH_ASSERT(hfile != INVALID_HANDLE_VALUE);
118 void mapfile::close()
121 if(hfile != INVALID_HANDLE_VALUE)
123 UnmapViewOfFile((void*)_first);
131 #elif !defined(BOOST_RE_NO_STL)
133 mapfile_iterator& mapfile_iterator::operator = (const mapfile_iterator& i)
146 mapfile_iterator& mapfile_iterator::operator++ ()
149 if((++offset == mapfile::buf_size) && file)
154 file->unlock(node-1);
159 mapfile_iterator mapfile_iterator::operator++ (int)
162 mapfile_iterator temp(*this);
163 if((++offset == mapfile::buf_size) && file)
168 file->unlock(node-1);
173 mapfile_iterator& mapfile_iterator::operator-- ()
176 if((offset == 0) && file)
179 offset = mapfile::buf_size - 1;
181 file->unlock(node + 1);
188 mapfile_iterator mapfile_iterator::operator-- (int)
191 mapfile_iterator temp(*this);
192 if((offset == 0) && file)
195 offset = mapfile::buf_size - 1;
197 file->unlock(node + 1);
204 mapfile_iterator operator + (const mapfile_iterator& i, long off)
207 mapfile_iterator temp(i);
212 mapfile_iterator operator - (const mapfile_iterator& i, long off)
215 mapfile_iterator temp(i);
220 mapfile::iterator mapfile::begin()const
223 return mapfile_iterator(this, 0);
226 mapfile::iterator mapfile::end()const
229 return mapfile_iterator(this, _size);
232 void mapfile::lock(pointer* node)const
235 assert(node >= _first);
236 assert(node <= _last);
243 *node = new char[sizeof(int) + buf_size];
244 *(reinterpret_cast<int*>(*node)) = 1;
248 pointer* p = condemed.front();
249 condemed.pop_front();
252 *(reinterpret_cast<int*>(*node)) = 1;
254 std::fseek(hfile, (node - _first) * buf_size, SEEK_SET);
255 if(node == _last - 1)
256 std::fread(*node + sizeof(int), _size % buf_size, 1, hfile);
258 std::fread(*node + sizeof(int), buf_size, 1, hfile);
262 if(*reinterpret_cast<int*>(*node) == 0)
264 *reinterpret_cast<int*>(*node) = 1;
265 condemed.remove(node);
268 ++(*reinterpret_cast<int*>(*node));
273 void mapfile::unlock(pointer* node)const
276 assert(node >= _first);
277 assert(node <= _last);
280 if(--(*reinterpret_cast<int*>(*node)) == 0)
282 condemed.push_back(node);
287 long int get_file_length(std::FILE* hfile)
291 std::fseek(hfile, 0, SEEK_END);
292 result = std::ftell(hfile);
293 std::fseek(hfile, 0, SEEK_SET);
298 void mapfile::open(const char* file)
301 hfile = std::fopen(file, "rb");
302 #ifndef BOOST_NO_EXCEPTIONS
307 _size = get_file_length(hfile);
308 long cnodes = (_size + buf_size - 1) / buf_size;
310 // check that number of nodes is not too high:
311 if(cnodes > (long)((INT_MAX) / sizeof(pointer*)))
319 _first = new pointer[(int)cnodes];
320 _last = _first + cnodes;
321 std::memset(_first, 0, cnodes*sizeof(pointer));
325 #ifndef BOOST_NO_EXCEPTIONS
326 throw std::runtime_error("Unable to open file.");
328 BOOST_REGEX_NOEH_ASSERT(hfile != 0);
331 #ifndef BOOST_NO_EXCEPTIONS
337 void mapfile::close()
354 condemed.erase(condemed.begin(), condemed.end());
362 file_iterator::file_iterator()
367 #ifndef BOOST_NO_EXCEPTIONS
370 _root = new char[MAX_PATH];
371 BOOST_REGEX_NOEH_ASSERT(_root)
372 _path = new char[MAX_PATH];
373 BOOST_REGEX_NOEH_ASSERT(_path)
377 ref = new file_iterator_ref();
378 BOOST_REGEX_NOEH_ASSERT(ref)
379 ref->hf = _fi_invalid_handle;
381 #ifndef BOOST_NO_EXCEPTIONS
393 file_iterator::file_iterator(const char* wild)
398 #ifndef BOOST_NO_EXCEPTIONS
401 _root = new char[MAX_PATH];
402 BOOST_REGEX_NOEH_ASSERT(_root)
403 _path = new char[MAX_PATH];
404 BOOST_REGEX_NOEH_ASSERT(_path)
405 std::strcpy(_root, wild);
408 while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
411 std::strcpy(_path, _root);
413 std::strcpy(_path, ".");
414 std::strcat(_path, _fi_sep);
415 ptr = _path + std::strlen(_path);
417 if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
420 std::strcpy(_path, _root);
421 ptr = _path + std::strlen(_path);
426 std::strcpy(_path, _root);
428 std::strcpy(_path, ".");
429 std::strcat(_path, _fi_sep);
430 ptr = _path + std::strlen(_path);
434 ref = new file_iterator_ref();
435 BOOST_REGEX_NOEH_ASSERT(ref)
436 ref->hf = FindFirstFileA(wild, &(ref->_data));
439 if(ref->hf == _fi_invalid_handle)
446 std::strcpy(ptr, ref->_data.cFileName);
447 if(ref->_data.dwFileAttributes & _fi_dir)
450 #ifndef BOOST_NO_EXCEPTIONS
462 file_iterator::file_iterator(const file_iterator& other)
467 #ifndef BOOST_NO_EXCEPTIONS
470 _root = new char[MAX_PATH];
471 BOOST_REGEX_NOEH_ASSERT(_root)
472 _path = new char[MAX_PATH];
473 BOOST_REGEX_NOEH_ASSERT(_path)
474 std::strcpy(_root, other._root);
475 std::strcpy(_path, other._path);
476 ptr = _path + (other.ptr - other._path);
478 #ifndef BOOST_NO_EXCEPTIONS
490 file_iterator& file_iterator::operator=(const file_iterator& other)
493 std::strcpy(_root, other._root);
494 std::strcpy(_path, other._path);
495 ptr = _path + (other.ptr - other._path);
496 if(--(ref->count) == 0)
498 if(ref->hf != _fi_invalid_handle)
508 file_iterator::~file_iterator()
513 if(--(ref->count) == 0)
515 if(ref->hf != _fi_invalid_handle)
521 file_iterator file_iterator::operator++(int)
524 file_iterator temp(*this);
530 void file_iterator::next()
533 if(ref->hf != _fi_invalid_handle)
538 cont = FindNextFileA(ref->hf, &(ref->_data));
539 if(cont && ((ref->_data.dwFileAttributes & _fi_dir) == 0))
546 ref->hf = _fi_invalid_handle;
551 std::strcpy(ptr, ref->_data.cFileName);
557 directory_iterator::directory_iterator()
562 #ifndef BOOST_NO_EXCEPTIONS
565 _root = new char[MAX_PATH];
566 BOOST_REGEX_NOEH_ASSERT(_root)
567 _path = new char[MAX_PATH];
568 BOOST_REGEX_NOEH_ASSERT(_path)
572 ref = new file_iterator_ref();
573 BOOST_REGEX_NOEH_ASSERT(ref)
574 ref->hf = _fi_invalid_handle;
576 #ifndef BOOST_NO_EXCEPTIONS
588 directory_iterator::directory_iterator(const char* wild)
593 #ifndef BOOST_NO_EXCEPTIONS
596 _root = new char[MAX_PATH];
597 BOOST_REGEX_NOEH_ASSERT(_root)
598 _path = new char[MAX_PATH];
599 BOOST_REGEX_NOEH_ASSERT(_path)
600 std::strcpy(_root, wild);
603 while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
606 std::strcpy(_path, _root);
608 std::strcpy(_path, ".");
609 std::strcat(_path, _fi_sep);
610 ptr = _path + std::strlen(_path);
612 if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
615 std::strcpy(_path, _root);
616 ptr = _path + std::strlen(_path);
621 std::strcpy(_path, _root);
623 std::strcpy(_path, ".");
624 std::strcat(_path, _fi_sep);
625 ptr = _path + std::strlen(_path);
628 ref = new file_iterator_ref();
629 BOOST_REGEX_NOEH_ASSERT(ref)
631 ref->hf = FindFirstFileA(wild, &(ref->_data));
632 if(ref->hf == _fi_invalid_handle)
639 std::strcpy(ptr, ref->_data.cFileName);
640 if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ref->_data.cFileName, ".") == 0) || (std::strcmp(ref->_data.cFileName, "..") == 0))
643 #ifndef BOOST_NO_EXCEPTIONS
655 directory_iterator::~directory_iterator()
660 if(--(ref->count) == 0)
662 if(ref->hf != _fi_invalid_handle)
668 directory_iterator::directory_iterator(const directory_iterator& other)
673 #ifndef BOOST_NO_EXCEPTIONS
676 _root = new char[MAX_PATH];
677 BOOST_REGEX_NOEH_ASSERT(_root)
678 _path = new char[MAX_PATH];
679 BOOST_REGEX_NOEH_ASSERT(_path)
680 std::strcpy(_root, other._root);
681 std::strcpy(_path, other._path);
682 ptr = _path + (other.ptr - other._path);
684 #ifndef BOOST_NO_EXCEPTIONS
696 directory_iterator& directory_iterator::operator=(const directory_iterator& other)
699 std::strcpy(_root, other._root);
700 std::strcpy(_path, other._path);
701 ptr = _path + (other.ptr - other._path);
702 if(--(ref->count) == 0)
704 if(ref->hf != _fi_invalid_handle)
713 directory_iterator directory_iterator::operator++(int)
716 directory_iterator temp(*this);
721 void directory_iterator::next()
724 if(ref->hf != _fi_invalid_handle)
729 cont = FindNextFileA(ref->hf, &(ref->_data));
730 if(cont && (ref->_data.dwFileAttributes & _fi_dir))
732 if(std::strcmp(ref->_data.cFileName, ".") && std::strcmp(ref->_data.cFileName, ".."))
740 ref->hf = _fi_invalid_handle;
745 std::strcpy(ptr, ref->_data.cFileName);
750 #ifdef BOOST_REGEX_FI_POSIX_DIR
757 _fi_priv_data(const char* p);
760 _fi_priv_data::_fi_priv_data(const char* p)
763 std::strcpy(root, p);
766 while((mask > root) && (*mask != *_fi_sep) && (*mask != *_fi_sep_alt)) --mask;
767 if(mask == root && ((*mask== *_fi_sep) || (*mask == *_fi_sep_alt)) )
770 std::strcpy(root+2, p+1);
773 else if(mask == root)
777 std::strcpy(root+2, p);
787 bool iswild(const char* mask, const char* name)
790 while(*mask && *name)
804 if(iswild(mask, name))
817 if(BOOST_REGEX_FI_TRANSLATE(*mask) != BOOST_REGEX_FI_TRANSLATE(*name))
829 unsigned _fi_attributes(const char* root, const char* name)
833 if( ( (root[0] == *_fi_sep) || (root[0] == *_fi_sep_alt) ) && (root[1] == '\0') )
834 std::sprintf(buf, "%s%s", root, name);
836 std::sprintf(buf, "%s%s%s", root, _fi_sep, name);
837 DIR* d = opendir(buf);
846 _fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData)
849 _fi_find_handle dat = new _fi_priv_data(lpFileName);
851 DIR* h = opendir(dat->root);
855 if(_fi_FindNextFile(dat, lpFindFileData))
862 bool _fi_FindNextFile(_fi_find_handle dat, _fi_find_data* lpFindFileData)
869 } while(d && !iswild(dat->mask, d->d_name));
873 std::strcpy(lpFindFileData->cFileName, d->d_name);
874 lpFindFileData->dwFileAttributes = _fi_attributes(dat->root, d->d_name);
880 bool _fi_FindClose(_fi_find_handle dat)
890 } // namespace re_detail
893 #endif // BOOST_REGEX_NO_FILEITER