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

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Compress/PPMD
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Compress/PPMD')
-rwxr-xr-xCPP/7zip/Compress/PPMD/DllExports.cpp93
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMD.dsp229
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMD.dsw29
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDContext.h489
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDDecode.h154
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDDecoder.cpp184
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDDecoder.h89
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDEncode.h142
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDEncoder.cpp155
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDEncoder.h81
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDSubAlloc.h292
-rwxr-xr-xCPP/7zip/Compress/PPMD/PPMDType.h19
-rwxr-xr-xCPP/7zip/Compress/PPMD/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Compress/PPMD/StdAfx.h8
-rwxr-xr-xCPP/7zip/Compress/PPMD/makefile41
-rwxr-xr-xCPP/7zip/Compress/PPMD/resource.rc3
16 files changed, 2011 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/PPMD/DllExports.cpp b/CPP/7zip/Compress/PPMD/DllExports.cpp
new file mode 100755
index 00000000..8159a2f8
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/DllExports.cpp
@@ -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;
+}
diff --git a/CPP/7zip/Compress/PPMD/PPMD.dsp b/CPP/7zip/Compress/PPMD/PPMD.dsp
new file mode 100755
index 00000000..9e512f6c
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMD.dsp
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMD.dsw b/CPP/7zip/Compress/PPMD/PPMD.dsw
new file mode 100755
index 00000000..8032f3db
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMD.dsw
@@ -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>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Compress/PPMD/PPMDContext.h b/CPP/7zip/Compress/PPMD/PPMDContext.h
new file mode 100755
index 00000000..a6a8dd60
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDContext.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDDecode.h b/CPP/7zip/Compress/PPMD/PPMDDecode.h
new file mode 100755
index 00000000..b05d8ee0
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDDecode.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp b/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp
new file mode 100755
index 00000000..2d0a2f52
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp
@@ -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
+
+}}
diff --git a/CPP/7zip/Compress/PPMD/PPMDDecoder.h b/CPP/7zip/Compress/PPMD/PPMDDecoder.h
new file mode 100755
index 00000000..8e30c35c
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDDecoder.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDEncode.h b/CPP/7zip/Compress/PPMD/PPMDEncode.h
new file mode 100755
index 00000000..6a720cac
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDEncode.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp b/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp
new file mode 100755
index 00000000..fe99ea5a
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp
@@ -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; }
+}
+
+}}
diff --git a/CPP/7zip/Compress/PPMD/PPMDEncoder.h b/CPP/7zip/Compress/PPMD/PPMDEncoder.h
new file mode 100755
index 00000000..915180b9
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDEncoder.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h b/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h
new file mode 100755
index 00000000..dce765d6
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/PPMDType.h b/CPP/7zip/Compress/PPMD/PPMDType.h
new file mode 100755
index 00000000..5200fa54
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/PPMDType.h
@@ -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
diff --git a/CPP/7zip/Compress/PPMD/StdAfx.cpp b/CPP/7zip/Compress/PPMD/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Compress/PPMD/StdAfx.h b/CPP/7zip/Compress/PPMD/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif
diff --git a/CPP/7zip/Compress/PPMD/makefile b/CPP/7zip/Compress/PPMD/makefile
new file mode 100755
index 00000000..2e687a70
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/makefile
@@ -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)
+
diff --git a/CPP/7zip/Compress/PPMD/resource.rc b/CPP/7zip/Compress/PPMD/resource.rc
new file mode 100755
index 00000000..fed98e19
--- /dev/null
+++ b/CPP/7zip/Compress/PPMD/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("PPMd Codec", "PPMd")