]> git.tdb.fi Git - ext/zlib.git/blob - contrib/dotzlib/DotZLib/CodecBase.cs
Import zlib 1.2.13
[ext/zlib.git] / contrib / dotzlib / DotZLib / CodecBase.cs
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.Runtime.InteropServices;
10
11 namespace DotZLib
12 {
13         /// <summary>
14         /// Implements the common functionality needed for all <see cref="Codec"/>s
15         /// </summary>
16         public abstract class CodecBase : Codec, IDisposable
17         {
18
19         #region Data members
20
21         /// <summary>
22         /// Instance of the internal zlib buffer structure that is
23         /// passed to all functions in the zlib dll
24         /// </summary>
25         internal ZStream _ztream = new ZStream();
26
27         /// <summary>
28         /// True if the object instance has been disposed, false otherwise
29         /// </summary>
30         protected bool _isDisposed = false;
31
32         /// <summary>
33         /// The size of the internal buffers
34         /// </summary>
35         protected const int kBufferSize = 16384;
36
37         private byte[] _outBuffer = new byte[kBufferSize];
38         private byte[] _inBuffer = new byte[kBufferSize];
39
40         private GCHandle _hInput;
41         private GCHandle _hOutput;
42
43         private uint _checksum = 0;
44
45         #endregion
46
47         /// <summary>
48         /// Initializes a new instance of the <c>CodeBase</c> class.
49         /// </summary>
50                 public CodecBase()
51                 {
52             try
53             {
54                 _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned);
55                 _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned);
56             }
57             catch (Exception)
58             {
59                 CleanUp(false);
60                 throw;
61             }
62         }
63
64
65         #region Codec Members
66
67         /// <summary>
68         /// Occurs when more processed data are available.
69         /// </summary>
70         public event DataAvailableHandler DataAvailable;
71
72         /// <summary>
73         /// Fires the <see cref="DataAvailable"/> event
74         /// </summary>
75         protected void OnDataAvailable()
76         {
77             if (_ztream.total_out > 0)
78             {
79                 if (DataAvailable != null)
80                     DataAvailable( _outBuffer, 0, (int)_ztream.total_out);
81                 resetOutput();
82             }
83         }
84
85         /// <summary>
86         /// Adds more data to the codec to be processed.
87         /// </summary>
88         /// <param name="data">Byte array containing the data to be added to the codec</param>
89         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
90         public void Add(byte[] data)
91         {
92             Add(data,0,data.Length);
93         }
94
95         /// <summary>
96         /// Adds more data to the codec to be processed.
97         /// </summary>
98         /// <param name="data">Byte array containing the data to be added to the codec</param>
99         /// <param name="offset">The index of the first byte to add from <c>data</c></param>
100         /// <param name="count">The number of bytes to add</param>
101         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
102         /// <remarks>This must be implemented by a derived class</remarks>
103         public abstract void Add(byte[] data, int offset, int count);
104
105         /// <summary>
106         /// Finishes up any pending data that needs to be processed and handled.
107         /// </summary>
108         /// <remarks>This must be implemented by a derived class</remarks>
109         public abstract void Finish();
110
111         /// <summary>
112         /// Gets the checksum of the data that has been added so far
113         /// </summary>
114         public uint Checksum { get { return _checksum; } }
115
116         #endregion
117
118         #region Destructor & IDisposable stuff
119
120         /// <summary>
121         /// Destroys this instance
122         /// </summary>
123         ~CodecBase()
124         {
125             CleanUp(false);
126         }
127
128         /// <summary>
129         /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class
130         /// </summary>
131         public void Dispose()
132         {
133             CleanUp(true);
134         }
135
136         /// <summary>
137         /// Performs any codec specific cleanup
138         /// </summary>
139         /// <remarks>This must be implemented by a derived class</remarks>
140         protected abstract void CleanUp();
141
142         // performs the release of the handles and calls the dereived CleanUp()
143         private void CleanUp(bool isDisposing)
144         {
145             if (!_isDisposed)
146             {
147                 CleanUp();
148                 if (_hInput.IsAllocated)
149                     _hInput.Free();
150                 if (_hOutput.IsAllocated)
151                     _hOutput.Free();
152
153                 _isDisposed = true;
154             }
155         }
156
157
158         #endregion
159
160         #region Helper methods
161
162         /// <summary>
163         /// Copies a number of bytes to the internal codec buffer - ready for proccesing
164         /// </summary>
165         /// <param name="data">The byte array that contains the data to copy</param>
166         /// <param name="startIndex">The index of the first byte to copy</param>
167         /// <param name="count">The number of bytes to copy from <c>data</c></param>
168         protected void copyInput(byte[] data, int startIndex, int count)
169         {
170             Array.Copy(data, startIndex, _inBuffer,0, count);
171             _ztream.next_in = _hInput.AddrOfPinnedObject();
172             _ztream.total_in = 0;
173             _ztream.avail_in = (uint)count;
174
175         }
176
177         /// <summary>
178         /// Resets the internal output buffers to a known state - ready for processing
179         /// </summary>
180         protected void resetOutput()
181         {
182             _ztream.total_out = 0;
183             _ztream.avail_out = kBufferSize;
184             _ztream.next_out = _hOutput.AddrOfPinnedObject();
185         }
186
187         /// <summary>
188         /// Updates the running checksum property
189         /// </summary>
190         /// <param name="newSum">The new checksum value</param>
191         protected void setChecksum(uint newSum)
192         {
193             _checksum = newSum;
194         }
195         #endregion
196
197     }
198 }