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; } } }