mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-16 08:11:46 -06:00
4.59 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
3901bf0ab8
commit
173c07e166
@@ -1,3 +0,0 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -4,57 +4,37 @@
|
||||
|
||||
#include "ZDecoder.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#include "../../../../C/Alloc.h"
|
||||
}
|
||||
|
||||
#include "../../Common/InBuffer.h"
|
||||
#include "../../Common/OutBuffer.h"
|
||||
#include "../../Common/LSBFDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NZ {
|
||||
|
||||
static const UInt32 kBufferSize = (1 << 20);
|
||||
static const Byte kNumBitsMask = 0x1F;
|
||||
static const Byte kBlockModeMask = 0x80;
|
||||
static const int kNumMinBits = 9;
|
||||
static const int kNumMaxBits = 16;
|
||||
static const Byte kNumBitsMask = 0x1F;
|
||||
static const Byte kBlockModeMask = 0x80;
|
||||
static const int kNumMinBits = 9;
|
||||
static const int kNumMaxBits = 16;
|
||||
|
||||
void CDecoder::Free()
|
||||
{
|
||||
MyFree(_parents);
|
||||
_parents = 0;
|
||||
MyFree(_suffixes);
|
||||
_suffixes = 0;
|
||||
MyFree(_stack);
|
||||
_stack = 0;
|
||||
MyFree(_parents); _parents = 0;
|
||||
MyFree(_suffixes); _suffixes = 0;
|
||||
MyFree(_stack); _stack = 0;
|
||||
}
|
||||
|
||||
bool CDecoder::Alloc(size_t numItems)
|
||||
{
|
||||
Free();
|
||||
_parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16));
|
||||
if (_parents == 0)
|
||||
return false;
|
||||
_suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte));
|
||||
if (_suffixes == 0)
|
||||
return false;
|
||||
_stack = (Byte *)MyAlloc(numItems * sizeof(Byte));
|
||||
return _stack != 0;
|
||||
}
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
CDecoder::~CDecoder() { Free(); }
|
||||
|
||||
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer;
|
||||
CInBuffer inBuffer;
|
||||
COutBuffer outBuffer;
|
||||
|
||||
if (!inBuffer.Create(kBufferSize))
|
||||
@@ -72,13 +52,13 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
return S_FALSE;
|
||||
UInt32 numItems = 1 << maxbits;
|
||||
bool blockMode = ((_properties & kBlockModeMask) != 0);
|
||||
if (!blockMode)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)
|
||||
{
|
||||
if (!Alloc(numItems))
|
||||
return E_OUTOFMEMORY;
|
||||
Free();
|
||||
_parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (_parents == 0) return E_OUTOFMEMORY;
|
||||
_suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_suffixes == 0) return E_OUTOFMEMORY;
|
||||
_stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_stack == 0) return E_OUTOFMEMORY;
|
||||
_numMaxBits = maxbits;
|
||||
}
|
||||
|
||||
@@ -88,25 +68,40 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
|
||||
bool needPrev = false;
|
||||
|
||||
int keepBits = 0;
|
||||
unsigned bitPos = 0;
|
||||
unsigned numBufBits = 0;
|
||||
|
||||
Byte buf[kNumMaxBits + 4];
|
||||
|
||||
_parents[256] = 0; // virus protection
|
||||
_suffixes[256] = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (keepBits < numBits)
|
||||
keepBits = numBits * 8;
|
||||
UInt32 symbol = inBuffer.ReadBits(numBits);
|
||||
if (inBuffer.ExtraBitsWereRead())
|
||||
if (numBufBits == bitPos)
|
||||
{
|
||||
numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8;
|
||||
bitPos = 0;
|
||||
UInt64 nowPos = outBuffer.GetProcessedSize();
|
||||
if (progress != NULL && nowPos - prevPos >= (1 << 18))
|
||||
{
|
||||
prevPos = nowPos;
|
||||
UInt64 packSize = inBuffer.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
|
||||
}
|
||||
}
|
||||
unsigned bytePos = bitPos >> 3;
|
||||
UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);
|
||||
symbol >>= (bitPos & 7);
|
||||
symbol &= (1 << numBits) - 1;
|
||||
bitPos += numBits;
|
||||
if (bitPos > numBufBits)
|
||||
break;
|
||||
keepBits -= numBits;
|
||||
if (symbol >= head)
|
||||
return S_FALSE;
|
||||
if (blockMode && symbol == 256)
|
||||
{
|
||||
for (;keepBits > 0; keepBits--)
|
||||
inBuffer.ReadBits(1);
|
||||
numBufBits = bitPos = 0;
|
||||
numBits = kNumMinBits;
|
||||
head = 257;
|
||||
needPrev = false;
|
||||
@@ -126,8 +121,9 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
if (symbol == head - 1)
|
||||
_stack[0] = (Byte)cur;
|
||||
}
|
||||
while (i > 0)
|
||||
do
|
||||
outBuffer.WriteByte((_stack[--i]));
|
||||
while (i > 0);
|
||||
if (head < numItems)
|
||||
{
|
||||
needPrev = true;
|
||||
@@ -136,21 +132,13 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
{
|
||||
if (numBits < maxbits)
|
||||
{
|
||||
numBufBits = bitPos = 0;
|
||||
numBits++;
|
||||
keepBits = numBits * 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
needPrev = false;
|
||||
|
||||
UInt64 nowPos = outBuffer.GetProcessedSize();
|
||||
if (progress != NULL && nowPos - prevPos > (1 << 18))
|
||||
{
|
||||
prevPos = nowPos;
|
||||
UInt64 packSize = inBuffer.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
|
||||
}
|
||||
}
|
||||
return outBuffer.Flush();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ public:
|
||||
CDecoder(): _properties(0), _numMaxBits(0), _parents(0), _suffixes(0), _stack(0) {};
|
||||
~CDecoder();
|
||||
void Free();
|
||||
bool Alloc(size_t numItems);
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user