Skip to content

Instantly share code, notes, and snippets.

@dimzon
Created September 22, 2017 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dimzon/4345d45a52336f461fad8786355e0038 to your computer and use it in GitHub Desktop.
Save dimzon/4345d45a52336f461fad8786355e0038 to your computer and use it in GitHub Desktop.
Stripped and minified sigle-file drop-in 100% managed LZMA-Alone stream decoder
/***********************************************************************************************
* Stripped and minified sigle-file drop-in 100% managed LZMA-Alone stream decoder.
* Compiled IL takes approx 10Kb only.
*
* Original code taken from LZMA SDK http://www.7-zip.org/sdk.html
*
* Decoder is placed in the public domain.
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute the
* original code, either in source code form or as a compiled binary,
* for any purpose, commercial or non-commercial, and by any means.
***********************************************************************************************/
using System;
using System.IO;
// ReSharper disable RedundantNameQualifier
// ReSharper disable CheckNamespace
// ReSharper disable SuggestVarOrType_Elsewhere
// ReSharper disable SuggestVarOrType_SimpleTypes
// ReSharper disable SuggestVarOrType_BuiltInTypes
// ReSharper disable InconsistentNaming
// ReSharper disable ArrangeThisQualifier
// ReSharper disable RedundantCast
// ReSharper disable LocalVariableHidesMember
// ReSharper disable ArrangeStaticMemberQualifier
// ReSharper disable ArrangeRedundantParentheses
public static class UnLzma
{
public static void Decompress(Stream inputStream, Stream outputStream)
{
UnLzma.V v = new UnLzma.V();
byte[] array = new byte[5];
inputStream.Read(array, 0, 5);
v.C(array);
for (int i = 0; i < 8; i++)
inputStream.ReadByte();
v.B(inputStream, outputStream, -1L);
}
private struct Z
{
private readonly UnLzma.Y[] a;
private readonly int b;
internal Z(int z)
{
this.b = z;
this.a = new UnLzma.Y[1 << z];
}
internal void A()
{
uint num = 1u;
while ((ulong)num < 1uL << (this.b & 31))
{
this.a[(int)((uint)((UIntPtr)num))].A();
num += 1u;
}
}
internal uint B(UnLzma.X z)
{
uint num = 1u;
for (int i = this.b; i > 0; i--)
{
num = (num << 1) + this.a[(int)((uint)((UIntPtr)num))].B(z);
}
return num - (1u << this.b);
}
internal uint C(UnLzma.X z)
{
uint num = 1u;
uint num2 = 0u;
for (int i = 0; i < this.b; i++)
{
uint num3 = this.a[(int)((uint)((UIntPtr)num))].B(z);
num <<= 1;
num += num3;
num2 |= num3 << i;
}
return num2;
}
internal static uint D(UnLzma.Y[] z, uint y, UnLzma.X x, int w)
{
uint num = 1u;
uint num2 = 0u;
for (int i = 0; i < w; i++)
{
uint num3 = z[(int)((uint)((UIntPtr)(y + num)))].B(x);
num <<= 1;
num += num3;
num2 |= num3 << i;
}
return num2;
}
}
private struct Y
{
private uint a;
internal void A()
{
this.a = 1024u;
}
internal uint B(UnLzma.X z)
{
uint num = (z.b >> 11) * this.a;
uint result;
if (z.a < num)
{
z.b = num;
this.a += 2048u - this.a >> 5;
if (z.b < 16777216u)
{
z.a = (z.a << 8 | (uint)((byte)z.c.ReadByte()));
z.b <<= 8;
}
result = 0u;
}
else
{
z.b -= num;
z.a -= num;
this.a -= this.a >> 5;
if (z.b < 16777216u)
{
z.a = (z.a << 8 | (uint)((byte)z.c.ReadByte()));
z.b <<= 8;
}
result = 1u;
}
return result;
}
}
private class X
{
internal uint a;
internal uint b;
internal Stream c;
internal void A(Stream z)
{
this.c = z;
this.a = 0u;
this.b = 4294967295u;
for (int i = 0; i < 5; i++)
{
this.a = (this.a << 8 | (uint)((byte)this.c.ReadByte()));
}
}
internal void B()
{
this.c = null;
}
internal uint C(int z)
{
uint num = this.b;
uint num2 = this.a;
uint num3 = 0u;
for (int i = z; i > 0; i--)
{
num >>= 1;
uint num4 = num2 - num >> 31;
num2 -= (num & num4 - 1u);
num3 = (num3 << 1 | 1u - num4);
if (num < 16777216u)
{
num2 = (num2 << 8 | (uint)((byte)this.c.ReadByte()));
num <<= 8;
}
}
this.b = num;
this.a = num2;
return num3;
}
}
private class W
{
private byte[] a;
private uint b;
private Stream c;
private uint d;
private uint e;
internal uint f;
internal void A(uint z)
{
if (this.e != z)
{
this.a = new byte[z];
}
this.e = z;
this.b = 0u;
this.d = 0u;
}
internal void B(Stream z, bool y)
{
this.C();
this.c = z;
if (!y)
{
this.d = 0u;
this.b = 0u;
this.f = 0u;
}
}
internal void C()
{
this.D();
this.c = null;
}
internal void D()
{
uint num = this.b - this.d;
if (num != 0u)
{
this.c.Write(this.a, (int)this.d, (int)num);
if (this.b >= this.e)
{
this.b = 0u;
}
this.d = this.b;
}
}
internal void E(uint z, uint y)
{
uint num = this.b - z - 1u;
if (num >= this.e)
{
num += this.e;
}
while (y > 0u)
{
if (num >= this.e)
{
num = 0u;
}
this.a[(int)((uint)((UIntPtr)(this.b++)))] = this.a[(int)((uint)((UIntPtr)(num++)))];
if (this.b >= this.e)
{
this.D();
}
y -= 1u;
}
}
internal void F(byte z)
{
this.a[(int)((uint)((UIntPtr)(this.b++)))] = z;
if (this.b >= this.e)
{
this.D();
}
}
internal byte G(uint z)
{
uint num = this.b - z - 1u;
if (num >= this.e)
{
num += this.e;
}
return this.a[(int)((uint)((UIntPtr)num))];
}
}
private class V
{
private bool a = false;
private uint b;
private uint c;
private readonly UnLzma.Y[] d = new UnLzma.Y[192];
private readonly UnLzma.Y[] e = new UnLzma.Y[192];
private readonly UnLzma.Y[] f = new UnLzma.Y[12];
private readonly UnLzma.Y[] g = new UnLzma.Y[12];
private readonly UnLzma.Y[] h = new UnLzma.Y[12];
private readonly UnLzma.Y[] i = new UnLzma.Y[12];
private readonly UnLzma.U j = new UnLzma.U();
private readonly UnLzma.T k = new UnLzma.T();
private readonly UnLzma.W l = new UnLzma.W();
private UnLzma.Z m = new UnLzma.Z(4);
private readonly UnLzma.Y[] n = new UnLzma.Y[114];
private readonly UnLzma.Z[] o = new UnLzma.Z[4];
private uint p;
private readonly UnLzma.X q = new UnLzma.X();
private readonly UnLzma.U r = new UnLzma.U();
private static uint A(uint z)
{
z -= 2u;
return z < 4u ? z : 3u;
}
internal V()
{
this.b = 4294967295u;
int num = 0;
while ((long)num < 4L)
{
this.o[num] = new UnLzma.Z(6);
num++;
}
}
internal void B(Stream z, Stream y, long x)
{
this.G(z, y);
UnLzma.R r = default(UnLzma.R);
r.A();
uint num = 0u;
uint num2 = 0u;
uint num3 = 0u;
uint num4 = 0u;
ulong num5 = 0uL;
if (num5 < (ulong)x)
{
if (this.d[(int)((uint)((UIntPtr)(r.a << 4)))].B(this.q) != 0u)
{
throw new UnLzma.Q();
}
r.B();
byte z2 = this.k.D(this.q, 0u, 0);
this.l.F(z2);
num5 += 1uL;
}
while (num5 < (ulong)x)
{
uint num6 = (uint)num5 & this.p;
if (this.d[(int)((uint)((UIntPtr)((r.a << 4) + num6)))].B(this.q) == 0u)
{
byte x2 = this.l.G(0u);
var z2 = r.F() ? this.k.D(this.q, (uint) num5, x2) : this.k.E(this.q, (uint) num5, x2, this.l.G(num));
this.l.F(z2);
r.B();
num5 += 1uL;
}
else
{
uint num8;
if (this.f[(int)((uint)((UIntPtr)r.a))].B(this.q) == 1u)
{
if (this.g[(int)((uint)((UIntPtr)r.a))].B(this.q) == 0u)
{
if (this.e[(int)((uint)((UIntPtr)((r.a << 4) + num6)))].B(this.q) == 0u)
{
r.E();
this.l.F(this.l.G(num));
num5 += 1uL;
continue;
}
}
else
{
uint num7;
if (this.h[(int)((uint)((UIntPtr)r.a))].B(this.q) == 0u)
{
num7 = num2;
}
else
{
if (this.i[(int)((uint)((UIntPtr)r.a))].B(this.q) == 0u)
{
num7 = num3;
}
else
{
num7 = num4;
num4 = num3;
}
num3 = num2;
}
num2 = num;
num = num7;
}
num8 = this.r.C(this.q, num6) + 2u;
r.D();
}
else
{
num4 = num3;
num3 = num2;
num2 = num;
num8 = 2u + this.j.C(this.q, num6);
r.C();
uint num9 = this.o[(int)((uint)((UIntPtr)UnLzma.V.A(num8)))].B(this.q);
if (num9 >= 4u)
{
int num10 = (int)((num9 >> 1) - 1u);
num = (2u | (num9 & 1u)) << num10;
if (num9 < 14u)
{
num += UnLzma.Z.D(this.n, num - num9 - 1u, this.q, num10);
}
else
{
num += this.q.C(num10 - 4) << 4;
num += this.m.C(this.q);
}
}
else
{
num = num9;
}
}
if ((ulong)num >= (ulong)this.l.f + num5 || num >= this.c)
{
if (num == 4294967295u)
{
break;
}
throw new UnLzma.Q();
}
else
{
this.l.E(num, num8);
num5 += (ulong)num8;
}
}
}
this.l.D();
this.l.C();
this.q.B();
}
internal void C(byte[] z)
{
if (z.Length < 5)
{
throw new UnLzma.P();
}
int y = (int)(z[0] % 9);
int num = (int)(z[0] / 9);
int z2 = num % 5;
int num2 = num / 5;
if (num2 > 4)
{
throw new UnLzma.P();
}
uint num3 = 0u;
for (int i = 0; i < 4; i++)
{
num3 += (uint)((uint)z[1 + i] << i * 8);
}
this.D(num3);
this.E(z2, y);
this.F(num2);
}
private void D(uint z)
{
if (this.b != z)
{
this.b = z;
this.c = Math.Max(this.b, 1u);
uint z2 = Math.Max(this.c, 4096u);
this.l.A(z2);
}
}
private void E(int z, int y)
{
if (z > 8)
{
throw new UnLzma.P();
}
if (y > 8)
{
throw new UnLzma.P();
}
this.k.A(z, y);
}
private void F(int z)
{
if (z > 4)
{
throw new UnLzma.P();
}
uint num = 1u << z;
this.j.A(num);
this.r.A(num);
this.p = num - 1u;
}
private void G(Stream z, Stream y)
{
this.q.A(z);
this.l.B(y, this.a);
for (uint num = 0u; num < 12u; num += 1u)
{
for (uint num2 = 0u; num2 <= this.p; num2 += 1u)
{
uint value = (num << 4) + num2;
this.d[(int)((uint)((UIntPtr)value))].A();
this.e[(int)((uint)((UIntPtr)value))].A();
}
this.f[(int)((uint)((UIntPtr)num))].A();
this.g[(int)((uint)((UIntPtr)num))].A();
this.h[(int)((uint)((UIntPtr)num))].A();
this.i[(int)((uint)((UIntPtr)num))].A();
}
this.k.B();
for (uint num = 0u; num < 4u; num += 1u)
{
this.o[(int)((uint)((UIntPtr)num))].A();
}
for (uint num = 0u; num < 114u; num += 1u)
{
this.n[(int)((uint)((UIntPtr)num))].A();
}
this.j.B();
this.r.B();
this.m.A();
}
}
private class U
{
private UnLzma.Y a = default(UnLzma.Y);
private UnLzma.Y b = default(UnLzma.Y);
private UnLzma.Z c = new UnLzma.Z(8);
private readonly UnLzma.Z[] d = new UnLzma.Z[16];
private readonly UnLzma.Z[] e = new UnLzma.Z[16];
private uint f;
internal void A(uint z)
{
for (uint num = this.f; num < z; num += 1u)
{
this.d[(int)((uint)((UIntPtr)num))] = new UnLzma.Z(3);
this.e[(int)((uint)((UIntPtr)num))] = new UnLzma.Z(3);
}
this.f = z;
}
internal void B()
{
this.a.A();
for (uint num = 0u; num < this.f; num += 1u)
{
this.d[(int)((uint)((UIntPtr)num))].A();
this.e[(int)((uint)((UIntPtr)num))].A();
}
this.b.A();
this.c.A();
}
internal uint C(UnLzma.X z, uint y)
{
uint result;
if (this.a.B(z) == 0u)
{
result = this.d[(int)((uint)((UIntPtr)y))].B(z);
}
else
{
uint num = 8u;
if (this.b.B(z) == 0u)
{
num += this.e[(int)((uint)((UIntPtr)y))].B(z);
}
else
{
num += 8u;
num += this.c.B(z);
}
result = num;
}
return result;
}
}
private class T
{
private UnLzma.S[] a;
private int b;
private int c;
private uint d;
internal void A(int z, int y)
{
if (this.a == null || this.c != y || this.b != z)
{
this.b = z;
this.d = (1u << z) - 1u;
this.c = y;
uint num = 1u << this.c + this.b;
this.a = new UnLzma.S[num];
for (uint num2 = 0u; num2 < num; num2 += 1u)
{
this.a[(int)((uint)((UIntPtr)num2))].A();
}
}
}
internal void B()
{
uint num = 1u << this.c + this.b;
for (uint num2 = 0u; num2 < num; num2 += 1u)
{
this.a[(int)((uint)((UIntPtr)num2))].B();
}
}
private uint C(uint z, byte y)
{
return ((z & this.d) << this.c) + (uint)(y >> 8 - this.c);
}
internal byte D(UnLzma.X z, uint y, byte x)
{
return this.a[(int)((uint)((UIntPtr)this.C(y, x)))].C(z);
}
internal byte E(UnLzma.X z, uint y, byte x, byte w)
{
return this.a[(int)((uint)((UIntPtr)this.C(y, x)))].D(z, w);
}
}
private struct S
{
private UnLzma.Y[] a;
internal void A()
{
this.a = new UnLzma.Y[768];
}
internal void B()
{
for (int i = 0; i < 768; i++)
{
this.a[i].A();
}
}
internal byte C(UnLzma.X z)
{
uint num = 1u;
do
{
num = (num << 1 | this.a[(int)((uint)((UIntPtr)num))].B(z));
}
while (num < 256u);
return (byte)num;
}
internal byte D(UnLzma.X z, byte y)
{
uint num = 1u;
while (true)
{
uint num2 = (uint)(y >> 7 & 1);
y = (byte)(y << 1);
uint num3 = this.a[(int)((uint)((UIntPtr)((1u + num2 << 8) + num)))].B(z);
num = (num << 1 | num3);
if (num2 != num3)
{
break;
}
if (num >= 256u)
{
goto Block_2;
}
}
while (num < 256u)
{
num = (num << 1 | this.a[(int)((uint)((UIntPtr)num))].B(z));
}
Block_2:
return (byte)num;
}
}
private struct R
{
internal uint a;
internal void A()
{
this.a = 0u;
}
internal void B()
{
if (this.a < 4u)
{
this.a = 0u;
}
else if (this.a < 10u)
{
this.a -= 3u;
}
else
{
this.a -= 6u;
}
}
internal void C()
{
this.a = ((this.a < 7u) ? 7u : 10u);
}
internal void D()
{
this.a = ((this.a < 7u) ? 8u : 11u);
}
internal void E()
{
this.a = ((this.a < 7u) ? 9u : 11u);
}
internal bool F()
{
return this.a < 7u;
}
}
private class Q : IOException
{
internal Q() : base("Data Error")
{
}
}
private class P : ArgumentException
{
internal P() : base("Invalid Parameter")
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment