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