|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <ezcompressor.h> |
|
17 #include "libzcore.h" |
|
18 |
|
19 CEZCompressor::CEZCompressor(MEZBufferManager* aInit) : |
|
20 iBufferInit(aInit) |
|
21 { |
|
22 |
|
23 } |
|
24 |
|
25 CEZCompressor::~CEZCompressor() |
|
26 { |
|
27 // Note that deflateEnd may have already been called by zlib if for example and alloc failure |
|
28 // occurred in deflateInit2. However there is no harm in calling deflateEnd twice. |
|
29 |
|
30 deflateEnd_r(&iStream); |
|
31 } |
|
32 |
|
33 /** |
|
34 Creates a new CEZCompressor object and leaves it on the CleanupStack |
|
35 |
|
36 @param aInit buffer manager to handle both input and output buffers |
|
37 @param aLevel compression levels |
|
38 @param aWindowBits the base two logarithm of the window size (the size of the history buffer). It should |
|
39 be in the range 8..15 for this version of the library. Larger values of this parameter result in better |
|
40 compression at the expense of memory usage. |
|
41 @param aMemLevel specifies how much memory should be allocated for the internal compression state. |
|
42 memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory |
|
43 for optimal speed. |
|
44 @param aStrategy compression strategy - used to tune the compression algorithm. The strategy parameter only affects |
|
45 the compression ratio but not the correctness of the compressed output even if it is not set appropriately |
|
46 @see TStrategy |
|
47 @return the new CEZCompressor object (on the CleanupStack) |
|
48 */ |
|
49 EXPORT_C CEZCompressor *CEZCompressor::NewLC(MEZBufferManager& aInit, TInt aLevel, TInt aWindowBits, |
|
50 TInt aMemLevel, TStrategy aStrategy) |
|
51 { |
|
52 CEZCompressor* deflater = new (ELeave) CEZCompressor(&aInit); |
|
53 CleanupStack::PushL(deflater); |
|
54 deflater->ConstructL(aLevel,aWindowBits,aMemLevel,aStrategy); |
|
55 return deflater; |
|
56 } |
|
57 |
|
58 /** |
|
59 Creates a new CEZCompressor object |
|
60 |
|
61 @param aInit buffer manager to handle both input and output buffers |
|
62 @param aLevel compression levels |
|
63 @param aWindowBits the base two logarithm of the window size (the size of the history buffer). It should |
|
64 be in the range 8..15 for this version of the library. Larger values of this parameter result in better |
|
65 compression at the expense of memory usage. |
|
66 @param aMemLevel specifies how much memory should be allocated for the internal compression state. |
|
67 memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory |
|
68 for optimal speed. |
|
69 @param aStrategy compression strategy - used to tune the compression algorithm. The strategy parameter only affects |
|
70 the compression ratio but not the correctness of the compressed output even if it is not set appropriately |
|
71 @see TStrategy |
|
72 @return the new CEZCompressor object |
|
73 */ |
|
74 EXPORT_C CEZCompressor* CEZCompressor::NewL(MEZBufferManager& aInit, TInt aLevel, TInt aWindowBits, |
|
75 TInt aMemLevel, TStrategy aStrategy) |
|
76 { |
|
77 CEZCompressor* deflater = new (ELeave) CEZCompressor(&aInit); |
|
78 CleanupStack::PushL(deflater); |
|
79 deflater->ConstructL(aLevel,aWindowBits,aMemLevel,aStrategy); |
|
80 CleanupStack::Pop(); |
|
81 return deflater; |
|
82 } |
|
83 |
|
84 /** |
|
85 Overload of CEZCompressor constructor takes aDictionary argument |
|
86 |
|
87 @param aInit buffer manager to handle both input and output buffers |
|
88 @param aDictionary used to initialize the compression dictionary from the given byte sequence |
|
89 without producing any compressed output. The compressor and decompressor must use exactly the same dictionary. |
|
90 The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, |
|
91 with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful |
|
92 when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than |
|
93 with the default empty dictionary. |
|
94 @param aLevel compression level |
|
95 @param aWindowBits the base two logarithm of the window size (the size of the history buffer). It should |
|
96 be in the range 8..15 for this version of the library. Larger values of this parameter result in better |
|
97 compression at the expense of memory usage. |
|
98 @param aMemLevel specifies how much memory should be allocated for the internal compression state. |
|
99 memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory |
|
100 for optimal speed. |
|
101 @param aStrategy compression strategy - used to tune the compression algorithm. The strategy parameter only affects |
|
102 the compression ratio but not the correctness of the compressed output even if it is not set appropriately |
|
103 @see TStrategy |
|
104 @return the new CEZCompressor object (on the CleanupStack) |
|
105 */ |
|
106 EXPORT_C CEZCompressor* CEZCompressor::NewLC(MEZBufferManager& aInit, const TDesC8& aDictionary, |
|
107 TInt aLevel, TInt aWindowBits, TInt aMemLevel, TStrategy aStrategy) |
|
108 { |
|
109 CEZCompressor* deflater = new (ELeave) CEZCompressor(&aInit); |
|
110 CleanupStack::PushL(deflater); |
|
111 deflater->ConstructL(aLevel,aDictionary.Ptr(),aDictionary.Size(),aWindowBits,aMemLevel,aStrategy); |
|
112 return deflater; |
|
113 } |
|
114 |
|
115 /** |
|
116 Overload of CEZCompressor constructor takes aDictionary argument |
|
117 |
|
118 @param aInit buffer manager to handle both input and output buffers |
|
119 @param aDictionary used to initialize the compression dictionary from the given byte sequence |
|
120 without producing any compressed output. The compressor and decompressor must use exactly the same dictionary. |
|
121 The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, |
|
122 with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful |
|
123 when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than |
|
124 with the default empty dictionary. |
|
125 @param aLevel compression level |
|
126 @param aWindowBits the base two logarithm of the window size (the size of the history buffer). It should |
|
127 be in the range 8..15 for this version of the library. Larger values of this parameter result in better |
|
128 compression at the expense of memory usage. |
|
129 @param aMemLevel specifies how much memory should be allocated for the internal compression state. |
|
130 memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory |
|
131 for optimal speed. |
|
132 @param aStrategy compression strategy - used to tune the compression algorithm. The strategy parameter only affects |
|
133 the compression ratio but not the correctness of the compressed output even if it is not set appropriately |
|
134 @see TStrategy |
|
135 @return the new CEZCompressor object |
|
136 */ |
|
137 EXPORT_C CEZCompressor* CEZCompressor::NewL(MEZBufferManager& aInit, const TDesC8& aDictionary, |
|
138 TInt aLevel, TInt aWindowBits, TInt aMemLevel, TStrategy aStrategy) |
|
139 { |
|
140 CEZCompressor* deflater = new (ELeave) CEZCompressor(&aInit); |
|
141 CleanupStack::PushL(deflater); |
|
142 deflater->ConstructL(aLevel,aDictionary.Ptr(),aDictionary.Size(),aWindowBits,aMemLevel,aStrategy); |
|
143 CleanupStack::Pop(); |
|
144 return deflater; |
|
145 } |
|
146 |
|
147 /** |
|
148 Resets the current compression operation, with the new buffer manager |
|
149 |
|
150 @param aInit new buffer manager to handle the new input and output buffers |
|
151 @leave ... Any of the system wide error codes |
|
152 */ |
|
153 EXPORT_C void CEZCompressor::ResetL(MEZBufferManager& aInit) |
|
154 { |
|
155 iBufferInit = &aInit; |
|
156 iBufferInit->InitializeL(*this); |
|
157 if (deflateReset_r(&iStream) == Z_STREAM_ERROR) |
|
158 User::Leave(KEZlibErrStream); |
|
159 iDeflationState = ENoFlush; |
|
160 } |
|
161 |
|
162 /** |
|
163 Compress the data to the buffer in stages, return value indicates if the compression has finalised |
|
164 or if further calls are necessary |
|
165 |
|
166 @leave KEZlibErrStream There is a problem with the stream |
|
167 @leave KEZlibErrBuf There is a problem with the buffer |
|
168 @leave KEZlibErrUnexpected Unexpected programming error |
|
169 @leave ... Any of the System wide error codes |
|
170 @return ETrue if the function must be called again, EFalse if compression is finalised |
|
171 */ |
|
172 EXPORT_C TBool CEZCompressor::DeflateL() |
|
173 { |
|
174 TInt err; |
|
175 TBool callAgain = ETrue; |
|
176 |
|
177 switch (iDeflationState) |
|
178 { |
|
179 case ENoFlush: |
|
180 err = deflate_r(&iStream,Z_NO_FLUSH); |
|
181 |
|
182 switch (err) |
|
183 { |
|
184 case Z_STREAM_ERROR: |
|
185 User::Leave(KEZlibErrStream); |
|
186 break; |
|
187 |
|
188 case Z_OK: |
|
189 if (iStream.avail_in == 0) |
|
190 iBufferInit->NeedInputL(*this); |
|
191 |
|
192 if (iStream.avail_out == 0) |
|
193 iBufferInit->NeedOutputL(*this); |
|
194 break; |
|
195 |
|
196 case Z_BUF_ERROR: |
|
197 // this is probably ok we have just run out of input. |
|
198 |
|
199 iDeflationState = EFinish; |
|
200 break; |
|
201 |
|
202 default: |
|
203 |
|
204 // there's something wrong with this code if we get here ! |
|
205 |
|
206 User::Leave(KEZlibErrUnexpected); |
|
207 break; |
|
208 } |
|
209 |
|
210 break; |
|
211 |
|
212 case EFinish: |
|
213 err = deflate_r(&iStream,Z_FINISH); |
|
214 |
|
215 switch (err) |
|
216 { |
|
217 case Z_STREAM_ERROR: |
|
218 User::Leave(KEZlibErrStream); |
|
219 break; |
|
220 |
|
221 case Z_BUF_ERROR: |
|
222 User::Leave(KEZlibErrBuf); |
|
223 break; |
|
224 |
|
225 case Z_OK: |
|
226 if (iStream.avail_in == 0) |
|
227 iBufferInit->NeedInputL(*this); |
|
228 |
|
229 if (iStream.avail_out == 0) |
|
230 iBufferInit->NeedOutputL(*this); |
|
231 break; |
|
232 |
|
233 case Z_STREAM_END: |
|
234 iDeflationState = EFinalize; |
|
235 break; |
|
236 |
|
237 default: |
|
238 // there's something wrong with this code if we get here ! |
|
239 |
|
240 User::Leave(KEZlibErrUnexpected); |
|
241 break; |
|
242 } |
|
243 |
|
244 break; |
|
245 |
|
246 case EFinalize: |
|
247 iBufferInit->FinalizeL(*this); |
|
248 callAgain = EFalse; |
|
249 iDeflationState = ETerminated; |
|
250 break; |
|
251 |
|
252 case ETerminated: |
|
253 User::Leave(KEZlibErrDeflateTerminated); |
|
254 } |
|
255 |
|
256 return callAgain; |
|
257 } |
|
258 |
|
259 void CEZCompressor::ConstructL(TInt aLevel, const TUint8 *aDictionary, TInt aLength, |
|
260 TInt aWindowBits, TInt aMemLevel, TStrategy aStrategy) |
|
261 { |
|
262 ConstructL(aLevel,aWindowBits,aMemLevel,aStrategy); |
|
263 if (deflateSetDictionary_r(&iStream,STATIC_CAST(const Bytef *,aDictionary),aLength) == |
|
264 Z_STREAM_ERROR) |
|
265 User::Leave(KEZlibErrStream); // This should never happen. |
|
266 } |
|
267 |
|
268 void CEZCompressor::ConstructL(TInt aLevel, TInt aWindowBits, TInt aMemLevel, TStrategy aStrategy) |
|
269 { |
|
270 // don't need to assert the validity of aWindowBits, aMemLevel & aStrategy as deflateInit2 will |
|
271 // do this for us. |
|
272 |
|
273 iStream.zalloc = Z_NULL; |
|
274 iStream.zfree = Z_NULL; |
|
275 iStream.opaque = Z_NULL; |
|
276 |
|
277 iBufferInit->InitializeL(*this); |
|
278 |
|
279 TInt err = deflateInit2_r(&iStream,aLevel,Z_DEFLATED,aWindowBits,aMemLevel, STATIC_CAST(int,aStrategy)); |
|
280 if (err == Z_STREAM_ERROR) |
|
281 User::Leave(KEZlibErrStream); |
|
282 else if (err == Z_MEM_ERROR) |
|
283 User::LeaveNoMemory(); |
|
284 |
|
285 iDeflationState = ENoFlush; |
|
286 } |
|
287 |
|
288 /** |
|
289 Compresses the data in the given buffer |
|
290 |
|
291 @param aDestination the target buffer for the compressed data |
|
292 @param aSource the buffer containing the data to be compressed |
|
293 @param aLevel the level of compression |
|
294 @leave KEZLibErrBuf There is a problem with the buffer |
|
295 @leave KEZLIbErrStream There is a problem with the stream |
|
296 @leave ... Any of the system wide error codes |
|
297 */ |
|
298 EXPORT_C void CEZCompressor::CompressL(TDes8 &aDestination, const TDesC8 &aSource, |
|
299 TInt aLevel) |
|
300 { |
|
301 Bytef* destinationBuffer = STATIC_CAST(Bytef* ,CONST_CAST(TUint8* ,aDestination.Ptr())); |
|
302 const Bytef* sourceBuffer = STATIC_CAST(const Bytef* ,aSource.Ptr()); |
|
303 uLongf dl = aDestination.MaxSize(); |
|
304 TInt err = compress2_r(destinationBuffer,&dl,sourceBuffer,aSource.Size(),aLevel); |
|
305 |
|
306 if (err == Z_MEM_ERROR) |
|
307 User::LeaveNoMemory(); |
|
308 else if (err == Z_BUF_ERROR) |
|
309 User::Leave(KEZlibErrBuf); |
|
310 else if (err == Z_STREAM_ERROR) |
|
311 User::Leave(KEZlibErrStream); |
|
312 |
|
313 aDestination.SetLength(dl); |
|
314 } |