os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_inflate.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\sfile\sf_inflate.h
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "sf_deflate.h"
sl@0
    19
#include "sf_ldr.h"
sl@0
    20
sl@0
    21
// Class RInflater
sl@0
    22
//
sl@0
    23
// The inflation algorithm, complete with huffman decoding
sl@0
    24
sl@0
    25
inline CInflater::CInflater(TBitInput& aInput)
sl@0
    26
	:iBits(&aInput),iEncoding(0),iOut(0)
sl@0
    27
	{}
sl@0
    28
sl@0
    29
void CInflater::ConstructL()
sl@0
    30
	{
sl@0
    31
	iEncoding=new(ELeave) TEncoding;
sl@0
    32
	InitL();
sl@0
    33
	iLen=0;
sl@0
    34
	iOut=new(ELeave) TUint8[KDeflateMaxDistance];
sl@0
    35
	iAvail=iLimit=iOut;
sl@0
    36
	}
sl@0
    37
sl@0
    38
CInflater* CInflater::NewLC(TBitInput& aInput)
sl@0
    39
	{
sl@0
    40
	CInflater* self=new(ELeave) CInflater(aInput);
sl@0
    41
	CleanupStack::PushL(self);
sl@0
    42
	self->ConstructL();
sl@0
    43
	return self;
sl@0
    44
	}
sl@0
    45
sl@0
    46
CInflater::~CInflater()
sl@0
    47
	{
sl@0
    48
	delete iEncoding;
sl@0
    49
	delete [] iOut;
sl@0
    50
	}
sl@0
    51
sl@0
    52
TInt CInflater::ReadL(TUint8* aBuffer,TInt aLength, TMemoryMoveFunction aMemMovefn)
sl@0
    53
	{
sl@0
    54
	TInt tfr=0;
sl@0
    55
	for (;;)
sl@0
    56
		{
sl@0
    57
		TInt len=Min(aLength,iLimit-iAvail);
sl@0
    58
		if (len && aBuffer)
sl@0
    59
			{
sl@0
    60
			aMemMovefn(aBuffer,iAvail,len);
sl@0
    61
			aBuffer+=len;
sl@0
    62
			}
sl@0
    63
		aLength-=len;
sl@0
    64
		iAvail+=len;
sl@0
    65
		tfr+=len;
sl@0
    66
		if (aLength==0)
sl@0
    67
			return tfr;
sl@0
    68
		len=InflateL();
sl@0
    69
		if (len==0)
sl@0
    70
			return tfr;
sl@0
    71
		iAvail=iOut;
sl@0
    72
		iLimit=iAvail+len;
sl@0
    73
		}
sl@0
    74
	}
sl@0
    75
sl@0
    76
TInt CInflater::SkipL(TInt aLength)
sl@0
    77
	{
sl@0
    78
	return ReadL(0,aLength,Mem::Move);
sl@0
    79
	}
sl@0
    80
sl@0
    81
void CInflater::InitL()
sl@0
    82
	{
sl@0
    83
// read the encoding
sl@0
    84
	Huffman::InternalizeL(*iBits,iEncoding->iLitLen,KDeflationCodes);
sl@0
    85
// validate the encoding
sl@0
    86
	if (!Huffman::IsValid(iEncoding->iLitLen,TEncoding::ELitLens) ||
sl@0
    87
		!Huffman::IsValid(iEncoding->iDistance,TEncoding::EDistances))
sl@0
    88
		LEAVE_FAILURE(KErrCorrupt);
sl@0
    89
// convert the length tables into huffman decoding trees
sl@0
    90
	Huffman::Decoding(iEncoding->iLitLen,TEncoding::ELitLens,iEncoding->iLitLen);
sl@0
    91
	Huffman::Decoding(iEncoding->iDistance,TEncoding::EDistances,iEncoding->iDistance,KDeflateDistCodeBase);
sl@0
    92
	}
sl@0
    93
sl@0
    94
TInt CInflater::InflateL()
sl@0
    95
//
sl@0
    96
// consume all data lag in the history buffer, then decode to fill up the output buffer
sl@0
    97
