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