410 lines
8.9 KiB
C#
410 lines
8.9 KiB
C#
namespace ComponentAce.Compression.Libs.zlib
|
|
{
|
|
internal sealed class Inflate
|
|
{
|
|
private const int MAX_WBITS = 15;
|
|
|
|
private const int PRESET_DICT = 32;
|
|
|
|
internal const int Z_NO_FLUSH = 0;
|
|
|
|
internal const int Z_PARTIAL_FLUSH = 1;
|
|
|
|
internal const int Z_SYNC_FLUSH = 2;
|
|
|
|
internal const int Z_FULL_FLUSH = 3;
|
|
|
|
internal const int Z_FINISH = 4;
|
|
|
|
private const int Z_DEFLATED = 8;
|
|
|
|
private const int Z_OK = 0;
|
|
|
|
private const int Z_STREAM_END = 1;
|
|
|
|
private const int Z_NEED_DICT = 2;
|
|
|
|
private const int Z_ERRNO = -1;
|
|
|
|
private const int Z_STREAM_ERROR = -2;
|
|
|
|
private const int Z_DATA_ERROR = -3;
|
|
|
|
private const int Z_MEM_ERROR = -4;
|
|
|
|
private const int Z_BUF_ERROR = -5;
|
|
|
|
private const int Z_VERSION_ERROR = -6;
|
|
|
|
private const int METHOD = 0;
|
|
|
|
private const int FLAG = 1;
|
|
|
|
private const int DICT4 = 2;
|
|
|
|
private const int DICT3 = 3;
|
|
|
|
private const int DICT2 = 4;
|
|
|
|
private const int DICT1 = 5;
|
|
|
|
private const int DICT0 = 6;
|
|
|
|
private const int BLOCKS = 7;
|
|
|
|
private const int CHECK4 = 8;
|
|
|
|
private const int CHECK3 = 9;
|
|
|
|
private const int CHECK2 = 10;
|
|
|
|
private const int CHECK1 = 11;
|
|
|
|
private const int DONE = 12;
|
|
|
|
private const int BAD = 13;
|
|
|
|
internal int mode;
|
|
|
|
internal int method;
|
|
|
|
internal long[] was = new long[1];
|
|
|
|
internal long need;
|
|
|
|
internal int marker;
|
|
|
|
internal int nowrap;
|
|
|
|
internal int wbits;
|
|
|
|
internal InfBlocks blocks;
|
|
|
|
private static byte[] mark = new byte[4]
|
|
{
|
|
0,
|
|
0,
|
|
(byte)SupportClass.Identity(255L),
|
|
(byte)SupportClass.Identity(255L)
|
|
};
|
|
|
|
internal int inflateReset(ZStream z)
|
|
{
|
|
if (z == null || z.istate == null)
|
|
{
|
|
return -2;
|
|
}
|
|
z.total_in = (z.total_out = 0L);
|
|
z.msg = null;
|
|
z.istate.mode = ((z.istate.nowrap != 0) ? 7 : 0);
|
|
z.istate.blocks.reset(z, null);
|
|
return 0;
|
|
}
|
|
|
|
internal int inflateEnd(ZStream z)
|
|
{
|
|
if (blocks != null)
|
|
{
|
|
blocks.free(z);
|
|
}
|
|
blocks = null;
|
|
return 0;
|
|
}
|
|
|
|
internal int inflateInit(ZStream z, int w)
|
|
{
|
|
z.msg = null;
|
|
blocks = null;
|
|
nowrap = 0;
|
|
if (w < 0)
|
|
{
|
|
w = -w;
|
|
nowrap = 1;
|
|
}
|
|
if (w < 8 || w > 15)
|
|
{
|
|
inflateEnd(z);
|
|
return -2;
|
|
}
|
|
wbits = w;
|
|
z.istate.blocks = new InfBlocks(z, (z.istate.nowrap != 0) ? null : this, 1 << w);
|
|
inflateReset(z);
|
|
return 0;
|
|
}
|
|
|
|
internal int inflate(ZStream z, int f)
|
|
{
|
|
if (z == null || z.istate == null || z.next_in == null)
|
|
{
|
|
return -2;
|
|
}
|
|
f = ((f == 4) ? (-5) : 0);
|
|
int num = -5;
|
|
while (true)
|
|
{
|
|
switch (z.istate.mode)
|
|
{
|
|
case 0:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xF) != 8)
|
|
{
|
|
z.istate.mode = 13;
|
|
z.msg = "unknown compression method";
|
|
z.istate.marker = 5;
|
|
break;
|
|
}
|
|
if ((z.istate.method >> 4) + 8 > z.istate.wbits)
|
|
{
|
|
z.istate.mode = 13;
|
|
z.msg = "invalid window size";
|
|
z.istate.marker = 5;
|
|
break;
|
|
}
|
|
z.istate.mode = 1;
|
|
goto case 1;
|
|
case 1:
|
|
{
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
int num2 = z.next_in[z.next_in_index++] & 0xFF;
|
|
if (((z.istate.method << 8) + num2) % 31 != 0)
|
|
{
|
|
z.istate.mode = 13;
|
|
z.msg = "incorrect header check";
|
|
z.istate.marker = 5;
|
|
break;
|
|
}
|
|
if ((num2 & 0x20) == 0)
|
|
{
|
|
z.istate.mode = 7;
|
|
break;
|
|
}
|
|
z.istate.mode = 2;
|
|
goto case 2;
|
|
}
|
|
case 2:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need = ((z.next_in[z.next_in_index++] & 0xFF) << 24) & -16777216;
|
|
z.istate.mode = 3;
|
|
goto case 3;
|
|
case 3:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 16) & 0xFF0000uL);
|
|
z.istate.mode = 4;
|
|
goto case 4;
|
|
case 4:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 8) & 0xFF00uL);
|
|
z.istate.mode = 5;
|
|
goto case 5;
|
|
case 5:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 0xFFuL);
|
|
z.adler = z.istate.need;
|
|
z.istate.mode = 6;
|
|
return 2;
|
|
case 6:
|
|
z.istate.mode = 13;
|
|
z.msg = "need dictionary";
|
|
z.istate.marker = 0;
|
|
return -2;
|
|
case 7:
|
|
num = z.istate.blocks.proc(z, num);
|
|
switch (num)
|
|
{
|
|
case -3:
|
|
z.istate.mode = 13;
|
|
z.istate.marker = 0;
|
|
goto end_IL_0031;
|
|
case 0:
|
|
num = f;
|
|
break;
|
|
}
|
|
if (num != 1)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.istate.blocks.reset(z, z.istate.was);
|
|
if (z.istate.nowrap != 0)
|
|
{
|
|
z.istate.mode = 12;
|
|
break;
|
|
}
|
|
z.istate.mode = 8;
|
|
goto case 8;
|
|
case 8:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need = ((z.next_in[z.next_in_index++] & 0xFF) << 24) & -16777216;
|
|
z.istate.mode = 9;
|
|
goto case 9;
|
|
case 9:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 16) & 0xFF0000uL);
|
|
z.istate.mode = 10;
|
|
goto case 10;
|
|
case 10:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 8) & 0xFF00uL);
|
|
z.istate.mode = 11;
|
|
goto case 11;
|
|
case 11:
|
|
if (z.avail_in == 0)
|
|
{
|
|
return num;
|
|
}
|
|
num = f;
|
|
z.avail_in--;
|
|
z.total_in++;
|
|
z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 0xFFuL);
|
|
if ((int)z.istate.was[0] != (int)z.istate.need)
|
|
{
|
|
z.istate.mode = 13;
|
|
z.msg = "incorrect data check";
|
|
z.istate.marker = 5;
|
|
break;
|
|
}
|
|
z.istate.mode = 12;
|
|
goto case 12;
|
|
case 12:
|
|
return 1;
|
|
case 13:
|
|
return -3;
|
|
default:
|
|
{
|
|
return -2;
|
|
}
|
|
end_IL_0031:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength)
|
|
{
|
|
int start = 0;
|
|
int num = dictLength;
|
|
if (z == null || z.istate == null || z.istate.mode != 6)
|
|
{
|
|
return -2;
|
|
}
|
|
if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler)
|
|
{
|
|
return -3;
|
|
}
|
|
z.adler = z._adler.adler32(0L, null, 0, 0);
|
|
if (num >= 1 << z.istate.wbits)
|
|
{
|
|
num = (1 << z.istate.wbits) - 1;
|
|
start = dictLength - num;
|
|
}
|
|
z.istate.blocks.set_dictionary(dictionary, start, num);
|
|
z.istate.mode = 7;
|
|
return 0;
|
|
}
|
|
|
|
internal int inflateSync(ZStream z)
|
|
{
|
|
if (z == null || z.istate == null)
|
|
{
|
|
return -2;
|
|
}
|
|
if (z.istate.mode != 13)
|
|
{
|
|
z.istate.mode = 13;
|
|
z.istate.marker = 0;
|
|
}
|
|
int num;
|
|
if ((num = z.avail_in) == 0)
|
|
{
|
|
return -5;
|
|
}
|
|
int num2 = z.next_in_index;
|
|
int num3 = z.istate.marker;
|
|
while (num != 0 && num3 < 4)
|
|
{
|
|
num3 = ((z.next_in[num2] != mark[num3]) ? ((z.next_in[num2] == 0) ? (4 - num3) : 0) : (num3 + 1));
|
|
num2++;
|
|
num--;
|
|
}
|
|
z.total_in += num2 - z.next_in_index;
|
|
z.next_in_index = num2;
|
|
z.avail_in = num;
|
|
z.istate.marker = num3;
|
|
if (num3 != 4)
|
|
{
|
|
return -3;
|
|
}
|
|
long total_in = z.total_in;
|
|
long total_out = z.total_out;
|
|
inflateReset(z);
|
|
z.total_in = total_in;
|
|
z.total_out = total_out;
|
|
z.istate.mode = 7;
|
|
return 0;
|
|
}
|
|
|
|
internal int inflateSyncPoint(ZStream z)
|
|
{
|
|
if (z == null || z.istate == null || z.istate.blocks == null)
|
|
{
|
|
return -2;
|
|
}
|
|
return z.istate.blocks.sync_point();
|
|
}
|
|
}
|
|
}
|