| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 | using System;using System.IO;namespace Houdar.Core.Communication.Transport{    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*4)        {            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        /// <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;        }    }}
 |