Unity Udexreal开发插件包
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1309 lines
42 KiB

//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
// CSDN博客:https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频:https://space.bilibili.com/94253567
// Gitee源代码仓库:https://gitee.com/RRQM_Home
// Github源代码仓库:https://github.com/RRQM
// API首页:https://www.yuque.com/rrqm/touchsocket/index
// 交流QQ群:234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
namespace TouchSocket.Core
{
/// <summary>
/// 字节块流
/// </summary>
[DebuggerDisplay("Len={Len},Pos={Pos},Capacity={Capacity}")]
//[IntelligentCoder.AsyncMethodPoster(Flags = IntelligentCoder.MemberFlags.Public)]
public sealed partial class ByteBlock : Stream, IWrite
{
private static float m_ratio = 1.5f;
private readonly bool m_needDis;
private byte[] m_buffer;
private int m_dis = 1;
private bool m_holding;
private long m_length;
private long m_position;
private bool m_using;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="byteSize"></param>
/// <param name="equalSize"></param>
public ByteBlock(int byteSize = 1024 * 64, bool equalSize = false)
{
m_needDis = true;
m_buffer = BytePool.Default.GetByteCore(byteSize, equalSize);
m_using = true;
}
/// <summary>
/// 实例化一个已知内存的对象。且该内存不会被回收。
/// </summary>
/// <param name="bytes"></param>
public ByteBlock(byte[] bytes)
{
m_buffer = bytes ?? throw new ArgumentNullException(nameof(bytes));
m_length = bytes.Length;
m_using = true;
}
/// <summary>
/// 扩容增长比,默认为1.5,
/// min:1.5
/// </summary>
public static float Ratio
{
get => m_ratio;
set
{
if (value < 1.5)
{
value = 1.5f;
}
m_ratio = value;
}
}
/// <summary>
/// 字节实例
/// </summary>
public byte[] Buffer => m_buffer;
/// <summary>
/// 仅当内存块可用,且<see cref="CanReadLen"/>>0时为True。
/// </summary>
public override bool CanRead => m_using && CanReadLen > 0;
/// <summary>
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
/// </summary>
public int CanReadLen => Len - Pos;
/// <summary>
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
/// </summary>
public long CanReadLength => m_length - m_position;
/// <summary>
/// 支持查找
/// </summary>
public override bool CanSeek => m_using;
/// <summary>
/// 可写入
/// </summary>
public override bool CanWrite => m_using;
/// <summary>
/// 容量
/// </summary>
public int Capacity => m_buffer.Length;
/// <summary>
/// 空闲长度,准确掌握该值,可以避免内存扩展,计算为<see cref="Capacity"/>与<see cref="Pos"/>的差值。
/// </summary>
public int FreeLength => Capacity - Pos;
/// <summary>
/// 表示持续性持有,为True时,Dispose将调用无效。
/// </summary>
public bool Holding => m_holding;
/// <summary>
/// Int真实长度
/// </summary>
public int Len => (int)m_length;
/// <summary>
/// 真实长度
/// </summary>
public override long Length => m_length;
/// <summary>
/// int型流位置
/// </summary>
public int Pos
{
get => (int)m_position;
set => m_position = value;
}
/// <summary>
/// 流位置
/// </summary>
public override long Position
{
get => m_position;
set => m_position = value;
}
/// <summary>
/// 使用状态
/// </summary>
public bool Using => m_using;
/// <summary>
/// 直接完全释放,游离该对象,然后等待GC
/// </summary>
public void AbsoluteDispose()
{
if (Interlocked.Decrement(ref m_dis) == 0)
{
Dis();
}
}
/// <summary>
/// 清空所有内存数据
/// </summary>
/// <exception cref="ObjectDisposedException">内存块已释放</exception>
public void Clear()
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
Array.Clear(m_buffer, 0, m_buffer.Length);
}
/// <summary>
/// 无实际效果
/// </summary>
//IntelligentCoder.AsyncMethodIgnore]
public override void Flush()
{
}
/// <summary>
/// 读取数据,然后递增Pos
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
/// <exception cref="ObjectDisposedException"></exception>
public override int Read(byte[] buffer, int offset, int length)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
int len = m_length - m_position > length ? length : CanReadLen;
Array.Copy(m_buffer, m_position, buffer, offset, len);
m_position += len;
return len;
}
/// <summary>
/// 读取数据,然后递增Pos
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public int Read(byte[] buffer)
{
return Read(buffer, 0, buffer.Length);
}
/// <summary>
/// 读取数据,然后递增Pos
/// </summary>
/// <param name="buffer"></param>
/// <param name="length"></param>
/// <returns></returns>
public int Read(out byte[] buffer, int length)
{
buffer = new byte[length];
return Read(buffer, 0, buffer.Length);
}
/// <summary>
/// 从当前流位置读取一个<see cref="byte"/>值
/// </summary>
public override int ReadByte()
{
byte value = m_buffer[m_position];
m_position++;
return value;
}
/// <summary>
/// 将内存块初始化到刚申请的状态。
/// <para>仅仅重置<see cref="Position"/>和<see cref="Length"/>属性。</para>
/// </summary>
/// <exception cref="ObjectDisposedException">内存块已释放</exception>
public void Reset()
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
m_position = 0;
m_length = 0;
}
/// <summary>
/// 设置流位置
/// </summary>
/// <param name="offset"></param>
/// <param name="origin"></param>
/// <returns></returns>
/// <exception cref="ObjectDisposedException"></exception>
public override long Seek(long offset, SeekOrigin origin)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
switch (origin)
{
case SeekOrigin.Begin:
m_position = offset;
break;
case SeekOrigin.Current:
m_position += offset;
break;
case SeekOrigin.End:
m_position = m_length + offset;
break;
}
return m_position;
}
/// <summary>
/// 移动游标
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public ByteBlock Seek(int position)
{
Position = position;
return this;
}
/// <summary>
/// 设置游标到末位
/// </summary>
/// <returns></returns>
public ByteBlock SeekToEnd()
{
Position = Length;
return this;
}
/// <summary>
/// 设置游标到首位
/// </summary>
/// <returns></returns>
public ByteBlock SeekToStart()
{
Position = 0;
return this;
}
/// <summary>
/// 重新设置容量
/// </summary>
/// <param name="size">新尺寸</param>
/// <param name="retainedData">是否保留元数据</param>
/// <exception cref="ObjectDisposedException"></exception>
public void SetCapacity(int size, bool retainedData = false)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
byte[] bytes = new byte[size];
if (retainedData)
{
Array.Copy(m_buffer, 0, bytes, 0, m_buffer.Length);
}
if (m_needDis)
{
BytePool.Default.Recycle(m_buffer);
}
m_buffer = bytes;
}
/// <summary>
/// 设置持续持有属性,当为True时,调用Dispose会失效,表示该对象将长期持有,直至设置为False。
/// 当为False时,会自动调用Dispose。
/// </summary>
/// <param name="holding"></param>
/// <exception cref="ObjectDisposedException"></exception>
public void SetHolding(bool holding)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
m_holding = holding;
if (!holding)
{
Dispose();
}
}
/// <summary>
/// 设置实际长度
/// </summary>
/// <param name="value"></param>
/// <exception cref="ObjectDisposedException"></exception>
public override void SetLength(long value)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
if (value > m_buffer.Length)
{
throw new Exception("设置值超出容量");
}
m_length = value;
}
/// <summary>
/// 从指定位置转化到指定长度的有效内存
/// </summary>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
public byte[] ToArray(int offset, int length)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
byte[] buffer = new byte[length];
Array.Copy(m_buffer, offset, buffer, 0, buffer.Length);
return buffer;
}
/// <summary>
/// 转换为有效内存
/// </summary>
/// <returns></returns>
public byte[] ToArray()
{
return ToArray(0, Len);
}
/// <summary>
/// 从指定位置转化到有效内存
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
/// <exception cref="ObjectDisposedException"></exception>
public byte[] ToArray(int offset)
{
return ToArray(offset, Len - offset);
}
/// <summary>
/// 转换为UTF-8字符
/// </summary>
/// <returns></returns>
public override string ToString()
{
return ToString(0, Len);
}
/// <summary>
/// 转换为UTF-8字符
/// </summary>
/// <param name="offset">偏移量</param>
/// <param name="length">长度</param>
/// <returns></returns>
public string ToString(int offset, int length)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
return Encoding.UTF8.GetString(m_buffer, offset, length);
}
/// <summary>
/// 转换为UTF-8字符
/// </summary>
/// <param name="offset">偏移量</param>
/// <returns></returns>
public string ToString(int offset)
{
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
return Encoding.UTF8.GetString(m_buffer, offset, Len - offset);
}
/// <summary>
/// 写入
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <exception cref="ObjectDisposedException"></exception>
public override void Write(byte[] buffer, int offset, int count)
{
if (count == 0)
{
return;
}
if (!m_using)
{
throw new ObjectDisposedException(GetType().FullName);
}
if (m_buffer.Length - m_position < count)
{
int need = m_buffer.Length + count - ((int)(m_buffer.Length - m_position));
int lend = m_buffer.Length;
while (need > lend)
{
lend = (int)(lend * m_ratio);
}
SetCapacity(lend, true);
}
Array.Copy(buffer, offset, m_buffer, m_position, count);
m_position += count;
m_length = Math.Max(m_position, m_length);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="buffer"></param>
/// <exception cref="NotImplementedException"></exception>
public void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
/// <summary>
/// 释放当前内存到指定内存池
/// </summary>
/// <param name="bytePool"></param>
public void Dispose(BytePool bytePool)
{
if (m_holding)
{
return;
}
if (m_needDis)
{
if (Interlocked.Decrement(ref m_dis) == 0)
{
GC.SuppressFinalize(this);
bytePool.Recycle(m_buffer);
Dis();
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override sealed void Dispose(bool disposing)
{
if (m_holding)
{
return;
}
if (m_needDis)
{
if (Interlocked.Decrement(ref m_dis) == 0)
{
GC.SuppressFinalize(this);
BytePool.Default.Recycle(m_buffer);
Dis();
}
}
base.Dispose(disposing);
}
private void Dis()
{
m_holding = false;
m_using = false;
m_position = 0;
m_length = 0;
m_buffer = null;
}
#region BytesPackage
/// <summary>
/// 从当前流位置读取一个独立的<see cref="byte"/>数组包
/// </summary>
public byte[] ReadBytesPackage()
{
byte status = (byte)ReadByte();
if (status == 0)
{
return null;
}
int length = ReadInt32();
byte[] data = new byte[length];
Array.Copy(Buffer, Pos, data, 0, length);
Pos += length;
return data;
}
/// <summary>
/// 尝试获取数据包信息,方便从Buffer操作数据
/// </summary>
/// <param name="pos"></param>
/// <param name="len"></param>
/// <returns></returns>
public bool TryReadBytesPackageInfo(out int pos, out int len)
{
byte status = (byte)ReadByte();
if (status == 0)
{
pos = 0;
len = 0;
return false;
}
len = ReadInt32();
pos = Pos;
return true;
}
/// <summary>
/// 写入一个独立的<see cref="byte"/>数组包,值可以为null。
/// </summary>
/// <param name="value"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public ByteBlock WriteBytesPackage(byte[] value, int offset, int length)
{
if (value == null)
{
Write((byte)0);
}
else
{
Write((byte)1);
Write(length);
Write(value, offset, length);
}
return this;
}
/// <summary>
/// 写入一个独立的<see cref="byte"/>数组包。值可以为null。
/// </summary>
/// <param name="value"></param>
public ByteBlock WriteBytesPackage(byte[] value)
{
if (value == null)
{
return WriteBytesPackage(value, 0, 0);
}
return WriteBytesPackage(value, 0, value.Length);
}
#endregion BytesPackage
#region Int32
/// <summary>
/// 从当前流位置读取一个<see cref="int"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public int ReadInt32(bool? bigEndian = null)
{
int value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToInt32(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToInt32(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToInt32(Buffer, Pos); break;
}
m_position += 4;
return value;
}
/// <summary>
/// 写入<see cref="int"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(int value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Int32
#region Int16
/// <summary>
/// 从当前流位置读取一个<see cref="short"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public short ReadInt16(bool? bigEndian = null)
{
short value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToInt16(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToInt16(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToInt16(Buffer, Pos); break;
}
Pos += 2;
return value;
}
/// <summary>
/// 写入<see cref="short"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(short value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Int16
#region Int64
/// <summary>
/// 从当前流位置读取一个<see cref="long"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public long ReadInt64(bool? bigEndian = null)
{
long value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToInt64(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToInt64(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToInt64(Buffer, Pos); break;
}
Pos += 8;
return value;
}
/// <summary>
/// 写入<see cref="long"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(long value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Int64
#region Boolean
/// <summary>
/// 从当前流位置读取一个<see cref="bool"/>值
/// </summary>
public bool ReadBoolean()
{
bool value = TouchSocketBitConverter.Default.ToBoolean(Buffer, Pos);
Pos += 1;
return value;
}
/// <summary>
/// 写入<see cref="bool"/>值
/// </summary>
/// <param name="value"></param>
public ByteBlock Write(bool value)
{
Write(TouchSocketBitConverter.Default.GetBytes(value));
return this;
}
#endregion Boolean
#region Byte
/// <summary>
/// 写入<see cref="byte"/>值
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public ByteBlock Write(byte value)
{
Write(new byte[] { value }, 0, 1);
return this;
}
#endregion Byte
#region String
/// <summary>
/// 从当前流位置读取一个<see cref="string"/>值
/// </summary>
public string ReadString()
{
int len = this.ReadInt32();
if (len < 0)
{
return null;
}
else
{
string str = Encoding.UTF8.GetString(Buffer, Pos, len);
Pos += len;
return str;
}
}
/// <summary>
/// 写入<see cref="string"/>值。值可以为null,或者空。
/// <para>注意:该操作不具备通用性,读取时必须使用ReadString。或者得先做出判断,由默认端序的int32值标识,具体如下:</para>
/// <list type="bullet">
/// <item>小于0,表示字符串为null</item>
/// <item>等于0,表示字符串为""</item>
/// <item>大于0,表示字符串在utf-8编码下的字节长度。</item>
/// </list>
/// </summary>
/// <param name="value"></param>
public ByteBlock Write(string value)
{
if (value == null)
{
Write(-1);
}
else
{
byte[] buffer = Encoding.UTF8.GetBytes(value);
Write(buffer.Length);
Write(buffer);
}
return this;
}
/// <summary>
/// 写入<see cref="string"/>值。值必须为有效值。可通用解析。
/// </summary>
/// <param name="value"></param>
/// <param name="encoding"></param>
public ByteBlock WriteString(string value, Encoding encoding = null)
{
Write((encoding ?? Encoding.UTF8).GetBytes(value));
return this;
}
#endregion String
#region Char
/// <summary>
/// 从当前流位置读取一个<see cref="char"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public char ReadChar(bool? bigEndian = null)
{
char value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToChar(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToChar(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToChar(Buffer, Pos); break;
}
Pos += 2;
return value;
}
/// <summary>
/// 写入<see cref="char"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(char value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Char
#region Double
/// <summary>
/// 从当前流位置读取一个<see cref="double"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public double ReadDouble(bool? bigEndian = null)
{
double value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToDouble(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToDouble(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToDouble(Buffer, Pos); break;
}
Pos += 8;
return value;
}
/// <summary>
/// 写入<see cref="double"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(double value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Double
#region Float
/// <summary>
/// 从当前流位置读取一个<see cref="float"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public float ReadFloat(bool? bigEndian = null)
{
float value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToSingle(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToSingle(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToSingle(Buffer, Pos); break;
}
Pos += 4;
return value;
}
/// <summary>
/// 写入<see cref="float"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(float value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion Float
#region UInt16
/// <summary>
/// 从当前流位置读取一个<see cref="ushort"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ushort ReadUInt16(bool? bigEndian = null)
{
ushort value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToUInt16(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToUInt16(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToUInt16(Buffer, Pos); break;
}
Pos += 2;
return value;
}
/// <summary>
/// 写入<see cref="ushort"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(ushort value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion UInt16
#region UInt32
/// <summary>
/// 从当前流位置读取一个<see cref="uint"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public uint ReadUInt32(bool? bigEndian = null)
{
uint value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToUInt32(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToUInt32(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToUInt32(Buffer, Pos); break;
}
Pos += 4;
return value;
}
/// <summary>
/// 写入<see cref="uint"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(uint value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion UInt32
#region UInt64
/// <summary>
/// 从当前流位置读取一个<see cref="ulong"/>值
/// </summary>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ulong ReadUInt64(bool? bigEndian = null)
{
ulong value;
switch (bigEndian)
{
case true: value = TouchSocketBitConverter.BigEndian.ToUInt64(Buffer, Pos); break;
case false: value = TouchSocketBitConverter.LittleEndian.ToUInt64(Buffer, Pos); break;
default: value = TouchSocketBitConverter.Default.ToUInt64(Buffer, Pos); break;
}
Pos += 8;
return value;
}
/// <summary>
/// 写入<see cref="ulong"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="bigEndian">是否为指定大端编码。允许true(大端),false(小端),null(默认端序)三种赋值。默认为null。</param>
public ByteBlock Write(ulong value, bool? bigEndian = null)
{
switch (bigEndian)
{
case true: Write(TouchSocketBitConverter.BigEndian.GetBytes(value)); break;
case false: Write(TouchSocketBitConverter.LittleEndian.GetBytes(value)); break;
default: Write(TouchSocketBitConverter.Default.GetBytes(value)); break;
}
return this;
}
#endregion UInt64
#region Null
/// <summary>
/// 从当前流位置读取一个标识值,判断是否为null。
/// </summary>
public bool ReadIsNull()
{
var status = ReadByte();
if (status == 0)
{
return true;
}
else if (status == 1)
{
return false;
}
else
{
throw new Exception("标识既非Null,也非NotNull,可能是流位置发生了错误。");
}
}
/// <summary>
/// 判断该值是否为Null,然后写入标识值
/// </summary>
public ByteBlock WriteIsNull<T>(T t) where T : class
{
if (t == null)
{
WriteNull();
}
else
{
WriteNotNull();
}
return this;
}
/// <summary>
/// 写入一个标识非Null值
/// </summary>
public ByteBlock WriteNotNull()
{
Write((byte)1);
return this;
}
/// <summary>
/// 写入一个标识Null值
/// </summary>
public ByteBlock WriteNull()
{
Write((byte)0);
return this;
}
#endregion Null
#region Package
/// <summary>
/// 读取一个指定类型的包
/// </summary>
/// <typeparam name="TPackage"></typeparam>
/// <returns></returns>
public TPackage ReadPackage<TPackage>() where TPackage : class, IPackage, new()
{
if (ReadIsNull())
{
return default;
}
else
{
TPackage package = new TPackage();
package.Unpackage(this);
return package;
}
}
/// <summary>
/// 以包进行写入。允许null值。
/// 读取时调用<see cref="ReadPackage"/>,解包。或者先判断<see cref="ReadIsNull"/>,然后自行解包。
/// </summary>
/// <typeparam name="TPackage"></typeparam>
/// <param name="package"></param>
/// <returns></returns>
public ByteBlock WritePackage<TPackage>(TPackage package) where TPackage : class, IPackage
{
WriteIsNull(package);
if (package != null)
{
package.Package(this);
}
return this;
}
#endregion Package
#region DateTime
/// <summary>
/// 从当前流位置读取一个<see cref="DateTime"/>值
/// </summary>
public DateTime ReadDateTime()
{
long value = TouchSocketBitConverter.Default.ToInt64(Buffer, Pos);
Pos += 8;
return DateTime.FromBinary(value);
}
/// <summary>
/// 写入<see cref="DateTime"/>值
/// </summary>
/// <param name="value"></param>
public ByteBlock Write(DateTime value)
{
Write(TouchSocketBitConverter.Default.GetBytes(value.ToBinary()));
return this;
}
#endregion DateTime
#region TimeSpan
/// <summary>
/// 从当前流位置读取一个<see cref="TimeSpan"/>值
/// </summary>
public TimeSpan ReadTimeSpan()
{
long value = TouchSocketBitConverter.Default.ToInt64(Buffer, Pos);
Pos += 8;
return TimeSpan.FromTicks(value);
}
/// <summary>
/// 写入<see cref="TimeSpan"/>值
/// </summary>
/// <param name="value"></param>
public ByteBlock Write(TimeSpan value)
{
Write(TouchSocketBitConverter.Default.GetBytes(value.Ticks));
return this;
}
#endregion TimeSpan
#region Object
/// <summary>
/// 从当前流位置读取一个泛型值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="serializationType"></param>
/// <returns></returns>
public T ReadObject<T>(SerializationType serializationType = SerializationType.FastBinary)
{
int length = ReadInt32();
if (length == 0)
{
return default;
}
T obj;
switch (serializationType)
{
case SerializationType.FastBinary:
{
obj = SerializeConvert.FastBinaryDeserialize<T>(Buffer, Pos);
}
break;
case SerializationType.Json:
{
string jsonString = Encoding.UTF8.GetString(Buffer, Pos, length);
obj = SerializeConvert.JsonDeserializeFromString<T>(jsonString);
}
break;
case SerializationType.Xml:
{
string jsonString = Encoding.UTF8.GetString(Buffer, Pos, length);
obj = SerializeConvert.XmlDeserializeFromString<T>(jsonString);
}
break;
case SerializationType.SystemBinary:
{
obj = SerializeConvert.BinaryDeserialize<T>(Buffer, Pos, length);
}
break;
default:
throw new Exception("未定义的序列化类型");
}
Pos += length;
return obj;
}
/// <summary>
/// 写入<see cref="object"/>值
/// </summary>
/// <param name="value"></param>
/// <param name="serializationType"></param>
public ByteBlock WriteObject(object value, SerializationType serializationType = SerializationType.FastBinary)
{
if (value == null)
{
Write(0);
return this;
}
byte[] data;
switch (serializationType)
{
case SerializationType.FastBinary:
{
data = SerializeConvert.FastBinarySerialize(value);
}
break;
case SerializationType.Json:
{
data = SerializeConvert.JsonSerializeToBytes(value);
}
break;
case SerializationType.Xml:
{
data = Encoding.UTF8.GetBytes(SerializeConvert.XmlSerializeToString(value));
}
break;
case SerializationType.SystemBinary:
{
data = SerializeConvert.BinarySerialize(value);
}
break;
default:
throw new Exception("未定义的序列化类型");
}
Write(data.Length);
Write(data);
return this;
}
#endregion Object
}
}