3 #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER 6 #ifdef PLATFORM_WINDOWS 7 #include "../conversion/stringconversion.h" 11 #if defined(CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF) 12 #include <ext/stdio_filebuf.h> 13 #elif defined(CPP_UTILITIES_USE_BOOST_IOSTREAMS) 14 #include <boost/iostreams/device/file_descriptor.hpp> 15 #include <boost/iostreams/stream.hpp> 17 #error "Configuration for NativeFileStream backend insufficient." 21 #if defined(PLATFORM_UNIX) 25 #include <sys/types.h> 26 #elif defined(PLATFORM_WINDOWS) 39 #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER 41 #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF 42 using StreamBuffer = __gnu_cxx::stdio_filebuf<char>;
43 #else // CPP_UTILITIES_USE_BOOST_IOSTREAMS 44 using StreamBuffer = boost::iostreams::stream_buffer<boost::iostreams::file_descriptor>;
47 struct NativeFileParams {
49 #ifdef PLATFORM_WINDOWS 50 NativeFileParams(ios_base::openmode cppOpenMode)
51 : openMode(cppOpenMode & ios_base::binary ? _O_BINARY : 0)
52 , flags(cppOpenMode & ios_base::binary ? 0 : _O_TEXT)
58 if ((cppOpenMode & ios_base::out) && (cppOpenMode & ios_base::in)) {
60 access = GENERIC_READ | GENERIC_WRITE;
61 shareMode = FILE_SHARE_READ;
62 creation = OPEN_EXISTING;
63 }
else if (cppOpenMode & ios_base::out) {
64 openMode |= _O_WRONLY | _O_CREAT;
65 permissions = _S_IREAD | _S_IWRITE;
66 access = GENERIC_WRITE;
67 creation = OPEN_ALWAYS;
68 }
else if (cppOpenMode & ios_base::in) {
69 openMode |= _O_RDONLY;
71 access = GENERIC_READ;
72 shareMode = FILE_SHARE_READ;
73 creation = OPEN_EXISTING;
75 if (cppOpenMode & ios_base::app) {
76 openMode |= _O_APPEND;
79 if (cppOpenMode & ios_base::trunc) {
81 creation = (cppOpenMode & ios_base::in) ? TRUNCATE_EXISTING : CREATE_ALWAYS;
92 NativeFileParams(ios_base::openmode cppOpenMode)
95 if ((cppOpenMode & ios_base::in) && (cppOpenMode & ios_base::out)) {
96 if (cppOpenMode & ios_base::app) {
98 openFlags = O_RDWR | O_APPEND;
99 }
else if (cppOpenMode & ios_base::trunc) {
101 openFlags = O_RDWR | O_TRUNC;
106 }
else if (cppOpenMode & ios_base::in) {
108 openFlags = O_RDONLY;
109 }
else if (cppOpenMode & ios_base::out) {
110 if (cppOpenMode & ios_base::app) {
112 openFlags = O_WRONLY | O_APPEND;
113 }
else if (cppOpenMode & ios_base::trunc) {
115 openFlags = O_WRONLY | O_TRUNC | O_CREAT;
118 openFlags = O_WRONLY | O_CREAT;
121 if (cppOpenMode & ios_base::binary) {
126 std::string openMode;
135 : iostream(new StreamBuffer)
144 : iostream(other.m_filebuf.release())
146 , m_fileHandle(other.m_fileHandle)
153 NativeFileStream::~NativeFileStream()
160 bool NativeFileStream::is_open()
const 162 return m_filebuf &&
static_cast<const StreamBuffer *
>(m_filebuf.get())->is_open();
178 void NativeFileStream::open(
const string &path, ios_base::openmode openMode)
180 setFileBuffer(makeFileBuffer(path, openMode));
191 void NativeFileStream::openFromFileDescriptor(
int fileDescriptor, ios_base::openmode openMode)
193 setFileBuffer(makeFileBuffer(fileDescriptor, openMode));
199 void NativeFileStream::close()
202 static_cast<StreamBuffer *
>(m_filebuf.get())->close();
209 void NativeFileStream::setFileBuffer(std::unique_ptr<std::basic_streambuf<char>> buffer)
212 m_filebuf = std::move(buffer);
218 std::unique_ptr<std::basic_streambuf<char>> NativeFileStream::makeFileBuffer(
const string &path, ios_base::openmode openMode)
220 #ifdef PLATFORM_WINDOWS 222 const auto widePath(makeWidePath(path));
226 const NativeFileParams nativeParams(openMode);
228 #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF 230 #ifdef PLATFORM_WINDOWS 231 const int fileHandle = _wopen(widePath.get(), nativeParams.openMode, nativeParams.permissions);
232 if (fileHandle == -1) {
236 const auto fileHandle = fopen(path.data(), nativeParams.openMode.data());
241 return make_unique<StreamBuffer>(fileHandle, openMode);
243 #else // CPP_UTILITIES_USE_BOOST_IOSTREAMS 245 #ifdef PLATFORM_WINDOWS 246 const auto fileDescriptor
247 = CreateFileW(widePath.get(), nativeParams.access, nativeParams.shareMode,
nullptr, nativeParams.creation, FILE_ATTRIBUTE_NORMAL);
248 if (fileDescriptor == INVALID_HANDLE_VALUE) {
252 const auto fileDescriptor = ::open(path.data(), nativeParams.openFlags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
253 if (fileDescriptor == -1) {
257 return make_unique<StreamBuffer>(fileDescriptor, boost::iostreams::close_handle);
264 std::unique_ptr<std::basic_streambuf<char>> NativeFileStream::makeFileBuffer(
int fileDescriptor, ios_base::openmode openMode)
267 const NativeFileParams nativeParams(openMode);
269 #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF 271 #ifdef PLATFORM_WINDOWS 272 const auto fileHandle = _get_osfhandle(fileDescriptor);
273 if (fileHandle == -1) {
276 const auto osFileHandle = _open_osfhandle(fileHandle, nativeParams.flags);
277 if (osFileHandle == -1) {
281 const auto fileHandle = fdopen(fileDescriptor, nativeParams.openMode.data());
286 return make_unique<StreamBuffer>(fileDescriptor, openMode);
288 #else // CPP_UTILITIES_USE_BOOST_IOSTREAMS 290 return make_unique<StreamBuffer>(fileDescriptor, boost::iostreams::close_handle);
294 #ifdef PLATFORM_WINDOWS 299 std::unique_ptr<wchar_t[]> NativeFileStream::makeWidePath(
const std::string &path)
301 auto widePath = ::ConversionUtilities::convertMultiByteToWide(path);
302 if (!widePath.first) {
305 return std::move(widePath.first);
CPP_UTILITIES_EXPORT void throwIoFailure(const char *what)
Throws an std::ios_base::failure with the specified message.
std::fstream NativeFileStream
Contains utility classes helping to read and write streams.