From 35ff33b0b5cdd579bb2059f044c3074b63743881 Mon Sep 17 00:00:00 2001 From: Danilo Borges Santos Date: Fri, 13 Dec 2024 13:40:51 -0300 Subject: [PATCH] Implementa BinaryWriter --- includes/csharp/io/binary.hpp | 100 ++++++++++++++++++++++++++----- includes/csharp/text/unicode.hpp | 16 ++--- samples/01_blank/xna.cpp | 21 +------ sources/csharp/io/binary.cpp | 27 ++++++++- 4 files changed, 121 insertions(+), 43 deletions(-) diff --git a/includes/csharp/io/binary.hpp b/includes/csharp/io/binary.hpp index f3ffd87..49b1bc8 100644 --- a/includes/csharp/io/binary.hpp +++ b/includes/csharp/io/binary.hpp @@ -8,10 +8,10 @@ namespace csharp { /* - * The BinaryReader class uses byte encodings, by default UTF8. + * The BinaryReader class uses byte encodings, by default UTF8. * This was not implemented, but we tried to follow the same standard. * Also the reading of primitives was modified. - * + * */ //TODO: ReadString and ReadChar as it only reads ASCII characters @@ -22,7 +22,7 @@ namespace csharp { class BinaryReader { public: BinaryReader(std::shared_ptr const& input, bool leaveOpen = false) - : _stream(input), _leaveOpen(leaveOpen) + : _stream(input), _leaveOpen(leaveOpen) { ArgumentNullException::ThrowIfNull(input.get(), "input"); @@ -48,7 +48,7 @@ namespace csharp { virtual uint8_t ReadByte() { return InternalReadByte(); } - + virtual inline int8_t ReadSByte() { return static_cast(InternalReadByte()); } @@ -58,8 +58,8 @@ namespace csharp { } virtual char ReadChar(bool twoBytesPerChar = false); - - virtual int16_t ReadInt16() { + + virtual int16_t ReadInt16() { return ReadNumeric(); } @@ -141,7 +141,7 @@ namespace csharp { { throw EndOfStreamException(SR::IO_EOF_ReadBeyondEOF); } - + const auto chars = reinterpret_cast(charBytes.data()); if (currPos == 0 && n == stringLength) @@ -165,11 +165,11 @@ namespace csharp { template TNUMERIC ReadNumeric() { - const auto numericSize = sizeof(TNUMERIC); - + const auto numericSize = sizeof(TNUMERIC); + if (_auxBuffer.size() != numericSize) _auxBuffer.resize(numericSize); - + InternalRead(_auxBuffer); const auto ptr = reinterpret_cast(_auxBuffer.data()); @@ -182,19 +182,20 @@ namespace csharp { std::shared_ptr _stream; bool _leaveOpen; - bool _disposed{false}; + bool _disposed{ false }; - std::vector _auxBuffer; + std::vector _auxBuffer; }; class BinaryWriter { public: BinaryWriter(std::shared_ptr const& output) - : BinaryWriter(output, false) { } + : BinaryWriter(output, false) { + } BinaryWriter(std::shared_ptr const& output, bool leaveOpen) { ArgumentNullException::ThrowIfNull(output.get(), "output"); - + if (!output->CanWrite()) throw ArgumentException(SR::Argument_StreamNotWritable); @@ -242,13 +243,82 @@ namespace csharp { OutStream->Write(buffer, bufferLength, index, count); } - virtual void Write(char ch); + inline virtual void Write(char ch) { + const auto byte = static_cast(ch); + OutStream->Write(&byte, 1); + } + + inline virtual void Write(char* chars, int32_t charsLength) { + ArgumentNullException::ThrowIfNull(chars, "chars"); + auto bytes = reinterpret_cast(chars); + OutStream->Write(bytes, charsLength); + } + + inline virtual void Write(char* chars, int32_t charsLength, int32_t index, int32_t count) { + ArgumentNullException::ThrowIfNull(chars, "chars"); + ArgumentOutOfRangeException::ThrowIfNegative(index, "index"); + ArgumentOutOfRangeException::ThrowIfNegative(count, "count"); + + if (index > charsLength - count) + throw ArgumentOutOfRangeException("index"); + + auto bytes = reinterpret_cast(chars); + OutStream->Write(bytes, charsLength, index, count); + } + + inline virtual void Write(double value) { + WriteNumeric(value); + } + + inline virtual void Write(int16_t value) { + WriteNumeric(value); + } + + inline virtual void Write(uint16_t value) { + WriteNumeric(value); + } + + inline virtual void Write(int32_t value) { + WriteNumeric(value); + } + + inline virtual void Write(uint32_t value) { + WriteNumeric(value); + } + + inline virtual void Write(int64_t value) { + WriteNumeric(value); + } + + inline virtual void Write(uint64_t value) { + WriteNumeric(value); + } + + inline virtual void Write(float value) { + WriteNumeric(value); + } + + virtual void Write(std::string const& value) { + Write7BitEncodedInt(static_cast(value.size())); + auto bytes = reinterpret_cast(value.data()); + OutStream->Write(bytes, value.size()); + } + + void Write7BitEncodedInt(int32_t value); + void Write7BitEncodedInt(int64_t value); protected: BinaryWriter() { OutStream = Stream::Null; } + template + void WriteNumeric(TNUMERIC const& value) { + auto bytes = reinterpret_cast(&value); + const auto size = sizeof(value); + OutStream->Write(bytes, static_cast(size)); + } + protected: std::shared_ptr OutStream; diff --git a/includes/csharp/text/unicode.hpp b/includes/csharp/text/unicode.hpp index 50bc9c5..2365d1e 100644 --- a/includes/csharp/text/unicode.hpp +++ b/includes/csharp/text/unicode.hpp @@ -2,6 +2,13 @@ #define CSHARP_TEXT_UNICODE_HPP #include +#include +#include "csharp/exception.hpp" + +// +// The char type keyword is an alias for the .NET System.Char structure type that represents a Unicode UTF-16 character. +// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/char +// namespace csharp { struct UnicodeUtility { @@ -48,11 +55,6 @@ namespace csharp { static constexpr bool IsAsciiCodePoint(uint32_t value) { return value <= 0x7Fu; } - - // Returns true if value is in the Basic Multilingual Plane (BMP - static constexpr bool IsAsciiCodePoint(uint32_t value) { - return value <= 0xFFFFu; - } //Returns true if is a UTF-16 high surrogate code point, i.e., is in [ U+D800..U+DBFF ], inclusive. static constexpr bool IsHighSurrogateCodePoint(uint32_t value) { @@ -60,7 +62,7 @@ namespace csharp { } //Returns true if is between - static consexpr bool IsInRangeInclusive(uint32_t value, uint32_t lowerBound, uint32_t upperBound) { + static constexpr bool IsInRangeInclusive(uint32_t value, uint32_t lowerBound, uint32_t upperBound) { return (value - lowerBound) <= (upperBound - lowerBound); } @@ -75,7 +77,7 @@ namespace csharp { } //Returns true if value is a valid Unicode code point, i.e., is in [ U+0000..U+10FFFF ], inclusive. - static constexpr bool IsValidCodePoint(uint32_t value) { + static constexpr bool IsValidCodePoint(uint32_t codePoint) { return codePoint <= 0x10FFFFU; } diff --git a/samples/01_blank/xna.cpp b/samples/01_blank/xna.cpp index 5f36356..8824a75 100644 --- a/samples/01_blank/xna.cpp +++ b/samples/01_blank/xna.cpp @@ -11,26 +11,7 @@ namespace xna { class Game1 : public Game { public: Game1() : Game() { - Content()->RootDirectory("Content"); - - short inteiro = 0xC3 | 0xA7; - char charpa = inteiro; - - auto stream = std::make_shared("D:/file.bin", csharp::FileMode::Open); - auto reader = csharp::BinaryReader(stream); - auto bo = reader.ReadBoolean(); //reader.ReadChar() - auto x = reader.ReadChar(); //x - auto cedilha = reader.ReadChar8(); //ç - auto sb = reader.ReadSByte(); //127 - auto by = reader.ReadByte(); //255 - auto i16 = reader.ReadInt16(); //32767 - auto ui16 = reader.ReadUInt16();//65535 - auto i32 = reader.ReadInt32(); //2147483647 - auto ui32 = reader.ReadUInt32(); //4294967295 - auto i64 = reader.ReadInt64(); //9223372036854775807 - auto ui64 = reader.ReadUInt64(); //18446744073709551615 - auto str = reader.ReadString(); //The string in stream. - auto str2 = reader.ReadString8(); //Ç de cedilha e ñ com til mas sem ¨ trema. + Content()->RootDirectory("Content"); } void Initialize() override { diff --git a/sources/csharp/io/binary.cpp b/sources/csharp/io/binary.cpp index 1e4f1d9..7fa4e3d 100644 --- a/sources/csharp/io/binary.cpp +++ b/sources/csharp/io/binary.cpp @@ -1,6 +1,7 @@ #include "csharp/io/binary.hpp" #include #include +#include "csharp/text/unicode.hpp" namespace csharp { int32_t BinaryReader::PeekChar() { @@ -82,7 +83,7 @@ namespace csharp { return static_cast(b); } - char BinaryReader::ReadChar(bool twoBytes = false) { + char BinaryReader::ReadChar(bool twoBytes) { const auto value = Read(twoBytes); if (value == -1) @@ -295,4 +296,28 @@ namespace csharp { result |= static_cast(byteReadJustNow) << (MaxBytesWithoutOverflow * 7); return static_cast(result); } + + void BinaryWriter::Write7BitEncodedInt(int32_t value) { + auto uValue = static_cast(value); + + while (uValue > 0x7Fu) + { + Write(static_cast(uValue | ~0x7Fu)); + uValue >>= 7; + } + + Write(static_cast(uValue)); + } + + void BinaryWriter::Write7BitEncodedInt(int64_t value) { + auto uValue = static_cast(value); + + while (uValue > 0x7Fu) + { + Write(static_cast(uValue | ~0x7Fu)); + uValue >>= 7; + } + + Write(static_cast(uValue)); + } } \ No newline at end of file