// return the number of available bytes in the output buffer. This is only ever less than
sl@0
    98
// the buffer size if the end of stream marker has been read
sl@0
    99
//
sl@0
   100
	{
sl@0
   101
// empty the history buffer into the output
sl@0
   102
	TUint8* out=iOut;
sl@0
   103
	TUint8* const end=out+KDeflateMaxDistance;
sl@0
   104
	const TUint32* tree=iEncoding->iLitLen;
sl@0
   105
	if (iLen<0)	// EOF
sl@0
   106
		return 0;
sl@0
   107
	if (iLen>0)
sl@0
   108
		goto useHistory;
sl@0
   109
//
sl@0
   110
	while (out<end)
sl@0
   111
		{
sl@0
   112
		// get a huffman code
sl@0
   113
		{
sl@0
   114
		TInt val=iBits->HuffmanL(tree)-TEncoding::ELiterals;
sl@0
   115
		if (val<0)
sl@0
   116
			{
sl@0
   117
			*out++=TUint8(val);
sl@0
   118
			continue;			// another literal/length combo
sl@0
   119
			}
sl@0
   120
		if (val==TEncoding::EEos-TEncoding::ELiterals)
sl@0
   121
			{	// eos marker. we're done
sl@0
   122
			iLen=-1;
sl@0
   123
			break;
sl@0
   124
			}
sl@0
   125
		// get the extra bits for the code
sl@0
   126
		TInt code=val&0xff;
sl@0
   127
		if (code>=8)
sl@0
   128
			{	// xtra bits
sl@0
   129
			TInt xtra=(code>>2)-1;
sl@0
   130
			code-=xtra<<2;
sl@0
   131
			code<<=xtra;
sl@0
   132
			code|=iBits->ReadL(xtra);
sl@0
   133
			}
sl@0
   134
		if (val<KDeflateDistCodeBase-TEncoding::ELiterals)
sl@0
   135
			{
sl@0
   136
			// length code... get the code
sl@0
   137
			if(TUint(code)>TUint(KDeflateMaxLength-KDeflateMinLength))
sl@0
   138
				{
sl@0
   139
				CHECK_FAILURE(KErrCorrupt);
sl@0
   140
				goto error;
sl@0
   141
				}
sl@0
   142
			iLen=code+KDeflateMinLength;
sl@0
   143
			tree=iEncoding->iDistance;
sl@0
   144
			continue;			// read the huffman code
sl@0
   145
			}
sl@0
   146
		// distance code
sl@0
   147
		if(TUint(code)>TUint(KDeflateMaxDistance-1))
sl@0
   148
			{
sl@0
   149
			CHECK_FAILURE(KErrCorrupt);
sl@0
   150
			goto error;
sl@0
   151
			}
sl@0
   152
		iRptr=out-(code+1);
sl@0
   153
		if (iRptr+KDeflateMaxDistance<end)
sl@0
   154
			iRptr+=KDeflateMaxDistance;
sl@0
   155
		if(!iLen)
sl@0
   156
			{
sl@0
   157
			CHECK_FAILURE(KErrCorrupt);
sl@0
   158
			goto error;
sl@0
   159
			}
sl@0
   160
		}
sl@0
   161
useHistory:
sl@0
   162
		{
sl@0
   163
		TInt tfr=Min(end-out,iLen);
sl@0
   164
		iLen-=tfr;
sl@0
   165
		const TUint8* from=iRptr;
sl@0
   166
		do
sl@0
   167
			{
sl@0
   168
			*out++=*from++;
sl@0
   169
			if (from==end)
sl@0
   170
				from-=KDeflateMaxDistance;
sl@0
   171
			} while (--tfr!=0);
sl@0
   172
		iRptr=from;
sl@0
   173
		tree=iEncoding->iLitLen;
sl@0
   174
		}
sl@0
   175
sl@0
   176
		};
sl@0
   177
	return out-iOut;
sl@0
   178
sl@0
   179
error:
sl@0
   180
	LEAVE_FAILURE(KErrCorrupt);
sl@0
   181
	return 0;
sl@0
   182
	}
sl@0
   183