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,93 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#ifdef _WIN32
#include "Common/Alloc.h"
#endif
#include "PPMDEncoder.h"
#include "PPMDDecoder.h"
// {23170F69-40C1-278B-0304-010000000000}
DEFINE_GUID(CLSID_CCompressPPMDDecoder,
0x23170F69, 0x40C1, 0x278B, 0x03, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0304-010000000100}
DEFINE_GUID(CLSID_CCompressPPMDEncoder,
0x23170F69, 0x40C1, 0x278B, 0x03, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00);
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID /*lpReserved*/)
{
#ifdef _WIN32
if (dwReason == DLL_PROCESS_ATTACH)
SetLargePageSize();
#endif
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;
if (*clsid == CLSID_CCompressPPMDDecoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NPPMD::CDecoder();
}
else if (*clsid == CLSID_CCompressPPMDEncoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NPPMD::CEncoder();
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*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[] = { 0x03, 0x04, 0x01 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(L"PPMD")) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressPPMDDecoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kEncoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressPPMDEncoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
return S_OK;
}

229
CPP/7zip/Compress/PPMD/PPMD.dsp Executable file
View File

@@ -0,0 +1,229 @@
# Microsoft Developer Studio Project File - Name="PPMD" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=PPMD - 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 "PPMD.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 "PPMD.mak" CFG="PPMD - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PPMD - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "PPMD - 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)" == "PPMD - 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 "PPMD_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /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\PPMd.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "PPMD - 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 "PPMD_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /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\PPMd.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "PPMD - Win32 Release"
# Name "PPMD - 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
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "PPMD"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\PPMDContext.h
# End Source File
# Begin Source File
SOURCE=.\PPMDDecode.h
# End Source File
# Begin Source File
SOURCE=.\PPMDDecoder.cpp
!IF "$(CFG)" == "PPMD - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "PPMD - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\PPMDDecoder.h
# End Source File
# Begin Source File
SOURCE=.\PPMDEncode.h
# End Source File
# Begin Source File
SOURCE=.\PPMDEncoder.cpp
!IF "$(CFG)" == "PPMD - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "PPMD - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\PPMDEncoder.h
# End Source File
# Begin Source File
SOURCE=.\PPMDSubAlloc.h
# End Source File
# Begin Source File
SOURCE=.\PPMDType.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\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 "RangeCoder"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\RangeCoder\RangeCoder.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\Types.h
# End Source File
# End Group
# End Target
# End Project

29
CPP/7zip/Compress/PPMD/PPMD.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: "PPMD"=.\PPMD.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,489 @@
// Compress/PPMD/Context.h
// This code is based on Dmitry Shkarin's PPMdH code
#ifndef __COMPRESS_PPMD_CONTEXT_H
#define __COMPRESS_PPMD_CONTEXT_H
#include "../../../Common/Types.h"
#include "../RangeCoder/RangeCoder.h"
#include "PPMDSubAlloc.h"
namespace NCompress {
namespace NPPMD {
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
struct SEE2_CONTEXT
{
// SEE-contexts for PPM-contexts with masked symbols
UInt16 Summ;
Byte Shift, Count;
void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }
unsigned int getMean()
{
unsigned int RetVal=(Summ >> Shift);
Summ = (UInt16)(Summ - RetVal);
return RetVal+(RetVal == 0);
}
void update()
{
if (Shift < PERIOD_BITS && --Count == 0)
{
Summ <<= 1;
Count = (Byte)(3 << Shift++);
}
}
};
struct PPM_CONTEXT
{
UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)
UInt16 SummFreq;
struct STATE
{
Byte Symbol, Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }
void SetSuccessor(UInt32 v)
{
SuccessorLow = (UInt16)(v & 0xFFFF);
SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);
}
};
UInt32 Stats;
UInt32 Suffix;
PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
{
PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
if (pc)
{
pc->NumStats = 1;
pc->oneState() = FirstState;
pc->Suffix = subAllocator.GetOffset(this);
pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
}
return pc;
}
STATE& oneState() const { return (STATE&) SummFreq; }
};
/////////////////////////////////
const UInt16 InitBinEsc[] =
{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
struct CInfo
{
CSubAllocator SubAllocator;
SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
PPM_CONTEXT * MinContext, * MaxContext;
PPM_CONTEXT::STATE* FoundState; // found next state transition
int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
UInt16 BinSumm[128][64]; // binary SEE-contexts
UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
return BinSumm[rs.Freq - 1][
PrevSuccess + NS2BSIndx[numStates - 1] +
HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
((RunLength >> 26) & 0x20)];
}
PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }
PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
void RestartModelRare()
{
int i, k, m;
memset(CharMask,0,sizeof(CharMask));
SubAllocator.InitSubAllocator();
InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
MinContext->Suffix = 0;
OrderFall = MaxOrder;
MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);
FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
PrevSuccess = 0;
for (RunLength = InitRL, i = 0; i < 256; i++)
{
PPM_CONTEXT::STATE &state = FoundState[i];
state.Symbol = (Byte)i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
for ( m=0; m < 64; m += 8)
BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
SEE2Cont[i][k].init(5*i+10);
}
void StartModelRare(int MaxOrder)
{
int i, k, m ,Step;
EscCount=PrintCount=1;
if (MaxOrder < 2)
{
memset(CharMask,0,sizeof(CharMask));
OrderFall = this->MaxOrder;
MinContext = MaxContext;
while (MinContext->Suffix != 0)
{
MinContext = GetContextNoCheck(MinContext->Suffix);
OrderFall--;
}
FoundState = GetState(MinContext->Stats);
MinContext = MaxContext;
}
else
{
this->MaxOrder = MaxOrder;
RestartModelRare();
NS2BSIndx[0] = 2 * 0;
NS2BSIndx[1] = 2 * 1;
memset(NS2BSIndx + 2, 2 * 2, 9);
memset(NS2BSIndx + 11, 2 * 3, 256 - 11);
for (i = 0; i < 3; i++)
NS2Indx[i] = (Byte)i;
for (m = i, k = Step = 1; i < 256; i++)
{
NS2Indx[i] = (Byte)m;
if ( !--k )
{
k = ++Step;
m++;
}
}
memset(HB2Flag, 0, 0x40);
memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);
DummySEE2Cont.Shift = PERIOD_BITS;
}
}
PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
{
// static UpState declaration bypasses IntelC bug
// static PPM_CONTEXT::STATE UpState;
PPM_CONTEXT::STATE UpState;
PPM_CONTEXT *pc = MinContext;
PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
if ( !skip )
{
*pps++ = FoundState;
if ( !pc->Suffix )
goto NO_LOOP;
}
if ( p1 )
{
p = p1;
pc = GetContext(pc->Suffix);
goto LOOP_ENTRY;
}
do
{
pc = GetContext(pc->Suffix);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
do { p++; } while (p->Symbol != FoundState->Symbol);
}
else
p = &(pc->oneState());
LOOP_ENTRY:
if (GetContext(p->GetSuccessor()) != UpBranch)
{
pc = GetContext(p->GetSuccessor());
break;
}
*pps++ = p;
}
while ( pc->Suffix );
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol = *(Byte*) UpBranch;
UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)
do { p++; } while (p->Symbol != UpState.Symbol);
unsigned int cf = p->Freq-1;
unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :
((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
else
UpState.Freq = pc->oneState().Freq;
do
{
pc = pc->createChild(SubAllocator, *--pps, UpState);
if ( !pc )
return NULL;
}
while (pps != ps);
return pc;
}
void UpdateModel()
{
PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
PPM_CONTEXT* pc, * Successor;
unsigned int ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)
{
pc = GetContextNoCheck(MinContext->Suffix);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)
{
do { p++; } while (p->Symbol != fs.Symbol);
if (p[0].Freq >= p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
p--;
}
}
if (p->Freq < MAX_FREQ-9)
{
p->Freq += 2;
pc->SummFreq += 2;
}
}
else
{
p = &(pc->oneState());
p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0));
}
}
if ( !OrderFall )
{
MinContext = MaxContext = CreateSuccessors(true, p);
FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));
if (MinContext == 0)
goto RESTART_MODEL;
return;
}
*SubAllocator.pText++ = fs.Symbol;
Successor = (PPM_CONTEXT*) SubAllocator.pText;
if (SubAllocator.pText >= SubAllocator.UnitsStart)
goto RESTART_MODEL;
if (fs.GetSuccessor() != 0)
{
if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)
{
PPM_CONTEXT* cs = CreateSuccessors(false, p);
fs.SetSuccessor(SubAllocator.GetOffset(cs));
if (cs == NULL)
goto RESTART_MODEL;
}
if ( !--OrderFall )
{
Successor = GetContext(fs.GetSuccessor());
SubAllocator.pText -= (MaxContext != MinContext);
}
}
else
{
FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));
fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));
}
s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);
for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))
{
if ((ns1 = pc->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);
pc->Stats = SubAllocator.GetOffset(ppp);
if (!ppp)
goto RESTART_MODEL;
}
pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &
(pc->SummFreq <= 8 * ns1)));
}
else
{
p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);
if ( !p )
goto RESTART_MODEL;
*p = pc->oneState();
pc->Stats = SubAllocator.GetOffsetNoCheck(p);
if (p->Freq < MAX_FREQ / 4 - 1)
p->Freq <<= 1;
else
p->Freq = MAX_FREQ - 4;
pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3));
}
cf = 2 * fs.Freq * (pc->SummFreq+6);
sf = s0 + pc->SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf)+(cf >= 4 * sf);
pc->SummFreq += 3;
}
else
{
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
pc->SummFreq = (UInt16)(pc->SummFreq + cf);
}
p = GetState(pc->Stats) + ns1;
p->SetSuccessor(SubAllocator.GetOffset(Successor));
p->Symbol = fs.Symbol;
p->Freq = (Byte)cf;
pc->NumStats = (UInt16)++ns1;
}
MaxContext = MinContext = GetContext(fs.GetSuccessor());
return;
RESTART_MODEL:
RestartModelRare();
EscCount = 0;
PrintCount = 0xFF;
}
void ClearMask()
{
EscCount = 1;
memset(CharMask, 0, sizeof(CharMask));
// if (++PrintCount == 0)
// PrintInfo(DecodedFile,EncodedFile);
}
void update1(PPM_CONTEXT::STATE* p)
{
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p[0].Freq > p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
FoundState = --p;
if (p->Freq > MAX_FREQ)
rescale();
}
}
void update2(PPM_CONTEXT::STATE* p)
{
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p->Freq > MAX_FREQ)
rescale();
EscCount++;
RunLength = InitRL;
}
SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)
{
SEE2_CONTEXT* psee2c;
if (MinContext->NumStats != 256)
{
psee2c = SEE2Cont[NS2Indx[Diff-1]] +
(Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +
2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +
4 * (NumMasked > Diff) +
HiBitsFlag;
scale = psee2c->getMean();
}
else
{
psee2c = &DummySEE2Cont;
scale = 1;
}
return psee2c;
}
void rescale()
{
int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;
PPM_CONTEXT::STATE* p1, * p;
PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);
for (p = FoundState; p != stats; p--)
_PPMD_SWAP(p[0], p[-1]);
stats->Freq += 4;
MinContext->SummFreq += 4;
EscFreq = MinContext->SummFreq - p->Freq;
Adder = (OrderFall != 0);
p->Freq = (Byte)((p->Freq + Adder) >> 1);
MinContext->SummFreq = p->Freq;
do
{
EscFreq -= (++p)->Freq;
p->Freq = (Byte)((p->Freq + Adder) >> 1);
MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq);
if (p[0].Freq > p[-1].Freq)
{
PPM_CONTEXT::STATE tmp = *(p1 = p);
do
{
p1[0] = p1[-1];
}
while (--p1 != stats && tmp.Freq > p1[-1].Freq);
*p1 = tmp;
}
}
while ( --i );
if (p->Freq == 0)
{
do { i++; } while ((--p)->Freq == 0);
EscFreq += i;
MinContext->NumStats = (UInt16)(MinContext->NumStats - i);
if (MinContext->NumStats == 1)
{
PPM_CONTEXT::STATE tmp = *stats;
do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1);
SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);
*(FoundState = &MinContext->oneState()) = tmp; return;
}
}
EscFreq -= (EscFreq >> 1);
MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq);
int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;
if (n0 != n1)
MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));
FoundState = GetState(MinContext->Stats);
}
void NextContext()
{
PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());
if (!OrderFall && (Byte *)c > SubAllocator.pText)
MinContext = MaxContext = c;
else
{
UpdateModel();
if (EscCount == 0)
ClearMask();
}
}
};
// Tabulated escapes for exponential symbol distribution
const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
}}
#endif

