This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions

View File

@@ -2,8 +2,7 @@
#include "StdAfx.h"
#define INITGUID
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "PPMDEncoder.h"

View File

@@ -101,6 +101,10 @@ SOURCE=.\PPMD.def
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc
# End Source File
@@ -197,9 +201,21 @@ SOURCE=..\..\Common\OutBuffer.h
SOURCE=..\RangeCoder\RangeCoder.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\resource.rc
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

View File

@@ -1,15 +1,13 @@
// Compress/PPM/PPMD/Context.h
// Compress/PPMD/Context.h
// This code is based on Dmitry Shkarin's PPMdH code
#pragma once
#ifndef __COMPRESS_PPMD_CONTEXT_H
#define __COMPRESS_PPMD_CONTEXT_H
#ifndef __COMPRESS_PPM_PPMD_CONTEXT_H
#define __COMPRESS_PPM_PPMD_CONTEXT_H
#include "../../../Common/Types.h"
#include "Common/Types.h"
#include "PPMDSubAlloc.h"
#include "../RangeCoder/RangeCoder.h"
#include "PPMDSubAlloc.h"
namespace NCompress {
namespace NPPMD {
@@ -20,12 +18,12 @@ const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
#pragma pack(1)
struct SEE2_CONTEXT
{ // SEE-contexts for PPM-contexts with masked symbols
WORD Summ;
BYTE Shift, Count;
UInt16 Summ;
Byte Shift, Count;
void init(int InitVal) { Summ=InitVal << (Shift=PERIOD_BITS-4); Count=4; }
UINT getMean()
unsigned int getMean()
{
UINT RetVal=(Summ >> Shift);
unsigned int RetVal=(Summ >> Shift);
Summ -= RetVal;
return RetVal+(RetVal == 0);
}
@@ -41,14 +39,14 @@ struct SEE2_CONTEXT
struct PPM_CONTEXT
{
WORD NumStats,SummFreq; // sizeof(WORD) > sizeof(BYTE)
struct STATE { BYTE Symbol, Freq; PPM_CONTEXT* Successor; } _PACK_ATTR * Stats;
UInt16 NumStats,SummFreq; // sizeof(UInt16) > sizeof(Byte)
struct STATE { Byte Symbol, Freq; PPM_CONTEXT* Successor; } _PACK_ATTR * Stats;
PPM_CONTEXT* Suffix;
PPM_CONTEXT* createChild(CSubAllocator &aSubAllocator, STATE* pStats, STATE& FirstState)
PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
{
PPM_CONTEXT* pc = (PPM_CONTEXT*) aSubAllocator.AllocContext();
if ( pc )
PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
if (pc)
{
pc->NumStats = 1;
pc->oneState() = FirstState;
@@ -64,7 +62,7 @@ struct PPM_CONTEXT
/////////////////////////////////
const WORD InitBinEsc[] =
const UInt16 InitBinEsc[] =
{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
struct CInfo
@@ -75,15 +73,15 @@ struct CInfo
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;
WORD BinSumm[128][64]; // binary SEE-contexts
Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
UInt16 BinSumm[128][64]; // binary SEE-contexts
WORD &GetBinSumm(const PPM_CONTEXT::STATE &rs, int aNumStates)
UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
return BinSumm[rs.Freq - 1][
PrevSuccess + NS2BSIndx[aNumStates - 1] +
PrevSuccess + NS2BSIndx[numStates - 1] +
HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
((RunLength >> 26) & 0x20)];
}
@@ -114,7 +112,7 @@ struct CInfo
SEE2Cont[i][k].init(5*i+10);
}
void _FASTCALL StartModelRare(int MaxOrder)
void StartModelRare(int MaxOrder)
{
int i, k, m ,Step;
EscCount=PrintCount=1;
@@ -156,7 +154,7 @@ struct CInfo
}
}
PPM_CONTEXT* CreateSuccessors(BOOL Skip, PPM_CONTEXT::STATE* p1)
PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
{
// static UpState declaration bypasses IntelC bug
// static PPM_CONTEXT::STATE UpState;
@@ -164,7 +162,7 @@ struct CInfo
PPM_CONTEXT* pc = MinContext, * UpBranch = FoundState->Successor;
PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
if ( !Skip )
if ( !skip )
{
*pps++ = FoundState;
if ( !pc->Suffix )
@@ -198,14 +196,14 @@ LOOP_ENTRY:
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol = *(BYTE*) UpBranch;
UpState.Successor = (PPM_CONTEXT*) (((BYTE*) UpBranch)+1);
UpState.Symbol = *(Byte*) UpBranch;
UpState.Successor = (PPM_CONTEXT*) (((Byte*) UpBranch)+1);
if (pc->NumStats != 1)
{
if ((p = pc->Stats)->Symbol != UpState.Symbol)
do { p++; } while (p->Symbol != UpState.Symbol);
UINT cf = p->Freq-1;
UINT s0 = pc->SummFreq - pc->NumStats - cf;
unsigned int cf = p->Freq-1;
unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
UpState.Freq = 1 + ((2 * cf <= s0) ? (5 * cf > s0) :
((2 * cf + 3 * s0 - 1) / (2 * s0)));
}
@@ -225,7 +223,7 @@ NO_LOOP:
{
PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
PPM_CONTEXT* pc, * Successor;
UINT ns1, ns, cf, sf, s0;
unsigned int ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
{
if (pc->NumStats != 1)
@@ -253,7 +251,7 @@ NO_LOOP:
}
if ( !OrderFall )
{
MinContext = MaxContext = FoundState->Successor = CreateSuccessors(TRUE, p);
MinContext = MaxContext = FoundState->Successor = CreateSuccessors(true, p);
if ( !MinContext )
goto RESTART_MODEL;
return;
@@ -264,8 +262,8 @@ NO_LOOP:
goto RESTART_MODEL;
if ( fs.Successor )
{
if ((BYTE*) fs.Successor <= SubAllocator.pText &&
(fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
if ((Byte*) fs.Successor <= SubAllocator.pText &&
(fs.Successor=CreateSuccessors(false, p)) == NULL)
goto RESTART_MODEL;
if ( !--OrderFall )
{
@@ -363,19 +361,19 @@ RESTART_MODEL:
RunLength = InitRL;
}
SEE2_CONTEXT* makeEscFreq2(int Diff, UINT32 &aScale)
SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)
{
SEE2_CONTEXT* psee2c;
if (MinContext->NumStats != 256)
{
psee2c = SEE2Cont[NS2Indx[Diff-1]] + (Diff < MinContext->Suffix->NumStats - MinContext->NumStats)+
2 * (MinContext->SummFreq < 11 * MinContext->NumStats) + 4 * (NumMasked > Diff) + HiBitsFlag;
aScale = psee2c->getMean();
scale = psee2c->getMean();
}
else
{
psee2c = &DummySEE2Cont;
aScale = 1;
scale = 1;
}
return psee2c;
}
@@ -427,7 +425,7 @@ RESTART_MODEL:
void NextContext()
{
if (!OrderFall && (BYTE*) FoundState->Successor > SubAllocator.pText)
if (!OrderFall && (Byte*) FoundState->Successor > SubAllocator.pText)
MinContext = MaxContext = FoundState->Successor;
else
{
@@ -439,7 +437,7 @@ RESTART_MODEL:
};
// 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 };
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))
}}

View File

@@ -1,10 +1,8 @@
// Decode.h
// PPMDDecode.h
// This code is based on Dmitry Shkarin's PPMdH code
#pragma once
#ifndef __COMPRESS_PPM_PPMD_DECODE_H
#define __COMPRESS_PPM_PPMD_DECODE_H
#ifndef __COMPRESS_PPMD_DECODE_H
#define __COMPRESS_PPMD_DECODE_H
#include "PPMDContext.h"
@@ -16,18 +14,18 @@ struct CDecodeInfo: public CInfo
void DecodeBinSymbol(NRangeCoder::CDecoder *rangeDecoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
WORD& bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
UInt16& bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0)
{
FoundState = &rs;
rs.Freq += (rs.Freq < 128);
bs += UINT16(INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
bs += UInt16(INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
PrevSuccess = 1;
RunLength++;
}
else
{
bs -= UINT16(GET_MEAN(bs,PERIOD_BITS,2));
bs -= UInt16(GET_MEAN(bs,PERIOD_BITS,2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
@@ -44,7 +42,7 @@ struct CDecodeInfo: public CInfo
{
PrevSuccess = (2 * hiCnt > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeDecoder->Decode(0, MinContext->Stats->Freq, MinContext->SummFreq);
rangeDecoder->Decode(0, MinContext->Stats->Freq); // MinContext->SummFreq);
(FoundState = p)->Freq=(hiCnt += 4);
MinContext->SummFreq += 4;
if (hiCnt > MAX_FREQ)
@@ -57,14 +55,14 @@ struct CDecodeInfo: public CInfo
if (--i == 0)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt, MinContext->SummFreq);
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);
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq);
update1(p);
}
@@ -72,7 +70,7 @@ struct CDecodeInfo: public CInfo
void DecodeSymbol2(NRangeCoder::CDecoder *rangeDecoder)
{
int count, hiCnt, i = MinContext->NumStats - NumMasked;
UINT32 freqSum;
UInt32 freqSum;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum);
PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = MinContext->Stats-1;
hiCnt = 0;
@@ -93,14 +91,14 @@ struct CDecodeInfo: public CInfo
hiCnt = 0;
while ((hiCnt += p->Freq) <= count)
p=*++pps;
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq, freqSum);
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum);
psee2c->update();
update2(p);
}
else
{
rangeDecoder->Decode(hiCnt, freqSum - hiCnt, freqSum);
rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum);
i = MinContext->NumStats - NumMasked;
pps--;
@@ -128,7 +126,7 @@ struct CDecodeInfo: public CInfo
while (MinContext->NumStats == NumMasked);
DecodeSymbol2(rangeDecoder);
}
BYTE symbol = FoundState->Symbol;
Byte symbol = FoundState->Symbol;
NextContext();
return symbol;
}

View File

@@ -10,17 +10,14 @@
namespace NCompress {
namespace NPPMD {
STDMETHODIMP CDecoder::SetDecoderProperties(ISequentialInStream *inStream)
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
{
UINT32 processedSize;
RINOK(inStream->Read(&_order,
sizeof(_order), &processedSize));
if (processedSize != sizeof(_order))
return E_FAIL;
RINOK(inStream->Read(&_usedMemorySize,
sizeof(_usedMemorySize), &processedSize));
if (processedSize != sizeof(_usedMemorySize))
return E_FAIL;
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);
return S_OK;
}
@@ -32,51 +29,46 @@ public:
~CDecoderFlusher()
{
_coder->Flush();
// _coder->ReleaseStreams();
_coder->ReleaseStreams();
}
};
UINT32 GetMatchLen(const BYTE *pointer1, const BYTE *pointer2,
UINT32 limit)
UInt32 GetMatchLen(const Byte *pointer1, const Byte *pointer2,
UInt32 limit)
{
UINT32 i;
UInt32 i;
for(i = 0; i < limit && *pointer1 == *pointer2;
pointer1++, pointer2++, i++);
return i;
}
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
_rangeDecoder.Init(inStream);
_outStream.Init(outStream);
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_outStream.Create(1 << 20))
return E_OUTOFMEMORY;
_rangeDecoder.SetStream(inStream);
_rangeDecoder.Init();
_outStream.SetStream(outStream);
_outStream.Init();
CDecoderFlusher flusher(this);
/*
if (outSize == NULL)
return E_INVALIDARG;
*/
UInt64 progressPosValuePrev = 0, pos = 0;
UINT64 progressPosValuePrev = 0, pos = 0;
try
{
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY;
}
catch(...)
{
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY;
}
// _info.Init();
// _info.MaxOrder = _order;
_info.MaxOrder = 0;
_info.StartModelRare(_order);
UINT64 size = (outSize == NULL) ? (UINT64)(INT64)(-1) : *outSize;
UInt64 size = (outSize == NULL) ? (UInt64)(Int64)(-1) : *outSize;
while(pos < size)
{
@@ -87,7 +79,7 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
_outStream.WriteByte(symbol);
if (pos - progressPosValuePrev >= (1 << 18) && progress != NULL)
{
UINT64 inSize = _rangeDecoder.GetProcessedSize();
UInt64 inSize = _rangeDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &pos));
progressPosValuePrev = pos;
}
@@ -96,7 +88,7 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
@@ -105,5 +97,4 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
catch(...) { return E_FAIL; }
}
}}

