wah getting fucked up on endian business

This commit is contained in:
Lani Aung
2024-09-29 15:17:58 -06:00
parent 94ab274246
commit 6dbc577566
11 changed files with 2430 additions and 57 deletions
@@ -1,5 +0,0 @@
namespace fxl.codes.kisekae.data.Archives.Algorithms;
public class HuffmanDynamic : IAlgorithm
{
}
@@ -1,35 +0,0 @@
namespace fxl.codes.kisekae.data.Archives.Algorithms;
public class HuffmanNode
{
public HuffmanNode(char value)
{
}
public HuffmanNode(HuffmanNode left, HuffmanNode right)
{
Left = left;
Left.Side = HuffmanNodeSide.Left;
Left.Parent = this;
Right = right;
Right.Side = HuffmanNodeSide.Right;
Right.Parent = this;
Weight = left.Weight + right.Weight;
}
public char? Value { get; set; }
public int Weight { get; set; } = 1;
public HuffmanNode? Parent { get; set; }
public HuffmanNode? Left { get; set; }
public HuffmanNode? Right { get; set; }
public HuffmanNodeSide? Side { get; set; }
}
public enum HuffmanNodeSide
{
Left,
Right
}
@@ -1,5 +0,0 @@
namespace fxl.codes.kisekae.data.Archives.Algorithms;
public class HuffmanStatic : IAlgorithm
{
}
@@ -2,4 +2,6 @@ namespace fxl.codes.kisekae.data.Archives.Algorithms;
public interface IAlgorithm
{
byte[] Encode(ReadOnlySpan<byte> stream);
byte[] Decode(ReadOnlySpan<byte> stream);
}
@@ -0,0 +1,57 @@
using System.Text;
namespace fxl.codes.kisekae.data.Archives.Algorithms;
internal class LZW : IAlgorithm
{
private readonly int Max;
internal LZW(int max = short.MaxValue)
{
Max = max;
}
public byte[] Decode(ReadOnlySpan<byte> stream)
{
uint next = byte.MaxValue + 1;
var dictionary = new Dictionary<uint, string>();
for (uint i = 0; i <= byte.MaxValue; i++) dictionary.Add(i, $"{(char)i}");
var buffer = "";
var decoded = new List<string>();
for (var i = 0; i < stream.Length; i += 4)
{
var code = BitConverter.ToUInt32(stream[i..(i + 4)]);
if (!dictionary.ContainsKey(code)) dictionary[code] = buffer + buffer[0];
decoded.Add(dictionary[code]);
if (buffer.Length > 0 && next <= Max) dictionary[next++] = buffer + dictionary[code][0];
buffer = dictionary[code];
}
return decoded.SelectMany(Encoding.UTF8.GetBytes).ToArray();
}
public byte[] Encode(ReadOnlySpan<byte> stream)
{
var next = byte.MaxValue + 1;
var dictionary = new Dictionary<string, int>();
for (var i = 0; i <= byte.MaxValue; i++) dictionary.Add($"{(char)i}", i);
var buffer = "";
var encoded = new List<int>();
foreach (var part in stream)
{
var charValue = (char)part;
buffer += charValue;
if (dictionary.ContainsKey(buffer)) continue;
if (next <= Max) dictionary.Add(buffer, next++);
encoded.Add(dictionary[$"{buffer[..^1]}"]);
buffer = $"{charValue}";
}
encoded.Add(dictionary[buffer]);
return encoded.SelectMany(BitConverter.GetBytes).ToArray();
}
}
@@ -0,0 +1,79 @@
namespace fxl.codes.kisekae.data.Archives;
public class BitStream : Stream
{
private readonly Stream _stream;
private uint _bitBuffer;
private int _bitBufferCount;
private long _length;
public BitStream(Stream stream)
{
_stream = stream;
#if DEBUG
var min = Math.Min(stream.Length, 4);
var bytes = new byte[min];
_stream.ReadExactly(bytes);
var temp = BitConverter.ToUInt32(bytes);
Console.WriteLine($"BitStream first 4 bytes: {temp:b}");
_stream.Position = 0;
#endif
_length = _stream.Length * 8;
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => _length;
public override long Position { get; set; }
public uint ReadBits(int bitLength)
{
// Fill buffer
if (_bitBufferCount <= 24)
while (_bitBufferCount < 32 && _stream.Position < _stream.Length)
{
_bitBuffer <<= 8;
_bitBuffer |= (uint)_stream.ReadByte();
_bitBufferCount += 8;
}
var buffer = _bitBuffer;
buffer >>= 32 - bitLength;
#if DEBUG
Console.WriteLine($"BitStream buffer: {_bitBuffer:b}, extracted number: {buffer:b}");
_stream.Position = 0;
#endif
_bitBuffer <<= bitLength;
Position += bitLength;
_bitBufferCount -= bitLength;
return buffer;
}
public override void Flush()
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
_length = value;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
@@ -2,8 +2,9 @@ using fxl.codes.kisekae.data.Archives.Algorithms;
namespace fxl.codes.kisekae.data.Archives.LhMethods;
internal abstract class BaseLhMethod(LhContainer container, int slidingWindowBytes, int matchingWindowBytes, IAlgorithm? algorithm)
internal abstract class BaseLhMethod(LhContainer container, int slidingWindowBytes, int matchingWindowBytes, IAlgorithm? algorithm = null)
{
internal static readonly IAlgorithm Lzw = new LZW();
public int SlidingWindow => slidingWindowBytes * 1024;
public void InitializeAlgorithm()
@@ -11,22 +12,22 @@ internal abstract class BaseLhMethod(LhContainer container, int slidingWindowByt
}
}
internal class Lzs(LhContainer container) : BaseLhMethod(container, 2, 17, null);
internal class Lzs(LhContainer container) : BaseLhMethod(container, 2, 17);
internal class Lz4(LhContainer container) : BaseLhMethod(container, 0, 0, null);
internal class Lz4(LhContainer container) : BaseLhMethod(container, 0, 0);
internal class Lh0(LhContainer container) : BaseLhMethod(container, 0, 0, null);
internal class Lh0(LhContainer container) : BaseLhMethod(container, 0, 0);
internal class Lh1(LhContainer container) : BaseLhMethod(container, 4, 60, new HuffmanDynamic());
internal class Lh1(LhContainer container) : BaseLhMethod(container, 4, 60, Lzw);
internal class Lh2(LhContainer container) : BaseLhMethod(container, 8, 256, new HuffmanDynamic());
internal class Lh2(LhContainer container) : BaseLhMethod(container, 8, 256, Lzw);
internal class Lh3(LhContainer container) : BaseLhMethod(container, 8, 256, new HuffmanStatic());
internal class Lh3(LhContainer container) : BaseLhMethod(container, 8, 256, Lzw);
internal class Lh4(LhContainer container) : BaseLhMethod(container, 4, 256, new HuffmanStatic());
internal class Lh4(LhContainer container) : BaseLhMethod(container, 4, 256, Lzw);
internal class Lh5(LhContainer container) : BaseLhMethod(container, 8, 256, new HuffmanStatic());
internal class Lh5(LhContainer container) : BaseLhMethod(container, 8, 256, Lzw);
internal class Lh6(LhContainer container) : BaseLhMethod(container, 32, 256, new HuffmanStatic());
internal class Lh6(LhContainer container) : BaseLhMethod(container, 32, 256, Lzw);
internal class Lh7(LhContainer container) : BaseLhMethod(container, 64, 256, new HuffmanStatic());
internal class Lh7(LhContainer container) : BaseLhMethod(container, 64, 256, Lzw);