View File

@@ -0,0 +1,154 @@
// PPMDDecode.h
// This code is based on Dmitry Shkarin's PPMdH code
#ifndef __COMPRESS_PPMD_DECODE_H
#define __COMPRESS_PPMD_DECODE_H
#include "PPMDContext.h"
namespace NCompress {
namespace NPPMD {
class CRangeDecoderVirt
{
public:
virtual UInt32 GetThreshold(UInt32 total) = 0;
virtual void Decode(UInt32 start, UInt32 size) = 0;
virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) = 0;
};
typedef NRangeCoder::CDecoder CRangeDecoderMy;
class CRangeDecoder:public CRangeDecoderVirt, public CRangeDecoderMy
{
UInt32 GetThreshold(UInt32 total) { return CRangeDecoderMy::GetThreshold(total); }
void Decode(UInt32 start, UInt32 size) { CRangeDecoderMy::Decode(start, size); }
UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { return CRangeDecoderMy::DecodeBit(size0, numTotalBits); }
};
struct CDecodeInfo: public CInfo
{
void DecodeBinSymbol(CRangeDecoderVirt *rangeDecoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0)
{
FoundState = &rs;
rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0));
bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2));
PrevSuccess = 1;
RunLength++;
}
else
{
bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
PrevSuccess = 0;
FoundState = NULL;
}
}
void DecodeSymbol1(CRangeDecoderVirt *rangeDecoder)
{
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats);
int i, count, hiCnt;
if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq))
{
PrevSuccess = (2 * hiCnt > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq);
(FoundState = p)->Freq = (Byte)(hiCnt += 4);
MinContext->SummFreq += 4;
if (hiCnt > MAX_FREQ)
rescale();
return;
}
PrevSuccess = 0;
i = MinContext->NumStats - 1;
while ((hiCnt += (++p)->Freq) <= count)
if (--i == 0)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt); // , MinContext->SummFreq);
CharMask[p->Symbol] = EscCount;
i = (NumMasked = MinContext->NumStats)-1;
FoundState = NULL;
do { CharMask[(--p)->Symbol] = EscCount; } while ( --i );
return;
}
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq);
update1(p);
}
void DecodeSymbol2(CRangeDecoderVirt *rangeDecoder)
{
int count, hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 freqSum;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum);
PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1;
hiCnt = 0;
do
{
do { p++; } while (CharMask[p->Symbol] == EscCount);
hiCnt += p->Freq;
*pps++ = p;
}
while ( --i );
freqSum += hiCnt;
count = rangeDecoder->GetThreshold(freqSum);
p = *(pps = ps);
if (count < hiCnt)
{
hiCnt = 0;
while ((hiCnt += p->Freq) <= count)
p=*++pps;
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum);
psee2c->update();
update2(p);
}
else
{
rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum);
i = MinContext->NumStats - NumMasked;
pps--;
do { CharMask[(*++pps)->Symbol] = EscCount; } while ( --i );
psee2c->Summ = (UInt16)(psee2c->Summ + freqSum);
NumMasked = MinContext->NumStats;
}
}
int DecodeSymbol(CRangeDecoderVirt *rangeDecoder)
{
if (MinContext->NumStats != 1)
DecodeSymbol1(rangeDecoder);
else
DecodeBinSymbol(rangeDecoder);
while ( !FoundState )
{
do
{
OrderFall++;
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return -1;
}
while (MinContext->NumStats == NumMasked);
DecodeSymbol2(rangeDecoder);
}
Byte symbol = FoundState->Symbol;
NextContext();
return symbol;
}
};
}}
#endif

