Add NativeFileStream to support unicode filenames under Windows
This commit is contained in:
parent
59a8dfe833
commit
9d91cfca07
|
@ -25,6 +25,7 @@ set(HEADER_FILES
|
||||||
io/inifile.h
|
io/inifile.h
|
||||||
io/path.h
|
io/path.h
|
||||||
io/catchiofailure.h
|
io/catchiofailure.h
|
||||||
|
io/nativefilestream.h
|
||||||
math/math.h
|
math/math.h
|
||||||
misc/memory.h
|
misc/memory.h
|
||||||
misc/random.h
|
misc/random.h
|
||||||
|
@ -49,6 +50,7 @@ set(SRC_FILES
|
||||||
io/inifile.cpp
|
io/inifile.cpp
|
||||||
io/path.cpp
|
io/path.cpp
|
||||||
io/catchiofailure.cpp
|
io/catchiofailure.cpp
|
||||||
|
io/nativefilestream.cpp
|
||||||
math/math.cpp
|
math/math.cpp
|
||||||
misc/random.cpp
|
misc/random.cpp
|
||||||
tests/testutils.cpp
|
tests/testutils.cpp
|
||||||
|
@ -119,6 +121,12 @@ set(META_VERSION_PATCH 0)
|
||||||
include(3rdParty)
|
include(3rdParty)
|
||||||
use_iconv(AUTO_LINKAGE REQUIRED)
|
use_iconv(AUTO_LINKAGE REQUIRED)
|
||||||
|
|
||||||
|
# configure use of native file buffer
|
||||||
|
option(USE_NATIVE_FILE_BUFFER "enables use of native file buffer under Windows, affects bc (required for unicode filenames under Windows)" OFF)
|
||||||
|
if(USE_NATIVE_FILE_BUFFER)
|
||||||
|
list(APPEND META_PUBLIC_COMPILE_DEFINITIONS ${META_PROJECT_VARNAME}_USE_NATIVE_FILE_BUFFER)
|
||||||
|
endif()
|
||||||
|
|
||||||
# include modules to apply configuration
|
# include modules to apply configuration
|
||||||
include(BasicConfig)
|
include(BasicConfig)
|
||||||
include(WindowsResources)
|
include(WindowsResources)
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "./nativefilestream.h"
|
||||||
|
|
||||||
|
#ifdef PLATFORM_MINGW
|
||||||
|
# include <c++utilities/io/catchiofailure.h>
|
||||||
|
# include <windows.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace IoUtilities {
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_MINGW) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
|
||||||
|
|
||||||
|
// just use std::fstream
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
NativeFileStream::NativeFileStream() :
|
||||||
|
m_filebuf(new __gnu_cxx::stdio_filebuf<char>)
|
||||||
|
{
|
||||||
|
rdbuf(m_filebuf.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeFileStream::~NativeFileStream()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void NativeFileStream::open(const string &path, ios_base::openmode flags)
|
||||||
|
{
|
||||||
|
// convert path to UTF-16
|
||||||
|
int requiredSize = MultiByteToWideChar(CP_UTF8, 0, path.data(), -1, nullptr, 0);
|
||||||
|
if(requiredSize <= 0) {
|
||||||
|
::IoUtilities::throwIoFailure("Unable to calculate buffer size for conversion of path to UTF-16");
|
||||||
|
}
|
||||||
|
auto widePath = make_unique<wchar_t[]>(static_cast<size_t>(requiredSize));
|
||||||
|
requiredSize = MultiByteToWideChar(CP_UTF8, 0, path.data(), -1, widePath.get(), requiredSize);
|
||||||
|
if(requiredSize <= 0) {
|
||||||
|
::IoUtilities::throwIoFailure("Unable to convert path to UTF-16");
|
||||||
|
}
|
||||||
|
// translate flags
|
||||||
|
int nativeFlags = (flags & ios_base::binary ? _O_BINARY : 0);
|
||||||
|
int permissions = 0;
|
||||||
|
if((flags & ios_base::out) && (flags & ios_base::in)) {
|
||||||
|
nativeFlags |= _O_RDWR;
|
||||||
|
} else if(flags & ios_base::out) {
|
||||||
|
nativeFlags |= _O_WRONLY | _O_CREAT;
|
||||||
|
permissions = _S_IREAD | _S_IWRITE;
|
||||||
|
} else if(flags & ios_base::in) {
|
||||||
|
nativeFlags |= _O_RDONLY;
|
||||||
|
}
|
||||||
|
if(flags & ios_base::trunc) {
|
||||||
|
nativeFlags |= _O_TRUNC;
|
||||||
|
}
|
||||||
|
// initialize stdio_filebuf
|
||||||
|
int fd = _wopen(widePath.get(), nativeFlags, permissions);
|
||||||
|
if(fd == -1) {
|
||||||
|
::IoUtilities::throwIoFailure("_wopen failed");
|
||||||
|
}
|
||||||
|
m_filebuf = make_unique<__gnu_cxx::stdio_filebuf<char> >(fd, flags);
|
||||||
|
rdbuf(m_filebuf.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeFileStream::close()
|
||||||
|
{
|
||||||
|
if(m_filebuf) {
|
||||||
|
m_filebuf->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef IOUTILITIES_NATIVE_FILE_STREAM
|
||||||
|
#define IOUTILITIES_NATIVE_FILE_STREAM
|
||||||
|
|
||||||
|
#include "../global.h"
|
||||||
|
|
||||||
|
#ifndef PLATFORM_MINGW
|
||||||
|
# include <fstream>
|
||||||
|
#else
|
||||||
|
# include "../misc/memory.h"
|
||||||
|
# include <string>
|
||||||
|
# include <iostream>
|
||||||
|
# include <ext/stdio_filebuf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace IoUtilities {
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_MINGW) || !defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
|
||||||
|
|
||||||
|
typedef std::fstream NativeFileStream;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
class CPP_UTILITIES_EXPORT NativeFileStream : public std::iostream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NativeFileStream();
|
||||||
|
~NativeFileStream();
|
||||||
|
|
||||||
|
bool is_open() const;
|
||||||
|
void open(const std::string &path, std::ios_base::openmode flags);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<__gnu_cxx::stdio_filebuf<char> > m_filebuf;
|
||||||
|
std::__c_file m_cfile;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool NativeFileStream::is_open() const
|
||||||
|
{
|
||||||
|
return m_filebuf && m_filebuf->is_open();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IOUTILITIES_NATIVE_FILE_STREAM
|
||||||
|
|
Loading…
Reference in New Issue