Merge lp:~zorba-coders/zorba/bug-986580 into lp:zorba

Proposed by Paul J. Lucas
Status: Superseded
Proposed branch: lp:~zorba-coders/zorba/bug-986580
Merge into: lp:zorba
Diff against target: 1346 lines (+295/-776)
17 files modified
CMakeLists.txt (+7/-0)
NOTICE.txt (+0/-18)
NOTICE.xml (+0/-16)
include/zorba/util/file.h (+0/-1)
src/api/fileimpl.cpp (+6/-17)
src/api/fileimpl.h (+3/-4)
src/unit_tests/CMakeLists.txt (+1/-0)
src/unit_tests/test_fs_iterator.cpp (+54/-0)
src/unit_tests/unit_test_list.h (+1/-0)
src/unit_tests/unit_tests.cpp (+1/-0)
src/util/CMakeLists.txt (+0/-1)
src/util/dir.cpp (+0/-175)
src/util/dir.h (+0/-100)
src/util/file.cpp (+0/-12)
src/util/fs_util.cpp (+129/-31)
src/util/fs_util.h (+93/-29)
src/util/win32/dirent.h (+0/-372)
To merge this branch: bzr merge lp:~zorba-coders/zorba/bug-986580
Reviewer Review Type Date Requested Status
Cezar Andrei Needs Fixing
Rodolfo Ochoa Approve
Review via email: mp+103408@code.launchpad.net

This proposal has been superseded by a proposal from 2012-04-25.

Commit message

Better implementation of listing files in a directory.

Description of the change

Better implementation of listing files in a directory.

To post a comment you must log in.
Revision history for this message
Rodolfo Ochoa (rodolfo-ochoa) :
review: Approve
Revision history for this message
Cezar Andrei (cezar-andrei) wrote :

Looks good, please do remove the dirent.h copyright/license from NOTICE.txt/xml files since you removed dirent.h.

review: Needs Fixing
lp:~zorba-coders/zorba/bug-986580 updated
10793. By Paul J. Lucas

Removed copyright notice for dirent.h.

10794. By Paul J. Lucas

