diff options
| author | Carl Hetherington <cth@carlh.net> | 2020-11-23 23:28:15 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2020-11-23 23:28:15 +0100 |
| commit | 53ce270e5e007f9babf74002f6504286e172ce36 (patch) | |
| tree | 03f6559d203f3525af43d7e423a5fe9aa762115d /src | |
| parent | 10f558f9b1b36a0a4e0a1356672a9b89620d5ae0 (diff) | |
Fix UTF-8 filename handling; replace DirScanner code with boost-based implementation.
Diffstat (limited to 'src')
| -rw-r--r-- | src/KM_fileio.cpp | 311 | ||||
| -rwxr-xr-x | src/KM_fileio.h | 17 |
2 files changed, 52 insertions, 276 deletions
diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp index c95c690..b942646 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -88,9 +88,19 @@ do_stat(const char* path, fstat_t* stat_info) #ifdef KM_WIN32 UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - if ( _stati64(path, stat_info) == (__int64)-1 ) + int const wn = MultiByteToWideChar (CP_UTF8, 0, path, -1, 0, 0); + wchar_t* buffer = new wchar_t[wn]; + if (MultiByteToWideChar (CP_UTF8, 0, path, -1, buffer, wn) == 0) + { + delete[] buffer; + return Kumu::RESULT_FAIL; + } + + if ( _wstati64(buffer, stat_info) == (__int64)-1 ) result = Kumu::RESULT_FILEOPEN; + delete[] buffer; + ::SetErrorMode( prev ); #else if ( stat(path, stat_info) == -1L ) @@ -755,7 +765,14 @@ Kumu::FileReader::OpenRead(const std::string& filename) const // suppress popup window on error UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - const_cast<FileReader*>(this)->m_Handle = ::CreateFileA(filename.c_str(), + int const wn = MultiByteToWideChar (CP_UTF8, 0, filename, -1, 0, 0); + wchar_t* buffer = new wchar_t[wn]; + if (MultiByteToWideChar (CP_UTF8, 0, filename, -1, buffer, wn) == 0) + { + delete[] buffer; + return Kumu::RESULT_FAIL; + } + const_cast<FileReader*>(this)->m_Handle = ::CreateFileW(buffer, (GENERIC_READ), // open for reading FILE_SHARE_READ, // share for reading NULL, // no security @@ -764,6 +781,8 @@ Kumu::FileReader::OpenRead(const std::string& filename) const NULL // no template file ); + delete[] buffer; + ::SetErrorMode(prev); return ( m_Handle == INVALID_HANDLE_VALUE ) ? @@ -879,7 +898,15 @@ Kumu::FileWriter::OpenWrite(const std::string& filename) // suppress popup window on error UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - m_Handle = ::CreateFileA(filename.c_str(), + int const wn = MultiByteToWideChar (CP_UTF8, 0, filename, -1, 0, 0); + wchar_t* buffer = new wchar_t[wn]; + if (MultiByteToWideChar (CP_UTF8, 0, filename, -1, buffer, wn) == 0) + { + delete[] buffer; + return Kumu::RESULT_FAIL; + } + + m_Handle = ::CreateFileW(buffer, (GENERIC_WRITE|GENERIC_READ), // open for reading FILE_SHARE_READ, // share for reading NULL, // no security @@ -888,6 +915,8 @@ Kumu::FileWriter::OpenWrite(const std::string& filename) NULL // no template file ); + delete[] buffer; + ::SetErrorMode(prev); if ( m_Handle == INVALID_HANDLE_VALUE ) @@ -1306,151 +1335,19 @@ Kumu::WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Fil //------------------------------------------------------------------------------------------ // - -// Win32 directory scanner -// -#ifdef KM_WIN32 - -// -Kumu::DirScanner::DirScanner(void) : m_Handle(-1) {} - -// -// -Result_t -Kumu::DirScanner::Open(const std::string& filename) +Kumu::DirScanner::DirScanner() + : _iterator(boost::filesystem::directory_iterator()) { - // we need to append a '*' to read the entire directory - ui32_t fn_len = filename.size(); - char* tmp_file = (char*)malloc(fn_len + 8); - - if ( tmp_file == 0 ) - return RESULT_ALLOC; - - strcpy(tmp_file, filename.c_str()); - char* p = &tmp_file[fn_len] - 1; - - if ( *p != '/' && *p != '\\' ) - { - p++; - *p++ = '/'; - } - - *p++ = '*'; - *p = 0; - // whew... - - m_Handle = _findfirsti64(tmp_file, &m_FileInfo); - Result_t result = RESULT_OK; - - if ( m_Handle == -1 ) - result = RESULT_NOT_FOUND; - - return result; } -// -// Result_t -Kumu::DirScanner::Close() -{ - if ( m_Handle == -1 ) - return RESULT_FILEOPEN; - - if ( _findclose((long)m_Handle) == -1 ) - return RESULT_FAIL; - - m_Handle = -1; - return RESULT_OK; -} - - -// This sets filename param to the same per-instance buffer every time, so -// the value will change on the next call -Result_t -Kumu::DirScanner::GetNext(char* filename) -{ - KM_TEST_NULL_L(filename); - - if ( m_Handle == -1 ) - return RESULT_FILEOPEN; - - if ( m_FileInfo.name[0] == '\0' ) - return RESULT_ENDOFFILE; - - strncpy(filename, m_FileInfo.name, MaxFilePath); - Result_t result = RESULT_OK; - - if ( _findnexti64((long)m_Handle, &m_FileInfo) == -1 ) - { - m_FileInfo.name[0] = '\0'; - - if ( errno != ENOENT ) - result = RESULT_FAIL; - } - - return result; -} - - -#else // KM_WIN32 - -// POSIX directory scanner - -// -Kumu::DirScanner::DirScanner(void) : m_Handle(NULL) {} - -// -Result_t -Kumu::DirScanner::Open(const std::string& dirname) -{ - Result_t result = RESULT_OK; - - if ( ( m_Handle = opendir(dirname.c_str()) ) == NULL ) - { - switch ( errno ) - { - case ENOENT: - case ENOTDIR: - result = RESULT_NOTAFILE; - case EACCES: - result = RESULT_NO_PERM; - case ELOOP: - case ENAMETOOLONG: - result = RESULT_PARAM; - case EMFILE: - case ENFILE: - result = RESULT_STATE; - default: - DefaultLogSink().Error("DirScanner::Open(%s): %s\n", dirname.c_str(), strerror(errno)); - result = RESULT_FAIL; - } - } - - return result; -} - - -// -Result_t -Kumu::DirScanner::Close() +Kumu::DirScanner::Open(const std::string& filename) { - if ( m_Handle == NULL ) - return RESULT_FILEOPEN; + if (!boost::filesystem::is_directory(filename)) + return RESULT_NOT_FOUND; - if ( closedir(m_Handle) == -1 ) { - switch ( errno ) - { - case EBADF: - case EINTR: - return RESULT_STATE; - default: - DefaultLogSink().Error("DirScanner::Close(): %s\n", strerror(errno)); - return RESULT_FAIL; - } - } - - m_Handle = NULL; + _iterator = boost::filesystem::directory_iterator(filename); return RESULT_OK; } @@ -1459,133 +1356,19 @@ Kumu::DirScanner::Close() Result_t Kumu::DirScanner::GetNext(char* filename) { - KM_TEST_NULL_L(filename); - - if ( m_Handle == NULL ) - return RESULT_FILEOPEN; - - struct dirent* entry; - - for (;;) - { - if ( ( entry = readdir(m_Handle)) == NULL ) - return RESULT_ENDOFFILE; - - break; - } - - strncpy(filename, entry->d_name, MaxFilePath); - return RESULT_OK; -} - - -// -Kumu::DirScannerEx::DirScannerEx() : m_Handle(0) {} - -// -Result_t -Kumu::DirScannerEx::Open(const std::string& dirname) -{ - Result_t result = RESULT_OK; - - if ( ( m_Handle = opendir(dirname.c_str()) ) == 0 ) - { - switch ( errno ) - { - case ENOENT: - case ENOTDIR: - result = RESULT_NOTAFILE; - case EACCES: - result = RESULT_NO_PERM; - case ELOOP: - case ENAMETOOLONG: - result = RESULT_PARAM; - case EMFILE: - case ENFILE: - result = RESULT_STATE; - default: - DefaultLogSink().Error("DirScanner::Open(%s): %s\n", dirname.c_str(), strerror(errno)); - result = RESULT_FAIL; - } - } - - if ( KM_SUCCESS(result) ) - m_Dirname = dirname; - - KM_RESULT_STATE_TEST_IMPLICIT(); - return result; -} - -// -Result_t -Kumu::DirScannerEx::Close() -{ - if ( m_Handle == NULL ) - return RESULT_FILEOPEN; - - if ( closedir(m_Handle) == -1 ) - { - switch ( errno ) - { - case EBADF: - case EINTR: - KM_RESULT_STATE_HERE(); - return RESULT_STATE; - - default: - DefaultLogSink().Error("DirScanner::Close(): %s\n", strerror(errno)); - return RESULT_FAIL; - } - } - - m_Handle = 0; - return RESULT_OK; -} - -// -Result_t -Kumu::DirScannerEx::GetNext(std::string& next_item_name, DirectoryEntryType_t& next_item_type) -{ - if ( m_Handle == 0 ) - return RESULT_FILEOPEN; - - struct dirent* entry; - - for (;;) - { - if ( ( entry = readdir(m_Handle) ) == 0 ) - return RESULT_ENDOFFILE; - - break; - } - - next_item_name.assign(entry->d_name, strlen(entry->d_name)); - - switch ( entry->d_type ) - { - case DT_DIR: - next_item_type = DET_DIR; - break; - - case DT_REG: - next_item_type = DET_FILE; - break; - - case DT_LNK: - next_item_type = DET_LINK; - break; - - default: - next_item_type = DET_DEV; - } + if (_iterator == boost::filesystem::directory_iterator()) + return RESULT_ENDOFFILE; +#if BOOST_FILESYSTEM_VERSION == 3 + std::string f = boost::filesystem::path(*_iterator).filename().generic_string(); +#else + std::string f = boost::filesystem::path(*_iterator).filename(); +#endif + strncpy(filename, f.c_str(), MaxFilePath); + ++_iterator; return RESULT_OK; } - -#endif // KM_WIN32 - - //------------------------------------------------------------------------------------------ // diff --git a/src/KM_fileio.h b/src/KM_fileio.h index 18dcf0e..03112fe 100755 --- a/src/KM_fileio.h +++ b/src/KM_fileio.h @@ -34,6 +34,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <KM_util.h> #include <string> +#include <boost/filesystem.hpp> #ifdef KM_WIN32 # include <io.h> @@ -51,23 +52,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Kumu { - // class DirScanner { public: -#ifdef KM_WIN32 - __int64 m_Handle; - struct _finddatai64_t m_FileInfo; -#else - DIR* m_Handle; -#endif - - DirScanner(void); - ~DirScanner() { Close(); } - + DirScanner(); Result_t Open(const std::string&); - Result_t Close(); Result_t GetNext(char*); + Result_t Close(); + private: + boost::filesystem::directory_iterator _iterator; }; |
