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