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/path.h
|
||||
io/catchiofailure.h
|
||||
io/nativefilestream.h
|
||||
math/math.h
|
||||
misc/memory.h
|
||||
misc/random.h
|
||||
|
@ -49,6 +50,7 @@ set(SRC_FILES
|
|||
io/inifile.cpp
|
||||
io/path.cpp
|
||||
io/catchiofailure.cpp
|
||||
io/nativefilestream.cpp
|
||||
math/math.cpp
|
||||
misc/random.cpp
|
||||
tests/testutils.cpp
|
||||
|
@ -119,6 +121,12 @@ set(META_VERSION_PATCH 0)
|
|||
include(3rdParty)
|
||||
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(BasicConfig)
|
||||
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