mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 20:11:35 -06:00
3.13
This commit is contained in:
356
7zip/Compress/LZMA/LZMADecoder.cpp
Executable file
356
7zip/Compress/LZMA/LZMADecoder.cpp
Executable file
@@ -0,0 +1,356 @@
|
||||
// LZMADecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LZMADecoder.h"
|
||||
#include "../../../Common/Defs.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
/*
|
||||
#include "fstream.h"
|
||||
#include "iomanip.h"
|
||||
|
||||
ofstream ofs("res.dat");
|
||||
|
||||
const int kNumCounters = 3;
|
||||
UINT32 g_Counter[kNumCounters];
|
||||
class C1
|
||||
{
|
||||
public:
|
||||
~C1()
|
||||
{
|
||||
for (int i = 0; i < kNumCounters; i++)
|
||||
ofs << setw(10) << g_Counter[i] << endl;
|
||||
}
|
||||
} g_C1;
|
||||
*/
|
||||
|
||||
/*
|
||||
const UINT32 kLenTableMax = 20;
|
||||
const UINT32 kNumDists = NCompress::NLZMA::kDistTableSizeMax / 2;
|
||||
UINT32 g_Counts[kLenTableMax][kNumDists];
|
||||
class C1
|
||||
{
|
||||
public:
|
||||
~C1 ()
|
||||
{
|
||||
UINT32 sums[kLenTableMax];
|
||||
for (int len = 2; len < kLenTableMax; len++)
|
||||
{
|
||||
sums[len] = 0;
|
||||
for (int dist = 0; dist < kNumDists; dist++)
|
||||
sums[len] += g_Counts[len][dist];
|
||||
if (sums[len] == 0)
|
||||
sums[len] = 1;
|
||||
}
|
||||
for (int dist = 0; dist < kNumDists; dist++)
|
||||
{
|
||||
ofs << setw(4) << dist << " ";
|
||||
for (int len = 2; len < kLenTableMax; len++)
|
||||
{
|
||||
ofs << setw(4) << g_Counts[len][dist] * 1000 / sums[len];
|
||||
}
|
||||
ofs << endl;
|
||||
}
|
||||
}
|
||||
} g_Class;
|
||||
|
||||
void UpdateStat(UINT32 len, UINT32 dist)
|
||||
{
|
||||
if (len >= kLenTableMax)
|
||||
len = kLenTableMax - 1;
|
||||
g_Counts[len][dist / 2]++;
|
||||
}
|
||||
*/
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLZMA {
|
||||
|
||||
HRESULT CDecoder::SetDictionarySize(UINT32 dictionarySize)
|
||||
{
|
||||
if (_dictionarySize != dictionarySize)
|
||||
{
|
||||
_dictionarySize = dictionarySize;
|
||||
_dictionarySizeCheck = MyMax(_dictionarySize, UINT32(1));
|
||||
UINT32 blockSize = MyMax(_dictionarySizeCheck, UINT32(1 << 12));
|
||||
try
|
||||
{
|
||||
_outWindowStream.Create(blockSize /*, kMatchMaxLen */);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::SetLiteralProperties(
|
||||
UINT32 numLiteralPosStateBits, UINT32 numLiteralContextBits)
|
||||
{
|
||||
if (numLiteralPosStateBits > 8)
|
||||
return E_INVALIDARG;
|
||||
if (numLiteralContextBits > 8)
|
||||
return E_INVALIDARG;
|
||||
_literalDecoder.Create(numLiteralPosStateBits, numLiteralContextBits);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::SetPosBitsProperties(UINT32 numPosStateBits)
|
||||
{
|
||||
if (numPosStateBits > NLength::kNumPosStatesBitsMax)
|
||||
return E_INVALIDARG;
|
||||
UINT32 numPosStates = 1 << numPosStateBits;
|
||||
_lenDecoder.Create(numPosStates);
|
||||
_repMatchLenDecoder.Create(numPosStates);
|
||||
_posStateMask = numPosStates - 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CDecoder::CDecoder():
|
||||
_dictionarySize((UINT32)-1)
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
HRESULT CDecoder::Create()
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
for(int i = 0; i < kNumPosModels; i++)
|
||||
_posDecoders[i].Create(((kStartPosModelIndex + i) >> 1) - 1);
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::Init(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream)
|
||||
{
|
||||
_rangeDecoder.Init(inStream);
|
||||
|
||||
_outWindowStream.Init(outStream);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < kNumStates; i++)
|
||||
{
|
||||
for (UINT32 j = 0; j <= _posStateMask; j++)
|
||||
{
|
||||
_mainChoiceDecoders[i][j].Init();
|
||||
_matchRepShortChoiceDecoders[i][j].Init();
|
||||
}
|
||||
_matchChoiceDecoders[i].Init();
|
||||
_matchRepChoiceDecoders[i].Init();
|
||||
_matchRep1ChoiceDecoders[i].Init();
|
||||
_matchRep2ChoiceDecoders[i].Init();
|
||||
}
|
||||
|
||||
_literalDecoder.Init();
|
||||
|
||||
// _repMatchLenDecoder.Init();
|
||||
|
||||
for (i = 0; i < kNumLenToPosStates; i++)
|
||||
_posSlotDecoder[i].Init();
|
||||
|
||||
for(i = 0; i < kNumPosModels; i++)
|
||||
_posDecoders[i].Init();
|
||||
|
||||
_lenDecoder.Init();
|
||||
_repMatchLenDecoder.Init();
|
||||
|
||||
_posAlignDecoder.Init();
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
/*
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
*/
|
||||
|
||||
Init(inStream, outStream);
|
||||
CDecoderFlusher flusher(this);
|
||||
|
||||
CState state;
|
||||
state.Init();
|
||||
bool peviousIsMatch = false;
|
||||
BYTE previousByte = 0;
|
||||
UINT32 repDistances[kNumRepDistances];
|
||||
for(int i = 0 ; i < kNumRepDistances; i++)
|
||||
repDistances[i] = 0;
|
||||
|
||||
UINT64 nowPos64 = 0;
|
||||
UINT64 size = (outSize == NULL) ? (UINT64)(INT64)(-1) : *outSize;
|
||||
while(nowPos64 < size)
|
||||
{
|
||||
UINT64 nextPos = MyMin(nowPos64 + (1 << 18), size);
|
||||
while(nowPos64 < nextPos)
|
||||
{
|
||||
UINT32 posState = UINT32(nowPos64) & _posStateMask;
|
||||
if (_mainChoiceDecoders[state.Index][posState].Decode(&_rangeDecoder) == kMainChoiceLiteralIndex)
|
||||
{
|
||||
state.UpdateChar();
|
||||
if(peviousIsMatch)
|
||||
{
|
||||
BYTE matchByte = _outWindowStream.GetOneByte(0 - repDistances[0] - 1);
|
||||
previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder,
|
||||
UINT32(nowPos64), previousByte, matchByte);
|
||||
peviousIsMatch = false;
|
||||
}
|
||||
else
|
||||
previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder,
|
||||
UINT32(nowPos64), previousByte);
|
||||
_outWindowStream.PutOneByte(previousByte);
|
||||
nowPos64++;
|
||||
}
|
||||
else
|
||||
{
|
||||
peviousIsMatch = true;
|
||||
UINT32 distance, len;
|
||||
if(_matchChoiceDecoders[state.Index].Decode(&_rangeDecoder) ==
|
||||
kMatchChoiceRepetitionIndex)
|
||||
{
|
||||
if(_matchRepChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0)
|
||||
{
|
||||
if(_matchRepShortChoiceDecoders[state.Index][posState].Decode(&_rangeDecoder) == 0)
|
||||
{
|
||||
state.UpdateShortRep();
|
||||
previousByte = _outWindowStream.GetOneByte(0 - repDistances[0] - 1);
|
||||
_outWindowStream.PutOneByte(previousByte);
|
||||
nowPos64++;
|
||||
continue;
|
||||
}
|
||||
distance = repDistances[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_matchRep1ChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0)
|
||||
distance = repDistances[1];
|
||||
else
|
||||
{
|
||||
if (_matchRep2ChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0)
|
||||
distance = repDistances[2];
|
||||
else
|
||||
{
|
||||
distance = repDistances[3];
|
||||
repDistances[3] = repDistances[2];
|
||||
}
|
||||
repDistances[2] = repDistances[1];
|
||||
}
|
||||
repDistances[1] = repDistances[0];
|
||||
repDistances[0] = distance;
|
||||
}
|
||||
len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
|
||||
state.UpdateRep();
|
||||
}
|
||||
else
|
||||
{
|
||||
len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
|
||||
state.UpdateMatch();
|
||||
UINT32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
{
|
||||
UINT32 numDirectBits = (posSlot >> 1) - 1;
|
||||
distance = ((2 | (posSlot & 1)) << numDirectBits);
|
||||
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
distance += _posDecoders[posSlot - kStartPosModelIndex].Decode(&_rangeDecoder);
|
||||
else
|
||||
{
|
||||
distance += (_rangeDecoder.DecodeDirectBits(
|
||||
numDirectBits - kNumAlignBits) << kNumAlignBits);
|
||||
distance += _posAlignDecoder.Decode(&_rangeDecoder);
|
||||
}
|
||||
}
|
||||
else
|
||||
distance = posSlot;
|
||||
|
||||
repDistances[3] = repDistances[2];
|
||||
repDistances[2] = repDistances[1];
|
||||
repDistances[1] = repDistances[0];
|
||||
repDistances[0] = distance;
|
||||
// UpdateStat(len, posSlot);
|
||||
}
|
||||
if (distance >= nowPos64 || distance >= _dictionarySizeCheck)
|
||||
{
|
||||
if (distance == (UINT32)(-1) && size == (UINT64)(INT64)(-1))
|
||||
{
|
||||
flusher.NeedFlush = false;
|
||||
return Flush();
|
||||
}
|
||||
throw "data error";
|
||||
}
|
||||
_outWindowStream.CopyBackBlock(distance, len);
|
||||
nowPos64 += len;
|
||||
previousByte = _outWindowStream.GetOneByte(0 - 1);
|
||||
}
|
||||
}
|
||||
if (progress != NULL)
|
||||
{
|
||||
UINT64 inSize = _rangeDecoder.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
|
||||
}
|
||||
}
|
||||
flusher.NeedFlush = false;
|
||||
return Flush();
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::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; }
|
||||
}
|
||||
|
||||
|
||||
static HRESULT DecodeProperties(ISequentialInStream *inStream,
|
||||
UINT32 &numPosStateBits,
|
||||
UINT32 &numLiteralPosStateBits,
|
||||
UINT32 &numLiteralContextBits,
|
||||
UINT32 &dictionarySize)
|
||||
{
|
||||
UINT32 processesedSize;
|
||||
|
||||
BYTE firstByte;
|
||||
RINOK(inStream->Read(&firstByte, sizeof(firstByte), &processesedSize));
|
||||
if (processesedSize != sizeof(firstByte))
|
||||
return E_INVALIDARG;
|
||||
|
||||
numLiteralContextBits = firstByte % 9;
|
||||
BYTE remainder = firstByte / 9;
|
||||
numLiteralPosStateBits = remainder % 5;
|
||||
numPosStateBits = remainder / 5;
|
||||
|
||||
RINOK(inStream->Read(&dictionarySize, sizeof(dictionarySize), &processesedSize));
|
||||
if (processesedSize != sizeof(dictionarySize))
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties(ISequentialInStream *inStream)
|
||||
{
|
||||
UINT32 numPosStateBits;
|
||||
UINT32 numLiteralPosStateBits;
|
||||
UINT32 numLiteralContextBits;
|
||||
UINT32 dictionarySize;
|
||||
RINOK(DecodeProperties(inStream,
|
||||
numPosStateBits,
|
||||
numLiteralPosStateBits,
|
||||
numLiteralContextBits,
|
||||
dictionarySize));
|
||||
RINOK(SetDictionarySize(dictionarySize));
|
||||
RINOK(SetLiteralProperties(numLiteralPosStateBits, numLiteralContextBits));
|
||||
RINOK(SetPosBitsProperties(numPosStateBits));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user