/*** 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 #include "FS.hpp" #include "FileStream.Generic.hpp" #if defined(_AURUNTIME_GENERICFILESTREAM) namespace Aurora::IO::FS { static const AuUInt64 kFileCopyBlock = 0x4000; // 16KiB template 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(RetPathHelper(str), std::ios_base::binary) #else stream_.open(std::filesystem::u8path(RetPathHelper(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 { 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(Memory::MemoryViewStreamWrite parameters) override { try { if (!stream_.is_open()) { return false; } stream_.read(reinterpret_cast(parameters.ptr), parameters.length); parameters.outVariable = stream_.gcount(); offset_ += parameters.outVariable; return true; } catch (...) { return false; } } bool Write(Memory::MemoryViewStreamRead parameters) override { return false; } }; class StdWriteFS : public StdFS { public: void GoToEof() override { stream_.seekp(0, std::ios_base::end); offset_ = stream_.tellp(); } bool Read(Memory::MemoryViewStreamWrite parameters) override { return false; } bool Write(Memory::MemoryViewStreamRead parameters) override { try { if (!stream_.is_open()) { return false; } auto start = stream_.tellp(); stream_.write(reinterpret_cast(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(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(that); } } #endif