mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-11 02:07:09 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
216
CPP/7zip/Compress/Lzh/LzhDecoder.cpp
Executable file
216
CPP/7zip/Compress/Lzh/LzhDecoder.cpp
Executable file
@@ -0,0 +1,216 @@
|
||||
// LzhDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LzhDecoder.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NCompress{
|
||||
namespace NLzh {
|
||||
namespace NDecoder {
|
||||
|
||||
static const UInt32 kHistorySize = (1 << 16);
|
||||
|
||||
static const int kBlockSizeBits = 16;
|
||||
static const int kNumCBits = 9;
|
||||
static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/
|
||||
|
||||
UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
|
||||
|
||||
HRESULT CCoder::ReadLevelTable()
|
||||
{
|
||||
int n = ReadBits(kNumLevelBits);
|
||||
if (n == 0)
|
||||
{
|
||||
m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);
|
||||
if (m_LevelHuffman.Symbol >= kNumLevelSymbols)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n > kNumLevelSymbols)
|
||||
return S_FALSE;
|
||||
m_LevelHuffman.Symbol = -1;
|
||||
Byte lens[kNumLevelSymbols];
|
||||
int i = 0;
|
||||
while (i < n)
|
||||
{
|
||||
int c = m_InBitStream.ReadBits(3);
|
||||
if (c == 7)
|
||||
while (ReadBits(1))
|
||||
if (c++ > kMaxHuffmanLen)
|
||||
return S_FALSE;
|
||||
lens[i++] = (Byte)c;
|
||||
if (i == kNumSpecLevelSymbols)
|
||||
{
|
||||
c = ReadBits(2);
|
||||
while (--c >= 0)
|
||||
lens[i++] = 0;
|
||||
}
|
||||
}
|
||||
while (i < kNumLevelSymbols)
|
||||
lens[i++] = 0;
|
||||
m_LevelHuffman.SetCodeLengths(lens);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCoder::ReadPTable(int numBits)
|
||||
{
|
||||
int n = ReadBits(numBits);
|
||||
if (n == 0)
|
||||
{
|
||||
m_PHuffmanDecoder.Symbol = ReadBits(numBits);
|
||||
if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n > kNumDistanceSymbols)
|
||||
return S_FALSE;
|
||||
m_PHuffmanDecoder.Symbol = -1;
|
||||
Byte lens[kNumDistanceSymbols];
|
||||
int i = 0;
|
||||
while (i < n)
|
||||
{
|
||||
int c = m_InBitStream.ReadBits(3);
|
||||
if (c == 7)
|
||||
while (ReadBits(1))
|
||||
{
|
||||
if (c > kMaxHuffmanLen)
|
||||
return S_FALSE;
|
||||
c++;
|
||||
}
|
||||
lens[i++] = (Byte)c;
|
||||
}
|
||||
while (i < kNumDistanceSymbols)
|
||||
lens[i++] = 0;
|
||||
m_PHuffmanDecoder.SetCodeLengths(lens);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCoder::ReadCTable()
|
||||
{
|
||||
int n = ReadBits(kNumCBits);
|
||||
if (n == 0)
|
||||
{
|
||||
m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);
|
||||
if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n > kNumCSymbols)
|
||||
return S_FALSE;
|
||||
m_CHuffmanDecoder.Symbol = -1;
|
||||
Byte lens[kNumCSymbols];
|
||||
int i = 0;
|
||||
while (i < n)
|
||||
{
|
||||
int c = m_LevelHuffman.Decode(&m_InBitStream);
|
||||
if (c < kNumSpecLevelSymbols)
|
||||
{
|
||||
if (c == 0)
|
||||
c = 1;
|
||||
else if (c == 1)
|
||||
c = ReadBits(4) + 3;
|
||||
else
|
||||
c = ReadBits(kNumCBits) + 20;
|
||||
while (--c >= 0)
|
||||
{
|
||||
if (i > kNumCSymbols)
|
||||
return S_FALSE;
|
||||
lens[i++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
lens[i++] = (Byte)(c - 2);
|
||||
}
|
||||
while (i < kNumCSymbols)
|
||||
lens[i++] = 0;
|
||||
m_CHuffmanDecoder.SetCodeLengths(lens);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!m_OutWindowStream.Create(kHistorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
UInt64 pos = 0;
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
m_OutWindowStream.Init(false);
|
||||
m_InBitStream.SetStream(inStream);
|
||||
m_InBitStream.Init();
|
||||
|
||||
CCoderReleaser coderReleaser(this);
|
||||
|
||||
int pbit;
|
||||
if (m_NumDictBits <= 13)
|
||||
pbit = 4;
|
||||
else
|
||||
pbit = 5;
|
||||
|
||||
UInt32 blockSize = 0;
|
||||
|
||||
while(pos < *outSize)
|
||||
{
|
||||
// for (i = 0; i < dictSize; i++) dtext[i] = 0x20;
|
||||
|
||||
if (blockSize == 0)
|
||||
{
|
||||
if (progress != NULL)
|
||||
{
|
||||
UInt64 packSize = m_InBitStream.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos));
|
||||
}
|
||||
blockSize = ReadBits(kBlockSizeBits);
|
||||
ReadLevelTable();
|
||||
ReadCTable();
|
||||
RINOK(ReadPTable(pbit));
|
||||
}
|
||||
blockSize--;
|
||||
UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);
|
||||
if (c < 256)
|
||||
{
|
||||
m_OutWindowStream.PutByte((Byte)c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;
|
||||
UInt32 len = c - 256 + kMinMatch;
|
||||
UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);
|
||||
if (distance != 0)
|
||||
distance = (1 << (distance - 1)) + ReadBits(distance - 1);
|
||||
pos += len;
|
||||
if (distance >= pos)
|
||||
throw 1;
|
||||
m_OutWindowStream.CopyBlock(distance, len);
|
||||
}
|
||||
}
|
||||
coderReleaser.NeedFlush = false;
|
||||
return m_OutWindowStream.Flush();
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
}}}
|
||||
103
CPP/7zip/Compress/Lzh/LzhDecoder.h
Executable file
103
CPP/7zip/Compress/Lzh/LzhDecoder.h
Executable file
@@ -0,0 +1,103 @@
|
||||
// LzhDecoder.h
|
||||
|
||||
#ifndef __COMPRESS_LZH_DECODER_H
|
||||
#define __COMPRESS_LZH_DECODER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Common/MSBFDecoder.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
#include "../Huffman/HuffmanDecoder.h"
|
||||
#include "../LZ/LZOutWindow.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLzh {
|
||||
namespace NDecoder {
|
||||
|
||||
const int kMaxHuffmanLen = 16; // Check it
|
||||
|
||||
const int kNumSpecLevelSymbols = 3;
|
||||
const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen;
|
||||
|
||||
const int kDictBitsMax = 16;
|
||||
const int kNumDistanceSymbols = kDictBitsMax + 1;
|
||||
|
||||
const int kMaxMatch = 256;
|
||||
const int kMinMatch = 3;
|
||||
const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch;
|
||||
|
||||
template <UInt32 m_NumSymbols>
|
||||
class CHuffmanDecoder:public NCompress::NHuffman::CDecoder<kMaxHuffmanLen, m_NumSymbols>
|
||||
{
|
||||
public:
|
||||
int Symbol;
|
||||
template <class TBitDecoder>
|
||||
UInt32 Decode(TBitDecoder *bitStream)
|
||||
{
|
||||
if (Symbol >= 0)
|
||||
return (UInt32)Symbol;
|
||||
return DecodeSymbol(bitStream);
|
||||
}
|
||||
};
|
||||
|
||||
class CCoder :
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
NStream::NMSBF::CDecoder<CInBuffer> m_InBitStream;
|
||||
|
||||
int m_NumDictBits;
|
||||
|
||||
CHuffmanDecoder<kNumLevelSymbols> m_LevelHuffman;
|
||||
CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;
|
||||
CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder;
|
||||
|
||||
void ReleaseStreams()
|
||||
{
|
||||
m_OutWindowStream.ReleaseStream();
|
||||
m_InBitStream.ReleaseStream();
|
||||
}
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CCoder *m_Coder;
|
||||
public:
|
||||
bool NeedFlush;
|
||||
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
|
||||
~CCoderReleaser()
|
||||
{
|
||||
if (NeedFlush)
|
||||
m_Coder->m_OutWindowStream.Flush();
|
||||
m_Coder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
friend class CCoderReleaser;
|
||||
|
||||
void MakeTable(int nchar, Byte *bitlen, int tablebits,
|
||||
UInt32 *table, int tablesize);
|
||||
|
||||
UInt32 ReadBits(int numBits);
|
||||
HRESULT ReadLevelTable();
|
||||
HRESULT ReadPTable(int numBits);
|
||||
HRESULT ReadCTable();
|
||||
|
||||
public:
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; }
|
||||
CCoder(): m_NumDictBits(0) {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user