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