vimpunk / mio

Cross-platform C++11 header-only library for memory mapped file IO
MIT License
1.71k stars 157 forks source link

WIN: Unable to mmap a file having special characters in file name #56

Open shivendra14 opened 5 years ago

shivendra14 commented 5 years ago

I was trying to mmap a file which has special characters in file name. アイコン mmap = mio::make_mmap_source(file.GetFullPath().as_UTF8(), error);

But the mapping fails.. does mio accepts UTF8? or should I be doing something else to read such file correctly.

    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);
}

This returns an invalid handle.

shivendra14 commented 5 years ago

https://stackoverflow.com/questions/8831143/windows-api-ansi-functions-and-utf-8

Can somebody help to fix this CreateFileA and add support of UTF8

shivendra14 commented 5 years ago

This is the code fix I have done locally to make this work:

std::wstring s2ws(const std::string& s)
{
    int slength = (int)s.length() + 1;
    int len = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), slength, 0, 0);
    auto buf = std::make_unique<wchar_t[]>(len);
    MultiByteToWideChar(CP_UTF8, 0, s.c_str(), slength, buf.get(), len);
    return buf.release();
}

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 ::CreateFileW(s2ws(path).c_str(),
            mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            0,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            0);
}
vimpunk commented 4 years ago

Thanks for using mio! And apologies for the late reply. mio doesn't support utf8 out of the box, sorry about the inconvenience. I have very little time for open source these days, so I would be glad if someone took up the task of adding utf8 support.

pps83 commented 4 years ago

@jdarpinian,

std::wstring s2ws(const std::string& s)

you could simply have two overloads for toWideStr that accept std::string and std::wstring and always do:

::CreateFileW(toWideStr(path).c_str(), ...

without using all that template mumbo-jumbo.

return buf.release();

FYI, this obviously leaks memory. Change it to return buf.get();