View File

@@ -0,0 +1,184 @@
// PPMDDecoder.cpp
#include "StdAfx.h"
#include "Common/Defs.h"
#include "Windows/Defs.h"
#include "PPMDDecoder.h"
namespace NCompress {
namespace NPPMD {
const int kLenIdFinished = -1;
const int kLenIdNeedInit = -2;
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
{
if (size < 5)
return E_INVALIDARG;
_order = properties[0];
_usedMemorySize = 0;
for (int i = 0; i < 4; i++)
_usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8);
if (_usedMemorySize > kMaxMemBlockSize)
return E_NOTIMPL;
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY;
return S_OK;
}
class CDecoderFlusher
{
CDecoder *_coder;
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}
~CDecoderFlusher()
{
if (NeedFlush)
_coder->Flush();
_coder->ReleaseStreams();
}
};
HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)
{
if (_outSizeDefined)
{
const UInt64 rem = _outSize - _processedSize;
if (size > rem)
size = (UInt32)rem;
}
const UInt32 startSize = size;
if (_remainLen == kLenIdFinished)
return S_OK;
if (_remainLen == kLenIdNeedInit)
{
_rangeDecoder.Init();
_remainLen = 0;
_info.MaxOrder = 0;
_info.StartModelRare(_order);
}
while (size != 0)
{
int symbol = _info.DecodeSymbol(&_rangeDecoder);
if (symbol < 0)
{
_remainLen = kLenIdFinished;
break;
}
if (memStream != 0)
*memStream++ = (Byte)symbol;
else
_outStream.WriteByte((Byte)symbol);
size--;
}
_processedSize += startSize - size;
return S_OK;
}
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (!_outStream.Create(1 << 20))
return E_OUTOFMEMORY;
SetInStream(inStream);
_outStream.SetStream(outStream);
SetOutStreamSize(outSize);
CDecoderFlusher flusher(this);
for (;;)
{
_processedSize = _outStream.GetProcessedSize();
UInt32 curSize = (1 << 18);
RINOK(CodeSpec(curSize, NULL));
if (_remainLen == kLenIdFinished)
break;
if (progress != NULL)
{
UInt64 inSize = _rangeDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
}
if (_outSizeDefined)
if (_outStream.GetProcessedSize() >= _outSize)
break;
}
flusher.NeedFlush = false;
return Flush();
}
#ifdef _NO_EXCEPTIONS
#define PPMD_TRY_BEGIN
#define PPMD_TRY_END
#else
#define PPMD_TRY_BEGIN try {
#define PPMD_TRY_END } \
catch(const CInBufferException &e) { return e.ErrorCode; } \
catch(const COutBufferException &e) { return e.ErrorCode; } \
catch(...) { return S_FALSE; }
#endif
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
PPMD_TRY_BEGIN
return CodeReal(inStream, outStream, inSize, outSize, progress);
PPMD_TRY_END
}
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
{
_rangeDecoder.SetStream(inStream);
return S_OK;
}
STDMETHODIMP CDecoder::ReleaseInStream()
{
_rangeDecoder.ReleaseStream();
return S_OK;
}
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
_outSizeDefined = (outSize != NULL);
if (_outSizeDefined)
_outSize = *outSize;
_processedSize = 0;
_remainLen = kLenIdNeedInit;
_outStream.Init();
return S_OK;
}
#ifdef _ST_MODE
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
PPMD_TRY_BEGIN
if (processedSize)
*processedSize = 0;
const UInt64 startPos = _processedSize;
RINOK(CodeSpec(size, (Byte *)data));
if (processedSize)
*processedSize = (UInt32)(_processedSize - startPos);
return Flush();
PPMD_TRY_END
}
#endif
}}

