e32tools/elf2e32/source/inflate.cpp
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 // Copyright (c) 2005-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 // Implementation of the Inflater for e32 image dump for the elf2e32 tool
       
    15 // @internalComponent
       
    16 // @released
       
    17 // 
       
    18 //
       
    19 
       
    20 #include "huffman.h"
       
    21 #include "inflate.h"
       
    22 #include <cpudefs.h>
       
    23 #include "farray.h"
       
    24 #include "errorhandler.h"
       
    25 #include<iostream>
       
    26 using std::cout;
       
    27 
       
    28 /*
       
    29 Inline constructor for CInflater
       
    30 @param aInput
       
    31 @internalComponent
       
    32 @released
       
    33 */
       
    34 inline CInflater::CInflater(TBitInput& aInput):iBits(&aInput),iEncoding(0),iOut(0)
       
    35 {
       
    36 }
       
    37 
       
    38 /*
       
    39 Function for the 2nd phase construction.
       
    40 @param 
       
    41 @internalComponent
       
    42 @released
       
    43 */
       
    44 void CInflater::ConstructL()
       
    45 {
       
    46 	iEncoding=new TEncoding;
       
    47 	InitL();
       
    48 	iLen=0;
       
    49 	iOut=new TUint8[KDeflateMaxDistance];
       
    50 	iAvail=iLimit=iOut;
       
    51 }
       
    52 
       
    53 /*
       
    54 Function NewLC
       
    55 @Leave OutOfMemory
       
    56 @param aInput
       
    57 @return pointer to self
       
    58 @internalComponent
       
    59 @released
       
    60 */
       
    61 CInflater* CInflater::NewLC(TBitInput& aInput)
       
    62 {
       
    63 	CInflater* self=new CInflater(aInput);
       
    64 	self->ConstructL();
       
    65 
       
    66 	return self;
       
    67 }
       
    68 
       
    69 /*
       
    70 Destructor for CInflater
       
    71 @internalComponent
       
    72 @released
       
    73 */
       
    74 CInflater::~CInflater()
       
    75 {
       
    76 	delete iEncoding;
       
    77 	delete [] iOut;
       
    78 }
       
    79 
       
    80 /*
       
    81 Function ReadL
       
    82 @Leave 
       
    83 @param aBuffer
       
    84 @param aLength
       
    85 @internalComponent
       
    86 @released
       
    87 */
       
    88 TInt CInflater::ReadL(TUint8* aBuffer,TInt aLength)
       
    89 {
       
    90 	TInt tfr=0;
       
    91 	for (;;)
       
    92 	{
       
    93 		TInt len;
       
    94 		if(aLength > (iLimit-iAvail))
       
    95 			len=iLimit-iAvail;
       
    96 		else
       
    97 			len=aLength;
       
    98 
       
    99 		if (len && aBuffer)
       
   100 		{
       
   101 			memcpy((void * const)aBuffer,(const void * const)iAvail,(size_t)len);
       
   102 			aBuffer+=len;
       
   103 		}
       
   104 		aLength-=len;
       
   105 		iAvail+=len;
       
   106 		tfr+=len;
       
   107 		if (aLength==0)
       
   108 			return tfr;
       
   109 		len=InflateL();
       
   110 		if (len==0)
       
   111 			return tfr;
       
   112 		iAvail=iOut;
       
   113 		iLimit=iAvail+len;
       
   114 	}
       
   115 }
       
   116 
       
   117 /*
       
   118 Function InitL
       
   119 @Leave
       
   120 @internalComponent
       
   121 @released
       
   122 */
       
   123 void CInflater::InitL()
       
   124 {
       
   125 	// read the encoding
       
   126 	Huffman::InternalizeL(*iBits,iEncoding->iLitLen,KDeflationCodes);
       
   127 	// validate the encoding
       
   128 	if (!Huffman::IsValid(iEncoding->iLitLen,TEncoding::ELitLens) ||
       
   129 		!Huffman::IsValid(iEncoding->iDistance,TEncoding::EDistances))	
       
   130 	{
       
   131 		throw E32ImageCompressionError(HUFFMANINVALIDCODINGERROR);
       
   132 	}
       
   133 
       
   134 	// convert the length tables into huffman decoding trees
       
   135 	Huffman::Decoding(iEncoding->iLitLen,TEncoding::ELitLens,iEncoding->iLitLen);
       
   136 	Huffman::Decoding(iEncoding->iDistance,TEncoding::EDistances,iEncoding->iDistance,KDeflateDistCodeBase);
       
   137 }
       
   138 
       
   139 /*
       
   140 Consume all data lag in the history buffer, then decode to fill up the output buffer
       
   141 Return the number of available bytes in the output buffer. This is only ever less than the
       
   142 buffer size if the end of stream marker has been read.
       
   143 @internalComponent
       
   144 @released
       
   145 */
       
   146 TInt CInflater::InflateL()
       
   147 {
       
   148 	// empty the history buffer into the output
       
   149 	TUint8* out=iOut;
       
   150 	TUint8* const end=out+KDeflateMaxDistance;
       
   151 	const TUint32* tree=iEncoding->iLitLen;
       
   152 	if (iLen<0)	// EOF
       
   153 		return 0;
       
   154 	if (iLen>0)
       
   155 		goto useHistory;
       
   156 
       
   157 	while (out<end)
       
   158 	{
       
   159 		// get a huffman code
       
   160 		{
       
   161 			TInt val=iBits->HuffmanL(tree)-TEncoding::ELiterals;
       
   162 			if (val<0)
       
   163 			{
       
   164 				*out++=TUint8(val);
       
   165 				continue;			// another literal/length combo
       
   166 			}
       
   167 			if (val==TEncoding::EEos-TEncoding::ELiterals)
       
   168 			{	// eos marker. we're done
       
   169 				iLen=-1;
       
   170 				break;
       
   171 			}
       
   172 		
       
   173 			// get the extra bits for the code
       
   174 			TInt code=val&0xff;
       
   175 			if (code>=8)
       
   176 			{	// xtra bits
       
   177 				TInt xtra=(code>>2)-1;
       
   178 				code-=xtra<<2;
       
   179 				code<<=xtra;
       
   180 				code|=iBits->ReadL(xtra);
       
   181 			}
       
   182 			if (val<KDeflateDistCodeBase-TEncoding::ELiterals)
       
   183 			{	// length code... get the code
       
   184 				iLen=code+KDeflateMinLength;
       
   185 				tree=iEncoding->iDistance;
       
   186 				continue;			// read the huffman code
       
   187 			}
       
   188 			// distance code
       
   189 			iRptr=out-(code+1);
       
   190 			if (iRptr+KDeflateMaxDistance<end)
       
   191 			iRptr+=KDeflateMaxDistance;
       
   192 		}
       
   193 		useHistory:
       
   194 			TInt tfr;
       
   195 			if(iLen > (end-out))
       
   196 				tfr=end-out;
       
   197 			else
       
   198 				tfr=iLen;
       
   199 
       
   200 			iLen-=tfr;
       
   201 			const TUint8* from=iRptr;
       
   202 			do
       
   203 			{
       
   204 				*out++=*from++;
       
   205 				if (from==end)
       
   206 					from-=KDeflateMaxDistance;
       
   207 			}while (--tfr!=0);
       
   208 			iRptr=from;
       
   209 			tree=iEncoding->iLitLen;
       
   210 	};
       
   211 	
       
   212 	return out-iOut;
       
   213 }
       
   214 
       
   215 /*
       
   216 TFileInput Constructor
       
   217 @param source
       
   218 @param size
       
   219 @internalComponent
       
   220 @released
       
   221 */
       
   222 TFileInput::TFileInput(unsigned char* source,int size):iReadBuf(source),iSize(size)
       
   223 {
       
   224 	Set(source,iSize*8);
       
   225 }
       
   226 
       
   227 /*
       
   228 TFileInput Destructor
       
   229 @internalComponent
       
   230 @released
       
   231 */
       
   232 TFileInput::~TFileInput()
       
   233 {
       
   234 
       
   235 }
       
   236 
       
   237 /*
       
   238 Function UnderFlowL
       
   239 @Leave E32ImageCompressionError
       
   240 @internalComponent
       
   241 @released
       
   242 */
       
   243 void TFileInput::UnderflowL()
       
   244 {
       
   245 	throw E32ImageCompressionError(HUFFMANBUFFERUNDERFLOWERROR);
       
   246 }
       
   247 
       
   248 /*
       
   249 Function InflateUncompress
       
   250 @param source
       
   251 @param sourcesize
       
   252 @param dest
       
   253 @param destsize
       
   254 @internalComponent
       
   255 @released
       
   256 */
       
   257 void InflateUnCompress(unsigned char* source, int sourcesize,unsigned char* dest, int destsize)
       
   258 {
       
   259 	TFileInput* input = new TFileInput(source, sourcesize);
       
   260 	CInflater* inflater=CInflater::NewLC(*input);
       
   261 	inflater->ReadL(dest,destsize);
       
   262 	delete input;
       
   263 	delete inflater;
       
   264 }
       
   265