Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Compress/Rar3Decoder.cpp')
-rwxr-xr-xCPP/7zip/Compress/Rar3Decoder.cpp152
1 files changed, 107 insertions, 45 deletions
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index 77106278..af5cef1a 100755
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -1,9 +1,13 @@
// Rar3Decoder.cpp
// According to unRAR license, this code may not be used to develop
// a program that creates RAR archives
+
+/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "StdAfx.h"
+#include "../../../C/Alloc.h"
+
#include "../Common/StreamUtils.h"
#include "Rar3Decoder.h"
@@ -11,6 +15,10 @@
namespace NCompress {
namespace NRar3 {
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
+static void SzBigFree(void *, void *address) { BigFree(address); }
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
+
static const UInt32 kNumAlignReps = 15;
static const UInt32 kSymbolReadTable = 256;
@@ -38,6 +46,48 @@ static const UInt32 kNormalMatchMinLen = 3;
static const UInt32 kVmDataSizeMax = 1 << 16;
static const UInt32 kVmCodeSizeMax = 1 << 16;
+extern "C" {
+
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)
+{
+ CRangeDecoder *p = (CRangeDecoder *)pp;
+ return p->Code / (p->Range /= total);
+}
+
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)
+{
+ CRangeDecoder *p = (CRangeDecoder *)pp;
+ start *= p->Range;
+ p->Low += start;
+ p->Code -= start;
+ p->Range *= size;
+ p->Normalize();
+}
+
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
+{
+ CRangeDecoder *p = (CRangeDecoder *)pp;
+ if (p->Code / (p->Range >>= 14) < size0)
+ {
+ Range_Decode(p, 0, size0);
+ return 0;
+ }
+ else
+ {
+ Range_Decode(p, size0, (1 << 14) - size0);
+ return 1;
+ }
+}
+
+}
+
+CRangeDecoder::CRangeDecoder()
+{
+ s.GetThreshold = Range_GetThreshold;
+ s.Decode = Range_Decode;
+ s.DecodeBit = Range_DecodeBit;
+}
+
CDecoder::CDecoder():
_window(0),
_winPos(0),
@@ -48,6 +98,7 @@ CDecoder::CDecoder():
_vmCode(0),
m_IsSolid(false)
{
+ Ppmd7_Construct(&_ppmd);
}
CDecoder::~CDecoder()
@@ -55,6 +106,7 @@ CDecoder::~CDecoder()
InitFilters();
::MidFree(_vmData);
::MidFree(_window);
+ Ppmd7_Free(&_ppmd, &g_BigAlloc);
}
HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
@@ -294,39 +346,39 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
bool CDecoder::ReadVmCodeLZ()
{
- UInt32 firstByte = m_InBitStream.ReadBits(8);
+ UInt32 firstByte = ReadBits(8);
UInt32 length = (firstByte & 7) + 1;
if (length == 7)
- length = m_InBitStream.ReadBits(8) + 7;
+ length = ReadBits(8) + 7;
else if (length == 8)
- length = m_InBitStream.ReadBits(16);
+ length = ReadBits(16);
if (length > kVmDataSizeMax)
return false;
for (UInt32 i = 0; i < length; i++)
- _vmData[i] = (Byte)m_InBitStream.ReadBits(8);
+ _vmData[i] = (Byte)ReadBits(8);
return AddVmCode(firstByte, length);
}
bool CDecoder::ReadVmCodePPM()
{
int firstByte = DecodePpmSymbol();
- if (firstByte == -1)
+ if (firstByte < 0)
return false;
UInt32 length = (firstByte & 7) + 1;
if (length == 7)
{
int b1 = DecodePpmSymbol();
- if (b1 == -1)
+ if (b1 < 0)
return false;
length = b1 + 7;
}
else if (length == 8)
{
int b1 = DecodePpmSymbol();
- if (b1 == -1)
+ if (b1 < 0)
return false;
int b2 = DecodePpmSymbol();
- if (b2 == -1)
+ if (b2 < 0)
return false;
length = b1 * 256 + b2;
}
@@ -335,7 +387,7 @@ bool CDecoder::ReadVmCodePPM()
for (UInt32 i = 0; i < length; i++)
{
int b = DecodePpmSymbol();
- if (b == -1)
+ if (b < 0)
return false;
_vmData[i] = (Byte)b;
}
@@ -344,7 +396,7 @@ bool CDecoder::ReadVmCodePPM()
#define RIF(x) { if (!(x)) return S_FALSE; }
-UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
+UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.bitDecoder.ReadBits(numBits); }
/////////////////////////////////////////////////
// PPM
@@ -359,7 +411,7 @@ HRESULT CDecoder::InitPPM()
maxMB = (Byte)ReadBits(8);
else
{
- if (_ppm.SubAllocator.GetSubAllocatorSize()== 0)
+ if (PpmError || !Ppmd7_WasAllocated(&_ppmd))
return S_FALSE;
}
if (maxOrder & 0x40)
@@ -371,34 +423,30 @@ HRESULT CDecoder::InitPPM()
*/
if (reset)
{
+ PpmError = true;
maxOrder = (maxOrder & 0x1F) + 1;
if (maxOrder > 16)
maxOrder = 16 + (maxOrder - 16) * 3;
if (maxOrder == 1)
{
- // SubAlloc.StopSubAllocator();
- _ppm.SubAllocator.StopSubAllocator();
+ Ppmd7_Free(&_ppmd, &g_BigAlloc);
return S_FALSE;
}
- // SubAlloc.StartSubAllocator(MaxMB+1);
- // StartModelRare(maxOrder);
-
- if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20))
+ if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))
return E_OUTOFMEMORY;
- _ppm.MaxOrder = 0;
- _ppm.StartModelRare(maxOrder);
-
+ Ppmd7_Init(&_ppmd, maxOrder);
+ PpmError = false;
}
- // return (minContext != NULL);
-
return S_OK;
}
-int CDecoder::DecodePpmSymbol() { return _ppm.DecodeSymbol(&m_InBitStream); }
+int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); }
HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
{
keepDecompressing = false;
+ if (PpmError)
+ return S_FALSE;
do
{
if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
@@ -411,15 +459,19 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
}
}
int c = DecodePpmSymbol();
- if (c == -1)
+ if (c < 0)
{
- // Original code sets PPMError=true here and then it returns S_OK. Why ???
- // return S_OK;
+ PpmError = true;
return S_FALSE;
}
if (c == PpmEscChar)
{
int nextCh = DecodePpmSymbol();
+ if (nextCh < 0)
+ {
+ PpmError = true;
+ return S_FALSE;
+ }
if (nextCh == 0)
return ReadTables(keepDecompressing);
if (nextCh == 2 || nextCh == -1)
@@ -427,7 +479,10 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
if (nextCh == 3)
{
if (!ReadVmCodePPM())
+ {
+ PpmError = true;
return S_FALSE;
+ }
continue;
}
if (nextCh == 4 || nextCh == 5)
@@ -439,16 +494,22 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
for (int i = 0; i < 3; i++)
{
int c = DecodePpmSymbol();
- if (c == -1)
- return S_OK;
+ if (c < 0)
+ {
+ PpmError = true;
+ return S_FALSE;
+ }
distance = (distance << 8) + (Byte)c;
}
distance++;
length += 28;
}
int c = DecodePpmSymbol();
- if (c == -1)
- return S_OK;
+ if (c < 0)
+ {
+ PpmError = true;
+ return S_FALSE;
+ }
length += c;
if (distance >= _lzSize)
return S_FALSE;
@@ -471,7 +532,7 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
HRESULT CDecoder::ReadTables(bool &keepDecompressing)
{
keepDecompressing = true;
- ReadBits((8 - m_InBitStream.GetBitPosition()) & 7);
+ ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7);
if (ReadBits(1) != 0)
{
_lzMode = false;
@@ -510,7 +571,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
i = 0;
while (i < kTablesSizesSum)
{
- UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
+ UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < 16)
{
newLevels[i] = Byte((number + m_LastLevels[i]) & 15);
@@ -620,7 +681,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
return S_OK;
}
}
- UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
+ UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < 256)
{
PutByte((Byte)number);
@@ -664,10 +725,10 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
rep0 = distance;
}
- UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream);
+ UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number >= kLenTableSize)
return S_FALSE;
- length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);
+ length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);
}
else
{
@@ -677,14 +738,14 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
if (number < 271)
{
number -= 263;
- rep0 = kLen2DistStarts[number] + m_InBitStream.ReadBits(kLen2DistDirectBits[number]);
+ rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]);
length = 2;
}
else if (number < 299)
{
number -= 271;
- length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);
- UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
+ length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);
+ UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number >= kDistTableSize)
return S_FALSE;
rep0 = kDistStart[number];
@@ -692,7 +753,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
if (number >= (kNumAlignBits * 2) + 2)
{
if (numBits > kNumAlignBits)
- rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
+ rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
if (PrevAlignCount > 0)
{
PrevAlignCount--;
@@ -700,7 +761,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
}
else
{
- UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream);
+ UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < (1 << kNumAlignBits))
{
rep0 += number;
@@ -716,7 +777,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
}
}
else
- rep0 += m_InBitStream.ReadBits(numBits);
+ rep0 += m_InBitStream.bitDecoder.ReadBits(numBits);
length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31);
}
else
@@ -749,6 +810,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
memset(m_LastLevels, 0, kTablesSizesSum);
TablesRead = false;
PpmEscChar = 2;
+ PpmError = true;
InitFilters();
}
if (!m_IsSolid || !TablesRead)
@@ -770,7 +832,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
{
RINOK(DecodePPM(1 << 18, keepDecompressing))
}
- UInt64 packSize = m_InBitStream.GetProcessedSize();
+ UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (!keepDecompressing)
break;
@@ -804,14 +866,14 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
if (_window == 0)
return E_OUTOFMEMORY;
}
- if (!m_InBitStream.Create(1 << 20))
+ if (!m_InBitStream.bitDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_vm.Create())
return E_OUTOFMEMORY;
- m_InBitStream.SetStream(inStream);
- m_InBitStream.Init();
+ m_InBitStream.bitDecoder.SetStream(inStream);
+ m_InBitStream.bitDecoder.Init();
_outStream = outStream;
CCoderReleaser coderReleaser(this);