UTF-8 string filename optional for windows
This commit is contained in:
parent
068d5ee1a3
commit
90a76a7ef9
@ -22,10 +22,14 @@ if(NOT CMAKE_CXX_STANDARD)
|
|||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
endif(NOT CMAKE_CXX_STANDARD)
|
endif(NOT CMAKE_CXX_STANDARD)
|
||||||
|
|
||||||
|
option(USE_LEVELDB_WINDOWS_UTF8_FILENAMES "Build LevelDB with UTF-8 filename in Windows." OFF)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_WINDOWS)
|
set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_WINDOWS)
|
||||||
# TODO(cmumford): Make UNICODE configurable for Windows.
|
# TODO(cmumford): Make UNICODE configurable for Windows.
|
||||||
add_definitions(-D_UNICODE -DUNICODE)
|
add_definitions(-D_UNICODE -DUNICODE)
|
||||||
|
if(USE_LEVELDB_WINDOWS_UTF8_FILENAMES)
|
||||||
|
add_definitions(-DLEVELDB_WINDOWS_UTF8_FILENAMES)
|
||||||
|
endif()
|
||||||
else (WIN32)
|
else (WIN32)
|
||||||
set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_POSIX)
|
set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_POSIX)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
37
port/port.h
37
port/port.h
@ -12,6 +12,43 @@
|
|||||||
// of what the new port_<platform>.h file must provide.
|
// of what the new port_<platform>.h file must provide.
|
||||||
#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS)
|
#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS)
|
||||||
#include "port/port_stdcxx.h"
|
#include "port/port_stdcxx.h"
|
||||||
|
#if defined(LEVELDB_PLATFORM_WINDOWS)
|
||||||
|
#ifdef LEVELDB_WINDOWS_UTF8_FILENAMES
|
||||||
|
#define LD_FN(a) leveldb::utf8_to_utf16(a)
|
||||||
|
#define FN_TO_LD(a) leveldb::utf16_to_utf8(a)
|
||||||
|
#define LD_DeleteFile DeleteFileW
|
||||||
|
#define LD_CreateFile CreateFileW
|
||||||
|
#define LD_CreateFileMapping CreateFileMappingW
|
||||||
|
#define LD_GetFileAttributesEx GetFileAttributesExW
|
||||||
|
#define LD_GetFileAttributes GetFileAttributesW
|
||||||
|
#define LD_FindFirstFile FindFirstFileW
|
||||||
|
#define LD_FindNextFile FindNextFileW
|
||||||
|
#define LD_WIN32_FIND_DATA WIN32_FIND_DATAW
|
||||||
|
#define LD_CreateDirectory CreateDirectoryW
|
||||||
|
#define LD_RemoveDirectory RemoveDirectoryW
|
||||||
|
#define LD_MoveFile MoveFileW
|
||||||
|
#define LD_ReplaceFile ReplaceFileW
|
||||||
|
#define LD_SPLITPATH_S _wsplitpath_s
|
||||||
|
#define LD_CHAR WCHAR
|
||||||
|
#else
|
||||||
|
#define LD_FN(a) a
|
||||||
|
#define FN_TO_LD(a) a
|
||||||
|
#define LD_DeleteFile DeleteFileA
|
||||||
|
#define LD_CreateFile CreateFileA
|
||||||
|
#define LD_CreateFileMapping CreateFileMappingA
|
||||||
|
#define LD_GetFileAttributesEx GetFileAttributesExA
|
||||||
|
#define LD_GetFileAttributes GetFileAttributesA
|
||||||
|
#define LD_FindFirstFile FindFirstFileA
|
||||||
|
#define LD_CreateDirectory CreateDirectoryA
|
||||||
|
#define LD_FindNextFile FindNextFileA
|
||||||
|
#define LD_WIN32_FIND_DATA WIN32_FIND_DATAA
|
||||||
|
#define LD_RemoveDirectory RemoveDirectoryA
|
||||||
|
#define LD_MoveFile MoveFileA
|
||||||
|
#define LD_ReplaceFile ReplaceFileA
|
||||||
|
#define LD_SPLITPATH_S _splitpath_s
|
||||||
|
#define LD_CHAR CHAR
|
||||||
|
#endif /* LEVELDB_WINDOWS_UTF8_FILENAMES */
|
||||||
|
#endif /* LEVELDB_PLATFORM_WINDOWS */
|
||||||
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
|
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
|
||||||
#include "port/port_chromium.h"
|
#include "port/port_chromium.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,10 +33,29 @@
|
|||||||
#include "util/mutexlock.h"
|
#include "util/mutexlock.h"
|
||||||
#include "util/windows_logger.h"
|
#include "util/windows_logger.h"
|
||||||
|
|
||||||
|
#ifdef LEVELDB_WINDOWS_UTF8_FILENAMES
|
||||||
|
// utf8 <-> utf16
|
||||||
|
#include <codecvt>
|
||||||
|
#include <locale>
|
||||||
|
#include <string>
|
||||||
|
#endif /* LEVELDB_WINDOWS_UTF8_FILENAMES */
|
||||||
|
|
||||||
namespace leveldb {
|
namespace leveldb {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
#ifdef LEVELDB_WINDOWS_UTF8_FILENAMES
|
||||||
|
std::string utf16_to_utf8(const std::wstring& utf16) {
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
|
||||||
|
return convert.to_bytes(utf16);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring utf8_to_utf16(const std::string& utf8) {
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||||
|
return converter.from_bytes(utf8);
|
||||||
|
}
|
||||||
|
#endif /* LEVELDB_WINDOWS_UTF8_FILENAMES */
|
||||||
|
|
||||||
constexpr const size_t kWritableFileBufferSize = 65536;
|
constexpr const size_t kWritableFileBufferSize = 65536;
|
||||||
|
|
||||||
// Up to 1000 mmaps for 64-bit binaries; none for 32-bit.
|
// Up to 1000 mmaps for 64-bit binaries; none for 32-bit.
|
||||||
@ -395,8 +414,8 @@ class WindowsEnv : public Env {
|
|||||||
*result = nullptr;
|
*result = nullptr;
|
||||||
DWORD desired_access = GENERIC_READ;
|
DWORD desired_access = GENERIC_READ;
|
||||||
DWORD share_mode = FILE_SHARE_READ;
|
DWORD share_mode = FILE_SHARE_READ;
|
||||||
ScopedHandle handle = ::CreateFileA(
|
ScopedHandle handle = LD_CreateFile(
|
||||||
filename.c_str(), desired_access, share_mode,
|
LD_FN(filename).c_str(), desired_access, share_mode,
|
||||||
/*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
/*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
||||||
/*hTemplateFile=*/nullptr);
|
/*hTemplateFile=*/nullptr);
|
||||||
if (!handle.is_valid()) {
|
if (!handle.is_valid()) {
|
||||||
@ -413,7 +432,7 @@ class WindowsEnv : public Env {
|
|||||||
DWORD desired_access = GENERIC_READ;
|
DWORD desired_access = GENERIC_READ;
|
||||||
DWORD share_mode = FILE_SHARE_READ;
|
DWORD share_mode = FILE_SHARE_READ;
|
||||||
ScopedHandle handle =
|
ScopedHandle handle =
|
||||||
::CreateFileA(filename.c_str(), desired_access, share_mode,
|
LD_CreateFile(LD_FN(filename).c_str(), desired_access, share_mode,
|
||||||
/*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
|
/*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_READONLY,
|
FILE_ATTRIBUTE_READONLY,
|
||||||
/*hTemplateFile=*/nullptr);
|
/*hTemplateFile=*/nullptr);
|
||||||
@ -433,7 +452,7 @@ class WindowsEnv : public Env {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScopedHandle mapping =
|
ScopedHandle mapping =
|
||||||
::CreateFileMappingA(handle.get(),
|
LD_CreateFileMapping(handle.get(),
|
||||||
/*security attributes=*/nullptr, PAGE_READONLY,
|
/*security attributes=*/nullptr, PAGE_READONLY,
|
||||||
/*dwMaximumSizeHigh=*/0,
|
/*dwMaximumSizeHigh=*/0,
|
||||||
/*dwMaximumSizeLow=*/0,
|
/*dwMaximumSizeLow=*/0,
|
||||||
@ -458,8 +477,8 @@ class WindowsEnv : public Env {
|
|||||||
WritableFile** result) override {
|
WritableFile** result) override {
|
||||||
DWORD desired_access = GENERIC_WRITE;
|
DWORD desired_access = GENERIC_WRITE;
|
||||||
DWORD share_mode = 0; // Exclusive access.
|
DWORD share_mode = 0; // Exclusive access.
|
||||||
ScopedHandle handle = ::CreateFileA(
|
ScopedHandle handle = LD_CreateFile(
|
||||||
filename.c_str(), desired_access, share_mode,
|
LD_FN(filename).c_str(), desired_access, share_mode,
|
||||||
/*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
/*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||||
/*hTemplateFile=*/nullptr);
|
/*hTemplateFile=*/nullptr);
|
||||||
if (!handle.is_valid()) {
|
if (!handle.is_valid()) {
|
||||||
@ -475,8 +494,8 @@ class WindowsEnv : public Env {
|
|||||||
WritableFile** result) override {
|
WritableFile** result) override {
|
||||||
DWORD desired_access = FILE_APPEND_DATA;
|
DWORD desired_access = FILE_APPEND_DATA;
|
||||||
DWORD share_mode = 0; // Exclusive access.
|
DWORD share_mode = 0; // Exclusive access.
|
||||||
ScopedHandle handle = ::CreateFileA(
|
ScopedHandle handle = LD_CreateFile(
|
||||||
filename.c_str(), desired_access, share_mode,
|
LD_FN(filename).c_str(), desired_access, share_mode,
|
||||||
/*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
/*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||||
/*hTemplateFile=*/nullptr);
|
/*hTemplateFile=*/nullptr);
|
||||||
if (!handle.is_valid()) {
|
if (!handle.is_valid()) {
|
||||||
@ -489,14 +508,14 @@ class WindowsEnv : public Env {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FileExists(const std::string& filename) override {
|
bool FileExists(const std::string& filename) override {
|
||||||
return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
|
return LD_GetFileAttributes(LD_FN(filename).c_str()) != INVALID_FILE_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status GetChildren(const std::string& directory_path,
|
Status GetChildren(const std::string& directory_path,
|
||||||
std::vector<std::string>* result) override {
|
std::vector<std::string>* result) override {
|
||||||
const std::string find_pattern = directory_path + "\\*";
|
const std::string find_pattern = directory_path + "\\*";
|
||||||
WIN32_FIND_DATAA find_data;
|
LD_WIN32_FIND_DATA find_data;
|
||||||
HANDLE dir_handle = ::FindFirstFileA(find_pattern.c_str(), &find_data);
|
HANDLE dir_handle = LD_FindFirstFile(LD_FN(find_pattern).c_str(), &find_data);
|
||||||
if (dir_handle == INVALID_HANDLE_VALUE) {
|
if (dir_handle == INVALID_HANDLE_VALUE) {
|
||||||
DWORD last_error = ::GetLastError();
|
DWORD last_error = ::GetLastError();
|
||||||
if (last_error == ERROR_FILE_NOT_FOUND) {
|
if (last_error == ERROR_FILE_NOT_FOUND) {
|
||||||
@ -505,14 +524,14 @@ class WindowsEnv : public Env {
|
|||||||
return WindowsError(directory_path, last_error);
|
return WindowsError(directory_path, last_error);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
char base_name[_MAX_FNAME];
|
LD_CHAR base_name[_MAX_FNAME];
|
||||||
char ext[_MAX_EXT];
|
LD_CHAR ext[_MAX_EXT];
|
||||||
|
|
||||||
if (!_splitpath_s(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
|
if (!LD_SPLITPATH_S(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
|
||||||
ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
|
ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
|
||||||
result->emplace_back(std::string(base_name) + ext);
|
result->emplace_back(std::string(FN_TO_LD(base_name)) + FN_TO_LD(ext));
|
||||||
}
|
}
|
||||||
} while (::FindNextFileA(dir_handle, &find_data));
|
} while (LD_FindNextFile(dir_handle, &find_data));
|
||||||
DWORD last_error = ::GetLastError();
|
DWORD last_error = ::GetLastError();
|
||||||
::FindClose(dir_handle);
|
::FindClose(dir_handle);
|
||||||
if (last_error != ERROR_NO_MORE_FILES) {
|
if (last_error != ERROR_NO_MORE_FILES) {
|
||||||
@ -522,21 +541,21 @@ class WindowsEnv : public Env {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status RemoveFile(const std::string& filename) override {
|
Status RemoveFile(const std::string& filename) override {
|
||||||
if (!::DeleteFileA(filename.c_str())) {
|
if (!LD_DeleteFile(LD_FN(filename).c_str())) {
|
||||||
return WindowsError(filename, ::GetLastError());
|
return WindowsError(filename, ::GetLastError());
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status CreateDir(const std::string& dirname) override {
|
Status CreateDir(const std::string& dirname) override {
|
||||||
if (!::CreateDirectoryA(dirname.c_str(), nullptr)) {
|
if (!LD_CreateDirectory(LD_FN(dirname).c_str(), nullptr)) {
|
||||||
return WindowsError(dirname, ::GetLastError());
|
return WindowsError(dirname, ::GetLastError());
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status RemoveDir(const std::string& dirname) override {
|
Status RemoveDir(const std::string& dirname) override {
|
||||||
if (!::RemoveDirectoryA(dirname.c_str())) {
|
if (!LD_RemoveDirectory(LD_FN(dirname).c_str())) {
|
||||||
return WindowsError(dirname, ::GetLastError());
|
return WindowsError(dirname, ::GetLastError());
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
@ -544,7 +563,7 @@ class WindowsEnv : public Env {
|
|||||||
|
|
||||||
Status GetFileSize(const std::string& filename, uint64_t* size) override {
|
Status GetFileSize(const std::string& filename, uint64_t* size) override {
|
||||||
WIN32_FILE_ATTRIBUTE_DATA file_attributes;
|
WIN32_FILE_ATTRIBUTE_DATA file_attributes;
|
||||||
if (!::GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
|
if (!LD_GetFileAttributesEx(LD_FN(filename).c_str(), GetFileExInfoStandard,
|
||||||
&file_attributes)) {
|
&file_attributes)) {
|
||||||
return WindowsError(filename, ::GetLastError());
|
return WindowsError(filename, ::GetLastError());
|
||||||
}
|
}
|
||||||
@ -558,7 +577,7 @@ class WindowsEnv : public Env {
|
|||||||
Status RenameFile(const std::string& from, const std::string& to) override {
|
Status RenameFile(const std::string& from, const std::string& to) override {
|
||||||
// Try a simple move first. It will only succeed when |to| doesn't already
|
// Try a simple move first. It will only succeed when |to| doesn't already
|
||||||
// exist.
|
// exist.
|
||||||
if (::MoveFileA(from.c_str(), to.c_str())) {
|
if (LD_MoveFile(LD_FN(from).c_str(), LD_FN(to).c_str())) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
DWORD move_error = ::GetLastError();
|
DWORD move_error = ::GetLastError();
|
||||||
@ -567,7 +586,7 @@ class WindowsEnv : public Env {
|
|||||||
// succeed when |to| does exist. When writing to a network share, we may not
|
// succeed when |to| does exist. When writing to a network share, we may not
|
||||||
// be able to change the ACLs. Ignore ACL errors then
|
// be able to change the ACLs. Ignore ACL errors then
|
||||||
// (REPLACEFILE_IGNORE_MERGE_ERRORS).
|
// (REPLACEFILE_IGNORE_MERGE_ERRORS).
|
||||||
if (::ReplaceFileA(to.c_str(), from.c_str(), /*lpBackupFileName=*/nullptr,
|
if (LD_ReplaceFile(LD_FN(to).c_str(), LD_FN(from).c_str(), /*lpBackupFileName=*/nullptr,
|
||||||
REPLACEFILE_IGNORE_MERGE_ERRORS,
|
REPLACEFILE_IGNORE_MERGE_ERRORS,
|
||||||
/*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
|
/*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
@ -587,8 +606,8 @@ class WindowsEnv : public Env {
|
|||||||
Status LockFile(const std::string& filename, FileLock** lock) override {
|
Status LockFile(const std::string& filename, FileLock** lock) override {
|
||||||
*lock = nullptr;
|
*lock = nullptr;
|
||||||
Status result;
|
Status result;
|
||||||
ScopedHandle handle = ::CreateFileA(
|
ScopedHandle handle = LD_CreateFile(
|
||||||
filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
|
LD_FN(filename).c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
|
||||||
/*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
/*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (!handle.is_valid()) {
|
if (!handle.is_valid()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user