diff -r c55016431358 -r 0a7b44b10206 symport/e32/euser/us_decode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32/euser/us_decode.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,399 @@ +// 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 the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\euser\us_decode.cpp +// +// + +#include +#include +#include +#include + +const TInt KHuffTerminate=0x0001; +const TUint32 KBranch1=sizeof(TUint32)<<16; +_LIT(KCat,"Huffman"); + +TUint32* HuffmanSubTree(TUint32* aPtr,const TUint32* aValue,TUint32** aLevel) +// +// write the subtree below aPtr and return the head +// + { + TUint32* l=*aLevel++; + if (l>aValue) + { + TUint32* sub0=HuffmanSubTree(aPtr,aValue,aLevel); // 0-tree first + aPtr=HuffmanSubTree(sub0,aValue-(aPtr-sub0)-1,aLevel); // 1-tree + TInt branch0=(TUint8*)sub0-(TUint8*)(aPtr-1); + *--aPtr=KBranch1|branch0; + } + else if (l==aValue) + { + TUint term0=*aValue--; // 0-term + aPtr=HuffmanSubTree(aPtr,aValue,aLevel); // 1-tree + *--aPtr=KBranch1|(term0>>16); + } + else // l>16<<16)|(term0>>16); + } + return aPtr; + } + +/** Create a canonical Huffman decoding tree + + This generates the huffman decoding tree used by TBitInput::HuffmanL() to read huffman + encoded data. The input is table of code lengths, as generated by Huffman::HuffmanL() + and must represent a valid huffman code. + + @param aHuffman The table of code lengths as generated by Huffman::HuffmanL() + @param aNumCodes The number of codes in the table + @param aDecodeTree The space for the decoding tree. This must be the same + size as the code-length table, and can safely be the same memory + @param aSymbolBase the base value for the output 'symbols' from the decoding tree, by default + this is zero. + + @panic "USER ???" If the provided code is not a valid Huffman coding + + @see IsValid() + @see HuffmanL() +*/ +EXPORT_C void Huffman::Decoding(const TUint32 aHuffman[],TInt aNumCodes,TUint32 aDecodeTree[],TInt aSymbolBase) + { + __ASSERT_ALWAYS(IsValid(aHuffman,aNumCodes),User::Panic(KCat,EHuffmanInvalidCoding)); +// + TFixedArray counts; + counts.Reset(); + TInt codes=0; + TInt ii; + for (ii=0;ii=0) + { + ++counts[len]; + ++codes; + } + } +// + TFixedArray level; + TUint32* lit=aDecodeTree+codes; + for (ii=0;ii>16; + aDecodeTree[0]=term|(term<<16); // 0- and 1-terminate at root + } + else if (codes>1) + HuffmanSubTree(aDecodeTree+codes-1,aDecodeTree+codes-1,&level[0]); + } + +// The decoding tree for the externalised code +const TUint32 HuffmanDecoding[]= + { + 0x0004006c, + 0x00040064, + 0x0004005c, + 0x00040050, + 0x00040044, + 0x0004003c, + 0x00040034, + 0x00040021, + 0x00040023, + 0x00040025, + 0x00040027, + 0x00040029, + 0x00040014, + 0x0004000c, + 0x00040035, + 0x00390037, + 0x00330031, + 0x0004002b, + 0x002f002d, + 0x001f001d, + 0x001b0019, + 0x00040013, + 0x00170015, + 0x0004000d, + 0x0011000f, + 0x000b0009, + 0x00070003, + 0x00050001 + }; + +/** Restore a canonical huffman encoding from a bit stream + + The encoding must have been stored using Huffman::ExternalizeL(). The resulting + code-length table can be used to create an encoding table using Huffman::Encoding() + or a decoding tree using Huffman::Decoding(). + + @param aInput The input stream with the encoding + @param aHuffman The internalized code-length table is placed here + @param aNumCodes The number of huffman codes in the table + + @leave TBitInput::HuffmanL() + + @see ExternalizeL() +*/ +EXPORT_C void Huffman::InternalizeL(TBitInput& aInput,TUint32 aHuffman[],TInt aNumCodes) +// See ExternalizeL for a description of the format + { + // initialise move-to-front list + TFixedArray list; + for (TInt i=0;i= TUint(end-p)) + User::Leave(KErrCorrupt); + while (rl>0) + { + *p++=last; + --rl; + } + --c; // c is now 1..27 + list[0]=TUint8(last); + last=list[c]; + Mem::Copy(&list[1],&list[0],c); + *p++=last; + } + } + + while (p>16); + v^=aVal; + v&=0xff00ffff; + aVal=(aVal>>8)|(aVal<<24); + return aVal^(v>>8); + } + +/** Construct a bit stream input object + + Following construction the bit stream is ready for reading bits, but will + immediately call UnderflowL() as the input buffer is empty. +*/ +EXPORT_C TBitInput::TBitInput() + :iCount(0),iRemain(0) + {} + +/** Construct a bit stream input object over a buffer + + Following construction the bit stream is ready for reading bits from + the specified buffer. + + @param aPtr The address of the buffer containing the bit stream + @param aLength The length of the bitstream in bits + @param aOffset The bit offset from the start of the buffer to the bit stream (defaults to zero) +*/ +EXPORT_C TBitInput::TBitInput(const TUint8* aPtr, TInt aLength, TInt aOffset) + { + Set(aPtr,aLength,aOffset); + } + +/** Set the memory buffer to use for input + + Bits will be read from this buffer until it is empty, at which point + UnderflowL() will be called. + + @param aPtr The address of the buffer containing the bit stream + @param aLength The length of the bitstream in bits + @param aOffset The bit offset from the start of the buffer to the bit stream (defaults to zero) +*/ +EXPORT_C void TBitInput::Set(const TUint8* aPtr, TInt aLength, TInt aOffset) + { + TUint p=(TUint)aPtr; + p+=aOffset>>3; // nearest byte to the specified bit offset + aOffset&=7; // bit offset within the byte + const TUint32* ptr=(const TUint32*)(p&~3); // word containing this byte + aOffset+=(p&3)<<3; // bit offset within the word + if (aLength==0) + iCount=0; + else + { + // read the first few bits of the stream + iBits=reverse(*ptr++)<>31; + } + +/** Read a multi-bit value from the input + + Return the next few bits as an unsigned integer. The last bit read is + the least significant bit of the returned value, and the value is + zero extended to return a 32-bit result. + + A read of zero bits will always reaturn zero. + + This will call UnderflowL() if there are not enough bits available. + + @param aSize The number of bits to read + + @return The bits read from the stream + + @leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called + to get more data +*/ +EXPORT_C TUint TBitInput::ReadL(TInt aSize) + { + if (!aSize) + return 0; + TUint val=0; + TUint bits=iBits; + iCount-=aSize; + while (iCount<0) + { + // need more bits +#ifdef __CPU_X86 + // X86 does not allow shift-by-32 + if (iCount+aSize!=0) + val|=bits>>(32-(iCount+aSize))<<(-iCount); // scrub low order bits +#else + val|=bits>>(32-(iCount+aSize))<<(-iCount); // scrub low order bits +#endif + aSize=-iCount; // bits still required + if (iRemain>0) + { + bits=reverse(*iPtr++); + iCount+=32; + iRemain-=32; + if (iRemain<0) + iCount+=iRemain; + } + else + { + UnderflowL(); + bits=iBits; + iCount-=aSize; + } + } +#ifdef __CPU_X86 + // X86 does not allow shift-by-32 + iBits=aSize==32?0:bits<>(32-aSize)); + } + +/** Read and decode a Huffman Code + + Interpret the next bits in the input as a Huffman code in the specified + decoding. The decoding tree should be the output from Huffman::Decoding(). + + @param aTree The huffman decoding tree + + @return The symbol that was decoded + + @leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called + to get more data +*/ +EXPORT_C TUint TBitInput::HuffmanL(const TUint32* aTree) + { + TUint huff=0; + do + { + aTree=PtrAdd(aTree,huff>>16); + huff=*aTree; + if (ReadL()==0) + huff<<=16; + } while ((huff&0x10000u)==0); + return huff>>17; + } + +#endif + +/** Handle an empty input buffer + + This virtual function is called when the input buffer is empty and + more bits are required. It should reset the input buffer with more + data using Set(). + + A derived class can replace this to read the data from a file + (for example) before reseting the input buffer. + + @leave KErrUnderflow The default implementation leaves +*/ +void TBitInput::UnderflowL() + { + User::Leave(KErrUnderflow); + }