diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2010-03-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:02 +0300 |
commit | 993daef9cbed7febf494217f07e40e0a26b3bc06 (patch) | |
tree | 41db24cb11222422aa3c4d61b80646344e3efefc /CPP/7zip/Compress | |
parent | db5eb6d638f5a5ec10517ed4a994b849a6cc7d29 (diff) |
9.119.11
Diffstat (limited to 'CPP/7zip/Compress')
-rwxr-xr-x | CPP/7zip/Compress/PpmdContext.h | 490 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdDecode.h | 155 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdDecoder.cpp | 204 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdDecoder.h | 55 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdEncode.h | 142 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdEncoder.cpp | 145 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdEncoder.h | 51 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdSubAlloc.h | 293 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdType.h | 14 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdZip.cpp | 223 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdZip.h | 74 | ||||
-rwxr-xr-x | CPP/7zip/Compress/Rar3Decoder.cpp | 152 | ||||
-rwxr-xr-x | CPP/7zip/Compress/Rar3Decoder.h | 90 |
13 files changed, 617 insertions, 1471 deletions
diff --git a/CPP/7zip/Compress/PpmdContext.h b/CPP/7zip/Compress/PpmdContext.h deleted file mode 100755 index cfff53ed..00000000 --- a/CPP/7zip/Compress/PpmdContext.h +++ /dev/null @@ -1,490 +0,0 @@ -// PpmdContext.h -// 2009-05-30 : Igor Pavlov : Public domain -// This code is based on Dmitry Shkarin's PPMdH code (public domain) - -#ifndef __COMPRESS_PPMD_CONTEXT_H -#define __COMPRESS_PPMD_CONTEXT_H - -#include "../../Common/Types.h" - -#include "PpmdSubAlloc.h" -#include "RangeCoder.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 = MaxOrder; - MinContext = MaxContext; - while (MinContext->Suffix != 0) - { - MinContext = GetContextNoCheck(MinContext->Suffix); - OrderFall--; - } - FoundState = GetState(MinContext->Stats); - MinContext = MaxContext; - } - else - { - 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/PpmdDecode.h b/CPP/7zip/Compress/PpmdDecode.h deleted file mode 100755 index d5ca25fe..00000000 --- a/CPP/7zip/Compress/PpmdDecode.h +++ /dev/null @@ -1,155 +0,0 @@ -// PpmdDecode.h -// 2009-05-30 : Igor Pavlov : Public domain -// This code is based on Dmitry Shkarin's PPMdH code (public domain) - -#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/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp index 0ac98c8b..c02f44f1 100755 --- a/CPP/7zip/Compress/PpmdDecoder.cpp +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -1,181 +1,165 @@ // PpmdDecoder.cpp -// 2009-05-30 : Igor Pavlov : Public domain +// 2009-03-11 : Igor Pavlov : Public domain #include "StdAfx.h" -#include "Common/Defs.h" -#include "Windows/Defs.h" +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "../Common/StreamUtils.h" #include "PpmdDecoder.h" namespace NCompress { namespace NPpmd { -const int kLenIdFinished = -1; -const int kLenIdNeedInit = -2; +static const UInt32 kBufSize = (1 << 20); + +enum +{ + kStatus_NeedInit, + kStatus_Normal, + kStatus_Finished, + kStatus_Error +}; + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +CDecoder::~CDecoder() +{ + ::MidFree(_outBuf); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} -STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, 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) + _order = props[0]; + UInt32 memSize = GetUi32(props + 1); + if (_order < PPMD7_MIN_ORDER || + _order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) return E_NOTIMPL; - - if (!_rangeDecoder.Create(1 << 20)) + if (!_inStream.Alloc(1 << 20)) return E_OUTOFMEMORY; - if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) return E_OUTOFMEMORY; - return S_OK; } -class CDecoderFlusher +HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) { - CDecoder *_coder; -public: - bool NeedFlush; - CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {} - ~CDecoderFlusher() + switch(_status) { - if (NeedFlush) - _coder->Flush(); - _coder->ReleaseStreams(); + case kStatus_Finished: return S_OK; + case kStatus_Error: return S_FALSE; + case kStatus_NeedInit: + _inStream.Init(); + if (!Ppmd7z_RangeDec_Init(&_rangeDec)) + { + _status = kStatus_Error; + return S_FALSE; + } + _status = kStatus_Normal; + Ppmd7_Init(&_ppmd, _order); + break; } -}; - -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) + UInt32 i; + int sym = 0; + for (i = 0; i != size; i++) { - _rangeDecoder.Init(); - _remainLen = 0; - _info.MaxOrder = 0; - _info.StartModelRare(_order); + sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p); + if (_inStream.Extra || sym < 0) + break; + memStream[i] = (Byte)sym; } - while (size != 0) + + _processedSize += i; + if (_inStream.Extra) { - int symbol = _info.DecodeSymbol(&_rangeDecoder); - if (symbol < 0) - { - _remainLen = kLenIdFinished; - break; - } - if (memStream != 0) - *memStream++ = (Byte)symbol; - else - _outStream.WriteByte((Byte)symbol); - size--; + _status = kStatus_Error; + return _inStream.Res; } - _processedSize += startSize - size; + if (sym < 0) + _status = (sym < -1) ? kStatus_Error : kStatus_Finished; return S_OK; } -STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (!_outStream.Create(1 << 20)) - return E_OUTOFMEMORY; + if (!_outBuf) + { + _outBuf = (Byte *)::MidAlloc(kBufSize); + if (!_outBuf) + return E_OUTOFMEMORY; + } - SetInStream(inStream); - _outStream.SetStream(outStream); + _inStream.Stream = inStream; SetOutStreamSize(outSize); - CDecoderFlusher flusher(this); - for (;;) + do { - _processedSize = _outStream.GetProcessedSize(); - UInt32 curSize = (1 << 18); - RINOK(CodeSpec(curSize, NULL)); - if (_remainLen == kLenIdFinished) + const UInt64 startPos = _processedSize; + HRESULT res = CodeSpec(_outBuf, kBufSize); + size_t processed = (size_t)(_processedSize - startPos); + RINOK(WriteStream(outStream, _outBuf, processed)); + RINOK(res); + if (_status == kStatus_Finished) break; - if (progress != NULL) + if (progress) { - UInt64 inSize = _rangeDecoder.GetProcessedSize(); + UInt64 inSize = _inStream.GetProcessed(); RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); } - if (_outSizeDefined) - if (_outStream.GetProcessedSize() >= _outSize) - break; } - flusher.NeedFlush = false; - return Flush(); + while (!_outSizeDefined || _processedSize < _outSize); + return S_OK; } -#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) +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { - PPMD_TRY_BEGIN - return CodeReal(inStream, outStream, inSize, outSize, progress); - PPMD_TRY_END + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + _processedSize = 0; + _status = kStatus_NeedInit; + return S_OK; } +#ifndef NO_READ_FROM_CODER + STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { - _rangeDecoder.SetStream(inStream); + InSeqStream = inStream; + _inStream.Stream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { - _rangeDecoder.ReleaseStream(); + InSeqStream.Release(); 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; -} - -#ifndef NO_READ_FROM_CODER - 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)); + HRESULT res = CodeSpec((Byte *)data, size); if (processedSize) *processedSize = (UInt32)(_processedSize - startPos); - return Flush(); - PPMD_TRY_END + return res; } #endif diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h index 31ab8f82..8ebcd700 100755 --- a/CPP/7zip/Compress/PpmdDecoder.h +++ b/CPP/7zip/Compress/PpmdDecoder.h @@ -1,17 +1,16 @@ // PpmdDecoder.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2009-03-11 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_DECODER_H #define __COMPRESS_PPMD_DECODER_H -#include "../../Common/MyCom.h" +#include "../../../C/Ppmd7.h" -#include "../ICoder.h" +#include "../../Common/MyCom.h" -#include "../Common/OutBuffer.h" +#include "../Common/CWrappers.h" -#include "PpmdDecode.h" -#include "RangeCoder.h" +#include "../ICoder.h" namespace NCompress { namespace NPpmd { @@ -26,25 +25,23 @@ class CDecoder : #endif public CMyUnknownImp { - CRangeDecoder _rangeDecoder; - - COutBuffer _outStream; - - CDecodeInfo _info; + Byte *_outBuf; + CPpmd7z_RangeDec _rangeDec; + CByteInBufWrap _inStream; + CPpmd7 _ppmd; Byte _order; - UInt32 _usedMemorySize; - - int _remainLen; - UInt64 _outSize; bool _outSizeDefined; + int _status; + UInt64 _outSize; UInt64 _processedSize; - HRESULT CodeSpec(UInt32 num, Byte *memStream); + HRESULT CodeSpec(Byte *memStream, UInt32 size); public: #ifndef NO_READ_FROM_CODER + CMyComPtr<ISequentialInStream> InSeqStream; MY_UNKNOWN_IMP4( ICompressSetDecoderProperties2, ICompressSetInStream, @@ -55,31 +52,25 @@ public: 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); #ifndef NO_READ_FROM_CODER + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif - CDecoder(): _outSizeDefined(false) {} + CDecoder(): _outBuf(NULL), _outSizeDefined(false) + { + Ppmd7z_RangeDec_CreateVTable(&_rangeDec); + _rangeDec.Stream = &_inStream.p; + Ppmd7_Construct(&_ppmd); + } + + ~CDecoder(); }; }} diff --git a/CPP/7zip/Compress/PpmdEncode.h b/CPP/7zip/Compress/PpmdEncode.h deleted file mode 100755 index 012f859c..00000000 --- a/CPP/7zip/Compress/PpmdEncode.h +++ /dev/null @@ -1,142 +0,0 @@ -// PpmdEncode.h -// 2009-05-30 : Igor Pavlov : Public domain -// This code is based on Dmitry Shkarin's PPMdH code (public domain) - -#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/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index 0af2ae7d..d823ffe8 100755 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -1,10 +1,10 @@ // PpmdEncoder.cpp -// 2009-05-30 : Igor Pavlov : Public domain +// 2009-03-11 : Igor Pavlov : Public domain #include "StdAfx.h" -// #include <fstream.h> -// #include <iomanip.h> +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" #include "../Common/StreamUtils.h" @@ -13,55 +13,46 @@ namespace NCompress { namespace NPpmd { -const UInt32 kMinMemSize = (1 << 11); -const UInt32 kMinOrder = 2; +static const UInt32 kBufSize = (1 << 20); -/* -UInt32 g_NumInner = 0; -UInt32 g_InnerCycles = 0; +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; -UInt32 g_Encode2 = 0; -UInt32 g_Encode2Cycles = 0; -UInt32 g_Encode2Cycles2 = 0; +CEncoder::CEncoder(): + _inBuf(NULL), + _usedMemSize(1 << 24), + _order(6) +{ + _rangeEnc.Stream = &_outStream.p; + Ppmd7_Construct(&_ppmd); +} -class CCounter +CEncoder::~CEncoder() { -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; -*/ + ::MidFree(_inBuf); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) { for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = props[i]; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; switch(propIDs[i]) { case NCoderPropID::kUsedMemorySize: - if (prop.vt != VT_UI4) + if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0) return E_INVALIDARG; - if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize) - return E_INVALIDARG; - _usedMemorySize = (UInt32)prop.ulVal; + _usedMemSize = v; break; case NCoderPropID::kOrder: - if (prop.vt != VT_UI4) - return E_INVALIDARG; - if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress) + if (v < 2 || v > 32) return E_INVALIDARG; - _order = (Byte)prop.ulVal; + _order = (Byte)v; break; default: return E_INVALIDARG; @@ -75,74 +66,54 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) const UInt32 kPropSize = 5; Byte props[kPropSize]; props[0] = _order; - for (int i = 0; i < 4; i++) - props[1 + i] = Byte(_usedMemorySize >> (8 * i)); + SetUi32(props + 1, _usedMemSize); return WriteStream(outStream, props, kPropSize); } -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) +HRESULT CEncoder::Code(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)) + if (!_inBuf) + { + _inBuf = (Byte *)::MidAlloc(kBufSize); + if (!_inBuf) + return E_OUTOFMEMORY; + } + if (!_outStream.Alloc(1 << 20)) return E_OUTOFMEMORY; - if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc)) return E_OUTOFMEMORY; - _inStream.SetStream(inStream); - _inStream.Init(); - - _rangeEncoder.SetStream(outStream); - _rangeEncoder.Init(); + _outStream.Stream = outStream; + _outStream.Init(); - CEncoderFlusher flusher(this); - - _info.MaxOrder = 0; - _info.StartModelRare(_order); + Ppmd7z_RangeEnc_Init(&_rangeEnc); + Ppmd7_Init(&_ppmd, _order); + UInt64 processed = 0; for (;;) { - UInt32 size = (1 << 18); - do + UInt32 size; + RINOK(inStream->Read(_inBuf, kBufSize, &size)); + if (size == 0) + { + // We don't write EndMark in PPMD-7z. + // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1); + Ppmd7z_RangeEnc_FlushData(&_rangeEnc); + return _outStream.Flush(); + } + for (UInt32 i = 0; i < size; i++) { - 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); + Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]); + RINOK(_outStream.Res); } - while (--size != 0); - if (progress != NULL) + processed += size; + if (progress) { - UInt64 inSize = _inStream.GetProcessedSize(); - UInt64 outSize = _rangeEncoder.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&inSize, &outSize)); + UInt64 outSize = _outStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&processed, &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/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index 07b368a7..ed8b3713 100755 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -1,17 +1,16 @@ // PpmdEncoder.h -// 2009-05-30 : Igor Pavlov : Public domain +// 2009-03-11 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_ENCODER_H #define __COMPRESS_PPMD_ENCODER_H +#include "../../../C/Ppmd7.h" + #include "../../Common/MyCom.h" #include "../ICoder.h" -#include "../Common/InBuffer.h" - -#include "PpmdEncode.h" -#include "RangeCoder.h" +#include "../Common/CWrappers.h" namespace NCompress { namespace NPpmd { @@ -22,56 +21,26 @@ class CEncoder : public ICompressWriteCoderProperties, public CMyUnknownImp { -public: - CInBuffer _inStream; + Byte *_inBuf; + CByteOutBufWrap _outStream; + CPpmd7z_RangeEnc _rangeEnc; + CPpmd7 _ppmd; - NRangeCoder::CEncoder _rangeEncoder; - - CEncodeInfo _info; - UInt32 _usedMemorySize; + UInt32 _usedMemSize; 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 *props, UInt32 numProps); - STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); CEncoder(); + ~CEncoder(); }; }} diff --git a/CPP/7zip/Compress/PpmdSubAlloc.h b/CPP/7zip/Compress/PpmdSubAlloc.h deleted file mode 100755 index 143f4632..00000000 --- a/CPP/7zip/Compress/PpmdSubAlloc.h +++ /dev/null @@ -1,293 +0,0 @@ -// PpmdSubAlloc.h -// 2009-05-30 : Igor Pavlov : Public domain -// This code is based on Dmitry Shkarin's PPMdH code (public domain) - -#ifndef __COMPRESS_PPMD_SUB_ALLOC_H -#define __COMPRESS_PPMD_SUB_ALLOC_H - -#include "../../../C/Alloc.h" - -#include "PpmdType.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/PpmdType.h b/CPP/7zip/Compress/PpmdType.h deleted file mode 100755 index e4b0203c..00000000 --- a/CPP/7zip/Compress/PpmdType.h +++ /dev/null @@ -1,14 +0,0 @@ -// PpmdType.h -// 2009-05-30 : Igor Pavlov : Public domain -// This code is based on Dmitry Shkarin's PPMdH code (public domain) - -#ifndef __COMPRESS_PPMD_TYPE_H -#define __COMPRESS_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/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp new file mode 100755 index 00000000..f576909f --- /dev/null +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -0,0 +1,223 @@ +// PpmdZip.cpp +// 2010-03-11 : Igor Pavlov : Public domain + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../Common/StreamUtils.h" + +#include "PpmdZip.h" + +namespace NCompress { +namespace NPpmdZip { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +CDecoder::CDecoder(bool fullFileMode): + _fullFileMode(fullFileMode) +{ + _ppmd.Stream.In = &_inStream.p; + Ppmd8_Construct(&_ppmd); +} + +CDecoder::~CDecoder() +{ + Ppmd8_Free(&_ppmd, &g_BigAlloc); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (!_outStream.Alloc()) + return E_OUTOFMEMORY; + if (!_inStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + + _inStream.Stream = inStream; + _inStream.Init(); + + { + Byte buf[2]; + for (int i = 0; i < 2; i++) + buf[i] = _inStream.ReadByte(); + if (_inStream.Extra) + return S_FALSE; + + UInt32 val = GetUi16(buf); + UInt32 order = (val & 0xF) + 1; + UInt32 mem = ((val >> 4) & 0xFF) + 1; + UInt32 restor = (val >> 12); + if (order < 2 || restor > 2) + return S_FALSE; + + #ifndef PPMD8_FREEZE_SUPPORT + if (restor == 2) + return E_NOTIMPL; + #endif + + if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc)) + return E_OUTOFMEMORY; + + if (!Ppmd8_RangeDec_Init(&_ppmd)) + return S_FALSE; + Ppmd8_Init(&_ppmd, order, restor); + } + + bool wasFinished = false; + UInt64 processedSize = 0; + while (!outSize || processedSize < *outSize) + { + size_t size = kBufSize; + if (outSize != NULL) + { + const UInt64 rem = *outSize - processedSize; + if (size > rem) + size = (size_t)rem; + } + Byte *data = _outStream.Buf; + size_t i = 0; + int sym = 0; + do + { + sym = Ppmd8_DecodeSymbol(&_ppmd); + if (_inStream.Extra || sym < 0) + break; + data[i] = (Byte)sym; + } + while (++i != size); + processedSize += i; + + RINOK(WriteStream(outStream, _outStream.Buf, i)); + + RINOK(_inStream.Res); + if (_inStream.Extra) + return S_FALSE; + + if (sym < 0) + { + if (sym != -1) + return S_FALSE; + wasFinished = true; + break; + } + if (progress) + { + UInt64 inSize = _inStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&inSize, &processedSize)); + } + } + RINOK(_inStream.Res); + if (_fullFileMode) + { + if (!wasFinished) + { + int res = Ppmd8_DecodeSymbol(&_ppmd); + RINOK(_inStream.Res); + if (_inStream.Extra || res != -1) + return S_FALSE; + } + if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd)) + return S_FALSE; + } + return S_OK; +} + + +// ---------- Encoder ---------- + +CEncoder::~CEncoder() +{ + Ppmd8_Free(&_ppmd, &g_BigAlloc); +} + +HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch(propIDs[i]) + { + case NCoderPropID::kAlgorithm: + if (v > 1) + return E_INVALIDARG; + _restor = v; + break; + case NCoderPropID::kUsedMemorySize: + if (v < (1 << 20) || v > (1 << 28)) + return E_INVALIDARG; + _usedMemInMB = v >> 20; + break; + case NCoderPropID::kOrder: + if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER) + return E_INVALIDARG; + _order = (Byte)v; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +CEncoder::CEncoder(): + _usedMemInMB(16), + _order(6), + _restor(PPMD8_RESTORE_METHOD_RESTART) +{ + _ppmd.Stream.Out = &_outStream.p; + Ppmd8_Construct(&_ppmd); +} + +HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + if (!_inStream.Alloc()) + return E_OUTOFMEMORY; + if (!_outStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc)) + return E_OUTOFMEMORY; + + _outStream.Stream = outStream; + _outStream.Init(); + + Ppmd8_RangeEnc_Init(&_ppmd); + Ppmd8_Init(&_ppmd, _order, _restor); + + UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12)); + _outStream.WriteByte((Byte)(val & 0xFF)); + _outStream.WriteByte((Byte)(val >> 8)); + RINOK(_outStream.Res); + + UInt64 processed = 0; + for (;;) + { + UInt32 size; + RINOK(inStream->Read(_inStream.Buf, kBufSize, &size)); + if (size == 0) + { + Ppmd8_EncodeSymbol(&_ppmd, -1); + Ppmd8_RangeEnc_FlushData(&_ppmd); + return _outStream.Flush(); + } + for (UInt32 i = 0; i < size; i++) + { + Ppmd8_EncodeSymbol(&_ppmd, _inStream.Buf[i]); + RINOK(_outStream.Res); + } + processed += size; + if (progress != NULL) + { + UInt64 outSize = _outStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&processed, &outSize)); + } + } +} + +}} diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h new file mode 100755 index 00000000..7deb31f4 --- /dev/null +++ b/CPP/7zip/Compress/PpmdZip.h @@ -0,0 +1,74 @@ +// PpmdZip.h +// 2010-03-11 : Igor Pavlov : Public domain + +#ifndef __COMPRESS_PPMD_ZIP_H +#define __COMPRESS_PPMD_ZIP_H + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/Ppmd8.h" + +#include "../../Common/MyCom.h" + +#include "../Common/CWrappers.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NPpmdZip { + +static const UInt32 kBufSize = (1 << 20); + +struct CBuf +{ + Byte *Buf; + + CBuf(): Buf(0) {} + ~CBuf() { ::MidFree(Buf); } + bool Alloc() + { + if (!Buf) + Buf = (Byte *)::MidAlloc(kBufSize); + return (Buf != 0); + } +}; + +class CDecoder : + public ICompressCoder, + public CMyUnknownImp +{ + CByteInBufWrap _inStream; + CBuf _outStream; + CPpmd8 _ppmd; + bool _fullFileMode; +public: + MY_UNKNOWN_IMP + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + CDecoder(bool fullFileMode); + ~CDecoder(); +}; + +class CEncoder : + public ICompressCoder, + public CMyUnknownImp +{ + CByteOutBufWrap _outStream; + CBuf _inStream; + CPpmd8 _ppmd; + UInt32 _usedMemInMB; + unsigned _order; + unsigned _restor; +public: + MY_UNKNOWN_IMP + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + CEncoder(); + ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index 77106278..af5cef1a 100755 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -1,9 +1,13 @@ // Rar3Decoder.cpp // According to unRAR license, this code may not be used to develop // a program that creates RAR archives + +/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ #include "StdAfx.h" +#include "../../../C/Alloc.h" + #include "../Common/StreamUtils.h" #include "Rar3Decoder.h" @@ -11,6 +15,10 @@ namespace NCompress { namespace NRar3 { +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + static const UInt32 kNumAlignReps = 15; static const UInt32 kSymbolReadTable = 256; @@ -38,6 +46,48 @@ static const UInt32 kNormalMatchMinLen = 3; static const UInt32 kVmDataSizeMax = 1 << 16; static const UInt32 kVmCodeSizeMax = 1 << 16; +extern "C" { + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + return p->Code / (p->Range /= total); +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + p->Normalize(); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + if (p->Code / (p->Range >>= 14) < size0) + { + Range_Decode(p, 0, size0); + return 0; + } + else + { + Range_Decode(p, size0, (1 << 14) - size0); + return 1; + } +} + +} + +CRangeDecoder::CRangeDecoder() +{ + s.GetThreshold = Range_GetThreshold; + s.Decode = Range_Decode; + s.DecodeBit = Range_DecodeBit; +} + CDecoder::CDecoder(): _window(0), _winPos(0), @@ -48,6 +98,7 @@ CDecoder::CDecoder(): _vmCode(0), m_IsSolid(false) { + Ppmd7_Construct(&_ppmd); } CDecoder::~CDecoder() @@ -55,6 +106,7 @@ CDecoder::~CDecoder() InitFilters(); ::MidFree(_vmData); ::MidFree(_window); + Ppmd7_Free(&_ppmd, &g_BigAlloc); } HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size) @@ -294,39 +346,39 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) bool CDecoder::ReadVmCodeLZ() { - UInt32 firstByte = m_InBitStream.ReadBits(8); + UInt32 firstByte = ReadBits(8); UInt32 length = (firstByte & 7) + 1; if (length == 7) - length = m_InBitStream.ReadBits(8) + 7; + length = ReadBits(8) + 7; else if (length == 8) - length = m_InBitStream.ReadBits(16); + length = ReadBits(16); if (length > kVmDataSizeMax) return false; for (UInt32 i = 0; i < length; i++) - _vmData[i] = (Byte)m_InBitStream.ReadBits(8); + _vmData[i] = (Byte)ReadBits(8); return AddVmCode(firstByte, length); } bool CDecoder::ReadVmCodePPM() { int firstByte = DecodePpmSymbol(); - if (firstByte == -1) + if (firstByte < 0) return false; UInt32 length = (firstByte & 7) + 1; if (length == 7) { int b1 = DecodePpmSymbol(); - if (b1 == -1) + if (b1 < 0) return false; length = b1 + 7; } else if (length == 8) { int b1 = DecodePpmSymbol(); - if (b1 == -1) + if (b1 < 0) return false; int b2 = DecodePpmSymbol(); - if (b2 == -1) + if (b2 < 0) return false; length = b1 * 256 + b2; } @@ -335,7 +387,7 @@ bool CDecoder::ReadVmCodePPM() for (UInt32 i = 0; i < length; i++) { int b = DecodePpmSymbol(); - if (b == -1) + if (b < 0) return false; _vmData[i] = (Byte)b; } @@ -344,7 +396,7 @@ bool CDecoder::ReadVmCodePPM() #define RIF(x) { if (!(x)) return S_FALSE; } -UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } +UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.bitDecoder.ReadBits(numBits); } ///////////////////////////////////////////////// // PPM @@ -359,7 +411,7 @@ HRESULT CDecoder::InitPPM() maxMB = (Byte)ReadBits(8); else { - if (_ppm.SubAllocator.GetSubAllocatorSize()== 0) + if (PpmError || !Ppmd7_WasAllocated(&_ppmd)) return S_FALSE; } if (maxOrder & 0x40) @@ -371,34 +423,30 @@ HRESULT CDecoder::InitPPM() */ if (reset) { + PpmError = true; maxOrder = (maxOrder & 0x1F) + 1; if (maxOrder > 16) maxOrder = 16 + (maxOrder - 16) * 3; if (maxOrder == 1) { - // SubAlloc.StopSubAllocator(); - _ppm.SubAllocator.StopSubAllocator(); + Ppmd7_Free(&_ppmd, &g_BigAlloc); return S_FALSE; } - // SubAlloc.StartSubAllocator(MaxMB+1); - // StartModelRare(maxOrder); - - if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20)) + if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc)) return E_OUTOFMEMORY; - _ppm.MaxOrder = 0; - _ppm.StartModelRare(maxOrder); - + Ppmd7_Init(&_ppmd, maxOrder); + PpmError = false; } - // return (minContext != NULL); - return S_OK; } -int CDecoder::DecodePpmSymbol() { return _ppm.DecodeSymbol(&m_InBitStream); } +int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); } HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) { keepDecompressing = false; + if (PpmError) + return S_FALSE; do { if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) @@ -411,15 +459,19 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) } } int c = DecodePpmSymbol(); - if (c == -1) + if (c < 0) { - // Original code sets PPMError=true here and then it returns S_OK. Why ??? - // return S_OK; + PpmError = true; return S_FALSE; } if (c == PpmEscChar) { int nextCh = DecodePpmSymbol(); + if (nextCh < 0) + { + PpmError = true; + return S_FALSE; + } if (nextCh == 0) return ReadTables(keepDecompressing); if (nextCh == 2 || nextCh == -1) @@ -427,7 +479,10 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) if (nextCh == 3) { if (!ReadVmCodePPM()) + { + PpmError = true; return S_FALSE; + } continue; } if (nextCh == 4 || nextCh == 5) @@ -439,16 +494,22 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) for (int i = 0; i < 3; i++) { int c = DecodePpmSymbol(); - if (c == -1) - return S_OK; + if (c < 0) + { + PpmError = true; + return S_FALSE; + } distance = (distance << 8) + (Byte)c; } distance++; length += 28; } int c = DecodePpmSymbol(); - if (c == -1) - return S_OK; + if (c < 0) + { + PpmError = true; + return S_FALSE; + } length += c; if (distance >= _lzSize) return S_FALSE; @@ -471,7 +532,7 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) HRESULT CDecoder::ReadTables(bool &keepDecompressing) { keepDecompressing = true; - ReadBits((8 - m_InBitStream.GetBitPosition()) & 7); + ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7); if (ReadBits(1) != 0) { _lzMode = false; @@ -510,7 +571,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) i = 0; while (i < kTablesSizesSum) { - UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); if (number < 16) { newLevels[i] = Byte((number + m_LastLevels[i]) & 15); @@ -620,7 +681,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) return S_OK; } } - UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); if (number < 256) { PutByte((Byte)number); @@ -664,10 +725,10 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) rep0 = distance; } - UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream); + UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); if (number >= kLenTableSize) return S_FALSE; - length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); + length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]); } else { @@ -677,14 +738,14 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) if (number < 271) { number -= 263; - rep0 = kLen2DistStarts[number] + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); + rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]); length = 2; } else if (number < 299) { number -= 271; - length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); - UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream); + length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]); + UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); if (number >= kDistTableSize) return S_FALSE; rep0 = kDistStart[number]; @@ -692,7 +753,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) if (number >= (kNumAlignBits * 2) + 2) { if (numBits > kNumAlignBits) - rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); + rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); if (PrevAlignCount > 0) { PrevAlignCount--; @@ -700,7 +761,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } else { - UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream); + UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder); if (number < (1 << kNumAlignBits)) { rep0 += number; @@ -716,7 +777,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } } else - rep0 += m_InBitStream.ReadBits(numBits); + rep0 += m_InBitStream.bitDecoder.ReadBits(numBits); length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); } else @@ -749,6 +810,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) memset(m_LastLevels, 0, kTablesSizesSum); TablesRead = false; PpmEscChar = 2; + PpmError = true; InitFilters(); } if (!m_IsSolid || !TablesRead) @@ -770,7 +832,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) { RINOK(DecodePPM(1 << 18, keepDecompressing)) } - UInt64 packSize = m_InBitStream.GetProcessedSize(); + UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); if (!keepDecompressing) break; @@ -804,14 +866,14 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (_window == 0) return E_OUTOFMEMORY; } - if (!m_InBitStream.Create(1 << 20)) + if (!m_InBitStream.bitDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_vm.Create()) return E_OUTOFMEMORY; - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); + m_InBitStream.bitDecoder.SetStream(inStream); + m_InBitStream.bitDecoder.Init(); _outStream = outStream; CCoderReleaser coderReleaser(this); diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h index 73d4c224..99b647dc 100755 --- a/CPP/7zip/Compress/Rar3Decoder.h +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -2,9 +2,13 @@ // According to unRAR license, this code may not be used to develop // a program that creates RAR archives +/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + #ifndef __COMPRESS_RAR3_DECODER_H #define __COMPRESS_RAR3_DECODER_H +#include "../../../C/Ppmd7.h" + #include "../../Common/MyCom.h" #include "../ICoder.h" @@ -13,7 +17,6 @@ #include "BitmDecoder.h" #include "HuffmanDecoder.h" -#include "PpmdDecode.h" #include "Rar3Vm.h" namespace NCompress { @@ -38,8 +41,8 @@ const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize class CBitDecoder { UInt32 m_Value; + unsigned m_BitPos; public: - UInt32 m_BitPos; CInBuffer m_Stream; bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} @@ -50,26 +53,13 @@ public: m_Stream.Init(); m_BitPos = 0; m_Value = 0; - // m_BitPos = kNumBigValueBits; - // Normalize(); } - UInt64 GetProcessedSize() const - { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; } + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; } UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); } - /* - void Normalize() + UInt32 GetValue(unsigned numBits) { - for (;m_BitPos >= 8; m_BitPos -= 8) - m_Value = (m_Value << 8) | m_Stream.ReadByte(); - } - */ - - UInt32 GetValue(UInt32 numBits) - { - // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits); - // return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits); if (m_BitPos < numBits) { m_BitPos += 8; @@ -83,13 +73,13 @@ public: return m_Value >> (m_BitPos - numBits); } - void MovePos(UInt32 numBits) + void MovePos(unsigned numBits) { m_BitPos -= numBits; m_Value = m_Value & ((1 << m_BitPos) - 1); } - UInt32 ReadBits(UInt32 numBits) + UInt32 ReadBits(unsigned numBits) { UInt32 res = GetValue(numBits); MovePos(numBits); @@ -97,67 +87,42 @@ public: } }; -const int kNumTopBits = 24; -const UInt32 kTopValue = (1 << kNumTopBits); +const UInt32 kTopValue = (1 << 24); const UInt32 kBot = (1 << 15); -class CRangeDecoder:public NPpmd::CRangeDecoderVirt, public CBitDecoder +struct CRangeDecoder { -public: + IPpmd7_RangeDec s; UInt32 Range; - UInt32 Low; UInt32 Code; + UInt32 Low; + CBitDecoder bitDecoder; + SRes Res; - void Normalize() - { - while ((Low ^ (Low + Range)) < kTopValue || - Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) - { - Code = (Code << 8) | m_Stream.ReadByte(); - Range <<= 8; - Low <<= 8; - } - } - +public: void InitRangeCoder() { Code = 0; Low = 0; Range = 0xFFFFFFFF; - for(int i = 0; i < 4; i++) - Code = (Code << 8) | ReadBits(8); - } - - virtual UInt32 GetThreshold(UInt32 total) - { - return (Code - Low) / ( Range /= total); - } - - virtual void Decode(UInt32 start, UInt32 size) - { - Low += start * Range; - Range *= size; - Normalize(); + for (int i = 0; i < 4; i++) + Code = (Code << 8) | bitDecoder.ReadBits(8); } - virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + void Normalize() { - if (((Code - Low) / (Range >>= numTotalBits)) < size0) - { - Decode(0, size0); - return 0; - } - else + while ((Low ^ (Low + Range)) < kTopValue || + Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) { - Decode(size0, (1 << numTotalBits) - size0); - return 1; + Code = (Code << 8) | bitDecoder.m_Stream.ReadByte(); + Range <<= 8; + Low <<= 8; } } - // UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); } + CRangeDecoder(); }; - struct CFilter: public NVm::CProgram { CRecordVector<Byte> GlobalData; @@ -219,8 +184,9 @@ class CDecoder: bool TablesRead; - NPpmd::CDecodeInfo _ppm; + CPpmd7 _ppmd; int PpmEscChar; + bool PpmError; HRESULT WriteDataToStream(const Byte *data, UInt32 size); HRESULT WriteData(const Byte *data, UInt32 size); @@ -252,7 +218,7 @@ public: void ReleaseStreams() { _outStream.Release(); - m_InBitStream.ReleaseStream(); + m_InBitStream.bitDecoder.ReleaseStream(); } STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, |