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
}
}