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