I'm reading gzip compressed files using zlib. Then you open a file using
gzFile gzopen(const char *filepath, const char *mode);
How do you handle Unicode file paths that are stored as const wchar_t* on Windows?
On UNIX-like platforms you can just convert the file path to UTF-8 and call gzopen(), but that will not work on Windows.
The next version of zlib will include this function where _WIN32 is #defined:
gzFile gzopen_w(const wchar_t *path, char *mode);
It works exactly like gzopen(), except it uses _wopen() instead of open().
I purposely did not duplicate the second argument of _wfopen(), and as a result I did not call it _wgzopen() to avoid possible confusion with that function's arguments.  Hence the name gzopen_w().  That also avoids the use of the C-reserved name space.
Here is my own version of unicode helper function, tested slightly better than version above.
static void GetFlags(const char* mode, int& flags, int& pmode)
{
    const char* _mode = mode;
    flags = 0;      // == O_RDONLY
    pmode = 0;      // pmode needs to be obtained, otherwise file gets read-only attribute, see 
                    // http://stackoverflow.com/questions/1412625/why-is-the-read-only-attribute-set-sometimes-for-files-created-by-my-service
    for( ; *_mode ; _mode++ )
    {
        switch( tolower(*_mode) )
        {
            case 'w':
                flags |= O_CREAT | O_TRUNC;
                pmode |= _S_IWRITE;
                break;
            case 'a':
                flags |= O_CREAT | O_APPEND;
                pmode |= _S_IREAD | _S_IWRITE;
                break;
            case 'r':
                pmode |= _S_IREAD;
                break;
            case 'b':
                flags |= O_BINARY;
                break;
            case '+':
                flags |= O_RDWR;
                pmode |= _S_IREAD | _S_IWRITE;
                break;
        }
    }
    if( (flags & O_CREAT) != 0 && (flags & O_RDWR) == 0 )
        flags |= O_WRONLY;
} //GetFlags
gzFile wgzopen(const wchar_t* fileName, const char* mode)
{
    gzFile gzstream = NULL;
    int f = 0;
    int flags = 0;
    int pmode = 0;
    GetFlags(mode, flags, pmode);
    f = _wopen(fileName, flags, pmode );
    if( f == -1 )
        return NULL;
    // gzdopen will also close file handle.
    gzstream = gzdopen(f, mode);
    if(!gzstream)
        _close(f);
    return gzstream;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With