using System; using System.Collections.Generic; using System.Linq; using System.Text; using HslCommunication.Core; namespace HslCommunication.BasicFramework { /// /// 一个线程安全的缓存数据块,支持批量动态修改,添加,并获取快照 /// /// /// 这个类可以实现什么功能呢,就是你有一个大的数组,作为你的应用程序的中间数据池,允许你往byte[]数组里存放指定长度的子byte[]数组,也允许从里面拿数据, /// 这些操作都是线程安全的,当然,本类扩展了一些额外的方法支持,也可以直接赋值或获取基本的数据类型对象。 /// /// /// 此处举例一些数据的读写说明,可以此处的数据示例。 /// /// public class SoftBuffer : IDisposable { #region Constructor /// /// 使用默认的大小初始化缓存空间 /// public SoftBuffer( ) { buffer = new byte[capacity]; hybirdLock = new SimpleHybirdLock( ); byteTransform = new RegularByteTransform( ); } /// /// 使用指定的容量初始化缓存数据块 /// /// 初始化的容量 public SoftBuffer(int capacity ) { buffer = new byte[capacity]; this.capacity = capacity; hybirdLock = new SimpleHybirdLock( ); byteTransform = new RegularByteTransform( ); } #endregion #region Bool Operate Support /// /// 设置指定的位置的数据块,如果超出,则丢弃数据 /// /// bool值 /// 目标存储的索引 /// public void SetBool( bool value, int destIndex ) { SetBool( new bool[] { value }, destIndex ); } /// /// 设置指定的位置的数据块,如果超出,则丢弃数据 /// /// bool数组值 /// 目标存储的索引 /// 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; } } } /// /// 获取指定的位置的bool值,如果超出,则引发异常 /// /// 目标存储的索引 /// 获取索引位置的bool数据值 /// public bool GetBool( int destIndex ) { return GetBool( destIndex, 1 )[0]; } /// /// 获取指定位置的bool数组值,如果超过,则引发异常 /// /// 目标存储的索引 /// 读取的数组长度 /// /// bool数组值 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 /// /// 设置指定的位置的数据块,如果超出,则丢弃数据 /// /// 数据块信息 /// 目标存储的索引 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( ); } } /// /// 设置指定的位置的数据块,如果超出,则丢弃数据 /// /// 数据块信息 /// 目标存储的索引 /// 准备拷贝的数据长度 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( ); } } /// /// 设置指定的位置的数据块,如果超出,则丢弃数据 /// /// 数据块信息 /// Data中的起始位置 /// 目标存储的索引 /// 准备拷贝的数据长度 /// 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( ); } } /// /// 获取内存指定长度的数据信息 /// /// 起始位置 /// 数组长度 /// 返回实际的数据信息 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; } /// /// 获取内存所有的数据信息 /// /// 实际的数据信息 public byte[] GetBytes( ) { return GetBytes( 0, capacity ); } #endregion #region BCL Set Support /// /// 设置byte类型的数据到缓存区 /// /// byte数值 /// 索引位置 public void SetValue(byte value, int index ) { SetBytes( new byte[] { value }, index ); } /// /// 设置short类型的数据到缓存区 /// /// short数组 /// 索引位置 public void SetValue( short[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置short类型的数据到缓存区 /// /// short数值 /// 索引位置 public void SetValue( short value, int index ) { SetValue( new short[] { value }, index ); } /// /// 设置ushort类型的数据到缓存区 /// /// ushort数组 /// 索引位置 public void SetValue( ushort[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置ushort类型的数据到缓存区 /// /// ushort数值 /// 索引位置 public void SetValue( ushort value, int index ) { SetValue( new ushort[] { value }, index ); } /// /// 设置int类型的数据到缓存区 /// /// int数组 /// 索引位置 public void SetValue( int[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置int类型的数据到缓存区 /// /// int数值 /// 索引位置 public void SetValue( int value, int index ) { SetValue( new int[] { value }, index ); } /// /// 设置uint类型的数据到缓存区 /// /// uint数组 /// 索引位置 public void SetValue(uint[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置uint类型的数据到缓存区 /// /// uint数值 /// 索引位置 public void SetValue( uint value, int index ) { SetValue( new uint[] { value }, index ); } /// /// 设置float类型的数据到缓存区 /// /// float数组 /// 索引位置 public void SetValue( float[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置float类型的数据到缓存区 /// /// float数值 /// 索引位置 public void SetValue( float value, int index ) { SetValue( new float[] { value }, index ); } /// /// 设置long类型的数据到缓存区 /// /// long数组 /// 索引位置 public void SetValue( long[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置long类型的数据到缓存区 /// /// long数值 /// 索引位置 public void SetValue( long value, int index ) { SetValue( new long[] { value }, index ); } /// /// 设置ulong类型的数据到缓存区 /// /// ulong数组 /// 索引位置 public void SetValue( ulong[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置ulong类型的数据到缓存区 /// /// ulong数值 /// 索引位置 public void SetValue( ulong value, int index ) { SetValue( new ulong[] { value }, index ); } /// /// 设置double类型的数据到缓存区 /// /// double数组 /// 索引位置 public void SetValue( double[] values, int index ) { SetBytes( byteTransform.TransByte( values ), index ); } /// /// 设置double类型的数据到缓存区 /// /// double数值 /// 索引位置 public void SetValue( double value, int index ) { SetValue( new double[] { value }, index ); } #endregion #region BCL Get Support /// /// 获取byte类型的数据 /// /// 索引位置 /// byte数值 public byte GetByte( int index ) { return GetBytes( index, 1 )[0]; } /// /// 获取short类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// short数组 public short[] GetInt16( int index, int length ) { byte[] tmp = GetBytes( index, length * 2 ); return byteTransform.TransInt16( tmp, 0, length ); } /// /// 获取short类型的数据到缓存区 /// /// 索引位置 /// short数据 public short GetInt16( int index ) { return GetInt16( index, 1 )[0]; } /// /// 获取ushort类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// ushort数组 public ushort[] GetUInt16( int index, int length ) { byte[] tmp = GetBytes( index, length * 2 ); return byteTransform.TransUInt16( tmp, 0, length ); } /// /// 获取ushort类型的数据到缓存区 /// /// 索引位置 /// ushort数据 public ushort GetUInt16( int index ) { return GetUInt16( index, 1 )[0]; } /// /// 获取int类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// int数组 public int[] GetInt32( int index, int length ) { byte[] tmp = GetBytes( index, length * 4 ); return byteTransform.TransInt32( tmp, 0, length ); } /// /// 获取int类型的数据到缓存区 /// /// 索引位置 /// int数据 public int GetInt32( int index ) { return GetInt32( index, 1 )[0]; } /// /// 获取uint类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// uint数组 public uint[] GetUInt32( int index, int length ) { byte[] tmp = GetBytes( index, length * 4 ); return byteTransform.TransUInt32( tmp, 0, length ); } /// /// 获取uint类型的数据到缓存区 /// /// 索引位置 /// uint数据 public uint GetUInt32( int index ) { return GetUInt32( index, 1 )[0]; } /// /// 获取float类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// float数组 public float[] GetSingle( int index, int length ) { byte[] tmp = GetBytes( index, length * 4 ); return byteTransform.TransSingle( tmp, 0, length ); } /// /// 获取float类型的数据到缓存区 /// /// 索引位置 /// float数据 public float GetSingle( int index ) { return GetSingle( index, 1 )[0]; } /// /// 获取long类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// long数组 public long[] GetInt64( int index, int length ) { byte[] tmp = GetBytes( index, length * 8 ); return byteTransform.TransInt64( tmp, 0, length ); } /// /// 获取long类型的数据到缓存区 /// /// 索引位置 /// long数据 public long GetInt64( int index ) { return GetInt64( index, 1 )[0]; } /// /// 获取ulong类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// ulong数组 public ulong[] GetUInt64( int index, int length ) { byte[] tmp = GetBytes( index, length * 8 ); return byteTransform.TransUInt64( tmp, 0, length ); } /// /// 获取ulong类型的数据到缓存区 /// /// 索引位置 /// ulong数据 public ulong GetUInt64( int index ) { return GetUInt64( index, 1 )[0]; } /// /// 获取double类型的数组到缓存区 /// /// 索引位置 /// 数组长度 /// ulong数组 public double[] GetDouble( int index, int length ) { byte[] tmp = GetBytes( index, length * 8 ); return byteTransform.TransDouble( tmp, 0, length ); } /// /// 获取double类型的数据到缓存区 /// /// 索引位置 /// double数据 public double GetDouble( int index ) { return GetDouble( index, 1 )[0]; } #endregion #region Customer Support /// /// 读取自定义类型的数据,需要规定解析规则 /// /// 类型名称 /// 起始索引 /// 自定义的数据类型 public T GetCustomer( int index ) where T : IDataTransfer, new() { T Content = new T( ); byte[] read = GetBytes( index, Content.ReadCount ); Content.ParseSource( read ); return Content; } /// /// 写入自定义类型的数据到缓存中去,需要规定生成字节的方法 /// /// 自定义类型 /// 实例对象 /// 起始地址 public void SetCustomer( T data, int index ) where T : IDataTransfer, new() { SetBytes( data.ToSource( ), index ); } #endregion #region Public Properties /// /// 获取或设置当前的数据缓存类的解析规则 /// 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 #region IDisposable Support private bool disposedValue = false; // 要检测冗余调用 /// /// 释放当前的对象 /// /// protected virtual void Dispose( bool disposing ) { if (!disposedValue) { if (disposing) { // TODO: 释放托管状态(托管对象)。 hybirdLock?.Dispose( ); buffer = null; } // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。 // TODO: 将大型字段设置为 null。 disposedValue = true; } } // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。 // ~SoftBuffer() // { // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 // Dispose(false); // } // 添加此代码以正确实现可处置模式。 /// /// 释放当前的对象 /// public void Dispose( ) { // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 Dispose( true ); // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。 // GC.SuppressFinalize(this); } #endregion } }