diff options
Diffstat (limited to 'core/src/Utils/IO/FileStream_Custom.inl')
-rw-r--r-- | core/src/Utils/IO/FileStream_Custom.inl | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/core/src/Utils/IO/FileStream_Custom.inl b/core/src/Utils/IO/FileStream_Custom.inl deleted file mode 100644 index 004dd01..0000000 --- a/core/src/Utils/IO/FileStream_Custom.inl +++ /dev/null @@ -1,358 +0,0 @@ -// Note: included by FileStream.cpp conditionally, not compiled separately -#include "FileStream.hpp" - -#include <cstring> -#include <filesystem> -#include <iostream> - -namespace fs = std::filesystem; - -#if defined(_WIN32) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <Windows.h> - -InputFileStream::InputFileStream(const fs::path& path) - : mOsFileHandle{ 0 } -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - - *handle = CreateFileW( - path.c_str(), // fs::path::c_str() returns a wide string on Windows - GENERIC_READ, - /* No sharing */ 0, - /* Use default security*/ nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - /* No attribute template */ nullptr); - - // TODO handle error -} - -InputFileStream::~InputFileStream() -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - CloseHandle(*handle); -} - -OutputFileStream::OutputFileStream(const fs::path& path, WriteMode mode) - : mOsFileHandle{ 0 } -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - - DWORD creationDisposition; - switch (mode) { - case AppendFile: creationDisposition = OPEN_ALWAYS; break; - case TruncateFile: creationDisposition = CREATE_ALWAYS; break; - } - - *handle = CreateFileW( - path.c_str(), - GENERIC_WRITE, - /* No sharing */ 0, - /* Use default security*/ nullptr, - creationDisposition, - FILE_ATTRIBUTE_NORMAL, - /* No attribute template */ nullptr); - - // TODO handle error -} - -OutputFileStream::~OutputFileStream() -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - CloseHandle(*handle); -} - -static IoResult::ErrorKind MapErrorCodeToIoResult(DWORD error) -{ - switch (error) { - // TODO - - default: - std::cerr << "Unimplemented win32 error code " << error << ", report bug immediately.\n"; - std::abort(); - } -} - -static IoResult ReadBytesDirect(HANDLE hFile, size_t byteCount, std::byte* bytes) -{ - DWORD bytesRead; - BOOL result = ReadFile(hFile, bytes, byteCount, &bytesRead, nullptr); - - if (result) { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesRead, - }; - } else { - DWORD errorCode = GetLastError(); - return IoResult{ - .Error = ::MapErrorCodeToIoResult(errorCode), - .SystemError = errorCode, - .BytesMoved = bytesRead, - }; - } -} - -static IoResult WriteBytesDirect(HANDLE hFile, size_t byteCount, const std::byte* bytes) -{ - DWORD bytesWritten; - BOOL result = WriteFile(hFile, bytes, byteCount, &bytesWritten, nullptr); - - if (result) { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesWritten, - }; - } else { - DWORD errorCode = GetLastError(); - return IoResult{ - .Error = ::MapErrorCodeToIoResult(errorCode), - .SystemError = errorCode, - .BytesMoved = bytesWritten, - }; - } -} - -#elif defined(__APPLE__) || defined(__linux__) -# include <fcntl.h> -# include <sys/stat.h> -# include <sys/types.h> -# include <unistd.h> - -InputFileStream::InputFileStream(const fs::path& path) - : mOsFileHandle{ 0 } -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - *fd = open(path.c_str(), O_RDONLY); -} - -InputFileStream::~InputFileStream() -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - close(*fd); -} - -OutputFileStream::OutputFileStream(const fs::path& path, WriteMode mode) - : mOsFileHandle{ 0 } -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - - int flags = O_WRONLY | O_CREAT; - switch (mode) { - case AppendFile: flags |= O_APPEND; break; - case TruncateFile: flags |= O_TRUNC; break; - } - - *fd = open(path.c_str(), flags, 0644); -} - -OutputFileStream::~OutputFileStream() -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - close(*fd); -} - -static IoResult::ErrorKind MapErrnoToIoResult(int err) -{ - switch (err) { - // TODO - case EFAULT: return IoResult::ERR_UnexpectedEof; - case EPERM: return IoResult::ERR_PermissionDenied; - case ENOSPC: return IoResult::ERR_OutOfSpace; - case EIO: return IoResult::ERR_Other; - - default: - std::cerr << "Unimplemented POSIX errno " << err << ", report bug immediately.\n"; - std::abort(); - } -} - -static IoResult ReadBytesDirect(const char* osFileHandle, size_t byteCount, std::byte* bytes) -{ - int fd = *reinterpret_cast<const int*>(osFileHandle); - int status = read(fd, bytes, byteCount); - - if (status == -1) { - int err = errno; - return IoResult{ - .Error = ::MapErrnoToIoResult(err), - .SystemError = (uint32_t)err, - .BytesMoved = 0, - }; - } else { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = (size_t)status, // Equal to number of bytes read - }; - } -} - -static IoResult WriteBytesDirect(const char* osFileHandle, size_t byteCount, const std::byte* bytes) -{ - int fd = *reinterpret_cast<const int*>(osFileHandle); - int status = write(fd, bytes, byteCount); - - if (status == -1) { - int err = errno; - return IoResult{ - .Error = ::MapErrnoToIoResult(err), - .SystemError = (uint32_t)err, - .BytesMoved = 0, - }; - } else { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = (size_t)status, // Equal to number of bytes read - }; - } -} - -#else -# error "Unsupported target platform." -#endif - -int InputFileStream::GetReadInSize() const -{ - return mReadInSize; -} - -void InputFileStream::SetReadInSize(int size) -{ - if (size > mReadInSize) { - mReadInSize = size; - mBuffer = std::make_unique<std::byte[]>(size); - } -} - -bool InputFileStream::IsEof() const -{ - return mEof; -} - -IoResult InputFileStream::ReadBytes(size_t bufferLength, std::byte* buffer) -{ - // TODO reduce duplicated code - - auto bytesMoved = std::min<size_t>(mAvailableBytes, bufferLength); - - // On first call after construction, mFirstByteIdx will equal to mReadInSize, i.e. bytesAvailable == 0 - // and this call to std::memcpy will be no-op - std::memcpy(buffer, &mBuffer[mFirstByteIdx], bytesMoved); - mFirstByteIdx += (int)bytesMoved; - mAvailableBytes -= (int)bytesMoved; - buffer += bytesMoved; - - size_t bytesLeft = bufferLength - bytesMoved; - if (bytesLeft > mReadInSize) { - // Our buffer can't handle rest of the request, just skip the buffering step - - // Read rest of the data into buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, bytesLeft, buffer); - bytesMoved += result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - - // Refill our buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, mReadInSize, mBuffer.get()); - mFirstByteIdx = 0; - mAvailableBytes = (int)result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - } else if (bytesLeft > 0) { - // Our buffer can handle rest of the request, first buffer than supply the requested data - - // Refill our buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, mReadInSize, mBuffer.get()); - mFirstByteIdx = 0; - mAvailableBytes = (int)result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - - // Copy data into buffer - { - std::memcpy(buffer, &mBuffer[mFirstByteIdx], bytesLeft); - mFirstByteIdx += (int)bytesLeft; - bytesMoved += bytesLeft; - buffer += bytesLeft; - } - } else { - // Request completed already - } - -end: - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesMoved, - }; -} - -int OutputFileStream::GetMaxBufferSize() const -{ - return mMaxBufferSize; -} - -void OutputFileStream::SetMaxBufferSize(int maxSize) -{ - FlushBuffer(); - if (maxSize > mMaxBufferSize) { - mMaxBufferSize = maxSize; - mBuffer = std::make_unique<std::byte[]>(maxSize); - } -} - -IoResult OutputFileStream::WriteBytes(size_t bufferLength, const std::byte* buffer) -{ - if (bufferLength + mCurrentBufferSize > mMaxBufferSize) { - FlushBuffer(); - - if (bufferLength > mMaxBufferSize) { - return ::WriteBytesDirect(mOsFileHandle, bufferLength, buffer); - } - } - - std::memcpy(mBuffer.get() + mCurrentBufferSize, buffer, bufferLength); - mCurrentBufferSize += (int)bufferLength; - - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bufferLength, - }; -} - -void OutputFileStream::FlushBuffer() -{ - ::WriteBytesDirect(mOsFileHandle, mCurrentBufferSize, mBuffer.get()); - mCurrentBufferSize = 0; -} |