mirror of
https://github.com/vimpunk/mio.git
synced 2025-12-06 08:46:51 +08:00
Add Windows wide char path support
This commit is contained in:
parent
d77add92da
commit
d4283a45ec
@ -71,8 +71,8 @@ int main()
|
||||
```
|
||||
However, mio does not check whether the provided file descriptor has the same access permissions as the desired mapping, so the mapping may fail. Such errors are reported via the `std::error_code` out parameter that is passed to the mapping function.
|
||||
|
||||
**WINDOWS USERS**: This library doesn't support the use of wide character
|
||||
types for functions where character strings are expected (e.g. path parameters).
|
||||
**WINDOWS USERS**: This library *does* support the use of wide character types
|
||||
for functions where character strings are expected (e.g. path parameters).
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
@ -38,18 +38,53 @@ namespace mio {
|
||||
namespace detail {
|
||||
|
||||
#ifdef _WIN32
|
||||
/** Returns the 4 upper bytes of a 8-byte integer. */
|
||||
namespace win {
|
||||
|
||||
/** Returns the 4 upper bytes of an 8-byte integer. */
|
||||
inline DWORD int64_high(int64_t n) noexcept
|
||||
{
|
||||
return n >> 32;
|
||||
}
|
||||
|
||||
/** Returns the 4 lower bytes of a 8-byte integer. */
|
||||
/** Returns the 4 lower bytes of an 8-byte integer. */
|
||||
inline DWORD int64_low(int64_t n) noexcept
|
||||
{
|
||||
return n & 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<
|
||||
typename String,
|
||||
typename = typename std::enable_if<
|
||||
std::is_same<typename char_type<String>::type, char>::value
|
||||
>::type
|
||||
> file_handle_type open_file_helper(const String& path, const access_mode mode)
|
||||
{
|
||||
return ::CreateFileA(c_str(path),
|
||||
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
}
|
||||
|
||||
template<typename String>
|
||||
typename std::enable_if<
|
||||
std::is_same<typename char_type<String>::type, wchar_t>::value,
|
||||
file_handle_type
|
||||
>::type open_file_helper(const String& path, const access_mode mode)
|
||||
{
|
||||
return ::CreateFileW(c_str(path),
|
||||
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
}
|
||||
|
||||
} // win
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* Returns the last platform specific system error (errno on POSIX and
|
||||
@ -67,8 +102,8 @@ inline std::error_code last_error() noexcept
|
||||
}
|
||||
|
||||
template<typename String>
|
||||
file_handle_type open_file(const String& path,
|
||||
const access_mode mode, std::error_code& error)
|
||||
file_handle_type open_file(const String& path, const access_mode mode,
|
||||
std::error_code& error)
|
||||
{
|
||||
error.clear();
|
||||
if(detail::empty(path))
|
||||
@ -77,13 +112,7 @@ file_handle_type open_file(const String& path,
|
||||
return invalid_handle;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
const auto handle = ::CreateFileA(c_str(path),
|
||||
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
const auto handle = win::open_file_helper(path, mode);
|
||||
#else // POSIX
|
||||
const auto handle = ::open(c_str(path),
|
||||
mode == access_mode::read ? O_RDONLY : O_RDWR);
|
||||
@ -138,8 +167,8 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
|
||||
file_handle,
|
||||
0,
|
||||
mode == access_mode::read ? PAGE_READONLY : PAGE_READWRITE,
|
||||
int64_high(max_file_size),
|
||||
int64_low(max_file_size),
|
||||
win::int64_high(max_file_size),
|
||||
win::int64_low(max_file_size),
|
||||
0);
|
||||
if(file_mapping_handle == invalid_handle)
|
||||
{
|
||||
@ -149,8 +178,8 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
|
||||
char* mapping_start = static_cast<char*>(::MapViewOfFile(
|
||||
file_mapping_handle,
|
||||
mode == access_mode::read ? FILE_MAP_READ : FILE_MAP_WRITE,
|
||||
int64_high(aligned_offset),
|
||||
int64_low(aligned_offset),
|
||||
win::int64_high(aligned_offset),
|
||||
win::int64_low(aligned_offset),
|
||||
length_to_map));
|
||||
if(mapping_start == nullptr)
|
||||
{
|
||||
|
||||
@ -26,17 +26,79 @@
|
||||
namespace mio {
|
||||
namespace detail {
|
||||
|
||||
template <typename String>
|
||||
struct is_c_str
|
||||
template<
|
||||
typename S,
|
||||
typename C = typename std::decay<S>::type,
|
||||
typename = decltype(std::declval<C>().data()),
|
||||
typename = typename std::enable_if<
|
||||
std::is_same<typename C::value_type, char>::value
|
||||
#ifdef _WIN32
|
||||
|| std::is_same<typename C::value_type, wchar_t>::value
|
||||
#endif
|
||||
>::type
|
||||
> struct char_type_helper {
|
||||
using type = typename C::value_type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct char_type {
|
||||
using type = typename char_type_helper<T>::type;
|
||||
};
|
||||
|
||||
// TODO: can we avoid this brute force approach?
|
||||
template<>
|
||||
struct char_type<char*> {
|
||||
using type = char;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_type<const char*> {
|
||||
using type = char;
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct char_type<char[N]> {
|
||||
using type = char;
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct char_type<const char[N]> {
|
||||
using type = char;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
template<>
|
||||
struct char_type<wchar_t*> {
|
||||
using type = wchar_t;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_type<const wchar_t*> {
|
||||
using type = wchar_t;
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct char_type<wchar_t[N]> {
|
||||
using type = wchar_t;
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct char_type<const wchar_t[N]> {
|
||||
using type = wchar_t;
|
||||
};
|
||||
#endif // _WIN32
|
||||
|
||||
template<typename CharT, typename S>
|
||||
struct is_c_str_helper
|
||||
{
|
||||
static constexpr bool value = std::is_same<
|
||||
char*,
|
||||
CharT*,
|
||||
// TODO: I'm so sorry for this... Can this be made cleaner?
|
||||
typename std::add_pointer<
|
||||
typename std::remove_cv<
|
||||
typename std::remove_pointer<
|
||||
typename std::decay<
|
||||
String
|
||||
S
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
@ -44,11 +106,35 @@ struct is_c_str
|
||||
>::value;
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
struct is_c_str
|
||||
{
|
||||
static constexpr bool value = is_c_str_helper<char, S>::value;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
template<typename S>
|
||||
struct is_c_wstr
|
||||
{
|
||||
static constexpr bool value = is_c_str_helper<wchar_t, S>::value;
|
||||
};
|
||||
#endif // _WIN32
|
||||
|
||||
template<typename S>
|
||||
struct is_c_str_or_c_wstr
|
||||
{
|
||||
static constexpr bool value = is_c_str<S>::value
|
||||
#ifdef _WIN32
|
||||
|| is_c_wstr<S>::value
|
||||
#endif
|
||||
;
|
||||
};
|
||||
|
||||
template<
|
||||
typename String,
|
||||
typename = decltype(std::declval<String>().data()),
|
||||
typename = typename std::enable_if<!is_c_str<String>::value>::type
|
||||
> const char* c_str(const String& path)
|
||||
typename = typename std::enable_if<!is_c_str_or_c_wstr<String>::value>::type
|
||||
> const typename char_type<String>::type* c_str(const String& path)
|
||||
{
|
||||
return path.data();
|
||||
}
|
||||
@ -56,7 +142,7 @@ template<
|
||||
template<
|
||||
typename String,
|
||||
typename = decltype(std::declval<String>().empty()),
|
||||
typename = typename std::enable_if<!is_c_str<String>::value>::type
|
||||
typename = typename std::enable_if<!is_c_str_or_c_wstr<String>::value>::type
|
||||
> bool empty(const String& path)
|
||||
{
|
||||
return path.empty();
|
||||
@ -64,15 +150,15 @@ template<
|
||||
|
||||
template<
|
||||
typename String,
|
||||
typename = typename std::enable_if<is_c_str<String>::value>::type
|
||||
> const char* c_str(String path)
|
||||
typename = typename std::enable_if<is_c_str_or_c_wstr<String>::value>::type
|
||||
> const typename char_type<String>::type* c_str(String path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
template<
|
||||
typename String,
|
||||
typename = typename std::enable_if<is_c_str<String>::value>::type
|
||||
typename = typename std::enable_if<is_c_str_or_c_wstr<String>::value>::type
|
||||
> bool empty(String path)
|
||||
{
|
||||
return !path || (*path == 0);
|
||||
|
||||
@ -98,7 +98,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure custom types compile.
|
||||
// Make sure these compile.
|
||||
mio::ummap_source _1;
|
||||
mio::shared_ummap_source _2;
|
||||
// Make sure shared_mmap mapping compiles as all testing was done on
|
||||
@ -106,6 +106,16 @@ int main()
|
||||
mio::shared_mmap_source _3(path, 0, mio::map_entire_file);
|
||||
auto _4 = mio::make_mmap_source(path, error);
|
||||
auto _5 = mio::make_mmap<mio::shared_mmap_source>(path, 0, mio::map_entire_file, error);
|
||||
#ifdef _WIN32
|
||||
const wchar_t* wpath1 = L"dasfsf";
|
||||
auto _6 = mio::make_mmap_source(wpath1, error);
|
||||
mio::mmap_source _7;
|
||||
_7.map(wpath1, error);
|
||||
const std::wstring wpath2 = wpath1;
|
||||
auto _8 = mio::make_mmap_source(wpath2, error);
|
||||
mio::mmap_source _9;
|
||||
_9.map(wpath1, error);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::printf("all tests passed!\n");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user