AuroraRuntime/Source/IO/FS/FileStream.Generic.cpp

240 lines
5.4 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FileStream.Generic.cpp
Date: 2021-6-12
Author: Reece
***/
// TODO: 64
#include <Source/RuntimeInternal.hpp>
#include "FS.hpp"
#include "FileStream.Generic.hpp"
#if defined(_AURUNTIME_GENERICFILESTREAM)
namespace Aurora::IO::FS
{
static const AuUInt64 kFileCopyBlock = 0x4000; // 16KiB
template<typename T>
class StdFS : public IFileStream
{
public:
void Close() override
{
try
{
if (stream_.is_open())
{
stream_.close();
}
}
catch (...)
{
SysPanic("Critical File IO error");
}
}
bool Open(const AuString &str)
{
try
{
#if defined(NO_STD_FS)
stream_.open(NormalizePathRet(str), std::ios_base::binary)
#else
stream_.open(std::filesystem::u8path(NormalizePathRet(str)), std::ios_base::binary);
#endif
}
catch (...)
{
return false;
}
return stream_.is_open();
}
AuUInt64 GetOffset() override
{
return offset_;
}
AuUInt64 GetLength() override
{
auto startingOffset = GetOffset();
GoToEof();
auto ret = GetOffset();
SetOffset(startingOffset);
return startingOffset;
}
virtual void Flush()
{
};
virtual void GoToEof() = 0;
protected:
AuUInt64 offset_ = 0;
T stream_;
};
class StdReadFS : public StdFS<std::ifstream>
{
public:
void GoToEof() override
{
stream_.seekg(0, std::ios_base::end);
offset_ = stream_.tellg();
}
bool SetOffset(AuUInt64 offset) override
{
try
{
stream_.seekg(offset, std::ios_base::beg);
offset_ = offset;
}
catch (...)
{
return false;
}
return true;
}
bool Read(const Memory::MemoryViewStreamWrite &parameters) override
{
try
{
if (!stream_.is_open())
{
return false;
}
stream_.read(reinterpret_cast<char *>(parameters.ptr), parameters.length);
parameters.outVariable = stream_.gcount();
offset_ += parameters.outVariable;
return true;
}
catch (...)
{
return false;
}
}
bool Write(const Memory::MemoryViewStreamRead & parameters) override
{
return false;
}
};
class StdWriteFS : public StdFS<std::ofstream>
{
public:
void GoToEof() override
{
stream_.seekp(0, std::ios_base::end);
offset_ = stream_.tellp();
}
bool Read(const Memory::MemoryViewStreamWrite &parameters) override
{
return false;
}
bool Write(const Memory::MemoryViewStreamRead & parameters) override
{
try
{
if (!stream_.is_open())
{
return false;
}
auto start = stream_.tellp();
stream_.write(reinterpret_cast<const char *>(parameters.ptr), parameters.length);
parameters.outVariable = stream_.tellp() - start;
offset_ += parameters.outVariable;
}
catch (...)
{
return false;
}
return true;
}
bool SetOffset(AuUInt64 offset) override
{
try
{
stream_.seekp(offset, std::ios_base::beg);
offset_ = offset;
}
catch (...)
{
return false;
}
return true;
}
void Flush() override
{
try
{
stream_.flush();
}
catch (...)
{
LogWarn("Couldn't flush file stream");
}
}
};
AUKN_SYM IFileStream *OpenReadNew(const AuString &path)
{
auto stream = _new StdReadFS();
if (!stream)
{
return nullptr;
}
if (!stream->Open(NormalizePathRet(path)))
{
delete stream;
return nullptr;
}
return stream;
}
AUKN_SYM void OpenReadRelease(IFileStream * that)
{
SafeDelete<StdReadFS *>(that);
}
AUKN_SYM IFileStream *OpenWriteNew(const AuString &path)
{
auto pathex = NormalizePathRet(path);
auto stream = _new StdWriteFS();
if (!stream)
{
return nullptr;
}
CreateDirectories(pathex, true);
if (!stream->Open(pathex))
{
delete stream;
return nullptr;
}
return stream;
}
AUKN_SYM void OpenWriteRelease(IFileStream * that)
{
SafeDelete<StdWriteFS *>(that);
}
}
#endif