blob: 82a1e6f2d58bc0b1f9ef9b6275cebefd36132144 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// Compress/HuffmanDecoder.h
#ifndef __COMPRESS_HUFFMAN_DECODER_H
#define __COMPRESS_HUFFMAN_DECODER_H
#include "../../Common/Types.h"
namespace NCompress {
namespace NHuffman {
const int kNumTableBits = 9;
template <int kNumBitsMax, UInt32 m_NumSymbols>
class CDecoder
{
UInt32 m_Limits[kNumBitsMax + 1]; // m_Limits[i] = value limit for symbols with length = i
UInt32 m_Positions[kNumBitsMax + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UInt32 m_Symbols[m_NumSymbols];
Byte m_Lengths[1 << kNumTableBits]; // Table oh length for short codes.
public:
bool SetCodeLengths(const Byte *codeLengths)
{
int lenCounts[kNumBitsMax + 1];
UInt32 tmpPositions[kNumBitsMax + 1];
int i;
for(i = 1; i <= kNumBitsMax; i++)
lenCounts[i] = 0;
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
int len = codeLengths[symbol];
if (len > kNumBitsMax)
return false;
lenCounts[len]++;
m_Symbols[symbol] = 0xFFFFFFFF;
}
lenCounts[0] = 0;
m_Positions[0] = m_Limits[0] = 0;
UInt32 startPos = 0;
UInt32 index = 0;
const UInt32 kMaxValue = (1 << kNumBitsMax);
for (i = 1; i <= kNumBitsMax; i++)
{
startPos += lenCounts[i] << (kNumBitsMax - i);
if (startPos > kMaxValue)
return false;
m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos;
m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1];
tmpPositions[i] = m_Positions[i];
if(i <= kNumTableBits)
{
UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits));
for (; index < limit; index++)
m_Lengths[index] = (Byte)i;
}
}
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
int len = codeLengths[symbol];
if (len != 0)
m_Symbols[tmpPositions[len]++] = symbol;
}
return true;
}
template <class TBitDecoder>
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
int numBits;
UInt32 value = bitStream->GetValue(kNumBitsMax);
if (value < m_Limits[kNumTableBits])
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
else
for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
bitStream->MovePos(numBits);
UInt32 index = m_Positions[numBits] +
((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
if (index >= m_NumSymbols)
// throw CDecoderException(); // test it
return 0xFFFFFFFF;
return m_Symbols[index];
}
};
}}
#endif
|