View File

@@ -1,11 +1,9 @@
// Compress/PPM/PPMDDecoder.h
#pragma once
#ifndef __COMPRESS_PPMD_DECODER_H
#define __COMPRESS_PPMD_DECODER_H
#ifndef __COMPRESS_PPM_PPMD_DECODER_H
#define __COMPRESS_PPM_PPMD_DECODER_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/OutBuffer.h"
@@ -18,7 +16,7 @@ namespace NPPMD {
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties,
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
NRangeCoder::CDecoder _rangeDecoder;
@@ -27,39 +25,32 @@ class CDecoder :
CDecodeInfo _info;
BYTE _order;
UINT32 _usedMemorySize;
Byte _order;
UInt32 _usedMemorySize;
public:
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties)
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
/*
void ReleaseStreams()
{
_rangeDecoder.ReleaseStream();
_outStream.ReleaseStream();
}
*/
// STDMETHOD(Code)(UINT32 aNumBytes, UINT32 &aProcessedBytes);
HRESULT Flush()
{ return _outStream.Flush(); }
HRESULT Flush() { return _outStream.Flush(); }
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetDecoderProperties
STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
};
}}

View File

@@ -1,10 +1,8 @@
// PPMDEncode.h
// This code is based on Dmitry Shkarin's PPMdH code
#pragma once
#ifndef __COMPRESS_PPM_PPMD_ENCODE_H
#define __COMPRESS_PPM_PPMD_ENCODE_H
#ifndef __COMPRESS_PPMD_ENCODE_H
#define __COMPRESS_PPMD_ENCODE_H
#include "PPMDContext.h"
@@ -17,20 +15,20 @@ struct CEncodeInfo: public CInfo
void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
WORD &bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
UInt16 &bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
if (rs.Symbol == symbol)
{
FoundState = &rs;
rs.Freq += (rs.Freq < 128);
rangeEncoder->EncodeBit(bs, TOT_BITS, 0);
bs += UINT16(INTERVAL-GET_MEAN(bs,PERIOD_BITS, 2));
bs += UInt16(INTERVAL-GET_MEAN(bs,PERIOD_BITS, 2));
PrevSuccess = 1;
RunLength++;
}
else
{
rangeEncoder->EncodeBit(bs, TOT_BITS, 1);
bs -= UINT16(GET_MEAN(bs,PERIOD_BITS, 2));
bs -= UInt16(GET_MEAN(bs,PERIOD_BITS, 2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
@@ -76,7 +74,7 @@ struct CEncodeInfo: public CInfo
void EncodeSymbol2(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
int hiCnt, i = MinContext->NumStats - NumMasked;
UINT32 scale;
UInt32 scale;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale);
PPM_CONTEXT::STATE* p = MinContext->Stats - 1;
hiCnt = 0;
@@ -98,8 +96,8 @@ struct CEncodeInfo: public CInfo
return;
SYMBOL_FOUND:
UINT32 highCount = hiCnt;
UINT32 lowCount = highCount - p->Freq;
UInt32 highCount = hiCnt;
UInt32 lowCount = highCount - p->Freq;
if ( --i )
{
PPM_CONTEXT::STATE* p1 = p;

View File

@@ -14,13 +14,16 @@
namespace NCompress {
namespace NPPMD {
/*
UINT32 g_NumInner = 0;
UINT32 g_InnerCycles = 0;
const UInt32 kMinMemSize = (1 << 11);
const UInt32 kMinOrder = 2;
UINT32 g_Encode2 = 0;
UINT32 g_Encode2Cycles = 0;
UINT32 g_Encode2Cycles2 = 0;
/*
UInt32 g_NumInner = 0;
UInt32 g_InnerCycles = 0;
UInt32 g_Encode2 = 0;
UInt32 g_Encode2Cycles = 0;
UInt32 g_Encode2Cycles2 = 0;
class CCounter
{
@@ -53,9 +56,9 @@ STDMETHODIMP CEncoder::SetRangeEncoder(CRangeEncoder *aRangeEncoder)
*/
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties)
const PROPVARIANT *properties, UInt32 numProperties)
{
for (UINT32 i = 0; i < numProperties; i++)
for (UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &aProperty = properties[i];
switch(propIDs[i])
@@ -72,7 +75,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
return E_INVALIDARG;
if (aProperty.ulVal < kMinOrder || aProperty.ulVal > kMaxOrderCompress)
return E_INVALIDARG;
_order = BYTE(aProperty.ulVal);
_order = Byte(aProperty.ulVal);
break;
default:
return E_INVALIDARG;
@@ -83,11 +86,15 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
RINOK(outStream->Write(&_order, sizeof(_order), NULL));
return outStream->Write(&_usedMemorySize, sizeof(_usedMemorySize), NULL);
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 outStream->Write(properties, kPropSize, NULL);
}
const UINT32 kUsedMemorySizeDefault = (1 << 24);
const UInt32 kUsedMemorySizeDefault = (1 << 24);
const int kOrderDefault = 6;
CEncoder::CEncoder():
@@ -112,7 +119,7 @@ public:
~CEncoderFlusher()
{
_encoder->Flush();
// _encoder->ReleaseStreams();
_encoder->ReleaseStreams();
}
};
@@ -120,16 +127,23 @@ public:
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
_inStream.Init(inStream);
_rangeEncoder.Init(outStream);
if (!_inStream.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_rangeEncoder.Create(1 << 20))
return E_OUTOFMEMORY;
CEncoderFlusher aFlusher(this);
_inStream.SetStream(inStream);
_inStream.Init();
_rangeEncoder.SetStream(outStream);
_rangeEncoder.Init();
UINT64 pos = 0;
UINT64 prevProgressPos = 0;
CEncoderFlusher flusher(this);
UInt64 pos = 0;
UInt64 prevProgressPos = 0;
try
{
@@ -148,7 +162,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
while (true)
{
BYTE symbol;
Byte symbol;
if (!_inStream.ReadByte(symbol))
{
// here we can write End Mark for stream version.
@@ -161,7 +175,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
pos++;
if (pos - prevProgressPos >= (1 << 18) && progress != NULL)
{
UINT64 outSize = _rangeEncoder.GetProcessedSize();
UInt64 outSize = _rangeEncoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&pos, &outSize));
prevProgressPos = pos;
}
@@ -169,7 +183,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
}
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }

View File

@@ -1,11 +1,9 @@
// Compress/PPMD/Encoder.h
#pragma once
#ifndef __COMPRESS_PPMD_ENCODER_H
#define __COMPRESS_PPMD_ENCODER_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/InBuffer.h"
@@ -28,8 +26,8 @@ public:
NRangeCoder::CEncoder _rangeEncoder;
CEncodeInfo _info;
UINT32 _usedMemorySize;
BYTE _order;
UInt32 _usedMemorySize;
Byte _order;
public:
@@ -39,23 +37,21 @@ public:
// ICoder interface
HRESULT Flush();
/*
void ReleaseStreams()
{
_inStream.ReleaseStream();
_rangeEncoder.ReleaseStream();
}
*/
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties);
const PROPVARIANT *properties, UInt32 numProperties);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

View File

@@ -1,35 +1,42 @@
// SubAlloc.h
// PPMDSubAlloc.h
// This code is based on Dmitry Shkarin's PPMdH code
#pragma once
#ifndef __PPMD_SUBALLOC_H
#define __PPMD_SUBALLOC_H
#ifndef __SubAlloc_H
#define __SubAlloc_H
#include "PPMDType.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;
#pragma pack(1)
struct MEM_BLK {
WORD Stamp, NU;
MEM_BLK* next, * prev;
void insertAt(MEM_BLK* p) {
next=(prev=p)->next; p->next=next->prev=this;
}
void remove() { prev->next=next; next->prev=prev; }
struct MEM_BLK
{
UInt16 Stamp, NU;
MEM_BLK *Next, *Prev;
void InsertAt(MEM_BLK* p)
{
Next = (Prev = p)->Next;
p->Next = Next->Prev = this;
}
void Remove()
{
Prev->Next=Next;
Next->Prev=Prev;
}
} _PACK_ATTR;
#pragma pack()
class CSubAllocator
{
DWORD SubAllocatorSize;
BYTE Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
struct NODE { NODE* next; } FreeList[N_INDEXES];
UInt32 SubAllocatorSize;
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
struct NODE { NODE* Next; } FreeList[N_INDEXES];
public:
BYTE* HeapStart, * pText, * UnitsStart, * LoUnit, * HiUnit;
Byte* HeapStart, *pText, *UnitsStart, *LoUnit, *HiUnit;
CSubAllocator():
SubAllocatorSize(0),
GlueCount(0),
@@ -47,159 +54,200 @@ public:
};
inline void InsertNode(void* p,int indx) {
((NODE*) p)->next=FreeList[indx].next; FreeList[indx].next=(NODE*) p;
}
inline void* RemoveNode(int indx) {
NODE* RetVal=FreeList[indx].next; FreeList[indx].next=RetVal->next;
return RetVal;
}
inline UINT U2B(int NU) { return 8*NU+4*NU; }
inline 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]);
}
void InsertNode(void* p, int indx)
{
((NODE*) p)->Next = FreeList[indx].Next;
FreeList[indx].Next = (NODE*)p;
}
DWORD _STDCALL GetUsedMemory()
{
DWORD i, k, RetVal=SubAllocatorSize-(HiUnit-LoUnit)-(UnitsStart-pText);
for (k=i=0;i < N_INDEXES;i++, k=0) {
for (NODE* pn=FreeList+i;(pn=pn->next) != NULL;k++)
;
RetVal -= UNIT_SIZE*Indx2Units[i]*k;
void* RemoveNode(int indx)
{
NODE* RetVal = FreeList[indx].Next;
FreeList[indx].Next = RetVal->Next;
return RetVal;
}
UINT U2B(int NU) { return 8 * NU + 4 * NU; }
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()
{
UInt32 i, k, RetVal = SubAllocatorSize - (HiUnit - LoUnit) - (UnitsStart-pText);
for (k = i = 0; i < N_INDEXES; i++, k = 0)
{
for (NODE* pn = FreeList + i;(pn = pn->Next) != NULL; k++)
;
RetVal -= UNIT_SIZE*Indx2Units[i] * k;
}
return (RetVal >> 2);
}
void _STDCALL StopSubAllocator()
}
void StopSubAllocator()
{
if ( SubAllocatorSize )
{
#ifdef WIN32
VirtualFree(HeapStart, 0, MEM_RELEASE);
#else
delete[] HeapStart;
#endif
BigFree(HeapStart);
SubAllocatorSize = 0;
HeapStart = 0;
}
}
bool _STDCALL StartSubAllocator(UINT32 aSize)
bool StartSubAllocator(UInt32 size)
{
if (SubAllocatorSize == aSize)
if (SubAllocatorSize == size)
return true;
StopSubAllocator();
#ifdef WIN32
if ((HeapStart = (BYTE *)::VirtualAlloc(0, aSize, MEM_COMMIT, PAGE_READWRITE)) == 0)
if ((HeapStart = (Byte *)::BigAlloc(size)) == 0)
return false;
#else
if ((HeapStart = new BYTE[aSize]) == NULL)
return false;
#endif
SubAllocatorSize = aSize;
SubAllocatorSize = size;
return true;
}
inline void InitSubAllocator()
{
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]=k;
for (k++;i < N1+N2 ;i++,k += 2) Indx2Units[i]=k;
for (k++;i < N1+N2+N3 ;i++,k += 3) Indx2Units[i]=k;
for (k++;i < N1+N2+N3+N4;i++,k += 4) Indx2Units[i]=k;
for (GlueCount=k=i=0;k < 128;k++) {
i += (Indx2Units[i] < k+1); Units2Indx[k]=i;
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]=k;
for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i]=k;
for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i]=k;
for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i]=k;
for (GlueCount = k = i = 0; k < 128; k++)
{
i += (Indx2Units[i] < k+1);
Units2Indx[k]=i;
}
}
inline void GlueFreeBlocks()
{
MEM_BLK s0, * p, * p1;
}
void GlueFreeBlocks()
{
MEM_BLK s0, *p, *p1;
int i, k, sz;
if (LoUnit != HiUnit) *LoUnit=0;
for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
while ( FreeList[i].next ) {
p=(MEM_BLK*) RemoveNode(i); p->insertAt(&s0);
p->Stamp=0xFFFF; p->NU=Indx2Units[i];
}
for (p=s0.next;p != &s0;p=p->next)
while ((p1=p+p->NU)->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000) {
p1->remove(); p->NU += p1->NU;
}
while ((p=s0.next) != &s0) {
for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p += 128)
InsertNode(p,N_INDEXES-1);
if (Indx2Units[i=Units2Indx[sz-1]] != sz) {
k=sz-Indx2Units[--i]; InsertNode(p+(sz-k),k-1);
}
InsertNode(p,i);
if (LoUnit != HiUnit)
*LoUnit=0;
for (i = 0, s0.Next = s0.Prev = &s0; i < N_INDEXES; i++)
while ( FreeList[i].Next )
{
p = (MEM_BLK*) RemoveNode(i);
p->InsertAt(&s0);
p->Stamp = 0xFFFF;
p->NU = Indx2Units[i];
}
for (p=s0.Next; p != &s0; p =p->Next)
while ((p1 = p + p->NU)->Stamp == 0xFFFF && int(p->NU) + p1->NU < 0x10000)
{
p1->Remove();
p->NU += p1->NU;
}
while ((p=s0.Next) != &s0)
{
for (p->Remove(), sz=p->NU; sz > 128; sz -= 128, p += 128)
InsertNode(p, N_INDEXES - 1);
if (Indx2Units[i = Units2Indx[sz-1]] != sz)
{
k = sz-Indx2Units[--i];
InsertNode(p + (sz - k), k - 1);
}
InsertNode(p,i);
}
}
void* AllocUnitsRare(int indx)
{
if ( !GlueCount ) {
GlueCount = 255; GlueFreeBlocks();
if ( FreeList[indx].next ) return RemoveNode(indx);
}
void* AllocUnitsRare(int indx)
{
if ( !GlueCount )
{
GlueCount = 255;
GlueFreeBlocks();
if (FreeList[indx].Next)
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].next );
void* RetVal=RemoveNode(i); SplitBlock(RetVal,i,indx);
int i = indx;
do
{
if (++i == N_INDEXES)
{
GlueCount--;
i = U2B(Indx2Units[indx]);
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
}
} while (!FreeList[i].Next);
void* RetVal = RemoveNode(i);
SplitBlock(RetVal, i, indx);
return RetVal;
}
inline void* AllocUnits(int NU)
{
int indx=Units2Indx[NU-1];
if ( FreeList[indx].next ) return RemoveNode(indx);
void* RetVal=LoUnit; LoUnit += U2B(Indx2Units[indx]);
if (LoUnit <= HiUnit) return RetVal;
LoUnit -= U2B(Indx2Units[indx]); return AllocUnitsRare(indx);
}
inline void* AllocContext()
{
if (HiUnit != LoUnit) return (HiUnit -= UNIT_SIZE);
if ( FreeList->next ) return RemoveNode(0);
}
void* AllocUnits(int NU)
{
int indx = Units2Indx[NU - 1];
if (FreeList[indx].Next)
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->Next)
return RemoveNode(0);
return AllocUnitsRare(0);
}
inline 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);
}
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;
}
inline 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].next ) {
void* ptr=RemoveNode(i1); memcpy(ptr,OldPtr,U2B(NewNU));
InsertNode(OldPtr,i0); return ptr;
} else {
SplitBlock(OldPtr,i0,i1); return OldPtr;
}
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].Next )
{
void* ptr = RemoveNode(i1);
memcpy(ptr, oldPtr, U2B(newNU));
InsertNode(oldPtr,i0);
return ptr;
}
else
{
SplitBlock(oldPtr, i0, i1);
return oldPtr;
}
}
inline void FreeUnits(void* ptr,int OldNU)
{
InsertNode(ptr,Units2Indx[OldNU-1]);
}
}
void FreeUnits(void* ptr, int oldNU)
{
InsertNode(ptr, Units2Indx[oldNU - 1]);
}
};
#endif