Put file::lsdir() back since it's used by the util-jvm module.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2012-04-24 12:39:38 +0000
3+++ CMakeLists.txt 2012-04-25 17:18:22 +0000
4@@ -309,6 +309,13 @@
5 MESSAGE (STATUS "")
6
7 #
8+# shlwapi
9+#
10+IF(WIN32)
11+ SET(requiredlibs ${requiredlibs} "shlwapi")
12+ENDIF(WIN32)
13+
14+#
15 # SWIG
16 #
17 IF (NOT ZORBA_SUPPRESS_SWIG)
18
19=== modified file 'NOTICE.txt'
20--- NOTICE.txt 2012-04-18 15:34:39 +0000
21+++ NOTICE.txt 2012-04-25 17:18:22 +0000
22@@ -459,24 +459,6 @@
23 suitability of this software for any purpose. It is provided "as is"
24 without express or implied warranty.
25
26-----------------------------------------------------
27-
28-src/util/win32/dirent.h
29-
30-Copyright: 2006 Toni Ronkko
31-
32-
33- Permission is hereby granted, free of charge, to any person obtaining
34- a copy of this software and associated documentation files (the
35- ``Software''), to deal in the Software without restriction, including
36- without limitation the rights to use, copy, modify, merge, publish,
37- distribute, sublicense, and/or sell copies of the Software, and to
38- permit persons to whom the Software is furnished to do so, subject to
39- the following conditions:
40-
41- The above copyright notice and this permission notice shall be included
42- in all copies or substantial portions of the Software.
43-
44
45 External libraries used by this project:
46 ----------------------------------------------------
47
48=== modified file 'NOTICE.xml'
49--- NOTICE.xml 2012-04-24 12:39:38 +0000
50+++ NOTICE.xml 2012-04-25 17:18:22 +0000
51@@ -423,22 +423,6 @@
52 without express or implied warranty.
53 </foreign-notice>
54 </foreign-files>
55- <foreign-files>
56- <file>src/util/win32/dirent.h</file>
57- <copyright>2006 Toni Ronkko</copyright>
58- <foreign-notice>
59- Permission is hereby granted, free of charge, to any person obtaining
60- a copy of this software and associated documentation files (the
61- ``Software''), to deal in the Software without restriction, including
62- without limitation the rights to use, copy, modify, merge, publish,
63- distribute, sublicense, and/or sell copies of the Software, and to
64- permit persons to whom the Software is furnished to do so, subject to
65- the following conditions:
66-
67- The above copyright notice and this permission notice shall be included
68- in all copies or substantial portions of the Software.
69- </foreign-notice>
70- </foreign-files>
71
72 <external-lib mandatory="true">
73 <name>LIBXML2</name>
74
75=== modified file 'include/zorba/util/file.h'
76--- include/zorba/util/file.h 2012-04-24 12:39:38 +0000
77+++ include/zorba/util/file.h 2012-04-25 17:18:22 +0000
78@@ -85,7 +85,6 @@
79 void mkdir();
80 void deep_mkdir();
81 void rmdir(bool ignore = true);
82- void lsdir(std::vector<std::string> &list);
83 #ifndef _WIN32_WCE
84 void chdir();
85 #endif
86
87=== modified file 'src/api/fileimpl.cpp'
88--- src/api/fileimpl.cpp 2012-04-24 12:39:38 +0000
89+++ src/api/fileimpl.cpp 2012-04-25 17:18:22 +0000
90@@ -29,44 +29,33 @@
91 #ifdef WIN32
92 #include <util/ascii_util.h>
93 #endif
94-#include <util/dir.h>
95
96 #include "util/uri_util.h"
97 #include "zorbaimpl.h"
98
99 namespace zorba {
100
101-DirectoryIteratorImpl::DirectoryIteratorImpl(std::string const& aPath)
102-{
103- theInternalDirIter = new dir_iterator(aPath);
104-}
105-
106-DirectoryIteratorImpl::~DirectoryIteratorImpl()
107-{
108- delete theInternalDirIter;
109+DirectoryIteratorImpl::DirectoryIteratorImpl(std::string const& aPath) :
110+ theInternalDirIter( aPath.c_str() )
111+{
112 }
113
114 bool
115 DirectoryIteratorImpl::next(std::string& aPathStr) const
116 {
117- if (theInternalDirIter->end()) {
118+ if (!theInternalDirIter.next()) {
119 return false;
120 }
121
122 // get the current pointed entry
123- aPathStr = *(*theInternalDirIter);
124-
125- // advance to the next entry
126- ++(*theInternalDirIter);
127+ aPathStr = theInternalDirIter.entry_name();
128
129 return true;
130 }
131
132 void DirectoryIteratorImpl::reset()
133 {
134- std::string aPath = theInternalDirIter->dirpath;
135- delete theInternalDirIter;
136- theInternalDirIter = new dir_iterator(aPath);
137+ theInternalDirIter.reset();
138 }
139
140 FileImpl::FileImpl(std::string const& path)
141
142=== modified file 'src/api/fileimpl.h'
143--- src/api/fileimpl.h 2012-04-24 12:39:38 +0000
144+++ src/api/fileimpl.h 2012-04-25 17:18:22 +0000
145@@ -20,10 +20,11 @@
146 #include <iostream>
147 #include <zorba/file.h>
148
149+#include "util/fs_util.h"
150+
151 namespace zorba {
152
153 class file;
154- class dir_iterator;
155 class DiagnosticHandler;
156
157
158@@ -31,14 +32,12 @@
159 {
160 private:
161
162- dir_iterator* theInternalDirIter;
163+ mutable fs::iterator theInternalDirIter;
164
165 public:
166
167 DirectoryIteratorImpl(std::string const& aPath);
168
169- ~DirectoryIteratorImpl();
170-
171 bool next(std::string& aPathStr) const;
172 void reset();
173 };
174
175=== modified file 'src/unit_tests/CMakeLists.txt'
176--- src/unit_tests/CMakeLists.txt 2012-04-24 12:39:38 +0000
177+++ src/unit_tests/CMakeLists.txt 2012-04-25 17:18:22 +0000
178@@ -20,6 +20,7 @@
179 unit_tests.cpp
180 test_uri.cpp
181 json_parser.cpp
182+ test_fs_iterator.cpp
183 )
184
185 IF (NOT ZORBA_NO_FULL_TEXT)
186
187=== added file 'src/unit_tests/test_fs_iterator.cpp'
188--- src/unit_tests/test_fs_iterator.cpp 1970-01-01 00:00:00 +0000
189+++ src/unit_tests/test_fs_iterator.cpp 2012-04-25 17:18:22 +0000
190@@ -0,0 +1,54 @@
191+/*
192+ * Copyright 2006-2010 The FLWOR Foundation.
193+ *
194+ * Licensed under the Apache License, Version 2.0 (the "License");
195+ * you may not use this file except in compliance with the License.
196+ * You may obtain a copy of the License at
197+ *
198+ * http://www.apache.org/licenses/LICENSE-2.0
199+ *
200+ * Unless required by applicable law or agreed to in writing, software
201+ * distributed under the License is distributed on an "AS IS" BASIS,
202+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203+ * See the License for the specific language governing permissions and
204+ * limitations under the License.
205+ */
206+
207+#include "stdafx.h"
208+
209+#include <iostream>
210+#include <zorba/zorba_exception.h>
211+
212+#include "util/fs_util.h"
213+
214+using namespace std;
215+using namespace zorba;
216+
217+///////////////////////////////////////////////////////////////////////////////
218+
219+namespace zorba {
220+namespace UnitTests {
221+
222+int test_fs_iterator( int argc, char *argv[] ) {
223+ int result = 0;
224+ try {
225+#ifndef WIN32
226+ fs::iterator dir_iter( "/" );
227+#else
228+ fs::iterator dir_iter( "C:\\" );
229+#endif /* WIN32 */
230+ while ( dir_iter.next() )
231+ cout << dir_iter.entry_name() << " (" << dir_iter.entry_type() << ')' << endl;
232+ }
233+ catch ( ZorbaException const &e ) {
234+ cerr << e << endl;
235+ result = 2;
236+ }
237+
238+ return result;
239+}
240+
241+} // namespace UnitTests
242+} // namespace zorba
243+
244+/* vim:set et sw=2 ts=2: */
245
246=== modified file 'src/unit_tests/unit_test_list.h'
247--- src/unit_tests/unit_test_list.h 2012-04-24 12:39:38 +0000
248+++ src/unit_tests/unit_test_list.h 2012-04-25 17:18:22 +0000
249@@ -28,6 +28,7 @@
250 int runDebuggerProtocolTest(int argc, char* argv[]);
251 int test_string( int, char*[] );
252 int test_unique_ptr( int, char*[] );
253+ int test_fs_iterator( int, char*[] );
254 #ifndef ZORBA_NO_FULL_TEXT
255 int test_stemmer( int, char*[] );
256 int test_thesaurus( int, char*[] );
257
258=== modified file 'src/unit_tests/unit_tests.cpp'
259--- src/unit_tests/unit_tests.cpp 2012-04-24 12:39:38 +0000
260+++ src/unit_tests/unit_tests.cpp 2012-04-25 17:18:22 +0000
261@@ -39,6 +39,7 @@
262 void initializeTestList() {
263 libunittests["string"] = test_string;
264 libunittests["uri"] = runUriTest;
265+ libunittests["fs_iterator"] = test_fs_iterator;
266 #ifndef ZORBA_NO_ICU
267 libunittests["icu_streambuf"] = test_icu_streambuf;
268 #endif /* ZORBA_NO_ICU */
269
270=== modified file 'src/util/CMakeLists.txt'
271--- src/util/CMakeLists.txt 2012-04-24 12:39:38 +0000
272+++ src/util/CMakeLists.txt 2012-04-25 17:18:22 +0000
273@@ -17,7 +17,6 @@
274 dynamic_bitset.cpp
275 error_util.cpp
276 file.cpp
277- dir.cpp
278 fs_util.cpp
279 indent.cpp
280 json_parser.cpp
281
282=== removed file 'src/util/dir.cpp'
283--- src/util/dir.cpp 2012-04-24 12:39:38 +0000
284+++ src/util/dir.cpp 1970-01-01 00:00:00 +0000
285@@ -1,175 +0,0 @@
286-/*
287- * Copyright 2006-2008 The FLWOR Foundation.
288- *
289- * Licensed under the Apache License, Version 2.0 (the "License");
290- * you may not use this file except in compliance with the License.
291- * You may obtain a copy of the License at
292- *
293- * http://www.apache.org/licenses/LICENSE-2.0
294- *
295- * Unless required by applicable law or agreed to in writing, software
296- * distributed under the License is distributed on an "AS IS" BASIS,
297- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
298- * See the License for the specific language governing permissions and
299- * limitations under the License.
300- */
301-#include "stdafx.h"
302-
303-#include "util/dir.h"
304-
305-#ifndef _WIN32_WCE
306-#include <errno.h>
307-#include <sys/stat.h>
308-#include <sys/types.h>
309-#else
310-#include <types.h>
311-#endif
312-#include <stdio.h>
313-
314-#if defined (WIN32)
315-#include <tchar.h>
316-#ifndef _WIN32_WCE
317-#include <io.h>
318-#include <direct.h>
319-#endif
320-#else
321-#include <sys/param.h>
322-#include <unistd.h>
323-#endif
324-
325-#ifndef _WIN32_WCE
326-#include <fcntl.h>
327-#endif
328-#include <sstream>
329-
330-#include "diagnostics/xquery_diagnostics.h"
331-
332-using namespace std;
333-
334-namespace zorba {
335-
336-// dir_iterator
337-
338-#define END true
339-
340-dir_iterator
341-directory::begin()
342-{
343- return dir_iterator(getPathString());
344-}
345-
346-dir_iterator
347-directory::end()
348-{
349- return dir_iterator(getPathString(), END);
350-}
351-
352-dir_iterator::dir_iterator(
353- string const& path,
354- bool end_iterator)
355-:
356- dirpath(path)
357-#ifndef WIN32
358- ,dirent(0)
359-#endif
360-{
361-#ifndef WIN32
362- dir = opendir(path.c_str());
363- if (dir==0) {
364- throw ZORBA_IO_EXCEPTION( "opendir()", path );
365- }
366- if (!end_iterator) operator++();
367-#else
368- if(!end_iterator) {
369- std::string path_star = path + "\\*.*";
370- WCHAR wpath_str[1024];
371- wpath_str[0] = 0;
372- if(MultiByteToWideChar(CP_UTF8,
373- 0, path_star.c_str(), -1,
374- wpath_str, sizeof(wpath_str)/sizeof(WCHAR)) == 0)
375- {//probably there is some invalid utf8 char, try the Windows ACP
376- MultiByteToWideChar(CP_ACP,
377- 0, path_star.c_str(), -1,
378- wpath_str, sizeof(wpath_str)/sizeof(WCHAR));
379- }
380- win32_dir = FindFirstFileW(wpath_str, &win32_direntry);
381- if(win32_dir == INVALID_HANDLE_VALUE) {
382- throw ZORBA_IO_EXCEPTION( "FindFirstFile()", path );
383- }
384- if (wcscmp(win32_direntry.cFileName, L".") == 0 ||
385- wcscmp(win32_direntry.cFileName, L"..") == 0) {
386- operator ++();
387- }
388- } else {
389- win32_dir = INVALID_HANDLE_VALUE;
390- wcscpy(win32_direntry.cFileName, L"");
391- }
392-#endif
393-
394-}
395-
396-dir_iterator::~dir_iterator()
397-{
398-#if ! defined (WIN32)
399- if (dir!=0) closedir(dir);
400-#else
401- if(win32_dir != INVALID_HANDLE_VALUE) {
402- FindClose(win32_dir);
403- }
404-#endif
405-}
406-
407-
408-void
409-dir_iterator::operator++()
410-{
411-#ifndef WIN32
412- if (dir!=0) {
413- while (true) {
414- dirent = readdir(dir);
415- if (dirent==0) {
416- closedir(dir);
417- dir = 0;
418- break;
419- }
420- if (strcmp(dirent->d_name,".") &&
421- strcmp(dirent->d_name,"..")) {
422- break;
423- }
424- }
425- }
426-#else
427- if(win32_dir != INVALID_HANDLE_VALUE) {
428- while(true) {
429- if(!FindNextFileW(win32_dir, &win32_direntry)) {
430- FindClose(win32_dir);
431- win32_dir = INVALID_HANDLE_VALUE;
432- wcscpy(win32_direntry.cFileName, L"");
433- break;
434- }
435- if (wcscmp(win32_direntry.cFileName, L".") &&
436- wcscmp(win32_direntry.cFileName, L"..")) {
437- break;
438- }
439- }
440- }
441-#endif
442-}
443-
444-bool operator!=(
445- dir_iterator const& x,
446- dir_iterator const& y)
447-{
448-#ifndef WIN32
449- if (x.dirpath==y.dirpath) return false;
450- if (x.dirent==y.dirent) return false;
451- return true;
452-#else
453- if (x.dirpath==y.dirpath) return false;
454- if (!wcscmp(x.win32_direntry.cFileName, y.win32_direntry.cFileName)) return false;
455- return true;
456-#endif
457-}
458-
459-} // namespace
460-/* vim:set et sw=2 ts=2: */
461
462=== removed file 'src/util/dir.h'
463--- src/util/dir.h 2012-04-24 12:39:38 +0000
464+++ src/util/dir.h 1970-01-01 00:00:00 +0000
465@@ -1,100 +0,0 @@
466-/*
467- * Copyright 2006-2008 The FLWOR Foundation.
468- *
469- * Licensed under the Apache License, Version 2.0 (the "License");
470- * you may not use this file except in compliance with the License.
471- * You may obtain a copy of the License at
472- *
473- * http://www.apache.org/licenses/LICENSE-2.0
474- *
475- * Unless required by applicable law or agreed to in writing, software
476- * distributed under the License is distributed on an "AS IS" BASIS,
477- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
478- * See the License for the specific language governing permissions and
479- * limitations under the License.
480- */
481-#pragma once
482-#ifndef ZORBA_UTIL_DIR_H
483-#define ZORBA_UTIL_DIR_H
484-
485-#include "zorba/util/file.h"
486-#include "zorbatypes/rchandle.h"
487-
488-#ifdef UNIX
489-#include <dirent.h>
490-#endif
491-
492-namespace zorba {
493-
494- class dir_iterator : public SimpleRCObject
495- {
496-
497- public:
498-
499- std::string dirpath;
500- std::string path;
501-#ifndef WIN32
502- DIR *dir;
503- struct dirent *dirent;
504-#else
505- HANDLE win32_dir;
506- WIN32_FIND_DATAW win32_direntry;
507- mutable char temp_file_name[1024];
508-#endif
509-
510- public:
511-
512- dir_iterator(const std::string& path, bool end_iterator = false);
513- ~dir_iterator();
514-
515- public: // iterator interface
516-
517- void operator++();
518-
519- bool end() const {
520-#ifndef WIN32
521- return dir == 0;
522-#else
523- return win32_dir == INVALID_HANDLE_VALUE;
524-#endif
525- }
526-
527-#ifndef WIN32
528- const char* operator*() {
529- return dirent->d_name;
530- }
531-#else
532- const char* operator*() {
533- WideCharToMultiByte(CP_UTF8, 0, win32_direntry.cFileName, -1, temp_file_name, sizeof(temp_file_name), NULL, NULL);
534- return temp_file_name;
535- }
536-#endif
537-
538- public:
539-#ifndef WIN32
540- const char* get_name() const {
541- return dirent?dirent->d_name:0;
542- }
543-#else
544- const char* get_name() const {
545- if (win32_dir == INVALID_HANDLE_VALUE)
546- return NULL;
547- WideCharToMultiByte(CP_UTF8, 0, win32_direntry.cFileName, -1, temp_file_name, sizeof(temp_file_name), NULL, NULL);
548- return temp_file_name;
549- }
550-#endif
551- };
552-
553- class directory : public file {
554-
555- public:
556- dir_iterator begin();
557- dir_iterator end();
558-
559- friend bool operator!=(dir_iterator const& x, dir_iterator const& y);
560-
561- };
562-
563-}
564-#endif
565-/* vim:set et sw=2 ts=2: */
566
567=== modified file 'src/util/file.cpp'
568--- src/util/file.cpp 2012-04-24 12:39:38 +0000
569+++ src/util/file.cpp 2012-04-25 17:18:22 +0000
570@@ -277,18 +277,6 @@
571 #endif
572 }
573
574-void file::lsdir(std::vector<std::string> &list) {
575-#ifdef ZORBA_WITH_FILE_ACCESS
576- try {
577- fs::lsdir( c_str(), list );
578- set_filetype( type_directory );
579- }
580- catch ( fs::exception const &e ) {
581- throw ZORBA_IO_EXCEPTION( e.function(), e.path() );
582- }
583-#endif
584-}
585-
586 void file::deep_mkdir() {
587 #ifdef ZORBA_WITH_FILE_ACCESS
588 vector<file> files;
589
590=== modified file 'src/util/fs_util.cpp'
591--- src/util/fs_util.cpp 2012-04-24 12:39:38 +0000
592+++ src/util/fs_util.cpp 2012-04-25 17:18:22 +0000
593@@ -23,6 +23,8 @@
594 # include <sys/types.h>
595 # include <sys/stat.h>
596 # include <unistd.h> /* for chdir(2) */
597+#else
598+# include <shlwapi.h>
599 #endif /* WIN32 */
600
601 #include "diagnostics/xquery_diagnostics.h"
602@@ -38,6 +40,17 @@
603 namespace zorba {
604 namespace fs {
605
606+///////////////////////////////////////////////////////////////////////////////
607+
608+char const *const type_string[] = {
609+ "non_existant",
610+ "directory",
611+ "file",
612+ "link",
613+ "volume",
614+ "other"
615+};
616+
617 ////////// helper functions ///////////////////////////////////////////////////
618
619 inline void replace_foreign( zstring *path ) {
620@@ -56,16 +69,21 @@
621
622 #ifdef ZORBA_WITH_FILE_ACCESS
623
624+static type map_type( DWORD dwFileAttributes ) {
625+ if ( dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
626+ return directory;
627+ if ( dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
628+ return link;
629+ return file;
630+}
631+
632 static type get_type( LPCWSTR wpath, size_type *size = nullptr ) {
633 WIN32_FILE_ATTRIBUTE_DATA data;
634 if ( ::GetFileAttributesEx( wpath, GetFileExInfoStandard, (void*)&data ) ) {
635- if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
636- return directory;
637- if ( data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
638- return link;
639- if ( size )
640+ type const t = map_type( data.dwFileAttributes );
641+ if ( t == file && size )
642 *size = ((size_type)data.nFileSizeHigh << 32) | data.nFileSizeLow;
643- return file;
644+ return t;
645 }
646 return non_existent;
647 }
648@@ -90,11 +108,13 @@
649 to_wchar( path, wpath );
650 WCHAR wfull_path[ MAX_PATH ];
651 DWORD const result = ::GetFullPathName(
652- wpath, sizeof( wpath ) / sizeof( wpath[0] ), wfull_path, NULL
653+ wpath, sizeof( wfull_path ) / sizeof( wfull_path[0] ), wfull_path, NULL
654 );
655 if ( !result )
656 throw ZORBA_IO_EXCEPTION( "GetFullPathName()", path );
657 to_char( wfull_path, abs_path );
658+#else
659+ ::strcpy( abs_path, path );
660 #endif /* WINCE */
661 }
662
663@@ -153,7 +173,7 @@
664 win32::to_char( wpath, path );
665 if ( !is_absolute( path ) ) {
666 // GetCurrentDirectory() sometimes misses drive letter.
667- filesystem_path fspath( path );
668+ filesystem_path fspath( path );
669 fspath.resolve_relative();
670 return fspath.get_path();
671 }
672@@ -277,29 +297,107 @@
673 #endif
674 }
675
676-void lsdir( char const *path, std::vector<std::string> &list )
677-{
678- DIR *dir;
679- struct dirent *ent;
680-
681- dir = opendir (path);
682- if (dir != NULL)
683- {
684- /* print all the files and directories within directory */
685- while ((ent = readdir (dir)) != NULL)
686- {
687- //printf ("%s\n", ent->d_name);
688- std::string item(ent->d_name);
689- list.push_back(item);
690- }
691- closedir (dir);
692- }
693- else
694- {
695- /* could not open directory */
696- throw fs::exception( "lsdir()", path );
697- }
698-}
699+iterator::iterator( char const *path ) : dir_path_( path ) {
700+ make_absolute( dir_path_ );
701+#ifndef WIN32
702+ if ( !(dir_ = ::opendir( dir_path_.c_str() )) )
703+ throw fs::exception( "iterator()", dir_path_.c_str() );
704+#else
705+ win32_opendir( dir_path_.c_str() );
706+#endif /* WIN32 */
707+}
708+
709+iterator::~iterator() {
710+#ifndef WIN32
711+ if ( ::closedir( dir_ ) != 0 )
712+ throw fs::exception( "closedir()", path() );
713+#else
714+ win32_closedir();
715+#endif /* WIN32 */
716+}
717+
718+bool iterator::next() {
719+ while ( true ) {
720+#ifndef WIN32
721+ if ( (ent_ = ::readdir( dir_ )) ) {
722+ switch ( ent_->d_type ) {
723+ case DT_DIR: {
724+ char const *const name = ent_->d_name;
725+ // skip "." and ".." entries
726+ if ( name[0] == '.' && (!name[1] || name[1] == '.' && !name[2]) )
727+ continue;
728+ ent_type_ = directory;
729+ break;
730+ }
731+ case DT_LNK:
732+ ent_type_ = link;
733+ break;
734+ case DT_REG:
735+ ent_type_ = file;
736+ break;
737+ default:
738+ ent_type_ = other;
739+ }
740+ return true;
741+ }
742+#else
743+ if ( !dir_is_empty_ ) {
744+ if ( use_first_ )
745+ use_first_ = false;
746+ else
747+ if ( !::FindNextFile( dir_, &ent_data_ ) ) {
748+ if ( ::GetLastError() != ERROR_NO_MORE_FILES )
749+ throw fs::exception( "FindNextFile()", path() );
750+ return false;
751+ }
752+
753+ LPCWSTR const wname = ent_data_.cFileName;
754+ // skip "." and ".." entries
755+ if ( wname[0] == TEXT('.') &&
756+ (!wname[1] || wname[1] == TEXT('.') && !wname[2]) )
757+ continue;
758+
759+ win32::to_char( wname, ent_name_ );
760+ ent_type_ = win32::map_type( ent_data_.dwFileAttributes );
761+ return true;
762+ }
763+#endif /* WIN32 */
764+ return false;
765+ } // while
766+}
767+
768+void iterator::reset() {
769+#ifndef WIN32
770+ ::rewinddir( dir_ );
771+#else
772+ win32_closedir();
773+ win32_opendir( dir_path_.c_str() );
774+#endif /* WIN32 */
775+}
776+
777+#ifdef WIN32
778+void iterator::win32_closedir() {
779+ if ( dir_ != INVALID_HANDLE_VALUE && !::FindClose( dir_ ) )
780+ throw fs::exception( "FindClose()", path() );
781+}
782+
783+void iterator::win32_opendir( char const *path ) {
784+ WCHAR wpath[ MAX_PATH ];
785+ win32::to_wchar( path, wpath );
786+ WCHAR wpattern[ MAX_PATH ];
787+ ::wcscpy( wpattern, wpath );
788+ ::PathAppend( wpattern, TEXT("*") );
789+ dir_ = ::FindFirstFile( wpattern, &ent_data_ );
790+ if ( dir_ == INVALID_HANDLE_VALUE ) {
791+ if ( ::GetLastError() != ERROR_FILE_NOT_FOUND )
792+ throw fs::exception( "FindFirstFile()", path );
793+ dir_is_empty_ = true;
794+ } else {
795+ dir_is_empty_ = false;
796+ use_first_ = true;
797+ }
798+}
799+#endif /* WIN32 */
800
801 bool remove( char const *path ) {
802 #ifndef WIN32
803
804=== modified file 'src/util/fs_util.h'
805--- src/util/fs_util.h 2012-04-24 12:39:38 +0000
806+++ src/util/fs_util.h 2012-04-25 17:18:22 +0000
807@@ -17,20 +17,14 @@
808 #ifndef ZORBA_FS_UTIL_H
809 #define ZORBA_FS_UTIL_H
810
811-#include <vector>
812-
813-#ifdef WIN32
814-# include "win32/dirent.h"
815-#else
816-# include <dirent.h> /* for implementing lsdir */
817-#endif /* WIN32 */
818-
819 #include <zorba/config.h>
820
821+#include <iostream>
822 #include <stdexcept>
823 #ifdef WIN32
824 # include <windows.h>
825 #else
826+# include <dirent.h>
827 # include <sys/types.h> /* for off_t */
828 #endif /* WIN32 */
829
830@@ -82,6 +76,11 @@
831 volume,
832 other // named pipe, character/block special, socket, etc.
833 };
834+extern char const *const type_string[];
835+
836+inline std::ostream& operator<<( std::ostream &o, type t ) {
837+ return o << type_string[ t ];
838+}
839
840 ////////// Windows ////////////////////////////////////////////////////////////
841
842@@ -152,25 +151,89 @@
843 mkdir( path.c_str() );
844 }
845
846-/**
847- * List files in dir
848- *
849- * @param path The full path of the directory to list.
850- * @throws fs::exception if the list fails.
851- */
852-void lsdir( char const *path, std::vector<std::string> & list );
853-
854-/**
855- * List files in dir
856- *
857- * @tparam PathStringType The \a path string type.
858- * @param path The full path of the directory to list.
859- * @throws fs::exception if the list fails.
860- */
861-template<class PathStringType> inline
862-void lsdir( PathStringType const &path, std::vector<std::string> & list ) {
863- lsdir( path.c_str(), list );
864-}
865+////////// Directory iteration ////////////////////////////////////////////////
866+
867+/**
868+ * An fs::iterator iterates over the entries in a directory.
869+ */
870+class iterator {
871+public:
872+ /**
873+ * Constructs an %itertor.
874+ *
875+ * @throws fs::exception if the construction failed, e.g., path not found.
876+ */
877+ iterator( char const *path );
878+
879+ /**
880+ * Destroys this %iterator.
881+ */
882+ ~iterator();
883+
884+ /**
885+ * Attempts to get the next directory entry.
886+ *
887+ * @return Returns \c true only if there is a next directory.
888+ */
889+ bool next();
890+
891+ /**
892+ * Gets the name of the curent directory entry.
893+ *
894+ * @return Returns said name.
895+ */
896+ char const* entry_name() const {
897+# ifndef WIN32
898+ return ent_->d_name;
899+# else
900+ return ent_name_;
901+# endif /* WIN32 */
902+ }
903+
904+ /**
905+ * Gets the type of the current directory entry.
906+ *
907+ * @return Returns said type.
908+ */
909+ type entry_type() const {
910+ return ent_type_;
911+ }
912+
913+ /**
914+ * Gets the directory's path.
915+ *
916+ * @return Returns said path.
917+ */
918+ char const* path() const {
919+ return dir_path_.c_str();
920+ }
921+
922+ /**
923+ * Resets this iterator to the beginning.
924+ */
925+ void reset();
926+
927+private:
928+ zstring dir_path_;
929+ type ent_type_;
930+#ifndef WIN32
931+ DIR *dir_;
932+ struct dirent *ent_;
933+#else
934+ HANDLE dir_;
935+ bool dir_is_empty_;
936+ WIN32_FIND_DATA ent_data_;
937+ char ent_name_[ MAX_PATH ];
938+ bool use_first_;
939+
940+ void win32_opendir( char const *path );
941+ void win32_closedir();
942+#endif /* WIN32 */
943+
944+ // forbid
945+ iterator( iterator const& );
946+ iterator& operator=( iterator const& );
947+};
948
949 #endif /* ZORBA_WITH_FILE_ACCESS */
950
951@@ -182,7 +245,7 @@
952 * Creates the given file.
953 *
954 * @param path The full path of the file to create.
955- * *throws fs::exception if the creation failed.
956+ * @throws fs::exception if the creation failed.
957 */
958 void create( char const *path );
959
960@@ -572,7 +635,8 @@
961 void make_absolute( PathStringType &path ) {
962 if ( !is_absolute( path ) ) {
963 #ifndef WIN32
964- path.insert( 0, 1, '/' );
965+ typedef typename PathStringType::size_type size_type;
966+ path.insert( static_cast<size_type>(0), static_cast<size_type>(1), '/' );
967 path.insert( 0, curdir().c_str() );
968 #else
969 char temp[ MAX_PATH ];
970
971=== removed file 'src/util/win32/dirent.h'
972--- src/util/win32/dirent.h 2012-03-08 23:20:54 +0000
973+++ src/util/win32/dirent.h 1970-01-01 00:00:00 +0000
974@@ -1,372 +0,0 @@
975-/*****************************************************************************
976- * dirent.h - dirent API for Microsoft Visual Studio
977- *
978- * Copyright (C) 2006 Toni Ronkko
979- *
980- * Permission is hereby granted, free of charge, to any person obtaining
981- * a copy of this software and associated documentation files (the
982- * ``Software''), to deal in the Software without restriction, including
983- * without limitation the rights to use, copy, modify, merge, publish,
984- * distribute, sublicense, and/or sell copies of the Software, and to
985- * permit persons to whom the Software is furnished to do so, subject to
986- * the following conditions:
987- *
988- * The above copyright notice and this permission notice shall be included
989- * in all copies or substantial portions of the Software.
990- *
991- * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
992- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
993- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
994- * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
995- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
996- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
997- * OTHER DEALINGS IN THE SOFTWARE.
998- *
999- * Mar 15, 2011, Toni Ronkko
1000- * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
1001- *
1002- * Aug 11, 2010, Toni Ronkko
1003- * Added d_type and d_namlen fields to dirent structure. The former is
1004- * especially useful for determining whether directory entry represents a
1005- * file or a directory. For more information, see
1006- * http://www.delorie.com/gnu/docs/glibc/libc_270.html
1007- *
1008- * Aug 11, 2010, Toni Ronkko
1009- * Improved conformance to the standards. For example, errno is now set
1010- * properly on failure and assert() is never used. Thanks to Peter Brockam
1011- * for suggestions.
1012- *
1013- * Aug 11, 2010, Toni Ronkko
1014- * Fixed a bug in rewinddir(): when using relative directory names, change
1015- * of working directory no longer causes rewinddir() to fail.
1016- *
1017- * Dec 15, 2009, John Cunningham
1018- * Added rewinddir member function
1019- *
1020- * Jan 18, 2008, Toni Ronkko
1021- * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
1022- * between multi-byte and unicode representations. This makes the
1023- * code simpler and also allows the code to be compiled under MingW. Thanks
1024- * to Azriel Fasten for the suggestion.
1025- *
1026- * Mar 4, 2007, Toni Ronkko
1027- * Bug fix: due to the strncpy_s() function this file only compiled in
1028- * Visual Studio 2005. Using the new string functions only when the
1029- * compiler version allows.
1030- *
1031- * Nov 2, 2006, Toni Ronkko
1032- * Major update: removed support for Watcom C, MS-DOS and Turbo C to
1033- * simplify the file, updated the code to compile cleanly on Visual
1034- * Studio 2005 with both unicode and multi-byte character strings,
1035- * removed rewinddir() as it had a bug.
1036- *
1037- * Aug 20, 2006, Toni Ronkko
1038- * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
1039- * comments by removing SGML tags.
1040- *
1041- * May 14 2002, Toni Ronkko
1042- * Embedded the function definitions directly to the header so that no
1043- * source modules need to be included in the Visual Studio project. Removed
1044- * all the dependencies to other projects so that this very header can be
1045- * used independently.
1046- *
1047- * May 28 1998, Toni Ronkko
1048- * First version.
1049- *****************************************************************************/
1050-#ifndef DIRENT_H
1051-#define DIRENT_H
1052-
1053-#define WIN32_LEAN_AND_MEAN
1054-#include <windows.h>
1055-#include <string.h>
1056-#include <stdlib.h>
1057-#include <sys/types.h>
1058-#include <sys/stat.h>
1059-#include <errno.h>
1060-
1061-/* Entries missing from MSVC 6.0 */
1062-#if !defined(FILE_ATTRIBUTE_DEVICE)
1063-# define FILE_ATTRIBUTE_DEVICE 0x40
1064-#endif
1065-
1066-/* File type and permission flags for stat() */
1067-#if defined(_MSC_VER) && !defined(S_IREAD)
1068-# define S_IFMT _S_IFMT /* file type mask */
1069-# define S_IFDIR _S_IFDIR /* directory */
1070-# define S_IFCHR _S_IFCHR /* character device */
1071-# define S_IFFIFO _S_IFFIFO /* pipe */
1072-# define S_IFREG _S_IFREG /* regular file */
1073-# define S_IREAD _S_IREAD /* read permission */
1074-# define S_IWRITE _S_IWRITE /* write permission */
1075-# define S_IEXEC _S_IEXEC /* execute permission */
1076-#endif
1077-#define S_IFBLK 0 /* block device */
1078-#define S_IFLNK 0 /* link */
1079-#define S_IFSOCK 0 /* socket */
1080-
1081-#if defined(_MSC_VER)
1082-# define S_IRUSR S_IREAD /* read, user */
1083-# define S_IWUSR S_IWRITE /* write, user */
1084-# define S_IXUSR 0 /* execute, user */
1085-# define S_IRGRP 0 /* read, group */
1086-# define S_IWGRP 0 /* write, group */
1087-# define S_IXGRP 0 /* execute, group */
1088-# define S_IROTH 0 /* read, others */
1089-# define S_IWOTH 0 /* write, others */
1090-# define S_IXOTH 0 /* execute, others */
1091-#endif
1092-
1093-/* Indicates that d_type field is available in dirent structure */
1094-#define _DIRENT_HAVE_D_TYPE
1095-
1096-/* File type flags for d_type */
1097-#define DT_UNKNOWN 0
1098-#define DT_REG S_IFREG
1099-#define DT_DIR S_IFDIR
1100-#define DT_FIFO S_IFFIFO
1101-#define DT_SOCK S_IFSOCK
1102-#define DT_CHR S_IFCHR
1103-#define DT_BLK S_IFBLK
1104-
1105-/* Macros for converting between st_mode and d_type */
1106-#define IFTODT(mode) ((mode) & S_IFMT)
1107-#define DTTOIF(type) (type)
1108-
1109-/*
1110- * File type macros. Note that block devices, sockets and links cannot be
1111- * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
1112- * only defined for compatibility. These macros should always return false
1113- * on Windows.
1114- */
1115-#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
1116-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
1117-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
1118-#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
1119-#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
1120-#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
1121-#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
1122-
1123-#ifdef __cplusplus
1124-extern "C" {
1125-#endif
1126-
1127-
1128-typedef struct dirent
1129-{
1130- char d_name[MAX_PATH + 1]; /* File name */
1131- size_t d_namlen; /* Length of name without \0 */
1132- int d_type; /* File type */
1133-} dirent;
1134-
1135-
1136-typedef struct DIR
1137-{
1138- dirent curentry; /* Current directory entry */
1139- WIN32_FIND_DATAA find_data; /* Private file data */
1140- int cached; /* True if data is valid */
1141- HANDLE search_handle; /* Win32 search handle */
1142- char patt[MAX_PATH + 3]; /* Initial directory name */
1143-} DIR;
1144-
1145-
1146-/* Forward declarations */
1147-static DIR *opendir(const char *dirname);
1148-static struct dirent *readdir(DIR *dirp);
1149-static int closedir(DIR *dirp);
1150-static void rewinddir(DIR* dirp);
1151-
1152-
1153-/* Use the new safe string functions introduced in Visual Studio 2005 */
1154-#if defined(_MSC_VER) && _MSC_VER >= 1400
1155-# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
1156-#else
1157-# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size))
1158-#endif
1159-
1160-/* Set errno variable */
1161-#if defined(_MSC_VER)
1162-#define DIRENT_SET_ERRNO(x) _set_errno (x)
1163-#else
1164-#define DIRENT_SET_ERRNO(x) (errno = (x))
1165-#endif
1166-
1167-
1168-/*****************************************************************************
1169- * Open directory stream DIRNAME for read and return a pointer to the
1170- * internal working area that is used to retrieve individual directory
1171- * entries.
1172- */
1173-static DIR *opendir(const char *dirname)
1174-{
1175- DIR *dirp;
1176-
1177- /* ensure that the resulting search pattern will be a valid file name */
1178- if (dirname == NULL) {
1179- DIRENT_SET_ERRNO (ENOENT);
1180- return NULL;
1181- }
1182- if (strlen (dirname) + 3 >= MAX_PATH) {
1183- DIRENT_SET_ERRNO (ENAMETOOLONG);
1184- return NULL;
1185- }
1186-
1187- /* construct new DIR structure */
1188- dirp = (DIR*) malloc (sizeof (struct DIR));
1189- if (dirp != NULL) {
1190- int error;
1191-
1192- /*
1193- * Convert relative directory name to an absolute one. This
1194- * allows rewinddir() to function correctly when the current working
1195- * directory is changed between opendir() and rewinddir().
1196- */
1197- if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) {
1198- char *p;
1199-
1200- /* append the search pattern "\\*\0" to the directory name */
1201- p = strchr (dirp->patt, '\0');
1202- if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') {
1203- *p++ = '\\';
1204- }
1205- *p++ = '*';
1206- *p = '\0';
1207-
1208- /* open directory stream and retrieve the first entry */
1209- dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
1210- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
1211- /* a directory entry is now waiting in memory */
1212- dirp->cached = 1;
1213- error = 0;
1214- } else {
1215- /* search pattern is not a directory name? */
1216- DIRENT_SET_ERRNO (ENOENT);
1217- error = 1;
1218- }
1219- } else {
1220- /* buffer too small */
1221- DIRENT_SET_ERRNO (ENOMEM);
1222- error = 1;
1223- }
1224-
1225- if (error) {
1226- free (dirp);
1227- dirp = NULL;
1228- }
1229- }
1230-
1231- return dirp;
1232-}
1233-
1234-
1235-/*****************************************************************************
1236- * Read a directory entry, and return a pointer to a dirent structure
1237- * containing the name of the entry in d_name field. Individual directory
1238- * entries returned by this very function include regular files,
1239- * sub-directories, pseudo-directories "." and "..", but also volume labels,
1240- * hidden files and system files may be returned.
1241- */
1242-static struct dirent *readdir(DIR *dirp)
1243-{
1244- DWORD attr;
1245- if (dirp == NULL) {
1246- /* directory stream did not open */
1247- DIRENT_SET_ERRNO (EBADF);
1248- return NULL;
1249- }
1250-
1251- /* get next directory entry */
1252- if (dirp->cached != 0) {
1253- /* a valid directory entry already in memory */
1254- dirp->cached = 0;
1255- } else {
1256- /* get the next directory entry from stream */
1257- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
1258- return NULL;
1259- }
1260- if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) {
1261- /* the very last entry has been processed or an error occured */
1262- FindClose (dirp->search_handle);
1263- dirp->search_handle = INVALID_HANDLE_VALUE;
1264- return NULL;
1265- }
1266- }
1267-
1268- /* copy as a multibyte character string */
1269- DIRENT_STRNCPY ( dirp->curentry.d_name,
1270- dirp->find_data.cFileName,
1271- sizeof(dirp->curentry.d_name) );
1272- dirp->curentry.d_name[MAX_PATH] = '\0';
1273-
1274- /* compute the length of name */
1275- dirp->curentry.d_namlen = strlen (dirp->curentry.d_name);
1276-
1277- /* determine file type */
1278- attr = dirp->find_data.dwFileAttributes;
1279- if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
1280- dirp->curentry.d_type = DT_CHR;
1281- } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1282- dirp->curentry.d_type = DT_DIR;
1283- } else {
1284- dirp->curentry.d_type = DT_REG;
1285- }
1286- return &dirp->curentry;
1287-}
1288-
1289-
1290-/*****************************************************************************
1291- * Close directory stream opened by opendir() function. Close of the
1292- * directory stream invalidates the DIR structure as well as any previously
1293- * read directory entry.
1294- */
1295-static int closedir(DIR *dirp)
1296-{
1297- if (dirp == NULL) {
1298- /* invalid directory stream */
1299- DIRENT_SET_ERRNO (EBADF);
1300- return -1;
1301- }
1302-
1303- /* release search handle */
1304- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
1305- FindClose (dirp->search_handle);
1306- dirp->search_handle = INVALID_HANDLE_VALUE;
1307- }
1308-
1309- /* release directory structure */
1310- free (dirp);
1311- return 0;
1312-}
1313-
1314-
1315-/*****************************************************************************
1316- * Resets the position of the directory stream to which dirp refers to the
1317- * beginning of the directory. It also causes the directory stream to refer
1318- * to the current state of the corresponding directory, as a call to opendir()
1319- * would have done. If dirp does not refer to a directory stream, the effect
1320- * is undefined.
1321- */
1322-static void rewinddir(DIR* dirp)
1323-{
1324- if (dirp != NULL) {
1325- /* release search handle */
1326- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
1327- FindClose (dirp->search_handle);
1328- }
1329-
1330- /* open new search handle and retrieve the first entry */
1331- dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
1332- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
1333- /* a directory entry is now waiting in memory */
1334- dirp->cached = 1;
1335- } else {
1336- /* failed to re-open directory: no directory entry in memory */
1337- dirp->cached = 0;
1338- }
1339- }
1340-}
1341-
1342-
1343-#ifdef __cplusplus
1344-}
1345-#endif
1346-#endif /*DIRENT_H*/

Subscribers

People subscribed via source and target branches