diff -r 3141a18cb091 -r 863e2b34c16d e32tools/e32lib/e32image/deflate/deflate.cpp --- a/e32tools/e32lib/e32image/deflate/deflate.cpp Thu Nov 04 09:25:46 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ -// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of "Eclipse Public License v1.0" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// e32tools\petran\Szip\deflate.cpp -// -// - -#include "deflate.h" -#include "h_utl.h" -#include "panic.h" - -class HDeflateHash - { -public: - inline static HDeflateHash* NewLC(TInt aLinks); -// - inline TInt First(const TUint8* aPtr,TInt aPos); - inline TInt Next(TInt aPos,TInt aOffset) const; -private: - inline HDeflateHash(); - inline static TInt Hash(const TUint8* aPtr); -private: - typedef TUint16 TOffset; -private: - TInt iHash[256]; - TOffset iOffset[1]; // or more - }; - -class MDeflater - { -public: - void DeflateL(const TUint8* aBase,TInt aLength); - inline virtual ~MDeflater() { }; -private: - const TUint8* DoDeflateL(const TUint8* aBase,const TUint8* aEnd,HDeflateHash& aHash); - static TInt Match(const TUint8* aPtr,const TUint8* aEnd,TInt aPos,HDeflateHash& aHas); - void SegmentL(TInt aLength,TInt aDistance); - virtual void LitLenL(TInt aCode) =0; - virtual void OffsetL(TInt aCode) =0; - virtual void ExtraL(TInt aLen,TUint aBits) =0; - }; - -class TDeflateStats : public MDeflater - { -public: - inline TDeflateStats(TEncoding& aEncoding); - inline virtual ~TDeflateStats() { } -private: -// from MDeflater - void LitLenL(TInt aCode); - void OffsetL(TInt aCode); - void ExtraL(TInt aLen,TUint aBits); -private: - TEncoding& iEncoding; - }; - -class TDeflater : public MDeflater - { -public: - inline TDeflater(TBitOutput& aOutput,const TEncoding& aEncoding); - inline virtual ~TDeflater() { }; -private: -// from MDeflater - void LitLenL(TInt aCode); - void OffsetL(TInt aCode); - void ExtraL(TInt aLen,TUint aBits); -private: - TBitOutput& iOutput; - const TEncoding& iEncoding; - }; - - -// Class HDeflateHash - -inline HDeflateHash::HDeflateHash() - {TInt* p=iHash+256;do *--p=-KDeflateMaxDistance-1; while (p>iHash);} - -inline HDeflateHash* HDeflateHash::NewLC(TInt aLinks) - { - return new(HMem::Alloc(0,_FOFF(HDeflateHash,iOffset[0]) + (sizeof(TOffset) * Min(aLinks,KDeflateMaxDistance)))) HDeflateHash; - } - -inline TInt HDeflateHash::Hash(const TUint8* aPtr) - { - TUint x=aPtr[0]|(aPtr[1]<<8)|(aPtr[2]<<16); - return (x*KDeflateHashMultiplier)>>KDeflateHashShift; - } - -inline TInt HDeflateHash::First(const TUint8* aPtr,TInt aPos) - { - TInt h=Hash(aPtr); - TInt offset=Min(aPos-iHash[h],KDeflateMaxDistance<<1); - iHash[h]=aPos; - iOffset[aPos&(KDeflateMaxDistance-1)]=TOffset(offset); - return offset; - } - -inline TInt HDeflateHash::Next(TInt aPos,TInt aOffset) const - {return aOffset+iOffset[(aPos-aOffset)&(KDeflateMaxDistance-1)];} - - -// Class TDeflater -// -// generic deflation algorithm, can do either statistics and the encoder - -TInt MDeflater::Match(const TUint8* aPtr,const TUint8* aEnd,TInt aPos,HDeflateHash& aHash) - { - TInt offset=aHash.First(aPtr,aPos); - if (offset>KDeflateMaxDistance) - return 0; - TInt match=0; - aEnd=Min(aEnd,aPtr+KDeflateMaxLength); - TUint8 c=*aPtr; - do - { - const TUint8* p=aPtr-offset; - if (p[match>>16]==c) - { // might be a better match - const TUint8* m=aPtr; - for (;;) - { - if (*p++!=*m++) - break; - if (mmatch>>16) - { - match=(l<<16)|offset; - c=m[-1]; - } - } - offset=aHash.Next(aPos,offset); - } while (offset<=KDeflateMaxDistance); - return match; - } - -const TUint8* MDeflater::DoDeflateL(const TUint8* aBase,const TUint8* aEnd,HDeflateHash& aHash) -// -// Apply the deflation algorithm to the data [aBase,aEnd) -// Return a pointer after the last byte that was deflated (which may not be aEnd) -// - { - const TUint8* ptr=aBase; - TInt prev=0; // the previous deflation match - do - { - TInt match=Match(ptr,aEnd,ptr-aBase,aHash); -// Extra deflation applies two optimisations which double the time taken -// 1. If we have a match at p, then test for a better match at p+1 before using it -// 2. When we have a match, add the hash links for all the data which will be skipped - if (match>>16 < prev>>16) - { // use the previous match--it was better - TInt len=prev>>16; - SegmentL(len,prev-(len<<16)); - // fill in missing hash entries for better compression - const TUint8* e=ptr+len-2; - do - { - ++ptr; - if (ptr + 2 < aEnd) - aHash.First(ptr,ptr-aBase); - } while (ptr>16; - SegmentL(len,prev-(len<<16)); - ptr+=len-1; - } - return ptr; - } - -void MDeflater::DeflateL(const TUint8* aBase,TInt aLength) -// -// The generic deflation algorithm -// - { - const TUint8* end=aBase+aLength; - if (aLength>KDeflateMinLength) - { // deflation kicks in if there is enough data - HDeflateHash* hash=HDeflateHash::NewLC(aLength); - if(hash==NULL) - Panic(EHuffmanOutOfMemory); - - aBase=DoDeflateL(aBase,end,*hash); - delete hash; - } - while (aBase=8) - { - ++extralen; - len>>=1; - } - LitLenL((extralen<<2)+len+TEncoding::ELiterals); - if (extralen) - ExtraL(extralen,aLength); -// - aDistance--; - extralen=0; - TUint dist=aDistance; - while (dist>=8) - { - ++extralen; - dist>>=1; - } - OffsetL((extralen<<2)+dist); - if (extralen) - ExtraL(extralen,aDistance); - } - -// Class TDeflateStats -// -// This class analyses the data stream to generate the frequency tables -// for the deflation algorithm - -inline TDeflateStats::TDeflateStats(TEncoding& aEncoding) - :iEncoding(aEncoding) - {} - -void TDeflateStats::LitLenL(TInt aCode) - { - ++iEncoding.iLitLen[aCode]; - } - -void TDeflateStats::OffsetL(TInt aCode) - { - ++iEncoding.iDistance[aCode]; - } - -void TDeflateStats::ExtraL(TInt,TUint) - {} - -// Class TDeflater -// -// Extends MDeflater to provide huffman encoding of the output - -inline TDeflater::TDeflater(TBitOutput& aOutput,const TEncoding& aEncoding) -// -// construct for encoding -// - :iOutput(aOutput),iEncoding(aEncoding) - {} - -void TDeflater::LitLenL(TInt aCode) - { - iOutput.HuffmanL(iEncoding.iLitLen[aCode]); - } - -void TDeflater::OffsetL(TInt aCode) - { - iOutput.HuffmanL(iEncoding.iDistance[aCode]); - } - -void TDeflater::ExtraL(TInt aLen,TUint aBits) - { - iOutput.WriteL(aBits,aLen); - } - -void DoDeflateL(const TUint8* aBuf,TInt aLength,TBitOutput& aOutput,TEncoding& aEncoding) - { -// analyse the data for symbol frequency - TDeflateStats analyser(aEncoding); - analyser.DeflateL(aBuf,aLength); - -// generate the required huffman encodings - Huffman::HuffmanL(aEncoding.iLitLen,TEncoding::ELitLens,aEncoding.iLitLen); - Huffman::HuffmanL(aEncoding.iDistance,TEncoding::EDistances,aEncoding.iDistance); - -// Store the encoding table - Huffman::ExternalizeL(aOutput,aEncoding.iLitLen,KDeflationCodes); - -// generate the tables - Huffman::Encoding(aEncoding.iLitLen,TEncoding::ELitLens,aEncoding.iLitLen); - Huffman::Encoding(aEncoding.iDistance,TEncoding::EDistances,aEncoding.iDistance); - -// now finally deflate the data with the generated encoding - TDeflater deflater(aOutput,aEncoding); - deflater.DeflateL(aBuf,aLength); - aOutput.PadL(1); - } - -void DeflateL(const TUint8* aBuf, TInt aLength, TBitOutput& aOutput) - { - TEncoding* encoding=new TEncoding; - HMem::FillZ(encoding,sizeof(TEncoding)); - DoDeflateL(aBuf,aLength,aOutput,*encoding); - } -