View File

@@ -3,45 +3,15 @@
* Written and distributed to public domain by Dmitry Shkarin 1997, *
* 1999-2001 *
* Contents: compilation parameters and miscelaneous definitions *
* Comments: system & compiler dependent file *
* Comments: system & compiler dependent file
* modified by Igor Pavlov (2004-08-29).
****************************************************************************/
#if !defined(_PPMDTYPE_H_)
#define _PPMDTYPE_H_
#ifndef __PPMD_TYPE_H
#define __PPMD_TYPE_H
#include <stdio.h>
const UINT32 kMinMemSize = (1 << 11);
const UINT32 kMinOrder = 2;
const int kMaxOrderCompress = 32;
const int MAX_O=255; /* maximum allowed model order */
#define _WIN32_ENVIRONMENT_
//#define _DOS32_ENVIRONMENT_
//#define _POSIX_ENVIRONMENT_
//#define _UNKNOWN_ENVIRONMENT_
#if defined(_WIN32_ENVIRONMENT_)+defined(_DOS32_ENVIRONMENT_)+defined(_POSIX_ENVIRONMENT_)+defined(_UNKNOWN_ENVIRONMENT_) != 1
#error Only one environment must be defined
#endif /* defined(_WIN32_ENVIRONMENT_)+defined(_DOS32_ENVIRONMENT_)+defined(_POSIX_ENVIRONMENT_)+defined(_UNKNOWN_ENVIRONMENT_) != 1 */
#if defined(_WIN32_ENVIRONMENT_)
#include <wtypes.h>
#else /* _DOS32_ENVIRONMENT_ || _POSIX_ENVIRONMENT_ || _UNKNOWN_ENVIRONMENT_ */
typedef int BOOL;
#define FALSE 0
#define TRUE 1
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned int UINT;
#endif /* defined(_WIN32_ENVIRONMENT_) */
#if !defined(_UNKNOWN_ENVIRONMENT_) && !defined(__GNUC__)
#define _FASTCALL __fastcall
#define _STDCALL __stdcall
#else
#define _FASTCALL
#define _STDCALL
#endif /* !defined(_UNKNOWN_ENVIRONMENT_) && !defined(__GNUC__) */
const int MAX_O = 255; /* maximum allowed model order */
#if defined(__GNUC__)
#define _PACK_ATTR __attribute__ ((packed))
@@ -49,14 +19,7 @@ typedef unsigned int UINT;
#define _PACK_ATTR
#endif /* defined(__GNUC__) */
// PPMd module works with file streams via ...GETC/...PUTC macros only
typedef FILE _PPMD_FILE;
#define _PPMD_E_GETC(fp) getc(fp)
#define _PPMD_E_PUTC(c,fp) putc((c),fp)
#define _PPMD_D_GETC(fp) getc(fp)
#define _PPMD_D_PUTC(c,fp) putc((c),fp)
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; }
#endif /* !defined(_PPMDTYPE_H_) */
#endif

View File

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,9,2,0
PRODUCTVERSION 3,9,2,0
FILEVERSION 4,16,0,0
PRODUCTVERSION 4,16,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -85,14 +85,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "PPMd Coder\0"
VALUE "FileVersion", "3, 9, 2, 0\0"
VALUE "FileVersion", "4, 16, 0, 0\0"
VALUE "InternalName", "PPMd\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "PPMd.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 9, 2, 0\0"
VALUE "ProductVersion", "4, 16, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END