using NPOI.SS.Formula.Functions; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; namespace InABox.DigitalMatter { public interface IDMBuffer { /// /// The remaining size of the buffer. /// public ushort BufferSize { get; } #region Bit Manipulation private static bool[] DecodeBits(byte[] value, int index, int length) { var result = new List(); var array = new BitArray(value); for (var i = index; i < index + length && i < array.Count; i++) result.Add(array[i]); return result.ToArray(); } private static byte[] EncodeBits(byte[] source, int index, bool[] bits) { var array = new BitArray(source); for (var i = 0; i < bits.Length; i++) array.Set(index + i, bits[i]); var result = new byte[source.Length]; array.CopyTo(result, 0); return result; } public static bool[] GetBits(byte[] value, int index, int length) { return DecodeBits(value, index, length); } public static byte[] SetBits(byte[] value, int index, bool[] bits) { return EncodeBits(value, index, bits); } public static bool[] DecodeByte(byte value, int index, int length) { return DecodeBits(new[] { value }, index, length); } public static bool[] DecodeBytes(byte[] value, int index, int length) { return DecodeBits(value, index, length); } public static bool[] DecodeInt8(sbyte value, int index, int length) { return DecodeBits(new[] { Convert.ToByte(value) }, index, length); } public static bool[] DecodeInt16(short value, int index, int length) { return DecodeBits(BitConverter.GetBytes(value), index, length); } public static bool[] DecodeUInt16(ushort value, int index, int length) { return DecodeBits(BitConverter.GetBytes(value), index, length); } public static bool[] DecodeInt32(int value, int index, int length) { return DecodeBits(BitConverter.GetBytes(value), index, length); } public static bool[] DecodeUInt32(uint value, int index, int length) { return DecodeBits(BitConverter.GetBytes(value), index, length); } public static byte EncodeByte(bool[] bits) { return EncodeBits(new byte[] { default }, 0, bits).First(); } public static byte[] EncodeBytes(bool[] bits, int size) { return EncodeBits(Array.CreateInstance(typeof(byte), size).OfType().ToArray(), 0, bits); } public static sbyte EncodeInt8(bool[] bits) { return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(default(sbyte)) }, 0, bits).First()); } public static short EncodeInt16(bool[] bits) { return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(default(short)), 0, bits), 0); } public static ushort EncodeUInt16(bool[] bits) { return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(default(ushort)), 0, bits), 0); } public static int EncodeInt32(bool[] bits) { return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(default(int)), 0, bits), 0); } public static uint EncodeUInt32(bool[] bits) { return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(default(uint)), 0, bits), 0); } public static byte UpdateByte(byte value, int index, bool[] bits) { return EncodeBits(new[] { value }, index, bits).First(); } public static byte[] UpdateBytes(byte[] value, int index, bool[] bits, int size) { return EncodeBits(value, 0, bits); } public static sbyte UpdateInt8(sbyte value, int index, bool[] bits) { return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(value) }, 0, bits).First()); } public static short UpdateInt16(short value, int index, bool[] bits) { return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0); } public static ushort UpdateUInt16(ushort value, int index, bool[] bits) { return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0); } public static int UpdateInt32(int value, int index, bool[] bits) { return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0); } public static uint UpdateUInt32(uint value, int index, bool[] bits) { return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0); } #endregion } public interface IDMReadBuffer : IDMBuffer { /// /// Read bytes, starting at , but don't advance the read pointer. /// /// Index to start the read. /// Number of bytes to read. /// The bytes read. protected byte[] Peek(int index, int length); /// /// Read bytes, advancing the read pointer by . /// /// Number of bytes to read. /// The bytes read. protected byte[] Take(int length); public byte PeekByte(int index) { return Peek(index, sizeof(byte)).First(); } public byte[] PeekBytes(int index, int length) { return Peek(index, length); } public sbyte PeekInt8(int index) { return unchecked((sbyte)PeekByte(index)); //hmmm... } public ushort PeekUInt16(int index) { return BitConverter.ToUInt16(Peek(index, sizeof(ushort)), 0); } public short PeekInt16(int index) { return BitConverter.ToInt16(Peek(index, sizeof(short)), 0); } public uint PeekUInt32(int index) { return BitConverter.ToUInt32(Peek(index, sizeof(uint)), 0); } public int PeekInt32(int index) { return BitConverter.ToInt32(Peek(index, sizeof(int)), 0); } public string PeekString(int index, int length) { return Encoding.Default.GetString(Peek(index, length)).Trim(); } public byte TakeByte() { return Take(sizeof(byte)).First(); } public byte[] TakeBytes(int length) { return Take(length); } public sbyte TakeInt8() { return unchecked((sbyte)TakeByte()); //hmmm... } public ushort TakeUInt16() { return BitConverter.ToUInt16(Take(sizeof(ushort)), 0); } public short TakeInt16() { return BitConverter.ToInt16(Take(sizeof(short)), 0); } public uint TakeUInt32() { return BitConverter.ToUInt32(Take(sizeof(uint)), 0); } public int TakeInt32() { return BitConverter.ToInt32(Take(sizeof(int)), 0); } public string TakeString(int length) { return Encoding.Default.GetString(Take(length)).Trim(); } } public interface IDMWriteBuffer : IDMBuffer { protected ushort Add(byte[] bytes); protected ushort Insert(int index, byte[] bytes); void Reset(); public ushort AddByte(byte value) { return Add(new[] { value }); } public ushort AddBytes(byte[] value) { return Add(value); } public ushort AddInt8(sbyte value) { return Add(BitConverter.GetBytes(value)); } public ushort AddUInt16(ushort value) { return Add(BitConverter.GetBytes(value)); } public ushort AddInt16(short value) { return Add(BitConverter.GetBytes(value)); } public ushort AddUInt32(uint value) { return Add(BitConverter.GetBytes(value)); } public ushort AddInt32(int value) { return Add(BitConverter.GetBytes(value)); } public ushort AddString(string value, int length) { return Add(FixedLengthString(value, length)); } public ushort InsertByte(int index, byte value) { return Insert(index, new[] { value }); } public ushort InsertBytes(int index, byte[] value) { return Insert(index, value); } public ushort InsertInt8(int index, sbyte value) { return Insert(index, BitConverter.GetBytes(value)); } public ushort InsertUInt16(int index, ushort value) { return Insert(index, BitConverter.GetBytes(value)); } public ushort InsertInt16(int index, short value) { return Insert(index, BitConverter.GetBytes(value)); } public ushort InsertUInt32(int index, uint value) { return Insert(index, BitConverter.GetBytes(value)); } public ushort InsertInt32(int index, int value) { return Insert(index, BitConverter.GetBytes(value)); } public ushort InsertString(int index, string value, int length) { return Insert(index, FixedLengthString(value, length)); } #region Private Members private static byte[] FixedLengthString(string value, int length) { var result = Encoding.Default.GetBytes(value).ToList(); while (result.Count < length) result.Add(0x00); return result.ToArray(); } #endregion } public class DMArrayReadBuffer : IDMReadBuffer { private byte[] _buffer { get; set; } private int _offset; public ushort BufferSize => (ushort)(_buffer.Length - _offset); public DMArrayReadBuffer(byte[] buffer) { _buffer = buffer; _offset = 0; } byte[] IDMReadBuffer.Peek(int index, int length) { index += _offset; length = Math.Min(length, _buffer.Length - index); var newBytes = new byte[length]; Buffer.BlockCopy(_buffer, index, newBytes, 0, length); return newBytes; } byte[] IDMReadBuffer.Take(int length) { length = Math.Min(length, _buffer.Length - _offset); var newBytes = new byte[length]; Buffer.BlockCopy(_buffer, _offset, newBytes, 0, length); _offset += length; return newBytes; } } public class DMListReadBuffer : IDMReadBuffer { private List _buffer { get; set; } private int _offset; public ushort BufferSize => (ushort)(_buffer.Count - _offset); public DMListReadBuffer(List buffer) { _buffer = buffer; _offset = 0; } byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length); private byte[] Peek(int index, int length) { index += _offset; length = Math.Min(length, _buffer.Count - index); var newBytes = new byte[length]; _buffer.CopyTo(index, newBytes, 0, length); return newBytes; } byte[] IDMReadBuffer.Take(int length) { var result = Peek(0, length); _offset += length; return result; } } public class DMPartialReadBuffer : IDMReadBuffer { private ushort _offset; private ushort _length; public IDMReadBuffer Buffer { get; } public ushort BufferSize => (ushort)(_length - (Offset - _offset)); public ushort Offset { get; private set; } public DMPartialReadBuffer(IDMReadBuffer buffer, ushort offset, ushort length) { _length = length; _offset = offset; Offset = offset; Buffer = buffer; } byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length); private byte[] Peek(int index, int length) { index += Offset; length = Math.Min(length, _offset + _length - index); return Buffer.PeekBytes(index, length); } byte[] IDMReadBuffer.Take(int length) { var bytes = Peek(0, length); Offset += (ushort)bytes.Length; return bytes; } } public class DMListWriteBuffer : IDMWriteBuffer { private List _buffer { get; set; } private int _offset; public List Buffer => _buffer; public ushort BufferSize => (ushort)(_buffer.Count - _offset); public DMListWriteBuffer(List buffer) { _buffer = buffer; _offset = 0; } public void Reset() { _buffer.Clear(); } ushort IDMWriteBuffer.Add(byte[] bytes) { _buffer.AddRange(bytes); return BufferSize; } ushort IDMWriteBuffer.Insert(int index, byte[] bytes) { _buffer.InsertRange(index, bytes); return BufferSize; } } public class DMBuffer : IDMReadBuffer, IDMWriteBuffer { public byte[] Buffer { get => _buffer.ToArray(); set => _buffer = value.ToList(); } public DMBuffer() { } public DMBuffer(byte[] buffer) { Buffer = buffer; } public DMBuffer(List buffer) { _buffer = buffer; } public ushort BufferSize => (ushort)_buffer.Count; public void Reset() { _buffer = new List(); } #region Private Members private List _buffer = new(); ushort IDMWriteBuffer.Add(byte[] bytes) { _buffer.AddRange(bytes); return BufferSize; } ushort IDMWriteBuffer.Insert(int index, byte[] bytes) { _buffer.InsertRange(index, bytes); return BufferSize; } private byte[] Peek(int index, int length) { return _buffer.Skip(index).Take(length).ToArray(); } byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length); byte[] IDMReadBuffer.Take(int length) { var result = Peek(0, length); _buffer.RemoveRange(0, length); return result; } #endregion } }