compressionlibs/ziplib/src/ezlib/compressor.cpp
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     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 	}