173 lines
4.1 KiB
C#
173 lines
4.1 KiB
C#
using System;
|
|
|
|
namespace Unity.IO.Compression
|
|
{
|
|
internal class FastEncoder
|
|
{
|
|
private FastEncoderWindow inputWindow;
|
|
|
|
private Match currentMatch;
|
|
|
|
private double lastCompressionRatio;
|
|
|
|
internal int BytesInHistory
|
|
{
|
|
get
|
|
{
|
|
return inputWindow.BytesAvailable;
|
|
}
|
|
}
|
|
|
|
internal DeflateInput UnprocessedInput
|
|
{
|
|
get
|
|
{
|
|
return inputWindow.UnprocessedInput;
|
|
}
|
|
}
|
|
|
|
internal double LastCompressionRatio
|
|
{
|
|
get
|
|
{
|
|
return lastCompressionRatio;
|
|
}
|
|
}
|
|
|
|
public FastEncoder()
|
|
{
|
|
inputWindow = new FastEncoderWindow();
|
|
currentMatch = new Match();
|
|
}
|
|
|
|
internal void FlushInput()
|
|
{
|
|
inputWindow.FlushWindow();
|
|
}
|
|
|
|
internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
|
|
{
|
|
WriteDeflatePreamble(output);
|
|
GetCompressedOutput(input, output, maxBytesToCopy);
|
|
WriteEndOfBlock(output);
|
|
}
|
|
|
|
internal void GetCompressedData(DeflateInput input, OutputBuffer output)
|
|
{
|
|
GetCompressedOutput(input, output, -1);
|
|
}
|
|
|
|
internal void GetBlockHeader(OutputBuffer output)
|
|
{
|
|
WriteDeflatePreamble(output);
|
|
}
|
|
|
|
internal void GetBlockFooter(OutputBuffer output)
|
|
{
|
|
WriteEndOfBlock(output);
|
|
}
|
|
|
|
private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
|
|
{
|
|
int bytesWritten = output.BytesWritten;
|
|
int num = 0;
|
|
int num2 = BytesInHistory + input.Count;
|
|
do
|
|
{
|
|
int num3 = ((input.Count >= inputWindow.FreeWindowSpace) ? inputWindow.FreeWindowSpace : input.Count);
|
|
if (maxBytesToCopy >= 1)
|
|
{
|
|
num3 = Math.Min(num3, maxBytesToCopy - num);
|
|
}
|
|
if (num3 > 0)
|
|
{
|
|
inputWindow.CopyBytes(input.Buffer, input.StartIndex, num3);
|
|
input.ConsumeBytes(num3);
|
|
num += num3;
|
|
}
|
|
GetCompressedOutput(output);
|
|
}
|
|
while (SafeToWriteTo(output) && InputAvailable(input) && (maxBytesToCopy < 1 || num < maxBytesToCopy));
|
|
int bytesWritten2 = output.BytesWritten;
|
|
int num4 = bytesWritten2 - bytesWritten;
|
|
int num5 = BytesInHistory + input.Count;
|
|
int num6 = num2 - num5;
|
|
if (num4 != 0)
|
|
{
|
|
lastCompressionRatio = (double)num4 / (double)num6;
|
|
}
|
|
}
|
|
|
|
private void GetCompressedOutput(OutputBuffer output)
|
|
{
|
|
while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output))
|
|
{
|
|
inputWindow.GetNextSymbolOrMatch(currentMatch);
|
|
if (currentMatch.State == MatchState.HasSymbol)
|
|
{
|
|
WriteChar(currentMatch.Symbol, output);
|
|
continue;
|
|
}
|
|
if (currentMatch.State == MatchState.HasMatch)
|
|
{
|
|
WriteMatch(currentMatch.Length, currentMatch.Position, output);
|
|
continue;
|
|
}
|
|
WriteChar(currentMatch.Symbol, output);
|
|
WriteMatch(currentMatch.Length, currentMatch.Position, output);
|
|
}
|
|
}
|
|
|
|
private bool InputAvailable(DeflateInput input)
|
|
{
|
|
return input.Count > 0 || BytesInHistory > 0;
|
|
}
|
|
|
|
private bool SafeToWriteTo(OutputBuffer output)
|
|
{
|
|
return output.FreeBytes > 16;
|
|
}
|
|
|
|
private void WriteEndOfBlock(OutputBuffer output)
|
|
{
|
|
uint num = FastEncoderStatics.FastEncoderLiteralCodeInfo[256];
|
|
int n = (int)(num & 0x1F);
|
|
output.WriteBits(n, num >> 5);
|
|
}
|
|
|
|
internal static void WriteMatch(int matchLen, int matchPos, OutputBuffer output)
|
|
{
|
|
uint num = FastEncoderStatics.FastEncoderLiteralCodeInfo[254 + matchLen];
|
|
int num2 = (int)(num & 0x1F);
|
|
if (num2 <= 16)
|
|
{
|
|
output.WriteBits(num2, num >> 5);
|
|
}
|
|
else
|
|
{
|
|
output.WriteBits(16, (num >> 5) & 0xFFFF);
|
|
output.WriteBits(num2 - 16, num >> 21);
|
|
}
|
|
num = FastEncoderStatics.FastEncoderDistanceCodeInfo[FastEncoderStatics.GetSlot(matchPos)];
|
|
output.WriteBits((int)(num & 0xF), num >> 8);
|
|
int num3 = (int)((num >> 4) & 0xF);
|
|
if (num3 != 0)
|
|
{
|
|
output.WriteBits(num3, (uint)matchPos & FastEncoderStatics.BitMask[num3]);
|
|
}
|
|
}
|
|
|
|
internal static void WriteChar(byte b, OutputBuffer output)
|
|
{
|
|
uint num = FastEncoderStatics.FastEncoderLiteralCodeInfo[b];
|
|
output.WriteBits((int)(num & 0x1F), num >> 5);
|
|
}
|
|
|
|
internal static void WriteDeflatePreamble(OutputBuffer output)
|
|
{
|
|
output.WriteBytes(FastEncoderStatics.FastEncoderTreeStructureData, 0, FastEncoderStatics.FastEncoderTreeStructureData.Length);
|
|
output.WriteBits(9, 34u);
|
|
}
|
|
}
|
|
}
|