sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32\sfile\sf_inflate.h sl@0: // sl@0: // sl@0: sl@0: #include "sf_deflate.h" sl@0: #include "sf_ldr.h" sl@0: sl@0: // Class RInflater sl@0: // sl@0: // The inflation algorithm, complete with huffman decoding sl@0: sl@0: inline CInflater::CInflater(TBitInput& aInput) sl@0: :iBits(&aInput),iEncoding(0),iOut(0) sl@0: {} sl@0: sl@0: void CInflater::ConstructL() sl@0: { sl@0: iEncoding=new(ELeave) TEncoding; sl@0: InitL(); sl@0: iLen=0; sl@0: iOut=new(ELeave) TUint8[KDeflateMaxDistance]; sl@0: iAvail=iLimit=iOut; sl@0: } sl@0: sl@0: CInflater* CInflater::NewLC(TBitInput& aInput) sl@0: { sl@0: CInflater* self=new(ELeave) CInflater(aInput); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: CInflater::~CInflater() sl@0: { sl@0: delete iEncoding; sl@0: delete [] iOut; sl@0: } sl@0: sl@0: TInt CInflater::ReadL(TUint8* aBuffer,TInt aLength, TMemoryMoveFunction aMemMovefn) sl@0: { sl@0: TInt tfr=0; sl@0: for (;;) sl@0: { sl@0: TInt len=Min(aLength,iLimit-iAvail); sl@0: if (len && aBuffer) sl@0: { sl@0: aMemMovefn(aBuffer,iAvail,len); sl@0: aBuffer+=len; sl@0: } sl@0: aLength-=len; sl@0: iAvail+=len; sl@0: tfr+=len; sl@0: if (aLength==0) sl@0: return tfr; sl@0: len=InflateL(); sl@0: if (len==0) sl@0: return tfr; sl@0: iAvail=iOut; sl@0: iLimit=iAvail+len; sl@0: } sl@0: } sl@0: sl@0: TInt CInflater::SkipL(TInt aLength) sl@0: { sl@0: return ReadL(0,aLength,Mem::Move); sl@0: } sl@0: sl@0: void CInflater::InitL() sl@0: { sl@0: // read the encoding sl@0: Huffman::InternalizeL(*iBits,iEncoding->iLitLen,KDeflationCodes); sl@0: // validate the encoding sl@0: if (!Huffman::IsValid(iEncoding->iLitLen,TEncoding::ELitLens) || sl@0: !Huffman::IsValid(iEncoding->iDistance,TEncoding::EDistances)) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: // convert the length tables into huffman decoding trees sl@0: Huffman::Decoding(iEncoding->iLitLen,TEncoding::ELitLens,iEncoding->iLitLen); sl@0: Huffman::Decoding(iEncoding->iDistance,TEncoding::EDistances,iEncoding->iDistance,KDeflateDistCodeBase); sl@0: } sl@0: sl@0: TInt CInflater::InflateL() sl@0: // sl@0: // consume all data lag in the history buffer, then decode to fill up the output buffer sl@0: // return the number of available bytes in the output buffer. This is only ever less than sl@0: // the buffer size if the end of stream marker has been read sl@0: // sl@0: { sl@0: // empty the history buffer into the output sl@0: TUint8* out=iOut; sl@0: TUint8* const end=out+KDeflateMaxDistance; sl@0: const TUint32* tree=iEncoding->iLitLen; sl@0: if (iLen<0) // EOF sl@0: return 0; sl@0: if (iLen>0) sl@0: goto useHistory; sl@0: // sl@0: while (outHuffmanL(tree)-TEncoding::ELiterals; sl@0: if (val<0) sl@0: { sl@0: *out++=TUint8(val); sl@0: continue; // another literal/length combo sl@0: } sl@0: if (val==TEncoding::EEos-TEncoding::ELiterals) sl@0: { // eos marker. we're done sl@0: iLen=-1; sl@0: break; sl@0: } sl@0: // get the extra bits for the code sl@0: TInt code=val&0xff; sl@0: if (code>=8) sl@0: { // xtra bits sl@0: TInt xtra=(code>>2)-1; sl@0: code-=xtra<<2; sl@0: code<<=xtra; sl@0: code|=iBits->ReadL(xtra); sl@0: } sl@0: if (valTUint(KDeflateMaxLength-KDeflateMinLength)) sl@0: { sl@0: CHECK_FAILURE(KErrCorrupt); sl@0: goto error; sl@0: } sl@0: iLen=code+KDeflateMinLength; sl@0: tree=iEncoding->iDistance; sl@0: continue; // read the huffman code sl@0: } sl@0: // distance code sl@0: if(TUint(code)>TUint(KDeflateMaxDistance-1)) sl@0: { sl@0: CHECK_FAILURE(KErrCorrupt); sl@0: goto error; sl@0: } sl@0: iRptr=out-(code+1); sl@0: if (iRptr+KDeflateMaxDistanceiLitLen; sl@0: } sl@0: sl@0: }; sl@0: return out-iOut; sl@0: sl@0: error: sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: return 0; sl@0: } sl@0: