From 1613ed905f28fe7cd6001c2329d2ea1a33945f5e Mon Sep 17 00:00:00 2001 From: Danilo Date: Tue, 26 Mar 2024 15:56:17 -0300 Subject: [PATCH] Implementa FileStream --- framework/csharp/stream.cpp | 113 +++++++++++++++++++++++++++++++++++- framework/csharp/stream.hpp | 65 +++++++++++++++++++++ framework/xnaerror.hpp | 2 +- 3 files changed, 178 insertions(+), 2 deletions(-) diff --git a/framework/csharp/stream.cpp b/framework/csharp/stream.cpp index 64d8fca..67089dc 100644 --- a/framework/csharp/stream.cpp +++ b/framework/csharp/stream.cpp @@ -32,7 +32,7 @@ namespace xna { } break; default: - xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } @@ -124,4 +124,115 @@ namespace xna { _buffer[_position++] = value; } + + Long FileStream::Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg){ + if (_closed) + return 0; + + int seek; + + switch (origin) + { + case SeekOrigin::Begin: + seek = std::ios_base::beg; + break; + case SeekOrigin::Current: + seek = std::ios_base::cur; + break; + case SeekOrigin::End: + seek = std::ios_base::end; + break; + default: + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + _fstream.seekg(offset, seek); + const auto state = _fstream.rdstate(); + + if (state != std::fstream::goodbit) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return -1; + } + + const auto pos = static_cast(_fstream.tellg()); + return pos; + } + + Int FileStream::Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg){ + if (buffer == nullptr || offset < 0 || count < 0 || bufferLength - offset < count) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + if (_closed) + return 0; + + auto _buff = reinterpret_cast(buffer); + _fstream.read(_buff + offset, count); + + if (_fstream.rdstate() != std::fstream::goodbit) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + return static_cast(_fstream.gcount()); + } + + Int FileStream::Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg){ + return Read(buffer.data(), static_cast(buffer.size()), offset, count, err); + } + + Int FileStream::ReadByte(xna_error_ptr_arg){ + if (_closed) + return 0; + + char c = 0; + + _fstream.read(&c, 1); + + if (_fstream.rdstate() != std::fstream::goodbit) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + const auto result = static_cast(c); + + return result; + } + + void FileStream::Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) { + if (buffer == nullptr || offset < 0 || count < 0 || bufferLength - offset < count) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return; + } + + if (_closed) + return; + + auto _buff = reinterpret_cast(buffer); + + _fstream.write(_buff + offset, count); + + if (_fstream.rdstate() != std::fstream::goodbit) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + } + } + + void FileStream::Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) { + Write(buffer.data(), static_cast(buffer.size()), offset, count, err); + } + + void FileStream::WriteByte(Byte value, xna_error_ptr_arg) { + if (_closed) + return; + + const char c = static_cast(value); + + _fstream.write(&c, 1); + + if (_fstream.rdstate() != std::fstream::goodbit) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + } + } } \ No newline at end of file diff --git a/framework/csharp/stream.hpp b/framework/csharp/stream.hpp index 35b012b..9e72787 100644 --- a/framework/csharp/stream.hpp +++ b/framework/csharp/stream.hpp @@ -4,6 +4,8 @@ #include "../types.hpp" #include "../enums.hpp" #include "../xnaerror.hpp" +#include +#include namespace xna { class Stream { @@ -60,6 +62,69 @@ namespace xna { std::vector _buffer; bool _closed{ false }; }; + + class FileStream : public Stream { + public: + FileStream(std::string const& path){ + int flags = std::fstream::in + | std::fstream::out + | std::fstream::binary + | std::fstream::ate; + + const auto exists = std::filesystem::exists(path); + + if (!exists) + flags |= std::fstream::trunc; + + _fstream.open(path.c_str(), flags); + + if (_fstream.is_open()) { + _filesize = _fstream.tellg(); + _fstream.seekg(0); + } + else { + _closed = true; + } + } + + ~FileStream() { + Close(); + } + + virtual constexpr Int Length() override { + if (_closed) + return 0; + + return static_cast(_filesize); + } + + virtual Long Position() override { + if (_closed) + return 0; + + return static_cast(_fstream.tellg()); + } + + virtual void Close() override { + _closed = true; + + if(_fstream.is_open()) + _fstream.close(); + } + + virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) override; + virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; + virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) override; + virtual Int ReadByte(xna_error_ptr_arg) override; + virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; + virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) override; + virtual void WriteByte(Byte value, xna_error_ptr_arg) override; + + public: + std::streampos _filesize{ 0 }; + std::fstream _fstream; + bool _closed{ false }; + }; } #endif \ No newline at end of file diff --git a/framework/xnaerror.hpp b/framework/xnaerror.hpp index 8e42e87..65a6da3 100644 --- a/framework/xnaerror.hpp +++ b/framework/xnaerror.hpp @@ -8,7 +8,7 @@ namespace xna { ARGUMENT_IS_NULL, INVALID_OPERATION, OVERFLOW_OPERATION, - NULL_CAST, + NULL_CAST, }; inline void xna_error_apply(XnaErrorCode* source, XnaErrorCode const& value) {