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 8 using System; 9 using System.Diagnostics; 10 using System.Runtime.InteropServices; 11 12 namespace DotZLib 13 { 14 15 /// <summary> 16 /// Implements a data compressor, using the deflate algorithm in the ZLib dll 17 /// </summary> 18 public sealed class Deflater : CodecBase 19 { 20 #region Dll imports 21 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] 22 private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); 23 24 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] 25 private static extern int deflate(ref ZStream sz, int flush); 26 27 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] 28 private static extern int deflateReset(ref ZStream sz); 29 30 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] 31 private static extern int deflateEnd(ref ZStream sz); 32 #endregion 33 34 /// <summary> 35 /// Constructs an new instance of the <c>Deflater</c> 36 /// </summary> 37 /// <param name="level">The compression level to use for this <c>Deflater</c></param> 38 public Deflater(CompressLevel level) : base() 39 { 40 int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); 41 if (retval != 0) 42 throw new ZLibException(retval, "Could not initialize deflater"); 43 44 resetOutput(); 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 while (err >= 0 && _ztream.avail_in > 0) 68 { 69 err = deflate(ref _ztream, (int)FlushTypes.None); 70 if (err == 0) 71 while (_ztream.avail_out == 0) 72 { 73 OnDataAvailable(); 74 err = deflate(ref _ztream, (int)FlushTypes.None); 75 } 76 inputIndex += (int)_ztream.total_in; 77 } 78 } 79 setChecksum( _ztream.adler ); 80 } 81 82 83 /// <summary> 84 /// Finishes up any pending data that needs to be processed and handled. 85 /// </summary> 86 public override void Finish() 87 { 88 int err; 89 do 90 { 91 err = deflate(ref _ztream, (int)FlushTypes.Finish); 92 OnDataAvailable(); 93 } 94 while (err == 0); 95 setChecksum( _ztream.adler ); 96 deflateReset(ref _ztream); 97 resetOutput(); 98 } 99 100 /// <summary> 101 /// Closes the internal zlib deflate stream 102 /// </summary> 103 protected override void CleanUp() { deflateEnd(ref _ztream); } 104 105 } 106 }