4.27 beta

This commit is contained in:
Igor Pavlov
2005-09-21 00:00:00 +00:00
committed by Kornel Lesiński
parent 31e7b924e8
commit d66cf2fcf3
393 changed files with 17345 additions and 4743 deletions

View File

@@ -0,0 +1,66 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "Rar20Decoder.h"
// {23170F69-40C1-278B-0403-020000000000}
DEFINE_GUID(CLSID_CCompressRar20Decoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
return TRUE;
}
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
COM_TRY_BEGIN
*outObject = 0;
if (*clsid != CLSID_CCompressRar20Decoder)
return CLASS_E_CLASSNOTAVAILABLE;
if (*iid != IID_ICompressCoder)
return E_NOINTERFACE;
CMyComPtr<ICompressCoder> coder = (ICompressCoder *)new
NCompress::NRar20::CDecoder;
*outObject = coder.Detach();
COM_TRY_END
return S_OK;
}
STDAPI GetNumberOfMethods(UINT32 *numMethods)
{
*numMethods = 1;
return S_OK;
}
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
if (index != 0)
return E_INVALIDARG;
::VariantClear((tagVARIANT *)value);
switch(propID)
{
case NMethodPropID::kID:
{
const char id[] = { 0x04, 0x03, 0x02 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(L"Rar20")) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressRar20Decoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
return S_OK;
}

View File

@@ -0,0 +1,65 @@
// Rar20CoderConst.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR20_CONST_H
#define __RAR20_CONST_H
#include "Rar20ExtConst.h"
namespace NCompress {
namespace NRar20 {
const UInt32 kMainTableSize = 298;
const UInt32 kLenTableSize = 28;
const UInt32 kDistTableStart = kMainTableSize;
const UInt32 kLenTableStart = kDistTableStart + kDistTableSize;
const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize;
const UInt32 kLevelTableSize = 19;
const UInt32 kMMTablesSizesSum = kMMTableSize * 4;
const UInt32 kMaxTableSize = kMMTablesSizesSum;
const UInt32 kTableDirectLevels = 16;
const UInt32 kTableLevelRepNumber = kTableDirectLevels;
const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
const UInt32 kLevelMask = 0xF;
const UInt32 kRepBothNumber = 256;
const UInt32 kRepNumber = kRepBothNumber + 1;
const UInt32 kLen2Number = kRepNumber + 4;
const UInt32 kLen2NumNumbers = 8;
const UInt32 kReadTableNumber = kLen2Number + kLen2NumNumbers;
const UInt32 kMatchNumber = kReadTableNumber + 1;
const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
const UInt32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
const Byte kLen2DistStarts[kLen2NumNumbers]={0,4,8,16,32,64,128,192};
const Byte kLen2DistDirectBits[kLen2NumNumbers]={2,2,3, 4, 5, 6, 6, 6};
const UInt32 kDistLimit2 = 0x101 - 1;
const UInt32 kDistLimit3 = 0x2000 - 1;
const UInt32 kDistLimit4 = 0x40000 - 1;
const UInt32 kMatchMaxLen = 255 + 2;
const UInt32 kMatchMaxLenMax = 255 + 5;
const UInt32 kNormalMatchMinLen = 3;
}}
#endif

View File

@@ -0,0 +1,319 @@
// Rar20Decoder.cpp
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#include "StdAfx.h"
#include "Rar20Decoder.h"
#include "Rar20Const.h"
namespace NCompress {
namespace NRar20 {
class CException
{
public:
enum ECauseType
{
kData
} Cause;
CException(ECauseType cause): Cause(cause) {}
};
static const char *kNumberErrorMessage = "Number error";
static const UInt32 kHistorySize = 1 << 20;
static const int kNumStats = 11;
static const UInt32 kWindowReservSize = (1 << 22) + 256;
CDecoder::CDecoder():
m_IsSolid(false)
{
}
void CDecoder::InitStructures()
{
m_Predictor.Init();
for(int i = 0; i < kNumRepDists; i++)
m_RepDists[i] = 0;
m_RepDistPtr = 0;
m_LastLength = 0;
memset(m_LastLevels, 0, kMaxTableSize);
}
#define RIF(x) { if (!(x)) return false; }
bool CDecoder::ReadTables(void)
{
Byte levelLevels[kLevelTableSize];
Byte newLevels[kMaxTableSize];
m_AudioMode = (m_InBitStream.ReadBits(1) == 1);
if (m_InBitStream.ReadBits(1) == 0)
memset(m_LastLevels, 0, kMaxTableSize);
int numLevels;
if (m_AudioMode)
{
m_NumChannels = m_InBitStream.ReadBits(2) + 1;
if (m_Predictor.CurrentChannel >= m_NumChannels)
m_Predictor.CurrentChannel = 0;
numLevels = m_NumChannels * kMMTableSize;
}
else
numLevels = kHeapTablesSizesSum;
int i;
for (i = 0; i < kLevelTableSize; i++)
levelLevels[i] = Byte(m_InBitStream.ReadBits(4));
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
i = 0;
while (i < numLevels)
{
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number < kTableDirectLevels)
{
newLevels[i] = Byte((number + m_LastLevels[i]) & kLevelMask);
i++;
}
else
{
if (number == kTableLevelRepNumber)
{
int t = m_InBitStream.ReadBits(2) + 3;
for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)
newLevels[i] = newLevels[i - 1];
}
else
{
int num;
if (number == kTableLevel0Number)
num = m_InBitStream.ReadBits(3) + 3;
else if (number == kTableLevel0Number2)
num = m_InBitStream.ReadBits(7) + 11;
else
return false;
for (;num > 0 && i < numLevels; num--)
newLevels[i++] = 0;
}
}
}
if (m_AudioMode)
for (i = 0; i < m_NumChannels; i++)
{
RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize]));
}
else
{
RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));
RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));
RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));
}
memcpy(m_LastLevels, newLevels, kMaxTableSize);
return true;
}
bool CDecoder::ReadLastTables()
{
// it differs a little from pure RAR sources;
// UInt64 ttt = m_InBitStream.GetProcessedSize() + 2;
// + 2 works for: return 0xFF; in CInBuffer::ReadByte.
if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect;
// if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
if (m_AudioMode)
{
UInt32 symbol = m_MMDecoders[m_Predictor.CurrentChannel].DecodeSymbol(&m_InBitStream);
if (symbol == 256)
return ReadTables();
if (symbol >= kMMTableSize)
return false;
}
else
{
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number == kReadTableNumber)
return ReadTables();
if (number >= kMainTableSize)
return false;
}
return true;
}
class CCoderReleaser
{
CDecoder *m_Coder;
public:
CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
~CCoderReleaser()
{
m_Coder->ReleaseStreams();
}
};
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (inSize == NULL || outSize == NULL)
return E_INVALIDARG;
if (!m_OutWindowStream.Create(kHistorySize))
return E_OUTOFMEMORY;
if (!m_InBitStream.Create(1 << 20))
return E_OUTOFMEMORY;
m_PackSize = *inSize;
UInt64 pos = 0, unPackSize = *outSize;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(m_IsSolid);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
if (!m_IsSolid)
{
InitStructures();
if (unPackSize == 0)
{
if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
if (!ReadTables())
return S_FALSE;
return S_OK;
}
if (!ReadTables())
return S_FALSE;
}
while(pos < unPackSize)
{
if (m_AudioMode)
while(pos < unPackSize)
{
UInt32 symbol = m_MMDecoders[m_Predictor.CurrentChannel].DecodeSymbol(&m_InBitStream);
if (symbol == 256)
{
if (progress != 0)
{
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
if (!ReadTables())
return S_FALSE;
break;
}
if (symbol >= kMMTableSize)
return S_FALSE;
Byte byPredict = m_Predictor.Predict();
Byte byReal = byPredict - Byte(symbol);
m_Predictor.Update(byReal, byPredict);
m_OutWindowStream.PutByte(byReal);
if (++m_Predictor.CurrentChannel == m_NumChannels)
m_Predictor.CurrentChannel = 0;
pos++;
}
else
while(pos < unPackSize)
{
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
UInt32 length, distance;
if (number < 256)
{
m_OutWindowStream.PutByte(Byte(number));
pos++;
continue;
}
else if (number >= kMatchNumber)
{
number -= kMatchNumber;
length = kNormalMatchMinLen + UInt32(kLenStart[number]) +
m_InBitStream.ReadBits(kLenDirectBits[number]);
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
if (number >= kDistTableSize)
return S_FALSE;
distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
if (distance >= kDistLimit3)
{
length += 2 - ((distance - kDistLimit4) >> 31);
// length++;
// if (distance >= kDistLimit4)
// length++;
}
}
else if (number == kRepBothNumber)
{
length = m_LastLength;
distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];
}
else if (number < kLen2Number)
{
distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3];
number = m_LenDecoder.DecodeSymbol(&m_InBitStream);
if (number >= kLenTableSize)
return S_FALSE;
length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);
if (distance >= kDistLimit2)
{
length++;
if (distance >= kDistLimit3)
{
length += 2 - ((distance - kDistLimit4) >> 31);
// length++;
// if (distance >= kDistLimit4)
// length++;
}
}
}
else if (number < kReadTableNumber)
{
number -= kLen2Number;
distance = kLen2DistStarts[number] +
m_InBitStream.ReadBits(kLen2DistDirectBits[number]);
length = 2;
}
else if (number == kReadTableNumber)
{
if (progress != 0)
{
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
if (!ReadTables())
return S_FALSE;
break;
}
else
return S_FALSE;
CopyBackBlockOp(distance, length);
pos += length;
}
}
if (pos > unPackSize)
throw CException(CException::kData);
if (!ReadLastTables())
return S_FALSE;
return m_OutWindowStream.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 CLZOutWindowException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
m_IsSolid = (data[0] != 0);
return S_OK;
}
}}

