1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

Correnções em BinaryReader

This commit is contained in:
Danilo Borges Santos 2024-12-06 13:50:32 -03:00
parent 75d5dd5011
commit 764184341a
9 changed files with 509 additions and 17 deletions

View File

@ -231,8 +231,8 @@ namespace csharp {
HRresult = HResults::HR_E_POINTER;
}
static void ThrowIfNull(void* argument, OptionalString const& paramName, std::source_location const& source = std::source_location::current()) {
if (!argument)
static void ThrowIfNull(void const* argument, OptionalString const& paramName, std::source_location const& source = std::source_location::current()) {
if (argument == nullptr)
{
throw ArgumentNullException(paramName, source);
}
@ -245,17 +245,23 @@ namespace csharp {
ArgumentOutOfRangeException(OptionalString const& message = std::nullopt, std::source_location const& source = std::source_location::current())
: ArgumentOutOfRangeException(message, std::nullopt, nullptr, source) { }
ArgumentOutOfRangeException(OptionalString const& message, OptionalString const& paramName, std::source_location const& source = std::source_location::current())
: ArgumentOutOfRangeException(message, paramName, nullptr, source) { }
ArgumentOutOfRangeException(OptionalString const& paramName, OptionalString const& message, std::source_location const& source = std::source_location::current())
: ArgumentOutOfRangeException(paramName, message, nullptr, source) { }
ArgumentOutOfRangeException(OptionalString const& message, std::shared_ptr<Exception> const& innerException, std::source_location const& source = std::source_location::current())
: ArgumentOutOfRangeException(message, std::nullopt, innerException, source) { }
ArgumentOutOfRangeException(OptionalString const& message, OptionalString const& paramName, std::shared_ptr<Exception> const& innerException, std::source_location const& source = std::source_location::current())
: ArgumentException(message.value_or(SR::Arg_ArgumentOutOfRangeException), paramName, innerException, source)
ArgumentOutOfRangeException(OptionalString const& paramName, OptionalString const& message, std::shared_ptr<Exception> const& innerException, std::source_location const& source = std::source_location::current())
: ArgumentException(paramName, message.value_or(SR::Arg_ArgumentOutOfRangeException), innerException, source)
{
HRresult = HResults::HR_E_POINTER;
}
}
template <typename T>
static void ThrowIfNegative(T& value, OptionalString const& paramName, std::source_location const& source = std::source_location::current()) {
if (value < 0)
throw ArgumentOutOfRangeException(paramName, source);
}
};
class SystemException : public Exception {

View File

@ -4,25 +4,135 @@
#include "stream.hpp"
#include "exception.hpp"
#include <optional>
#include <cstdint>
namespace csharp {
/*
* 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.
*/
//The BinaryReader class uses byte encodings, by default UTF8
class BinaryReader {
public:
BinaryReader(std::shared_ptr<Stream> input, bool leaveOpen = false)
BinaryReader(std::shared_ptr<Stream> const& input, bool leaveOpen = false)
: _stream(input), _leaveOpen(leaveOpen)
{
if (input == nullptr)
throw csharp::ArgumentNullException(std::nullopt, "input");
ArgumentNullException::ThrowIfNull(input.get(), "input");
if (!input->CanRead())
throw ArgumentException(SR::Argument_StreamNotReadable);
}
virtual std::shared_ptr<Stream> BaseStream() const { return _stream; }
virtual void Close() {
if (_disposed)
return;
if (!_leaveOpen)
_stream->Close();
_disposed = true;
}
virtual int32_t PeekChar();
virtual int32_t Read();
virtual uint8_t ReadByte() {
return InternalReadByte();
}
virtual inline int8_t ReadSByte() {
return static_cast<int8_t>(InternalReadByte());
}
virtual inline bool ReadBoolean() {
return InternalReadByte() != 0;
}
virtual char ReadChar();
virtual int16_t ReadInt16() {
return ReadNumeric<int16_t>();
}
virtual uint16_t ReadUInt16() {
return ReadNumeric<uint16_t>();
}
virtual int32_t ReadInt32() {
return ReadNumeric<int32_t>();
}
virtual uint32_t ReadUInt32() {
return ReadNumeric<uint32_t>();
}
virtual int64_t ReadInt64() {
return ReadNumeric<int64_t>();
}
virtual uint64_t ReadUInt64() {
return ReadNumeric<uint64_t>();
}
virtual float ReadSingle() {
return ReadNumeric<float>();
}
virtual double ReadDouble() {
return ReadNumeric<double>();
}
virtual std::string ReadString();
virtual int32_t Read(char* buffer, int32_t bufferLength, int32_t index, int32_t count);
virtual int32_t Read(char* buffer, int32_t bufferLength);
virtual std::vector<char> ReadChars(int32_t count);
virtual int32_t Read(uint8_t* buffer, int32_t bufferLength, int32_t index, int32_t count);
virtual int32_t Read(uint8_t* buffer, int32_t bufferLength);
virtual std::vector<uint8_t> ReadBytes(int32_t count);
virtual void ReadExactly(uint8_t* buffer, int32_t bufferLength);
int32_t Read7BitEncodedInt();
int64_t Read7BitEncodedInt64();
private:
uint8_t InternalReadByte();
void InternalRead(std::vector<uint8_t>& buffer);
int32_t InternalReadChars(char* buffer, int32_t bufferLength);
template<class TNUMERIC>
TNUMERIC ReadNumeric() {
const auto numericSize = sizeof(TNUMERIC);
if (_auxBuffer.size() != numericSize)
_auxBuffer.resize(numericSize);
InternalRead(_auxBuffer);
const auto ptr = reinterpret_cast<TNUMERIC*>(_auxBuffer.data());
const auto value = *ptr;
return value;
}
private:
static constexpr int MaxCharBytesSize = 128;
std::shared_ptr<Stream> _stream;
bool _leaveOpen;
bool _disposed{false};
bool _2BytesPerChar{ false };
std::vector<uint8_t> _auxBuffer;
};
}

View File

@ -60,13 +60,21 @@ namespace csharp {
virtual int32_t Read(uint8_t* buffer, int32_t bufferLength);
virtual int32_t ReadByte();
virtual int32_t ReadExactly(uint8_t* buffer, int32_t bufferLength, int32_t offset, int32_t count) {
return ReadAtLeastCore(buffer, bufferLength, bufferLength, true);
void ReadExactly(uint8_t* buffer, int32_t bufferLength) {
ReadAtLeastCore(buffer, bufferLength, bufferLength, true);
}
virtual void ReadExactly(uint8_t* buffer, int32_t offset, int32_t count) {
ReadAtLeastCore(buffer + offset, count, count, true);
}
int32_t ReadAtLeast(uint8_t* buffer, int32_t bufferLength, int32_t minimumBytes, bool throwOnEndOfStream = true) {
return ReadAtLeastCore(buffer, bufferLength, minimumBytes, throwOnEndOfStream);
}
virtual void Write(uint8_t const* buffer, int32_t bufferLength, int32_t offset, int32_t count) = 0;
virtual void Write(uint8_t const* buffer, int32_t bufferLength);
virtual void WriteByte(uint8_t value);
virtual void WriteByte(uint8_t value) = 0;
protected:
void ValidateBuffer(uint8_t const* buffer, int32_t bufferLength);

View File

@ -50,7 +50,13 @@ namespace csharp {
inline static const std::string ArgumentOutOfRange_StreamLength
= "Stream length must be non-negative and less than 2^31 - 1 - origin.";
inline static const std::string net_uri_NotAbsolute
= "This operation is not supported for a relative URI.";
= "This operation is not supported for a relative URI.";
inline static const std::string Argument_StreamNotReadable
= "Stream was not readable.";
inline static const std::string Format_Bad7BitInt
= "Too many bytes in what should have been a 7-bit encoded integer.";
inline static const std::string IO_InvalidStringLen_Len
= "BinaryReader encountered an invalid string length.";
};
};

View File

@ -10,4 +10,4 @@ if (CMAKE_VERSION VERSION_GREATER 3.12)
endif()
# TODO: Add tests and install targets if needed.
target_link_libraries(BlankApp Xn65DX)
target_link_libraries(BlankApp Xn65DX CSharp++)

View File

@ -2,6 +2,7 @@
//
#include "xna-dx/framework.hpp"
#include "csharp/io/binary.hpp"
using namespace std;
using namespace xna;
@ -11,6 +12,21 @@ namespace xna {
public:
Game1() : Game() {
Content()->RootDirectory("Content");
auto stream = std::make_shared<csharp::FileStream>("D:/file.bin", csharp::FileMode::Open);
auto reader = csharp::BinaryReader(stream);
auto bo = reader.ReadBoolean(); //reader.ReadChar()
auto sb = reader.ReadSByte(); //127
auto by = reader.ReadByte(); //255
auto ch = reader.ReadChar(); //x
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.ReadString(); //Ç de cedilha e ñ com til mas sem ¨ trema.
}
void Initialize() override {

View File

@ -5,7 +5,7 @@
# Add source to this project's executable.
add_library (CSharp++ STATIC
"exception.cpp"
"io/stream.cpp")
"io/stream.cpp" "io/binary.cpp")
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET CSharp++ PROPERTY CXX_STANDARD 20)

View File

@ -0,0 +1,345 @@
#include "csharp/io/binary.hpp"
#include <vector>
#include <cstdint>
namespace csharp {
int32_t BinaryReader::PeekChar() {
if (_disposed)
throw InvalidOperationException();
if (!_stream->CanSeek())
{
return -1;
}
const auto origPos = _stream->Position();
const auto ch = Read();
_stream->Position(origPos);
return ch;
}
int32_t BinaryReader::Read() {
if (_disposed)
throw InvalidOperationException();
int32_t charsRead = 0;
int32_t numBytes;
int64_t posSav = 0;
if (_stream->CanSeek())
{
posSav = _stream->Position();
}
auto charBytes = std::vector<uint8_t>(MaxCharBytesSize);
char singleChar = '\0';
while (charsRead == 0) {
numBytes = _2BytesPerChar ? 2 : 1;
auto r = _stream->ReadByte();
charBytes[0] = static_cast<uint8_t>(r);
if (r == -1)
{
numBytes = 0;
}
if (numBytes == 2)
{
r = _stream->ReadByte();
charBytes[1] = static_cast<uint8_t>(r);
if (r == -1)
{
numBytes = 1;
}
}
if (numBytes == 0)
{
return -1;
}
const auto chars = reinterpret_cast<char*>(charBytes.data());
const auto decoder = std::string(chars);
charsRead = decoder.size();
singleChar = decoder[0];
}
return singleChar;
}
uint8_t BinaryReader::InternalReadByte() {
if (_disposed)
throw InvalidOperationException();
const auto b = _stream->ReadByte();
if (b == -1)
{
throw EndOfStreamException(SR::IO_EOF_ReadBeyondEOF);
}
return static_cast<uint8_t>(b);
}
char BinaryReader::ReadChar() {
const auto value = Read();
if (value == -1)
{
throw EndOfStreamException(SR::IO_EOF_ReadBeyondEOF);
}
return static_cast<char>(value);
}
void BinaryReader::InternalRead(std::vector<uint8_t>& buffer) {
if (_disposed)
throw InvalidOperationException();
_stream->ReadExactly(buffer.data(), buffer.size());
}
std::string BinaryReader::ReadString() {
if (_disposed)
throw InvalidOperationException();
const auto stringLength = Read7BitEncodedInt();
if (stringLength < 0)
{
throw IOException(SR::IO_InvalidStringLen_Len);
}
if (stringLength == 0)
{
return {};
}
auto charBytes = std::vector<uint8_t>(MaxCharBytesSize);
int32_t currPos = 0;
std::string sb;
do
{
const auto readLength = std::min(MaxCharBytesSize, stringLength - currPos);
const auto n = _stream->Read(charBytes.data(), readLength);
if (n == 0)
{
throw EndOfStreamException(SR::IO_EOF_ReadBeyondEOF);
}
const auto chars = reinterpret_cast<char*>(charBytes.data());
if (currPos == 0 && n == stringLength)
{
return std::string(chars);
}
sb.append(chars);
currPos += n;
} while (currPos < stringLength);
return sb;
}
int32_t BinaryReader::Read(char* buffer, int32_t bufferLength, int32_t index, int32_t count) {
ArgumentNullException::ThrowIfNull(buffer, "buffer");
if (index < 0)
index = 0;
if (count < 0)
count = 0;
if (bufferLength - index < count) {
throw ArgumentException(SR::Argument_InvalidOffLen);
}
if (_disposed)
throw InvalidOperationException();
return InternalReadChars(buffer + index, count);
}
int32_t BinaryReader::Read(char* buffer, int32_t bufferLength) {
if (_disposed)
throw InvalidOperationException();
return InternalReadChars(buffer, bufferLength);
}
int32_t BinaryReader::InternalReadChars(char* buffer, int32_t bufferLength) {
int totalCharsRead = 0;
auto charBytes = std::vector<uint8_t>(MaxCharBytesSize);
auto numBytes = bufferLength;
while (bufferLength > 0)
{
auto numBytes = bufferLength;
if (_2BytesPerChar)
{
numBytes <<= 1;
}
std::vector<uint8_t> byteBuffer;
if (numBytes > MaxCharBytesSize)
{
numBytes = MaxCharBytesSize;
}
numBytes = _stream->Read(charBytes.data(), numBytes);
byteBuffer = std::vector<uint8_t>(charBytes.begin(), charBytes.begin() + numBytes);
if (byteBuffer.empty())
{
break;
}
auto chars = reinterpret_cast<char*>(byteBuffer.data());
auto charsRead = std::string(chars);
bufferLength = charsRead.length();
totalCharsRead += charsRead.length();
}
// we may have read fewer than the number of characters requested if end of stream reached
// or if the encoding makes the char count too big for the buffer (e.g. fallback sequence)
return totalCharsRead;
}
std::vector<char> BinaryReader::ReadChars(int32_t count) {
if (count < 0)
throw ArgumentOutOfRangeException();
if (_disposed)
throw InvalidOperationException();
if (count == 0)
return std::vector<char>();
auto chars = std::vector<char>(count);
const auto n = InternalReadChars(chars.data(), chars.size());
if (n != count) {
chars = std::vector<char>(chars.begin(), chars.begin() + count);
}
return chars;
}
int32_t BinaryReader::Read(uint8_t* buffer, int32_t bufferLength, int32_t index, int32_t count) {
ArgumentNullException::ThrowIfNull(buffer, "buffer");
ArgumentOutOfRangeException::ThrowIfNegative(index, "index");
ArgumentOutOfRangeException::ThrowIfNegative(count, "count");
if (bufferLength - index < count) {
throw ArgumentException(SR::Argument_InvalidOffLen);
}
if (_disposed)
throw InvalidOperationException();
return _stream->Read(buffer, bufferLength, index, count);
}
int32_t BinaryReader::Read(uint8_t* buffer, int32_t bufferLength) {
if (_disposed)
throw InvalidOperationException();
return _stream->Read(buffer, bufferLength);
}
std::vector<uint8_t> BinaryReader::ReadBytes(int32_t count) {
ArgumentOutOfRangeException::ThrowIfNegative(count, "count");
if (_disposed)
throw InvalidOperationException();
if (count == 0)
return std::vector<uint8_t>();
auto result = std::vector<uint8_t>(count);
const auto numRead = _stream->ReadAtLeast(result.data(), result.size(), result.size(), false);
if (numRead != result.size())
{
result = std::vector<uint8_t>(result.begin(), result.begin() + numRead);
}
return result;
}
void BinaryReader::ReadExactly(uint8_t* buffer, int32_t bufferLength) {
if (_disposed)
throw InvalidOperationException();
_stream->ReadExactly(buffer, bufferLength);
}
int32_t BinaryReader::Read7BitEncodedInt() {
uint32_t result = 0;
uint8_t byteReadJustNow;
constexpr int32_t MaxBytesWithoutOverflow = 4;
for (int32_t shift = 0; shift < MaxBytesWithoutOverflow * 7; shift += 7)
{
byteReadJustNow = ReadByte();
result |= (byteReadJustNow & 0x7Fu) << shift;
if (byteReadJustNow <= 0x7Fu)
{
return static_cast<int32_t>(result);
}
}
byteReadJustNow = ReadByte();
if (byteReadJustNow > 15u)
{
//FormatException
throw InvalidOperationException(SR::Format_Bad7BitInt);
}
result |= static_cast<uint32_t>(byteReadJustNow) << (MaxBytesWithoutOverflow * 7);
return static_cast<int32_t>(result);
}
int64_t BinaryReader::Read7BitEncodedInt64() {
uint64_t result = 0;
uint8_t byteReadJustNow;
constexpr int32_t MaxBytesWithoutOverflow = 9;
for (int32_t shift = 0; shift < MaxBytesWithoutOverflow * 7; shift += 7)
{
byteReadJustNow = ReadByte();
result |= (byteReadJustNow & 0x7Ful) << shift;
if (byteReadJustNow <= 0x7Fu)
{
return static_cast<int64_t>(result);
}
}
byteReadJustNow = ReadByte();
if (byteReadJustNow > 1u)
{
//FormatException
throw InvalidOperationException(SR::Format_Bad7BitInt);
}
result |= static_cast<int64_t>(byteReadJustNow) << (MaxBytesWithoutOverflow * 7);
return static_cast<int64_t>(result);
}
}

View File

@ -684,7 +684,8 @@ namespace csharp {
return -1;
}
const auto result = static_cast<int32_t>(c);
const auto uchar = static_cast<unsigned char>(c);
const auto result = static_cast<int32_t>(uchar);
return result;
}