|
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 } |