#ifndef __COMPRESSION_HUFFMANDECODER_H #define __COMPRESSION_HUFFMANDECODER_H namespace NCompression { namespace NHuffman { const UINT32 kValueTableBits = 8; template class CDecoder { UINT32 m_Limitits[kNumBitsInLongestCode + 1]; // m_Limitits[i] = value limit for symbols with length = i UINT32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i UINT32 m_NumSymbols; UINT32 *m_Symbols; // symbols: at first with len = 1 then 2, ... 15. BYTE m_Lengths[1 << kValueTableBits]; public: CDecoder(UINT32 aNumSymbols): m_NumSymbols(aNumSymbols) { m_Symbols = new UINT32[m_NumSymbols]; } ~CDecoder() { delete []m_Symbols; } void SetNumSymbols(UINT32 aNumSymbols) { m_NumSymbols = aNumSymbols; } void SetCodeLengths(const BYTE *aCodeLengths); template UINT32 DecodeSymbol(TBitDecoder *aStream) { UINT32 aNumBits; UINT32 aValue = aStream->GetValue(kNumBitsInLongestCode); if (aValue < m_Limitits[kValueTableBits]) aNumBits = m_Lengths[aValue >> (kNumBitsInLongestCode - kValueTableBits)]; else if (aValue < m_Limitits[10]) if (aValue < m_Limitits[9]) aNumBits = 9; else aNumBits = 10; else if (aValue < m_Limitits[11]) aNumBits = 11; else if (aValue < m_Limitits[12]) aNumBits = 12; else for (aNumBits = 13; aNumBits < kNumBitsInLongestCode; aNumBits++) if (aValue < m_Limitits[aNumBits]) break; aStream->MovePos(aNumBits); UINT32 anIndex = m_Positions[aNumBits] + ((aValue - m_Limitits[aNumBits - 1]) >> (kNumBitsInLongestCode - aNumBits)); if (anIndex >= m_NumSymbols) throw E_INTERNAL_ERROR; // test it return m_Symbols[anIndex]; } }; template void CDecoder::SetCodeLengths(const BYTE *aCodeLengths) { int aLenCounts[kNumBitsInLongestCode + 1], aTmpPositions[kNumBitsInLongestCode + 1]; int i; for(i = 1; i <= kNumBitsInLongestCode; i++) aLenCounts[i] = 0; UINT32 aSymbol; for (aSymbol = 0; aSymbol < m_NumSymbols; aSymbol++) { BYTE aCodeLength = aCodeLengths[aSymbol]; if (aCodeLength > kNumBitsInLongestCode) throw E_INTERNAL_ERROR; aLenCounts[aCodeLength]++; } aLenCounts[0] = 0; aTmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0; UINT32 aStartPos = 0; UINT32 anIndex = 0; const int kMaxValue = (1 << kNumBitsInLongestCode); for (i = 1; i <= kNumBitsInLongestCode; i++) { aStartPos += aLenCounts[i] << (kNumBitsInLongestCode - i); if (aStartPos > kMaxValue) throw E_INTERNAL_ERROR; m_Limitits[i] = aStartPos; m_Positions[i] = m_Positions[i - 1] + aLenCounts[i - 1]; aTmpPositions[i] = m_Positions[i]; if(i <= kValueTableBits) { UINT32 aLimit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it memset(m_Lengths + anIndex, BYTE(i), aLimit - anIndex); anIndex = aLimit; } } // if (aStartPos != kMaxValue) // throw E_INTERNAL_ERROR; for (aSymbol = 0; aSymbol < m_NumSymbols; aSymbol++) if (aCodeLengths[aSymbol] != 0) m_Symbols[aTmpPositions[aCodeLengths[aSymbol]]++] = aSymbol; } }} #endif