View File

@@ -0,0 +1,95 @@
// Rar20Decoder.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR20_DECODER_H
#define __RAR20_DECODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../LZ/LZOutWindow.h"
#include "../Huffman/HuffmanDecoder.h"
#include "Rar20Multimedia.h"
#include "Rar20Const.h"
namespace NCompress {
namespace NRar20 {
typedef NStream::NMSBF::CDecoder<CInBuffer> CBitDecoder;
const int kNumHuffmanBits = 15;
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
CLZOutWindow m_OutWindowStream;
CBitDecoder m_InBitStream;
NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kMMTableSize> m_MMDecoders[NMultimedia::kNumChanelsMax];
NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
bool m_AudioMode;
NMultimedia::CPredictor m_Predictor;
int m_NumChannels;
UInt32 m_RepDists[kNumRepDists];
UInt32 m_RepDistPtr;
UInt32 m_LastLength;
Byte m_LastLevels[kMaxTableSize];
UInt64 m_PackSize;
bool m_IsSolid;
void InitStructures();
bool ReadTables();
bool ReadLastTables();
void CopyBackBlockOp(UInt32 aDistance, UInt32 aLength)
{
/*
if(m_Position <= aDistance)
throw CDecoderException(CDecoderException::kData);
*/
m_RepDists[m_RepDistPtr++ & 3] = aDistance;
m_LastLength = aLength;
m_OutWindowStream.CopyBlock(aDistance, aLength);
}
public:
CDecoder();
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
}
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);
};
}}
#endif

