]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/libs/regex/src/fileiter.cpp
Update to boost 1.72
[lyx.git] / 3rdparty / 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 <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(__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
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       _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
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
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
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
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
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
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
217 mapfile_iterator operator + (const mapfile_iterator& i, long off)
218 {
219    mapfile_iterator temp(i);
220    temp += off;
221    return temp;
222 }
223
224 mapfile_iterator operator - (const mapfile_iterator& i, long off)
225 {
226    mapfile_iterator temp(i);
227    temp -= off;
228    return temp;
229 }
230
231 mapfile::iterator mapfile::begin()const
232 {
233    return mapfile_iterator(this, 0);
234 }
235
236 mapfile::iterator mapfile::end()const
237 {
238    return mapfile_iterator(this, _size);
239 }
240
241 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         if((read_size == 0) || (std::ferror(hfile)))
271         { 
272 #ifndef BOOST_NO_EXCEPTIONS 
273            unlock(node);
274            throw std::runtime_error("Unable to read file."); 
275 #else 
276            BOOST_REGEX_NOEH_ASSERT((0 == std::ferror(hfile)) && (read_size != 0)); 
277 #endif 
278         } 
279       }
280       else
281       {
282          if(*reinterpret_cast<int*>(*node) == 0)
283          {
284             *reinterpret_cast<int*>(*node) = 1;
285             condemed.remove(node);
286          }
287          else
288             ++(*reinterpret_cast<int*>(*node));
289       }
290    }
291 }
292
293 void mapfile::unlock(pointer* node)const
294 {
295    BOOST_ASSERT(node >= _first);
296    BOOST_ASSERT(node <= _last);
297    if(node < _last)
298    {
299       if(--(*reinterpret_cast<int*>(*node)) == 0)
300       {
301          condemed.push_back(node);
302       }
303    }
304 }
305
306 long int get_file_length(std::FILE* hfile)
307 {
308    long int result;
309    std::fseek(hfile, 0, SEEK_END);
310    result = std::ftell(hfile);
311    std::fseek(hfile, 0, SEEK_SET);
312    return result;
313 }
314
315
316 void mapfile::open(const char* file)
317 {
318    hfile = std::fopen(file, "rb");
319 #ifndef BOOST_NO_EXCEPTIONS
320    try{
321 #endif
322    if(hfile != 0)
323    {
324       _size = get_file_length(hfile);
325       long cnodes = (_size + buf_size - 1) / buf_size;
326
327       // check that number of nodes is not too high:
328       if(cnodes > (long)((INT_MAX) / sizeof(pointer*)))
329       {
330          std::fclose(hfile);
331          hfile = 0;
332          _size = 0;
333          return;
334       }
335
336       _first = new pointer[(int)cnodes];
337       _last = _first + cnodes;
338       std::memset(_first, 0, cnodes*sizeof(pointer));
339    }
340    else
341    {
342        std::runtime_error err("Unable to open file.");
343    }
344 #ifndef BOOST_NO_EXCEPTIONS
345    }catch(...)
346    { close(); throw; }
347 #endif
348 }
349
350 void mapfile::close()
351 {
352    if(hfile != 0)
353    {
354       pointer* p = _first;
355       while(p != _last)
356       {
357          if(*p)
358             delete[] *p;
359          ++p;
360       }
361       delete[] _first;
362       _size = 0;
363       _first = _last = 0;
364       std::fclose(hfile);
365       hfile = 0;
366       condemed.erase(condemed.begin(), condemed.end());
367    }
368 }
369
370
371 #endif
372
373 inline _fi_find_handle find_first_file(const char* wild,  _fi_find_data& data)
374 {
375 #ifdef BOOST_NO_ANSI_APIS
376    std::size_t wild_size = std::strlen(wild);
377    LPWSTR wide_wild = (LPWSTR)_alloca( (wild_size + 1) * sizeof(WCHAR) );
378    if (::MultiByteToWideChar(CP_ACP, 0,  wild, wild_size,  wide_wild, wild_size + 1) == 0)
379       return _fi_invalid_handle;
380
381    return FindFirstFileW(wide_wild, &data);
382 #else
383    return FindFirstFileA(wild, &data);
384 #endif
385 }
386
387 inline bool find_next_file(_fi_find_handle hf,  _fi_find_data& data)
388 {
389 #ifdef BOOST_NO_ANSI_APIS
390    return FindNextFileW(hf, &data);
391 #else
392    return FindNextFileA(hf, &data);
393 #endif
394 }
395    
396 inline void copy_find_file_result_with_overflow_check(const _fi_find_data& data,  char* path, size_t max_size)
397 {
398 #ifdef BOOST_NO_ANSI_APIS
399    if (::WideCharToMultiByte(CP_ACP, 0,  data.cFileName, -1,  path, max_size,  NULL, NULL) == 0)
400       BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(1);
401 #else
402    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(path, max_size,  data.cFileName));
403 #endif
404 }
405
406 inline bool is_not_current_or_parent_path_string(const _fi_find_data& data)
407 {
408 #ifdef BOOST_NO_ANSI_APIS
409    return (std::wcscmp(data.cFileName, L".") && std::wcscmp(data.cFileName, L".."));
410 #else
411    return (std::strcmp(data.cFileName, ".") && std::strcmp(data.cFileName, ".."));
412 #endif
413 }
414
415
416 file_iterator::file_iterator()
417 {
418    _root = _path = 0;
419    ref = 0;
420 #ifndef BOOST_NO_EXCEPTIONS
421    try{
422 #endif
423    _root = new char[MAX_PATH];
424    BOOST_REGEX_NOEH_ASSERT(_root)
425    _path = new char[MAX_PATH];
426    BOOST_REGEX_NOEH_ASSERT(_path)
427    ptr = _path;
428    *_path = 0;
429    *_root = 0;
430    ref = new file_iterator_ref();
431    BOOST_REGEX_NOEH_ASSERT(ref)
432    ref->hf = _fi_invalid_handle;
433    ref->count = 1;
434 #ifndef BOOST_NO_EXCEPTIONS
435    }
436    catch(...)
437    {
438       delete[] _root;
439       delete[] _path;
440       delete ref;
441       throw;
442    }
443 #endif
444 }
445
446 file_iterator::file_iterator(const char* wild)
447 {
448    _root = _path = 0;
449    ref = 0;
450 #ifndef BOOST_NO_EXCEPTIONS
451    try{
452 #endif
453    _root = new char[MAX_PATH];
454    BOOST_REGEX_NOEH_ASSERT(_root)
455    _path = new char[MAX_PATH];
456    BOOST_REGEX_NOEH_ASSERT(_path)
457    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, wild));
458    ptr = _root;
459    while(*ptr)++ptr;
460    while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
461    if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
462    {
463      _root[1]='\0';
464      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root));
465    }
466    else
467    {
468      *ptr = 0;
469      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root));
470      if(*_path == 0)
471        BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, "."));
472      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcat_s(_path, MAX_PATH, _fi_sep));
473    }
474    ptr = _path + std::strlen(_path);
475
476    ref = new file_iterator_ref();
477    BOOST_REGEX_NOEH_ASSERT(ref)
478    ref->hf = find_first_file(wild,  ref->_data);
479    ref->count = 1;
480
481    if(ref->hf == _fi_invalid_handle)
482    {
483       *_path = 0;
484       ptr = _path;
485    }
486    else
487    {
488       copy_find_file_result_with_overflow_check(ref->_data,  ptr, (MAX_PATH - (ptr - _path)));
489       if(ref->_data.dwFileAttributes & _fi_dir)
490          next();
491    }
492 #ifndef BOOST_NO_EXCEPTIONS
493    }
494    catch(...)
495    {
496       delete[] _root;
497       delete[] _path;
498       delete ref;
499       throw;
500    }
501 #endif
502 }
503
504 file_iterator::file_iterator(const file_iterator& other)
505 {
506    _root = _path = 0;
507    ref = 0;
508 #ifndef BOOST_NO_EXCEPTIONS
509    try{
510 #endif
511    _root = new char[MAX_PATH];
512    BOOST_REGEX_NOEH_ASSERT(_root)
513    _path = new char[MAX_PATH];
514    BOOST_REGEX_NOEH_ASSERT(_path)
515    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root));
516    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path));
517    ptr = _path + (other.ptr - other._path);
518    ref = other.ref;
519 #ifndef BOOST_NO_EXCEPTIONS
520    }
521    catch(...)
522    {
523       delete[] _root;
524       delete[] _path;
525       throw;
526    }
527 #endif
528    ++(ref->count);
529 }
530
531 file_iterator& file_iterator::operator=(const file_iterator& other)
532 {
533    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root));
534    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path));
535    ptr = _path + (other.ptr - other._path);
536    if(--(ref->count) == 0)
537    {
538       if(ref->hf != _fi_invalid_handle)
539          FindClose(ref->hf);
540       delete ref;
541    }
542    ref = other.ref;
543    ++(ref->count);
544    return *this;
545 }
546
547
548 file_iterator::~file_iterator()
549 {
550    delete[] _root;
551    delete[] _path;
552    if(--(ref->count) == 0)
553    {
554       if(ref->hf != _fi_invalid_handle)
555          FindClose(ref->hf);
556       delete ref;
557    }
558 }
559
560 file_iterator file_iterator::operator++(int)
561 {
562    file_iterator temp(*this);
563    next();
564    return temp;
565 }
566
567
568 void file_iterator::next()
569 {
570    if(ref->hf != _fi_invalid_handle)
571    {
572       bool cont = true;
573       while(cont)
574       {
575          cont = find_next_file(ref->hf, ref->_data);
576          if(cont && ((ref->_data.dwFileAttributes & _fi_dir) == 0))
577             break;
578       }
579       if(!cont)
580       {
581          // end of sequence
582          FindClose(ref->hf);
583          ref->hf = _fi_invalid_handle;
584          *_path = 0;
585          ptr = _path;
586       }
587       else
588          copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
589    }
590 }
591
592
593
594 directory_iterator::directory_iterator()
595 {
596    _root = _path = 0;
597    ref = 0;
598 #ifndef BOOST_NO_EXCEPTIONS
599    try{
600 #endif
601    _root = new char[MAX_PATH];
602    BOOST_REGEX_NOEH_ASSERT(_root)
603    _path = new char[MAX_PATH];
604    BOOST_REGEX_NOEH_ASSERT(_path)
605    ptr = _path;
606    *_path = 0;
607    *_root = 0;
608    ref = new file_iterator_ref();
609    BOOST_REGEX_NOEH_ASSERT(ref)
610    ref->hf = _fi_invalid_handle;
611    ref->count = 1;
612 #ifndef BOOST_NO_EXCEPTIONS
613    }
614    catch(...)
615    {
616       delete[] _root;
617       delete[] _path;
618       delete ref;
619       throw;
620    }
621 #endif
622 }
623
624 directory_iterator::directory_iterator(const char* wild)
625 {
626    _root = _path = 0;
627    ref = 0;
628 #ifndef BOOST_NO_EXCEPTIONS
629    try{
630 #endif
631    _root = new char[MAX_PATH];
632    BOOST_REGEX_NOEH_ASSERT(_root)
633    _path = new char[MAX_PATH];
634    BOOST_REGEX_NOEH_ASSERT(_path)
635    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, wild));
636    ptr = _root;
637    while(*ptr)++ptr;
638    while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
639
640    if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
641    {
642      _root[1]='\0';
643      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root));
644    }
645    else
646    {
647      *ptr = 0;
648      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root));
649      if(*_path == 0)
650        BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, "."));
651      BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcat_s(_path, MAX_PATH, _fi_sep));
652    }
653    ptr = _path + std::strlen(_path);
654
655    ref = new file_iterator_ref();
656    BOOST_REGEX_NOEH_ASSERT(ref)
657    ref->count = 1;
658    ref->hf = find_first_file(wild,  ref->_data);
659    if(ref->hf == _fi_invalid_handle)
660    {
661       *_path = 0;
662       ptr = _path;
663    }
664    else
665    {
666       copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
667       if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ptr, ".") == 0) || (std::strcmp(ptr, "..") == 0))
668          next();
669    }
670 #ifndef BOOST_NO_EXCEPTIONS
671    }
672    catch(...)
673    {
674       delete[] _root;
675       delete[] _path;
676       delete ref;
677       throw;
678    }
679 #endif
680 }
681
682 directory_iterator::~directory_iterator()
683 {
684    delete[] _root;
685    delete[] _path;
686    if(--(ref->count) == 0)
687    {
688       if(ref->hf != _fi_invalid_handle)
689          FindClose(ref->hf);
690       delete ref;
691    }
692 }
693
694 directory_iterator::directory_iterator(const directory_iterator& other)
695 {
696    _root = _path = 0;
697    ref = 0;
698 #ifndef BOOST_NO_EXCEPTIONS
699    try{
700 #endif
701    _root = new char[MAX_PATH];
702    BOOST_REGEX_NOEH_ASSERT(_root)
703    _path = new char[MAX_PATH];
704    BOOST_REGEX_NOEH_ASSERT(_path)
705    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root));
706    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path));
707    ptr = _path + (other.ptr - other._path);
708    ref = other.ref;
709 #ifndef BOOST_NO_EXCEPTIONS
710    }
711    catch(...)
712    {
713       delete[] _root;
714       delete[] _path;
715       throw;
716    }
717 #endif
718    ++(ref->count);
719 }
720
721 directory_iterator& directory_iterator::operator=(const directory_iterator& other)
722 {
723    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root));
724    BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path));
725    ptr = _path + (other.ptr - other._path);
726    if(--(ref->count) == 0)
727    {
728       if(ref->hf != _fi_invalid_handle)
729          FindClose(ref->hf);
730       delete ref;
731    }
732    ref = other.ref;
733    ++(ref->count);
734    return *this;
735 }
736
737 directory_iterator directory_iterator::operator++(int)
738 {
739    directory_iterator temp(*this);
740    next();
741    return temp;
742 }
743
744 void directory_iterator::next()
745 {
746    if(ref->hf != _fi_invalid_handle)
747    {
748       bool cont = true;
749       while(cont)
750       {
751          cont = find_next_file(ref->hf, ref->_data);
752          if(cont && (ref->_data.dwFileAttributes & _fi_dir))
753          {
754             if(is_not_current_or_parent_path_string(ref->_data))
755                break;
756          }
757       }
758       if(!cont)
759       {
760          // end of sequence
761          FindClose(ref->hf);
762          ref->hf = _fi_invalid_handle;
763          *_path = 0;
764          ptr = _path;
765       }
766       else
767          copy_find_file_result_with_overflow_check(ref->_data,  ptr, MAX_PATH - (ptr - _path));
768    }
769 }
770
771
772 #ifdef BOOST_REGEX_FI_POSIX_DIR
773
774 struct _fi_priv_data
775 {
776    char root[MAX_PATH];
777    char* mask;
778    DIR* d;
779    _fi_priv_data(const char* p);
780 };
781
782 _fi_priv_data::_fi_priv_data(const char* p)
783 {
784    std::strcpy(root, p);
785    mask = root;
786    while(*mask) ++mask;
787    while((mask > root) && (*mask != *_fi_sep) && (*mask != *_fi_sep_alt)) --mask;
788    if(mask == root && ((*mask== *_fi_sep) || (*mask == *_fi_sep_alt)) )
789    {
790       root[1] = '\0';
791       std::strcpy(root+2, p+1);
792       mask = root+2;
793    }
794    else if(mask == root)
795    {
796       root[0] = '.';
797       root[1] = '\0';
798       std::strcpy(root+2, p);
799       mask = root+2;
800    }
801    else
802    {
803       *mask = 0;
804       ++mask;
805    }
806 }
807
808 bool iswild(const char* mask, const char* name)
809 {
810    while(*mask && *name)
811    {
812       switch(*mask)
813       {
814       case '?':
815          ++name;
816          ++mask;
817          continue;
818       case '*':
819          ++mask;
820          if(*mask == 0)
821             return true;
822          while(*name)
823          {
824             if(iswild(mask, name))
825                return true;
826             ++name;
827          }
828          return false;
829       case '.':
830          if(0 == *name)
831          {
832             ++mask;
833             continue;
834          }
835          // fall through
836       default:
837          if(BOOST_REGEX_FI_TRANSLATE(*mask) != BOOST_REGEX_FI_TRANSLATE(*name))
838             return false;
839          ++mask;
840          ++name;
841          continue;
842       }
843    }
844    if(*mask != *name)
845       return false;
846    return true;
847 }
848
849 unsigned _fi_attributes(const char* root, const char* name)
850 {
851    char buf[MAX_PATH];
852    // verify that we can not overflow:
853    if(std::strlen(root) + std::strlen(_fi_sep) + std::strlen(name) >= MAX_PATH)
854       return 0;
855    int r;
856    if( ( (root[0] == *_fi_sep) || (root[0] == *_fi_sep_alt) ) && (root[1] == '\0') )
857       r = (std::sprintf)(buf, "%s%s", root, name);
858    else
859       r = (std::sprintf)(buf, "%s%s%s", root, _fi_sep, name);
860    if(r < 0)
861       return 0; // sprintf failed
862    DIR* d = opendir(buf);
863    if(d)
864    {
865       closedir(d);
866       return _fi_dir;
867    }
868    return 0;
869 }
870
871 _fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData)
872 {
873    _fi_find_handle dat = new _fi_priv_data(lpFileName);
874
875    DIR* h = opendir(dat->root);
876    dat->d = h;
877    if(h != 0)
878    {
879       if(_fi_FindNextFile(dat, lpFindFileData))
880          return dat;
881       closedir(h);
882    }
883    delete dat;
884    return 0;
885 }
886
887 bool _fi_FindNextFile(_fi_find_handle dat, _fi_find_data* lpFindFileData)
888 {
889    dirent* d;
890    do
891    {
892       d = readdir(dat->d);
893    } while(d && !iswild(dat->mask, d->d_name));
894
895    if(d)
896    {
897       std::strcpy(lpFindFileData->cFileName, d->d_name);
898       lpFindFileData->dwFileAttributes = _fi_attributes(dat->root, d->d_name);
899       return true;
900    }
901    return false;
902 }
903
904 bool _fi_FindClose(_fi_find_handle dat)
905 {
906    closedir(dat->d);
907    delete dat;
908    return true;
909 }
910
911 #endif
912
913 } // namespace BOOST_REGEX_DETAIL_NS
914 } // namspace boost
915
916 #endif    // BOOST_REGEX_NO_FILEITER
917
918
919
920
921
922
923
924
925
926
927
928