namespace com.hitrust.util.Zip.Compression { using System; public class Deflater { public static int BEST_COMPRESSION = 9; public static int BEST_SPEED = 1; private static int BUSY_STATE = 0x10; private static int CLOSED_STATE = 0x7f; public static int DEFAULT_COMPRESSION = -1; public static int DEFLATED = 8; private DeflaterEngine engine; private static int FINISHED_STATE = 30; private static int FINISHING_STATE = 0x1c; private static int FLUSHING_STATE = 20; private static int INIT_STATE = 0; private static int IS_FINISHING = 8; private static int IS_FLUSHING = 4; private static int IS_SETDICT = 1; private int level; public static int NO_COMPRESSION = 0; private bool noZlibHeaderOrFooter; private DeflaterPending pending; private static int SETDICT_STATE = 1; private int state; private long totalOut; public Deflater() : this(DEFAULT_COMPRESSION, false) { } public Deflater(int lvl) : this(lvl, false) { } public Deflater(int level, bool noZlibHeaderOrFooter) { if (level == DEFAULT_COMPRESSION) { level = 6; } else if ((level < NO_COMPRESSION) || (level > BEST_COMPRESSION)) { throw new ArgumentOutOfRangeException("level"); } this.pending = new DeflaterPending(); this.engine = new DeflaterEngine(this.pending); this.noZlibHeaderOrFooter = noZlibHeaderOrFooter; this.SetStrategy(DeflateStrategy.Default); this.SetLevel(level); this.Reset(); } public int Deflate(byte[] output) { return this.Deflate(output, 0, output.Length); } public int Deflate(byte[] output, int offset, int length) { int num = length; if (this.state == CLOSED_STATE) { throw new InvalidOperationException("Deflater closed"); } if (this.state < BUSY_STATE) { int s = (DEFLATED + 0x70) << 8; int num3 = (this.level - 1) >> 1; if ((num3 < 0) || (num3 > 3)) { num3 = 3; } s |= num3 << 6; if ((this.state & IS_SETDICT) != 0) { s |= 0x20; } s += 0x1f - (s % 0x1f); this.pending.WriteShortMSB(s); if ((this.state & IS_SETDICT) != 0) { int adler = this.engine.Adler; this.engine.ResetAdler(); this.pending.WriteShortMSB(adler >> 0x10); this.pending.WriteShortMSB(adler & 0xffff); } this.state = BUSY_STATE | (this.state & (IS_FLUSHING | IS_FINISHING)); } while (true) { do { int num5 = this.pending.Flush(output, offset, length); offset += num5; this.totalOut += num5; length -= num5; if ((length == 0) || (this.state == FINISHED_STATE)) { return (num - length); } } while (this.engine.Deflate((this.state & IS_FLUSHING) != 0, (this.state & IS_FINISHING) != 0)); if (this.state == BUSY_STATE) { return (num - length); } if (this.state == FLUSHING_STATE) { if (this.level != NO_COMPRESSION) { for (int i = 8 + (-this.pending.BitCount & 7); i > 0; i -= 10) { this.pending.WriteBits(2, 10); } } this.state = BUSY_STATE; } else if (this.state == FINISHING_STATE) { this.pending.AlignToByte(); if (!this.noZlibHeaderOrFooter) { int num7 = this.engine.Adler; this.pending.WriteShortMSB(num7 >> 0x10); this.pending.WriteShortMSB(num7 & 0xffff); } this.state = FINISHED_STATE; } } } public void Finish() { this.state |= IS_FLUSHING | IS_FINISHING; } public void Flush() { this.state |= IS_FLUSHING; } public int GetLevel() { return this.level; } public void Reset() { this.state = this.noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE; this.totalOut = 0L; this.pending.Reset(); this.engine.Reset(); } public void SetDictionary(byte[] dict) { this.SetDictionary(dict, 0, dict.Length); } public void SetDictionary(byte[] dict, int offset, int length) { if (this.state != INIT_STATE) { throw new InvalidOperationException(); } this.state = SETDICT_STATE; this.engine.SetDictionary(dict, offset, length); } public void SetInput(byte[] input) { this.SetInput(input, 0, input.Length); } public void SetInput(byte[] input, int off, int len) { if ((this.state & IS_FINISHING) != 0) { throw new InvalidOperationException("finish()/end() already called"); } this.engine.SetInput(input, off, len); } public void SetLevel(int lvl) { if (lvl == DEFAULT_COMPRESSION) { lvl = 6; } else if ((lvl < NO_COMPRESSION) || (lvl > BEST_COMPRESSION)) { throw new ArgumentOutOfRangeException("lvl"); } if (this.level != lvl) { this.level = lvl; this.engine.SetLevel(lvl); } } public void SetStrategy(DeflateStrategy strategy) { this.engine.Strategy = strategy; } public int Adler { get { return this.engine.Adler; } } public bool IsFinished { get { return ((this.state == FINISHED_STATE) && this.pending.IsFlushed); } } public bool IsNeedingInput { get { return this.engine.NeedsInput(); } } public int TotalIn { get { return this.engine.TotalIn; } } public long TotalOut { get { return this.totalOut; } } } }