mirror of
https://github.com/thebreaddev/Supercell.GUT.git
synced 2025-04-14 01:49:47 +00:00
302 lines
No EOL
6.7 KiB
C#
302 lines
No EOL
6.7 KiB
C#
using Supercell.GUT.Titan.Math;
|
|
using System.Buffers.Binary;
|
|
using System.Runtime.CompilerServices;
|
|
using TextEncoding = System.Text.Encoding;
|
|
|
|
namespace Supercell.GUT.Titan.Encoding.Streamed;
|
|
|
|
public class ByteStream : ChecksumEncoder
|
|
{
|
|
public byte[] Buffer { get; set; }
|
|
|
|
private int _bitIndex;
|
|
private int _length;
|
|
|
|
public int Offset { get; set; }
|
|
|
|
public int Length => _length > 0 ? _length : Offset;
|
|
|
|
public ByteStream(byte[] buffer, int length)
|
|
{
|
|
Buffer = buffer;
|
|
_length = length;
|
|
}
|
|
|
|
public ByteStream(int capacity)
|
|
{
|
|
Buffer = new byte[capacity];
|
|
}
|
|
|
|
public ByteStream()
|
|
{
|
|
Buffer = new byte[10];
|
|
}
|
|
|
|
public void SetByteArray(byte[] buffer, int length)
|
|
{
|
|
Buffer = buffer;
|
|
_length = length;
|
|
}
|
|
|
|
public bool ReadBoolean()
|
|
{
|
|
if (_bitIndex == 0)
|
|
++Offset;
|
|
|
|
bool value = (Buffer[Offset - 1] & 1 << _bitIndex) != 0;
|
|
_bitIndex = _bitIndex + 1 & 7;
|
|
return value;
|
|
}
|
|
|
|
public byte ReadByte()
|
|
{
|
|
_bitIndex = 0;
|
|
return Buffer[Offset++];
|
|
}
|
|
|
|
public short ReadShort()
|
|
{
|
|
_bitIndex = 0;
|
|
|
|
short ret = BinaryPrimitives.ReadInt16BigEndian(Buffer.AsSpan()[Offset..]);
|
|
Offset += 2;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public int ReadInt()
|
|
{
|
|
_bitIndex = 0;
|
|
|
|
int ret = BinaryPrimitives.ReadInt32BigEndian(Buffer.AsSpan()[Offset..]);
|
|
Offset += 4;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public int ReadVInt()
|
|
{
|
|
_bitIndex = 0;
|
|
|
|
int value = 0;
|
|
byte byteValue = Buffer[Offset++];
|
|
|
|
if ((byteValue & 0x40) != 0)
|
|
{
|
|
value |= byteValue & 0x3F;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 6;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 13;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 20;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((_ = Buffer[Offset++]) & 0x7F) << 27;
|
|
return (int)(value | 0x80000000);
|
|
}
|
|
|
|
return (int)(value | 0xF8000000);
|
|
}
|
|
|
|
return (int)(value | 0xFFF00000);
|
|
}
|
|
|
|
return (int)(value | 0xFFFFE000);
|
|
}
|
|
|
|
return (int)(value | 0xFFFFFFC0);
|
|
}
|
|
|
|
value |= byteValue & 0x3F;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 6;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 13;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 20;
|
|
|
|
if ((byteValue & 0x80) != 0)
|
|
{
|
|
value |= ((_ = Buffer[Offset++]) & 0x7F) << 27;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
public LogicLong ReadLong()
|
|
{
|
|
LogicLong ll = new();
|
|
ll.Decode(this);
|
|
|
|
return ll;
|
|
}
|
|
|
|
public string? ReadString()
|
|
{
|
|
int length = ReadInt();
|
|
if (length is < 0 or > 900000)
|
|
return null;
|
|
else if (length == 0)
|
|
return string.Empty;
|
|
|
|
string ret = TextEncoding.UTF8.GetString(Buffer, Offset, length);
|
|
Offset += length;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public string ReadStringReference()
|
|
{
|
|
int length = ReadInt();
|
|
if (length is <= 0 or > 900000) return string.Empty;
|
|
|
|
string ret = TextEncoding.UTF8.GetString(Buffer, Offset, length);
|
|
Offset += length;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public byte[] ReadBytes(int length)
|
|
{
|
|
_bitIndex = 0;
|
|
|
|
byte[] ret = Buffer.Skip(Offset).Take(length).ToArray();
|
|
Offset += length;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteBoolean(bool value)
|
|
{
|
|
base.WriteBoolean(value);
|
|
|
|
if (_bitIndex == 0)
|
|
{
|
|
EnsureCapacity(1);
|
|
Buffer[Offset++] = 0;
|
|
}
|
|
|
|
Buffer[Offset - 1] |= (byte)(value ? 1 : 0);
|
|
_bitIndex = _bitIndex + 1 & 7;
|
|
|
|
return this;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteByte(byte value)
|
|
{
|
|
base.WriteByte(value);
|
|
EnsureCapacity(1);
|
|
|
|
Buffer[Offset++] = value;
|
|
|
|
return this;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteShort(short value)
|
|
{
|
|
base.WriteShort(value);
|
|
EnsureCapacity(2);
|
|
|
|
BinaryPrimitives.WriteInt16BigEndian(Buffer.AsSpan()[Offset..], value);
|
|
Offset += 2;
|
|
|
|
return this;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteInt(int value)
|
|
{
|
|
base.WriteInt(value);
|
|
EnsureCapacity(4);
|
|
|
|
WriteIntToByteArray(value);
|
|
return this;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteString(string? value)
|
|
{
|
|
base.WriteString(value);
|
|
if (value == null)
|
|
{
|
|
WriteIntToByteArray(-1);
|
|
return this;
|
|
}
|
|
|
|
int size = TextEncoding.UTF8.GetByteCount(value);
|
|
WriteIntToByteArray(size);
|
|
|
|
EnsureCapacity(size);
|
|
TextEncoding.UTF8.GetBytes(value, Buffer.AsSpan()[Offset..]);
|
|
|
|
Offset += size;
|
|
return this;
|
|
}
|
|
|
|
public override ChecksumEncoder WriteBytes(ReadOnlySpan<byte> value)
|
|
{
|
|
base.WriteBytes(value);
|
|
|
|
WriteIntToByteArray(value.Length);
|
|
|
|
EnsureCapacity(value.Length);
|
|
value.CopyTo(Buffer.AsSpan()[Offset..]);
|
|
Offset += value.Length;
|
|
|
|
return this;
|
|
}
|
|
|
|
public override bool IsCheckSumOnlyMode => false;
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private void WriteIntToByteArray(int value)
|
|
{
|
|
EnsureCapacity(4);
|
|
|
|
BinaryPrimitives.WriteInt32BigEndian(Buffer.AsSpan()[Offset..], value);
|
|
Offset += 4;
|
|
}
|
|
|
|
public void EnsureCapacity(int capacity)
|
|
{
|
|
_bitIndex = 0;
|
|
int bufferLength = Buffer.Length;
|
|
|
|
if (Offset + capacity > bufferLength)
|
|
{
|
|
byte[] tmpBuffer = new byte[Buffer.Length + capacity + 100];
|
|
System.Buffer.BlockCopy(Buffer, 0, tmpBuffer, 0, bufferLength);
|
|
Buffer = tmpBuffer;
|
|
}
|
|
}
|
|
|
|
public bool IsAtEnd()
|
|
{
|
|
return Offset >= Buffer.Length;
|
|
}
|
|
|
|
public void ResetOffset()
|
|
{
|
|
this.Offset = 0;
|
|
}
|
|
|
|
public void Destruct()
|
|
{
|
|
;
|
|
}
|
|
} |