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)
33namespace 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
60namespace 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
70BOOST_REGEX_DECL const char* _fi_sep = "\\";
71const 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
80BOOST_REGEX_DECL const char* _fi_sep = "/";
81const 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
88void 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
137void 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
151mapfile_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
163mapfile_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
175mapfile_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
188mapfile_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
202mapfile_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
217mapfile_iterator operator + (const mapfile_iterator& i, long off)
218{
219 mapfile_iterator temp(i);
220 temp += off;
221 return temp;
222}
223
224mapfile_iterator operator - (const mapfile_iterator& i, long off)
225{
226 mapfile_iterator temp(i);
227 temp -= off;
228 return temp;
229}
230
231mapfile::iterator mapfile::begin()const
232{
233 return mapfile_iterator(this, 0);
234}
235
236mapfile::iterator mapfile::end()const
237{
238 return mapfile_iterator(this, _size);
239}
240
241void 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
293void 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
306long 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
316void 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
350void 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
373inline _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
387inline 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
396inline 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
406inline 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
416file_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
446file_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
504file_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
531file_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
548file_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
560file_iterator file_iterator::operator++(int)
561{
562 file_iterator temp(*this);
563 next();
564 return temp;
565}
566
567
568void 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
594directory_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
624directory_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
682directory_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
694directory_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
721directory_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
737directory_iterator directory_iterator::operator++(int)
738{
739 directory_iterator temp(*this);
740 next();
741 return temp;
742}
743
744void 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
774struct _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
808bool 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
849unsigned _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
887bool _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
904bool _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
929