physfs/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h

256 lines
6.7 KiB
C++

// LZMA/Decoder.h
#ifndef __LZMA_DECODER_H
#define __LZMA_DECODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../LZ/LZOutWindow.h"
#include "../RangeCoder/RangeCoderBitTree.h"
extern "C"
{
#include "../../../../C/Alloc.h"
}
#include "LZMA.h"
namespace NCompress {
namespace NLZMA {
typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder;
class CLiteralDecoder2
{
CMyBitDecoder _decoders[0x300];
public:
void Init()
{
for (int i = 0; i < 0x300; i++)
_decoders[i].Init();
}
Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder)
{
UInt32 symbol = 1;
RC_INIT_VAR
do
{
// symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
}
while (symbol < 0x100);
RC_FLUSH_VAR
return (Byte)symbol;
}
Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte)
{
UInt32 symbol = 1;
RC_INIT_VAR
do
{
UInt32 matchBit = (matchByte >> 7) & 1;
matchByte <<= 1;
// UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder);
// symbol = (symbol << 1) | bit;
UInt32 bit;
RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol,
bit = 0, bit = 1)
if (matchBit != bit)
{
while (symbol < 0x100)
{
// symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
}
break;
}
}
while (symbol < 0x100);
RC_FLUSH_VAR
return (Byte)symbol;
}
};
class CLiteralDecoder
{
CLiteralDecoder2 *_coders;
int _numPrevBits;
int _numPosBits;
UInt32 _posMask;
public:
CLiteralDecoder(): _coders(0) {}
~CLiteralDecoder() { Free(); }
void Free()
{
MyFree(_coders);
_coders = 0;
}
bool Create(int numPosBits, int numPrevBits)
{
if (_coders == 0 || (numPosBits + numPrevBits) !=
(_numPrevBits + _numPosBits) )
{
Free();
UInt32 numStates = 1 << (numPosBits + numPrevBits);
_coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2));
}
_numPosBits = numPosBits;
_posMask = (1 << numPosBits) - 1;
_numPrevBits = numPrevBits;
return (_coders != 0);
}
void Init()
{
UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
for (UInt32 i = 0; i < numStates; i++)
_coders[i].Init();
}
UInt32 GetState(UInt32 pos, Byte prevByte) const
{ return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte)
{ return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte)
{ return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
};
namespace NLength {
class CDecoder
{
CMyBitDecoder _choice;
CMyBitDecoder _choice2;
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax];
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax];
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder;
public:
void Init(UInt32 numPosStates)
{
_choice.Init();
_choice2.Init();
for (UInt32 posState = 0; posState < numPosStates; posState++)
{
_lowCoder[posState].Init();
_midCoder[posState].Init();
}
_highCoder.Init();
}
UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState)
{
if(_choice.Decode(rangeDecoder) == 0)
return _lowCoder[posState].Decode(rangeDecoder);
if(_choice2.Decode(rangeDecoder) == 0)
return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder);
return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder);
}
};
}
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
public ICompressGetInStreamProcessedSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
public CMyUnknownImp
{
CLZOutWindow _outWindowStream;
NRangeCoder::CDecoder _rangeDecoder;
CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax];
CMyBitDecoder _isRep[kNumStates];
CMyBitDecoder _isRepG0[kNumStates];
CMyBitDecoder _isRepG1[kNumStates];
CMyBitDecoder _isRepG2[kNumStates];
CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax];
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex];
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder;
NLength::CDecoder _lenDecoder;
NLength::CDecoder _repMatchLenDecoder;
CLiteralDecoder _literalDecoder;
UInt32 _posStateMask;
///////////////////
// State
UInt32 _reps[4];
CState _state;
Int32 _remainLen; // -1 means end of stream. // -2 means need Init
UInt64 _outSize;
bool _outSizeDefined;
void Init();
HRESULT CodeSpec(UInt32 size);
public:
#ifndef NO_READ_FROM_CODER
MY_UNKNOWN_IMP5(
ICompressSetDecoderProperties2,
ICompressGetInStreamProcessedSize,
ICompressSetInStream,
ICompressSetOutStreamSize,
ISequentialInStream)
#else
MY_UNKNOWN_IMP2(
ICompressSetDecoderProperties2,
ICompressGetInStreamProcessedSize)
#endif
void ReleaseStreams()
{
_outWindowStream.ReleaseStream();
ReleaseInStream();
}
class CDecoderFlusher
{
CDecoder *_decoder;
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
~CDecoderFlusher()
{
if (NeedFlush)
_decoder->Flush();
_decoder->ReleaseStreams();
}
};
HRESULT Flush() { return _outWindowStream.Flush(); }
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);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifndef NO_READ_FROM_CODER
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif
CDecoder(): _outSizeDefined(false) {}
virtual ~CDecoder() {}
};
}}
#endif