2021-06-27 21:25:29 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
2021-09-06 10:58:08 +00:00
File : FileStream . NT . cpp
2021-06-27 21:25:29 +00:00
Date : 2021 - 6 - 12
Author : Reece
* * */
2021-09-30 14:57:41 +00:00
# include <Source/RuntimeInternal.hpp>
2021-06-27 21:25:29 +00:00
# include "FS.hpp"
2021-09-06 10:58:08 +00:00
# include "FileStream.NT.hpp"
2021-06-27 21:25:29 +00:00
# if !defined(_AURUNTIME_GENERICFILESTREAM)
namespace Aurora : : IO : : FS
{
2021-09-13 20:11:12 +00:00
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
2021-06-27 21:25:29 +00:00
WinFileStream : : ~ WinFileStream ( )
{
Close ( ) ;
}
2021-09-06 10:58:08 +00:00
void WinFileStream : : Init ( HANDLE handle , const AuString & path )
2021-06-27 21:25:29 +00:00
{
handle_ = handle ;
2021-09-06 10:58:08 +00:00
path_ = path ;
2021-06-27 21:25:29 +00:00
}
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 )
{
2021-11-08 01:15:37 +00:00
LogWarn ( " SetFilePointerEx IO Error: 0x{:x}, {} " , GetLastError ( ) , path_ ) ;
2021-06-27 21:25:29 +00:00
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 )
{
2021-11-08 01:15:37 +00:00
LogWarn ( " SetFilePointerEx IO Error: 0x{:x}, {} " , GetLastError ( ) , path_ ) ;
2021-06-27 21:25:29 +00:00
SysPushErrorIO ( ) ;
return false ;
}
return true ;
}
AuUInt64 WinFileStream : : GetLength ( )
{
LARGE_INTEGER length ;
2021-09-06 10:58:08 +00:00
if ( handle_ = = INVALID_HANDLE_VALUE )
{
SysPushErrorUninitialized ( ) ;
return 0 ;
}
2021-06-27 21:25:29 +00:00
if ( ! GetFileSizeEx ( handle_ , & length ) )
{
SysPushErrorIO ( ) ;
return 0 ;
}
return length . QuadPart ;
}
2021-09-15 18:55:22 +00:00
bool WinFileStream : : Read ( const Memory : : MemoryViewStreamWrite & parameters )
2021-06-27 21:25:29 +00:00
{
if ( handle_ = = INVALID_HANDLE_VALUE )
{
SysPushErrorUninitialized ( ) ;
2021-09-14 23:56:26 +00:00
return { } ;
2021-06-27 21:25:29 +00:00
}
2021-09-14 23:56:26 +00:00
auto length = parameters . length ;
2021-06-27 21:25:29 +00:00
AuUInt64 offset { 0 } ;
while ( length )
{
DWORD read ;
int blockSize = std : : min ( kFileCopyBlock , length ) ;
2021-09-14 23:56:26 +00:00
if ( ! : : ReadFile ( handle_ , & reinterpret_cast < char * > ( parameters . ptr ) [ offset ] , blockSize , & read , NULL ) )
2021-06-27 21:25:29 +00:00
{
2021-09-17 19:26:05 +00:00
LogWarn ( " ReadFile IO Error: 0x{:x}, {} " , GetLastError ( ) , path_ ) ;
2021-06-27 21:25:29 +00:00
SysPushErrorIO ( ) ;
2021-09-14 23:56:26 +00:00
return false ;
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
if ( read = = 0 )
2021-06-27 21:25:29 +00:00
{
2021-09-06 10:58:08 +00:00
break ;
2021-06-27 21:25:29 +00:00
}
offset + = read ;
length - = read ;
}
2021-09-14 23:56:26 +00:00
if ( ! offset )
{
return false ;
}
parameters . outVariable = offset ;
return true ;
2021-06-27 21:25:29 +00:00
}
2021-09-15 18:55:22 +00:00
bool WinFileStream : : Write ( const Memory : : MemoryViewStreamRead & parameters )
2021-06-27 21:25:29 +00:00
{
if ( handle_ = = INVALID_HANDLE_VALUE )
{
SysPushErrorUninitialized ( ) ;
return 0 ;
}
2021-09-14 23:56:26 +00:00
auto length = parameters . length ;
AuUInt offset { 0 } ;
2021-06-27 21:25:29 +00:00
while ( length )
{
DWORD written ;
int blockSize = std : : min ( kFileCopyBlock , length ) ;
2021-09-14 23:56:26 +00:00
if ( ! : : WriteFile ( handle_ , & reinterpret_cast < const char * > ( parameters . ptr ) [ offset ] , blockSize , & written , NULL ) )
2021-06-27 21:25:29 +00:00
{
2021-09-17 19:26:05 +00:00
LogWarn ( " WriteFileEx IO Error: 0x{:x}, {} " , GetLastError ( ) , path_ ) ;
2021-06-27 21:25:29 +00:00
SysPushErrorIO ( ) ;
2021-09-14 23:56:26 +00:00
return false ;
2021-06-27 21:25:29 +00:00
}
if ( written ! = blockSize )
{
SysPushErrorIO ( ) ;
2021-09-14 23:56:26 +00:00
parameters . outVariable = offset ;
return true ;
2021-06-27 21:25:29 +00:00
}
offset + = written ;
length - = written ;
}
2021-09-14 23:56:26 +00:00
if ( ! offset )
{
return false ;
}
parameters . outVariable = offset ;
return true ;
2021-06-27 21:25:29 +00:00
}
void WinFileStream : : Close ( )
{
2021-09-13 20:11:12 +00:00
AuWin32CloseHandle ( handle_ ) ;
2021-06-27 21:25:29 +00:00
}
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 ;
}
2021-09-06 10:58:08 +00:00
stream - > Init ( fileHandle , pathex ) ;
2021-06-27 21:25:29 +00:00
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