using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
// ReSharper disable InconsistentNaming
namespace OpenVIII
{
///
/// NEW LZSS
/// LZSS.C -- A Data Compression Program
/// (tab = 4 spaces)
/// 4/6/1989 Haruhiko Okumura
/// Use, distribute, and modify this program freely.
/// Please send me your improved versions.
/// PC-VAN SCIENCE
/// NIFTY-Serve PAF01022
/// CompuServe 74050,1022
///
public class LZSS
{
#region Fields
private const int EOF = -1;
private const int F = 18;
private const int N = 4096;
private const int THRESHOLD = 2;
#endregion Fields
#region Methods
public static byte[] DecompressAllNew(byte[] data, int uncompressedSize, bool skip = false)
{
if (uncompressedSize < 0) throw new ArgumentOutOfRangeException(nameof(uncompressedSize)); // if 0 ignore checks.
//Memory.Log.WriteLine($"{nameof(LZSS)}::{nameof(DecompressAllNew)} :: decompressing data");
byte[] outFileArray;
using (var infile = new MemoryStream(!skip ? data : data.Skip(4).ToArray()))
{
Decode(infile, out outFileArray);
}
if (uncompressedSize > 0 && outFileArray.Length != uncompressedSize)
throw new InvalidDataException($"{nameof(LZSS)}::{nameof(DecompressAllNew)} Expected size ({uncompressedSize}) != ({outFileArray.Length})");
return outFileArray;
}
//Code borrowed from Java's implementation of LZSS by antiquechrono
private static void Decode(Stream infile, out byte[] outFileArray)
{
var outfile = new List();
var textBuf = new int[N + F - 1]; // ring buffer of size N, with extra F-1 bytes to facilitate string comparison
var r = N - F; var flags = 0;
for (; ; )
{
int c;
if (((flags >>= 1) & 256) == 0)
{
if ((c = infile.ReadByte()) == EOF) break;
flags = c | 0xff00; // uses higher byte cleverly
} // to Count eight
if ((flags & 1) == 1)
{
if ((c = infile.ReadByte()) == EOF) break;
outfile.Add((byte)c);
textBuf[r++] = c;
r &= (N - 1);
}
else
{
int i;
if ((i = infile.ReadByte()) == EOF) break;
int j;
if ((j = infile.ReadByte()) == EOF) break;
i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
int k;
for (k = 0; k <= j; k++)
{
c = textBuf[(i + k) & (N - 1)];
outfile.Add((byte)c);
textBuf[r++] = c;
r &= (N - 1);
}
}
}
outFileArray = outfile.ToArray();
}
#endregion Methods
}
}