namespace com.hitrust.util.GZip
|
|
{
|
|
using com.hitrust.util.Checksums;
|
|
using com.hitrust.util.Zip.Compression;
|
|
using com.hitrust.util.Zip.Compression.Streams;
|
|
using System;
|
|
using System.IO;
|
|
|
|
public class GZipOutputStream : DeflaterOutputStream
|
|
{
|
|
protected Crc32 crc;
|
|
private static int GZIP_MAGIC = 0x8b1f;
|
|
private OutputState state_;
|
|
|
|
public GZipOutputStream(Stream baseOutputStream) : this(baseOutputStream, 0x200)
|
|
{
|
|
}
|
|
|
|
public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size)
|
|
{
|
|
this.crc = new Crc32();
|
|
this.state_ = OutputState.Header;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
try
|
|
{
|
|
this.Finish();
|
|
}
|
|
finally
|
|
{
|
|
if (this.state_ != OutputState.Closed)
|
|
{
|
|
this.state_ = OutputState.Closed;
|
|
if (base.IsStreamOwner)
|
|
{
|
|
base.baseOutputStream_.Close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Finish()
|
|
{
|
|
if (this.state_ == OutputState.Header)
|
|
{
|
|
this.WriteHeader();
|
|
}
|
|
if (this.state_ == OutputState.Footer)
|
|
{
|
|
this.state_ = OutputState.Finished;
|
|
base.Finish();
|
|
uint totalin = (uint) (base.deflater_.TotalIn & 0xffffffffL);
|
|
uint crcval = (uint) (((ulong) this.crc.Value) & 0xffffffffL);
|
|
byte[] gzipFooter = new byte[] { (byte) crcval, (byte) (crcval >> 8), (byte) (crcval >> 0x10), (byte) (crcval >> 0x18), (byte) totalin, (byte) (totalin >> 8), (byte) (totalin >> 0x10), (byte) (totalin >> 0x18) };
|
|
base.baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length);
|
|
}
|
|
}
|
|
|
|
public int GetLevel()
|
|
{
|
|
return base.deflater_.GetLevel();
|
|
}
|
|
|
|
public void SetLevel(int level)
|
|
{
|
|
if (level < Deflater.BEST_SPEED)
|
|
{
|
|
throw new ArgumentOutOfRangeException("level");
|
|
}
|
|
base.deflater_.SetLevel(level);
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
if (this.state_ == OutputState.Header)
|
|
{
|
|
this.WriteHeader();
|
|
}
|
|
if (this.state_ != OutputState.Footer)
|
|
{
|
|
throw new InvalidOperationException("Write not permitted in current state");
|
|
}
|
|
this.crc.Update(buffer, offset, count);
|
|
base.Write(buffer, offset, count);
|
|
}
|
|
|
|
private void WriteHeader()
|
|
{
|
|
if (this.state_ == OutputState.Header)
|
|
{
|
|
this.state_ = OutputState.Footer;
|
|
DateTime date = new DateTime(0x7b2, 1, 1);
|
|
int mod_time = (int) ((DateTime.Now.Ticks - date.Ticks) / 0x989680L);
|
|
byte[] bytes = new byte[10];
|
|
bytes[0] = (byte) GZIP_MAGIC;
|
|
bytes[1] = (byte) (GZIP_MAGIC >> 8);
|
|
bytes[2] = (byte) Deflater.DEFLATED;
|
|
byte[] gzipHeader = bytes;
|
|
base.baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length);
|
|
}
|
|
}
|
|
|
|
private enum OutputState
|
|
{
|
|
Header,
|
|
Footer,
|
|
Finished,
|
|
Closed
|
|
}
|
|
}
|
|
}
|
|
|