You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

249 lines
7.4 KiB

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;
}
}
}
}