123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639 |
- 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;
- /// <summary>
- /// 缓冲区
- /// </summary>
- public byte[] Buffer { get; private set; }
- /// <summary>
- /// 当前读取位置
- /// </summary>
- public int ReadIndex { get; private set; }
- /// <summary>
- /// 当前写入位置
- /// </summary>
- public int WriteIndex { get; private set; }
- /// <summary>
- /// 设置读取位置标记
- /// </summary>
- public int MarkReadIndex { get; private set; }
- /// <summary>
- /// 设置写入位置标记
- /// </summary>
- public int MarkWirteIndex { get; private set; }
- /// <summary>
- /// 当前缓冲大小
- /// </summary>
- public int Capacity { get; private set; }
- /// <summary>
- /// 缓冲扩充单位
- /// </summary>
- public int CapacityUnit { get; set; }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="capacity"></param>
- private ByteBuffer(int capacity = 1024)
- {
- _bufferCache = new byte[0x10];
- Buffer = new byte[capacity];
- Capacity = capacity;
- CapacityUnit = Capacity;
- }
- /// <summary>
- /// 构建一个<see cref="ByteBuffer"/>对象
- /// </summary>
- /// <param name="capacity"></param>
- /// <returns></returns>
- public static ByteBuffer Allocate(int capacity = 1024)
- {
- return new ByteBuffer(capacity);
- }
- /// <summary>
- /// 计算扩容需量
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- private int FixLength(int length)
- {
- int n = 2;
- int b = 2;
- while (b < length)
- {
- b = 2 << n;
- n++;
- }
- return (b / CapacityUnit + 1) * CapacityUnit;
- }
- /// <summary>
- /// 长度不够扩充<see cref="Buffer"/>容量
- /// </summary>
- /// <param name="currLen"></param>
- /// <param name="futureLen"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 写入字节数组
- /// </summary>
- /// <param name="bytes"></param>
- /// <param name="length"></param>
- /// <param name="reversed"></param>
- public void Push(byte[] bytes, int length, bool reversed = false)
- {
- if (reversed) bytes = bytes.Reverse(0, length);
- Push(bytes, 0, length);
- }
- /// <summary>
- /// 写入字节数组
- /// </summary>
- /// <param name="bytes"></param>
- /// <param name="reversed"></param>
- public void Push(byte[] bytes, bool reversed = false)
- {
- Push(bytes, bytes.Length, reversed);
- }
- /// <summary>
- /// 写入另一个<see cref="ByteBuffer"/>对象
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="reversed"></param>
- public void Push(ByteBuffer buffer, bool reversed = false)
- {
- if (buffer == null) return;
- if (buffer.ReadableBytes() <= 0) return;
- Push(buffer.ToArray(), reversed);
- }
- /// <summary>
- /// 写入一个<see cref="short"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- public void Push(short value, bool reversed = false)
- {
- Push((ushort)value, reversed);
- }
- /// <summary>
- /// 写入一个<see cref="ushort"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- 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);
- }
- /// <summary>
- /// 写入一个<see cref="int"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- public void Push(int value, bool reversed = false)
- {
- Push((uint)value);
- }
- /// <summary>
- /// 写入一个<see cref="uint"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- 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);
- }
- /// <summary>
- /// 写入一个<see cref="long"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- public void Push(long value, bool reversed = false)
- {
- Push((ulong)value);
- }
- /// <summary>
- /// 写入一个<see cref="ulong"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- 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);
- }
- /// <summary>
- /// 写入一个<see cref="float"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- public void Push(float value, bool reversed = false)
- {
- var buf = BitConverter.GetBytes(value);
- Push(buf, reversed);
- }
- /// <summary>
- /// 写入一个<see cref="byte"/>对象
- /// </summary>
- /// <param name="value"></param>
- public void Push(byte value)
- {
- lock (this)
- {
- int afterLen = WriteIndex + 1;
- int len = Buffer.Length;
- FixSizeAndReset(len, afterLen);
- Buffer[WriteIndex] = value;
- WriteIndex = afterLen;
- }
- }
- /// <summary>
- /// 写入一个<see cref="double"/>对象
- /// </summary>
- /// <param name="value"></param>
- /// <param name="reversed"></param>
- public void Push(double value, bool reversed = false)
- {
- var buf = BitConverter.GetBytes(value);
- Push(buf, reversed);
- }
- #endregion 压入对象
- #region pop出一个对象
- /// <summary>
- /// 读取一个<see cref="byte"/>
- /// </summary>
- /// <returns></returns>
- public byte PopByte()
- {
- byte b = Buffer[ReadIndex];
- ReadIndex++;
- return b;
- }
- /// <summary>
- /// 读取指定的<see cref="byte"/>[]
- /// </summary>
- /// <param name="len"></param>
- /// <param name="reversed"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 读取指定的<see cref="ushort"/>
- /// </summary>
- /// <returns></returns>
- public ushort PopUshort(bool reversed = false)
- {
- var buf = Pop(2, reversed);
- return (ushort)(buf[0] << 8 | buf[1]);
- }
- /// <summary>
- /// 读取指定的<see cref="ushort"/>
- /// </summary>
- /// <returns></returns>
- public char PopChar(bool reversed = false)
- {
- var buf = Pop(2, reversed);
- return (char)(buf[0] << 8 | buf[1]);
- }
- /// <summary>
- /// 读取指定的<see cref="short"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- public short PopShort(bool reversed = false)
- {
- var buf = Pop(2, reversed);
- return (short)(buf[0] << 8 | buf[1]);
- }
- /// <summary>
- /// 读取指定的<see cref="uint"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- public uint PopUint(bool reversed = false)
- {
- var buf = Pop(4, reversed);
- return (uint)(buf[0] << 0x18 | buf[1] << 0x10 | buf[2] << 0x8 | buf[3]);
- }
- /// <summary>
- /// 读取指定的<see cref="int"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- public int PopInt(bool reversed = false)
- {
- var buf = Pop(4, reversed);
- return buf[0] << 0x18 |
- buf[1] << 0x10 |
- buf[2] << 0x8 |
- buf[3];
- }
- /// <summary>
- /// 读取指定的<see cref="ulong"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- 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]);
- }
- /// <summary>
- /// 读取指定的<see cref="long"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- 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];
- }
- /// <summary>
- /// 读取指定的<see cref="float"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- public float PopFloat(bool reversed = false)
- {
- return BitConverter.ToSingle(Pop(4, reversed), 0);
- }
- /// <summary>
- /// 读取指定的<see cref="double"/>
- /// </summary>
- /// <param name="reversed"></param>
- /// <returns></returns>
- public double PopDouble(bool reversed = false)
- {
- return BitConverter.ToDouble(Pop(8, reversed), 0);
- }
- /// <summary>
- /// 读取指定长度的<see cref="byte"/>[]
- /// </summary>
- /// <param name="desBytes"></param>
- /// <param name="desStart"></param>
- /// <param name="len"></param>
- 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出一个对象
- /// <summary>
- /// 清除已读缓冲 后续队列前移
- /// </summary>
- 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;
- }
- /// <summary>
- /// 清空缓存
- /// </summary>
- public void Clear()
- {
- Buffer = new byte[Buffer.Length];
- ReadIndex = 0;
- WriteIndex = 0;
- MarkReadIndex = 0;
- MarkWirteIndex = 0;
- }
- /// <summary>
- /// 设置缓存读取位置
- /// </summary>
- /// <param name="index"></param>
- public void SetReaderIndex(int index)
- {
- if (index < 0) return;
- ReadIndex = index;
- }
- /// <summary>
- /// 标记当前读取的索引位置
- /// </summary>
- public void MarkReaderIndex()
- {
- MarkReadIndex = ReadIndex;
- }
- /// <summary>
- /// 标记当前写入的索引位置
- /// </summary>
- public void MarkWriterIndex()
- {
- MarkWirteIndex = WriteIndex;
- }
- /// <summary>
- /// 将读取的索引位置重置为标记的读取索引位置
- /// </summary>
- public void ResetReaderIndex()
- {
- ReadIndex = MarkReadIndex;
- }
- /// <summary>
- /// 将写入的索引位置重置为标记的写入索引位置
- /// </summary>
- public void ResetWriterIndex()
- {
- WriteIndex = MarkWirteIndex;
- }
- /// <summary>
- /// 剩余可读数量
- /// </summary>
- /// <returns></returns>
- public int ReadableBytes()
- {
- return WriteIndex - ReadIndex;
- }
- /// <summary>
- /// 剩余可读缓存转数组
- /// </summary>
- /// <returns></returns>
- 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;
- }
- }
- }
|