#include "csharp/binary.hpp" #include "csharp/buffer.hpp" namespace xna { Int BinaryReader::PeekChar(xna_error_ptr_arg) { if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } const auto position = stream->Position(); const auto num = Read(err); if (xna_error_haserros(err)) return -1; stream->Seek(position, SeekOrigin::Begin, err); if (xna_error_haserros(err)) return -1; return num; } Int BinaryReader::Read(xna_error_ptr_arg) { if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } const auto result = InternalReadOneChar(err); return xna_error_haserros(err) ? -1 : result; } bool BinaryReader::ReadBoolean(xna_error_ptr_arg) { FillBuffer(1, err); return xna_error_haserros(err) ? false : buffer[0] > 0; } Byte BinaryReader::ReadByte(xna_error_ptr_arg) { if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } const auto num = stream->ReadByte(); if (num == -1) { xna_error_apply(err, XnaErrorCode::END_OF_FILE); return 0; } return static_cast(num); } Sbyte BinaryReader::ReadSByte(xna_error_ptr_arg) { FillBuffer(1, err); return xna_error_haserros(err) ? -1 : static_cast(buffer[0]); } Char BinaryReader::ReadChar(xna_error_ptr_arg) { auto num = Read(err); if (xna_error_haserros(err) || num == -1) return '\0'; return static_cast(num); } Short BinaryReader::ReadInt16(xna_error_ptr_arg) { FillBuffer(2, err); if (xna_error_haserros(err)) return -1; return static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8); } Ushort BinaryReader::ReadUInt16(xna_error_ptr_arg) { FillBuffer(2, err); if (xna_error_haserros(err)) return 0; return static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8); } Int BinaryReader::ReadInt32(xna_error_ptr_arg) { FillBuffer(4, err); if (xna_error_haserros(err)) return -1; return static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 16 | static_cast(buffer[3]) << 24; } Uint BinaryReader::ReadUInt32(xna_error_ptr_arg) { FillBuffer(4, err); if (xna_error_haserros(err)) return -1; return static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 16 | static_cast(buffer[3]) << 24); } Long BinaryReader::ReadInt64(xna_error_ptr_arg) { FillBuffer(8, err); if (xna_error_haserros(err)) return -1; const auto num1 = static_cast( static_cast(buffer[4]) | static_cast(buffer[5]) << 8 | static_cast(buffer[6]) << 16 | static_cast(buffer[7]) << 24); const auto num2 = static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 16 | static_cast(buffer[3]) << 24); return static_cast(num1) << 32 | static_cast(num2); } Ulong BinaryReader::ReadUInt64(xna_error_ptr_arg) { FillBuffer(8, err); if (xna_error_haserros(err)) return 0; const auto num1 = static_cast( static_cast(buffer[4]) | static_cast(buffer[5]) << 8 | static_cast(buffer[6]) << 16 | static_cast(buffer[7]) << 24); const auto num2 = static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 16 | static_cast(buffer[3]) << 24); return static_cast(num1) << 32 | static_cast(num2); } float BinaryReader::ReadSingle(xna_error_ptr_arg) { FillBuffer(4, err); if (xna_error_haserros(err)) return std::numeric_limits::quiet_NaN(); const auto num = static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 16 | static_cast(buffer[3]) << 24); return *(float*)# } double BinaryReader::ReadDouble(xna_error_ptr_arg) { FillBuffer(8, err); if (xna_error_haserros(err)) return std::numeric_limits::quiet_NaN(); const auto num1 = static_cast( static_cast(buffer[4]) | static_cast(buffer[5]) << 8 | static_cast(buffer[6]) << 16 | static_cast(buffer[7]) << 24); const auto num2 = static_cast( static_cast(buffer[0]) | static_cast(buffer[1]) << 8 | static_cast(buffer[2]) << 6 | static_cast(buffer[3]) << 24); const auto num3 = static_cast(num1) << 32 | static_cast(num2); return *(double*)&num3; } std::string BinaryReader::ReadString(xna_error_ptr_arg) { static const auto empty = std::string(); if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return std::string(); } Int num = 0; auto val1 = Read7BitEncodedInt(err); if (xna_error_haserros(err)) return empty; if (val1 < 0) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return empty; } if (val1 == 0) return empty; if (charBytes.empty()) charBytes.resize(maxCharBytesSize); if (charBuffer.empty()) charBuffer.resize(maxCharBytesSize); std::string sb; do { const auto byteCount = stream->Read(charBytes, 0, val1 - num > 128 ? 128 : val1 - num); if (byteCount == 0) { xna_error_apply(err, XnaErrorCode::END_OF_FILE); return empty; } auto data = reinterpret_cast(charBytes.data()); const auto result = std::string(data); if (num == 0 && byteCount == val1) { return result; } sb.append(result); num += byteCount; } while (num < val1); return sb; } Int BinaryReader::InternalReadOneChar(xna_error_ptr_arg) { Int num1 = 0; Long num2 = 0; Long num3 = stream->Position(); if (charBytes.empty()) charBytes.resize(128); if (singleChar.empty()) singleChar.resize(1); while (num1 == 0) { auto byteCount = m2BytesPerChar ? 2 : 1; const auto num4 = stream->ReadByte(); charBytes[0] = static_cast(num4); if (num4 == -1) byteCount = 0; if (byteCount == 2) { auto num5 = stream->ReadByte(); charBytes[1] = static_cast(num5); if (num5 == -1) byteCount = 1; } if (byteCount == 0) { return -1; } auto data = reinterpret_cast(charBytes.data()); const auto result = std::string(data, data + byteCount); if (!result.empty()) { num1 = static_cast(result.size()); singleChar[0] = result[0]; } } return num1 == 0 ? -1 : static_cast(singleChar[0]); } void BinaryReader::FillBuffer(Int numBytes, xna_error_ptr_arg) { if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } if (!buffer.empty() && (numBytes < 0 || numBytes > buffer.size())) { xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE); return; } int offset = 0; if (numBytes == 1) { const auto num = stream->ReadByte(); if (num == -1) { xna_error_apply(err, XnaErrorCode::END_OF_FILE); return; } buffer[0] = static_cast(num); } else { do { const auto num = stream->Read(buffer, offset, numBytes - offset); if (num == 0) { xna_error_apply(err, XnaErrorCode::END_OF_FILE); return; } offset += num; } while (offset < numBytes); } } Int BinaryReader::InternalReadChars(Char* buffer, size_t bufferSize, size_t index, size_t count, xna_error_ptr_arg) { auto charCount = count; if (charBytes.empty()) charBytes.resize(128); while (charCount > 0) { auto count1 = charCount; if (count1 > 1) --count1; if (m2BytesPerChar) count1 <<= 1; if (count1 > 128) count1 = 128; Int position = 0; Int byteCount; std::vector numArray; byteCount = stream->Read(charBytes, 0, static_cast(count1), err); numArray = charBytes; if (byteCount == 0) return static_cast(count - charCount); if (position < 0 || byteCount < 0 || (position + byteCount) > numArray.size()) { xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE); return -1; } if (index < 0 || charCount < 0 || (index + charCount) > bufferSize) { xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE); return -1; } auto data = reinterpret_cast(charBytes.data()); auto pChars = reinterpret_cast(buffer); //const auto result = std::string((data + position), (pChars + index) + byteCount); const auto result = std::string((data + position), (data + position) + byteCount); Buffer::BlockCopy(result.c_str(), position, pChars, index, byteCount); buffer = reinterpret_cast(pChars); const auto chars = static_cast(result.size()); charCount -= chars; index += chars; } return static_cast(count - charCount); } Long BinaryWriter::Seek(Int offset, SeekOrigin origin, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } return _stream->Seek(offset, origin); } void BinaryWriter::Write(bool value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = value ? (Byte)1 : (Byte)0; _stream->Write(_buffer, 0, 1); } void BinaryWriter::Write(Byte value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->WriteByte(value); } void BinaryWriter::Write(Sbyte value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->WriteByte(static_cast(value)); } void BinaryWriter::Write(Byte const* buffer, Int bufferLength, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->Write(buffer, bufferLength, 0, bufferLength); } void BinaryWriter::Write(std::vector const& buffer, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->Write(buffer, 0, static_cast(buffer.size())); } void BinaryWriter::Write(Byte const* buffer, Int bufferLength, Int index, Int count, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->Write(buffer, bufferLength, index, count); } void BinaryWriter::Write(std::vector const& buffer, Int index, Int count, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _stream->Write(buffer, index, count); } void BinaryWriter::Write(Char ch, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(ch); _stream->Write(_buffer, 0, 1); } void BinaryWriter::Write(double value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } Ulong num = (Ulong) * (Long*)&value; _buffer[0] = static_cast(num); _buffer[1] = static_cast(num >> 8); _buffer[2] = static_cast(num >> 16); _buffer[3] = static_cast(num >> 24); _buffer[4] = static_cast(num >> 32); _buffer[5] = static_cast(num >> 40); _buffer[6] = static_cast(num >> 48); _buffer[7] = static_cast(num >> 56); _stream->Write(_buffer, 0, 8); } void BinaryWriter::Write(Short value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast((Uint)value >> 8); _stream->Write(_buffer, 0, 2); } void BinaryWriter::Write(Ushort value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast((Uint)value >> 8); _stream->Write(_buffer, 0, 2); } void BinaryWriter::Write(Int value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast(value >> 8); _buffer[2] = static_cast(value >> 16); _buffer[3] = static_cast(value >> 24); _stream->Write(_buffer, 0, 4); } void BinaryWriter::Write(Uint value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast(value >> 8); _buffer[2] = static_cast(value >> 16); _buffer[3] = static_cast(value >> 24); _stream->Write(_buffer, 0, 4); } void BinaryWriter::Write(Ulong value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast(value >> 8); _buffer[2] = static_cast(value >> 16); _buffer[3] = static_cast(value >> 24); _buffer[4] = static_cast(value >> 32); _buffer[5] = static_cast(value >> 40); _buffer[6] = static_cast(value >> 48); _buffer[7] = static_cast(value >> 56); _stream->Write(_buffer, 0, 8); } void BinaryWriter::Write(float value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } Uint num = *(Uint*)&value; _buffer[0] = static_cast(num); _buffer[1] = static_cast(num >> 8); _buffer[2] = static_cast(num >> 16); _buffer[3] = static_cast(num >> 24); _stream->Write(_buffer, 0, 4); } void BinaryWriter::Write(std::string const& value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } Write(value.c_str(), value.size()); } void BinaryWriter::Write(const char* _string, size_t stringLength, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } Write7BitEncodedInt(static_cast(stringLength)); const auto b = reinterpret_cast(_string); _stream->Write(b, static_cast(stringLength), 0, static_cast(stringLength)); } void BinaryWriter::Write7BitEncodedInt(Int value) { Uint num; for (num = (Uint)value; num >= (Uint)128U; num >>= 7) Write((Byte)(num | (Uint)128U)); Write((Byte)num); } void BinaryWriter::Write(Long value, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return; } _buffer[0] = static_cast(value); _buffer[1] = static_cast(value >> 8); _buffer[2] = static_cast(value >> 16); _buffer[3] = static_cast(value >> 24); _buffer[4] = static_cast(value >> 32); _buffer[5] = static_cast(value >> 40); _buffer[6] = static_cast(value >> 48); _buffer[7] = static_cast(value >> 56); _stream->Write(_buffer, 0, 8); } Int BinaryReader::Read7BitEncodedInt(xna_error_ptr_arg) { Int num1 = 0; Int num2 = 0; while (num2 != 35) { auto num3 = ReadByte(err); if (xna_error_haserros(err)) return -1; num1 |= (static_cast(num3) & static_cast(SbyteMaxValue)) << num2; num2 += 7; if ((static_cast(num3) & 128) == 0) return num1; } xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; } Int BinaryReader::Read(std::vector& buffer, size_t index, size_t count, xna_error_ptr_arg) { return InternalReadChars(buffer.data(), buffer.size(), index, count, err); } Int BinaryReader::Read(std::vector& buffer, size_t index, size_t count, xna_error_ptr_arg) { auto data = reinterpret_cast(buffer.data()); return InternalReadChars(data, buffer.size(), index, count, err); } std::vector BinaryReader::ReadBytes(size_t count, xna_error_ptr_arg) { std::vector result(count); Int numRead = 0; do { const auto n = stream->Read(result, static_cast(numRead), static_cast(count), err); if (n == 0) break; numRead += n; count -= n; } while (count > 0); if (numRead != result.size()) { std::vector copy(numRead); Buffer::BlockCopy(result.data(), 0, copy.data(), 0, numRead); result = copy; } return result; } }