//--------------------------------------------------
// Motion Framework
// Copyright©2018-2020 何冠峰
// Licensed under the MIT license
//--------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
#if MOTION_SERVER
using System.Numerics;
#else
using UnityEngine;
#endif
namespace MotionFramework.IO
{
///
/// 字节缓冲区
///
public class ByteBuffer
{
private readonly byte[] _buffer;
private int _readerIndex = 0;
private int _writerIndex = 0;
private int _markedReaderIndex = 0;
private int _markedWriterIndex = 0;
///
/// 字节缓冲区
///
public ByteBuffer(int capacity)
{
_buffer = new byte[capacity];
}
///
/// 字节缓冲区
///
public ByteBuffer(byte[] data)
{
_buffer = data;
_writerIndex = data.Length;
}
///
/// 获取数据
///
public byte[] GetBuffer()
{
return _buffer;
}
///
/// 缓冲区容量
///
public int Capacity
{
get { return _buffer.Length; }
}
///
/// 清空缓冲区
///
public void Clear()
{
_readerIndex = 0;
_writerIndex = 0;
_markedReaderIndex = 0;
_markedWriterIndex = 0;
}
///
/// 删除已读部分,重新初始化数组
///
public void DiscardReadBytes()
{
if (_readerIndex == 0)
return;
if (_readerIndex == _writerIndex)
{
_readerIndex = 0;
_writerIndex = 0;
}
else
{
for (int i = 0, j = _readerIndex, length = _writerIndex - _readerIndex; i < length; i++, j++)
{
_buffer[i] = _buffer[j];
}
_writerIndex -= _readerIndex;
_readerIndex = 0;
}
}
#region 读取相关
///
/// 读取的下标位置
///
public int ReaderIndex
{
get { return _readerIndex; }
}
///
/// 当前可读数据量
///
public int ReadableBytes
{
get { return _writerIndex - _readerIndex; }
}
///
/// 查询是否可以读取
///
/// 读取数据量
public bool IsReadable(int size = 1)
{
return _writerIndex - _readerIndex >= size;
}
///
/// 标记读取的下标位置,便于某些时候回退到该位置
///
public void MarkReaderIndex()
{
_markedReaderIndex = _readerIndex;
}
///
/// 回退到标记的读取下标位置
///
public void ResetReaderIndex()
{
_readerIndex = _markedReaderIndex;
}
#endregion
#region 写入相关
///
/// 写入的下标位置
///
public int WriterIndex
{
get { return _writerIndex; }
}
///
/// 当前可写入数据量
///
public int WriteableBytes
{
get { return Capacity - _writerIndex; }
}
///
/// 查询是否可以写入
///
/// 写入数据量
public bool IsWriteable(int size = 1)
{
return Capacity - _writerIndex >= size;
}
///
/// 标记写入的下标位置,便于某些时候回退到该位置。
///
public void MarkWriterIndex()
{
_markedWriterIndex = _writerIndex;
}
///
/// 回退到标记的写入下标位置
///
public void ResetWriterIndex()
{
_writerIndex = _markedWriterIndex;
}
#endregion
#region 读取操作
[Conditional("DEBUG")]
private void CheckReaderIndex(int length)
{
if (_readerIndex + length > _writerIndex)
{
throw new IndexOutOfRangeException();
}
}
public byte[] ReadBytes(int count)
{
CheckReaderIndex(count);
var data = new byte[count];
Buffer.BlockCopy(_buffer, _readerIndex, data, 0, count);
_readerIndex += count;
return data;
}
public bool ReadBool()
{
CheckReaderIndex(1);
return _buffer[_readerIndex++] == 1;
}
public byte ReadByte()
{
CheckReaderIndex(1);
return _buffer[_readerIndex++];
}
public sbyte ReadSbyte()
{
return (sbyte)ReadByte();
}
public short ReadShort()
{
CheckReaderIndex(2);
short result = BitConverter.ToInt16(_buffer, _readerIndex);
_readerIndex += 2;
return result;
}
public ushort ReadUShort()
{
CheckReaderIndex(2);
ushort result = BitConverter.ToUInt16(_buffer, _readerIndex);
_readerIndex += 2;
return result;
}
public int ReadInt()
{
CheckReaderIndex(4);
int result = BitConverter.ToInt32(_buffer, _readerIndex);
_readerIndex += 4;
return result;
}
public uint ReadUInt()
{
CheckReaderIndex(4);
uint result = BitConverter.ToUInt32(_buffer, _readerIndex);
_readerIndex += 4;
return result;
}
public long ReadLong()
{
CheckReaderIndex(8);
long result = BitConverter.ToInt64(_buffer, _readerIndex);
_readerIndex += 8;
return result;
}
public ulong ReadULong()
{
CheckReaderIndex(8);
ulong result = BitConverter.ToUInt64(_buffer, _readerIndex);
_readerIndex += 8;
return result;
}
public float ReadFloat()
{
CheckReaderIndex(4);
float result = BitConverter.ToSingle(_buffer, _readerIndex);
_readerIndex += 4;
return result;
}
public double ReadDouble()
{
CheckReaderIndex(8);
double result = BitConverter.ToDouble(_buffer, _readerIndex);
_readerIndex += 8;
return result;
}
public string ReadUTF()
{
ushort count = ReadUShort();
CheckReaderIndex(count);
string result = Encoding.UTF8.GetString(_buffer, _readerIndex, count - 1); // 注意:读取的时候忽略字符串末尾写入结束符
_readerIndex += count;
return result;
}
public List ReadListInt()
{
List result = new List();
int count = ReadInt();
for (int i = 0; i < count; i++)
{
result.Add(ReadInt());
}
return result;
}
public List ReadListLong()
{
List result = new List();
int count = ReadInt();
for (int i = 0; i < count; i++)
{
result.Add(ReadLong());
}
return result;
}
public List ReadListFloat()
{
List result = new List();
int count = ReadInt();
for (int i = 0; i < count; i++)
{
result.Add(ReadFloat());
}
return result;
}
public List ReadListDouble()
{
List result = new List();
int count = ReadInt();
for (int i = 0; i < count; i++)
{
result.Add(ReadDouble());
}
return result;
}
public List ReadListUTF()
{
List result = new List();
int count = ReadInt();
for (int i = 0; i < count; i++)
{
result.Add(ReadUTF());
}
return result;
}
public Vector2 ReadVector2()
{
float x = ReadFloat();
float y = ReadFloat();
return new Vector2(x, y);
}
public Vector3 ReadVector3()
{
float x = ReadFloat();
float y = ReadFloat();
float z = ReadFloat();
return new Vector3(x, y, z);
}
public Vector4 ReadVector4()
{
float x = ReadFloat();
float y = ReadFloat();
float z = ReadFloat();
float w = ReadFloat();
return new Vector4(x, y, z, w);
}
#endregion
#region 写入操作
[Conditional("DEBUG")]
private void CheckWriterIndex(int length)
{
if (_writerIndex + length > Capacity)
{
throw new IndexOutOfRangeException();
}
}
public void WriteBytes(byte[] data)
{
WriteBytes(data, 0, data.Length);
}
public void WriteBytes(byte[] data, int offset, int count)
{
CheckWriterIndex(count);
Buffer.BlockCopy(data, offset, _buffer, _writerIndex, count);
_writerIndex += count;
}
public void WriteBool(bool value)
{
WriteByte((byte)(value ? 1 : 0));
}
public void WriteByte(byte value)
{
CheckWriterIndex(1);
_buffer[_writerIndex++] = value;
}
public void WriteSbyte(sbyte value)
{
// 注意:从sbyte强转到byte不会有数据变化或丢失
WriteByte((byte)value);
}
public void WriteShort(short value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteUShort(ushort value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteInt(int value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteUInt(uint value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteLong(long value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteULong(ulong value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteFloat(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteDouble(double value)
{
byte[] bytes = BitConverter.GetBytes(value);
WriteBytes(bytes);
}
public void WriteUTF(string value)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
int num = bytes.Length + 1; // 注意:字符串末尾写入结束符
if (num > ushort.MaxValue)
throw new FormatException($"String length cannot be greater than {ushort.MaxValue} !");
WriteUShort(Convert.ToUInt16(num));
WriteBytes(bytes);
WriteByte((byte)'\0');
}
public void WriteListInt(List values)
{
int count = 0;
if (values != null)
count = values.Count;
WriteInt(count);
for (int i = 0; i < count; i++)
{
WriteInt(values[i]);
}
}
public void WriteListLong(List values)
{
int count = 0;
if (values != null)
count = values.Count;
WriteInt(count);
for (int i = 0; i < count; i++)
{
WriteLong(values[i]);
}
}
public void WriteListFloat(List values)
{
int count = 0;
if (values != null)
count = values.Count;
WriteInt(count);
for (int i = 0; i < count; i++)
{
WriteFloat(values[i]);
}
}
public void WriteListDouble(List values)
{
int count = 0;
if (values != null)
count = values.Count;
WriteInt(count);
for (int i = 0; i < count; i++)
{
WriteDouble(values[i]);
}
}
public void WriteListUTF(List values)
{
int count = 0;
if (values != null)
count = values.Count;
WriteInt(count);
for (int i = 0; i < count; i++)
{
WriteUTF(values[i]);
}
}
#if MOTION_SERVER
public void WriteVector2(Vector2 value)
{
WriteFloat(value.X);
WriteFloat(value.Y);
}
public void WriteVector3(Vector3 value)
{
WriteFloat(value.X);
WriteFloat(value.Y);
WriteFloat(value.Z);
}
public void WriteVector4(Vector4 value)
{
WriteFloat(value.X);
WriteFloat(value.Y);
WriteFloat(value.Z);
WriteFloat(value.W);
}
#else
public void WriteVector2(Vector2 value)
{
WriteFloat(value.x);
WriteFloat(value.y);
}
public void WriteVector3(Vector3 value)
{
WriteFloat(value.x);
WriteFloat(value.y);
WriteFloat(value.z);
}
public void WriteVector4(Vector4 value)
{
WriteFloat(value.x);
WriteFloat(value.y);
WriteFloat(value.z);
WriteFloat(value.w);
}
#endif
#endregion
///
/// 大小端转换
///
public static void ReverseOrder(byte[] data)
{
ReverseOrder(data, 0, data.Length);
}
public static void ReverseOrder(byte[] data, int offset, int length)
{
if (length <= 1)
return;
int end = offset + length - 1;
int max = offset + length / 2;
byte temp;
for (int index = offset; index < max; index++, end--)
{
temp = data[end];
data[end] = data[index];
data[index] = temp;
}
}
}
}