4.27 beta

This commit is contained in:
Igor Pavlov
2005-09-21 00:00:00 +00:00
committed by Kornel Lesiński
parent 31e7b924e8
commit d66cf2fcf3
393 changed files with 17345 additions and 4743 deletions
+8
View File
@@ -192,6 +192,14 @@ SOURCE=..\..\Common\OutBuffer.cpp
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"
+96 -57
View File
@@ -15,9 +15,9 @@ 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;
#pragma pack(1)
struct SEE2_CONTEXT
{ // SEE-contexts for PPM-contexts with masked symbols
{
// SEE-contexts for PPM-contexts with masked symbols
UInt16 Summ;
Byte Shift, Count;
void init(int InitVal) { Summ=InitVal << (Shift=PERIOD_BITS-4); Count=4; }
@@ -39,9 +39,25 @@ struct SEE2_CONTEXT
struct PPM_CONTEXT
{
UInt16 NumStats,SummFreq; // sizeof(UInt16) > sizeof(Byte)
struct STATE { Byte Symbol, Freq; PPM_CONTEXT* Successor; } _PACK_ATTR * Stats;
PPM_CONTEXT* Suffix;
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)
{
@@ -50,15 +66,14 @@ struct PPM_CONTEXT
{
pc->NumStats = 1;
pc->oneState() = FirstState;
pc->Suffix = this;
pStats->Successor = pc;
pc->Suffix = subAllocator.GetOffset(this);
pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
}
return pc;
}
STATE& oneState() const { return (STATE&) SummFreq; }
};
#pragma pack()
/////////////////////////////////
@@ -68,8 +83,8 @@ const UInt16 InitBinEsc[] =
struct CInfo
{
CSubAllocator SubAllocator;
SEE2_CONTEXT _PACK_ATTR SEE2Cont[25][16], DummySEE2Cont;
PPM_CONTEXT _PACK_ATTR * MinContext, * MaxContext;
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;
@@ -86,6 +101,11 @@ struct CInfo
((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;
@@ -93,15 +113,17 @@ struct CInfo
SubAllocator.InitSubAllocator();
InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
MinContext->Suffix = NULL;
MinContext->Suffix = 0;
OrderFall = MaxOrder;
MinContext->SummFreq = (MinContext->NumStats = 256) + 1;
FoundState = MinContext->Stats = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(256 / 2);
FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
for (RunLength = InitRL, PrevSuccess = i = 0; i < 256; i++)
{
MinContext->Stats[i].Symbol = i;
MinContext->Stats[i].Freq = 1;
MinContext->Stats[i].Successor = NULL;
PPM_CONTEXT::STATE &state = FoundState[i];
state.Symbol = i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
@@ -121,12 +143,12 @@ struct CInfo
memset(CharMask,0,sizeof(CharMask));
OrderFall = this->MaxOrder;
MinContext = MaxContext;
while (MinContext->Suffix != NULL)
while (MinContext->Suffix != 0)
{
MinContext = MinContext->Suffix;
OrderFall--;
MinContext = GetContextNoCheck(MinContext->Suffix);
OrderFall--;
}
FoundState = MinContext->Stats;
FoundState = GetState(MinContext->Stats);
MinContext = MaxContext;
}
else
@@ -160,7 +182,8 @@ struct CInfo
// static PPM_CONTEXT::STATE UpState;
PPM_CONTEXT::STATE UpState;
PPM_CONTEXT* pc = MinContext, * UpBranch = FoundState->Successor;
PPM_CONTEXT *pc = MinContext;
PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
if ( !skip )
{
@@ -171,23 +194,23 @@ struct CInfo
if ( p1 )
{
p = p1;
pc = pc->Suffix;
pc = GetContext(pc->Suffix);
goto LOOP_ENTRY;
}
do
{
pc = pc->Suffix;
pc = GetContext(pc->Suffix);
if (pc->NumStats != 1)
{
if ((p = pc->Stats)->Symbol != FoundState->Symbol)
if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
do { p++; } while (p->Symbol != FoundState->Symbol);
}
else
p = &(pc->oneState());
LOOP_ENTRY:
if (p->Successor != UpBranch)
if (GetContext(p->GetSuccessor()) != UpBranch)
{
pc = p->Successor;
pc = GetContext(p->GetSuccessor());
break;
}
*pps++ = p;
@@ -197,10 +220,10 @@ NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol = *(Byte*) UpBranch;
UpState.Successor = (PPM_CONTEXT*) (((Byte*) UpBranch)+1);
UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
if (pc->NumStats != 1)
{
if ((p = pc->Stats)->Symbol != UpState.Symbol)
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;
@@ -224,11 +247,13 @@ NO_LOOP:
PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
PPM_CONTEXT* pc, * Successor;
unsigned int ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)
{
pc = GetContextNoCheck(MinContext->Suffix);
if (pc->NumStats != 1)
{
if ((p = pc->Stats)->Symbol != fs.Symbol)
if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)
{
do { p++; } while (p->Symbol != fs.Symbol);
if (p[0].Freq >= p[-1].Freq)
@@ -251,8 +276,9 @@ NO_LOOP:
}
if ( !OrderFall )
{
MinContext = MaxContext = FoundState->Successor = CreateSuccessors(true, p);
if ( !MinContext )
MinContext = MaxContext = CreateSuccessors(true, p);
FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));
if (MinContext == 0)
goto RESTART_MODEL;
return;
}
@@ -260,31 +286,36 @@ NO_LOOP:
Successor = (PPM_CONTEXT*) SubAllocator.pText;
if (SubAllocator.pText >= SubAllocator.UnitsStart)
goto RESTART_MODEL;
if ( fs.Successor )
if (fs.GetSuccessor() != 0)
{
if ((Byte*) fs.Successor <= SubAllocator.pText &&
(fs.Successor=CreateSuccessors(false, p)) == NULL)
goto RESTART_MODEL;
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 = fs.Successor;
Successor = GetContext(fs.GetSuccessor());
SubAllocator.pText -= (MaxContext != MinContext);
}
}
else
{
FoundState->Successor = Successor;
fs.Successor = MinContext;
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 = pc->Suffix)
for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))
{
if ((ns1 = pc->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
pc->Stats = (PPM_CONTEXT::STATE*) SubAllocator.ExpandUnits(pc->Stats, ns1 >> 1);
if ( !pc->Stats )
void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);
pc->Stats = SubAllocator.GetOffset(ppp);
if (!ppp)
goto RESTART_MODEL;
}
pc->SummFreq += (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &
@@ -296,7 +327,7 @@ NO_LOOP:
if ( !p )
goto RESTART_MODEL;
*p = pc->oneState();
pc->Stats = p;
pc->Stats = SubAllocator.GetOffsetNoCheck(p);
if (p->Freq < MAX_FREQ / 4 - 1)
p->Freq += p->Freq;
else
@@ -315,13 +346,13 @@ NO_LOOP:
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
pc->SummFreq += cf;
}
p = pc->Stats + ns1;
p->Successor = Successor;
p = GetState(pc->Stats) + ns1;
p->SetSuccessor(SubAllocator.GetOffset(Successor));
p->Symbol = fs.Symbol;
p->Freq = cf;
pc->NumStats = ++ns1;
}
MaxContext = MinContext = fs.Successor;
MaxContext = MinContext = GetContext(fs.GetSuccessor());
return;
RESTART_MODEL:
RestartModelRare();
@@ -366,8 +397,11 @@ RESTART_MODEL:
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;
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
@@ -384,9 +418,10 @@ RESTART_MODEL:
{
int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;
PPM_CONTEXT::STATE* p1, * p;
for (p = FoundState; p != MinContext->Stats; p--)
PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);
for (p = FoundState; p != stats; p--)
_PPMD_SWAP(p[0], p[-1]);
MinContext->Stats->Freq += 4;
stats->Freq += 4;
MinContext->SummFreq += 4;
EscFreq = MinContext->SummFreq - p->Freq;
Adder = (OrderFall != 0);
@@ -398,7 +433,11 @@ RESTART_MODEL:
if (p[0].Freq > p[-1].Freq)
{
PPM_CONTEXT::STATE tmp = *(p1 = p);
do { p1[0] = p1[-1]; } while (--p1 != MinContext->Stats && tmp.Freq > p1[-1].Freq);
do
{
p1[0] = p1[-1];
}
while (--p1 != stats && tmp.Freq > p1[-1].Freq);
*p1 = tmp;
}
}
@@ -409,24 +448,24 @@ RESTART_MODEL:
EscFreq += i;
if ((MinContext->NumStats -= i) == 1)
{
PPM_CONTEXT::STATE tmp = *MinContext->Stats;
PPM_CONTEXT::STATE tmp = *stats;
do { tmp.Freq -= (tmp.Freq >> 1); EscFreq >>= 1; } while (EscFreq > 1);
SubAllocator.FreeUnits(MinContext->Stats, (OldNS+1) >> 1);
SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);
*(FoundState = &MinContext->oneState()) = tmp; return;
}
}
MinContext->SummFreq += (EscFreq -= (EscFreq >> 1));
int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;
if (n0 != n1)
MinContext->Stats =
(PPM_CONTEXT::STATE*) SubAllocator.ShrinkUnits(MinContext->Stats, n0, n1);
FoundState = MinContext->Stats;
MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));
FoundState = GetState(MinContext->Stats);
}
void NextContext()
{
if (!OrderFall && (Byte*) FoundState->Successor > SubAllocator.pText)
MinContext = MaxContext = FoundState->Successor;
PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());
if (!OrderFall && (Byte *)c > SubAllocator.pText)
MinContext = MaxContext = c;
else
{
UpdateModel();
+6 -6
View File
@@ -14,7 +14,7 @@ struct CDecodeInfo: public CInfo
void DecodeBinSymbol(NRangeCoder::CDecoder *rangeDecoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16& bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0)
{
FoundState = &rs;
@@ -36,13 +36,13 @@ struct CDecodeInfo: public CInfo
void DecodeSymbol1(NRangeCoder::CDecoder *rangeDecoder)
{
PPM_CONTEXT::STATE* p = MinContext->Stats;
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, MinContext->Stats->Freq); // MinContext->SummFreq);
rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq);
(FoundState = p)->Freq=(hiCnt += 4);
MinContext->SummFreq += 4;
if (hiCnt > MAX_FREQ)
@@ -72,7 +72,7 @@ struct CDecodeInfo: public CInfo
int count, hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 freqSum;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum);
PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = MinContext->Stats-1;
PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1;
hiCnt = 0;
do
{
@@ -119,8 +119,8 @@ struct CDecodeInfo: public CInfo
do
{
OrderFall++;
MinContext = MinContext->Suffix;
if ( !MinContext )
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return -1;
}
while (MinContext->NumStats == NumMasked);
+124 -42
View File
@@ -10,6 +10,9 @@
namespace NCompress {
namespace NPPMD {
const int kLenIdFinished = -1;
const int kLenIdNeedInit = -2;
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
{
if (size < 5)
@@ -18,6 +21,15 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size
_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;
}
@@ -25,76 +37,146 @@ class CDecoderFlusher
{
CDecoder *_coder;
public:
CDecoderFlusher(CDecoder *coder): _coder(coder) {}
bool NeedFlush;
CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}
~CDecoderFlusher()
{
_coder->Flush();
if (NeedFlush)
_coder->Flush();
_coder->ReleaseStreams();
}
};
UInt32 GetMatchLen(const Byte *pointer1, const Byte *pointer2,
UInt32 limit)
{
UInt32 i;
for(i = 0; i < limit && *pointer1 == *pointer2;
pointer1++, pointer2++, i++);
return i;
HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)
{
const startSize = size;
if (_outSizeDefined)
{
const UInt64 rem = _outSize - _processedSize;
if (size > rem)
size = (UInt32)rem;
}
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++ = 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 (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_outStream.Create(1 << 20))
return E_OUTOFMEMORY;
_rangeDecoder.SetStream(inStream);
_rangeDecoder.Init();
SetInStream(inStream);
_outStream.SetStream(outStream);
_outStream.Init();
SetOutStreamSize(outSize);
CDecoderFlusher flusher(this);
UInt64 progressPosValuePrev = 0, pos = 0;
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;
while(pos < size)
while(true)
{
pos++;
int symbol = _info.DecodeSymbol(&_rangeDecoder);
if (symbol < 0)
return S_OK;
_outStream.WriteByte(symbol);
if (pos - progressPosValuePrev >= (1 << 18) && progress != NULL)
_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, &pos));
progressPosValuePrev = pos;
RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
}
if (_outSizeDefined)
if (_outStream.GetProcessedSize() >= _outSize)
break;
}
return S_OK;
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)
{
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; }
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)
{
if (_outSizeDefined = (outSize != NULL))
_outSize = *outSize;
_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
}}
+33 -2
View File
@@ -17,6 +17,11 @@ namespace NPPMD {
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties2,
#ifdef _ST_MODE
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
public CMyUnknownImp
{
NRangeCoder::CDecoder _rangeDecoder;
@@ -28,13 +33,28 @@ class CDecoder :
Byte _order;
UInt32 _usedMemorySize;
int _remainLen;
UInt64 _outSize;
bool _outSizeDefined;
UInt64 _processedSize;
HRESULT CodeSpec(UInt32 num, Byte *memStream);
public:
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
#ifdef _ST_MODE
MY_UNKNOWN_IMP4(
ICompressSetDecoderProperties2,
ICompressSetInStream,
ICompressSetOutStreamSize,
ISequentialInStream)
#else
MY_UNKNOWN_IMP1(
ICompressSetDecoderProperties2)
#endif
void ReleaseStreams()
{
_rangeDecoder.ReleaseStream();
ReleaseInStream();
_outStream.ReleaseStream();
}
@@ -51,6 +71,17 @@ public:
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) {}
};
}}
+6 -6
View File
@@ -15,7 +15,7 @@ struct CEncodeInfo: public CInfo
void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16 &bs = GetBinSumm(rs, MinContext->Suffix->NumStats);
UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rs.Symbol == symbol)
{
FoundState = &rs;
@@ -39,12 +39,12 @@ struct CEncodeInfo: public CInfo
void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE* p = MinContext->Stats;
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats);
if (p->Symbol == symbol)
{
PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeEncoder->Encode(0, MinContext->Stats->Freq, MinContext->SummFreq);
rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq);
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p->Freq > MAX_FREQ)
@@ -76,7 +76,7 @@ struct CEncodeInfo: public CInfo
int hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 scale;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale);
PPM_CONTEXT::STATE* p = MinContext->Stats - 1;
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1;
hiCnt = 0;
do
{
@@ -126,8 +126,8 @@ SYMBOL_FOUND:
do
{
OrderFall++;
MinContext = MinContext->Suffix;
if ( !MinContext )
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return; // S_OK;
}
while (MinContext->NumStats == NumMasked);
+29 -70
View File
@@ -9,6 +9,8 @@
#include "Common/Defs.h"
#include "../../Common/StreamUtils.h"
#include "PPMDEncoder.h"
namespace NCompress {
@@ -40,19 +42,7 @@ public:
}
};
CCounter g_Counter;
/*
// ISetRangeEncoder
STDMETHODIMP CEncoder::SetRangeEncoder(CRangeEncoder *aRangeEncoder)
{
_rangeEncoder = aRangeEncoder;
RINOK(_rangeEncoder.QueryInterface(&m_InitOutCoder));
return S_OK;
}
*/
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
@@ -60,22 +50,22 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
{
for (UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &aProperty = properties[i];
const PROPVARIANT &prop = properties[i];
switch(propIDs[i])
{
case NCoderPropID::kUsedMemorySize:
if (aProperty.vt != VT_UI4)
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (aProperty.ulVal < kMinMemSize)
if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize)
return E_INVALIDARG;
_usedMemorySize = aProperty.ulVal;
_usedMemorySize = (UInt32)prop.ulVal;
break;
case NCoderPropID::kOrder:
if (aProperty.vt != VT_UI4)
if (prop.vt != VT_UI4)
return E_INVALIDARG;
if (aProperty.ulVal < kMinOrder || aProperty.ulVal > kMaxOrderCompress)
if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress)
return E_INVALIDARG;
_order = Byte(aProperty.ulVal);
_order = (Byte)prop.ulVal;
break;
default:
return E_INVALIDARG;
@@ -91,7 +81,7 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
properties[0] = _order;
for (int i = 0; i < 4; i++)
properties[1 + i] = Byte(_usedMemorySize >> (8 * i));
return outStream->Write(properties, kPropSize, NULL);
return WriteStream(outStream, properties, kPropSize, NULL);
}
const UInt32 kUsedMemorySizeDefault = (1 << 24);
@@ -101,30 +91,9 @@ CEncoder::CEncoder():
_usedMemorySize(kUsedMemorySizeDefault),
_order(kOrderDefault)
{
// SubAllocator.StartSubAllocator(kSubAllocator);
}
HRESULT CEncoder::Flush()
{
_rangeEncoder.FlushData();
return _rangeEncoder.FlushStream();
}
class CEncoderFlusher
{
CEncoder *_encoder;
public:
CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {}
~CEncoderFlusher()
{
_encoder->Flush();
_encoder->ReleaseStreams();
}
};
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
@@ -134,50 +103,41 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
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);
UInt64 pos = 0;
UInt64 prevProgressPos = 0;
try
{
if ( !_info.SubAllocator.StartSubAllocator(_usedMemorySize) )
return E_OUTOFMEMORY;
}
catch(...)
{
return E_OUTOFMEMORY;
}
_info.MaxOrder = 0;
_info.StartModelRare(_order);
while (true)
while(true)
{
Byte symbol;
if (!_inStream.ReadByte(symbol))
UInt32 size = (1 << 18);
do
{
// here we can write End Mark for stream version.
// In current version this feature is not used.
// _info.EncodeSymbol(-1, &_rangeEncoder);
return S_OK;
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);
}
_info.EncodeSymbol(symbol, &_rangeEncoder);
pos++;
if (pos - prevProgressPos >= (1 << 18) && progress != NULL)
while (--size != 0);
if (progress != NULL)
{
UInt64 inSize = _inStream.GetProcessedSize();
UInt64 outSize = _rangeEncoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&pos, &outSize));
prevProgressPos = pos;
RINOK(progress->SetRatioInfo(&inSize, &outSize));
}
}
}
@@ -193,4 +153,3 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
}
}}
+24 -7
View File
@@ -29,14 +29,12 @@ public:
UInt32 _usedMemorySize;
Byte _order;
public:
HRESULT Flush()
{
_rangeEncoder.FlushData();
return _rangeEncoder.FlushStream();
}
MY_UNKNOWN_IMP2(
ICompressSetCoderProperties,
ICompressWriteCoderProperties)
// ICoder interface
HRESULT Flush();
void ReleaseStreams()
{
_inStream.ReleaseStream();
@@ -46,6 +44,25 @@ public:
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);
+92 -59
View File
@@ -11,39 +11,47 @@
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)
// 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;
MEM_BLK *Next, *Prev;
void InsertAt(MEM_BLK* p)
UInt32 Next, Prev;
void InsertAt(Byte *Base, UInt32 p)
{
Next = (Prev = p)->Next;
p->Next = Next->Prev = this;
Prev = p;
MEM_BLK *pp = (MEM_BLK *)(Base + p);
Next = pp->Next;
pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (Byte *)this - Base;
}
void Remove()
void Remove(Byte *Base)
{
Prev->Next=Next;
Next->Prev=Prev;
((MEM_BLK *)(Base + Prev))->Next = Next;
((MEM_BLK *)(Base + Next))->Prev = Prev;
}
} _PACK_ATTR;
#pragma pack()
};
class CSubAllocator
{
UInt32 SubAllocatorSize;
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
struct NODE { NODE* Next; } FreeList[N_INDEXES];
UInt32 FreeList[N_INDEXES];
Byte *Base;
Byte *HeapStart, *LoUnit, *HiUnit;
public:
Byte* HeapStart, *pText, *UnitsStart, *LoUnit, *HiUnit;
Byte *pText, *UnitsStart;
CSubAllocator():
SubAllocatorSize(0),
GlueCount(0),
pText(0),
UnitsStart(0),
LoUnit(0),
HiUnit(0)
HiUnit(0),
pText(0),
UnitsStart(0)
{
memset(Indx2Units, 0, sizeof(Indx2Units));
memset(FreeList, 0, sizeof(FreeList));
@@ -53,21 +61,28 @@ public:
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)
{
((NODE*) p)->Next = FreeList[indx].Next;
FreeList[indx].Next = (NODE*)p;
*(UInt32 *)p = FreeList[indx];
FreeList[indx] = GetOffsetNoCheck(p);
}
void* RemoveNode(int indx)
{
NODE* RetVal = FreeList[indx].Next;
FreeList[indx].Next = RetVal->Next;
return RetVal;
UInt32 offset = FreeList[indx];
UInt32 *p = GetNode(offset);
FreeList[indx] = *p;
return (void *)p;
}
UINT U2B(int NU) { return 8 * NU + 4 * NU; }
UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; }
void SplitBlock(void* pv, int oldIndx, int newIndx)
{
@@ -82,25 +97,22 @@ public:
InsertNode(p, Units2Indx[UDiff - 1]);
}
UInt32 GetUsedMemory()
UInt32 GetUsedMemory() const
{
UInt32 i, k, RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(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;
}
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);
}
void StopSubAllocator()
{
if ( SubAllocatorSize )
if (SubAllocatorSize != 0)
{
BigFree(HeapStart);
BigFree(Base);
SubAllocatorSize = 0;
HeapStart = 0;
Base = 0;
}
}
@@ -110,10 +122,13 @@ public:
return true;
StopSubAllocator();
if (size == 0)
HeapStart = 0;
Base = 0;
else
if ((HeapStart = (Byte *)::BigAlloc(size)) == 0)
{
if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0)
return false;
HeapStart = Base + UNIT_SIZE; // we need such code to support NULL;
}
SubAllocatorSize = size;
return true;
}
@@ -138,34 +153,52 @@ public:
void GlueFreeBlocks()
{
MEM_BLK s0, *p, *p1;
int i, k, sz;
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;
for (i = 0, s0.Next = s0.Prev = &s0; i < N_INDEXES; i++)
while ( FreeList[i].Next )
ps0->Next = ps0->Prev = s0;
for (i = 0; i < N_INDEXES; i++)
while (FreeList[i] != 0)
{
p = (MEM_BLK*) RemoveNode(i);
p->InsertAt(&s0);
p->Stamp = 0xFFFF;
p->NU = Indx2Units[i];
MEM_BLK *pp = (MEM_BLK *)RemoveNode(i);
pp->InsertAt(Base, s0);
pp->Stamp = 0xFFFF;
pp->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 = ps0->Next; p != s0; p = GetBlk(p)->Next)
{
for (p->Remove(), sz=p->NU; sz > 128; sz -= 128, p += 128)
InsertNode(p, N_INDEXES - 1);
while (true)
{
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 += 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)
{
k = sz-Indx2Units[--i];
InsertNode(p + (sz - k), k - 1);
int k = sz - Indx2Units[--i];
InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1);
}
InsertNode(p,i);
InsertNode(Base + p, i);
}
}
void* AllocUnitsRare(int indx)
@@ -174,7 +207,7 @@ public:
{
GlueCount = 255;
GlueFreeBlocks();
if (FreeList[indx].Next)
if (FreeList[indx] != 0)
return RemoveNode(indx);
}
int i = indx;
@@ -186,7 +219,7 @@ public:
i = U2B(Indx2Units[indx]);
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
}
} while (!FreeList[i].Next);
} while (FreeList[i] == 0);
void* RetVal = RemoveNode(i);
SplitBlock(RetVal, i, indx);
return RetVal;
@@ -195,7 +228,7 @@ public:
void* AllocUnits(int NU)
{
int indx = Units2Indx[NU - 1];
if (FreeList[indx].Next)
if (FreeList[indx] != 0)
return RemoveNode(indx);
void* RetVal = LoUnit;
LoUnit += U2B(Indx2Units[indx]);
@@ -209,7 +242,7 @@ public:
{
if (HiUnit != LoUnit)
return (HiUnit -= UNIT_SIZE);
if (FreeList->Next)
if (FreeList[0] != 0)
return RemoveNode(0);
return AllocUnitsRare(0);
}
@@ -233,7 +266,7 @@ public:
int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1];
if (i0 == i1)
return oldPtr;
if ( FreeList[i1].Next )
if (FreeList[i1] != 0)
{
void* ptr = RemoveNode(i1);
memcpy(ptr, oldPtr, U2B(newNU));
-6
View File
@@ -13,12 +13,6 @@
const int kMaxOrderCompress = 32;
const int MAX_O = 255; /* maximum allowed model order */
#if defined(__GNUC__)
#define _PACK_ATTR __attribute__ ((packed))
#else
#define _PACK_ATTR
#endif /* defined(__GNUC__) */
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; }
+1
View File
@@ -16,6 +16,7 @@ COMMON_OBJS = \
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
$O\StreamUtils.obj \
OBJS = \