diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/elf2e32/source/byte_pair.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/elf2e32/source/byte_pair.cpp Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,488 @@ +// Copyright (c) 2005-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: +// + +#include "byte_pair.h" + + +#undef ASSERT +#define ASSERT(c) if(!(c)) \ + { \ + __BREAKPOINT() \ + } + +const TInt MaxBlockSize = 0x1000; + +TUint16 PairCount[0x10000]; +TUint16 PairBuffer[MaxBlockSize*2]; + +TUint16 GlobalPairs[0x10000] = {0}; +TUint16 GlobalTokenCounts[0x100] = {0}; + +TUint16 ByteCount[0x100+4]; + +void CountBytes(TUint8* data, TInt size) + { + memset(ByteCount,0,sizeof(ByteCount)); + TUint8* dataEnd = data+size; + while(databestCount) + { + bestCount = f; + bestPair = p; + bestTieBreak = TieBreak(p&0xff,p>>8); + } + else if(f==bestCount) + { + TInt tieBreak = TieBreak(p&0xff,p>>8); + if(tieBreak>bestTieBreak) + { + bestCount = f; + bestPair = p; + bestTieBreak = tieBreak; + } + } + } + pair = bestPair; + return bestCount; + } + + +TInt LeastCommonByte(TInt& byte) + { + TInt bestCount = 0xffff; + TInt bestByte = -1; + for(TInt b=0; b<0x100; b++) + { + TInt f = ByteCount[b]; + if(f0; --r) + { + TInt byte; + TInt byteCount = LeastCommonByte(byte); + TInt pair; + TInt pairCount = MostCommonPair(pair,in,size,overhead+1,marker); + TInt saving = pairCount-byteCount; + if(saving<=overhead) + break; + + overhead = 3; + if(tokenCount>=32) + overhead = 2; + + TUint8* d=tokens+3*tokenCount; + ++tokenCount; + *d++ = (TUint8)byte; + ByteUsed(byte); + *d++ = (TUint8)pair; + ByteUsed(pair&0xff); + *d++ = (TUint8)(pair>>8); + ByteUsed(pair>>8); + ++GlobalPairs[pair]; + + inEnd = in+size; + outStart = out; + while(in>8)) + { + ++in; + b = byte; + --pairCount; + } + *out++ = (TUint8)b; + } + ASSERT(!byteCount); + ASSERT(!pairCount); + size = out-outStart; + + outToggle ^= 1; + if(outToggle) + { + in = dst; + out = dst2; + } + else + { + in = dst2; + out = dst; + } + } + + // sort tokens with a bubble sort... + for(TInt x=0; xtokens[y*3]) + { + TInt z = tokens[x*3]; + tokens[x*3] = tokens[y*3]; + tokens[y*3] = (TUint8)z; + z = tokens[x*3+1]; + tokens[x*3+1] = tokens[y*3+1]; + tokens[y*3+1] = (TUint8)z; + z = tokens[x*3+2]; + tokens[x*3+2] = tokens[y*3+2]; + tokens[y*3+2] = (TUint8)z; + } + + // check for not being able to compress... + if(size>originalSize) + { + *dst++ = 0; // store zero token count + memcpy(dst,src,originalSize); // store original data + return originalSize+1; + } + + // make sure data is in second buffer (dst2) + if(in!=dst2) + memcpy(dst2,dst,size); + + // store tokens... + TUint8* originalDst = dst; + *dst++ = (TUint8)tokenCount; + if(tokenCount) + { + *dst++ = (TUint8)marker; + if(tokenCount<32) + { + memcpy(dst,tokens,tokenCount*3); + dst += tokenCount*3; + } + else + { + TUint8* bitMask = dst; + memset(bitMask,0,32); + dst += 32; + TUint8* d=tokens; + do + { + TInt t=*d++; + bitMask[t>>3] |= (1<<(t&7)); + *dst++ = *d++; + *dst++ = *d++; + } + while(--tokenCount); + } + } + // store data... + memcpy(dst,dst2,size); + dst += size; + + // get stats... + ++GlobalTokenCounts[tokenCount]; + + // return total size of compressed data... + return dst-originalDst; + } + + +TInt Unpak(TUint8* dst, TInt dstSize, TUint8* src, TInt srcSize, TUint8*& srcNext) + { + TUint8* dstStart = dst; + TUint8* dstEnd = dst+dstSize; + TUint8* srcEnd = src+srcSize; + + TUint32 LUT[0x100/2]; + TUint8* LUT0 = (TUint8*)LUT; + TUint8* LUT1 = LUT0+0x100; + + TUint8 stack[0x100]; + TUint8* stackStart = stack+sizeof(stack); + TUint8* sp = stackStart; + + TUint32 marker = ~0u; + TInt numTokens; + TUint32 p1; + TUint32 p2; + + TUint32* l = (TUint32*)LUT; + TUint32 b = 0x03020100; + TUint32 step = 0x04040404; + do + { + *l++ = b; + b += step; + } + while(b>step); + + if(src>=srcEnd) + goto error; + numTokens = *src++; + if(numTokens) + { + if(src>=srcEnd) + goto error; + marker = *src++; + LUT0[marker] = (TUint8)~marker; + + if(numTokens<32) + { + TUint8* tokenEnd = src+3*numTokens; + if(tokenEnd>srcEnd) + goto error; + do + { + TInt b = *src++; + TInt p1 = *src++; + TInt p2 = *src++; + LUT0[b] = (TUint8)p1; + LUT1[b] = (TUint8)p2; + } + while(srcsrcEnd) + goto error; + TInt b=0; + do + { + TUint8 mask = bitMask[b>>3]; + if(mask&(1<<(b&7))) + { + if(src>srcEnd) + goto error; + TInt p1 = *src++; + if(src>srcEnd) + goto error; + TInt p2 = *src++; + LUT0[b] = (TUint8)p1; + LUT1[b] = (TUint8)p2; + --numTokens; + } + ++b; + } + while(b<0x100); + if(numTokens) + goto error; + } + } + + if(src>=srcEnd) + goto error; + b = *src++; + if(dst>=dstEnd) + goto error; + p1 = LUT0[b]; + if(p1!=b) + goto not_single; +next: + if(src>=srcEnd) + goto done_s; + b = *src++; + *dst++ = (TUint8)p1; + if(dst>=dstEnd) + goto done_d; + p1 = LUT0[b]; + if(p1==b) + goto next; + +not_single: + if(b==marker) + goto do_marker; + +do_pair: + p2 = LUT1[b]; + b = p1; + p1 = LUT0[b]; + if(sp<=stack) + goto error; + *--sp = (TUint8)p2; + +recurse: + if(b!=p1) + goto do_pair; + + if(sp==stackStart) + goto next; + b = *sp++; + if(dst>=dstEnd) + goto error; + *dst++ = (TUint8)p1; + p1 = LUT0[b]; + goto recurse; + +do_marker: + if(src>=srcEnd) + goto error; + p1 = *src++; + goto next; + +error: + srcNext = 0; + return KErrCorrupt; + +done_s: + *dst++ = (TUint8)p1; + srcNext = src; + return dst-dstStart; + +done_d: + if(dst>=dstEnd) + --src; + srcNext = src; + return dst-dstStart; + } + + +TUint8 PakBuffer[MaxBlockSize*4]; +TUint8 UnpakBuffer[MaxBlockSize]; + + +TInt BytePairCompress(TUint8* dst, TUint8* src, TInt size) + { + ASSERT(size<=MaxBlockSize); + TInt compressedSize = Pak(PakBuffer,src,size); + TUint8* pakEnd; + TInt us = Unpak(UnpakBuffer,MaxBlockSize,PakBuffer,compressedSize,pakEnd); + ASSERT(us==size) + ASSERT(pakEnd==PakBuffer+compressedSize) + ASSERT(!memcmp(src,UnpakBuffer,size)) + if(compressedSize>=size) + return KErrTooBig; + memcpy(dst,PakBuffer,compressedSize); + return compressedSize; + }