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