123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using MECF.Framework.RT.Core.IoProviders.Common.Net;
- using MECF.Framework.RT.Core.ThreadLock;
- namespace MECF.Framework.RT.Core.IoProviders.Common.Transfer
- {
- /// <summary>
- /// 一个线程安全的缓存数据块,支持批量动态修改,添加,并获取快照
- /// </summary>
- /// <remarks>
- /// 这个类可以实现什么功能呢,就是你有一个大的数组,作为你的应用程序的中间数据池,允许你往byte[]数组里存放指定长度的子byte[]数组,也允许从里面拿数据,
- /// 这些操作都是线程安全的,当然,本类扩展了一些额外的方法支持,也可以直接赋值或获取基本的数据类型对象。
- /// </remarks>
- /// <example>
- /// 此处举例一些数据的读写说明,可以此处的数据示例。
- /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\BasicFramework\SoftBufferExample.cs" region="SoftBufferExample1" title="SoftBuffer示例" />
- /// </example>
- public class SoftBuffer
- {
- #region Constructor
- /// <summary>
- /// 使用默认的大小初始化缓存空间
- /// </summary>
- public SoftBuffer()
- {
- buffer = new byte[capacity];
- hybirdLock = new SimpleHybirdLock();
- byteTransform = new RegularByteTransform();
- }
- /// <summary>
- /// 使用指定的容量初始化缓存数据块
- /// </summary>
- /// <param name="capacity">初始化的容量</param>
- public SoftBuffer(int capacity)
- {
- buffer = new byte[capacity];
- this.capacity = capacity;
- hybirdLock = new SimpleHybirdLock();
- byteTransform = new RegularByteTransform();
- }
- #endregion
- #region Bool Operate Support
- /// <summary>
- /// 设置指定的位置的数据块,如果超出,则丢弃数据
- /// </summary>
- /// <param name="value">bool值</param>
- /// <param name="destIndex">目标存储的索引</param>
- /// <exception cref="IndexOutOfRangeException"></exception>
- public void SetBool(bool value, int destIndex)
- {
- SetBool(new bool[] { value }, destIndex);
- }
- /// <summary>
- /// 设置指定的位置的数据块,如果超出,则丢弃数据
- /// </summary>
- /// <param name="value">bool数组值</param>
- /// <param name="destIndex">目标存储的索引</param>
- /// <exception cref="IndexOutOfRangeException"></exception>
- public void SetBool(bool[] value, int destIndex)
- {
- if (value != null)
- {
- try
- {
- hybirdLock.Enter();
- for (int i = 0; i < value.Length; i++)
- {
- int byteIndex = (destIndex + i) / 8;
- int offect = (destIndex + i) % 8;
- if (value[i])
- {
- buffer[byteIndex] = (byte)(buffer[byteIndex] | getOrByte(offect));
- }
- else
- {
- buffer[byteIndex] = (byte)(buffer[byteIndex] & getAndByte(offect));
- }
- }
- hybirdLock.Leave();
- }
- catch
- {
- hybirdLock.Leave();
- throw;
- }
- }
- }
- /// <summary>
- /// 获取指定的位置的bool值,如果超出,则引发异常
- /// </summary>
- /// <param name="destIndex">目标存储的索引</param>
- /// <returns>获取索引位置的bool数据值</returns>
- /// <exception cref="IndexOutOfRangeException"></exception>
- public bool GetBool(int destIndex)
- {
- return GetBool(destIndex, 1)[0];
- }
- /// <summary>
- /// 获取指定位置的bool数组值,如果超过,则引发异常
- /// </summary>
- /// <param name="destIndex">目标存储的索引</param>
- /// <param name="length">读取的数组长度</param>
- /// <exception cref="IndexOutOfRangeException"></exception>
- /// <returns>bool数组值</returns>
- public bool[] GetBool(int destIndex, int length)
- {
- bool[] result = new bool[length];
- try
- {
- hybirdLock.Enter();
- for (int i = 0; i < length; i++)
- {
- int byteIndex = (destIndex + i) / 8;
- int offect = (destIndex + i) % 8;
- result[i] = (buffer[byteIndex] & getOrByte(offect)) == getOrByte(offect);
- }
- hybirdLock.Leave();
- }
- catch
- {
- hybirdLock.Leave();
- throw;
- }
- return result;
- }
- private byte getAndByte(int offect)
- {
- switch (offect)
- {
- case 0: return 0xFE;
- case 1: return 0xFD;
- case 2: return 0xFB;
- case 3: return 0xF7;
- case 4: return 0xEF;
- case 5: return 0xDF;
- case 6: return 0xBF;
- case 7: return 0x7F;
- default: return 0xFF;
- }
- }
- private byte getOrByte(int offect)
- {
- switch (offect)
- {
- case 0: return 0x01;
- case 1: return 0x02;
- case 2: return 0x04;
- case 3: return 0x08;
- case 4: return 0x10;
- case 5: return 0x20;
- case 6: return 0x40;
- case 7: return 0x80;
- default: return 0x00;
- }
- }
- #endregion
- #region Byte Operate Support
- /// <summary>
- /// 设置指定的位置的数据块,如果超出,则丢弃数据
- /// </summary>
- /// <param name="data">数据块信息</param>
- /// <param name="destIndex">目标存储的索引</param>
- public void SetBytes(byte[] data, int destIndex)
- {
- if (destIndex < capacity && destIndex >= 0 && data != null)
- {
- hybirdLock.Enter();
- if ((data.Length + destIndex) > buffer.Length)
- {
- Array.Copy(data, 0, buffer, destIndex, (buffer.Length - destIndex));
- }
- else
- {
- data.CopyTo(buffer, destIndex);
- }
- hybirdLock.Leave();
- }
- }
- /// <summary>
- /// 设置指定的位置的数据块,如果超出,则丢弃数据
- /// </summary>
- /// <param name="data">数据块信息</param>
- /// <param name="destIndex">目标存储的索引</param>
- /// <param name="length">准备拷贝的数据长度</param>
- public void SetBytes(byte[] data, int destIndex, int length)
- {
- if (destIndex < capacity && destIndex >= 0 && data != null)
- {
- if (length > data.Length) length = data.Length;
- hybirdLock.Enter();
- if ((length + destIndex) > buffer.Length)
- {
- Array.Copy(data, 0, buffer, destIndex, (buffer.Length - destIndex));
- }
- else
- {
- Array.Copy(data, 0, buffer, destIndex, length);
- }
- hybirdLock.Leave();
- }
- }
- /// <summary>
- /// 设置指定的位置的数据块,如果超出,则丢弃数据
- /// </summary>
- /// <param name="data">数据块信息</param>
- /// <param name="sourceIndex">Data中的起始位置</param>
- /// <param name="destIndex">目标存储的索引</param>
- /// <param name="length">准备拷贝的数据长度</param>
- /// <exception cref="IndexOutOfRangeException"></exception>
- public void SetBytes(byte[] data, int sourceIndex, int destIndex, int length)
- {
- if (destIndex < capacity && destIndex >= 0 && data != null)
- {
- if (length > data.Length) length = data.Length;
- hybirdLock.Enter();
- Array.Copy(data, sourceIndex, buffer, destIndex, length);
- hybirdLock.Leave();
- }
- }
- /// <summary>
- /// 获取内存指定长度的数据信息
- /// </summary>
- /// <param name="index">起始位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>返回实际的数据信息</returns>
- public byte[] GetBytes(int index, int length)
- {
- byte[] result = new byte[length];
- if (length > 0)
- {
- hybirdLock.Enter();
- if (index >= 0 && (index + length) <= buffer.Length)
- {
- Array.Copy(buffer, index, result, 0, length);
- }
- hybirdLock.Leave();
- }
- return result;
- }
- /// <summary>
- /// 获取内存所有的数据信息
- /// </summary>
- /// <returns>实际的数据信息</returns>
- public byte[] GetBytes()
- {
- return GetBytes(0, capacity);
- }
- #endregion
- #region BCL Set Support
- /// <summary>
- /// 设置byte类型的数据到缓存区
- /// </summary>
- /// <param name="value">byte数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(byte value, int index)
- {
- SetBytes(new byte[] { value }, index);
- }
- /// <summary>
- /// 设置short类型的数据到缓存区
- /// </summary>
- /// <param name="values">short数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(short[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置short类型的数据到缓存区
- /// </summary>
- /// <param name="value">short数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(short value, int index)
- {
- SetValue(new short[] { value }, index);
- }
- /// <summary>
- /// 设置ushort类型的数据到缓存区
- /// </summary>
- /// <param name="values">ushort数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(ushort[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置ushort类型的数据到缓存区
- /// </summary>
- /// <param name="value">ushort数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(ushort value, int index)
- {
- SetValue(new ushort[] { value }, index);
- }
- /// <summary>
- /// 设置int类型的数据到缓存区
- /// </summary>
- /// <param name="values">int数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(int[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置int类型的数据到缓存区
- /// </summary>
- /// <param name="value">int数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(int value, int index)
- {
- SetValue(new int[] { value }, index);
- }
- /// <summary>
- /// 设置uint类型的数据到缓存区
- /// </summary>
- /// <param name="values">uint数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(uint[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置uint类型的数据到缓存区
- /// </summary>
- /// <param name="value">uint数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(uint value, int index)
- {
- SetValue(new uint[] { value }, index);
- }
- /// <summary>
- /// 设置float类型的数据到缓存区
- /// </summary>
- /// <param name="values">float数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(float[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置float类型的数据到缓存区
- /// </summary>
- /// <param name="value">float数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(float value, int index)
- {
- SetValue(new float[] { value }, index);
- }
- /// <summary>
- /// 设置long类型的数据到缓存区
- /// </summary>
- /// <param name="values">long数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(long[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置long类型的数据到缓存区
- /// </summary>
- /// <param name="value">long数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(long value, int index)
- {
- SetValue(new long[] { value }, index);
- }
- /// <summary>
- /// 设置ulong类型的数据到缓存区
- /// </summary>
- /// <param name="values">ulong数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(ulong[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置ulong类型的数据到缓存区
- /// </summary>
- /// <param name="value">ulong数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(ulong value, int index)
- {
- SetValue(new ulong[] { value }, index);
- }
- /// <summary>
- /// 设置double类型的数据到缓存区
- /// </summary>
- /// <param name="values">double数组</param>
- /// <param name="index">索引位置</param>
- public void SetValue(double[] values, int index)
- {
- SetBytes(byteTransform.TransByte(values), index);
- }
- /// <summary>
- /// 设置double类型的数据到缓存区
- /// </summary>
- /// <param name="value">double数值</param>
- /// <param name="index">索引位置</param>
- public void SetValue(double value, int index)
- {
- SetValue(new double[] { value }, index);
- }
- #endregion
- #region BCL Get Support
- /// <summary>
- /// 获取byte类型的数据
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>byte数值</returns>
- public byte GetByte(int index)
- {
- return GetBytes(index, 1)[0];
- }
- /// <summary>
- /// 获取short类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>short数组</returns>
- public short[] GetInt16(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 2);
- return byteTransform.TransInt16(tmp, 0, length);
- }
- /// <summary>
- /// 获取short类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>short数据</returns>
- public short GetInt16(int index)
- {
- return GetInt16(index, 1)[0];
- }
- /// <summary>
- /// 获取ushort类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>ushort数组</returns>
- public ushort[] GetUInt16(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 2);
- return byteTransform.TransUInt16(tmp, 0, length);
- }
- /// <summary>
- /// 获取ushort类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>ushort数据</returns>
- public ushort GetUInt16(int index)
- {
- return GetUInt16(index, 1)[0];
- }
- /// <summary>
- /// 获取int类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>int数组</returns>
- public int[] GetInt32(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 4);
- return byteTransform.TransInt32(tmp, 0, length);
- }
- /// <summary>
- /// 获取int类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>int数据</returns>
- public int GetInt32(int index)
- {
- return GetInt32(index, 1)[0];
- }
- /// <summary>
- /// 获取uint类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>uint数组</returns>
- public uint[] GetUInt32(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 4);
- return byteTransform.TransUInt32(tmp, 0, length);
- }
- /// <summary>
- /// 获取uint类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>uint数据</returns>
- public uint GetUInt32(int index)
- {
- return GetUInt32(index, 1)[0];
- }
- /// <summary>
- /// 获取float类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>float数组</returns>
- public float[] GetSingle(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 4);
- return byteTransform.TransSingle(tmp, 0, length);
- }
- /// <summary>
- /// 获取float类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>float数据</returns>
- public float GetSingle(int index)
- {
- return GetSingle(index, 1)[0];
- }
- /// <summary>
- /// 获取long类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>long数组</returns>
- public long[] GetInt64(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 8);
- return byteTransform.TransInt64(tmp, 0, length);
- }
- /// <summary>
- /// 获取long类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>long数据</returns>
- public long GetInt64(int index)
- {
- return GetInt64(index, 1)[0];
- }
- /// <summary>
- /// 获取ulong类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>ulong数组</returns>
- public ulong[] GetUInt64(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 8);
- return byteTransform.TransUInt64(tmp, 0, length);
- }
- /// <summary>
- /// 获取ulong类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>ulong数据</returns>
- public ulong GetUInt64(int index)
- {
- return GetUInt64(index, 1)[0];
- }
- /// <summary>
- /// 获取double类型的数组到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <param name="length">数组长度</param>
- /// <returns>ulong数组</returns>
- public double[] GetDouble(int index, int length)
- {
- byte[] tmp = GetBytes(index, length * 8);
- return byteTransform.TransDouble(tmp, 0, length);
- }
- /// <summary>
- /// 获取double类型的数据到缓存区
- /// </summary>
- /// <param name="index">索引位置</param>
- /// <returns>double数据</returns>
- public double GetDouble(int index)
- {
- return GetDouble(index, 1)[0];
- }
- #endregion
- #region Customer Support
- /// <summary>
- /// 读取自定义类型的数据,需要规定解析规则
- /// </summary>
- /// <typeparam name="T">类型名称</typeparam>
- /// <param name="index">起始索引</param>
- /// <returns>自定义的数据类型</returns>
- public T GetCustomer<T>(int index) where T : IDataTransfer, new()
- {
- T Content = new T();
- byte[] read = GetBytes(index, Content.ReadCount);
- Content.ParseSource(read);
- return Content;
- }
- /// <summary>
- /// 写入自定义类型的数据到缓存中去,需要规定生成字节的方法
- /// </summary>
- /// <typeparam name="T">自定义类型</typeparam>
- /// <param name="data">实例对象</param>
- /// <param name="index">起始地址</param>
- public void SetCustomer<T>(T data, int index) where T : IDataTransfer, new()
- {
- SetBytes(data.ToSource(), index);
- }
- #endregion
- #region Public Properties
- /// <summary>
- /// 获取或设置当前的数据缓存类的解析规则
- /// </summary>
- public IByteTransform ByteTransform
- {
- get => byteTransform;
- set => byteTransform = value;
- }
- #endregion
- #region Private Member
- private int capacity = 10; // 缓存的容量
- private byte[] buffer; // 缓存的数据
- private SimpleHybirdLock hybirdLock; // 高效的混合锁
- private IByteTransform byteTransform; // 数据转换类
- #endregion
- }
- }
|