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