#include "csharp/io/binary.hpp" #include #include #include "csharp/text/unicode.hpp" 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(bool twoBytesPerChar) { if (_disposed) throw InvalidOperationException(); int32_t charsRead = 0; int32_t numBytes; int64_t posSav = 0; if (_stream->CanSeek()) { posSav = _stream->Position(); } char singleChar = '\0'; while (charsRead == 0) { numBytes = twoBytesPerChar ? 2 : 1; auto r = _stream->ReadByte(); if (r == -1) { numBytes = 0; } if (numBytes == 2) { auto r2 = _stream->ReadByte(); r |= r2; if (r == -1) { numBytes = 1; } } if (numBytes == 0) { return -1; } const char chars = r; 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(b); } char BinaryReader::ReadChar(bool twoBytes) { const auto value = Read(twoBytes); if (value == -1) { throw EndOfStreamException(SR::IO_EOF_ReadBeyondEOF); } return static_cast(value); } void BinaryReader::InternalRead(std::vector& buffer) { if (_disposed) throw InvalidOperationException(); _stream->ReadExactly(buffer.data(), buffer.size()); } std::string BinaryReader::ReadString() { return GenericReadString(); } std::u8string BinaryReader::ReadString8() { return GenericReadString(); } 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(MaxCharBytesSize); auto numBytes = bufferLength; while (bufferLength > 0) { auto numBytes = bufferLength; std::vector byteBuffer; if (numBytes > MaxCharBytesSize) { numBytes = MaxCharBytesSize; } numBytes = _stream->Read(charBytes.data(), numBytes); byteBuffer = std::vector(charBytes.begin(), charBytes.begin() + numBytes); if (byteBuffer.empty()) { break; } auto chars = reinterpret_cast(byteBuffer.data()); auto charsRead = std::string(chars); bufferLength = charsRead.length(); totalCharsRead += charsRead.length(); } return totalCharsRead; } std::vector BinaryReader::ReadChars(int32_t count) { if (count < 0) throw ArgumentOutOfRangeException(); if (_disposed) throw InvalidOperationException(); if (count == 0) return std::vector(); auto chars = std::vector(count); const auto n = InternalReadChars(chars.data(), chars.size()); if (n != count) { chars = std::vector(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 BinaryReader::ReadBytes(int32_t count) { ArgumentOutOfRangeException::ThrowIfNegative(count, "count"); if (_disposed) throw InvalidOperationException(); if (count == 0) return std::vector(); auto result = std::vector(count); const auto numRead = _stream->ReadAtLeast(result.data(), result.size(), result.size(), false); if (numRead != result.size()) { result = std::vector(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(result); } } byteReadJustNow = ReadByte(); if (byteReadJustNow > 15u) { //FormatException throw InvalidOperationException(SR::Format_Bad7BitInt); } result |= static_cast(byteReadJustNow) << (MaxBytesWithoutOverflow * 7); return static_cast(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(result); } } byteReadJustNow = ReadByte(); if (byteReadJustNow > 1u) { //FormatException throw InvalidOperationException(SR::Format_Bad7BitInt); } 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)); } }