Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-986580 into lp:zorba.
Requested reviews: Cezar Andrei (cezar-andrei) Rodolfo Ochoa (rodolfo-ochoa) Related bugs: Bug #986580 in Zorba: "fs::lsdir() improvements" https://bugs.launchpad.net/zorba/+bug/986580 For more details, see: https://code.launchpad.net/~zorba-coders/zorba/bug-986580/+merge/103552 Better implementation of listing files in a directory. -- https://code.launchpad.net/~zorba-coders/zorba/bug-986580/+merge/103552 Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'CMakeLists.txt' --- CMakeLists.txt 2012-04-24 12:39:38 +0000 +++ CMakeLists.txt 2012-04-25 19:52:28 +0000 @@ -309,6 +309,13 @@ MESSAGE (STATUS "") # +# shlwapi +# +IF(WIN32) + SET(requiredlibs ${requiredlibs} "shlwapi") +ENDIF(WIN32) + +# # SWIG # IF (NOT ZORBA_SUPPRESS_SWIG) === modified file 'NOTICE.txt' --- NOTICE.txt 2012-04-18 15:34:39 +0000 +++ NOTICE.txt 2012-04-25 19:52:28 +0000 @@ -459,24 +459,6 @@ suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ----------------------------------------------------- - -src/util/win32/dirent.h - -Copyright: 2006 Toni Ronkko - - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - External libraries used by this project: ---------------------------------------------------- === modified file 'NOTICE.xml' --- NOTICE.xml 2012-04-24 12:39:38 +0000 +++ NOTICE.xml 2012-04-25 19:52:28 +0000 @@ -423,22 +423,6 @@ without express or implied warranty. </foreign-notice> </foreign-files> - <foreign-files> - <file>src/util/win32/dirent.h</file> - <copyright>2006 Toni Ronkko</copyright> - <foreign-notice> - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - </foreign-notice> - </foreign-files> <external-lib mandatory="true"> <name>LIBXML2</name> === modified file 'src/api/fileimpl.cpp' --- src/api/fileimpl.cpp 2012-04-24 12:39:38 +0000 +++ src/api/fileimpl.cpp 2012-04-25 19:52:28 +0000 @@ -29,44 +29,33 @@ #ifdef WIN32 #include <util/ascii_util.h> #endif -#include <util/dir.h> #include "util/uri_util.h" #include "zorbaimpl.h" namespace zorba { -DirectoryIteratorImpl::DirectoryIteratorImpl(std::string const& aPath) -{ - theInternalDirIter = new dir_iterator(aPath); -} - -DirectoryIteratorImpl::~DirectoryIteratorImpl() -{ - delete theInternalDirIter; +DirectoryIteratorImpl::DirectoryIteratorImpl(std::string const& aPath) : + theInternalDirIter( aPath.c_str() ) +{ } bool DirectoryIteratorImpl::next(std::string& aPathStr) const { - if (theInternalDirIter->end()) { + if (!theInternalDirIter.next()) { return false; } // get the current pointed entry - aPathStr = *(*theInternalDirIter); - - // advance to the next entry - ++(*theInternalDirIter); + aPathStr = theInternalDirIter.entry_name(); return true; } void DirectoryIteratorImpl::reset() { - std::string aPath = theInternalDirIter->dirpath; - delete theInternalDirIter; - theInternalDirIter = new dir_iterator(aPath); + theInternalDirIter.reset(); } FileImpl::FileImpl(std::string const& path) === modified file 'src/api/fileimpl.h' --- src/api/fileimpl.h 2012-04-24 12:39:38 +0000 +++ src/api/fileimpl.h 2012-04-25 19:52:28 +0000 @@ -20,10 +20,11 @@ #include <iostream> #include <zorba/file.h> +#include "util/fs_util.h" + namespace zorba { class file; - class dir_iterator; class DiagnosticHandler; @@ -31,14 +32,12 @@ { private: - dir_iterator* theInternalDirIter; + mutable fs::iterator theInternalDirIter; public: DirectoryIteratorImpl(std::string const& aPath); - ~DirectoryIteratorImpl(); - bool next(std::string& aPathStr) const; void reset(); }; === modified file 'src/unit_tests/CMakeLists.txt' --- src/unit_tests/CMakeLists.txt 2012-04-24 12:39:38 +0000 +++ src/unit_tests/CMakeLists.txt 2012-04-25 19:52:28 +0000 @@ -20,6 +20,7 @@ unit_tests.cpp test_uri.cpp json_parser.cpp + test_fs_iterator.cpp ) IF (NOT ZORBA_NO_FULL_TEXT) === added file 'src/unit_tests/test_fs_iterator.cpp' --- src/unit_tests/test_fs_iterator.cpp 1970-01-01 00:00:00 +0000 +++ src/unit_tests/test_fs_iterator.cpp 2012-04-25 19:52:28 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright 2006-2010 The FLWOR Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdafx.h" + +#include <iostream> +#include <zorba/zorba_exception.h> + +#include "util/fs_util.h" + +using namespace std; +using namespace zorba; + +/////////////////////////////////////////////////////////////////////////////// + +namespace zorba { +namespace UnitTests { + +int test_fs_iterator( int argc, char *argv[] ) { + int result = 0; + try { +#ifndef WIN32 + fs::iterator dir_iter( "/" ); +#else + fs::iterator dir_iter( "C:\\" ); +#endif /* WIN32 */ + while ( dir_iter.next() ) + cout << dir_iter.entry_name() << " (" << dir_iter.entry_type() << ')' << endl; + } + catch ( ZorbaException const &e ) { + cerr << e << endl; + result = 2; + } + + return result; +} + +} // namespace UnitTests +} // namespace zorba + +/* vim:set et sw=2 ts=2: */ === modified file 'src/unit_tests/unit_test_list.h' --- src/unit_tests/unit_test_list.h 2012-04-24 12:39:38 +0000 +++ src/unit_tests/unit_test_list.h 2012-04-25 19:52:28 +0000 @@ -28,6 +28,7 @@ int runDebuggerProtocolTest(int argc, char* argv[]); int test_string( int, char*[] ); int test_unique_ptr( int, char*[] ); + int test_fs_iterator( int, char*[] ); #ifndef ZORBA_NO_FULL_TEXT int test_stemmer( int, char*[] ); int test_thesaurus( int, char*[] ); === modified file 'src/unit_tests/unit_tests.cpp' --- src/unit_tests/unit_tests.cpp 2012-04-24 12:39:38 +0000 +++ src/unit_tests/unit_tests.cpp 2012-04-25 19:52:28 +0000 @@ -39,6 +39,7 @@ void initializeTestList() { libunittests["string"] = test_string; libunittests["uri"] = runUriTest; + libunittests["fs_iterator"] = test_fs_iterator; #ifndef ZORBA_NO_ICU libunittests["icu_streambuf"] = test_icu_streambuf; #endif /* ZORBA_NO_ICU */ === modified file 'src/util/CMakeLists.txt' --- src/util/CMakeLists.txt 2012-04-24 12:39:38 +0000 +++ src/util/CMakeLists.txt 2012-04-25 19:52:28 +0000 @@ -17,7 +17,6 @@ dynamic_bitset.cpp error_util.cpp file.cpp - dir.cpp fs_util.cpp indent.cpp json_parser.cpp === removed file 'src/util/dir.cpp' --- src/util/dir.cpp 2012-04-24 12:39:38 +0000 +++ src/util/dir.cpp 1970-01-01 00:00:00 +0000 @@ -1,175 +0,0 @@ -/* - * Copyright 2006-2008 The FLWOR Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "stdafx.h" - -#include "util/dir.h" - -#ifndef _WIN32_WCE -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> -#else -#include <types.h> -#endif -#include <stdio.h> - -#if defined (WIN32) -#include <tchar.h> -#ifndef _WIN32_WCE -#include <io.h> -#include <direct.h> -#endif -#else -#include <sys/param.h> -#include <unistd.h> -#endif - -#ifndef _WIN32_WCE -#include <fcntl.h> -#endif -#include <sstream> - -#include "diagnostics/xquery_diagnostics.h" - -using namespace std; - -namespace zorba { - -// dir_iterator - -#define END true - -dir_iterator -directory::begin() -{ - return dir_iterator(getPathString()); -} - -dir_iterator -directory::end() -{ - return dir_iterator(getPathString(), END); -} - -dir_iterator::dir_iterator( - string const& path, - bool end_iterator) -: - dirpath(path) -#ifndef WIN32 - ,dirent(0) -#endif -{ -#ifndef WIN32 - dir = opendir(path.c_str()); - if (dir==0) { - throw ZORBA_IO_EXCEPTION( "opendir()", path ); - } - if (!end_iterator) operator++(); -#else - if(!end_iterator) { - std::string path_star = path + "\\*.*"; - WCHAR wpath_str[1024]; - wpath_str[0] = 0; - if(MultiByteToWideChar(CP_UTF8, - 0, path_star.c_str(), -1, - wpath_str, sizeof(wpath_str)/sizeof(WCHAR)) == 0) - {//probably there is some invalid utf8 char, try the Windows ACP - MultiByteToWideChar(CP_ACP, - 0, path_star.c_str(), -1, - wpath_str, sizeof(wpath_str)/sizeof(WCHAR)); - } - win32_dir = FindFirstFileW(wpath_str, &win32_direntry); - if(win32_dir == INVALID_HANDLE_VALUE) { - throw ZORBA_IO_EXCEPTION( "FindFirstFile()", path ); - } - if (wcscmp(win32_direntry.cFileName, L".") == 0 || - wcscmp(win32_direntry.cFileName, L"..") == 0) { - operator ++(); - } - } else { - win32_dir = INVALID_HANDLE_VALUE; - wcscpy(win32_direntry.cFileName, L""); - } -#endif - -} - -dir_iterator::~dir_iterator() -{ -#if ! defined (WIN32) - if (dir!=0) closedir(dir); -#else - if(win32_dir != INVALID_HANDLE_VALUE) { - FindClose(win32_dir); - } -#endif -} - - -void -dir_iterator::operator++() -{ -#ifndef WIN32 - if (dir!=0) { - while (true) { - dirent = readdir(dir); - if (dirent==0) { - closedir(dir); - dir = 0; - break; - } - if (strcmp(dirent->d_name,".") && - strcmp(dirent->d_name,"..")) { - break; - } - } - } -#else - if(win32_dir != INVALID_HANDLE_VALUE) { - while(true) { - if(!FindNextFileW(win32_dir, &win32_direntry)) { - FindClose(win32_dir); - win32_dir = INVALID_HANDLE_VALUE; - wcscpy(win32_direntry.cFileName, L""); - break; - } - if (wcscmp(win32_direntry.cFileName, L".") && - wcscmp(win32_direntry.cFileName, L"..")) { - break; - } - } - } -#endif -} - -bool operator!=( - dir_iterator const& x, - dir_iterator const& y) -{ -#ifndef WIN32 - if (x.dirpath==y.dirpath) return false; - if (x.dirent==y.dirent) return false; - return true; -#else - if (x.dirpath==y.dirpath) return false; - if (!wcscmp(x.win32_direntry.cFileName, y.win32_direntry.cFileName)) return false; - return true; -#endif -} - -} // namespace -/* vim:set et sw=2 ts=2: */ === removed file 'src/util/dir.h' --- src/util/dir.h 2012-04-24 12:39:38 +0000 +++ src/util/dir.h 1970-01-01 00:00:00 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright 2006-2008 The FLWOR Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once -#ifndef ZORBA_UTIL_DIR_H -#define ZORBA_UTIL_DIR_H - -#include "zorba/util/file.h" -#include "zorbatypes/rchandle.h" - -#ifdef UNIX -#include <dirent.h> -#endif - -namespace zorba { - - class dir_iterator : public SimpleRCObject - { - - public: - - std::string dirpath; - std::string path; -#ifndef WIN32 - DIR *dir; - struct dirent *dirent; -#else - HANDLE win32_dir; - WIN32_FIND_DATAW win32_direntry; - mutable char temp_file_name[1024]; -#endif - - public: - - dir_iterator(const std::string& path, bool end_iterator = false); - ~dir_iterator(); - - public: // iterator interface - - void operator++(); - - bool end() const { -#ifndef WIN32 - return dir == 0; -#else - return win32_dir == INVALID_HANDLE_VALUE; -#endif - } - -#ifndef WIN32 - const char* operator*() { - return dirent->d_name; - } -#else - const char* operator*() { - WideCharToMultiByte(CP_UTF8, 0, win32_direntry.cFileName, -1, temp_file_name, sizeof(temp_file_name), NULL, NULL); - return temp_file_name; - } -#endif - - public: -#ifndef WIN32 - const char* get_name() const { - return dirent?dirent->d_name:0; - } -#else - const char* get_name() const { - if (win32_dir == INVALID_HANDLE_VALUE) - return NULL; - WideCharToMultiByte(CP_UTF8, 0, win32_direntry.cFileName, -1, temp_file_name, sizeof(temp_file_name), NULL, NULL); - return temp_file_name; - } -#endif - }; - - class directory : public file { - - public: - dir_iterator begin(); - dir_iterator end(); - - friend bool operator!=(dir_iterator const& x, dir_iterator const& y); - - }; - -} -#endif -/* vim:set et sw=2 ts=2: */ === modified file 'src/util/file.cpp' --- src/util/file.cpp 2012-04-24 12:39:38 +0000 +++ src/util/file.cpp 2012-04-25 19:52:28 +0000 @@ -280,7 +280,9 @@ void file::lsdir(std::vector<std::string> &list) { #ifdef ZORBA_WITH_FILE_ACCESS try { - fs::lsdir( c_str(), list ); + fs::iterator dir_iter( c_str() ); + while ( dir_iter.next() ) + list.push_back( dir_iter.entry_name() ); set_filetype( type_directory ); } catch ( fs::exception const &e ) { === modified file 'src/util/fs_util.cpp' --- src/util/fs_util.cpp 2012-04-24 12:39:38 +0000 +++ src/util/fs_util.cpp 2012-04-25 19:52:28 +0000 @@ -23,6 +23,8 @@ # include <sys/types.h> # include <sys/stat.h> # include <unistd.h> /* for chdir(2) */ +#else +# include <shlwapi.h> #endif /* WIN32 */ #include "diagnostics/xquery_diagnostics.h" @@ -38,6 +40,17 @@ namespace zorba { namespace fs { +/////////////////////////////////////////////////////////////////////////////// + +char const *const type_string[] = { + "non_existant", + "directory", + "file", + "link", + "volume", + "other" +}; + ////////// helper functions /////////////////////////////////////////////////// inline void replace_foreign( zstring *path ) { @@ -56,16 +69,21 @@ #ifdef ZORBA_WITH_FILE_ACCESS +static type map_type( DWORD dwFileAttributes ) { + if ( dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + return directory; + if ( dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) + return link; + return file; +} + static type get_type( LPCWSTR wpath, size_type *size = nullptr ) { WIN32_FILE_ATTRIBUTE_DATA data; if ( ::GetFileAttributesEx( wpath, GetFileExInfoStandard, (void*)&data ) ) { - if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) - return directory; - if ( data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) - return link; - if ( size ) + type const t = map_type( data.dwFileAttributes ); + if ( t == file && size ) *size = ((size_type)data.nFileSizeHigh << 32) | data.nFileSizeLow; - return file; + return t; } return non_existent; } @@ -90,11 +108,13 @@ to_wchar( path, wpath ); WCHAR wfull_path[ MAX_PATH ]; DWORD const result = ::GetFullPathName( - wpath, sizeof( wpath ) / sizeof( wpath[0] ), wfull_path, NULL + wpath, sizeof( wfull_path ) / sizeof( wfull_path[0] ), wfull_path, NULL ); if ( !result ) throw ZORBA_IO_EXCEPTION( "GetFullPathName()", path ); to_char( wfull_path, abs_path ); +#else + ::strcpy( abs_path, path ); #endif /* WINCE */ } @@ -153,7 +173,7 @@ win32::to_char( wpath, path ); if ( !is_absolute( path ) ) { // GetCurrentDirectory() sometimes misses drive letter. - filesystem_path fspath( path ); + filesystem_path fspath( path ); fspath.resolve_relative(); return fspath.get_path(); } @@ -277,29 +297,107 @@ #endif } -void lsdir( char const *path, std::vector<std::string> &list ) -{ - DIR *dir; - struct dirent *ent; - - dir = opendir (path); - if (dir != NULL) - { - /* print all the files and directories within directory */ - while ((ent = readdir (dir)) != NULL) - { - //printf ("%s\n", ent->d_name); - std::string item(ent->d_name); - list.push_back(item); - } - closedir (dir); - } - else - { - /* could not open directory */ - throw fs::exception( "lsdir()", path ); - } -} +iterator::iterator( char const *path ) : dir_path_( path ) { + make_absolute( dir_path_ ); +#ifndef WIN32 + if ( !(dir_ = ::opendir( dir_path_.c_str() )) ) + throw fs::exception( "iterator()", dir_path_.c_str() ); +#else + win32_opendir( dir_path_.c_str() ); +#endif /* WIN32 */ +} + +iterator::~iterator() { +#ifndef WIN32 + if ( ::closedir( dir_ ) != 0 ) + throw fs::exception( "closedir()", path() ); +#else + win32_closedir(); +#endif /* WIN32 */ +} + +bool iterator::next() { + while ( true ) { +#ifndef WIN32 + if ( (ent_ = ::readdir( dir_ )) ) { + switch ( ent_->d_type ) { + case DT_DIR: { + char const *const name = ent_->d_name; + // skip "." and ".." entries + if ( name[0] == '.' && (!name[1] || name[1] == '.' && !name[2]) ) + continue; + ent_type_ = directory; + break; + } + case DT_LNK: + ent_type_ = link; + break; + case DT_REG: + ent_type_ = file; + break; + default: + ent_type_ = other; + } + return true; + } +#else + if ( !dir_is_empty_ ) { + if ( use_first_ ) + use_first_ = false; + else + if ( !::FindNextFile( dir_, &ent_data_ ) ) { + if ( ::GetLastError() != ERROR_NO_MORE_FILES ) + throw fs::exception( "FindNextFile()", path() ); + return false; + } + + LPCWSTR const wname = ent_data_.cFileName; + // skip "." and ".." entries + if ( wname[0] == TEXT('.') && + (!wname[1] || wname[1] == TEXT('.') && !wname[2]) ) + continue; + + win32::to_char( wname, ent_name_ ); + ent_type_ = win32::map_type( ent_data_.dwFileAttributes ); + return true; + } +#endif /* WIN32 */ + return false; + } // while +} + +void iterator::reset() { +#ifndef WIN32 + ::rewinddir( dir_ ); +#else + win32_closedir(); + win32_opendir( dir_path_.c_str() ); +#endif /* WIN32 */ +} + +#ifdef WIN32 +void iterator::win32_closedir() { + if ( dir_ != INVALID_HANDLE_VALUE && !::FindClose( dir_ ) ) + throw fs::exception( "FindClose()", path() ); +} + +void iterator::win32_opendir( char const *path ) { + WCHAR wpath[ MAX_PATH ]; + win32::to_wchar( path, wpath ); + WCHAR wpattern[ MAX_PATH ]; + ::wcscpy( wpattern, wpath ); + ::PathAppend( wpattern, TEXT("*") ); + dir_ = ::FindFirstFile( wpattern, &ent_data_ ); + if ( dir_ == INVALID_HANDLE_VALUE ) { + if ( ::GetLastError() != ERROR_FILE_NOT_FOUND ) + throw fs::exception( "FindFirstFile()", path ); + dir_is_empty_ = true; + } else { + dir_is_empty_ = false; + use_first_ = true; + } +} +#endif /* WIN32 */ bool remove( char const *path ) { #ifndef WIN32 === modified file 'src/util/fs_util.h' --- src/util/fs_util.h 2012-04-24 12:39:38 +0000 +++ src/util/fs_util.h 2012-04-25 19:52:28 +0000 @@ -17,20 +17,14 @@ #ifndef ZORBA_FS_UTIL_H #define ZORBA_FS_UTIL_H -#include <vector> - -#ifdef WIN32 -# include "win32/dirent.h" -#else -# include <dirent.h> /* for implementing lsdir */ -#endif /* WIN32 */ - #include <zorba/config.h> +#include <iostream> #include <stdexcept> #ifdef WIN32 # include <windows.h> #else +# include <dirent.h> # include <sys/types.h> /* for off_t */ #endif /* WIN32 */ @@ -82,6 +76,11 @@ volume, other // named pipe, character/block special, socket, etc. }; +extern char const *const type_string[]; + +inline std::ostream& operator<<( std::ostream &o, type t ) { + return o << type_string[ t ]; +} ////////// Windows //////////////////////////////////////////////////////////// @@ -152,25 +151,89 @@ mkdir( path.c_str() ); } -/** - * List files in dir - * - * @param path The full path of the directory to list. - * @throws fs::exception if the list fails. - */ -void lsdir( char const *path, std::vector<std::string> & list ); - -/** - * List files in dir - * - * @tparam PathStringType The \a path string type. - * @param path The full path of the directory to list. - * @throws fs::exception if the list fails. - */ -template<class PathStringType> inline -void lsdir( PathStringType const &path, std::vector<std::string> & list ) { - lsdir( path.c_str(), list ); -} +////////// Directory iteration //////////////////////////////////////////////// + +/** + * An fs::iterator iterates over the entries in a directory. + */ +class iterator { +public: + /** + * Constructs an %itertor. + * + * @throws fs::exception if the construction failed, e.g., path not found. + */ + iterator( char const *path ); + + /** + * Destroys this %iterator. + */ + ~iterator(); + + /** + * Attempts to get the next directory entry. + * + * @return Returns \c true only if there is a next directory. + */ + bool next(); + + /** + * Gets the name of the curent directory entry. + * + * @return Returns said name. + */ + char const* entry_name() const { +# ifndef WIN32 + return ent_->d_name; +# else + return ent_name_; +# endif /* WIN32 */ + } + + /** + * Gets the type of the current directory entry. + * + * @return Returns said type. + */ + type entry_type() const { + return ent_type_; + } + + /** + * Gets the directory's path. + * + * @return Returns said path. + */ + char const* path() const { + return dir_path_.c_str(); + } + + /** + * Resets this iterator to the beginning. + */ + void reset(); + +private: + zstring dir_path_; + type ent_type_; +#ifndef WIN32 + DIR *dir_; + struct dirent *ent_; +#else + HANDLE dir_; + bool dir_is_empty_; + WIN32_FIND_DATA ent_data_; + char ent_name_[ MAX_PATH ]; + bool use_first_; + + void win32_opendir( char const *path ); + void win32_closedir(); +#endif /* WIN32 */ + + // forbid + iterator( iterator const& ); + iterator& operator=( iterator const& ); +}; #endif /* ZORBA_WITH_FILE_ACCESS */ @@ -182,7 +245,7 @@ * Creates the given file. * * @param path The full path of the file to create. - * *throws fs::exception if the creation failed. + * @throws fs::exception if the creation failed. */ void create( char const *path ); @@ -572,7 +635,8 @@ void make_absolute( PathStringType &path ) { if ( !is_absolute( path ) ) { #ifndef WIN32 - path.insert( 0, 1, '/' ); + typedef typename PathStringType::size_type size_type; + path.insert( static_cast<size_type>(0), static_cast<size_type>(1), '/' ); path.insert( 0, curdir().c_str() ); #else char temp[ MAX_PATH ]; === removed file 'src/util/win32/dirent.h' --- src/util/win32/dirent.h 2012-03-08 23:20:54 +0000 +++ src/util/win32/dirent.h 1970-01-01 00:00:00 +0000 @@ -1,372 +0,0 @@ -/***************************************************************************** - * dirent.h - dirent API for Microsoft Visual Studio - * - * Copyright (C) 2006 Toni Ronkko - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * ``Software''), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Mar 15, 2011, Toni Ronkko - * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. - * - * Aug 11, 2010, Toni Ronkko - * Added d_type and d_namlen fields to dirent structure. The former is - * especially useful for determining whether directory entry represents a - * file or a directory. For more information, see - * http://www.delorie.com/gnu/docs/glibc/libc_270.html - * - * Aug 11, 2010, Toni Ronkko - * Improved conformance to the standards. For example, errno is now set - * properly on failure and assert() is never used. Thanks to Peter Brockam - * for suggestions. - * - * Aug 11, 2010, Toni Ronkko - * Fixed a bug in rewinddir(): when using relative directory names, change - * of working directory no longer causes rewinddir() to fail. - * - * Dec 15, 2009, John Cunningham - * Added rewinddir member function - * - * Jan 18, 2008, Toni Ronkko - * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string - * between multi-byte and unicode representations. This makes the - * code simpler and also allows the code to be compiled under MingW. Thanks - * to Azriel Fasten for the suggestion. - * - * Mar 4, 2007, Toni Ronkko - * Bug fix: due to the strncpy_s() function this file only compiled in - * Visual Studio 2005. Using the new string functions only when the - * compiler version allows. - * - * Nov 2, 2006, Toni Ronkko - * Major update: removed support for Watcom C, MS-DOS and Turbo C to - * simplify the file, updated the code to compile cleanly on Visual - * Studio 2005 with both unicode and multi-byte character strings, - * removed rewinddir() as it had a bug. - * - * Aug 20, 2006, Toni Ronkko - * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified - * comments by removing SGML tags. - * - * May 14 2002, Toni Ronkko - * Embedded the function definitions directly to the header so that no - * source modules need to be included in the Visual Studio project. Removed - * all the dependencies to other projects so that this very header can be - * used independently. - * - * May 28 1998, Toni Ronkko - * First version. - *****************************************************************************/ -#ifndef DIRENT_H -#define DIRENT_H - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -/* Entries missing from MSVC 6.0 */ -#if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 -#endif - -/* File type and permission flags for stat() */ -#if defined(_MSC_VER) && !defined(S_IREAD) -# define S_IFMT _S_IFMT /* file type mask */ -# define S_IFDIR _S_IFDIR /* directory */ -# define S_IFCHR _S_IFCHR /* character device */ -# define S_IFFIFO _S_IFFIFO /* pipe */ -# define S_IFREG _S_IFREG /* regular file */ -# define S_IREAD _S_IREAD /* read permission */ -# define S_IWRITE _S_IWRITE /* write permission */ -# define S_IEXEC _S_IEXEC /* execute permission */ -#endif -#define S_IFBLK 0 /* block device */ -#define S_IFLNK 0 /* link */ -#define S_IFSOCK 0 /* socket */ - -#if defined(_MSC_VER) -# define S_IRUSR S_IREAD /* read, user */ -# define S_IWUSR S_IWRITE /* write, user */ -# define S_IXUSR 0 /* execute, user */ -# define S_IRGRP 0 /* read, group */ -# define S_IWGRP 0 /* write, group */ -# define S_IXGRP 0 /* execute, group */ -# define S_IROTH 0 /* read, others */ -# define S_IWOTH 0 /* write, others */ -# define S_IXOTH 0 /* execute, others */ -#endif - -/* Indicates that d_type field is available in dirent structure */ -#define _DIRENT_HAVE_D_TYPE - -/* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK - -/* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) -#define DTTOIF(type) (type) - -/* - * File type macros. Note that block devices, sockets and links cannot be - * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are - * only defined for compatibility. These macros should always return false - * on Windows. - */ -#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) -#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef struct dirent -{ - char d_name[MAX_PATH + 1]; /* File name */ - size_t d_namlen; /* Length of name without \0 */ - int d_type; /* File type */ -} dirent; - - -typedef struct DIR -{ - dirent curentry; /* Current directory entry */ - WIN32_FIND_DATAA find_data; /* Private file data */ - int cached; /* True if data is valid */ - HANDLE search_handle; /* Win32 search handle */ - char patt[MAX_PATH + 3]; /* Initial directory name */ -} DIR; - - -/* Forward declarations */ -static DIR *opendir(const char *dirname); -static struct dirent *readdir(DIR *dirp); -static int closedir(DIR *dirp); -static void rewinddir(DIR* dirp); - - -/* Use the new safe string functions introduced in Visual Studio 2005 */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 -# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE) -#else -# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size)) -#endif - -/* Set errno variable */ -#if defined(_MSC_VER) -#define DIRENT_SET_ERRNO(x) _set_errno (x) -#else -#define DIRENT_SET_ERRNO(x) (errno = (x)) -#endif - - -/***************************************************************************** - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static DIR *opendir(const char *dirname) -{ - DIR *dirp; - - /* ensure that the resulting search pattern will be a valid file name */ - if (dirname == NULL) { - DIRENT_SET_ERRNO (ENOENT); - return NULL; - } - if (strlen (dirname) + 3 >= MAX_PATH) { - DIRENT_SET_ERRNO (ENAMETOOLONG); - return NULL; - } - - /* construct new DIR structure */ - dirp = (DIR*) malloc (sizeof (struct DIR)); - if (dirp != NULL) { - int error; - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly when the current working - * directory is changed between opendir() and rewinddir(). - */ - if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) { - char *p; - - /* append the search pattern "\\*\0" to the directory name */ - p = strchr (dirp->patt, '\0'); - if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') { - *p++ = '\\'; - } - *p++ = '*'; - *p = '\0'; - - /* open directory stream and retrieve the first entry */ - dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); - if (dirp->search_handle != INVALID_HANDLE_VALUE) { - /* a directory entry is now waiting in memory */ - dirp->cached = 1; - error = 0; - } else { - /* search pattern is not a directory name? */ - DIRENT_SET_ERRNO (ENOENT); - error = 1; - } - } else { - /* buffer too small */ - DIRENT_SET_ERRNO (ENOMEM); - error = 1; - } - - if (error) { - free (dirp); - dirp = NULL; - } - } - - return dirp; -} - - -/***************************************************************************** - * Read a directory entry, and return a pointer to a dirent structure - * containing the name of the entry in d_name field. Individual directory - * entries returned by this very function include regular files, - * sub-directories, pseudo-directories "." and "..", but also volume labels, - * hidden files and system files may be returned. - */ -static struct dirent *readdir(DIR *dirp) -{ - DWORD attr; - if (dirp == NULL) { - /* directory stream did not open */ - DIRENT_SET_ERRNO (EBADF); - return NULL; - } - - /* get next directory entry */ - if (dirp->cached != 0) { - /* a valid directory entry already in memory */ - dirp->cached = 0; - } else { - /* get the next directory entry from stream */ - if (dirp->search_handle == INVALID_HANDLE_VALUE) { - return NULL; - } - if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) { - /* the very last entry has been processed or an error occured */ - FindClose (dirp->search_handle); - dirp->search_handle = INVALID_HANDLE_VALUE; - return NULL; - } - } - - /* copy as a multibyte character string */ - DIRENT_STRNCPY ( dirp->curentry.d_name, - dirp->find_data.cFileName, - sizeof(dirp->curentry.d_name) ); - dirp->curentry.d_name[MAX_PATH] = '\0'; - - /* compute the length of name */ - dirp->curentry.d_namlen = strlen (dirp->curentry.d_name); - - /* determine file type */ - attr = dirp->find_data.dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - dirp->curentry.d_type = DT_CHR; - } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - dirp->curentry.d_type = DT_DIR; - } else { - dirp->curentry.d_type = DT_REG; - } - return &dirp->curentry; -} - - -/***************************************************************************** - * Close directory stream opened by opendir() function. Close of the - * directory stream invalidates the DIR structure as well as any previously - * read directory entry. - */ -static int closedir(DIR *dirp) -{ - if (dirp == NULL) { - /* invalid directory stream */ - DIRENT_SET_ERRNO (EBADF); - return -1; - } - - /* release search handle */ - if (dirp->search_handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->search_handle); - dirp->search_handle = INVALID_HANDLE_VALUE; - } - - /* release directory structure */ - free (dirp); - return 0; -} - - -/***************************************************************************** - * Resets the position of the directory stream to which dirp refers to the - * beginning of the directory. It also causes the directory stream to refer - * to the current state of the corresponding directory, as a call to opendir() - * would have done. If dirp does not refer to a directory stream, the effect - * is undefined. - */ -static void rewinddir(DIR* dirp) -{ - if (dirp != NULL) { - /* release search handle */ - if (dirp->search_handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->search_handle); - } - - /* open new search handle and retrieve the first entry */ - dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); - if (dirp->search_handle != INVALID_HANDLE_VALUE) { - /* a directory entry is now waiting in memory */ - dirp->cached = 1; - } else { - /* failed to re-open directory: no directory entry in memory */ - dirp->cached = 0; - } - } -} - - -#ifdef __cplusplus -} -#endif -#endif /*DIRENT_H*/
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp