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 decompressor, using the inflate algorithm in the ZLib dll 17*44bedb31SLionel Sambuc /// </summary> 18*44bedb31SLionel Sambuc public class Inflater : CodecBase 19*44bedb31SLionel Sambuc { 20*44bedb31SLionel Sambuc #region Dll imports 21*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] inflateInit_(ref ZStream sz, string vs, int size)22*44bedb31SLionel Sambuc private static extern int inflateInit_(ref ZStream sz, string vs, int size); 23*44bedb31SLionel Sambuc 24*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] inflate(ref ZStream sz, int flush)25*44bedb31SLionel Sambuc private static extern int inflate(ref ZStream sz, int flush); 26*44bedb31SLionel Sambuc 27*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] inflateReset(ref ZStream sz)28*44bedb31SLionel Sambuc private static extern int inflateReset(ref ZStream sz); 29*44bedb31SLionel Sambuc 30*44bedb31SLionel Sambuc [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] inflateEnd(ref ZStream sz)31*44bedb31SLionel Sambuc private static extern int inflateEnd(ref ZStream sz); 32*44bedb31SLionel Sambuc #endregion 33*44bedb31SLionel Sambuc 34*44bedb31SLionel Sambuc /// <summary> 35*44bedb31SLionel Sambuc /// Constructs an new instance of the <c>Inflater</c> 36*44bedb31SLionel Sambuc /// </summary> Inflater()37*44bedb31SLionel Sambuc public Inflater() : base() 38*44bedb31SLionel Sambuc { 39*44bedb31SLionel Sambuc int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); 40*44bedb31SLionel Sambuc if (retval != 0) 41*44bedb31SLionel Sambuc throw new ZLibException(retval, "Could not initialize inflater"); 42*44bedb31SLionel Sambuc 43*44bedb31SLionel Sambuc resetOutput(); 44*44bedb31SLionel Sambuc } 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 err = inflate(ref _ztream, (int)FlushTypes.None); 68*44bedb31SLionel Sambuc if (err == 0) 69*44bedb31SLionel Sambuc while (_ztream.avail_out == 0) 70*44bedb31SLionel Sambuc { 71*44bedb31SLionel Sambuc OnDataAvailable(); 72*44bedb31SLionel Sambuc err = inflate(ref _ztream, (int)FlushTypes.None); 73*44bedb31SLionel Sambuc } 74*44bedb31SLionel Sambuc 75*44bedb31SLionel Sambuc inputIndex += (int)_ztream.total_in; 76*44bedb31SLionel Sambuc } 77*44bedb31SLionel Sambuc setChecksum( _ztream.adler ); 78*44bedb31SLionel Sambuc } 79*44bedb31SLionel Sambuc 80*44bedb31SLionel Sambuc 81*44bedb31SLionel Sambuc /// <summary> 82*44bedb31SLionel Sambuc /// Finishes up any pending data that needs to be processed and handled. 83*44bedb31SLionel Sambuc /// </summary> Finish()84*44bedb31SLionel Sambuc public override void Finish() 85*44bedb31SLionel Sambuc { 86*44bedb31SLionel Sambuc int err; 87*44bedb31SLionel Sambuc do 88*44bedb31SLionel Sambuc { 89*44bedb31SLionel Sambuc err = inflate(ref _ztream, (int)FlushTypes.Finish); 90*44bedb31SLionel Sambuc OnDataAvailable(); 91*44bedb31SLionel Sambuc } 92*44bedb31SLionel Sambuc while (err == 0); 93*44bedb31SLionel Sambuc setChecksum( _ztream.adler ); 94*44bedb31SLionel Sambuc inflateReset(ref _ztream); 95*44bedb31SLionel Sambuc resetOutput(); 96*44bedb31SLionel Sambuc } 97*44bedb31SLionel Sambuc 98*44bedb31SLionel Sambuc /// <summary> 99*44bedb31SLionel Sambuc /// Closes the internal zlib inflate stream 100*44bedb31SLionel Sambuc /// </summary> CleanUp()101*44bedb31SLionel Sambuc protected override void CleanUp() { inflateEnd(ref _ztream); } 102*44bedb31SLionel Sambuc 103*44bedb31SLionel Sambuc 104*44bedb31SLionel Sambuc } 105*44bedb31SLionel Sambuc } 106