compressionlibs/ziplib/src/ezlib/decompressor.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 <ezdecompressor.h>
       
    17 #include "libzcore.h"
       
    18 #include <e32debug.h>
       
    19 
       
    20 CEZDecompressor::~CEZDecompressor()
       
    21 	{
       
    22 
       
    23 	// Note inflateEnd may already have been called by zlib if an error occured during inflation.
       
    24 	// However nothing bad will happen if it gets called twice.
       
    25 
       
    26 	inflateEnd_r(&iStream);
       
    27 	}
       
    28 
       
    29 CEZDecompressor::CEZDecompressor(MEZBufferManager* aInit,const TUint8 *aDictionary, TInt aLength) : 
       
    30 		iBufferInit(aInit), iDictionary(aDictionary), iDictionaryLength(aLength)
       
    31 	{
       
    32 	
       
    33 	}
       
    34 
       
    35 CEZDecompressor::CEZDecompressor(MEZBufferManager* aInit) : 
       
    36 		iBufferInit(aInit), iDictionary(NULL), iDictionaryLength(-1)
       
    37 	{
       
    38 	
       
    39 	}
       
    40 
       
    41 
       
    42 void CEZDecompressor::ConstructL(TInt aWindowBits)
       
    43 	{
       
    44 	iStream.zalloc = Z_NULL;
       
    45 	iStream.zfree = Z_NULL;
       
    46 	iStream.opaque = Z_NULL;
       
    47 
       
    48 	iBufferInit->InitializeL(*this);
       
    49 
       
    50 	TInt err = inflateInit2_r(&iStream,aWindowBits);
       
    51 	if (err == Z_VERSION_ERROR)
       
    52 		User::Leave(KEZlibErrVersion);
       
    53 	else if (err == Z_MEM_ERROR)
       
    54 		User::LeaveNoMemory();
       
    55 
       
    56 	iInflationState = ENoFlush;
       
    57 	}
       
    58 
       
    59 /**
       
    60 Creates a new CEZDecompressor object and leaves it on the CleanupStack
       
    61 
       
    62 @param aInit buffer manager to handle both input and output buffers
       
    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 @return the new CEZDecompressor object (on the CleanupStack)
       
    67 */
       
    68 EXPORT_C CEZDecompressor*  CEZDecompressor::NewLC(MEZBufferManager& aInit, TInt aWindowBits)
       
    69 	{
       
    70 	CEZDecompressor *inf = new (ELeave) CEZDecompressor(&aInit);
       
    71 	CleanupStack::PushL(inf);
       
    72 	inf->ConstructL(aWindowBits);
       
    73 	return inf;
       
    74 	}
       
    75 
       
    76 /**
       
    77 Creates a new CEZDecompressor object
       
    78 
       
    79 @param aInit buffer manager to handle both input and output buffers
       
    80 @param aWindowBits the base two logarithm of the window size (the size of the history buffer).  It should 
       
    81 be in the range 8..15 for this version of the library. Larger values of this parameter result in better 
       
    82 compression at the expense of memory usage.
       
    83 @return the new CEZDecompressor object
       
    84 */
       
    85 EXPORT_C CEZDecompressor* CEZDecompressor::NewL(MEZBufferManager& aInit, TInt aWindowBits)
       
    86 	{
       
    87 	CEZDecompressor *inf = new (ELeave) CEZDecompressor(&aInit);
       
    88 	CleanupStack::PushL(inf);
       
    89 	inf->ConstructL(aWindowBits);
       
    90 	CleanupStack::Pop();
       
    91 	return inf;
       
    92 	}
       
    93 
       
    94 /**
       
    95 Overload of CEZDecompressor constructor takes aDictionary argument
       
    96 
       
    97 @param aInit buffer manager to handle both input and output buffers
       
    98 @param aDictionary used to initialize the de-compression dictionary from the given byte sequence.  The compressor and 
       
    99 decompressor must use exactly the same dictionary.
       
   100 @param aWindowBits the base two logarithm of the window size (the size of the history buffer).  It should 
       
   101 be in the range 8..15 for this version of the library. Larger values of this parameter result in better 
       
   102 compression at the expense of memory usage.
       
   103 @return the new CEZDecompressor object (on the CleanupStack)
       
   104 */
       
   105 EXPORT_C CEZDecompressor* CEZDecompressor::NewLC(MEZBufferManager& aInit, const TDesC8& aDictionary, TInt aWindowBits)
       
   106 	{
       
   107 	CEZDecompressor *inf = new (ELeave) CEZDecompressor(&aInit,aDictionary.Ptr(),aDictionary.Size());
       
   108 	CleanupStack::PushL(inf);
       
   109 	inf->ConstructL(aWindowBits);
       
   110 	return inf;
       
   111 	}
       
   112 
       
   113 /**
       
   114 Overload of CEZDecompressor constructor takes aDictionary argument
       
   115 
       
   116 @param aInit buffer manager to handle both input and output buffers
       
   117 @param aDictionary used to initialize the de-compression dictionary from the given byte sequence.  The compressor and 
       
   118 decompressor must use exactly the same dictionary.
       
   119 @param aWindowBits the base two logarithm of the window size (the size of the history buffer).  It should 
       
   120 be in the range 8..15 for this version of the library. Larger values of this parameter result in better 
       
   121 compression at the expense of memory usage.
       
   122 @return the new CEZDecompressor object
       
   123 */
       
   124 EXPORT_C CEZDecompressor* CEZDecompressor::NewL(MEZBufferManager& aInit, const TDesC8& aDictionary, TInt aWindowBits)
       
   125 	{
       
   126 	CEZDecompressor *inf = new (ELeave) CEZDecompressor(&aInit,aDictionary.Ptr(),aDictionary.Size());
       
   127 	CleanupStack::PushL(inf);
       
   128 	inf->ConstructL(aWindowBits);
       
   129 	CleanupStack::Pop();
       
   130 	return inf;
       
   131 	}
       
   132 
       
   133 /**
       
   134 Resets the current de-compression operation, with the new buffer manager
       
   135 
       
   136 @param aInit new buffer manager to handle the new input and output buffers
       
   137 @leave KEZlibErrStream There is a problem with the stream
       
   138 @leave ... Any of the System wide error codes
       
   139 */
       
   140 EXPORT_C void CEZDecompressor::ResetL(MEZBufferManager& aInit)
       
   141 	{
       
   142 	iBufferInit = &aInit;
       
   143 	iBufferInit->InitializeL(*this);
       
   144 	if (inflateReset_r(&iStream) == Z_STREAM_ERROR)
       
   145 		User::Leave(KEZlibErrStream);
       
   146 	iInflationState = ENoFlush;	
       
   147 	}
       
   148 
       
   149 /**
       
   150 De-compress the data to the buffer in stages, return value indicates if the de-compression has finalised 
       
   151 or if further calls are necessary
       
   152 
       
   153 @leave KEZlibErrStream There is a problem with the stream
       
   154 @leave KEZlibErrBuf There is a problem with the buffer
       
   155 @leave KEZlibErrData There is a problem with the data
       
   156 @leave KEZlibErrUnexpected Unexpected programming error
       
   157 @leave ... Any of the System wide error codes
       
   158 @return ETrue if the function must be called again, EFalse if compression is finalised
       
   159 */
       
   160 EXPORT_C TBool CEZDecompressor::InflateL()
       
   161 	{
       
   162 	TInt err;
       
   163 	TBool callAgain = ETrue;
       
   164 	
       
   165 	switch (iInflationState)
       
   166 		{
       
   167 	case ENoFlush:
       
   168 		err = inflate_r(&iStream,Z_NO_FLUSH);
       
   169 				
       
   170 		switch (err)
       
   171 			{
       
   172 		case Z_STREAM_ERROR:			
       
   173 			User::Leave(KEZlibErrStream);
       
   174 
       
   175 			break;
       
   176 
       
   177 		case Z_OK:
       
   178 			if (iStream.avail_in == 0)
       
   179 				iBufferInit->NeedInputL(*this);
       
   180 				
       
   181 			if (iStream.avail_out == 0)
       
   182 				iBufferInit->NeedOutputL(*this);
       
   183 			break;
       
   184 
       
   185 		case Z_BUF_ERROR:  			
       
   186 			User::Leave(KEZlibErrBuf);
       
   187 			break;
       
   188 
       
   189 		case Z_NEED_DICT:
       
   190 			SetDictionaryL();
       
   191 			break;
       
   192 
       
   193 		case Z_STREAM_END:
       
   194 			iInflationState = EFinalize;
       
   195 			break;
       
   196 
       
   197 		case Z_MEM_ERROR:
       
   198 			User::LeaveNoMemory();
       
   199 			break;
       
   200 		
       
   201 		case Z_DATA_ERROR:
       
   202 			User::Leave(KEZlibErrData);
       
   203 			break;
       
   204 
       
   205 		default:
       
   206 			
       
   207 			// there's something wrong with this code if we get here !
       
   208 
       
   209 			User::Leave(KEZlibErrUnexpected);
       
   210 			break;
       
   211 		}
       
   212 		break;
       
   213 	
       
   214 	case EFinalize:
       
   215 		iBufferInit->FinalizeL(*this);
       
   216 		callAgain = EFalse;
       
   217 		iInflationState = ETerminated;
       
   218 		break;
       
   219 
       
   220 	case ETerminated:		
       
   221 		User::Leave(KEZlibErrInflateTerminated);
       
   222 		}
       
   223 
       
   224 	return callAgain;
       
   225 	}
       
   226 
       
   227 void CEZDecompressor::SetDictionaryL()
       
   228 	{
       
   229 	if(!iDictionary  || iDictionaryLength < 0)
       
   230 		{
       
   231 		User::Leave(KEZlibErrData);
       
   232 		}
       
   233 
       
   234 	TInt err = inflateSetDictionary_r(&iStream,STATIC_CAST(const Bytef*,iDictionary),iDictionaryLength);
       
   235 
       
   236 	if (err == Z_DATA_ERROR)
       
   237 		User::Leave(KEZlibErrInflateDictionary);
       
   238 	else if (err == Z_STREAM_ERROR)
       
   239 		User::Leave(KEZlibErrInflateDictionary);
       
   240 
       
   241 	}
       
   242 
       
   243 /**
       
   244 De-compresses the data in the given buffer
       
   245 
       
   246 @param aDestination the target buffer for the de-compressed data
       
   247 @param aSource the buffer containing the compressed data
       
   248 @leave KEZLibErrBuf There is a problem with the buffer
       
   249 @leave KEZLIbErrData There is a problem with the data
       
   250 @leave ... Any of the system wide error codes
       
   251 */
       
   252 EXPORT_C void CEZDecompressor::DecompressL(TDes8 &aDestination, const TDesC8 &aSource)
       
   253 	{
       
   254 	uLongf dl = aDestination.MaxSize();
       
   255 	Bytef *destinationBuffer = STATIC_CAST(Bytef* , CONST_CAST(TUint8* ,aDestination.Ptr()));
       
   256 	const Bytef* sourceBuffer = STATIC_CAST(const Bytef* ,aSource.Ptr());
       
   257 	TInt err = uncompress_r(destinationBuffer,&dl,sourceBuffer,aSource.Size());
       
   258 
       
   259 	if (err == Z_MEM_ERROR) 
       
   260 		User::LeaveNoMemory();
       
   261 	else if (err == Z_BUF_ERROR)
       
   262 		User::Leave(KEZlibErrBuf);
       
   263 	else if (err == Z_DATA_ERROR)
       
   264 		User::Leave(KEZlibErrData);
       
   265 
       
   266 	aDestination.SetLength(dl);
       
   267 	}
       
   268 
       
   269 
       
   270 
       
   271