mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 18:11:37 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
@@ -1,60 +1,42 @@
|
||||
// Compress/HuffmanDecoder.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __COMPRESS_HUFFMANDECODER_H
|
||||
#define __COMPRESS_HUFFMANDECODER_H
|
||||
|
||||
#include "../../../Common/Types.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NHuffman {
|
||||
|
||||
class CDecoderException{};
|
||||
|
||||
const UINT32 kValueTableBits = 8;
|
||||
const UInt32 kValueTableBits = 9;
|
||||
|
||||
template <int kNumBitsInLongestCode>
|
||||
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
|
||||
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];
|
||||
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_Symbols[m_NumSymbols]; // symbols: at first with len = 1 then 2, ... 15.
|
||||
Byte m_Lengths[1 << kValueTableBits];
|
||||
public:
|
||||
CDecoder(UINT32 numSymbols):
|
||||
m_NumSymbols(numSymbols)
|
||||
{ m_Symbols = new UINT32[m_NumSymbols]; }
|
||||
|
||||
~CDecoder()
|
||||
{ delete []m_Symbols; }
|
||||
|
||||
void SetNumSymbols(UINT32 numSymbols)
|
||||
{ m_NumSymbols = numSymbols; }
|
||||
void SetCodeLengths(const BYTE *codeLengths);
|
||||
void SetNumSymbols(UInt32 numSymbols) { m_NumSymbols = numSymbols; }
|
||||
void SetCodeLengths(const Byte *codeLengths);
|
||||
template <class TBitDecoder>
|
||||
UINT32 DecodeSymbol(TBitDecoder *bitStream)
|
||||
UInt32 DecodeSymbol(TBitDecoder *bitStream)
|
||||
{
|
||||
UINT32 numBits;
|
||||
UInt32 numBits;
|
||||
|
||||
UINT32 value = bitStream->GetValue(kNumBitsInLongestCode);
|
||||
UInt32 value = bitStream->GetValue(kNumBitsInLongestCode);
|
||||
|
||||
if (value < m_Limitits[kValueTableBits])
|
||||
numBits = m_Lengths[value >> (kNumBitsInLongestCode - kValueTableBits)];
|
||||
else if (value < m_Limitits[10])
|
||||
if (value < m_Limitits[9])
|
||||
numBits = 9;
|
||||
else
|
||||
numBits = 10;
|
||||
else if (value < m_Limitits[11])
|
||||
numBits = 11;
|
||||
else if (value < m_Limitits[12])
|
||||
numBits = 12;
|
||||
else
|
||||
for (numBits = 13; numBits < kNumBitsInLongestCode; numBits++)
|
||||
for (numBits = kValueTableBits + 1; numBits < kNumBitsInLongestCode; numBits++)
|
||||
if (value < m_Limitits[numBits])
|
||||
break;
|
||||
bitStream->MovePos(numBits);
|
||||
UINT32 index = m_Positions[numBits] +
|
||||
UInt32 index = m_Positions[numBits] +
|
||||
((value - m_Limitits[numBits - 1]) >> (kNumBitsInLongestCode - numBits));
|
||||
if (index >= m_NumSymbols)
|
||||
throw CDecoderException(); // test it
|
||||
@@ -62,27 +44,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <int kNumBitsInLongestCode>
|
||||
void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
|
||||
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
|
||||
void CDecoder<kNumBitsInLongestCode, m_NumSymbols>::SetCodeLengths(const Byte *codeLengths)
|
||||
{
|
||||
int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
|
||||
int i;
|
||||
for(i = 1; i <= kNumBitsInLongestCode; i++)
|
||||
lenCounts[i] = 0;
|
||||
UINT32 symbol;
|
||||
UInt32 symbol;
|
||||
for (symbol = 0; symbol < m_NumSymbols; symbol++)
|
||||
{
|
||||
BYTE codeLength = codeLengths[symbol];
|
||||
Byte codeLength = codeLengths[symbol];
|
||||
if (codeLength > kNumBitsInLongestCode)
|
||||
throw CDecoderException();
|
||||
lenCounts[codeLength]++;
|
||||
}
|
||||
lenCounts[0] = 0;
|
||||
tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;
|
||||
UINT32 startPos = 0;
|
||||
UINT32 index = 0;
|
||||
const UINT32 kMaxValue = (1 << kNumBitsInLongestCode);
|
||||
UInt32 startPos = 0;
|
||||
UInt32 index = 0;
|
||||
const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);
|
||||
for (i = 1; i <= kNumBitsInLongestCode; i++)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsInLongestCode - i);
|
||||
@@ -94,8 +75,8 @@ void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
|
||||
|
||||
if(i <= kValueTableBits)
|
||||
{
|
||||
UINT32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
|
||||
memset(m_Lengths + index, BYTE(i), limit - index);
|
||||
UInt32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
|
||||
memset(m_Lengths + index, Byte(i), limit - index);
|
||||
index = limit;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user