From c18d1fef7876ad95c163d46d2e85638fc95de696 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 12 Nov 2019 20:35:37 +1100 Subject: [PATCH] Stylecop cleanup DeflaterEngine --- ...erThrowHelper.cs => DeflateThrowHelper.cs} | 2 +- src/ImageSharp/Formats/Png/Zlib/Deflater.cs | 4 +- .../Formats/Png/Zlib/DeflaterEngine.cs | 840 ++++++++---------- 3 files changed, 395 insertions(+), 451 deletions(-) rename src/ImageSharp/Formats/Png/Zlib/{DeflaterThrowHelper.cs => DeflateThrowHelper.cs} (92%) diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterThrowHelper.cs b/src/ImageSharp/Formats/Png/Zlib/DeflateThrowHelper.cs similarity index 92% rename from src/ImageSharp/Formats/Png/Zlib/DeflaterThrowHelper.cs rename to src/ImageSharp/Formats/Png/Zlib/DeflateThrowHelper.cs index b59d32c4d..a360e5e87 100644 --- a/src/ImageSharp/Formats/Png/Zlib/DeflaterThrowHelper.cs +++ b/src/ImageSharp/Formats/Png/Zlib/DeflateThrowHelper.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Png.Zlib { - internal static class DeflaterThrowHelper + internal static class DeflateThrowHelper { [MethodImpl(InliningOptions.ColdPath)] public static void ThrowAlreadyFinished() => throw new InvalidOperationException("Finish() already called."); diff --git a/src/ImageSharp/Formats/Png/Zlib/Deflater.cs b/src/ImageSharp/Formats/Png/Zlib/Deflater.cs index 26d1f9a45..33b3019b8 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Deflater.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Deflater.cs @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib { if ((this.state & IsFinishing) != 0) { - DeflaterThrowHelper.ThrowAlreadyFinished(); + DeflateThrowHelper.ThrowAlreadyFinished(); } this.engine.SetInput(input, offset, count); @@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib if (this.state == ClosedState) { - DeflaterThrowHelper.ThrowAlreadyClosed(); + DeflateThrowHelper.ThrowAlreadyClosed(); } if (this.state < BusyState) diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs index c9967056e..ddf571884 100644 --- a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs +++ b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System; using System.Collections.Generic; using System.Text; @@ -51,54 +50,145 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// public class DeflaterEngine { - #region Constants - private const int TooFar = 4096; - #endregion Constants + // Hash index of string to be inserted + private int insertHashIndex; - #region Constructors + /// + /// Hashtable, hashing three characters to an index for window, so + /// that window[index]..window[index+2] have this hash code. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xFFFF. + /// + private short[] head; /// - /// Construct instance with pending buffer - /// Adler calculation will be peformed + /// prev[index & WMASK] points to the previous index that has the + /// same hash code as the string starting at index. This way + /// entries with the same hash code are in a linked list. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xFFFF. /// - /// - /// Pending buffer to use - /// - public DeflaterEngine(DeflaterPendingBuffer pending) - : this(pending, false) - { - } + private short[] prev; + private int matchStart; + // Length of best match + private int matchLen; + + // Set if previous match exists + private bool prevAvailable; + + private int blockStart; /// - /// Construct instance with pending buffer + /// Points to the current character in the window. /// - /// - /// Pending buffer to use - /// + private int strstart; + + /// + /// lookahead is the number of characters starting at strstart in + /// window that are valid. + /// So window[strstart] until window[strstart+lookahead-1] are valid + /// characters. + /// + private int lookahead; + + /// + /// This array contains the part of the uncompressed stream that + /// is of relevance. The current character is indexed by strstart. + /// + private byte[] window; + private int maxChain; + private int maxLazy; + private int niceLength; + private int goodLength; + + /// + /// The current compression function. + /// + private int compressionFunction; + + /// + /// The input data for compression. + /// + private byte[] inputBuf; + + /// + /// The total bytes of input read. + /// + private long totalIn; + + /// + /// The offset into inputBuf, where input data starts. + /// + private int inputOff; + + /// + /// The end offset of the input data. + /// + private int inputEnd; + + private DeflaterPendingBuffer pending; + private DeflaterHuffman huffman; + + /// + /// The adler checksum + /// + private Adler32 adler; + + /// + /// Initializes a new instance of the class. + /// + /// The pending buffer to use. /// /// If no adler calculation should be performed /// public DeflaterEngine(DeflaterPendingBuffer pending, bool noAdlerCalculation) { this.pending = pending; - huffman = new DeflaterHuffman(pending); + this.huffman = new DeflaterHuffman(pending); if (!noAdlerCalculation) - adler = new Adler32(); + { + this.adler = new Adler32(); + } - window = new byte[2 * DeflaterConstants.WSIZE]; - head = new short[DeflaterConstants.HASH_SIZE]; - prev = new short[DeflaterConstants.WSIZE]; + this.window = new byte[2 * DeflaterConstants.WSIZE]; + this.head = new short[DeflaterConstants.HASH_SIZE]; + this.prev = new short[DeflaterConstants.WSIZE]; // We start at index 1, to avoid an implementation deficiency, that // we cannot build a repeat pattern at index 0. - blockStart = strstart = 1; + this.blockStart = this.strstart = 1; } - #endregion Constructors + /// + /// Gets the current value of Adler checksum + /// + public int Adler + { + get + { + return (this.adler != null) ? unchecked((int)this.adler.Value) : 0; + } + } + + /// + /// Gets the total data processed + /// + public long TotalIn + { + get + { + return this.totalIn; + } + } + + /// + /// Gets or sets the deflate strategy + /// + public DeflateStrategy Strategy { get; set; } /// /// Deflate drives actual compression of data @@ -111,33 +201,28 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib bool progress; do { - FillWindow(); - bool canFlush = flush && (inputOff == inputEnd); + this.FillWindow(); + bool canFlush = flush && (this.inputOff == this.inputEnd); -#if DebugDeflation - if (DeflaterConstants.DEBUGGING) { - Console.WriteLine("window: [" + blockStart + "," + strstart + "," - + lookahead + "], " + compressionFunction + "," + canFlush); - } -#endif - switch (compressionFunction) + switch (this.compressionFunction) { case DeflaterConstants.DEFLATE_STORED: - progress = DeflateStored(canFlush, finish); + progress = this.DeflateStored(canFlush, finish); break; case DeflaterConstants.DEFLATE_FAST: - progress = DeflateFast(canFlush, finish); + progress = this.DeflateFast(canFlush, finish); break; case DeflaterConstants.DEFLATE_SLOW: - progress = DeflateSlow(canFlush, finish); + progress = this.DeflateSlow(canFlush, finish); break; default: throw new InvalidOperationException("unknown compressionFunction"); } - } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + } + while (this.pending.IsFlushed && progress); // repeat while we have no pending output and progress was made return progress; } @@ -165,24 +250,23 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib throw new ArgumentOutOfRangeException(nameof(count)); } - if (inputOff < inputEnd) + if (this.inputOff < this.inputEnd) { - throw new InvalidOperationException("Old input was not completely processed"); + throw new InvalidOperationException("Old input was not completely processed."); } int end = offset + count; - /* We want to throw an ArrayIndexOutOfBoundsException early. The - * check is very tricky: it also handles integer wrap around. - */ + // We want to throw an ArrayIndexOutOfBoundsException early. + // The check is very tricky: it also handles integer wrap around. if ((offset > end) || (end > buffer.Length)) { throw new ArgumentOutOfRangeException(nameof(count)); } - inputBuf = buffer; - inputOff = offset; - inputEnd = end; + this.inputBuf = buffer; + this.inputOff = offset; + this.inputEnd = end; } /// @@ -191,7 +275,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// Return true if input is needed via SetInput public bool NeedsInput() { - return (inputEnd == inputOff); + return this.inputEnd == this.inputOff; } /// @@ -202,13 +286,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// The length of the dictionary data. public void SetDictionary(byte[] buffer, int offset, int length) { -#if DebugDeflation - if (DeflaterConstants.DEBUGGING && (strstart != 1) ) - { - throw new InvalidOperationException("strstart not 1"); - } -#endif - adler?.Update(new ArraySegment(buffer, offset, length)); + this.adler?.Update(new ArraySegment(buffer, offset, length)); if (length < DeflaterConstants.MIN_MATCH) { return; @@ -220,17 +298,18 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib length = DeflaterConstants.MAX_DIST; } - System.Array.Copy(buffer, offset, window, strstart, length); + System.Array.Copy(buffer, offset, this.window, this.strstart, length); - UpdateHash(); + this.UpdateHash(); --length; while (--length > 0) { - InsertString(); - strstart++; + this.InsertString(); + this.strstart++; } - strstart += 2; - blockStart = strstart; + + this.strstart += 2; + this.blockStart = this.strstart; } /// @@ -238,22 +317,22 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// public void Reset() { - huffman.Reset(); - adler?.Reset(); - blockStart = strstart = 1; - lookahead = 0; - totalIn = 0; - prevAvailable = false; - matchLen = DeflaterConstants.MIN_MATCH - 1; + this.huffman.Reset(); + this.adler?.Reset(); + this.blockStart = this.strstart = 1; + this.lookahead = 0; + this.totalIn = 0; + this.prevAvailable = false; + this.matchLen = DeflaterConstants.MIN_MATCH - 1; for (int i = 0; i < DeflaterConstants.HASH_SIZE; i++) { - head[i] = 0; + this.head[i] = 0; } for (int i = 0; i < DeflaterConstants.WSIZE; i++) { - prev[i] = 0; + this.prev[i] = 0; } } @@ -262,44 +341,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// public void ResetAdler() { - adler?.Reset(); - } - - /// - /// Get current value of Adler checksum - /// - public int Adler - { - get - { - return (adler != null) ? unchecked((int)adler.Value) : 0; - } - } - - /// - /// Total data processed - /// - public long TotalIn - { - get - { - return totalIn; - } - } - - /// - /// Get/set the deflate strategy - /// - public DeflateStrategy Strategy - { - get - { - return strategy; - } - set - { - strategy = value; - } + this.adler?.Reset(); } /// @@ -313,55 +355,52 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib throw new ArgumentOutOfRangeException(nameof(level)); } - goodLength = DeflaterConstants.GOOD_LENGTH[level]; - max_lazy = DeflaterConstants.MAX_LAZY[level]; - niceLength = DeflaterConstants.NICE_LENGTH[level]; - max_chain = DeflaterConstants.MAX_CHAIN[level]; + this.goodLength = DeflaterConstants.GOOD_LENGTH[level]; + this.maxLazy = DeflaterConstants.MAX_LAZY[level]; + this.niceLength = DeflaterConstants.NICE_LENGTH[level]; + this.maxChain = DeflaterConstants.MAX_CHAIN[level]; - if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) + if (DeflaterConstants.COMPR_FUNC[level] != this.compressionFunction) { -#if DebugDeflation - if (DeflaterConstants.DEBUGGING) { - Console.WriteLine("Change from " + compressionFunction + " to " - + DeflaterConstants.COMPR_FUNC[level]); - } -#endif - switch (compressionFunction) + switch (this.compressionFunction) { case DeflaterConstants.DEFLATE_STORED: - if (strstart > blockStart) + if (this.strstart > this.blockStart) { - huffman.FlushStoredBlock(window, blockStart, - strstart - blockStart, false); - blockStart = strstart; + this.huffman.FlushStoredBlock(this.window, this.blockStart, this.strstart - this.blockStart, false); + this.blockStart = this.strstart; } - UpdateHash(); + + this.UpdateHash(); break; case DeflaterConstants.DEFLATE_FAST: - if (strstart > blockStart) + if (this.strstart > this.blockStart) { - huffman.FlushBlock(window, blockStart, strstart - blockStart, - false); - blockStart = strstart; + this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, false); + this.blockStart = this.strstart; } + break; case DeflaterConstants.DEFLATE_SLOW: - if (prevAvailable) + if (this.prevAvailable) { - huffman.TallyLit(window[strstart - 1] & 0xff); + this.huffman.TallyLit(this.window[this.strstart - 1] & 0xff); } - if (strstart > blockStart) + + if (this.strstart > this.blockStart) { - huffman.FlushBlock(window, blockStart, strstart - blockStart, false); - blockStart = strstart; + this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, false); + this.blockStart = this.strstart; } - prevAvailable = false; - matchLen = DeflaterConstants.MIN_MATCH - 1; + + this.prevAvailable = false; + this.matchLen = DeflaterConstants.MIN_MATCH - 1; break; } - compressionFunction = DeflaterConstants.COMPR_FUNC[level]; + + this.compressionFunction = DeflaterConstants.COMPR_FUNC[level]; } } @@ -370,48 +409,40 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// public void FillWindow() { - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (strstart >= DeflaterConstants.WSIZE + DeflaterConstants.MAX_DIST) + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + if (this.strstart >= DeflaterConstants.WSIZE + DeflaterConstants.MAX_DIST) { - SlideWindow(); + this.SlideWindow(); } - /* If there is not enough lookahead, but still some input left, - * read in the input - */ - if (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + // If there is not enough lookahead, but still some input left, read in the input. + if (this.lookahead < DeflaterConstants.MIN_LOOKAHEAD && this.inputOff < this.inputEnd) { - int more = 2 * DeflaterConstants.WSIZE - lookahead - strstart; + int more = (2 * DeflaterConstants.WSIZE) - this.lookahead - this.strstart; - if (more > inputEnd - inputOff) + if (more > this.inputEnd - this.inputOff) { - more = inputEnd - inputOff; + more = this.inputEnd - this.inputOff; } - System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more); - adler?.Update(new ArraySegment(inputBuf, inputOff, more)); + Array.Copy(this.inputBuf, this.inputOff, this.window, this.strstart + this.lookahead, more); + this.adler?.Update(new ArraySegment(this.inputBuf, this.inputOff, more)); - inputOff += more; - totalIn += more; - lookahead += more; + this.inputOff += more; + this.totalIn += more; + this.lookahead += more; } - if (lookahead >= DeflaterConstants.MIN_MATCH) + if (this.lookahead >= DeflaterConstants.MIN_MATCH) { - UpdateHash(); + this.UpdateHash(); } } private void UpdateHash() { - /* - if (DEBUGGING) { - Console.WriteLine("updateHash: "+strstart); - } - */ - ins_h = (window[strstart] << DeflaterConstants.HASH_SHIFT) ^ window[strstart + 1]; + this.insertHashIndex = (this.window[this.strstart] << DeflaterConstants.HASH_SHIFT) ^ this.window[this.strstart + 1]; } /// @@ -422,90 +453,87 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private int InsertString() { short match; - int hash = ((ins_h << DeflaterConstants.HASH_SHIFT) ^ window[strstart + (DeflaterConstants.MIN_MATCH - 1)]) & DeflaterConstants.HASH_MASK; + int hash = ((this.insertHashIndex << DeflaterConstants.HASH_SHIFT) ^ this.window[this.strstart + (DeflaterConstants.MIN_MATCH - 1)]) & DeflaterConstants.HASH_MASK; -#if DebugDeflation - if (DeflaterConstants.DEBUGGING) - { - if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ - (window[strstart + 1] << HASH_SHIFT) ^ - (window[strstart + 2])) & HASH_MASK)) { - throw new ImageFormatException("hash inconsistent: " + hash + "/" - +window[strstart] + "," - +window[strstart + 1] + "," - +window[strstart + 2] + "," + HASH_SHIFT); - } - } -#endif - prev[strstart & DeflaterConstants.WMASK] = match = head[hash]; - head[hash] = unchecked((short)strstart); - ins_h = hash; - return match & 0xffff; + this.prev[this.strstart & DeflaterConstants.WMASK] = match = this.head[hash]; + this.head[hash] = unchecked((short)this.strstart); + this.insertHashIndex = hash; + return match & 0xFFFF; } private void SlideWindow() { - Array.Copy(window, DeflaterConstants.WSIZE, window, 0, DeflaterConstants.WSIZE); - matchStart -= DeflaterConstants.WSIZE; - strstart -= DeflaterConstants.WSIZE; - blockStart -= DeflaterConstants.WSIZE; + Array.Copy(this.window, DeflaterConstants.WSIZE, this.window, 0, DeflaterConstants.WSIZE); + this.matchStart -= DeflaterConstants.WSIZE; + this.strstart -= DeflaterConstants.WSIZE; + this.blockStart -= DeflaterConstants.WSIZE; // Slide the hash table (could be avoided with 32 bit values // at the expense of memory usage). for (int i = 0; i < DeflaterConstants.HASH_SIZE; ++i) { - int m = head[i] & 0xffff; - head[i] = (short)(m >= DeflaterConstants.WSIZE ? (m - DeflaterConstants.WSIZE) : 0); + int m = this.head[i] & 0xFFFF; + this.head[i] = (short)(m >= DeflaterConstants.WSIZE ? (m - DeflaterConstants.WSIZE) : 0); } // Slide the prev table. for (int i = 0; i < DeflaterConstants.WSIZE; i++) { - int m = prev[i] & 0xffff; - prev[i] = (short)(m >= DeflaterConstants.WSIZE ? (m - DeflaterConstants.WSIZE) : 0); + int m = this.prev[i] & 0xFFFF; + this.prev[i] = (short)(m >= DeflaterConstants.WSIZE ? (m - DeflaterConstants.WSIZE) : 0); } } /// + /// /// Find the best (longest) string in the window matching the /// string starting at strstart. - /// + /// + /// /// Preconditions: /// /// strstart + DeflaterConstants.MAX_MATCH <= window.length. + /// /// - /// + /// The current match. /// True if a match greater than the minimum length is found private bool FindLongestMatch(int curMatch) { int match; - int scan = strstart; + int scan = this.strstart; + // scanMax is the highest position that we can look at - int scanMax = scan + Math.Min(DeflaterConstants.MAX_MATCH, lookahead) - 1; + int scanMax = scan + Math.Min(DeflaterConstants.MAX_MATCH, this.lookahead) - 1; int limit = Math.Max(scan - DeflaterConstants.MAX_DIST, 0); byte[] window = this.window; short[] prev = this.prev; - int chainLength = this.max_chain; - int niceLength = Math.Min(this.niceLength, lookahead); + int chainLength = this.maxChain; + int niceLength = Math.Min(this.niceLength, this.lookahead); - matchLen = Math.Max(matchLen, DeflaterConstants.MIN_MATCH - 1); + this.matchLen = Math.Max(this.matchLen, DeflaterConstants.MIN_MATCH - 1); - if (scan + matchLen > scanMax) return false; + if (scan + this.matchLen > scanMax) + { + return false; + } - byte scan_end1 = window[scan + matchLen - 1]; - byte scan_end = window[scan + matchLen]; + byte scan_end1 = window[scan + this.matchLen - 1]; + byte scan_end = window[scan + this.matchLen]; // Do not waste too much time if we already have a good match: - if (matchLen >= this.goodLength) chainLength >>= 2; + if (this.matchLen >= this.goodLength) + { + chainLength >>= 2; + } do { match = curMatch; - scan = strstart; + scan = this.strstart; - if (window[match + matchLen] != scan_end - || window[match + matchLen - 1] != scan_end1 + if (window[match + this.matchLen] != scan_end + || window[match + this.matchLen - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[++scan]) { @@ -516,120 +544,144 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib // scanMax - scan is the maximum number of bytes we can compare. // below we compare 8 bytes at a time, so first we compare // (scanMax - scan) % 8 bytes, so the remainder is a multiple of 8 - switch ((scanMax - scan) % 8) { case 1: - if (window[++scan] == window[++match]) break; + if (window[++scan] == window[++match]) + { + break; + } + break; case 2: if (window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match]) + { + break; + } + break; case 3: if (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match] + && window[++scan] == window[++match]) + { + break; + } + break; case 4: if (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match]) + { + break; + } + break; case 5: if (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match]) + { + break; + } + break; case 6: if (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match]) + { + break; + } + break; case 7: if (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]) break; + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match]) + { + break; + } + break; } if (window[scan] == window[match]) { - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart + 258 unless lookahead is - * exhausted first. - */ + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart + 258 unless lookahead is + // exhausted first. do { if (scan == scanMax) { - ++scan; // advance to first position not matched + ++scan; // advance to first position not matched ++match; break; } } while (window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match] - && window[++scan] == window[++match]); + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match] + && window[++scan] == window[++match]); } - if (scan - strstart > matchLen) + if (scan - this.strstart > this.matchLen) { -#if DebugDeflation - if (DeflaterConstants.DEBUGGING && (ins_h == 0) ) - Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart)); -#endif + this.matchStart = curMatch; + this.matchLen = scan - this.strstart; - matchStart = curMatch; - matchLen = scan - strstart; - - if (matchLen >= niceLength) + if (this.matchLen >= niceLength) + { break; + } scan_end1 = window[scan - 1]; scan_end = window[scan]; } - } while ((curMatch = (prev[curMatch & DeflaterConstants.WMASK] & 0xffff)) > limit && 0 != --chainLength); + } + while ((curMatch = prev[curMatch & DeflaterConstants.WMASK] & 0xFFFF) > limit && --chainLength != 0); - return matchLen >= DeflaterConstants.MIN_MATCH; + return this.matchLen >= DeflaterConstants.MIN_MATCH; } private bool DeflateStored(bool flush, bool finish) { - if (!flush && (lookahead == 0)) + if (!flush && (this.lookahead == 0)) { return false; } - strstart += lookahead; - lookahead = 0; + this.strstart += this.lookahead; + this.lookahead = 0; - int storedLength = strstart - blockStart; + int storedLength = this.strstart - this.blockStart; if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full - (blockStart < DeflaterConstants.WSIZE && storedLength >= DeflaterConstants.MAX_DIST) || // Block may move out of window + (this.blockStart < DeflaterConstants.WSIZE && storedLength >= DeflaterConstants.MAX_DIST) || // Block may move out of window flush) { bool lastBlock = finish; @@ -639,86 +691,70 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib lastBlock = false; } -#if DebugDeflation - if (DeflaterConstants.DEBUGGING) - { - Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]"); - } -#endif - - huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock); - blockStart += storedLength; + this.huffman.FlushStoredBlock(this.window, this.blockStart, storedLength, lastBlock); + this.blockStart += storedLength; return !(lastBlock || storedLength == 0); } + return true; } private bool DeflateFast(bool flush, bool finish) { - if (lookahead < DeflaterConstants.MIN_LOOKAHEAD && !flush) + if (this.lookahead < DeflaterConstants.MIN_LOOKAHEAD && !flush) { return false; } - while (lookahead >= DeflaterConstants.MIN_LOOKAHEAD || flush) + while (this.lookahead >= DeflaterConstants.MIN_LOOKAHEAD || flush) { - if (lookahead == 0) + if (this.lookahead == 0) { // We are flushing everything - huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); - blockStart = strstart; + this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, finish); + this.blockStart = this.strstart; return false; } - if (strstart > 2 * DeflaterConstants.WSIZE - DeflaterConstants.MIN_LOOKAHEAD) + if (this.strstart > (2 * DeflaterConstants.WSIZE) - DeflaterConstants.MIN_LOOKAHEAD) { - /* slide window, as FindLongestMatch needs this. - * This should only happen when flushing and the window - * is almost full. - */ - SlideWindow(); + // slide window, as FindLongestMatch needs this. + // This should only happen when flushing and the window + // is almost full. + this.SlideWindow(); } int hashHead; - if (lookahead >= DeflaterConstants.MIN_MATCH && - (hashHead = InsertString()) != 0 && - strategy != DeflateStrategy.HuffmanOnly && - strstart - hashHead <= DeflaterConstants.MAX_DIST && - FindLongestMatch(hashHead)) + if (this.lookahead >= DeflaterConstants.MIN_MATCH && + (hashHead = this.InsertString()) != 0 && + this.Strategy != DeflateStrategy.HuffmanOnly && + this.strstart - hashHead <= DeflaterConstants.MAX_DIST && + this.FindLongestMatch(hashHead)) { // longestMatch sets matchStart and matchLen -#if DebugDeflation - if (DeflaterConstants.DEBUGGING) - { - for (int i = 0 ; i < matchLen; i++) { - if (window[strstart + i] != window[matchStart + i]) { - throw new ImageFormatException("Match failure"); - } - } - } -#endif + bool full = this.huffman.TallyDist(this.strstart - this.matchStart, this.matchLen); - bool full = huffman.TallyDist(strstart - matchStart, matchLen); - - lookahead -= matchLen; - if (matchLen <= max_lazy && lookahead >= DeflaterConstants.MIN_MATCH) + this.lookahead -= this.matchLen; + if (this.matchLen <= this.maxLazy && this.lookahead >= DeflaterConstants.MIN_MATCH) { - while (--matchLen > 0) + while (--this.matchLen > 0) { - ++strstart; - InsertString(); + ++this.strstart; + this.InsertString(); } - ++strstart; + + ++this.strstart; } else { - strstart += matchLen; - if (lookahead >= DeflaterConstants.MIN_MATCH - 1) + this.strstart += this.matchLen; + if (this.lookahead >= DeflaterConstants.MIN_MATCH - 1) { - UpdateHash(); + this.UpdateHash(); } } - matchLen = DeflaterConstants.MIN_MATCH - 1; + + this.matchLen = DeflaterConstants.MIN_MATCH - 1; if (!full) { continue; @@ -727,84 +763,77 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib else { // No match found - huffman.TallyLit(window[strstart] & 0xff); - ++strstart; - --lookahead; + this.huffman.TallyLit(this.window[this.strstart] & 0xff); + ++this.strstart; + --this.lookahead; } - if (huffman.IsFull()) + if (this.huffman.IsFull()) { - bool lastBlock = finish && (lookahead == 0); - huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); - blockStart = strstart; + bool lastBlock = finish && (this.lookahead == 0); + this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, lastBlock); + this.blockStart = this.strstart; return !lastBlock; } } + return true; } private bool DeflateSlow(bool flush, bool finish) { - if (lookahead < DeflaterConstants.MIN_LOOKAHEAD && !flush) + if (this.lookahead < DeflaterConstants.MIN_LOOKAHEAD && !flush) { return false; } - while (lookahead >= DeflaterConstants.MIN_LOOKAHEAD || flush) + while (this.lookahead >= DeflaterConstants.MIN_LOOKAHEAD || flush) { - if (lookahead == 0) + if (this.lookahead == 0) { - if (prevAvailable) + if (this.prevAvailable) { - huffman.TallyLit(window[strstart - 1] & 0xff); + this.huffman.TallyLit(this.window[this.strstart - 1] & 0xff); } - prevAvailable = false; + + this.prevAvailable = false; // We are flushing everything -#if DebugDeflation - if (DeflaterConstants.DEBUGGING && !flush) - { - throw new ImageFormatException("Not flushing, but no lookahead"); - } -#endif - huffman.FlushBlock(window, blockStart, strstart - blockStart, - finish); - blockStart = strstart; + this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, finish); + this.blockStart = this.strstart; return false; } - if (strstart >= 2 * DeflaterConstants.WSIZE - DeflaterConstants.MIN_LOOKAHEAD) + if (this.strstart >= (2 * DeflaterConstants.WSIZE) - DeflaterConstants.MIN_LOOKAHEAD) { - /* slide window, as FindLongestMatch needs this. - * This should only happen when flushing and the window - * is almost full. - */ - SlideWindow(); + // slide window, as FindLongestMatch needs this. + // This should only happen when flushing and the window + // is almost full. + this.SlideWindow(); } - int prevMatch = matchStart; - int prevLen = matchLen; - if (lookahead >= DeflaterConstants.MIN_MATCH) + int prevMatch = this.matchStart; + int prevLen = this.matchLen; + if (this.lookahead >= DeflaterConstants.MIN_MATCH) { - int hashHead = InsertString(); + int hashHead = this.InsertString(); - if (strategy != DeflateStrategy.HuffmanOnly && + if (this.Strategy != DeflateStrategy.HuffmanOnly && hashHead != 0 && - strstart - hashHead <= DeflaterConstants.MAX_DIST && - FindLongestMatch(hashHead)) + this.strstart - hashHead <= DeflaterConstants.MAX_DIST && + this.FindLongestMatch(hashHead)) { // longestMatch sets matchStart and matchLen - // Discard match if too small and too far away - if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == DeflaterConstants.MIN_MATCH && strstart - matchStart > TooFar))) + if (this.matchLen <= 5 && (this.Strategy == DeflateStrategy.Filtered || (this.matchLen == DeflaterConstants.MIN_MATCH && this.strstart - this.matchStart > TooFar))) { - matchLen = DeflaterConstants.MIN_MATCH - 1; + this.matchLen = DeflaterConstants.MIN_MATCH - 1; } } } // previous match was better - if ((prevLen >= DeflaterConstants.MIN_MATCH) && (matchLen <= prevLen)) + if ((prevLen >= DeflaterConstants.MIN_MATCH) && (this.matchLen <= prevLen)) { #if DebugDeflation if (DeflaterConstants.DEBUGGING) @@ -815,137 +844,52 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } } #endif - huffman.TallyDist(strstart - 1 - prevMatch, prevLen); + this.huffman.TallyDist(this.strstart - 1 - prevMatch, prevLen); prevLen -= 2; do { - strstart++; - lookahead--; - if (lookahead >= DeflaterConstants.MIN_MATCH) + this.strstart++; + this.lookahead--; + if (this.lookahead >= DeflaterConstants.MIN_MATCH) { - InsertString(); + this.InsertString(); } - } while (--prevLen > 0); + } + while (--prevLen > 0); - strstart++; - lookahead--; - prevAvailable = false; - matchLen = DeflaterConstants.MIN_MATCH - 1; + this.strstart++; + this.lookahead--; + this.prevAvailable = false; + this.matchLen = DeflaterConstants.MIN_MATCH - 1; } else { - if (prevAvailable) + if (this.prevAvailable) { - huffman.TallyLit(window[strstart - 1] & 0xff); + this.huffman.TallyLit(this.window[this.strstart - 1] & 0xff); } - prevAvailable = true; - strstart++; - lookahead--; + + this.prevAvailable = true; + this.strstart++; + this.lookahead--; } - if (huffman.IsFull()) + if (this.huffman.IsFull()) { - int len = strstart - blockStart; - if (prevAvailable) + int len = this.strstart - this.blockStart; + if (this.prevAvailable) { len--; } - bool lastBlock = (finish && (lookahead == 0) && !prevAvailable); - huffman.FlushBlock(window, blockStart, len, lastBlock); - blockStart += len; + + bool lastBlock = finish && (this.lookahead == 0) && !this.prevAvailable; + this.huffman.FlushBlock(this.window, this.blockStart, len, lastBlock); + this.blockStart += len; return !lastBlock; } } + return true; } - - #region Instance Fields - - // Hash index of string to be inserted - private int ins_h; - - /// - /// Hashtable, hashing three characters to an index for window, so - /// that window[index]..window[index+2] have this hash code. - /// Note that the array should really be unsigned short, so you need - /// to and the values with 0xffff. - /// - private short[] head; - - /// - /// prev[index & WMASK] points to the previous index that has the - /// same hash code as the string starting at index. This way - /// entries with the same hash code are in a linked list. - /// Note that the array should really be unsigned short, so you need - /// to and the values with 0xffff. - /// - private short[] prev; - - private int matchStart; - - // Length of best match - private int matchLen; - - // Set if previous match exists - private bool prevAvailable; - - private int blockStart; - - /// - /// Points to the current character in the window. - /// - private int strstart; - - /// - /// lookahead is the number of characters starting at strstart in - /// window that are valid. - /// So window[strstart] until window[strstart+lookahead-1] are valid - /// characters. - /// - private int lookahead; - - /// - /// This array contains the part of the uncompressed stream that - /// is of relevance. The current character is indexed by strstart. - /// - private byte[] window; - - private DeflateStrategy strategy; - private int max_chain, max_lazy, niceLength, goodLength; - - /// - /// The current compression function. - /// - private int compressionFunction; - - /// - /// The input data for compression. - /// - private byte[] inputBuf; - - /// - /// The total bytes of input read. - /// - private long totalIn; - - /// - /// The offset into inputBuf, where input data starts. - /// - private int inputOff; - - /// - /// The end offset of the input data. - /// - private int inputEnd; - - private DeflaterPendingBuffer pending; - private DeflaterHuffman huffman; - - /// - /// The adler checksum - /// - private Adler32 adler; - - #endregion Instance Fields } }