241 lines
5.8 KiB
C++
241 lines
5.8 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: FileStream.NT.cpp
|
|
Date: 2021-6-12
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "FS.hpp"
|
|
#include "FileStream.NT.hpp"
|
|
|
|
#if !defined(_AURUNTIME_GENERICFILESTREAM)
|
|
|
|
namespace Aurora::IO::FS
|
|
{
|
|
static const AuUInt64 kFileCopyBlock = 0xFFFF; // 64KiB, 1k iterations to max out 64MB/s disk, 2k iteration to make out 128MB/s disk, is this number still way too low? cpu go brr
|
|
|
|
WinFileStream::~WinFileStream()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void WinFileStream::Init(HANDLE handle, const AuString &path)
|
|
{
|
|
handle_ = handle;
|
|
path_ = path;
|
|
}
|
|
|
|
AuUInt64 WinFileStream::GetOffset()
|
|
{
|
|
LARGE_INTEGER distance {};
|
|
LARGE_INTEGER pos {};
|
|
|
|
if (handle_ == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorUninitialized();
|
|
return 0;
|
|
}
|
|
|
|
if (SetFilePointerEx(handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
|
|
{
|
|
LogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
|
SysPushErrorIO();
|
|
return 0;
|
|
}
|
|
|
|
return pos.QuadPart;
|
|
}
|
|
|
|
bool WinFileStream::SetOffset(AuUInt64 offset)
|
|
{
|
|
LARGE_INTEGER distance {};
|
|
LARGE_INTEGER pos {};
|
|
|
|
if (handle_ == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorUninitialized();
|
|
return false;
|
|
}
|
|
|
|
distance.QuadPart = offset;
|
|
|
|
if (SetFilePointerEx(handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
|
|
{
|
|
LogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
|
SysPushErrorIO();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
AuUInt64 WinFileStream::GetLength()
|
|
{
|
|
LARGE_INTEGER length;
|
|
|
|
if (handle_ == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorUninitialized();
|
|
return 0;
|
|
}
|
|
|
|
if (!GetFileSizeEx(handle_, &length))
|
|
{
|
|
SysPushErrorIO();
|
|
return 0;
|
|
}
|
|
|
|
return length.QuadPart;
|
|
}
|
|
|
|
bool WinFileStream::Read(const Memory::MemoryViewStreamWrite ¶meters)
|
|
{
|
|
if (handle_ == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorUninitialized();
|
|
return {};
|
|
}
|
|
|
|
auto length = parameters.length;
|
|
AuUInt64 offset {0};
|
|
while (length)
|
|
{
|
|
DWORD read;
|
|
|
|
int blockSize = std::min(kFileCopyBlock, length);
|
|
|
|
if (!::ReadFile(handle_, &reinterpret_cast<char *>(parameters.ptr)[offset], blockSize, &read, NULL))
|
|
{
|
|
LogWarn("ReadFile IO Error: 0x{:x}, {}", GetLastError(), path_);
|
|
SysPushErrorIO();
|
|
return false;
|
|
}
|
|
|
|
if (read == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
offset += read;
|
|
length -= read;
|
|
}
|
|
|
|
if (!offset)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
parameters.outVariable = offset;
|
|
return true;
|
|
}
|
|
|
|
bool WinFileStream::Write(const Memory::MemoryViewStreamRead & parameters)
|
|
{
|
|
if (handle_ == INVALID_HANDLE_VALUE)
|
|
{
|
|
SysPushErrorUninitialized();
|
|
return 0;
|
|
}
|
|
|
|
auto length = parameters.length;
|
|
AuUInt offset {0};
|
|
while (length)
|
|
{
|
|
DWORD written;
|
|
|
|
int blockSize = std::min(kFileCopyBlock, length);
|
|
|
|
if (!::WriteFile(handle_, &reinterpret_cast<const char *>(parameters.ptr)[offset], blockSize, &written, NULL))
|
|
{
|
|
LogWarn("WriteFileEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
|
SysPushErrorIO();
|
|
return false;
|
|
}
|
|
|
|
if (written != blockSize)
|
|
{
|
|
SysPushErrorIO();
|
|
parameters.outVariable = offset;
|
|
return true;
|
|
}
|
|
|
|
offset += written;
|
|
length -= written;
|
|
}
|
|
|
|
if (!offset)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
parameters.outVariable = offset;
|
|
return true;
|
|
}
|
|
|
|
void WinFileStream::Close()
|
|
{
|
|
AuWin32CloseHandle(handle_);
|
|
}
|
|
|
|
void WinFileStream::Flush()
|
|
{
|
|
FlushFileBuffers(handle_);
|
|
}
|
|
|
|
static IFileStream *OpenNew(const AuString &path, bool read)
|
|
{
|
|
auto pathex = NormalizePathRet(path);
|
|
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
|
|
|
HANDLE fileHandle;
|
|
if (read)
|
|
{
|
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
}
|
|
else
|
|
{
|
|
CreateDirectories(pathex, true);
|
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
}
|
|
|
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
LogWarn("Missing file: {}", path);
|
|
SysPushErrorIO("Missing file: {}", path);
|
|
return nullptr;
|
|
}
|
|
|
|
auto stream = _new WinFileStream();
|
|
if (!stream)
|
|
{
|
|
CloseHandle(fileHandle);
|
|
return nullptr;
|
|
}
|
|
|
|
stream->Init(fileHandle, pathex);
|
|
return stream;
|
|
}
|
|
|
|
AUKN_SYM IFileStream *OpenReadNew(const AuString &path)
|
|
{
|
|
return OpenNew(path, true);
|
|
}
|
|
|
|
AUKN_SYM void OpenReadRelease(IFileStream * that)
|
|
{
|
|
SafeDelete<WinFileStream *>(that);
|
|
}
|
|
|
|
AUKN_SYM IFileStream *OpenWriteNew(const AuString &path)
|
|
{
|
|
return OpenNew(path, false);
|
|
}
|
|
|
|
AUKN_SYM void OpenWriteRelease(IFileStream * that)
|
|
{
|
|
SafeDelete<WinFileStream *>(that);
|
|
}
|
|
}
|
|
|
|
#endif |