View File

@@ -0,0 +1,89 @@
// Compress/PPM/PPMDDecoder.h
#ifndef __COMPRESS_PPMD_DECODER_H
#define __COMPRESS_PPMD_DECODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/OutBuffer.h"
#include "../RangeCoder/RangeCoder.h"
#include "PPMDDecode.h"
namespace NCompress {
namespace NPPMD {
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties2,
#ifdef _ST_MODE
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
public CMyUnknownImp
{
CRangeDecoder _rangeDecoder;
COutBuffer _outStream;
CDecodeInfo _info;
Byte _order;
UInt32 _usedMemorySize;
int _remainLen;
UInt64 _outSize;
bool _outSizeDefined;
UInt64 _processedSize;
HRESULT CodeSpec(UInt32 num, Byte *memStream);
public:
#ifdef _ST_MODE
MY_UNKNOWN_IMP4(
ICompressSetDecoderProperties2,
ICompressSetInStream,
ICompressSetOutStreamSize,
ISequentialInStream)
#else
MY_UNKNOWN_IMP1(
ICompressSetDecoderProperties2)
#endif
void ReleaseStreams()
{
ReleaseInStream();
_outStream.ReleaseStream();
}
HRESULT Flush() { return _outStream.Flush(); }
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifdef _ST_MODE
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif
CDecoder(): _outSizeDefined(false) {}
};
}}
#endif

