1*44bedb31SLionel Sambuc // 2*44bedb31SLionel Sambuc // � Copyright Henrik Ravn 2004 3*44bedb31SLionel Sambuc // 4*44bedb31SLionel Sambuc // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 5*44bedb31SLionel Sambuc // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6*44bedb31SLionel Sambuc // 7*44bedb31SLionel Sambuc 8*44bedb31SLionel Sambuc using System; 9*44bedb31SLionel Sambuc using System.Diagnostics; 10*44bedb31SLionel Sambuc using System.Runtime.InteropServices; 11*44bedb31SLionel Sambuc 12*44bedb31SLionel Sambuc namespace DotZLib 13*44bedb31SLionel Sambuc { 14*44bedb31SLionel Sambuc 15*44bedb31SLionel Sambuc /// <summary> 16*44bedb31SLionel Sambuc /// Implements a data compressor, using the deflate algorithm in the ZLib dll 17*44bedb31SLionel Sambuc /// </summary> 18*44bedb31SLionel Sambuc public sealed class Deflater : CodecBase 19*44bedb31SLionel Sambuc { 20*44bedb31SLionel Sambuc #region Dll imports 21*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] deflateInit_(ref ZStream sz, int level, string vs, int size)22*44bedb31SLionel Sambuc private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); 23*44bedb31SLionel Sambuc 24*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] deflate(ref ZStream sz, int flush)25*44bedb31SLionel Sambuc private static extern int deflate(ref ZStream sz, int flush); 26*44bedb31SLionel Sambuc 27*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] deflateReset(ref ZStream sz)28*44bedb31SLionel Sambuc private static extern int deflateReset(ref ZStream sz); 29*44bedb31SLionel Sambuc 30*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] deflateEnd(ref ZStream sz)31*44bedb31SLionel Sambuc private static extern int deflateEnd(ref ZStream sz); 32*44bedb31SLionel Sambuc #endregion 33*44bedb31SLionel Sambuc 34*44bedb31SLionel Sambuc /// <summary> 35*44bedb31SLionel Sambuc /// Constructs an new instance of the <c>Deflater</c> 36*44bedb31SLionel Sambuc /// </summary> 37*44bedb31SLionel Sambuc /// <param name="level">The compression level to use for this <c>Deflater</c></param> Deflater(CompressLevel level)38*44bedb31SLionel Sambuc public Deflater(CompressLevel level) : base() 39*44bedb31SLionel Sambuc { 40*44bedb31SLionel Sambuc int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); 41*44bedb31SLionel Sambuc if (retval != 0) 42*44bedb31SLionel Sambuc throw new ZLibException(retval, "Could not initialize deflater"); 43*44bedb31SLionel Sambuc 44*44bedb31SLionel Sambuc resetOutput(); 45*44bedb31SLionel Sambuc } 46*44bedb31SLionel Sambuc 47*44bedb31SLionel Sambuc /// <summary> 48*44bedb31SLionel Sambuc /// Adds more data to the codec to be processed. 49*44bedb31SLionel Sambuc /// </summary> 50*44bedb31SLionel Sambuc /// <param name="data">Byte array containing the data to be added to the codec</param> 51*44bedb31SLionel Sambuc /// <param name="offset">The index of the first byte to add from <c>data</c></param> 52*44bedb31SLionel Sambuc /// <param name="count">The number of bytes to add</param> 53*44bedb31SLionel Sambuc /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> Add(byte[] data, int offset, int count)54*44bedb31SLionel Sambuc public override void Add(byte[] data, int offset, int count) 55*44bedb31SLionel Sambuc { 56*44bedb31SLionel Sambuc if (data == null) throw new ArgumentNullException(); 57*44bedb31SLionel Sambuc if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); 58*44bedb31SLionel Sambuc if ((offset+count) > data.Length) throw new ArgumentException(); 59*44bedb31SLionel Sambuc 60*44bedb31SLionel Sambuc int total = count; 61*44bedb31SLionel Sambuc int inputIndex = offset; 62*44bedb31SLionel Sambuc int err = 0; 63*44bedb31SLionel Sambuc 64*44bedb31SLionel Sambuc while (err >= 0 && inputIndex < total) 65*44bedb31SLionel Sambuc { 66*44bedb31SLionel Sambuc copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); 67*44bedb31SLionel Sambuc while (err >= 0 && _ztream.avail_in > 0) 68*44bedb31SLionel Sambuc { 69*44bedb31SLionel Sambuc err = deflate(ref _ztream, (int)FlushTypes.None); 70*44bedb31SLionel Sambuc if (err == 0) 71*44bedb31SLionel Sambuc while (_ztream.avail_out == 0) 72*44bedb31SLionel Sambuc { 73*44bedb31SLionel Sambuc OnDataAvailable(); 74*44bedb31SLionel Sambuc err = deflate(ref _ztream, (int)FlushTypes.None); 75*44bedb31SLionel Sambuc } 76*44bedb31SLionel Sambuc inputIndex += (int)_ztream.total_in; 77*44bedb31SLionel Sambuc } 78*44bedb31SLionel Sambuc } 79*44bedb31SLionel Sambuc setChecksum( _ztream.adler ); 80*44bedb31SLionel Sambuc } 81*44bedb31SLionel Sambuc 82*44bedb31SLionel Sambuc 83*44bedb31SLionel Sambuc /// <summary> 84*44bedb31SLionel Sambuc /// Finishes up any pending data that needs to be processed and handled. 85*44bedb31SLionel Sambuc /// </summary> Finish()86*44bedb31SLionel Sambuc public override void Finish() 87*44bedb31SLionel Sambuc { 88*44bedb31SLionel Sambuc int err; 89*44bedb31SLionel Sambuc do 90*44bedb31SLionel Sambuc { 91*44bedb31SLionel Sambuc err = deflate(ref _ztream, (int)FlushTypes.Finish); 92*44bedb31SLionel Sambuc OnDataAvailable(); 93*44bedb31SLionel Sambuc } 94*44bedb31SLionel Sambuc while (err == 0); 95*44bedb31SLionel Sambuc setChecksum( _ztream.adler ); 96*44bedb31SLionel Sambuc deflateReset(ref _ztream); 97*44bedb31SLionel Sambuc resetOutput(); 98*44bedb31SLionel Sambuc } 99*44bedb31SLionel Sambuc 100*44bedb31SLionel Sambuc /// <summary> 101*44bedb31SLionel Sambuc /// Closes the internal zlib deflate stream 102*44bedb31SLionel Sambuc /// </summary> CleanUp()103*44bedb31SLionel Sambuc protected override void CleanUp() { deflateEnd(ref _ztream); } 104*44bedb31SLionel Sambuc 105*44bedb31SLionel Sambuc } 106*44bedb31SLionel Sambuc } 107