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 #if !defined(__ANDROID_API__) || !defined(__ANDROID_API_N__) || (__ANDROID_API__ < __ANDROID_API_N__)
147 , m_fileHandle(other.m_fileHandle)
155 NativeFileStream::~NativeFileStream()
162 bool NativeFileStream::is_open()
const 164 return m_filebuf && static_cast<const StreamBuffer *>(m_filebuf.get())->is_open();
180 void NativeFileStream::open(
const string &path, ios_base::openmode openMode)
182 setFileBuffer(makeFileBuffer(path, openMode));
193 void NativeFileStream::openFromFileDescriptor(
int fileDescriptor, ios_base::openmode openMode)
195 setFileBuffer(makeFileBuffer(fileDescriptor, openMode));
201 void NativeFileStream::close()
204 static_cast<StreamBuffer *>(m_filebuf.get())->close();
211 void NativeFileStream::setFileBuffer(std::unique_ptr<std::basic_streambuf<char>> buffer)
214 m_filebuf = std::move(buffer);
220 std::unique_ptr<std::basic_streambuf<char>> NativeFileStream::makeFileBuffer(
const string &path, ios_base::openmode openMode)
222 #ifdef PLATFORM_WINDOWS 224 const auto widePath(makeWidePath(path));
228 const NativeFileParams nativeParams(openMode);
230 #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF 232 #ifdef PLATFORM_WINDOWS 233 const int fileHandle = _wopen(widePath.get(), nativeParams.openMode, nativeParams.permissions);
234 if (fileHandle == -1) {
238 const auto fileHandle = fopen(path.data(), nativeParams.openMode.data());
243 return make_unique<StreamBuffer>(fileHandle, openMode);
245 #else // CPP_UTILITIES_USE_BOOST_IOSTREAMS 247 #ifdef PLATFORM_WINDOWS 248 const auto fileDescriptor
249 = CreateFileW(widePath.get(), nativeParams.access, nativeParams.shareMode,
nullptr, nativeParams.creation, FILE_ATTRIBUTE_NORMAL);
250 if (fileDescriptor == INVALID_HANDLE_VALUE) {
254 const auto fileDescriptor = ::open(path.data(), nativeParams.openFlags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
255 if (fileDescriptor == -1) {
259 return make_unique<StreamBuffer>(fileDescriptor, boost::iostreams::close_handle);
266 std::unique_ptr<std::basic_streambuf<char>> NativeFileStream::makeFileBuffer(
int fileDescriptor, ios_base::openmode openMode)
269 const NativeFileParams nativeParams(openMode);
271 #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF 273 #ifdef PLATFORM_WINDOWS 274 const auto fileHandle = _get_osfhandle(fileDescriptor);
275 if (fileHandle == -1) {
278 const auto osFileHandle = _open_osfhandle(fileHandle, nativeParams.flags);
279 if (osFileHandle == -1) {
283 const auto fileHandle = fdopen(fileDescriptor, nativeParams.openMode.data());
288 return make_unique<StreamBuffer>(fileDescriptor, openMode);
290 #else // CPP_UTILITIES_USE_BOOST_IOSTREAMS 292 return make_unique<StreamBuffer>(fileDescriptor, boost::iostreams::close_handle);
296 #ifdef PLATFORM_WINDOWS 301 std::unique_ptr<wchar_t[]> NativeFileStream::makeWidePath(
const std::string &path)
303 auto widePath = ::ConversionUtilities::convertMultiByteToWide(path);
304 if (!widePath.first) {
307 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.