View File

@@ -0,0 +1,142 @@
// PPMDEncode.h
// This code is based on Dmitry Shkarin's PPMdH code
#ifndef __COMPRESS_PPMD_ENCODE_H
#define __COMPRESS_PPMD_ENCODE_H
#include "PPMDContext.h"
namespace NCompress {
namespace NPPMD {
struct CEncodeInfo: public CInfo
{
void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rs.Symbol == symbol)
{
FoundState = &rs;
rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0));
rangeEncoder->EncodeBit(bs, TOT_BITS, 0);
bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2));
PrevSuccess = 1;
RunLength++;
}
else
{
rangeEncoder->EncodeBit(bs, TOT_BITS, 1);
bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
PrevSuccess = 0;
FoundState = NULL;
}
}
void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats);
if (p->Symbol == symbol)
{
PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq);
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p->Freq > MAX_FREQ)
rescale();
return;
}
PrevSuccess = 0;
int LoCnt = p->Freq, i = MinContext->NumStats - 1;
while ((++p)->Symbol != symbol)
{
LoCnt += p->Freq;
if (--i == 0)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
CharMask[p->Symbol] = EscCount;
i=(NumMasked = MinContext->NumStats)-1;
FoundState = NULL;
do { CharMask[(--p)->Symbol] = EscCount; } while ( --i );
rangeEncoder->Encode(LoCnt, MinContext->SummFreq - LoCnt, MinContext->SummFreq);
return;
}
}
rangeEncoder->Encode(LoCnt, p->Freq, MinContext->SummFreq);
update1(p);
}
void EncodeSymbol2(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
int hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 scale;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale);
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1;
hiCnt = 0;
do
{
do { p++; } while (CharMask[p->Symbol] == EscCount);
hiCnt += p->Freq;
if (p->Symbol == symbol)
goto SYMBOL_FOUND;
CharMask[p->Symbol] = EscCount;
}
while ( --i );
rangeEncoder->Encode(hiCnt, scale, hiCnt + scale);
scale += hiCnt;
psee2c->Summ = (UInt16)(psee2c->Summ + scale);
NumMasked = MinContext->NumStats;
return;
SYMBOL_FOUND:
UInt32 highCount = hiCnt;
UInt32 lowCount = highCount - p->Freq;
if ( --i )
{
PPM_CONTEXT::STATE* p1 = p;
do
{
do { p1++; } while (CharMask[p1->Symbol] == EscCount);
hiCnt += p1->Freq;
}
while ( --i );
}
// SubRange.scale += hiCnt;
scale += hiCnt;
rangeEncoder->Encode(lowCount, highCount - lowCount, scale);
psee2c->update();
update2(p);
}
void EncodeSymbol(int c, NRangeCoder::CEncoder *rangeEncoder)
{
if (MinContext->NumStats != 1)
EncodeSymbol1(c, rangeEncoder);
else
EncodeBinSymbol(c, rangeEncoder);
while ( !FoundState )
{
do
{
OrderFall++;
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return; // S_OK;
}
while (MinContext->NumStats == NumMasked);
EncodeSymbol2(c, rangeEncoder);
}
NextContext();
}
};
}}
#endif

