1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00
xn65/sources/csharp/io/binary.cpp
2024-12-13 13:40:51 -03:00

323 lines
8.5 KiB
C++

#include "csharp/io/binary.hpp"
#include <vector>
#include <cstdint>
#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<uint8_t>(b);
}
char BinaryReader::ReadChar(bool twoBytes) {
const auto value = Read(twoBytes);
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() {
return GenericReadString<std::string>();
}
std::u8string BinaryReader::ReadString8() {
return GenericReadString<std::u8string>();
}
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;
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();
}
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);
}
void BinaryWriter::Write7BitEncodedInt(int32_t value) {
auto uValue = static_cast<uint32_t>(value);
while (uValue > 0x7Fu)
{
Write(static_cast<uint8_t>(uValue | ~0x7Fu));
uValue >>= 7;
}
Write(static_cast<uint8_t>(uValue));
}
void BinaryWriter::Write7BitEncodedInt(int64_t value) {
auto uValue = static_cast<uint32_t>(value);
while (uValue > 0x7Fu)
{
Write(static_cast<uint8_t>(uValue | ~0x7Fu));
uValue >>= 7;
}
Write(static_cast<uint8_t>(uValue));
}
}