4.44 beta

This commit is contained in:
Igor Pavlov
2007-01-20 00:00:00 +00:00
committed by Kornel Lesiński
parent 804edc5756
commit d9666cf046
1331 changed files with 10535 additions and 13791 deletions

View File

@@ -0,0 +1,91 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "Rar1Decoder.h"
#include "Rar2Decoder.h"
#include "Rar3Decoder.h"
// #include "Rar29Decoder.h"
#define RarClassId(ver) CLSID_CCompressRar ## ver ## Decoder
#define MyClassRar(ver) DEFINE_GUID(RarClassId(ver), \
0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, ver, 0x00, 0x00, 0x00, 0x00, 0x00);
MyClassRar(1);
MyClassRar(2);
MyClassRar(3);
#define CreateCoder(ver) if (*clsid == RarClassId(ver)) \
{ if (!correctInterface) return E_NOINTERFACE; \
coder = (ICompressCoder *)new NCompress::NRar ## ver::CDecoder; }
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;
int correctInterface = (*iid == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
CreateCoder(1) else
CreateCoder(2) else
CreateCoder(3) else
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = coder.Detach();
COM_TRY_END
return S_OK;
}
struct CRarMethodItem
{
char ID[3];
const wchar_t *UserName;
const GUID *Decoder;
};
static CRarMethodItem g_Methods[] =
{
{ { 0x04, 0x03, 0x01 }, L"Rar15", &RarClassId(1) },
{ { 0x04, 0x03, 0x02 }, L"Rar20", &RarClassId(2) },
{ { 0x04, 0x03, 0x03 }, L"Rar29", &RarClassId(3) }
};
STDAPI GetNumberOfMethods(UINT32 *numMethods)
{
*numMethods = sizeof(g_Methods) / sizeof(g_Methods[1]);
return S_OK;
}
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
if (index > sizeof(g_Methods) / sizeof(g_Methods[1]))
return E_INVALIDARG;
VariantClear((tagVARIANT *)value);
const CRarMethodItem &method = g_Methods[index];
switch(propID)
{
case NMethodPropID::kID:
if ((value->bstrVal = ::SysAllocStringByteLen(method.ID,
sizeof(method.ID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(method.UserName)) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)method.Decoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
return S_OK;
}

View File

@@ -0,0 +1,485 @@
// Rar1Decoder.cpp
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#include "StdAfx.h"
#include "Rar1Decoder.h"
namespace NCompress {
namespace NRar1 {
static UInt32 PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32, 256};
static UInt32 PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36, 256};
static UInt32 PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33, 257};
static UInt32 PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127, 257};
static UInt32 PosHf2[]={0,0,0,0,0,0,2,7,53,117,233, 257,0};
static UInt32 PosHf3[]={0,0,0,0,0,0,0,2,16,218,251, 257,0};
static UInt32 PosHf4[]={0,0,0,0,0,0,0,0,0,255, 257,0,0};
static const UInt32 kHistorySize = (1 << 16);
class CCoderReleaser
{
CDecoder *m_Coder;
public:
CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
~CCoderReleaser() { m_Coder->ReleaseStreams(); }
};
CDecoder::CDecoder(): m_IsSolid(false) { }
void CDecoder::InitStructures()
{
for(int i = 0; i < kNumRepDists; i++)
m_RepDists[i] = 0;
m_RepDistPtr = 0;
LastLength = 0;
LastDist = 0;
}
UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
HRESULT CDecoder::CopyBlock(UInt32 distance, UInt32 len)
{
m_UnpackSize -= len;
return m_OutWindowStream.CopyBlock(distance, len) ? S_OK : S_FALSE;
}
UInt32 CDecoder::DecodeNum(const UInt32 *posTab)
{
UInt32 startPos = 2;
UInt32 num = m_InBitStream.GetValue(12);
for (;;)
{
UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - startPos);
if (num < cur)
break;
startPos++;
num -= cur;
}
m_InBitStream.MovePos(startPos);
return((num >> (12 - startPos)) + posTab[startPos]);
}
static Byte kShortLen1[] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 };
static Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 };
static Byte kShortLen2[] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 };
static Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 };
static UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
static UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
HRESULT CDecoder::ShortLZ()
{
UInt32 len, saveLen, dist;
int distancePlace;
Byte *kShortLen;
const UInt32 *kShortXor;
NumHuf = 0;
if (LCount == 2)
{
if (ReadBits(1))
return CopyBlock(LastDist, LastLength);
LCount = 0;
}
UInt32 bitField = m_InBitStream.GetValue(8);
if (AvrLn1 < 37)
{
kShortLen = Buf60 ? kShortLen1a : kShortLen1;
kShortXor = kShortXor1;
}
else
{
kShortLen = Buf60 ? kShortLen2a : kShortLen2;
kShortXor = kShortXor2;
}
for (len = 0; ((bitField ^ kShortXor[len]) & (~(0xff >> kShortLen[len]))) != 0; len++);
m_InBitStream.MovePos(kShortLen[len]);
if (len >= 9)
{
if (len == 9)
{
LCount++;
return CopyBlock(LastDist, LastLength);
}
if (len == 14)
{
LCount = 0;
len = DecodeNum(PosL2) + 5;
dist = 0x8000 + ReadBits(15) - 1;
LastLength = len;
LastDist = dist;
return CopyBlock(dist, len);
}
LCount = 0;
saveLen = len;
dist = m_RepDists[(m_RepDistPtr - (len - 9)) & 3];
len = DecodeNum(PosL1) + 2;
if (len == 0x101 && saveLen == 10)
{
Buf60 ^= 1;
return S_OK;
}
if (dist >= 256)
len++;
if (dist >= MaxDist3 - 1)
len++;
}
else
{
LCount = 0;
AvrLn1 += len;
AvrLn1 -= AvrLn1 >> 4;
distancePlace = DecodeNum(PosHf2) & 0xff;
dist = ChSetA[distancePlace];
if (--distancePlace != -1)
{
PlaceA[dist]--;
UInt32 lastDistance = ChSetA[distancePlace];
PlaceA[lastDistance]++;
ChSetA[distancePlace + 1] = lastDistance;
ChSetA[distancePlace] = dist;
}
len += 2;
}
m_RepDists[m_RepDistPtr++] = dist;
m_RepDistPtr &= 3;
LastLength = len;
LastDist = dist;
return CopyBlock(dist, len);
}
HRESULT CDecoder::LongLZ()
{
UInt32 len;
UInt32 dist;
UInt32 distancePlace, newDistancePlace;
UInt32 oldAvr2, oldAvr3;
NumHuf = 0;
Nlzb += 16;
if (Nlzb > 0xff)
{
Nlzb = 0x90;
Nhfb >>= 1;
}
oldAvr2=AvrLn2;
if (AvrLn2 >= 122)
len = DecodeNum(PosL2);
else if (AvrLn2 >= 64)
len = DecodeNum(PosL1);
else
{
UInt32 bitField = m_InBitStream.GetValue(16);
if (bitField < 0x100)
{
len = bitField;
m_InBitStream.MovePos(16);
}
else
{
for (len = 0; ((bitField << len) & 0x8000) == 0; len++)
;
m_InBitStream.MovePos(len + 1);
}
}
AvrLn2 += len;
AvrLn2 -= AvrLn2 >> 5;
if (AvrPlcB > 0x28ff)
distancePlace = DecodeNum(PosHf2);
else if (AvrPlcB > 0x6ff)
distancePlace = DecodeNum(PosHf1);
else
distancePlace = DecodeNum(PosHf0);
AvrPlcB += distancePlace;
AvrPlcB -= AvrPlcB >> 8;
for (;;)
{
dist = ChSetB[distancePlace & 0xff];
newDistancePlace = NToPlB[dist++ & 0xff]++;
if (!(dist & 0xff))
CorrHuff(ChSetB,NToPlB);
else
break;
}
ChSetB[distancePlace] = ChSetB[newDistancePlace];
ChSetB[newDistancePlace] = dist;
dist = ((dist & 0xff00) >> 1) | ReadBits(7);
oldAvr3 = AvrLn3;
if (len != 1 && len != 4)
if (len == 0 && dist <= MaxDist3)
{
AvrLn3++;
AvrLn3 -= AvrLn3 >> 8;
}
else
if (AvrLn3 > 0)
AvrLn3--;
len += 3;
if (dist >= MaxDist3)
len++;
if (dist <= 256)
len += 8;
if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40)
MaxDist3 = 0x7f00;
else
MaxDist3 = 0x2001;
m_RepDists[m_RepDistPtr++] = --dist;
m_RepDistPtr &= 3;
LastLength = len;
LastDist = dist;
return CopyBlock(dist, len);
}
HRESULT CDecoder::HuffDecode()
{
UInt32 curByte, newBytePlace;
UInt32 len;
UInt32 dist;
int bytePlace;
if (AvrPlc > 0x75ff) bytePlace = DecodeNum(PosHf4);
else if (AvrPlc > 0x5dff) bytePlace = DecodeNum(PosHf3);
else if (AvrPlc > 0x35ff) bytePlace = DecodeNum(PosHf2);
else if (AvrPlc > 0x0dff) bytePlace = DecodeNum(PosHf1);
else bytePlace = DecodeNum(PosHf0);
if (StMode)
{
if (--bytePlace == -1)
{
if (ReadBits(1))
{
NumHuf = StMode = 0;
return S_OK;
}
else
{
len = (ReadBits(1)) ? 4 : 3;
dist = DecodeNum(PosHf2);
dist = (dist << 5) | ReadBits(5);
return CopyBlock(dist - 1, len);
}
}
}
else if (NumHuf++ >= 16 && FlagsCnt == 0)
StMode = 1;
bytePlace &= 0xff;
AvrPlc += bytePlace;
AvrPlc -= AvrPlc >> 8;
Nhfb+=16;
if (Nhfb > 0xff)
{
Nhfb=0x90;
Nlzb >>= 1;
}
m_UnpackSize --;
m_OutWindowStream.PutByte((Byte)(ChSet[bytePlace] >> 8));
for (;;)
{
curByte = ChSet[bytePlace];
newBytePlace = NToPl[curByte++ & 0xff]++;
if ((curByte & 0xff) > 0xa1)
CorrHuff(ChSet, NToPl);
else
break;
}
ChSet[bytePlace] = ChSet[newBytePlace];
ChSet[newBytePlace] = curByte;
return S_OK;
}
void CDecoder::GetFlagsBuf()
{
UInt32 flags, newFlagsPlace;
UInt32 flagsPlace = DecodeNum(PosHf2);
for (;;)
{
flags = ChSetC[flagsPlace];
FlagBuf = flags >> 8;
newFlagsPlace = NToPlC[flags++ & 0xff]++;
if ((flags & 0xff) != 0)
break;
CorrHuff(ChSetC, NToPlC);
}
ChSetC[flagsPlace] = ChSetC[newFlagsPlace];
ChSetC[newFlagsPlace] = flags;
}
void CDecoder::InitData()
{
if (!m_IsSolid)
{
AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;
AvrPlc = 0x3500;
MaxDist3 = 0x2001;
Nhfb = Nlzb = 0x80;
}
FlagsCnt = 0;
FlagBuf = 0;
StMode = 0;
LCount = 0;
}
void CDecoder::CorrHuff(UInt32 *CharSet,UInt32 *NumToPlace)
{
int i;
for (i = 7; i >= 0; i--)
for (int j = 0; j < 32; j++, CharSet++)
*CharSet = (*CharSet & ~0xff) | i;
memset(NumToPlace, 0, sizeof(NToPl));
for (i = 6; i >= 0; i--)
NumToPlace[i] = (7 - i) * 32;
}
void CDecoder::InitHuff()
{
for (UInt32 i = 0; i < 256; i++)
{
Place[i] = PlaceA[i] = PlaceB[i] = i;
PlaceC[i] = (~i + 1) & 0xff;
ChSet[i] = ChSetB[i] = i << 8;
ChSetA[i] = i;
ChSetC[i] = ((~i + 1) & 0xff) << 8;
}
memset(NToPl, 0, sizeof(NToPl));
memset(NToPlB, 0, sizeof(NToPlB));
memset(NToPlC, 0, sizeof(NToPlC));
CorrHuff(ChSetB, NToPlB);
}
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_UnpackSize = (Int64)*outSize;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(m_IsSolid);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
InitData();
if (!m_IsSolid)
{
InitStructures();
InitHuff();
}
if (m_UnpackSize > 0)
{
GetFlagsBuf();
FlagsCnt = 8;
}
while (m_UnpackSize > 0)
{
if (StMode)
{
RINOK(HuffDecode());
continue;
}
if (--FlagsCnt < 0)
{
GetFlagsBuf();
FlagsCnt=7;
}
if (FlagBuf & 0x80)
{
FlagBuf <<= 1;
if (Nlzb > Nhfb)
{
RINOK(LongLZ());
}
else
{
RINOK(HuffDecode());
}
}
else
{
FlagBuf <<= 1;
if (--FlagsCnt < 0)
{
GetFlagsBuf();
FlagsCnt = 7;
}
if (FlagBuf & 0x80)
{
FlagBuf <<= 1;
if (Nlzb > Nhfb)
{
RINOK(HuffDecode());
}
else
{
RINOK(LongLZ());
}
}
else
{
FlagBuf <<= 1;
RINOK(ShortLZ());
}
}
}
if (m_UnpackSize < 0)
return S_FALSE;
return m_OutWindowStream.Flush();
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try
{
HRESULT res = CodeReal(inStream, outStream, inSize, outSize, progress);
m_OutWindowStream.Flush();
return res;
}
catch(const CLZOutWindowException &e) { m_OutWindowStream.Flush(); return e.ErrorCode; }
catch(...) { m_OutWindowStream.Flush(); 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,90 @@
// Rar15Decoder.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR10_DECODER_H
#define __RAR10_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"
namespace NCompress {
namespace NRar1 {
const UInt32 kNumRepDists = 4;
typedef NStream::NMSBF::CDecoder<CInBuffer> CBitDecoder;
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
public:
CLZOutWindow m_OutWindowStream;
CBitDecoder m_InBitStream;
UInt32 m_RepDists[kNumRepDists];
UInt32 m_RepDistPtr;
UInt32 LastDist;
UInt32 LastLength;
Int64 m_UnpackSize;
bool m_IsSolid;
UInt32 ReadBits(int numBits);
HRESULT CopyBlock(UInt32 distance, UInt32 len);
UInt32 DecodeNum(const UInt32 *posTab);
HRESULT ShortLZ();
HRESULT LongLZ();
HRESULT HuffDecode();
void GetFlagsBuf();
void InitData();
void InitHuff();
void CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace);
void OldUnpWriteBuf();
UInt32 ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
UInt32 Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
UInt32 NToPl[256],NToPlB[256],NToPlC[256];
UInt32 FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
int Buf60,NumHuf,StMode,LCount,FlagsCnt;
UInt32 Nhfb,Nlzb,MaxDist3;
void InitStructures();
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

297
CPP/7zip/Compress/Rar/Rar29.dsp Executable file
View File

@@ -0,0 +1,297 @@
# Microsoft Developer Studio Project File - Name="Rar29" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Rar29 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Rar29.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Rar29.mak" CFG="Rar29 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Rar29 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Rar29 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "Rar29 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR29_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR29_EXPORTS" /D "SILENT" /D "NOCRYPT" /D "NOVOLUME" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\Rar29.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Rar29 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR29_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR29_EXPORTS" /D "SILENT" /D "NOCRYPT" /D "NOVOLUME" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\Rar29.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Rar29 - Win32 Release"
# Name "Rar29 - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Codec.def
# End Source File
# Begin Source File
SOURCE=.\DllExports.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"StdAfx.h"
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "7zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\InBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MSBFDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.h
# End Source File
# End Group
# Begin Group "LZ"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\LZOutWindow.cpp
# End Source File
# Begin Source File
SOURCE=..\LZ\LZOutWindow.h
# End Source File
# End Group
# Begin Group "Huffman"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Huffman\HuffmanDecoder.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Alloc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Alloc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Vector.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Vector.h
# End Source File
# End Group
# Begin Group "Rar3"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\PPMD\PPMDContext.h
# End Source File
# Begin Source File
SOURCE=..\PPMD\PPMDDecode.h
# End Source File
# Begin Source File
SOURCE=..\PPMD\PPMDSubAlloc.h
# End Source File
# Begin Source File
SOURCE=..\PPMD\PPMDType.h
# End Source File
# Begin Source File
SOURCE=.\Rar1Decoder.cpp
!IF "$(CFG)" == "Rar29 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Rar29 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Rar1Decoder.h
# End Source File
# Begin Source File
SOURCE=.\Rar2Decoder.cpp
!IF "$(CFG)" == "Rar29 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Rar29 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Rar2Decoder.h
# End Source File
# Begin Source File
SOURCE=.\Rar3Decoder.cpp
!IF "$(CFG)" == "Rar29 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Rar29 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Rar3Decoder.h
# End Source File
# Begin Source File
SOURCE=.\Rar3Vm.cpp
!IF "$(CFG)" == "Rar29 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Rar29 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Rar3Vm.h
# End Source File
# End Group
# End Target
# End Project

29
CPP/7zip/Compress/Rar/Rar29.dsw Executable file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Rar29"=.\Rar29.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,401 @@
// Rar2Decoder.cpp
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#include "StdAfx.h"
#include "Rar2Decoder.h"
namespace NCompress {
namespace NRar2 {
namespace NMultimedia {
Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
{
D4 = D3;
D3 = D2;
D2 = LastDelta - D1;
D1 = LastDelta;
int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);
Byte realValue = (Byte)(predictedValue - deltaByte);
int i = ((int)(signed char)deltaByte) << 3;
Dif[0] += abs(i);
Dif[1] += abs(i - D1);
Dif[2] += abs(i + D1);
Dif[3] += abs(i - D2);
Dif[4] += abs(i + D2);
Dif[5] += abs(i - D3);
Dif[6] += abs(i + D3);
Dif[7] += abs(i - D4);
Dif[8] += abs(i + D4);
Dif[9] += abs(i - channelDelta);
Dif[10] += abs(i + channelDelta);
channelDelta = LastDelta = (signed char)(realValue - LastChar);
LastChar = realValue;
if (((++ByteCount) & 0x1F) == 0)
{
UInt32 minDif = Dif[0];
UInt32 numMinDif = 0;
Dif[0] = 0;
for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++)
{
if (Dif[i] < minDif)
{
minDif = Dif[i];
numMinDif = i;
}
Dif[i] = 0;
}
switch(numMinDif)
{
case 1: if (K1 >= -16) K1--; break;
case 2: if (K1 < 16) K1++; break;
case 3: if (K2 >= -16) K2--; break;
case 4: if (K2 < 16) K2++; break;
case 5: if (K3 >= -16) K3--; break;
case 6: if (K3 < 16) K3++; break;
case 7: if (K4 >= -16) K4--; break;
case 8: if (K4 < 16) K4++; break;
case 9: if (K5 >= -16) K5--; break;
case 10:if (K5 < 16) K5++; break;
}
}
return realValue;
}
}
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_MmFilter.Init();
for(int i = 0; i < kNumRepDists; i++)
m_RepDists[i] = 0;
m_RepDistPtr = 0;
m_LastLength = 0;
memset(m_LastLevels, 0, kMaxTableSize);
}
UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
#define RIF(x) { if (!(x)) return false; }
bool CDecoder::ReadTables(void)
{
Byte levelLevels[kLevelTableSize];
Byte newLevels[kMaxTableSize];
m_AudioMode = (ReadBits(1) == 1);
if (ReadBits(1) == 0)
memset(m_LastLevels, 0, kMaxTableSize);
int numLevels;
if (m_AudioMode)
{
m_NumChannels = ReadBits(2) + 1;
if (m_MmFilter.CurrentChannel >= m_NumChannels)
m_MmFilter.CurrentChannel = 0;
numLevels = m_NumChannels * kMMTableSize;
}
else
numLevels = kHeapTablesSizesSum;
int i;
for (i = 0; i < kLevelTableSize; i++)
levelLevels[i] = (Byte)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 = 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 = ReadBits(3) + 3;
else if (number == kTableLevel0Number2)
num = 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_MmFilter.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();
}
};
bool CDecoder::DecodeMm(UInt32 pos)
{
while (pos-- > 0)
{
UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream);
if (symbol == 256)
return true;
if (symbol >= kMMTableSize)
return false;
/*
Byte byPredict = m_Predictor.Predict();
Byte byReal = (Byte)(byPredict - (Byte)symbol);
m_Predictor.Update(byReal, byPredict);
*/
Byte byReal = m_MmFilter.Decode((Byte)symbol);
m_OutWindowStream.PutByte(byReal);
if (++m_MmFilter.CurrentChannel == m_NumChannels)
m_MmFilter.CurrentChannel = 0;
}
return true;
}
bool CDecoder::DecodeLz(Int32 pos)
{
while (pos > 0)
{
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 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 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)
return true;
else
return false;
m_RepDists[m_RepDistPtr++ & 3] = distance;
m_LastLength = length;
if (!m_OutWindowStream.CopyBlock(distance, length))
return false;
pos -= length;
}
return true;
}
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;
}
UInt64 startPos = m_OutWindowStream.GetProcessedSize();
while(pos < unPackSize)
{
UInt32 blockSize = 1 << 20;
if (blockSize > unPackSize - pos)
blockSize = (UInt32)(unPackSize - pos);
UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize();
if (m_AudioMode)
{
if (!DecodeMm(blockSize))
return S_FALSE;
}
else
{
if (!DecodeLz((Int32)blockSize))
return S_FALSE;
}
UInt64 globalPos = m_OutWindowStream.GetProcessedSize();
pos = globalPos - blockStartPos;
if (pos < blockSize)
if (!ReadTables())
return S_FALSE;
pos = globalPos - startPos;
if (progress != 0)
{
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
}
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,176 @@
// Rar2Decoder.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR2DECODER_H
#define __RAR2DECODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../LZ/LZOutWindow.h"
#include "../Huffman/HuffmanDecoder.h"
namespace NCompress {
namespace NRar2 {
const UInt32 kNumRepDists = 4;
const UInt32 kDistTableSize = 48;
const int kMMTableSize = 256 + 1;
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;
namespace NMultimedia {
struct CFilter
{
int K1,K2,K3,K4,K5;
int D1,D2,D3,D4;
int LastDelta;
UInt32 Dif[11];
UInt32 ByteCount;
int LastChar;
Byte Decode(int &channelDelta, Byte delta);
void Init() { memset(this, 0, sizeof(*this)); }
};
const int kNumChanelsMax = 4;
class CFilter2
{
public:
CFilter m_Filters[kNumChanelsMax];
int m_ChannelDelta;
int CurrentChannel;
void Init() { memset(this, 0, sizeof(*this)); }
Byte Decode(Byte delta)
{
return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta);
}
};
}
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::CFilter2 m_MmFilter;
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();
UInt32 ReadBits(int numBits);
bool ReadTables();
bool ReadLastTables();
bool DecodeMm(UInt32 pos);
bool DecodeLz(Int32 pos);
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,832 @@
// Rar3Decoder.cpp
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#include "StdAfx.h"
#include "Rar3Decoder.h"
#include "../../Common/StreamUtils.h"
namespace NCompress {
namespace NRar3 {
static const UInt32 kNumAlignReps = 15;
static const UInt32 kSymbolReadTable = 256;
static const UInt32 kSymbolRep = 259;
static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps;
static 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};
static 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};
static 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,
18,18,18,18,18,18,18,18,18,18,18,18};
static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192};
static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6};
static const UInt32 kDistLimit3 = 0x2000 - 2;
static const UInt32 kDistLimit4 = 0x40000 - 2;
static const UInt32 kNormalMatchMinLen = 3;
static const UInt32 kVmDataSizeMax = 1 << 16;
static const UInt32 kVmCodeSizeMax = 1 << 16;
CDecoder::CDecoder():
_window(0),
_winPos(0),
_wrPtr(0),
_lzSize(0),
_writtenFileSize(0),
_vmData(0),
_vmCode(0),
m_IsSolid(false)
{
}
CDecoder::~CDecoder()
{
InitFilters();
if (_vmData)
::MidFree(_vmData);
}
HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
{
UInt32 processedSize;
HRESULT res = WriteStream(_outStream, data, size, &processedSize);
if (res == S_OK && processedSize != size)
res = E_FAIL;
return res;
}
HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)
{
HRESULT res = S_OK;
if (_writtenFileSize < _unpackSize)
{
UInt32 curSize = size;
UInt64 remain = _unpackSize - _writtenFileSize;
if (remain < curSize)
curSize = (UInt32)remain;
res = WriteDataToStream(data, curSize);
}
_writtenFileSize += size;
return res;
}
HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)
{
if (startPtr <= endPtr)
return WriteData(_window + startPtr, endPtr - startPtr);
RINOK(WriteData(_window + startPtr, kWindowSize - startPtr));
return WriteData(_window, endPtr);
}
void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
{
CTempFilter *tempFilter = _tempFilters[tempFilterIndex];
tempFilter->InitR[6] = (UInt32)_writtenFileSize;
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
CFilter *filter = _filters[tempFilter->FilterIndex];
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
delete tempFilter;
_tempFilters[tempFilterIndex] = 0;
}
HRESULT CDecoder::WriteBuf()
{
UInt32 writtenBorder = _wrPtr;
UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;
for (int i = 0; i < _tempFilters.Size(); i++)
{
CTempFilter *filter = _tempFilters[i];
if (filter == NULL)
continue;
if (filter->NextWindow)
{
filter->NextWindow = false;
continue;
}
UInt32 blockStart = filter->BlockStart;
UInt32 blockSize = filter->BlockSize;
if (((blockStart - writtenBorder) & kWindowMask) < writeSize)
{
if (writtenBorder != blockStart)
{
RINOK(WriteArea(writtenBorder, blockStart));
writtenBorder = blockStart;
writeSize = (_winPos - writtenBorder) & kWindowMask;
}
if (blockSize <= writeSize)
{
UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;
if (blockStart < blockEnd || blockEnd == 0)
_vm.SetMemory(0, _window + blockStart, blockSize);
else
{
UInt32 tailSize = kWindowSize - blockStart;
_vm.SetMemory(0, _window + blockStart, tailSize);
_vm.SetMemory(tailSize, _window, blockEnd);
}
NVm::CBlockRef outBlockRef;
ExecuteFilter(i, outBlockRef);
while (i + 1 < _tempFilters.Size())
{
CTempFilter *nextFilter = _tempFilters[i + 1];
if (nextFilter == NULL || nextFilter->BlockStart != blockStart ||
nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow)
break;
_vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
ExecuteFilter(++i, outBlockRef);
}
WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
_writtenFileSize += outBlockRef.Size;
writtenBorder = blockEnd;
writeSize = (_winPos - writtenBorder) & kWindowMask;
}
else
{
for (int j = i; j < _tempFilters.Size(); j++)
{
CTempFilter *filter = _tempFilters[j];
if (filter != NULL && filter->NextWindow)
filter->NextWindow = false;
}
_wrPtr = writtenBorder;
return S_OK; // check it
}
}
}
_wrPtr = _winPos;
return WriteArea(writtenBorder, _winPos);
}
void CDecoder::InitFilters()
{
_lastFilter = 0;
int i;
for (i = 0; i < _tempFilters.Size(); i++)
delete _tempFilters[i];
_tempFilters.Clear();
for (i = 0; i < _filters.Size(); i++)
delete _filters[i];
_filters.Clear();
}
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
{
CMemBitDecoder inp;
inp.Init(_vmData, codeSize);
UInt32 filterIndex;
if (firstByte & 0x80)
{
filterIndex = NVm::ReadEncodedUInt32(inp);
if (filterIndex == 0)
InitFilters();
else
filterIndex--;
}
else
filterIndex = _lastFilter;
if (filterIndex > (UInt32)_filters.Size())
return false;
_lastFilter = filterIndex;
bool newFilter = (filterIndex == (UInt32)_filters.Size());
CFilter *filter;
if (newFilter)
{
// check if too many filters
if (filterIndex > 1024)
return false;
filter = new CFilter;
_filters.Add(filter);
}
else
{
filter = _filters[filterIndex];
filter->ExecCount++;
}
int numEmptyItems = 0;
int i;
for (i = 0; i < _tempFilters.Size(); i++)
{
_tempFilters[i - numEmptyItems] = _tempFilters[i];
if (_tempFilters[i] == NULL)
numEmptyItems++;
if (numEmptyItems > 0)
_tempFilters[i] = NULL;
}
if (numEmptyItems == 0)
{
_tempFilters.Add(NULL);
numEmptyItems = 1;
}
CTempFilter *tempFilter = new CTempFilter;
_tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter;
tempFilter->FilterIndex = filterIndex;
tempFilter->ExecCount = filter->ExecCount;
UInt32 blockStart = NVm::ReadEncodedUInt32(inp);
if (firstByte & 0x40)
blockStart += 258;
tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;
if (firstByte & 0x20)
filter->BlockSize = NVm::ReadEncodedUInt32(inp);
tempFilter->BlockSize = filter->BlockSize;
tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;
memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));
tempFilter->InitR[3] = NVm::kGlobalOffset;
tempFilter->InitR[4] = tempFilter->BlockSize;
tempFilter->InitR[5] = tempFilter->ExecCount;
if (firstByte & 0x10)
{
UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);
for (int i = 0; i < NVm::kNumGpRegs; i++)
if (initMask & (1 << i))
tempFilter->InitR[i] = NVm::ReadEncodedUInt32(inp);
}
if (newFilter)
{
UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp);
if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)
return false;
for (UInt32 i = 0; i < vmCodeSize; i++)
_vmCode[i] = (Byte)inp.ReadBits(8);
_vm.PrepareProgram(_vmCode, vmCodeSize, filter);
}
tempFilter->AllocateEmptyFixedGlobal();
Byte *globalData = &tempFilter->GlobalData[0];
for (i = 0; i < NVm::kNumGpRegs; i++)
NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);
NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);
NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?
NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], tempFilter->ExecCount);
if (firstByte & 8)
{
UInt32 dataSize = NVm::ReadEncodedUInt32(inp);
if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)
return false;
CRecordVector<Byte> &globalData = tempFilter->GlobalData;
int requredSize = (int)(dataSize + NVm::kFixedGlobalSize);
if (globalData.Size() < requredSize)
{
globalData.Reserve(requredSize);
for (; globalData.Size() < requredSize; i++)
globalData.Add(0);
}
for (UInt32 i = 0; i < dataSize; i++)
globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8);
}
return true;
}
bool CDecoder::ReadVmCodeLZ()
{
UInt32 firstByte = m_InBitStream.ReadBits(8);
UInt32 length = (firstByte & 7) + 1;
if (length == 7)
length = m_InBitStream.ReadBits(8) + 7;
else if (length == 8)
length = m_InBitStream.ReadBits(16);
if (length > kVmDataSizeMax)
return false;
for (UInt32 i = 0; i < length; i++)
_vmData[i] = (Byte)m_InBitStream.ReadBits(8);
return AddVmCode(firstByte, length);
}
bool CDecoder::ReadVmCodePPM()
{
int firstByte = DecodePpmSymbol();
if (firstByte == -1)
return false;
UInt32 length = (firstByte & 7) + 1;
if (length == 7)
{
int b1 = DecodePpmSymbol();
if (b1 == -1)
return false;
length = b1 + 7;
}
else if (length == 8)
{
int b1 = DecodePpmSymbol();
if (b1 == -1)
return false;
int b2 = DecodePpmSymbol();
if (b2 == -1)
return false;
length = b1 * 256 + b2;
}
if (length > kVmDataSizeMax)
return false;
for (UInt32 i = 0; i < length; i++)
{
int b = DecodePpmSymbol();
if (b == -1)
return false;
_vmData[i] = (Byte)b;
}
return AddVmCode(firstByte, length);
}
#define RIF(x) { if (!(x)) return S_FALSE; }
UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
/////////////////////////////////////////////////
// PPM
HRESULT CDecoder::InitPPM()
{
Byte maxOrder = (Byte)ReadBits(7);
bool reset = ((maxOrder & 0x20) != 0);
int maxMB = 0;
if (reset)
maxMB = (Byte)ReadBits(8);
else
{
if (_ppm.SubAllocator.GetSubAllocatorSize()== 0)
return S_FALSE;
}
if (maxOrder & 0x40)
PpmEscChar = (Byte)ReadBits(8);
m_InBitStream.InitRangeCoder();
/*
if (m_InBitStream.m_BitPos != 0)
return S_FALSE;
*/
if (reset)
{
maxOrder = (maxOrder & 0x1F) + 1;
if (maxOrder > 16)
maxOrder = 16 + (maxOrder - 16) * 3;
if (maxOrder == 1)
{
// SubAlloc.StopSubAllocator();
_ppm.SubAllocator.StopSubAllocator();
return S_FALSE;
}
// SubAlloc.StartSubAllocator(MaxMB+1);
// StartModelRare(maxOrder);
if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20))
return E_OUTOFMEMORY;
_ppm.MaxOrder = 0;
_ppm.StartModelRare(maxOrder);
}
// return (minContext != NULL);
return S_OK;
}
int CDecoder::DecodePpmSymbol() { return _ppm.DecodeSymbol(&m_InBitStream); }
HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
{
keepDecompressing = false;
do
{
if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
{
RINOK(WriteBuf());
if (_writtenFileSize > _unpackSize)
return S_OK;
}
int c = DecodePpmSymbol();
if (c == -1)
{
// Original code sets PPMError=true here and then it returns S_OK. Why ???
// return S_OK;
return S_FALSE;
}
if (c == PpmEscChar)
{
int nextCh = DecodePpmSymbol();
if (nextCh == 0)
return ReadTables(keepDecompressing);
if (nextCh == 2 || nextCh == -1)
return S_OK;
if (nextCh == 3)
{
if (!ReadVmCodePPM())
return S_FALSE;
continue;
}
if (nextCh == 4 || nextCh == 5)
{
UInt32 distance = 0;
UInt32 length = 4;
if (nextCh == 4)
{
for (int i = 0; i < 3; i++)
{
int c = DecodePpmSymbol();
if (c == -1)
return S_OK;
distance = (distance << 8) + (Byte)c;
}
distance++;
length += 28;
}
int c = DecodePpmSymbol();
if (c == -1)
return S_OK;
length += c;
if (distance >= _lzSize)
return S_FALSE;
CopyBlock(distance, length);
num -= (Int32)length;
continue;
}
}
PutByte((Byte)c);
num--;
}
while (num >= 0);
keepDecompressing = true;
return S_OK;
}
/////////////////////////////////////////////////
// LZ
HRESULT CDecoder::ReadTables(bool &keepDecompressing)
{
keepDecompressing = true;
ReadBits((8 - m_InBitStream.GetBitPosition()) & 7);
if (ReadBits(1) != 0)
{
_lzMode = false;
return InitPPM();
}
_lzMode = true;
PrevAlignBits = 0;
PrevAlignCount = 0;
Byte levelLevels[kLevelTableSize];
Byte newLevels[kTablesSizesSum];
if (ReadBits(1) == 0)
memset(m_LastLevels, 0, kTablesSizesSum);
int i;
for (i = 0; i < kLevelTableSize; i++)
{
UInt32 length = ReadBits(4);
if (length == 15)
{
UInt32 zeroCount = ReadBits(4);
if (zeroCount != 0)
{
zeroCount += 2;
while (zeroCount-- > 0 && i < kLevelTableSize)
levelLevels[i++]=0;
i--;
continue;
}
}
levelLevels[i] = (Byte)length;
}
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
i = 0;
while (i < kTablesSizesSum)
{
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number < 16)
{
newLevels[i] = Byte((number + m_LastLevels[i]) & 15);
i++;
}
else if (number > kLevelTableSize)
return S_FALSE;
else
{
int num;
if (((number - 16) & 1) == 0)
num = ReadBits(3) + 3;
else
num = ReadBits(7) + 11;
if (number < 18)
{
if (i == 0)
return S_FALSE;
for (; num > 0 && i < kTablesSizesSum; num--, i++)
newLevels[i] = newLevels[i - 1];
}
else
{
for (; num > 0 && i < kTablesSizesSum; num--)
newLevels[i++] = 0;
}
}
}
TablesRead = true;
// original code has check here:
/*
if (InAddr > ReadTop)
{
keepDecompressing = false;
return true;
}
*/
RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));
RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));
RIF(m_AlignDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));
RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize]));
memcpy(m_LastLevels, newLevels, kTablesSizesSum);
return S_OK;
}
class CCoderReleaser
{
CDecoder *m_Coder;
public:
CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
~CCoderReleaser()
{
// m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)
{
if (ReadBits(1) != 0)
{
// old file
TablesRead = false;
return ReadTables(keepDecompressing);
}
// new file
keepDecompressing = false;
TablesRead = (ReadBits(1) == 0);
return S_OK;
}
UInt32 kDistStart[kDistTableSize];
class CDistInit
{
public:
CDistInit() { Init(); }
void Init()
{
UInt32 start = 0;
for (UInt32 i = 0; i < kDistTableSize; i++)
{
kDistStart[i] = start;
start += (1 << kDistDirectBits[i]);
}
}
} g_DistInit;
HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
{
UInt32 rep0 = _reps[0];
UInt32 rep1 = _reps[1];
UInt32 rep2 = _reps[2];
UInt32 rep3 = _reps[3];
UInt32 length = _lastLength;
for (;;)
{
if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
{
RINOK(WriteBuf());
if (_writtenFileSize > _unpackSize)
return S_OK;
}
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number < 256)
{
PutByte(Byte(number));
continue;
}
else if (number == kSymbolReadTable)
{
RINOK(ReadEndOfBlock(keepDecompressing));
break;
}
else if (number == 257)
{
if (!ReadVmCodeLZ())
return S_FALSE;
continue;
}
else if (number == 258)
{
}
else if (number < kSymbolRep + 4)
{
if (number != kSymbolRep)
{
UInt32 distance;
if (number == kSymbolRep + 1)
distance = rep1;
else
{
if (number == kSymbolRep + 2)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream);
if (number >= kLenTableSize)
return S_FALSE;
length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
if (number < 271)
{
number -= 263;
rep0 = kLen2DistStarts[number] + m_InBitStream.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);
if (number >= kDistTableSize)
return S_FALSE;
rep0 = kDistStart[number];
int numBits = kDistDirectBits[number];
if (number >= (kNumAlignBits * 2) + 2)
{
if (numBits > kNumAlignBits)
rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
if (PrevAlignCount > 0)
{
PrevAlignCount--;
rep0 += PrevAlignBits;
}
else
{
UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream);
if (number < (1 << kNumAlignBits))
{
rep0 += number;
PrevAlignBits = number;
}
else if (number == (1 << kNumAlignBits))
{
PrevAlignCount = kNumAlignReps;
rep0 += PrevAlignBits;
}
else
return S_FALSE;
}
}
else
rep0 += m_InBitStream.ReadBits(numBits);
length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31);
}
else
return S_FALSE;
}
if (rep0 >= _lzSize)
return S_FALSE;
CopyBlock(rep0, length);
}
_reps[0] = rep0;
_reps[1] = rep1;
_reps[2] = rep2;
_reps[3] = rep3;
_lastLength = length;
return S_OK;
}
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
{
_writtenFileSize = 0;
if (!m_IsSolid)
{
_lzSize = 0;
_winPos = 0;
_wrPtr = 0;
for (int i = 0; i < kNumReps; i++)
_reps[i] = 0;
_lastLength = 0;
memset(m_LastLevels, 0, kTablesSizesSum);
TablesRead = false;
PpmEscChar = 2;
InitFilters();
}
if (!m_IsSolid || !TablesRead)
{
bool keepDecompressing;
RINOK(ReadTables(keepDecompressing));
if (!keepDecompressing)
return S_OK;
}
for(;;)
{
bool keepDecompressing;
if (_lzMode)
{
RINOK(DecodeLZ(keepDecompressing))
}
else
{
RINOK(DecodePPM(1 << 18, keepDecompressing))
}
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (!keepDecompressing)
break;
}
RINOK(WriteBuf());
if (_writtenFileSize < _unpackSize)
return S_FALSE;
// return m_OutWindowStream.Flush();
return S_OK;
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try
{
if (inSize == NULL || outSize == NULL)
return E_INVALIDARG;
if (_vmData == 0)
{
_vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
if (_vmData == 0)
return E_OUTOFMEMORY;
_vmCode = _vmData + kVmDataSizeMax;
}
if (_window == 0)
{
_window = (Byte *)::MidAlloc(kWindowSize);
if (_window == 0)
return E_OUTOFMEMORY;
}
if (!m_InBitStream.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_vm.Create())
return E_OUTOFMEMORY;
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
_outStream = outStream;
CCoderReleaser coderReleaser(this);
_unpackSize = *outSize;
return CodeReal(progress);
}
catch(...) { return S_FALSE; }
// CNewException is possible here. But probably CNewException is caused
// by error in data stream.
}
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,294 @@
// Rar3Decoder.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR3DECODER_H
#define __RAR3DECODER_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 "../PPMD/PPMDDecode.h"
#include "Rar3Vm.h"
namespace NCompress {
namespace NRar3 {
const UInt32 kWindowSize = 1 << 22;
const UInt32 kWindowMask = (kWindowSize - 1);
const UInt32 kNumReps = 4;
const UInt32 kNumLen2Symbols = 8;
const UInt32 kLenTableSize = 28;
const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize;
const UInt32 kDistTableSize = 60;
const int kNumAlignBits = 4;
const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1;
const UInt32 kLevelTableSize = 20;
const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
template<class TInByte>
class CBitDecoder2
{
UInt32 m_Value;
public:
UInt32 m_BitPos;
TInByte m_Stream;
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}
void ReleaseStream() { m_Stream.ReleaseStream();}
void Init()
{
m_Stream.Init();
m_BitPos = 0;
m_Value = 0;
// m_BitPos = kNumBigValueBits;
// Normalize();
}
UInt64 GetProcessedSize() const
{ return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }
UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); }
/*
void Normalize()
{
for (;m_BitPos >= 8; m_BitPos -= 8)
m_Value = (m_Value << 8) | m_Stream.ReadByte();
}
*/
UInt32 GetValue(UInt32 numBits)
{
// return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits);
// return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits);
if (m_BitPos < numBits)
{
m_BitPos += 8;
m_Value = (m_Value << 8) | m_Stream.ReadByte();
if (m_BitPos < numBits)
{
m_BitPos += 8;
m_Value = (m_Value << 8) | m_Stream.ReadByte();
}
}
return m_Value >> (m_BitPos - numBits);
}
void MovePos(UInt32 numBits)
{
m_BitPos -= numBits;
m_Value = m_Value & ((1 << m_BitPos) - 1);
}
UInt32 ReadBits(UInt32 numBits)
{
UInt32 res = GetValue(numBits);
MovePos(numBits);
return res;
}
};
typedef CBitDecoder2<CInBuffer> CBitDecoder;
const int kNumTopBits = 24;
const UInt32 kTopValue = (1 << kNumTopBits);
const UInt32 kBot = (1 << 15);
class CRangeDecoder:public NPPMD::CRangeDecoderVirt, public CBitDecoder
{
public:
UInt32 Range;
UInt32 Low;
UInt32 Code;
void Normalize()
{
while ((Low ^ (Low + Range)) < kTopValue ||
Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
{
Code = (Code << 8) | m_Stream.ReadByte();
Range <<= 8;
Low <<= 8;
}
}
void InitRangeCoder()
{
Code = 0;
Low = 0;
Range = 0xFFFFFFFF;
for(int i = 0; i < 4; i++)
Code = (Code << 8) | ReadBits(8);
}
virtual UInt32 GetThreshold(UInt32 total)
{
return (Code - Low) / ( Range /= total);
}
virtual void Decode(UInt32 start, UInt32 size)
{
Low += start * Range;
Range *= size;
Normalize();
}
virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
{
if (((Code - Low) / (Range >>= numTotalBits)) < size0)
{
Decode(0, size0);
return 0;
}
else
{
Decode(size0, (1 << numTotalBits) - size0);
return 1;
}
}
// UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); }
};
struct CFilter: public NVm::CProgram
{
CRecordVector<Byte> GlobalData;
UInt32 BlockStart;
UInt32 BlockSize;
UInt32 ExecCount;
CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}
};
struct CTempFilter: public NVm::CProgramInitState
{
UInt32 BlockStart;
UInt32 BlockSize;
UInt32 ExecCount;
bool NextWindow;
UInt32 FilterIndex;
};
const int kNumHuffmanBits = 15;
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
CRangeDecoder m_InBitStream;
Byte *_window;
UInt32 _winPos;
UInt32 _wrPtr;
UInt64 _lzSize;
UInt64 _unpackSize;
UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
CMyComPtr<ISequentialOutStream> _outStream;
NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
UInt32 _reps[kNumReps];
UInt32 _lastLength;
Byte m_LastLevels[kTablesSizesSum];
Byte *_vmData;
Byte *_vmCode;
NVm::CVm _vm;
CRecordVector<CFilter *> _filters;
CRecordVector<CTempFilter *> _tempFilters;
UInt32 _lastFilter;
bool m_IsSolid;
bool _lzMode;
UInt32 PrevAlignBits;
UInt32 PrevAlignCount;
bool TablesRead;
NPPMD::CDecodeInfo _ppm;
int PpmEscChar;
HRESULT WriteDataToStream(const Byte *data, UInt32 size);
HRESULT WriteData(const Byte *data, UInt32 size);
HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef);
HRESULT WriteBuf();
void InitFilters();
bool AddVmCode(UInt32 firstByte, UInt32 codeSize);
bool ReadVmCodeLZ();
bool ReadVmCodePPM();
UInt32 ReadBits(int numBits);
HRESULT InitPPM();
int DecodePpmSymbol();
HRESULT DecodePPM(Int32 num, bool &keepDecompressing);
HRESULT ReadTables(bool &keepDecompressing);
HRESULT ReadEndOfBlock(bool &keepDecompressing);
HRESULT DecodeLZ(bool &keepDecompressing);
HRESULT CodeReal(ICompressProgressInfo *progress);
public:
CDecoder();
~CDecoder();
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
void ReleaseStreams()
{
_outStream.Release();
m_InBitStream.ReleaseStream();
}
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
void CopyBlock(UInt32 distance, UInt32 len)
{
_lzSize += len;
UInt32 pos = (_winPos - distance - 1) & kWindowMask;
do
{
_window[_winPos] = _window[pos];
_winPos = (_winPos + 1) & kWindowMask;
pos = (pos + 1) & kWindowMask;
}
while(--len != 0);
}
void PutByte(Byte b)
{
_window[_winPos] = b;
_winPos = (_winPos + 1) & kWindowMask;
_lzSize++;
}
};
}}
#endif

