using System; namespace Invensys.Compression; internal class AAFastEncoder { private AAFastEncoderWindow inputWindow; private AAMatch currentMatch; private double lastCompressionRatio; internal int BytesInHistory => inputWindow.BytesAvailable; internal AADeflateInput UnprocessedInput => inputWindow.UnprocessedInput; internal double LastCompressionRatio => lastCompressionRatio; public AAFastEncoder() { inputWindow = new AAFastEncoderWindow(); currentMatch = new AAMatch(); } internal void FlushInput() { inputWindow.FlushWindow(); } internal void GetBlock(AADeflateInput input, AAOutputBuffer output, int maxBytesToCopy) { WriteDeflatePreamble(output); GetCompressedOutput(input, output, maxBytesToCopy); WriteEndOfBlock(output); } internal void GetCompressedData(AADeflateInput input, AAOutputBuffer output) { GetCompressedOutput(input, output, -1); } internal void GetBlockHeader(AAOutputBuffer output) { WriteDeflatePreamble(output); } internal void GetBlockFooter(AAOutputBuffer output) { WriteEndOfBlock(output); } private void GetCompressedOutput(AADeflateInput input, AAOutputBuffer output, int maxBytesToCopy) { int bytesWritten = output.BytesWritten; int num = 0; int num2 = BytesInHistory + input.Count; do { int num3 = ((input.Count < inputWindow.FreeWindowSpace) ? input.Count : inputWindow.FreeWindowSpace); 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 num4 = output.BytesWritten - bytesWritten; int num5 = BytesInHistory + input.Count; int num6 = num2 - num5; if (num4 != 0) { lastCompressionRatio = (double)num4 / (double)num6; } } private void GetCompressedOutput(AAOutputBuffer output) { while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output)) { inputWindow.GetNextSymbolOrMatch(currentMatch); if (currentMatch.State == AAMatchState.HasSymbol) { WriteChar(currentMatch.Symbol, output); continue; } if (currentMatch.State == AAMatchState.HasMatch) { WriteMatch(currentMatch.Length, currentMatch.Position, output); continue; } WriteChar(currentMatch.Symbol, output); WriteMatch(currentMatch.Length, currentMatch.Position, output); } } private bool InputAvailable(AADeflateInput input) { if (input.Count <= 0) { return BytesInHistory > 0; } return true; } private bool SafeToWriteTo(AAOutputBuffer output) { return output.FreeBytes > 16; } private void WriteEndOfBlock(AAOutputBuffer output) { uint num = AAFastEncoderStatics.FastEncoderLiteralCodeInfo[256]; int n = (int)(num & 0x1F); output.WriteBits(n, num >> 5); } internal static void WriteMatch(int matchLen, int matchPos, AAOutputBuffer output) { uint num = AAFastEncoderStatics.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 = AAFastEncoderStatics.FastEncoderDistanceCodeInfo[AAFastEncoderStatics.GetSlot(matchPos)]; output.WriteBits((int)(num & 0xF), num >> 8); int num3 = (int)((num >> 4) & 0xF); if (num3 != 0) { output.WriteBits(num3, (uint)matchPos & AAFastEncoderStatics.BitMask[num3]); } } internal static void WriteChar(byte b, AAOutputBuffer output) { uint num = AAFastEncoderStatics.FastEncoderLiteralCodeInfo[b]; output.WriteBits((int)(num & 0x1F), num >> 5); } internal static void WriteDeflatePreamble(AAOutputBuffer output) { output.WriteBytes(AAFastEncoderStatics.FastEncoderTreeStructureData, 0, AAFastEncoderStatics.FastEncoderTreeStructureData.Length); output.WriteBits(9, 34u); } }