View File

@@ -0,0 +1,155 @@
// Compress/Associative/Encoder.h
#include "StdAfx.h"
#include "Windows/Defs.h"
// #include <fstream.h>
// #include <iomanip.h>
#include "Common/Defs.h"
#include "../../Common/StreamUtils.h"
#include "PPMDEncoder.h"
namespace NCompress {
namespace NPPMD {
const UInt32 kMinMemSize = (1 << 11);
const UInt32 kMinOrder = 2;
/*
UInt32 g_NumInner = 0;
UInt32 g_InnerCycles = 0;
UInt32 g_Encode2 = 0;
UInt32 g_Encode2Cycles = 0;
UInt32 g_Encode2Cycles2 = 0;
class CCounter
{
public:
CCounter() {}
~CCounter()
{
ofstream ofs("Res.dat");
ofs << "innerEncode1 = " << setw(10) << g_NumInner << endl;
ofs << "g_InnerCycles = " << setw(10) << g_InnerCycles << endl;
ofs << "g_Encode2 = " << setw(10) << g_Encode2 << endl;
ofs << "g_Encode2Cycles = " << setw(10) << g_Encode2Cycles << endl;
ofs << "g_Encode2Cycles2= " << setw(10) << g_Encode2Cycles2 << endl;
}
};
CCounter g_Counter;
*/
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{
for (UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &prop = properties[i];
switch(propIDs[i])
{
case NCoderPropID::kUsedMemorySize:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize)
return E_INVALIDARG;
_usedMemorySize = (UInt32)prop.ulVal;
break;
case NCoderPropID::kOrder:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress)
return E_INVALIDARG;
_order = (Byte)prop.ulVal;
break;
default:
return E_INVALIDARG;
}
}
return S_OK;
}
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
const UInt32 kPropSize = 5;
Byte properties[kPropSize];
properties[0] = _order;
for (int i = 0; i < 4; i++)
properties[1 + i] = Byte(_usedMemorySize >> (8 * i));
return WriteStream(outStream, properties, kPropSize, NULL);
}
const UInt32 kUsedMemorySizeDefault = (1 << 24);
const int kOrderDefault = 6;
CEncoder::CEncoder():
_usedMemorySize(kUsedMemorySizeDefault),
_order(kOrderDefault)
{
}
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */,
ICompressProgressInfo *progress)
{
if (!_inStream.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_rangeEncoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY;
_inStream.SetStream(inStream);
_inStream.Init();
_rangeEncoder.SetStream(outStream);
_rangeEncoder.Init();
CEncoderFlusher flusher(this);
_info.MaxOrder = 0;
_info.StartModelRare(_order);
for (;;)
{
UInt32 size = (1 << 18);
do
{
Byte symbol;
if (!_inStream.ReadByte(symbol))
{
// here we can write End Mark for stream version.
// In current version this feature is not used.
// _info.EncodeSymbol(-1, &_rangeEncoder);
return S_OK;
}
_info.EncodeSymbol(symbol, &_rangeEncoder);
}
while (--size != 0);
if (progress != NULL)
{
UInt64 inSize = _inStream.GetProcessedSize();
UInt64 outSize = _rangeEncoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &outSize));
}
}
}
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(...) { return E_FAIL; }
}
}}

View File

