namespace PlcSiemens.O
{
public static class ExtensionHelper
{
public static byte[] Reverse(this byte[] buf, int index, int length)
{
Array.Reverse(buf, index, length);
return buf;
}
public static int CompareTo(this byte[] source, Int64 start, Int64 count, byte[] buffer, Int64 offset = 0, Int64 length = -1)
{
if (source == buffer) return 0;
if (start < 0) start = 0;
if (count <= 0 || count > source.Length - start) count = source.Length - start;
if (length <= 0 || length > buffer.Length - offset) length = buffer.Length - offset;
// 逐字节比较
for (int i = 0; i < count && i < length; i++)
{
int rs = source[start + i].CompareTo(buffer[offset + i]);
if (rs != 0) return i > 0 ? i : 1;
}
// 比较完成。如果长度不相等,则较长者较大
if (count != length) return count > length ? 1 : -1;
return 0;
}
}
public class ByteBuffer
{
private readonly byte[] _bufferCache;
///
/// 缓冲区
///
public byte[] Buffer { get; private set; }
///
/// 当前读取位置
///
public int ReadIndex { get; private set; }
///
/// 当前写入位置
///
public int WriteIndex { get; private set; }
///
/// 设置读取位置标记
///
public int MarkReadIndex { get; private set; }
///
/// 设置写入位置标记
///
public int MarkWirteIndex { get; private set; }
///
/// 当前缓冲大小
///
public int Capacity { get; private set; }
///
/// 缓冲扩充单位
///
public int CapacityUnit { get; set; }
///
/// 构造函数
///
///
private ByteBuffer(int capacity = 1024)
{
_bufferCache = new byte[0x10];
Buffer = new byte[capacity];
Capacity = capacity;
CapacityUnit = Capacity;
}
///
/// 构建一个对象
///
///
///
public static ByteBuffer Allocate(int capacity = 1024)
{
return new ByteBuffer(capacity);
}
///
/// 计算扩容需量
///
///
///
private int FixLength(int length)
{
int n = 2;
int b = 2;
while (b < length)
{
b = 2 << n;
n++;
}
return (b / CapacityUnit + 1) * CapacityUnit;
}
///
/// 长度不够扩充容量
///
///
///
///
private int FixSizeAndReset(int currLen, int futureLen)
{
if (futureLen > currLen)
{
int size = FixLength(currLen) + Capacity;
byte[] newbuf = new byte[size];
Array.Copy(Buffer, 0, newbuf, 0, currLen);
Buffer = newbuf;
Capacity = newbuf.Length;
}
return futureLen;
}
#region 压入对象
public void Push(byte[] bytes, int startIndex, int length)
{
lock (this)
{
int offset = length - startIndex;
if (offset <= 0) return;
int total = offset + WriteIndex;
int len = Buffer.Length;
FixSizeAndReset(len, total);
for (int i = WriteIndex, j = startIndex; i < total; i++, j++)
{
Buffer[i] = bytes[j];
}
WriteIndex = total;
}
}
///
/// 写入字节数组
///
///
///
///
public void Push(byte[] bytes, int length, bool reversed = false)
{
if (reversed) bytes = bytes.Reverse(0, length);
Push(bytes, 0, length);
}
///
/// 写入字节数组
///
///
///
public void Push(byte[] bytes, bool reversed = false)
{
Push(bytes, bytes.Length, reversed);
}
///
/// 写入另一个对象
///
///
///
public void Push(ByteBuffer buffer, bool reversed = false)
{
if (buffer == null) return;
if (buffer.ReadableBytes() <= 0) return;
Push(buffer.ToArray(), reversed);
}
///
/// 写入一个对象
///
///
///
public void Push(short value, bool reversed = false)
{
Push((ushort)value, reversed);
}
///
/// 写入一个对象
///
///
///
public void Push(ushort value, bool reversed = false)
{
_bufferCache[0] = (byte)(value >> 8);
_bufferCache[1] = (byte)value;
Push(_bufferCache, 2, reversed);
}
public void Push(char value, bool reversed = false)
{
Push((short)value, reversed);
}
///
/// 写入一个对象
///
///
///
public void Push(int value, bool reversed = false)
{
Push((uint)value);
}
///
/// 写入一个对象
///
///
///
public void Push(uint value, bool reversed = false)
{
_bufferCache[0] = (byte)(value >> 0x18);
_bufferCache[1] = (byte)(value >> 0x10);
_bufferCache[2] = (byte)(value >> 8);
_bufferCache[3] = (byte)value;
Push(_bufferCache, 4, reversed);
}
///
/// 写入一个对象
///
///
///
public void Push(long value, bool reversed = false)
{
Push((ulong)value);
}
///
/// 写入一个对象
///
///
///
public void Push(ulong value, bool reversed = false)
{
_bufferCache[0] = (byte)(value >> 0x38);
_bufferCache[1] = (byte)(value >> 0x30);
_bufferCache[2] = (byte)(value >> 0x28);
_bufferCache[3] = (byte)(value >> 0x20);
_bufferCache[4] = (byte)(value >> 0x18);
_bufferCache[5] = (byte)(value >> 0x10);
_bufferCache[6] = (byte)(value >> 8);
_bufferCache[7] = (byte)value;
Push(_bufferCache, 8, reversed);
}
///
/// 写入一个对象
///
///
///
public void Push(float value, bool reversed = false)
{
var buf = BitConverter.GetBytes(value);
Push(buf, reversed);
}
///
/// 写入一个对象
///
///
public void Push(byte value)
{
lock (this)
{
int afterLen = WriteIndex + 1;
int len = Buffer.Length;
FixSizeAndReset(len, afterLen);
Buffer[WriteIndex] = value;
WriteIndex = afterLen;
}
}
///
/// 写入一个对象
///
///
///
public void Push(double value, bool reversed = false)
{
var buf = BitConverter.GetBytes(value);
Push(buf, reversed);
}
#endregion 压入对象
#region pop出一个对象
///
/// 读取一个
///
///
public byte PopByte()
{
byte b = Buffer[ReadIndex];
ReadIndex++;
return b;
}
///
/// 读取指定的[]
///
///
///
///
private byte[] Pop(int len, bool reversed = false)
{
byte[] bytes = new byte[len];
Array.Copy(Buffer, ReadIndex, bytes, 0, len);
if (reversed)
Array.Reverse(bytes);
ReadIndex += len;
return bytes;
}
///
/// 读取指定的
///
///
public ushort PopUshort(bool reversed = false)
{
var buf = Pop(2, reversed);
return (ushort)(buf[0] << 8 | buf[1]);
}
///
/// 读取指定的
///
///
public char PopChar(bool reversed = false)
{
var buf = Pop(2, reversed);
return (char)(buf[0] << 8 | buf[1]);
}
///
/// 读取指定的
///
///
///
public short PopShort(bool reversed = false)
{
var buf = Pop(2, reversed);
return (short)(buf[0] << 8 | buf[1]);
}
///
/// 读取指定的
///
///
///
public uint PopUint(bool reversed = false)
{
var buf = Pop(4, reversed);
return (uint)(buf[0] << 0x18 | buf[1] << 0x10 | buf[2] << 0x8 | buf[3]);
}
///
/// 读取指定的
///
///
///
public int PopInt(bool reversed = false)
{
var buf = Pop(4, reversed);
return buf[0] << 0x18 |
buf[1] << 0x10 |
buf[2] << 0x8 |
buf[3];
}
///
/// 读取指定的
///
///
///
public ulong PopUlong(bool reversed = false)
{
var buf = Pop(8, reversed);
return (ulong)(buf[0] << 0x38 |
buf[1] << 0x30 |
buf[2] << 0x28 |
buf[3] << 0x20 |
buf[4] << 0x18 |
buf[5] << 0x10 |
buf[6] << 0x08 |
buf[7]);
}
///
/// 读取指定的
///
///
///
public long PopLong(bool reversed = false)
{
var buf = Pop(8, reversed);
return buf[0] << 0x38 |
buf[1] << 0x30 |
buf[2] << 0x28 |
buf[3] << 0x20 |
buf[4] << 0x18 |
buf[5] << 0x10 |
buf[6] << 0x08 |
buf[7];
}
///
/// 读取指定的
///
///
///
public float PopFloat(bool reversed = false)
{
return BitConverter.ToSingle(Pop(4, reversed), 0);
}
///
/// 读取指定的
///
///
///
public double PopDouble(bool reversed = false)
{
return BitConverter.ToDouble(Pop(8, reversed), 0);
}
///
/// 读取指定长度的[]
///
///
///
///
public void PopBytes(byte[] desBytes, int desStart, int len)
{
int size = desStart + len;
for (int i = desStart; i < size; i++)
{
desBytes[i] = PopByte();
}
}
public byte[] PopBytes(int len)
{
var buf = new byte[len];
for (int i = 0; i < len; i++)
{
buf[i] = PopByte();
}
return buf;
}
#endregion pop出一个对象
///
/// 清除已读缓冲 后续队列前移
///
public void DiscardReadBytes()
{
if (ReadIndex <= 0) return;
int len = Buffer.Length - ReadIndex;
byte[] newbuf = new byte[Buffer.Length];
Array.Copy(Buffer, ReadIndex, newbuf, 0, len);
Buffer = newbuf;
WriteIndex -= ReadIndex;
MarkReadIndex -= ReadIndex;
if (MarkReadIndex < 0)
{
MarkReadIndex = ReadIndex;
}
MarkWirteIndex -= ReadIndex;
if (MarkWirteIndex < 0 || MarkWirteIndex < ReadIndex || MarkWirteIndex < MarkReadIndex)
{
MarkWirteIndex = WriteIndex;
}
ReadIndex = 0;
}
///
/// 清空缓存
///
public void Clear()
{
Buffer = new byte[Buffer.Length];
ReadIndex = 0;
WriteIndex = 0;
MarkReadIndex = 0;
MarkWirteIndex = 0;
}
///
/// 设置缓存读取位置
///
///
public void SetReaderIndex(int index)
{
if (index < 0) return;
ReadIndex = index;
}
///
/// 标记当前读取的索引位置
///
public void MarkReaderIndex()
{
MarkReadIndex = ReadIndex;
}
///
/// 标记当前写入的索引位置
///
public void MarkWriterIndex()
{
MarkWirteIndex = WriteIndex;
}
///
/// 将读取的索引位置重置为标记的读取索引位置
///
public void ResetReaderIndex()
{
ReadIndex = MarkReadIndex;
}
///
/// 将写入的索引位置重置为标记的写入索引位置
///
public void ResetWriterIndex()
{
WriteIndex = MarkWirteIndex;
}
///
/// 剩余可读数量
///
///
public int ReadableBytes()
{
return WriteIndex - ReadIndex;
}
///
/// 剩余可读缓存转数组
///
///
public byte[] ToArray()
{
byte[] bytes = new byte[WriteIndex];
Array.Copy(Buffer, 0, bytes, 0, bytes.Length);
return bytes;
}
public int IndexOf(byte[] buf, int offset = 0, int length = -1)
{
if (length <= 0) length = buf.Length - offset;
// 位置
int p = -1;
for (int i = 0; i < length;)
{
if (ReadableBytes() < 1) return -1;
int c = PopByte();
if (c == -1) return -1;
p++;
if (c == buf[offset + i])
{
i++;
// 全部匹配,退出
if (i >= length) return p - length + 1;
}
else
{
int n = i;
i = 0;
for (int j = 1; j < n; j++)
{
// 在字节数组前(j,n)里面找自己(0,n-j)
if (buf.CompareTo(j, n, buf, 0, n - j) == 0)
{
// 前面(0,n-j)相等,窗口退回到这里
i = n - j;
break;
}
}
}
}
return -1;
}
public bool EnsureStartWith(byte[] buf, int offset = 0, int length = -1)
{
if (buf.Length < offset) throw new ArgumentOutOfRangeException("offset");
if (offset < 0) offset = 0;
if (length < 0 || buf.Length < (offset + length)) length = buf.Length - offset;
int index = IndexOf(buf, offset, length);
if (index == -1)
{
//重建缓冲清除数据
//DiscardReadBytes();
//不能重建缓冲 有可能尾部有数据部分匹配而导致数据丢失
//重置ReaderIndex即可
SetReaderIndex(0);
return false;
}
if (index == 0) return true;
SetReaderIndex(index);
DiscardReadBytes();
return true;
}
}
}