1089
CPP/7zip/Compress/Rar/Rar3Vm.cpp Executable file
View File

File diff suppressed because it is too large Load Diff

219
CPP/7zip/Compress/Rar/Rar3Vm.h Executable file
View File

@@ -0,0 +1,219 @@
// Rar3Vm.h
// According to unRAR license,
// this code may not be used to develop a
// RAR (WinRAR) compatible archiver
#ifndef __RAR3VM_H
#define __RAR3VM_H
#include "Common/Types.h"
#include "Common/Vector.h"
#define RARVM_STANDARD_FILTERS
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) // || defined(_M_IA64) || defined(__ia64__)
// Define RARVM_LITTLE_ENDIAN_UNALIGN, if CPU is LITTLE_ENDIAN and if it supports
// unaligned 32-bit memory accesses.
// It's for speed optimization, if you are not sure, just don't define it.
#define RARVM_LITTLE_ENDIAN_UNALIGN
#endif
namespace NCompress {
namespace NRar3 {
class CMemBitDecoder
{
const Byte *_data;
UInt32 _bitSize;
UInt32 _bitPos;
public:
void Init(const Byte *data, UInt32 byteSize)
{
_data = data;
_bitSize = (byteSize << 3);
_bitPos = 0;
}
UInt32 ReadBits(int numBits);
UInt32 ReadBit();
bool Avail() const { return (_bitPos < _bitSize); }
};
namespace NVm {
inline UInt32 GetValue32(const void *addr)
{
#ifdef RARVM_LITTLE_ENDIAN_UNALIGN
return *(const UInt32 *)addr;
#else
const Byte *b = (const Byte *)addr;
return UInt32((UInt32)b[0]|((UInt32)b[1]<<8)|((UInt32)b[2]<<16)|((UInt32)b[3]<<24));
#endif
}
inline void SetValue32(void *addr, UInt32 value)
{
#ifdef RARVM_LITTLE_ENDIAN_UNALIGN
*(UInt32 *)addr = value;
#else
((Byte *)addr)[0] = (Byte)value;
((Byte *)addr)[1] = (Byte)(value >> 8);
((Byte *)addr)[2] = (Byte)(value >> 16);
((Byte *)addr)[3] = (Byte)(value >> 24);
#endif
}
UInt32 ReadEncodedUInt32(CMemBitDecoder &inp);
const int kNumRegBits = 3;
const UInt32 kNumRegs = 1 << kNumRegBits;
const UInt32 kNumGpRegs = kNumRegs - 1;
const UInt32 kSpaceSize = 0x40000;
const UInt32 kSpaceMask = kSpaceSize -1;
const UInt32 kGlobalOffset = 0x3C000;
const UInt32 kGlobalSize = 0x2000;
const UInt32 kFixedGlobalSize = 64;
namespace NGlobalOffset
{
const UInt32 kBlockSize = 0x1C;
const UInt32 kBlockPos = 0x20;
const UInt32 kExecCount = 0x2C;
const UInt32 kGlobalMemOutSize = 0x30;
};
enum ECommand
{
CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
CMD_JMP, CMD_XOR, CMD_AND, CMD_OR, CMD_TEST, CMD_JS, CMD_JNS, CMD_JB,
CMD_JBE, CMD_JA, CMD_JAE, CMD_PUSH, CMD_POP, CMD_CALL, CMD_RET, CMD_NOT,
CMD_SHL, CMD_SHR, CMD_SAR, CMD_NEG, CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF,
CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL, CMD_DIV, CMD_ADC, CMD_SBB, CMD_PRINT,
CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB,
CMD_XORB, CMD_ANDB, CMD_ORB, CMD_TESTB,CMD_NEGB,
CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB
};
enum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE};
// Addr in COperand object can link (point) to CVm object!!!
struct COperand
{
EOpType Type;
UInt32 Data;
UInt32 Base;
COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {}
};
struct CCommand
{
ECommand OpCode;
bool ByteMode;
COperand Op1, Op2;
};
struct CBlockRef
{
UInt32 Offset;
UInt32 Size;
};
struct CProgram
{
CRecordVector<CCommand> Commands;
#ifdef RARVM_STANDARD_FILTERS
int StandardFilterIndex;
#endif
CRecordVector<Byte> StaticData;
};
struct CProgramInitState
{
UInt32 InitR[kNumGpRegs];
CRecordVector<Byte> GlobalData;
void AllocateEmptyFixedGlobal()
{
GlobalData.Clear();
GlobalData.Reserve(NVm::kFixedGlobalSize);
for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++)
GlobalData.Add(0);
}
};
class CVm
{
static UInt32 GetValue(bool byteMode, const void *addr)
{
if (byteMode)
return(*(const Byte *)addr);
else
{
#ifdef RARVM_LITTLE_ENDIAN_UNALIGN
return *(const UInt32 *)addr;
#else
const Byte *b = (const Byte *)addr;
return UInt32((UInt32)b[0]|((UInt32)b[1]<<8)|((UInt32)b[2]<<16)|((UInt32)b[3]<<24));
#endif
}
}
static void SetValue(bool byteMode, void *addr, UInt32 value)
{
if (byteMode)
*(Byte *)addr = (Byte)value;
else
{
#ifdef RARVM_LITTLE_ENDIAN_UNALIGN
*(UInt32 *)addr = value;
#else
((Byte *)addr)[0] = (Byte)value;
((Byte *)addr)[1] = (Byte)(value >> 8);
((Byte *)addr)[2] = (Byte)(value >> 16);
((Byte *)addr)[3] = (Byte)(value >> 24);
#endif
}
}
UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); }
void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); }
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
public:
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
private:
UInt32 GetOperand32(const COperand *op) const;
void SetOperand32(const COperand *op, UInt32 val);
Byte GetOperand8(const COperand *op) const;
void SetOperand8(const COperand *op, Byte val);
UInt32 GetOperand(bool byteMode, const COperand *op) const;
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode);
bool ExecuteCode(const CProgram *prg);
#ifdef RARVM_STANDARD_FILTERS
void ExecuteStandardFilter(int filterIndex);
#endif
Byte *Mem;
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
UInt32 Flags;
void ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg);
public:
CVm();
~CVm();
bool Create();
void PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg);
void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize);
bool Execute(CProgram *prg, const CProgramInitState *initState,
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
};
#endif
}}}

View File

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

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

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

49
CPP/7zip/Compress/Rar/makefile Executable file
View File

@@ -0,0 +1,49 @@
PROG = Rar29.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../
LIBS = $(LIBS) oleaut32.lib
RAR29_OBJS = \
$O\DllExports.obj \
RAR29_OPT_OBJS = \
$O\Rar1Decoder.obj \
$O\Rar2Decoder.obj \
$O\Rar3Decoder.obj \
$O\Rar3Vm.obj \
COMMON_OBJS = \
$O\Alloc.obj \
$O\CRC.obj \
$O\Vector.obj \
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
$O\StreamUtils.obj \
LZ_OBJS = \
$O\LZOutWindow.obj \
OBJS = \
$O\StdAfx.obj \
$(RAR29_OBJS) \
$(RAR29_OPT_OBJS) \
$(COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(LZ_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(RAR29_OBJS): $(*B).cpp
$(COMPL)
$(RAR29_OPT_OBJS): $(*B).cpp
$(COMPL_O2)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$(LZ_OBJS): ../LZ/$(*B).cpp
$(COMPL)

View File

@@ -0,0 +1,3 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_DLL("Rar29 Codec", "Rar29")