View File

@@ -0,0 +1,21 @@
// Rar20ExtConst.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR20_EXTCONST_H
#define __RAR20_EXTCONST_H
#include "../../../Common/Types.h"
namespace NCompress {
namespace NRar20 {
const UInt32 kNumRepDists = 4;
const UInt32 kDistTableSize = 48;
const int kMMTableSize = 256 + 1;
}}
#endif

View File

@@ -0,0 +1,128 @@
// Rar20Multimedia.cpp
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#include "StdAfx.h"
#include "Rar20Multimedia.h"
namespace NCompress {
namespace NRar20 {
namespace NMultimedia {
void CAudioVariables::Init()
{
memset(this, 0, sizeof(CAudioVariables));
}
void CPredictor::Init()
{
for(int i = 0; i < kNumChanelsMax; i++)
m_AudioVariablesArray[i].Init();
m_ChannelDelta = 0;
CurrentChannel = 0;
}
Byte CPredictor::Predict()
{
CAudioVariables *v = &m_AudioVariablesArray[CurrentChannel];
v->ByteCount++;
v->D4 = v->D3;
v->D3 = v->D2;
v->D2 = v->LastDelta-v->D1;
v->D1 = v->LastDelta;
int pCh = 8 * v->LastChar +
v->K1 * v->D1 +
v->K2 * v->D2 +
v->K3 * v->D3 +
v->K4 * v->D4 +
v->K5*m_ChannelDelta;
pCh = (pCh >> 3) & 0xFF;
return Byte(pCh);
}
void CPredictor::Update(Byte realValue, int predictedValue)
{
struct CAudioVariables *v = &m_AudioVariablesArray[CurrentChannel];
int delta = predictedValue - realValue;
int i = ((signed char)delta) << 3;
v->Dif[0] += abs(i);
v->Dif[1] += abs(i - v->D1);
v->Dif[2] += abs(i + v->D1);
v->Dif[3] += abs(i - v->D2);
v->Dif[4] += abs(i + v->D2);
v->Dif[5] += abs(i - v->D3);
v->Dif[6] += abs(i + v->D3);
v->Dif[7] += abs(i - v->D4);
v->Dif[8] += abs(i + v->D4);
v->Dif[9] += abs(i - m_ChannelDelta);
v->Dif[10] += abs(i + m_ChannelDelta);
m_ChannelDelta = v->LastDelta = (signed char)(realValue - v->LastChar);
v->LastChar = realValue;
UInt32 numMinDif, minDif;
if ((v->ByteCount & 0x1F)==0)
{
minDif = v->Dif[0];
numMinDif = 0;
v->Dif[0] = 0;
for (i = 1; i < sizeof(v->Dif) / sizeof(v->Dif[0]); i++)
{
if (v->Dif[i] < minDif)
{
minDif = v->Dif[i];
numMinDif = i;
}
v->Dif[i] = 0;
}
switch(numMinDif)
{
case 1:
if (v->K1 >= -16)
v->K1--;
break;
case 2:
if (v->K1 < 16)
v->K1++;
break;
case 3:
if (v->K2 >= -16)
v->K2--;
break;
case 4:
if (v->K2 < 16)
v->K2++;
break;
case 5:
if (v->K3 >= -16)
v->K3--;
break;
case 6:
if (v->K3 < 16)
v->K3++;
break;
case 7:
if (v->K4 >= -16)
v->K4--;
break;
case 8:
if (v->K4 < 16)
v->K4++;
break;
case 9:
if (v->K5 >= -16)
v->K5--;
break;
case 10:
if (v->K5 < 16)
v->K5++;
break;
}
}
}
}}}

View File

@@ -0,0 +1,43 @@
// Rar20Multimedia.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR20_MULTIMEDIA_H
#define __RAR20_MULTIMEDIA_H
#include "../../../Common/Types.h"
namespace NCompress {
namespace NRar20 {
namespace NMultimedia {
struct CAudioVariables
{
int K1,K2,K3,K4,K5;
int D1,D2,D3,D4;
int LastDelta;
UInt32 Dif[11];
UInt32 ByteCount;
int LastChar;
void Init();
};
const int kNumChanelsMax = 4;
class CPredictor
{
CAudioVariables m_AudioVariablesArray[kNumChanelsMax];
int m_ChannelDelta;
public:
int CurrentChannel;
void Init();
Byte Predict();
void Update(Byte realValue, int predictedValue);
};
}}}
#endif

3
7zip/Compress/Rar20/StdAfx.cpp Executable file
View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

8
7zip/Compress/Rar20/StdAfx.h Executable file
View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif