From 3f984fcea26e8f2679d644c4d152ec23a7558286 Mon Sep 17 00:00:00 2001 From: Danilo Date: Tue, 26 Mar 2024 10:32:56 -0300 Subject: [PATCH] Implementa MemoryStream --- framework/CMakeLists.txt | 2 +- framework/csharp/buffer.hpp | 27 ++++++++ framework/csharp/stream.cpp | 127 ++++++++++++++++++++++++++++++++++ framework/csharp/stream.hpp | 65 +++++++++++++++++ framework/csharp/timespan.hpp | 5 ++ framework/enums.hpp | 6 ++ framework/forward.hpp | 10 +++ framework/types.hpp | 4 ++ framework/xnaerror.hpp | 27 ++++++++ 9 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 framework/csharp/buffer.hpp create mode 100644 framework/csharp/stream.cpp create mode 100644 framework/csharp/stream.hpp create mode 100644 framework/xnaerror.hpp diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 348b7d6..8c10639 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -3,7 +3,7 @@ # # Add source to this project's executable. -add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp") +add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp" "csharp/stream.cpp") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET xna PROPERTY CXX_STANDARD 20) diff --git a/framework/csharp/buffer.hpp b/framework/csharp/buffer.hpp new file mode 100644 index 0000000..6c5775f --- /dev/null +++ b/framework/csharp/buffer.hpp @@ -0,0 +1,27 @@ +#ifndef XNA_CSHARP_BUFFER_HPP +#define XNA_CSHARP_BUFFER_HPP + +#include +#include + +namespace xna { + class Buffer { + public: + template + static void BlockCopy( + T const* src, + rsize_t srcOffset, + T* dst, + rsize_t dstOffset, + rsize_t byteCount) { + memmove_s(dst + dstOffset, byteCount, src + srcOffset, byteCount); + } + + private: + constexpr Buffer() = default; + constexpr Buffer(Buffer&&) = default; + constexpr Buffer(const Buffer&) = default; + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/stream.cpp b/framework/csharp/stream.cpp new file mode 100644 index 0000000..64d8fca --- /dev/null +++ b/framework/csharp/stream.cpp @@ -0,0 +1,127 @@ +#include "stream.hpp" +#include "buffer.hpp" + +namespace xna { + Long MemoryStream::Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) { + Long p = 0; + + switch (origin) + { + case SeekOrigin::Begin: + p = _origin + offset; + + if (p < _origin) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return -1; + } + break; + case SeekOrigin::Current: + p = _position + offset; + + if (p < _origin) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return -1; + } + break; + case SeekOrigin::End: + p = _length + offset; + + if (p < _origin) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return -1; + } + break; + default: + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return -1; + } + + assertm(_position >= 0, "position >= 0"); + + _position = static_cast(p); + return _position; + } + + Int MemoryStream::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; + } + + auto off = _length - _position; + if (off > count) off = count; + + if (off <= 0 || _closed) + return 0; + + if (off <= 8) { + auto byteCount = off; + while (--byteCount >= 0) + buffer[offset + byteCount] = _buffer[_position + static_cast(byteCount)]; + } + else { + Buffer::BlockCopy(_buffer.data(), _position, buffer, offset, off); + } + + _position += off; + + return off; + } + + Int MemoryStream::Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) { + return Read(buffer.data(), static_cast(buffer.size()), offset, count, err); + } + + Int MemoryStream::ReadByte(xna_error_ptr_arg) { + if (!_closed) + return 0; + + if (_position >= _length) + return -1; + + return _buffer[_position++]; + } + + void MemoryStream::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 i = _position + count; + + if (i < 0 || i > _length) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return; + } + + if (count <= 8) { + auto byteCount = count; + while (--byteCount >= 0) + _buffer[_position + static_cast(byteCount)] = buffer[offset + byteCount]; + } + else + Buffer::BlockCopy(buffer, offset, _buffer.data(), _position, count); + + _position = i; + } + + void MemoryStream::Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg){ + Write(buffer.data(), static_cast(buffer.size()), offset, count, err); + } + + void MemoryStream::WriteByte(Byte value, xna_error_ptr_arg) { + if (_closed) + return; + + if (_position >= _length) { + xna_error_apply(err, XnaErrorCode::OVERFLOW_OPERATION); + return; + } + + _buffer[_position++] = value; + } +} \ No newline at end of file diff --git a/framework/csharp/stream.hpp b/framework/csharp/stream.hpp new file mode 100644 index 0000000..35b012b --- /dev/null +++ b/framework/csharp/stream.hpp @@ -0,0 +1,65 @@ +#ifndef XNA_CSHARP_STREAM_HPP +#define XNA_CSHARP_STREAM_HPP + +#include "../types.hpp" +#include "../enums.hpp" +#include "../xnaerror.hpp" + +namespace xna { + class Stream { + public: + virtual Int Length() = 0; + virtual Long Position() = 0; + virtual void Close() = 0; + virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) = 0; + virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) = 0; + virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_nullarg) = 0; + virtual Int ReadByte(xna_error_nullarg) = 0; + virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) = 0; + virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_nullarg) = 0; + virtual void WriteByte(Byte value, xna_error_nullarg) = 0; + }; + + class MemoryStream : public Stream { + public: + constexpr MemoryStream(Int capacity) : + _buffer(static_cast(capacity)), + _length(capacity > 0 ? capacity : 0){} + + virtual constexpr Int Length() override { + if (_closed) + return 0; + + return _length; + } + + virtual constexpr Long Position() override { + if (_closed) + return 0; + + return _position; + } + + virtual constexpr void Close() override { + _closed = true; + _buffer = std::vector(); + } + + 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: + Int _position{ 0 }; + Int _origin{ 0 }; + Int _length{ 0 }; + std::vector _buffer; + bool _closed{ false }; + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/timespan.hpp b/framework/csharp/timespan.hpp index 7ccd96b..a8912ae 100644 --- a/framework/csharp/timespan.hpp +++ b/framework/csharp/timespan.hpp @@ -1,3 +1,8 @@ +/* + TimeSpan in C++ + Source code: https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs,865ef7b89f41b632 +*/ + #ifndef XNA_CSHARP_TIMESPAN_HPP #define XNA_CSHARP_TIMESPAN_HPP diff --git a/framework/enums.hpp b/framework/enums.hpp index 000a2e5..451fe35 100644 --- a/framework/enums.hpp +++ b/framework/enums.hpp @@ -47,6 +47,12 @@ namespace xna { Portrait = 4, }; + enum class SeekOrigin { + Begin, + Current, + End, + }; + enum class SurfaceFormat { Color = 0, Bgr565 = 1, diff --git a/framework/forward.hpp b/framework/forward.hpp index c3b09c1..6cc546d 100644 --- a/framework/forward.hpp +++ b/framework/forward.hpp @@ -4,6 +4,16 @@ #include "types.hpp" namespace xna { + //CShap + struct TimeSpan; + using PTimeSpan = std::shared_ptr; + class Stream; + using PStream = std::shared_ptr; + class FileStream; + using PFileStream = std::shared_ptr; + class MemoryStream; + using PMemoryStream = std::shared_ptr; + //Framework class BoundingBox; using PBoundingBox = std::shared_ptr; diff --git a/framework/types.hpp b/framework/types.hpp index d10fe40..8adac56 100644 --- a/framework/types.hpp +++ b/framework/types.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace xna { using Sbyte = int8_t; @@ -53,6 +54,9 @@ namespace xna { } #define PLATFORM_DEVELOPMENT + +//See ref: https://en.cppreference.com/w/cpp/error/assert +#define assertm(exp, msg) assert(((void)msg, exp)) } #endif \ No newline at end of file diff --git a/framework/xnaerror.hpp b/framework/xnaerror.hpp new file mode 100644 index 0000000..8e42e87 --- /dev/null +++ b/framework/xnaerror.hpp @@ -0,0 +1,27 @@ +#ifndef XNA_XNAERROR_HPP +#define XNA_XNAERROR_HPP + +namespace xna { + enum class XnaErrorCode { + NONE, + ARGUMENT_OUT_OF_RANGE, + ARGUMENT_IS_NULL, + INVALID_OPERATION, + OVERFLOW_OPERATION, + NULL_CAST, + }; + + inline void xna_error_apply(XnaErrorCode* source, XnaErrorCode const& value) { + if (source != nullptr) + *source = value; + } + + inline bool xna_error_haserros(XnaErrorCode* source) { + return source != nullptr; + } + +#define xna_error_nullarg XnaErrorCode* err = nullptr +#define xna_error_ptr_arg XnaErrorCode* err +} + +#endif \ No newline at end of file