public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) { int count = 0; if (input != null) { count = Math.Min(input.Count, (output.FreeBytes - 5) - output.BitsInBuffer); if (count > 0xfffb) { count = 0xfffb; } } if (isFinal) { output.WriteBits(3, 1); } else { output.WriteBits(3, 0); } output.FlushBits(); this.WriteLenNLen((ushort) count, output); if ((input != null) && (count > 0)) { output.WriteBytes(input.Buffer, input.StartIndex, count); input.ConsumeBytes(count); } }
public FastEncoder(bool doGZip) { this.usingGzip = doGZip; this.inputWindow = new FastEncoderWindow(); this.inputBuffer = new DeflateInput(); this.output = new Output(); this.currentMatch = new Match(); }
// Copy the compressed bytes to output buffer as a block. maxBytesToCopy limits the number of // bytes we can copy from input. Set to any value < 1 if no limit internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy) { Debug.Assert(InputAvailable(input), "call SetInput before trying to compress!"); WriteDeflatePreamble(output); GetCompressedOutput(input, output, maxBytesToCopy); WriteEndOfBlock(output); }
private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy) { int bytesWritten = output.BytesWritten; int num2 = 0; int num3 = this.BytesInHistory + input.Count; do { int num4 = (input.Count < this.inputWindow.FreeWindowSpace) ? input.Count : this.inputWindow.FreeWindowSpace; if (maxBytesToCopy >= 1) { num4 = Math.Min(num4, maxBytesToCopy - num2); } if (num4 > 0) { this.inputWindow.CopyBytes(input.Buffer, input.StartIndex, num4); input.ConsumeBytes(num4); num2 += num4; } this.GetCompressedOutput(output); }while ((this.SafeToWriteTo(output) && this.InputAvailable(input)) && ((maxBytesToCopy < 1) || (num2 < maxBytesToCopy))); int num6 = output.BytesWritten - bytesWritten; int num7 = this.BytesInHistory + input.Count; int num8 = num3 - num7; if (num6 != 0) { this.lastCompressionRatio = ((double)num6) / ((double)num8); } }
// maxBytesToCopy limits the number of bytes we can copy from input. Set to any value < 1 if no limit private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy) { // snapshot for compression ratio stats int bytesWrittenPre = output.BytesWritten; int bytesConsumedFromInput = 0; int inputBytesPre = BytesInHistory + input.Count; do { // read more input data into the window if there is space available int bytesToCopy = (input.Count < inputWindow.FreeWindowSpace) ? input.Count : inputWindow.FreeWindowSpace; if (maxBytesToCopy >= 1) { bytesToCopy = Math.Min(bytesToCopy, maxBytesToCopy - bytesConsumedFromInput); } if (bytesToCopy > 0) { // copy data into history window inputWindow.CopyBytes(input.Buffer, input.StartIndex, bytesToCopy); input.ConsumeBytes(bytesToCopy); bytesConsumedFromInput += bytesToCopy; } GetCompressedOutput(output); } while (SafeToWriteTo(output) && InputAvailable(input) && (maxBytesToCopy < 1 || bytesConsumedFromInput < maxBytesToCopy)); // determine compression ratio, save int bytesWrittenPost = output.BytesWritten; int bytesWritten = bytesWrittenPost - bytesWrittenPre; int inputBytesPost = BytesInHistory + input.Count; int totalBytesConsumed = inputBytesPre - inputBytesPost; if (bytesWritten != 0) { lastCompressionRatio = (double)bytesWritten / (double)totalBytesConsumed; } }
public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) { int count = 0; if (input != null) { count = Math.Min(input.Count, (output.FreeBytes - 5) - output.BitsInBuffer); if (count > 0xfffb) { count = 0xfffb; } } if (isFinal) { output.WriteBits(3, 1); } else { output.WriteBits(3, 0); } output.FlushBits(); this.WriteLenNLen((ushort)count, output); if ((input != null) && (count > 0)) { output.WriteBytes(input.Buffer, input.StartIndex, count); input.ConsumeBytes(count); } }
private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy) { int bytesWritten = output.BytesWritten; int num2 = 0; int num3 = this.BytesInHistory + input.Count; do { int num4 = (input.Count < this.inputWindow.FreeWindowSpace) ? input.Count : this.inputWindow.FreeWindowSpace; if (maxBytesToCopy >= 1) { num4 = Math.Min(num4, maxBytesToCopy - num2); } if (num4 > 0) { this.inputWindow.CopyBytes(input.Buffer, input.StartIndex, num4); input.ConsumeBytes(num4); num2 += num4; } this.GetCompressedOutput(output); } while ((this.SafeToWriteTo(output) && this.InputAvailable(input)) && ((maxBytesToCopy < 1) || (num2 < maxBytesToCopy))); int num6 = output.BytesWritten - bytesWritten; int num7 = this.BytesInHistory + input.Count; int num8 = num3 - num7; if (num6 != 0) { this.lastCompressionRatio = ((double) num6) / ((double) num8); } }
internal DeflaterManaged() { deflateEncoder = new FastEncoder(); copyEncoder = new CopyEncoder(); input = new DeflateInput(); output = new OutputBuffer(); processingState = DeflaterState.NotStarted; }
private bool InputAvailable(DeflateInput input) { if (input.Count <= 0) { return(this.BytesInHistory > 0); } return(true); }
/// <summary> /// null input means write an empty payload with formatting info. This is needed for the final block. /// </summary> public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) { Debug.Assert(output != null); Debug.Assert(output.FreeBytes >= PaddingSize); // determine number of bytes to write int count = 0; if (input != null) { // allow space for padding and bits not yet flushed to buffer count = Math.Min(input.Count, output.FreeBytes - PaddingSize - output.BitsInBuffer); // we don't expect the output buffer to ever be this big (currently 4K), but we'll check this // just in case that changes. if (count > MaxUncompressedBlockSize - PaddingSize) { count = MaxUncompressedBlockSize - PaddingSize; } } // write header and flush bits if (isFinal) { output.WriteBits( FastEncoderStatics.BFinalNoCompressionHeaderBitCount, FastEncoderStatics.BFinalNoCompressionHeader); } else { output.WriteBits( FastEncoderStatics.NoCompressionHeaderBitCount, FastEncoderStatics.NoCompressionHeader); } // now we're aligned output.FlushBits(); // write len, nlen WriteLenNLen((ushort)count, output); // write uncompressed bytes if (input != null && count > 0) { output.WriteBytes(input.Buffer, input.StartIndex, count); input.ConsumeBytes(count); } }
// null input means write an empty payload with formatting info. This is needed for the final block. public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) { Debug.Assert(output != null); Debug.Assert(output.FreeBytes >= PaddingSize); // determine number of bytes to write int count = 0; if (input != null) { // allow space for padding and bits not yet flushed to buffer count = Math.Min(input.Count, output.FreeBytes - PaddingSize - output.BitsInBuffer); // we don't expect the output buffer to ever be this big (currently 4K), but we'll check this // just in case that changes. if (count > MaxUncompressedBlockSize - PaddingSize) { count = MaxUncompressedBlockSize - PaddingSize; } } // write header and flush bits if (isFinal) { output.WriteBits(FastEncoderStatics.BFinalNoCompressionHeaderBitCount, FastEncoderStatics.BFinalNoCompressionHeader); } else { output.WriteBits(FastEncoderStatics.NoCompressionHeaderBitCount, FastEncoderStatics.NoCompressionHeader); } // now we're aligned output.FlushBits(); // write len, nlen WriteLenNLen((ushort)count, output); // write uncompressed bytes if (input != null && count > 0) { output.WriteBytes(input.Buffer, input.StartIndex, count); input.ConsumeBytes(count); } }
private bool InputAvailable(DeflateInput input) { return(input.Count > 0 || BytesInHistory > 0); }
private bool InputAvailable(DeflateInput input) => input.Count > 0 || BytesInHistory > 0;
internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy) { WriteDeflatePreamble(output); this.GetCompressedOutput(input, output, maxBytesToCopy); this.WriteEndOfBlock(output); }
// Compress data but don't format as block (doesn't have header and footer) internal void GetCompressedData(DeflateInput input, OutputBuffer output) { GetCompressedOutput(input, output, -1); }
// Compress data but don't format as block (doesn't have header and footer) internal void GetCompressedData(DeflateInput input, OutputBuffer output) => GetCompressedOutput(input, output, maxBytesToCopy: -1);
int IDeflater.GetDeflateOutput(byte[] outputBuffer) { Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!"); Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input"); output.UpdateBuffer(outputBuffer); switch (processingState) { case DeflaterState.NotStarted: { // first call. Try to compress but if we get bad compression ratio, switch to uncompressed blocks. Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window"); // save these in case we need to switch to uncompressed format DeflateInput.InputState initialInputState = input.DumpState(); OutputBuffer.BufferState initialOutputState = output.DumpState(); deflateEncoder.GetBlockHeader(output); deflateEncoder.GetCompressedData(input, output); if (!UseCompressed(deflateEncoder.LastCompressionRatio)) { // we're expanding; restore state and switch to uncompressed input.RestoreState(initialInputState); output.RestoreState(initialOutputState); copyEncoder.GetBlock(input, output, false); FlushInputWindows(); processingState = DeflaterState.CheckingForIncompressible; } else { processingState = DeflaterState.CompressThenCheck; } break; } case DeflaterState.CompressThenCheck: { // continue assuming data is compressible. If we reach data that indicates otherwise // finish off remaining data in history and decide whether to compress on a // block-by-block basis deflateEncoder.GetCompressedData(input, output); if (!UseCompressed(deflateEncoder.LastCompressionRatio)) { processingState = DeflaterState.SlowDownForIncompressible1; inputFromHistory = deflateEncoder.UnprocessedInput; } break; } case DeflaterState.SlowDownForIncompressible1: { // finish off previous compressed block deflateEncoder.GetBlockFooter(output); processingState = DeflaterState.SlowDownForIncompressible2; goto case DeflaterState.SlowDownForIncompressible2; // yeah I know, but there's no fallthrough } case DeflaterState.SlowDownForIncompressible2: { // clear out data from history, but add them as uncompressed blocks if (inputFromHistory.Count > 0) { copyEncoder.GetBlock(inputFromHistory, output, false); } if (inputFromHistory.Count == 0) { // now we're clean deflateEncoder.FlushInput(); processingState = DeflaterState.CheckingForIncompressible; } break; } case DeflaterState.CheckingForIncompressible: { // decide whether to compress on a block-by-block basis Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window"); // save these in case we need to store as uncompressed DeflateInput.InputState initialInputState = input.DumpState(); OutputBuffer.BufferState initialOutputState = output.DumpState(); // enforce max so we can ensure state between calls deflateEncoder.GetBlock(input, output, CleanCopySize); if (!UseCompressed(deflateEncoder.LastCompressionRatio)) { // we're expanding; restore state and switch to uncompressed input.RestoreState(initialInputState); output.RestoreState(initialOutputState); copyEncoder.GetBlock(input, output, false); FlushInputWindows(); } break; } case DeflaterState.StartingSmallData: { // add compressed header and data, but not footer. Subsequent calls will keep // adding compressed data (no header and no footer). We're doing this to // avoid overhead of header and footer size relative to compressed payload. deflateEncoder.GetBlockHeader(output); processingState = DeflaterState.HandlingSmallData; goto case DeflaterState.HandlingSmallData; // yeah I know, but there's no fallthrough } case DeflaterState.HandlingSmallData: { // continue adding compressed data deflateEncoder.GetCompressedData(input, output); break; } } return(output.BytesWritten); }
int IDeflater.GetDeflateOutput(byte[] outputBuffer) { Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!"); Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input"); _output.UpdateBuffer(outputBuffer); switch (_processingState) { case DeflaterState.NotStarted: { // first call. Try to compress but if we get bad compression ratio, switch to uncompressed blocks. Debug.Assert(_deflateEncoder.BytesInHistory == 0, "have leftover bytes in window"); // save these in case we need to switch to uncompressed format DeflateInput.InputState initialInputState = _input.DumpState(); OutputBuffer.BufferState initialOutputState = _output.DumpState(); _deflateEncoder.GetBlockHeader(_output); _deflateEncoder.GetCompressedData(_input, _output); if (!UseCompressed(_deflateEncoder.LastCompressionRatio)) { // we're expanding; restore state and switch to uncompressed _input.RestoreState(initialInputState); _output.RestoreState(initialOutputState); _copyEncoder.GetBlock(_input, _output, false); FlushInputWindows(); _processingState = DeflaterState.CheckingForIncompressible; } else { _processingState = DeflaterState.CompressThenCheck; } break; } case DeflaterState.CompressThenCheck: { // continue assuming data is compressible. If we reach data that indicates otherwise // finish off remaining data in history and decide whether to compress on a // block-by-block basis _deflateEncoder.GetCompressedData(_input, _output); if (!UseCompressed(_deflateEncoder.LastCompressionRatio)) { _processingState = DeflaterState.SlowDownForIncompressible1; _inputFromHistory = _deflateEncoder.UnprocessedInput; } break; } case DeflaterState.SlowDownForIncompressible1: { // finish off previous compressed block _deflateEncoder.GetBlockFooter(_output); _processingState = DeflaterState.SlowDownForIncompressible2; goto case DeflaterState.SlowDownForIncompressible2; // yeah I know, but there's no fallthrough } case DeflaterState.SlowDownForIncompressible2: { // clear out data from history, but add them as uncompressed blocks if (_inputFromHistory.Count > 0) { _copyEncoder.GetBlock(_inputFromHistory, _output, false); } if (_inputFromHistory.Count == 0) { // now we're clean _deflateEncoder.FlushInput(); _processingState = DeflaterState.CheckingForIncompressible; } break; } case DeflaterState.CheckingForIncompressible: { // decide whether to compress on a block-by-block basis Debug.Assert(_deflateEncoder.BytesInHistory == 0, "have leftover bytes in window"); // save these in case we need to store as uncompressed DeflateInput.InputState initialInputState = _input.DumpState(); OutputBuffer.BufferState initialOutputState = _output.DumpState(); // enforce max so we can ensure state between calls _deflateEncoder.GetBlock(_input, _output, CleanCopySize); if (!UseCompressed(_deflateEncoder.LastCompressionRatio)) { // we're expanding; restore state and switch to uncompressed _input.RestoreState(initialInputState); _output.RestoreState(initialOutputState); _copyEncoder.GetBlock(_input, _output, false); FlushInputWindows(); } break; } case DeflaterState.StartingSmallData: { // add compressed header and data, but not footer. Subsequent calls will keep // adding compressed data (no header and no footer). We're doing this to // avoid overhead of header and footer size relative to compressed payload. _deflateEncoder.GetBlockHeader(_output); _processingState = DeflaterState.HandlingSmallData; goto case DeflaterState.HandlingSmallData; // yeah I know, but there's no fallthrough } case DeflaterState.HandlingSmallData: { // continue adding compressed data _deflateEncoder.GetCompressedData(_input, _output); break; } } return _output.BytesWritten; }
public int GetDeflateOutput(byte[] outputBuffer) { this.output.UpdateBuffer(outputBuffer); switch (this.processingState) { case DeflaterState.NotStarted: { DeflateInput.InputState state = this.input.DumpState(); OutputBuffer.BufferState state2 = this.output.DumpState(); this.deflateEncoder.GetBlockHeader(this.output); this.deflateEncoder.GetCompressedData(this.input, this.output); if (this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.processingState = DeflaterState.CompressThenCheck; } else { this.input.RestoreState(state); this.output.RestoreState(state2); this.copyEncoder.GetBlock(this.input, this.output, false); this.FlushInputWindows(); this.processingState = DeflaterState.CheckingForIncompressible; } goto Label_023A; } case DeflaterState.SlowDownForIncompressible1: this.deflateEncoder.GetBlockFooter(this.output); this.processingState = DeflaterState.SlowDownForIncompressible2; break; case DeflaterState.SlowDownForIncompressible2: break; case DeflaterState.StartingSmallData: this.deflateEncoder.GetBlockHeader(this.output); this.processingState = DeflaterState.HandlingSmallData; goto Label_0223; case DeflaterState.CompressThenCheck: this.deflateEncoder.GetCompressedData(this.input, this.output); if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.processingState = DeflaterState.SlowDownForIncompressible1; this.inputFromHistory = this.deflateEncoder.UnprocessedInput; } goto Label_023A; case DeflaterState.CheckingForIncompressible: { DeflateInput.InputState state3 = this.input.DumpState(); OutputBuffer.BufferState state4 = this.output.DumpState(); this.deflateEncoder.GetBlock(this.input, this.output, 0xf88); if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.input.RestoreState(state3); this.output.RestoreState(state4); this.copyEncoder.GetBlock(this.input, this.output, false); this.FlushInputWindows(); } goto Label_023A; } case DeflaterState.HandlingSmallData: goto Label_0223; default: goto Label_023A; } if (this.inputFromHistory.Count > 0) { this.copyEncoder.GetBlock(this.inputFromHistory, this.output, false); } if (this.inputFromHistory.Count == 0) { this.deflateEncoder.FlushInput(); this.processingState = DeflaterState.CheckingForIncompressible; } goto Label_023A; Label_0223: this.deflateEncoder.GetCompressedData(this.input, this.output); Label_023A: return(this.output.BytesWritten); }
internal void GetCompressedData(DeflateInput input, OutputBuffer output) { this.GetCompressedOutput(input, output, -1); }
private bool InputAvailable(DeflateInput input) { return input.Count > 0 || BytesInHistory > 0; }
private bool InputAvailable(DeflateInput input) { if (input.Count <= 0) { return (this.BytesInHistory > 0); } return true; }
public int GetDeflateOutput(byte[] outputBuffer) { this.output.UpdateBuffer(outputBuffer); switch (this.processingState) { case DeflaterState.NotStarted: { DeflateInput.InputState state = this.input.DumpState(); OutputBuffer.BufferState state2 = this.output.DumpState(); this.deflateEncoder.GetBlockHeader(this.output); this.deflateEncoder.GetCompressedData(this.input, this.output); if (this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.processingState = DeflaterState.CompressThenCheck; } else { this.input.RestoreState(state); this.output.RestoreState(state2); this.copyEncoder.GetBlock(this.input, this.output, false); this.FlushInputWindows(); this.processingState = DeflaterState.CheckingForIncompressible; } goto Label_023A; } case DeflaterState.SlowDownForIncompressible1: this.deflateEncoder.GetBlockFooter(this.output); this.processingState = DeflaterState.SlowDownForIncompressible2; break; case DeflaterState.SlowDownForIncompressible2: break; case DeflaterState.StartingSmallData: this.deflateEncoder.GetBlockHeader(this.output); this.processingState = DeflaterState.HandlingSmallData; goto Label_0223; case DeflaterState.CompressThenCheck: this.deflateEncoder.GetCompressedData(this.input, this.output); if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.processingState = DeflaterState.SlowDownForIncompressible1; this.inputFromHistory = this.deflateEncoder.UnprocessedInput; } goto Label_023A; case DeflaterState.CheckingForIncompressible: { DeflateInput.InputState state3 = this.input.DumpState(); OutputBuffer.BufferState state4 = this.output.DumpState(); this.deflateEncoder.GetBlock(this.input, this.output, 0xf88); if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio)) { this.input.RestoreState(state3); this.output.RestoreState(state4); this.copyEncoder.GetBlock(this.input, this.output, false); this.FlushInputWindows(); } goto Label_023A; } case DeflaterState.HandlingSmallData: goto Label_0223; default: goto Label_023A; } if (this.inputFromHistory.Count > 0) { this.copyEncoder.GetBlock(this.inputFromHistory, this.output, false); } if (this.inputFromHistory.Count == 0) { this.deflateEncoder.FlushInput(); this.processingState = DeflaterState.CheckingForIncompressible; } goto Label_023A; Label_0223: this.deflateEncoder.GetCompressedData(this.input, this.output); Label_023A: return this.output.BytesWritten; }