@@ -0,0 +1,81 @@
// Compress/PPMD/Encoder.h
#ifndef __COMPRESS_PPMD_ENCODER_H
#define __COMPRESS_PPMD_ENCODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/InBuffer.h"
#include "../RangeCoder/RangeCoder.h"
#include "PPMDEncode.h"
namespace NCompress {
namespace NPPMD {
class CEncoder :
public ICompressCoder,
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
public CMyUnknownImp
{
public:
CInBuffer _inStream;
NRangeCoder::CEncoder _rangeEncoder;
CEncodeInfo _info;
UInt32 _usedMemorySize;
Byte _order;
HRESULT Flush()
{
_rangeEncoder.FlushData();
return _rangeEncoder.FlushStream();
}
void ReleaseStreams()
{
_inStream.ReleaseStream();
_rangeEncoder.ReleaseStream();
}
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
class CEncoderFlusher
{
CEncoder *_encoder;
public:
CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {}
~CEncoderFlusher()
{
_encoder->Flush();
_encoder->ReleaseStreams();
}
};
public:
MY_UNKNOWN_IMP2(
ICompressSetCoderProperties,
ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
CEncoder();
};
}}
#endif

View File

@@ -0,0 +1,292 @@
// PPMDSubAlloc.h
// This code is based on Dmitry Shkarin's PPMdH code
#ifndef __PPMD_SUBALLOC_H
#define __PPMD_SUBALLOC_H
#include "PPMDType.h"
#include "../../../Common/Alloc.h"
const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4;
// Extra 1 * UNIT_SIZE for NULL support
// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks()
const UInt32 kExtraSize = (UNIT_SIZE * 3);
const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize;
struct MEM_BLK
{
UInt16 Stamp, NU;
UInt32 Next, Prev;
void InsertAt(Byte *Base, UInt32 p)
{
Prev = p;
MEM_BLK *pp = (MEM_BLK *)(Base + p);
Next = pp->Next;
pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (UInt32)((Byte *)this - Base);
}
void Remove(Byte *Base)
{
((MEM_BLK *)(Base + Prev))->Next = Next;
((MEM_BLK *)(Base + Next))->Prev = Prev;
}
};
class CSubAllocator
{
UInt32 SubAllocatorSize;
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
UInt32 FreeList[N_INDEXES];
Byte *Base;
Byte *HeapStart, *LoUnit, *HiUnit;
public:
Byte *pText, *UnitsStart;
CSubAllocator():
SubAllocatorSize(0),
GlueCount(0),
LoUnit(0),
HiUnit(0),
pText(0),
UnitsStart(0)
{
memset(Indx2Units, 0, sizeof(Indx2Units));
memset(FreeList, 0, sizeof(FreeList));
}
~CSubAllocator()
{
StopSubAllocator();
};
void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); }
void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); }
UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); }
UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); }
MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); }
UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); }
void InsertNode(void* p, int indx)
{
*(UInt32 *)p = FreeList[indx];
FreeList[indx] = GetOffsetNoCheck(p);
}
void* RemoveNode(int indx)
{
UInt32 offset = FreeList[indx];
UInt32 *p = GetNode(offset);
FreeList[indx] = *p;
return (void *)p;
}
UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; }
void SplitBlock(void* pv, int oldIndx, int newIndx)
{
int i, UDiff = Indx2Units[oldIndx] - Indx2Units[newIndx];
Byte* p = ((Byte*)pv) + U2B(Indx2Units[newIndx]);
if (Indx2Units[i = Units2Indx[UDiff-1]] != UDiff)
{
InsertNode(p, --i);
p += U2B(i = Indx2Units[i]);
UDiff -= i;
}
InsertNode(p, Units2Indx[UDiff - 1]);
}
UInt32 GetUsedMemory() const
{
UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText);
for (UInt32 i = 0; i < N_INDEXES; i++)
for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE)
pn = *GetNode(pn);
return (RetVal >> 2);
}
UInt32 GetSubAllocatorSize() const { return SubAllocatorSize; }
void StopSubAllocator()
{
if (SubAllocatorSize != 0)
{
BigFree(Base);
SubAllocatorSize = 0;
Base = 0;
}
}
bool StartSubAllocator(UInt32 size)
{
if (SubAllocatorSize == size)
return true;
StopSubAllocator();
if (size == 0)
Base = 0;
else
{
if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0)
return false;
HeapStart = Base + UNIT_SIZE; // we need such code to support NULL;
}
SubAllocatorSize = size;
return true;
}
void InitSubAllocator()
{
int i, k;
memset(FreeList, 0, sizeof(FreeList));
HiUnit = (pText = HeapStart) + SubAllocatorSize;
UINT Diff = UNIT_SIZE * (SubAllocatorSize / 8 / UNIT_SIZE * 7);
LoUnit = UnitsStart = HiUnit - Diff;
for (i = 0, k=1; i < N1 ; i++, k += 1) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i] = (Byte)k;
GlueCount = 0;
for (k = i = 0; k < 128; k++)
{
i += (Indx2Units[i] < k+1);
Units2Indx[k] = (Byte)i;
}
}
void GlueFreeBlocks()
{
UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base);
// We need add exta MEM_BLK with Stamp=0
GetBlk(s0)->Stamp = 0;
s0 += UNIT_SIZE;
MEM_BLK *ps0 = GetBlk(s0);
UInt32 p;
int i;
if (LoUnit != HiUnit)
*LoUnit=0;
ps0->Next = ps0->Prev = s0;
for (i = 0; i < N_INDEXES; i++)
while (FreeList[i] != 0)
{
MEM_BLK *pp = (MEM_BLK *)RemoveNode(i);
pp->InsertAt(Base, s0);
pp->Stamp = 0xFFFF;
pp->NU = Indx2Units[i];
}
for (p = ps0->Next; p != s0; p = GetBlk(p)->Next)
{
for (;;)
{
MEM_BLK *pp = GetBlk(p);
MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE);
if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000)
break;
pp1->Remove(Base);
pp->NU = (UInt16)(pp->NU + pp1->NU);
}
}
while ((p = ps0->Next) != s0)
{
MEM_BLK *pp = GetBlk(p);
pp->Remove(Base);
int sz;
for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE)
InsertNode(Base + p, N_INDEXES - 1);
if (Indx2Units[i = Units2Indx[sz-1]] != sz)
{
int k = sz - Indx2Units[--i];
InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1);
}
InsertNode(Base + p, i);
}
}
void* AllocUnitsRare(int indx)
{
if ( !GlueCount )
{
GlueCount = 255;
GlueFreeBlocks();
if (FreeList[indx] != 0)
return RemoveNode(indx);
}
int i = indx;
do
{
if (++i == N_INDEXES)
{
GlueCount--;
i = U2B(Indx2Units[indx]);
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
}
} while (FreeList[i] == 0);
void* RetVal = RemoveNode(i);
SplitBlock(RetVal, i, indx);
return RetVal;
}
void* AllocUnits(int NU)
{
int indx = Units2Indx[NU - 1];
if (FreeList[indx] != 0)
return RemoveNode(indx);
void* RetVal = LoUnit;
LoUnit += U2B(Indx2Units[indx]);
if (LoUnit <= HiUnit)
return RetVal;
LoUnit -= U2B(Indx2Units[indx]);
return AllocUnitsRare(indx);
}
void* AllocContext()
{
if (HiUnit != LoUnit)
return (HiUnit -= UNIT_SIZE);
if (FreeList[0] != 0)
return RemoveNode(0);
return AllocUnitsRare(0);
}
void* ExpandUnits(void* oldPtr, int oldNU)
{
int i0=Units2Indx[oldNU - 1], i1=Units2Indx[oldNU - 1 + 1];
if (i0 == i1)
return oldPtr;
void* ptr = AllocUnits(oldNU + 1);
if (ptr)
{
memcpy(ptr, oldPtr, U2B(oldNU));
InsertNode(oldPtr, i0);
}
return ptr;
}
void* ShrinkUnits(void* oldPtr, int oldNU, int newNU)
{
int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1];
if (i0 == i1)
return oldPtr;
if (FreeList[i1] != 0)
{
void* ptr = RemoveNode(i1);
memcpy(ptr, oldPtr, U2B(newNU));
InsertNode(oldPtr,i0);
return ptr;
}
else
{
SplitBlock(oldPtr, i0, i1);
return oldPtr;
}
}
void FreeUnits(void* ptr, int oldNU)
{
InsertNode(ptr, Units2Indx[oldNU - 1]);
}
};
#endif

