1 /*
2  *
3  * Copyright (c) 1998-2002
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE:        fileiter.cpp
15   *   VERSION:     see <cutl/details/boost/version.hpp>
16   *   DESCRIPTION: Implements file io primitives + directory searching for class cutl_details_boost::RegEx.
17   */
18 
19 
20 #define BOOST_REGEX_SOURCE
21 
22 #include <cutl/details/boost/config.hpp>
23 #include <climits>
24 #include <stdexcept>
25 #include <string>
26 #include <cutl/details/boost/throw_exception.hpp>
27 #include <cutl/details/boost/regex/v4/fileiter.hpp>
28 #include <cutl/details/boost/regex/v4/regex_workaround.hpp>
29 #include <cutl/details/boost/regex/pattern_except.hpp>
30 
31 #include <cstdio>
32 #if defined(BOOST_NO_STDC_NAMESPACE)
33 namespace std{
34    using ::sprintf;
35    using ::fseek;
36    using ::fread;
37    using ::ftell;
38    using ::fopen;
39    using ::fclose;
40    using ::FILE;
41    using ::strcpy;
42    using ::strcpy;
43    using ::strcat;
44    using ::strcmp;
45    using ::strlen;
46 }
47 #endif
48 
49 
50 #ifndef BOOST_REGEX_NO_FILEITER
51 
52 #if defined(__CYGWIN__) || defined(__CYGWIN32__)
53 #include <sys/cygwin.h>
54 #endif
55 
56 #ifdef BOOST_MSVC
57 #  pragma warning(disable: 4800)
58 #endif
59 
60 namespace cutl_details_boost{
61    namespace re_detail{
62 // start with the operating system specific stuff:
63 
64 #if (defined(__BORLANDC__) || defined(BOOST_REGEX_FI_WIN32_DIR) || defined(BOOST_MSVC)) && !defined(BOOST_RE_NO_WIN32)
65 
66 // platform is DOS or Windows
67 // directories are separated with '\\'
68 // and names are insensitive of case
69 
70 BOOST_REGEX_DECL const char* _fi_sep = "\\";
71 const char* _fi_sep_alt = "/";
72 #define BOOST_REGEX_FI_TRANSLATE(c) std::tolower(c)
73 
74 #else
75 
76 // platform is not DOS or Windows
77 // directories are separated with '/'
78 // and names are sensitive of case
79 
80 BOOST_REGEX_DECL const char* _fi_sep = "/";
81 const char* _fi_sep_alt = _fi_sep;
82 #define BOOST_REGEX_FI_TRANSLATE(c) c
83 
84 #endif
85 
86 #ifdef BOOST_REGEX_FI_WIN32_MAP
87 
open(const char * file)88 void mapfile::open(const char* file)
89 {
90 #if defined(BOOST_NO_ANSI_APIS)
91    int filename_size = strlen(file);
92    LPWSTR wide_file = (LPWSTR)_alloca( (filename_size + 1) * sizeof(WCHAR) );
93    if(::MultiByteToWideChar(CP_ACP, 0,  file, filename_size,  wide_file, filename_size + 1) == 0)
94       hfile = INVALID_HANDLE_VALUE;
95    else
96       hfile = CreateFileW(wide_file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
97 #elif defined(__CYGWIN__)||defined(__CYGWIN32__)
98    char win32file[ MAX_PATH ];
99    cygwin_conv_to_win32_path( file, win32file );
100    hfile = CreateFileA(win32file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
101 #else
102    hfile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
103 #endif
104    if(hfile != INVALID_HANDLE_VALUE)
105    {
106       hmap = CreateFileMapping(hfile, 0, PAGE_READONLY, 0, 0, 0);
107       if((hmap == INVALID_HANDLE_VALUE) || (hmap == NULL))
108       {
109          CloseHandle(hfile);
110          hmap = 0;
111          hfile = 0;
112          std::runtime_error err("Unable to create file mapping.");
113          cutl_details_boost::re_detail::raise_runtime_error(err);
114       }
115       _first = static_cast<const char*>(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0));
116       if(_first == 0)
117       {
118          CloseHandle(hmap);
119          CloseHandle(hfile);
120          hmap = 0;
121          hfile = 0;
122          std::runtime_error err("Unable to create file mapping.");
123       }
124       _last = _first + GetFileSize(hfile, 0);
125    }
126    else
127    {
128       hfile = 0;
129 #ifndef BOOST_NO_EXCEPTIONS
130       throw std::runtime_error("Unable to open file.");
131 #else
132       BOOST_REGEX_NOEH_ASSERT(hfile != INVALID_HANDLE_VALUE);
133 #endif
134    }
135 }
136 
close()137 void mapfile::close()
138 {
139    if(hfile != INVALID_HANDLE_VALUE)
140    {
141       UnmapViewOfFile((void*)_first);
142       CloseHandle(hmap);
143       CloseHandle(hfile);
144       hmap = hfile = 0;
145       _first = _last = 0;
146    }
147 }
148 
149 #elif !defined(BOOST_RE_NO_STL)
150 
operator =(const mapfile_iterator & i)151 mapfile_iterator& mapfile_iterator::operator = (const mapfile_iterator& i)
152 {
153    if(file && node)
154       file->unlock(node);
155    file = i.file;
156    node = i.node;
157    offset = i.offset;
158    if(file)
159       file->lock(node);
160    return *this;
161 }
162 
operator ++()163 mapfile_iterator& mapfile_iterator::operator++ ()
164 {
165    if((++offset == mapfile::buf_size) && file)
166    {
167       ++node;
168       offset = 0;
169       file->lock(node);
170       file->unlock(node-1);
171    }
172    return *this;
173 }
174 
operator ++(int)175 mapfile_iterator mapfile_iterator::operator++ (int)
176 {
177    mapfile_iterator temp(*this);
178    if((++offset == mapfile::buf_size) && file)
179    {
180       ++node;
181       offset = 0;
182       file->lock(node);
183       file->unlock(node-1);
184    }
185    return temp;
186 }
187 
operator --()188 mapfile_iterator& mapfile_iterator::operator-- ()
189 {
190    if((offset == 0) && file)
191    {
192       --node;
193       offset = mapfile::buf_size - 1;
194       file->lock(node);
195       file->unlock(node + 1);
196    }
197    else
198       --offset;
199    return *this;
200 }
201 
operator --(int)202 mapfile_iterator mapfile_iterator::operator-- (int)
203 {
204    mapfile_iterator temp(*this);
205    if((offset == 0) && file)
206    {
207       --node;
208       offset = mapfile::buf_size - 1;
209       file->lock(node);
210       file->unlock(node + 1);
211    }
212    else
213       --offset;
214    return temp;
215 }
216 
operator +(const mapfile_iterator & i,long off)217 mapfile_iterator operator + (const mapfile_iterator& i, long off)
218 {
219    mapfile_iterator temp(i);
220    temp += off;
221    return temp;
222 }
223 
operator -(const mapfile_iterator & i,long off)224 mapfile_iterator operator - (const mapfile_iterator& i, long off)
225 {
226    mapfile_iterator temp(i);
227    temp -= off;
228    return temp;
229 }
230 
begin() const231 mapfile::iterator mapfile::begin()const
232 {
233    return mapfile_iterator(this, 0);
234 }
235 
end() const236 mapfile::iterator mapfile::end()const
237 {
238    return mapfile_iterator(this, _size);
239 }
240 
lock(pointer * node) const241 void mapfile::lock(pointer* node)const
242 {
243    BOOST_ASSERT(node >= _first);
244    BOOST_ASSERT(node <= _last);
245    if(node < _last)
246    {
247       if(*node == 0)
248       {
249          if(condemed.empty())
250          {
251             *node = new char[sizeof(int) + buf_size];
252             *(reinterpret_cast<int*>(*node)) = 1;
253          }
254          else
255          {
256             pointer* p = condemed.front();
257             condemed.pop_front();
258             *node = *p;
259             *p = 0;
260             *(reinterpret_cast<int*>(*node)) = 1;
261          }
262 
263         std::size_t read_size = 0;
264         int read_pos = std::fseek(hfile, (node - _first) * buf_size, SEEK_SET);
265 
266         if(0 == read_pos && node == _last - 1)
267            read_size = std::fread(*node + sizeof(int), _size % buf_size, 1, hfile);
268         else
269            read_size = std::fread(*node + sizeof(int), buf_size, 1, hfile);
270 #ifndef BOOST_NO_EXCEPTIONS
271         if((read_size == 0) || (std::ferror(hfile)))
272         {
273            throw std::runtime_error("Unable to read file.");
274         }
275 #else
276         BOOST_REGEX_NOEH_ASSERT((0 == std::ferror(hfile)) && (read_size != 0));
277 #endif
278       }
279       else
280       {
281          if(*reinterpret_cast<int*>(*node) == 0)
282          {
283             *reinterpret_cast<int*>(*node) = 1;
284             condemed.remove(node);
285          }
286          else
287             ++(*reinterpret_cast<int*>(*node));
288       }
289    }
290 }
291 
unlock(pointer * node) const292 void mapfile::unlock(pointer* node)const
293 {
294    BOOST_ASSERT(node >= _first);
295    BOOST_ASSERT(node <= _last);
296    if(node < _last)
297    {
298       if(--(*reinterpret_cast<int*>(*node)) == 0)
299       {
300          condemed.push_back(node);
301       }
302    }
303 }
304 
get_file_length(std::FILE * hfile)305 long int get_file_length(std::FILE* hfile)
306 {
307    long int result;
308    std::fseek(hfile, 0, SEEK_END);
309    result = std::ftell(hfile);
310    std::fseek(hfile, 0, SEEK_SET);
311    return result;
312 }
313 
314 
open(const char * file)315 void mapfile::open(const char* file)
316 {
317    hfile = std::fopen(file, "rb");
318 #ifndef BOOST_NO_EXCEPTIONS
319    try{
320 #endif
321    if(hfile != 0)
322    {
323       _size = get_file_length(hfile);
324       long cnodes = (_size + buf_size - 1) / buf_size;
325 
326       // check that number of nodes is not too high:
327       if(cnodes > (long)((INT_MAX) / sizeof(pointer*)))
328       {
329          std::fclose(hfile);
330          hfile = 0;
331          _size = 0;
332          return;
333       }
334 
335       _first = new pointer[(int)cnodes];
336       _last = _first + cnodes;
337       std::memset(_first, 0, cnodes*sizeof(pointer));
338    }
339    else
340    {
341        std::runtime_error err("Unable to open file.");
342    }
343 #ifndef BOOST_NO_EXCEPTIONS
344    }catch(...)
345    { close(); throw; }
346 #endif
347 }
348 
close()349 void mapfile::close()
350 {
351    if(hfile != 0)
352    {
353       pointer* p = _first;
354       while(p != _last)
355       {
356          if(*p)
357             delete[] *p;
358          ++p;
359       }
360       delete[] _first;
361       _size = 0;
362       _first = _last = 0;
363       std::fclose(hfile);
364       hfile = 0;
365       condemed.erase(condemed.begin(), condemed.end());
366    }
367 }
368 
369 
370 #endif
371 
find_first_file(const char * wild,_fi_find_data & data)372 inline _fi_find_handle find_first_file(const char* wild,  _fi_find_data& data)
373 {
374 #ifdef BOOST_NO_ANSI_APIS
375    std::size_t wild_size = std::strlen(wild);
376    LPWSTR wide_wild = (LPWSTR)_alloca( (wild_size + 1) * sizeof(WCHAR) );
377    if (::MultiByteToWideChar(CP_ACP, 0,  wild, wild_size,  wide_wild, wild_size + 1) == 0)
378       return _fi_invalid_handle;
379 
380    return FindFirstFileW(wide_wild, &data);
381 #else
382    return FindFirstFileA(wild, &data);
383 #endif
384 }
385 
find_next_file(_fi_find_handle hf,_fi_find_data & data)386 inline bool find_next_file(_fi_find_handle hf,  _fi_find_data& data)
387 {
388 #ifdef BOOST_NO_ANSI_APIS
389    return FindNextFileW(hf, &data);
390 #else
391    return FindNextFileA(hf, &data);
392 #endif
393 }
394 
copy_find_file_result_with_overflow_check(const _fi_find_data & data,char * path,size_t max_size)395 inline void copy_find_file_result_with_overflow_check(const _fi_find_data& data,  char* path, size_t max_size)
396 {
397 #ifdef BOOST_NO_ANSI_APIS
398    if (::WideCharToMultiByte(CP_ACP, 0,  data.cFileName, -1,  path, max_size,  NULL, NULL) == 0)
399       re_detail::overflow_error_if_not_zero(1);
400 #else
401    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(path, max_size,  data.cFileName));
402 #endif
403 }
404 
is_not_current_or_parent_path_string(const _fi_find_data & data)405 inline bool is_not_current_or_parent_path_string(const _fi_find_data& data)
406 {
407 #ifdef BOOST_NO_ANSI_APIS
408    return (std::wcscmp(data.cFileName, L".") && std::wcscmp(data.cFileName, L".."));
409 #else
410    return (std::strcmp(data.cFileName, ".") && std::strcmp(data.cFileName, ".."));
411 #endif
412 }
413 
414 
file_iterator()415 file_iterator::file_iterator()
416 {
417    _root = _path = 0;
418    ref = 0;
419 #ifndef BOOST_NO_EXCEPTIONS
420    try{
421 #endif
422    _root = new char[MAX_PATH];
423    BOOST_REGEX_NOEH_ASSERT(_root)
424    _path = new char[MAX_PATH];
425    BOOST_REGEX_NOEH_ASSERT(_path)
426    ptr = _path;
427    *_path = 0;
428    *_root = 0;
429    ref = new file_iterator_ref();
430    BOOST_REGEX_NOEH_ASSERT(ref)
431    ref->hf = _fi_invalid_handle;
432    ref->count = 1;
433 #ifndef BOOST_NO_EXCEPTIONS
434    }
435    catch(...)
436    {
437       delete[] _root;
438       delete[] _path;
439       delete ref;
440       throw;
441    }
442 #endif
443 }
444 
file_iterator(const char * wild)445 file_iterator::file_iterator(const char* wild)
446 {
447    _root = _path = 0;
448    ref = 0;
449 #ifndef BOOST_NO_EXCEPTIONS
450    try{
451 #endif
452    _root = new char[MAX_PATH];
453    BOOST_REGEX_NOEH_ASSERT(_root)
454    _path = new char[MAX_PATH];
455    BOOST_REGEX_NOEH_ASSERT(_path)
456    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild));
457    ptr = _root;
458    while(*ptr)++ptr;
459    while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
460    if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
461    {
462      _root[1]='\0';
463      re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
464    }
465    else
466    {
467      *ptr = 0;
468      re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
469      if(*_path == 0)
470        re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, "."));
471      re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep));
472    }
473    ptr = _path + std::strlen(_path);
474 
475    ref = new file_iterator_ref();
476    BOOST_REGEX_NOEH_ASSERT(ref)
477    ref->hf = find_first_file(wild,  ref->_data);
478    ref->count = 1;
479 
480    if(ref->hf == _fi_invalid_handle)
481    {
482       *_path = 0;
483       ptr = _path;
484    }
485    else
486    {
487       copy_find_file_result_with_overflow_check(ref->_data,  ptr, (MAX_PATH - (ptr - _path)));
488       if(ref->_data.dwFileAttributes & _fi_dir)
489          next();
490    }
491 #ifndef BOOST_NO_EXCEPTIONS
492    }
493    catch(...)
494    {
495       delete[] _root;
496       delete[] _path;
497       delete ref;
498       throw;
499    }
500 #endif
501 }
502 
file_iterator(const file_iterator & other)503 file_iterator::file_iterator(const file_iterator& other)
504 {
505    _root = _path = 0;
506    ref = 0;
507 #ifndef BOOST_NO_EXCEPTIONS
508    try{
509 #endif
510    _root = new char[MAX_PATH];
511    BOOST_REGEX_NOEH_ASSERT(_root)
512    _path = new char[MAX_PATH];
513    BOOST_REGEX_NOEH_ASSERT(_path)
514    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
515    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
516    ptr = _path + (other.ptr - other._path);
517    ref = other.ref;
518 #ifndef BOOST_NO_EXCEPTIONS
519    }
520    catch(...)
521    {
522       delete[] _root;
523       delete[] _path;
524       throw;
525    }
526 #endif
527    ++(ref->count);
528 }
529 
operator =(const file_iterator & other)530 file_iterator& file_iterator::operator=(const file_iterator& other)
531 {
532    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
533    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
534    ptr = _path + (other.ptr - other._path);
535    if(--(ref->count) == 0)
536    {
537       if(ref->hf != _fi_invalid_handle)
538          FindClose(ref->hf);
539       delete ref;
540    }
541    ref = other.ref;
542    ++(ref->count);
543    return *this;
544 }
545 
546 
~file_iterator()547 file_iterator::~file_iterator()
548 {
549    delete[] _root;
550    delete[] _path;
551    if(--(ref->count) == 0)
552    {
553       if(ref->hf != _fi_invalid_handle)
554          FindClose(ref->hf);
555       delete ref;
556    }
557 }
558 
operator ++(int)559 file_iterator file_iterator::operator++(int)
560 {
561    file_iterator temp(*this);
562    next();
563    return temp;
564 }
565 
566 
next()567 void file_iterator::next()
568 {
569    if(ref->hf != _fi_invalid_handle)
570    {
571       bool cont = true;
572       while(cont)
573       {
574          cont = find_next_file(ref->hf, ref->_data);
575          if(cont && ((ref->_data.dwFileAttributes & _fi_dir) == 0))
576             break;
577       }
578       if(!cont)
579       {
580          // end of sequence
581          FindClose(ref->hf);
582          ref->hf = _fi_invalid_handle;
583          *_path = 0;
584          ptr = _path;
585       }
586       else
587          copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
588    }
589 }
590 
591 
592 
directory_iterator()593 directory_iterator::directory_iterator()
594 {
595    _root = _path = 0;
596    ref = 0;
597 #ifndef BOOST_NO_EXCEPTIONS
598    try{
599 #endif
600    _root = new char[MAX_PATH];
601    BOOST_REGEX_NOEH_ASSERT(_root)
602    _path = new char[MAX_PATH];
603    BOOST_REGEX_NOEH_ASSERT(_path)
604    ptr = _path;
605    *_path = 0;
606    *_root = 0;
607    ref = new file_iterator_ref();
608    BOOST_REGEX_NOEH_ASSERT(ref)
609    ref->hf = _fi_invalid_handle;
610    ref->count = 1;
611 #ifndef BOOST_NO_EXCEPTIONS
612    }
613    catch(...)
614    {
615       delete[] _root;
616       delete[] _path;
617       delete ref;
618       throw;
619    }
620 #endif
621 }
622 
directory_iterator(const char * wild)623 directory_iterator::directory_iterator(const char* wild)
624 {
625    _root = _path = 0;
626    ref = 0;
627 #ifndef BOOST_NO_EXCEPTIONS
628    try{
629 #endif
630    _root = new char[MAX_PATH];
631    BOOST_REGEX_NOEH_ASSERT(_root)
632    _path = new char[MAX_PATH];
633    BOOST_REGEX_NOEH_ASSERT(_path)
634    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild));
635    ptr = _root;
636    while(*ptr)++ptr;
637    while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
638 
639    if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
640    {
641      _root[1]='\0';
642      re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
643    }
644    else
645    {
646      *ptr = 0;
647      re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
648      if(*_path == 0)
649        re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, "."));
650      re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep));
651    }
652    ptr = _path + std::strlen(_path);
653 
654    ref = new file_iterator_ref();
655    BOOST_REGEX_NOEH_ASSERT(ref)
656    ref->count = 1;
657    ref->hf = find_first_file(wild,  ref->_data);
658    if(ref->hf == _fi_invalid_handle)
659    {
660       *_path = 0;
661       ptr = _path;
662    }
663    else
664    {
665       copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
666       if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ptr, ".") == 0) || (std::strcmp(ptr, "..") == 0))
667          next();
668    }
669 #ifndef BOOST_NO_EXCEPTIONS
670    }
671    catch(...)
672    {
673       delete[] _root;
674       delete[] _path;
675       delete ref;
676       throw;
677    }
678 #endif
679 }
680 
~directory_iterator()681 directory_iterator::~directory_iterator()
682 {
683    delete[] _root;
684    delete[] _path;
685    if(--(ref->count) == 0)
686    {
687       if(ref->hf != _fi_invalid_handle)
688          FindClose(ref->hf);
689       delete ref;
690    }
691 }
692 
directory_iterator(const directory_iterator & other)693 directory_iterator::directory_iterator(const directory_iterator& other)
694 {
695    _root = _path = 0;
696    ref = 0;
697 #ifndef BOOST_NO_EXCEPTIONS
698    try{
699 #endif
700    _root = new char[MAX_PATH];
701    BOOST_REGEX_NOEH_ASSERT(_root)
702    _path = new char[MAX_PATH];
703    BOOST_REGEX_NOEH_ASSERT(_path)
704    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
705    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
706    ptr = _path + (other.ptr - other._path);
707    ref = other.ref;
708 #ifndef BOOST_NO_EXCEPTIONS
709    }
710    catch(...)
711    {
712       delete[] _root;
713       delete[] _path;
714       throw;
715    }
716 #endif
717    ++(ref->count);
718 }
719 
operator =(const directory_iterator & other)720 directory_iterator& directory_iterator::operator=(const directory_iterator& other)
721 {
722    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
723    re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
724    ptr = _path + (other.ptr - other._path);
725    if(--(ref->count) == 0)
726    {
727       if(ref->hf != _fi_invalid_handle)
728          FindClose(ref->hf);
729       delete ref;
730    }
731    ref = other.ref;
732    ++(ref->count);
733    return *this;
734 }
735 
operator ++(int)736 directory_iterator directory_iterator::operator++(int)
737 {
738    directory_iterator temp(*this);
739    next();
740    return temp;
741 }
742 
next()743 void directory_iterator::next()
744 {
745    if(ref->hf != _fi_invalid_handle)
746    {
747       bool cont = true;
748       while(cont)
749       {
750          cont = find_next_file(ref->hf, ref->_data);
751          if(cont && (ref->_data.dwFileAttributes & _fi_dir))
752          {
753             if(is_not_current_or_parent_path_string(ref->_data))
754                break;
755          }
756       }
757       if(!cont)
758       {
759          // end of sequence
760          FindClose(ref->hf);
761          ref->hf = _fi_invalid_handle;
762          *_path = 0;
763          ptr = _path;
764       }
765       else
766          copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
767    }
768 }
769 
770 
771 #ifdef BOOST_REGEX_FI_POSIX_DIR
772 
773 struct _fi_priv_data
774 {
775    char root[MAX_PATH];
776    char* mask;
777    DIR* d;
778    _fi_priv_data(const char* p);
779 };
780 
_fi_priv_data(const char * p)781 _fi_priv_data::_fi_priv_data(const char* p)
782 {
783    std::strcpy(root, p);
784    mask = root;
785    while(*mask) ++mask;
786    while((mask > root) && (*mask != *_fi_sep) && (*mask != *_fi_sep_alt)) --mask;
787    if(mask == root && ((*mask== *_fi_sep) || (*mask == *_fi_sep_alt)) )
788    {
789       root[1] = '\0';
790       std::strcpy(root+2, p+1);
791       mask = root+2;
792    }
793    else if(mask == root)
794    {
795       root[0] = '.';
796       root[1] = '\0';
797       std::strcpy(root+2, p);
798       mask = root+2;
799    }
800    else
801    {
802       *mask = 0;
803       ++mask;
804    }
805 }
806 
iswild(const char * mask,const char * name)807 bool iswild(const char* mask, const char* name)
808 {
809    while(*mask && *name)
810    {
811       switch(*mask)
812       {
813       case '?':
814          ++name;
815          ++mask;
816          continue;
817       case '*':
818          ++mask;
819          if(*mask == 0)
820             return true;
821          while(*name)
822          {
823             if(iswild(mask, name))
824                return true;
825             ++name;
826          }
827          return false;
828       case '.':
829          if(0 == *name)
830          {
831             ++mask;
832             continue;
833          }
834          // fall through:
835       default:
836          if(BOOST_REGEX_FI_TRANSLATE(*mask) != BOOST_REGEX_FI_TRANSLATE(*name))
837             return false;
838          ++mask;
839          ++name;
840          continue;
841       }
842    }
843    if(*mask != *name)
844       return false;
845    return true;
846 }
847 
_fi_attributes(const char * root,const char * name)848 unsigned _fi_attributes(const char* root, const char* name)
849 {
850    char buf[MAX_PATH];
851    // verify that we can not overflow:
852    if(std::strlen(root) + std::strlen(_fi_sep) + std::strlen(name) >= MAX_PATH)
853       return 0;
854    int r;
855    if( ( (root[0] == *_fi_sep) || (root[0] == *_fi_sep_alt) ) && (root[1] == '\0') )
856       r = (std::sprintf)(buf, "%s%s", root, name);
857    else
858       r = (std::sprintf)(buf, "%s%s%s", root, _fi_sep, name);
859    if(r < 0)
860       return 0; // sprintf failed
861    DIR* d = opendir(buf);
862    if(d)
863    {
864       closedir(d);
865       return _fi_dir;
866    }
867    return 0;
868 }
869 
_fi_FindFirstFile(const char * lpFileName,_fi_find_data * lpFindFileData)870 _fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData)
871 {
872    _fi_find_handle dat = new _fi_priv_data(lpFileName);
873 
874    DIR* h = opendir(dat->root);
875    dat->d = h;
876    if(h != 0)
877    {
878       if(_fi_FindNextFile(dat, lpFindFileData))
879          return dat;
880       closedir(h);
881    }
882    delete dat;
883    return 0;
884 }
885 
_fi_FindNextFile(_fi_find_handle dat,_fi_find_data * lpFindFileData)886 bool _fi_FindNextFile(_fi_find_handle dat, _fi_find_data* lpFindFileData)
887 {
888    dirent* d;
889    do
890    {
891       d = readdir(dat->d);
892    } while(d && !iswild(dat->mask, d->d_name));
893 
894    if(d)
895    {
896       std::strcpy(lpFindFileData->cFileName, d->d_name);
897       lpFindFileData->dwFileAttributes = _fi_attributes(dat->root, d->d_name);
898       return true;
899    }
900    return false;
901 }
902 
_fi_FindClose(_fi_find_handle dat)903 bool _fi_FindClose(_fi_find_handle dat)
904 {
905    closedir(dat->d);
906    delete dat;
907    return true;
908 }
909 
910 #endif
911 
912 } // namespace re_detail
913 } // namspace boost
914 
915 #endif    // BOOST_REGEX_NO_FILEITER
916 
917 
918 
919 
920 
921 
922 
923 
924 
925 
926 
927 
928