chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
// LzhDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LzhDecoder.h"
|
||||
|
||||
namespace NCompress{
|
||||
namespace NLzh {
|
||||
namespace NDecoder {
|
||||
|
||||
static const UInt32 kWindowSizeMin = 1 << 16;
|
||||
|
||||
bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec)
|
||||
{
|
||||
_symbolT = -1;
|
||||
|
||||
const unsigned n = (unsigned)_inBitStream.ReadBits(numBits);
|
||||
if (n == 0)
|
||||
{
|
||||
const unsigned s = (unsigned)_inBitStream.ReadBits(numBits);
|
||||
_symbolT = (int)s;
|
||||
return (s < num);
|
||||
}
|
||||
if (n > num)
|
||||
return false;
|
||||
|
||||
{
|
||||
Byte lens[NPT];
|
||||
unsigned i;
|
||||
for (i = 0; i < NPT; i++)
|
||||
lens[i] = 0;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
unsigned val = (unsigned)_inBitStream.GetValue(16);
|
||||
unsigned c = val >> 13;
|
||||
unsigned mov = 3;
|
||||
if (c == 7)
|
||||
{
|
||||
while (val & (1 << 12))
|
||||
{
|
||||
val += val;
|
||||
c++;
|
||||
}
|
||||
if (c > 16)
|
||||
return false;
|
||||
mov = c - 3;
|
||||
}
|
||||
lens[i++] = (Byte)c;
|
||||
_inBitStream.MovePos(mov);
|
||||
if ((int)i == spec)
|
||||
i += _inBitStream.ReadBits(2);
|
||||
}
|
||||
while (i < n);
|
||||
|
||||
return _decoderT.Build(lens, NHuffman::k_BuildMode_Full);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned NUM_C_BITS = 9;
|
||||
|
||||
bool CCoder::ReadC()
|
||||
{
|
||||
_symbolC = -1;
|
||||
|
||||
const unsigned n = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);
|
||||
if (n == 0)
|
||||
{
|
||||
const unsigned s = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);
|
||||
_symbolC = (int)s;
|
||||
return (s < NC);
|
||||
}
|
||||
if (n > NC)
|
||||
return false;
|
||||
|
||||
{
|
||||
Byte lens[NC];
|
||||
unsigned i = 0;
|
||||
do
|
||||
{
|
||||
unsigned c = (unsigned)_symbolT;
|
||||
if (_symbolT < 0)
|
||||
c = _decoderT.DecodeFull(&_inBitStream);
|
||||
|
||||
if (c <= 2)
|
||||
{
|
||||
if (c == 0)
|
||||
c = 1;
|
||||
else if (c == 1)
|
||||
c = _inBitStream.ReadBits(4) + 3;
|
||||
else
|
||||
c = _inBitStream.ReadBits(NUM_C_BITS) + 20;
|
||||
|
||||
if (i + c > n)
|
||||
return false;
|
||||
|
||||
do
|
||||
lens[i++] = 0;
|
||||
while (--c);
|
||||
}
|
||||
else
|
||||
lens[i++] = (Byte)(c - 2);
|
||||
}
|
||||
while (i < n);
|
||||
|
||||
while (i < NC) lens[i++] = 0;
|
||||
return _decoderC.Build(lens, /* n, */ NHuffman::k_BuildMode_Full);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)
|
||||
{
|
||||
UInt32 blockSize = 0;
|
||||
|
||||
while (rem != 0)
|
||||
{
|
||||
if (blockSize == 0)
|
||||
{
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
if (progress)
|
||||
{
|
||||
const UInt64 packSize = _inBitStream.GetProcessedSize();
|
||||
const UInt64 pos = _outWindow.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos))
|
||||
}
|
||||
|
||||
blockSize = _inBitStream.ReadBits(16);
|
||||
if (blockSize == 0)
|
||||
return S_FALSE;
|
||||
|
||||
if (!ReadTP(NT, 5, 3))
|
||||
return S_FALSE;
|
||||
if (!ReadC())
|
||||
return S_FALSE;
|
||||
const unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5);
|
||||
if (!ReadTP(NP, pbit, -1))
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
blockSize--;
|
||||
|
||||
unsigned number = (unsigned)_symbolC;
|
||||
if (_symbolC < 0)
|
||||
number = _decoderC.DecodeFull(&_inBitStream);
|
||||
|
||||
if (number < 256)
|
||||
{
|
||||
_outWindow.PutByte((Byte)number);
|
||||
rem--;
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned len = number - 256 + kMatchMinLen;
|
||||
|
||||
UInt32 dist = (UInt32)(unsigned)_symbolT;
|
||||
if (_symbolT < 0)
|
||||
dist = (UInt32)_decoderT.DecodeFull(&_inBitStream);
|
||||
|
||||
if (dist > 1)
|
||||
{
|
||||
dist--;
|
||||
dist = ((UInt32)1 << dist) + _inBitStream.ReadBits((unsigned)dist);
|
||||
}
|
||||
|
||||
if (dist >= DictSize)
|
||||
return S_FALSE;
|
||||
|
||||
if (len > rem)
|
||||
{
|
||||
// if (FinishMode)
|
||||
return S_FALSE;
|
||||
// len = (unsigned)rem;
|
||||
}
|
||||
|
||||
if (!_outWindow.CopyBlock(dist, len))
|
||||
return S_FALSE;
|
||||
rem -= len;
|
||||
}
|
||||
}
|
||||
|
||||
// if (FinishMode)
|
||||
{
|
||||
if (blockSize != 0)
|
||||
return S_FALSE;
|
||||
if (_inBitStream.ReadAlignBits() != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt32 outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_inBitStream.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
_outWindow.SetStream(outStream);
|
||||
_outWindow.Init(false);
|
||||
_inBitStream.SetStream(inStream);
|
||||
_inBitStream.Init();
|
||||
{
|
||||
CCoderReleaser coderReleaser(this);
|
||||
RINOK(CodeReal(outSize, progress))
|
||||
coderReleaser.Disable();
|
||||
}
|
||||
return _outWindow.Flush();
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
}}}
|
||||
Reference in New Issue
Block a user