View File

@@ -0,0 +1,19 @@
/****************************************************************************
* This file is part of PPMd project *
* Written and distributed to public domain by Dmitry Shkarin 1997, *
* 1999-2001 *
* Contents: compilation parameters and miscelaneous definitions *
* Comments: system & compiler dependent file
* modified by Igor Pavlov (2004-08-29).
****************************************************************************/
#ifndef __PPMD_TYPE_H
#define __PPMD_TYPE_H
const int kMaxOrderCompress = 32;
const int MAX_O = 255; /* maximum allowed model order */
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; }
#endif

View File

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

View File

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

41
CPP/7zip/Compress/PPMD/makefile Executable file
View File

@@ -0,0 +1,41 @@
PROG = PPMd.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../
LIBS = $(LIBS) oleaut32.lib
PPMD_OBJS = \
$O\DllExports.obj \
PPMD_OPT_OBJS = \
$O\PPMDDecoder.obj \
$O\PPMDEncoder.obj \
COMMON_OBJS = \
$O\Alloc.obj \
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
$O\StreamUtils.obj \
OBJS = \
$O\StdAfx.obj \
$(PPMD_OBJS) \
$(PPMD_OPT_OBJS) \
$(COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(PPMD_OBJS): $(*B).cpp
$(COMPL)
$(PPMD_OPT_OBJS): $(*B).cpp
$(COMPL_O2)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)

View File

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