This commit is contained in:
Igor Pavlov
2010-03-15 00:00:00 +00:00
committed by Kornel Lesiński
parent db5eb6d638
commit 993daef9cb
74 changed files with 5177 additions and 1736 deletions

4
C/7z.h
View File

@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2009-08-17 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
@@ -96,11 +96,13 @@ typedef struct
CNtfsFileTime MTime; CNtfsFileTime MTime;
UInt64 Size; UInt64 Size;
UInt32 Crc; UInt32 Crc;
UInt32 Attrib;
Byte HasStream; Byte HasStream;
Byte IsDir; Byte IsDir;
Byte IsAnti; Byte IsAnti;
Byte CrcDefined; Byte CrcDefined;
Byte MTimeDefined; Byte MTimeDefined;
Byte AttribDefined;
} CSzFileItem; } CSzFileItem;
void SzFile_Init(CSzFileItem *p); void SzFile_Init(CSzFileItem *p);

164
C/7zDec.c
View File

@@ -1,14 +1,20 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2009-08-16 : Igor Pavlov : Public domain */ 2010-03-15 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
/* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h" #include "7z.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h"
#include "LzmaDec.h" #include "LzmaDec.h"
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h"
#endif
#define k_Copy 0 #define k_Copy 0
#define k_LZMA2 0x21 #define k_LZMA2 0x21
@@ -16,6 +22,104 @@
#define k_BCJ 0x03030103 #define k_BCJ 0x03030103
#define k_BCJ2 0x0303011B #define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401
typedef struct
{
IByteIn p;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
ILookInStream *inStream;
} CByteInToLook;
static Byte ReadByte(void *pp)
{
CByteInToLook *p = (CByteInToLook *)pp;
if (p->cur != p->end)
return *p->cur++;
if (p->res == SZ_OK)
{
size_t size = p->cur - p->begin;
p->processed += size;
p->res = p->inStream->Skip(p->inStream, size);
size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin;
p->end = p->begin + size;
if (size != 0)
return *p->cur++;;
}
p->extra = True;
return 0;
}
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CPpmd7 ppmd;
CByteInToLook s;
SRes res = SZ_OK;
s.p.Read = ReadByte;
s.inStream = inStream;
s.begin = s.end = s.cur = NULL;
s.extra = False;
s.res = SZ_OK;
s.processed = 0;
if (coder->Props.size != 5)
return SZ_ERROR_UNSUPPORTED;
{
unsigned order = coder->Props.data[0];
UInt32 memSize = GetUi32(coder->Props.data + 1);
if (order < PPMD7_MIN_ORDER ||
order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE ||
memSize > PPMD7_MAX_MEM_SIZE)
return SZ_ERROR_UNSUPPORTED;
Ppmd7_Construct(&ppmd);
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
return SZ_ERROR_MEM;
Ppmd7_Init(&ppmd, order);
}
{
CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p;
if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA;
else if (s.extra)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else
{
SizeT i;
for (i = 0; i < outSize; i++)
{
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
if (s.extra || sym < 0)
break;
outBuffer[i] = (Byte)sym;
}
if (i != outSize)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
res = SZ_ERROR_DATA;
}
}
Ppmd7_Free(&ppmd, allocMain);
return res;
}
#endif
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{ {
@@ -34,7 +138,7 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -84,7 +188,7 @@ static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inS
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -121,7 +225,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
size_t curSize = (1 << 18); size_t curSize = (1 << 18);
if (curSize > inSize) if (curSize > inSize)
curSize = (size_t)inSize; curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
if (curSize == 0) if (curSize == 0)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize); memcpy(outBuffer, inBuf, curSize);
@@ -132,16 +236,38 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
return SZ_OK; return SZ_OK;
} }
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA && (m) != k_LZMA2) static Bool IS_MAIN_METHOD(UInt32 m)
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) {
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) switch(m)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) {
case k_Copy:
case k_LZMA:
case k_LZMA2:
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
return True;
}
return False;
}
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
c->NumInStreams == 1 &&
c->NumOutStreams == 1 &&
c->MethodID <= (UInt32)0xFFFFFFFF &&
IS_MAIN_METHOD((UInt32)c->MethodID);
}
#define IS_BCJ(c) ((c)->MethodID == k_BCJ && (c)->NumInStreams == 1 && (c)->NumOutStreams == 1)
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f) static SRes CheckSupportedFolder(const CSzFolder *f)
{ {
if (f->NumCoders < 1 || f->NumCoders > 4) if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (IS_UNSUPPORTED_CODER(f->Coders[0])) if (!IS_SUPPORTED_CODER(&f->Coders[0]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1) if (f->NumCoders == 1)
{ {
@@ -151,7 +277,7 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
} }
if (f->NumCoders == 2) if (f->NumCoders == 2)
{ {
if (IS_NO_BCJ(f->Coders[1]) || if (!IS_BCJ(&f->Coders[1]) ||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 || f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
@@ -160,9 +286,9 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
} }
if (f->NumCoders == 4) if (f->NumCoders == 4)
{ {
if (IS_UNSUPPORTED_CODER(f->Coders[1]) || if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
IS_UNSUPPORTED_CODER(f->Coders[2]) || !IS_SUPPORTED_CODER(&f->Coders[2]) ||
IS_NO_BCJ2(f->Coders[3])) !IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 || if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 || f->PackStreams[0] != 2 ||
@@ -204,7 +330,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
{ {
CSzCoderInfo *coder = &folder->Coders[ci]; CSzCoderInfo *coder = &folder->Coders[ci];
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA || coder->MethodID == k_LZMA2) if (IS_MAIN_METHOD((UInt32)coder->MethodID))
{ {
UInt32 si = 0; UInt32 si = 0;
UInt64 offset; UInt64 offset;
@@ -252,10 +378,18 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
{ {
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else else if (coder->MethodID == k_LZMA2)
{ {
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else
{
#ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else
return SZ_ERROR_UNSUPPORTED;
#endif
}
} }
else if (coder->MethodID == k_BCJ) else if (coder->MethodID == k_BCJ)
{ {

View File

@@ -1,5 +1,5 @@
/* 7zIn.c -- 7z Input functions /* 7zIn.c -- 7z Input functions
2009-11-24 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -1038,6 +1038,25 @@ static SRes SzReadHeader2(
RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
break; break;
} }
case k7zIdWinAttributes:
{
RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
RINOK(SzReadSwitch(sd));
for (i = 0; i < numFiles; i++)
{
CSzFileItem *f = &files[i];
Byte defined = (*lwtVector)[i];
f->AttribDefined = defined;
f->Attrib = 0;
if (defined)
{
RINOK(SzReadUInt32(sd, &f->Attrib));
}
}
IAlloc_Free(allocTemp, *lwtVector);
*lwtVector = NULL;
break;
}
case k7zIdMTime: case k7zIdMTime:
{ {
RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
@@ -1054,6 +1073,8 @@ static SRes SzReadHeader2(
RINOK(SzReadUInt32(sd, &f->MTime.High)); RINOK(SzReadUInt32(sd, &f->MTime.High));
} }
} }
IAlloc_Free(allocTemp, *lwtVector);
*lwtVector = NULL;
break; break;
} }
default: default:

View File

@@ -1,5 +1,5 @@
/* 7zStream.c -- 7z Stream functions /* 7zStream.c -- 7z Stream functions
2008-11-23 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -39,7 +39,7 @@ SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
{ {
void *lookBuf; const void *lookBuf;
if (*size == 0) if (*size == 0)
return SZ_OK; return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size)); RINOK(stream->Look(stream, &lookBuf, size));
@@ -66,7 +66,7 @@ SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
@@ -84,7 +84,7 @@ static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
return res; return res;
} }
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 10 #define MY_VER_MINOR 11
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.10 beta" #define MY_VERSION "9.11 beta"
#define MY_DATE "2009-12-22" #define MY_DATE "2010-03-15"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2009-11-25: Igor Pavlov : Public domain */ 2010-03-11: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -24,10 +24,18 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_64BIT #define MY_CPU_64BIT
#endif #endif
#if defined(_M_IX86) || defined(__i386__) || defined(MY_CPU_AMD64) #if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64 #define MY_CPU_X86_OR_AMD64
#endif #endif
#if defined(MY_CPU_X86) || defined(_M_ARM)
#define MY_CPU_32BIT
#endif
#if defined(_WIN32) && defined(_M_ARM) #if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE #define MY_CPU_ARM_LE
#endif #endif

81
C/Ppmd.h Executable file
View File

@@ -0,0 +1,81 @@
/* Ppmd.h -- PPMD codec common code
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H
#define __PPMD_H
#include "Types.h"
#include "CpuArch.h"
EXTERN_C_BEGIN
#ifdef MY_CPU_32BIT
#define PPMD_32BIT
#endif
#define PPMD_INT_BITS 7
#define PPMD_PERIOD_BITS 7
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
#define PPMD_N1 4
#define PPMD_N2 4
#define PPMD_N3 4
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
/* SEE-contexts for PPM-contexts with masked symbols */
typedef struct
{
UInt16 Summ; /* Freq */
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
Byte Count; /* Count to next change of Shift */
} CPpmd_See;
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
typedef struct
{
Byte Symbol;
Byte Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
} CPpmd_State;
typedef
#ifdef PPMD_32BIT
CPpmd_State *
#else
UInt32
#endif
CPpmd_State_Ref;
typedef
#ifdef PPMD_32BIT
void *
#else
UInt32
#endif
CPpmd_Void_Ref;
typedef
#ifdef PPMD_32BIT
Byte *
#else
UInt32
#endif
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
EXTERN_C_END
#endif

708
C/Ppmd7.c Executable file
View File

@@ -0,0 +1,708 @@
/* Ppmd7.c -- PPMdH codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include <memory.h>
#include "Ppmd7.h"
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
#define MAX_FREQ 124
#define UNIT_SIZE 12
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
#define U2I(nu) (p->Units2Indx[(nu) - 1])
#define I2U(indx) (p->Indx2Units[indx])
#ifdef PPMD_32BIT
#define REF(ptr) (ptr)
#else
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
#endif
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
#define SUFFIX(ctx) CTX((ctx)->Suffix)
typedef CPpmd7_Context * CTX_PTR;
struct CPpmd7_Node_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Node_ *
#else
UInt32
#endif
CPpmd7_Node_Ref;
typedef struct CPpmd7_Node_
{
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
UInt16 NU;
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
CPpmd7_Node_Ref Prev;
} CPpmd7_Node;
#ifdef PPMD_32BIT
#define NODE(ptr) (ptr)
#else
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
#endif
void Ppmd7_Construct(CPpmd7 *p)
{
unsigned i, k, m;
p->Base = 0;
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step);
p->Indx2Units[i] = (Byte)k;
}
p->NS2BSIndx[0] = (0 << 1);
p->NS2BSIndx[1] = (1 << 1);
memset(p->NS2BSIndx + 2, (2 << 1), 9);
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
for (i = 0; i < 3; i++)
p->NS2Indx[i] = (Byte)i;
for (m = i, k = 1; i < 256; i++)
{
p->NS2Indx[i] = (Byte)m;
if (--k == 0)
k = (++m) - 2;
}
memset(p->HB2Flag, 0, 0x40);
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->Base);
p->Size = 0;
p->Base = 0;
}
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
{
if (p->Base == 0 || p->Size != size)
{
Ppmd7_Free(p, alloc);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
)) == 0)
return False;
p->Size = size;
}
return True;
}
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
{
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
p->FreeList[indx] = REF(node);
}
static void *RemoveNode(CPpmd7 *p, unsigned indx)
{
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
p->FreeList[indx] = *node;
return node;
}
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
{
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
ptr = (Byte *)ptr + U2B(I2U(newIndx));
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
}
InsertNode(p, ptr, i);
}
static void GlueFreeBlocks(CPpmd7 *p)
{
#ifdef PPMD_32BIT
CPpmd7_Node headItem;
CPpmd7_Node_Ref head = &headItem;
#else
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
#endif
CPpmd7_Node_Ref n = head;
unsigned i;
p->GlueCount = 255;
/* create doubly-linked list of free blocks */
for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
UInt16 nu = I2U(i);
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
p->FreeList[i] = 0;
while (next != 0)
{
CPpmd7_Node *node = NODE(next);
node->Next = n;
n = NODE(n)->Prev = next;
next = *(const CPpmd7_Node_Ref *)node;
node->Stamp = 0;
node->NU = (UInt16)nu;
}
}
NODE(head)->Stamp = 1;
NODE(head)->Next = n;
NODE(n)->Prev = head;
if (p->LoUnit != p->HiUnit)
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
/* Glue free blocks */
while (n != head)
{
CPpmd7_Node *node = NODE(n);
UInt32 nu = (UInt32)node->NU;
for (;;)
{
CPpmd7_Node *node2 = NODE(n) + nu;
nu += node2->NU;
if (node2->Stamp != 0 || nu >= 0x10000)
break;
NODE(node2->Prev)->Next = node2->Next;
NODE(node2->Next)->Prev = node2->Prev;
node->NU = (UInt16)nu;
}
n = node->Next;
}
/* Fill lists of free blocks */
for (n = NODE(head)->Next; n != head;)
{
CPpmd7_Node *node = NODE(n);
unsigned nu;
CPpmd7_Node_Ref next = node->Next;
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, node + k, nu - k - 1);
}
InsertNode(p, node, i);
n = next;
}
}
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
{
unsigned i;
void *retVal;
if (p->GlueCount == 0)
{
GlueFreeBlocks(p);
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
}
i = indx;
do
{
if (++i == PPMD_NUM_INDEXES)
{
UInt32 numBytes = U2B(I2U(indx));
p->GlueCount--;
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
}
}
while (p->FreeList[i] == 0);
retVal = RemoveNode(p, i);
SplitBlock(p, retVal, i, indx);
return retVal;
}
static void *AllocUnits(CPpmd7 *p, unsigned indx)
{
UInt32 numBytes;
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
numBytes = U2B(I2U(indx));
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
{
void *retVal = p->LoUnit;
p->LoUnit += numBytes;
return retVal;
}
return AllocUnitsRare(p, indx);
}
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
unsigned i0 = U2I(oldNU);
unsigned i1 = U2I(newNU);
if (i0 == i1)
return oldPtr;
if (p->FreeList[i1] != 0)
{
void *ptr = RemoveNode(p, i1);
MyMem12Cpy(ptr, oldPtr, newNU);
InsertNode(p, oldPtr, i0);
return ptr;
}
SplitBlock(p, oldPtr, i0, i1);
return oldPtr;
}
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
{
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
}
static void RestartModel(CPpmd7 *p)
{
unsigned i, k, m;
memset(p->FreeList, 0, sizeof(p->FreeList));
p->Text = p->Base + p->AlignOffset;
p->HiUnit = p->Text + p->Size;
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
p->GlueCount = 0;
p->OrderFall = p->MaxOrder;
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
p->PrevSuccess = 0;
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
p->MinContext->Suffix = 0;
p->MinContext->NumStats = 256;
p->MinContext->SummFreq = 256 + 1;
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
p->LoUnit += U2B(256 / 2);
p->MinContext->Stats = REF(p->FoundState);
for (i = 0; i < 256; i++)
{
CPpmd_State *s = &p->FoundState[i];
s->Symbol = (Byte)i;
s->Freq = 1;
SetSuccessor(s, 0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
{
UInt16 *dest = p->BinSumm[i] + k;
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
for (m = 0; m < 64; m += 8)
dest[m] = val;
}
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
{
CPpmd_See *s = &p->See[i][k];
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
s->Count = 4;
}
}
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
{
p->MaxOrder = maxOrder;
RestartModel(p);
p->DummySee.Shift = PPMD_PERIOD_BITS;
p->DummySee.Summ = 0; /* unused */
p->DummySee.Count = 64; /* unused */
}
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
{
CPpmd_State upState;
CTX_PTR c = p->MinContext;
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
CPpmd_State *ps[PPMD7_MAX_ORDER];
unsigned numPs = 0;
if (!skip)
ps[numPs++] = p->FoundState;
while (c->Suffix)
{
CPpmd_Void_Ref successor;
CPpmd_State *s;
c = SUFFIX(c);
if (c->NumStats != 1)
{
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
}
else
s = ONE_STATE(c);
successor = SUCCESSOR(s);
if (successor != upBranch)
{
c = CTX(successor);
if (numPs == 0)
return c;
break;
}
ps[numPs++] = s;
}
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
SetSuccessor(&upState, upBranch + 1);
if (c->NumStats == 1)
upState.Freq = ONE_STATE(c)->Freq;
else
{
UInt32 cf, s0;
CPpmd_State *s;
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
cf = s->Freq - 1;
s0 = c->SummFreq - c->NumStats - cf;
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
do
{
/* Create Child */
CTX_PTR c1; /* = AllocContext(p); */
if (p->HiUnit != p->LoUnit)
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
else if (p->FreeList[0] != 0)
c1 = (CTX_PTR)RemoveNode(p, 0);
else
{
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
if (!c1)
return NULL;
}
c1->NumStats = 1;
*ONE_STATE(c1) = upState;
c1->Suffix = REF(c);
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
}
while (numPs != 0);
return c;
}
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
{
CPpmd_State tmp = *t1;
*t1 = *t2;
*t2 = tmp;
}
static void UpdateModel(CPpmd7 *p)
{
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
CTX_PTR c;
unsigned s0, ns;
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
{
c = SUFFIX(p->MinContext);
if (c->NumStats == 1)
{
CPpmd_State *s = ONE_STATE(c);
if (s->Freq < 32)
s->Freq++;
}
else
{
CPpmd_State *s = STATS(c);
if (s->Symbol != p->FoundState->Symbol)
{
do { s++; } while (s->Symbol != p->FoundState->Symbol);
if (s[0].Freq >= s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
s--;
}
}
if (s->Freq < MAX_FREQ - 9)
{
s->Freq += 2;
c->SummFreq += 2;
}
}
}
if (p->OrderFall == 0)
{
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
if (p->MinContext == 0)
{
RestartModel(p);
return;
}
SetSuccessor(p->FoundState, REF(p->MinContext));
return;
}
*p->Text++ = p->FoundState->Symbol;
successor = REF(p->Text);
if (p->Text >= p->UnitsStart)
{
RestartModel(p);
return;
}
if (fSuccessor)
{
if (fSuccessor <= successor)
{
CTX_PTR cs = CreateSuccessors(p, False);
if (cs == NULL)
{
RestartModel(p);
return;
}
fSuccessor = REF(cs);
}
if (--p->OrderFall == 0)
{
successor = fSuccessor;
p->Text -= (p->MaxContext != p->MinContext);
}
}
else
{
SetSuccessor(p->FoundState, successor);
fSuccessor = REF(p->MinContext);
}
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
{
unsigned ns1;
UInt32 cf, sf;
if ((ns1 = c->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
/* Expand for one UNIT */
unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU);
if (i != U2I(oldNU + 1))
{
void *ptr = AllocUnits(p, i + 1);
void *oldPtr;
if (!ptr)
{
RestartModel(p);
return;
}
oldPtr = STATS(c);
MyMem12Cpy(ptr, oldPtr, oldNU);
InsertNode(p, oldPtr, i);
c->Stats = STATS_REF(ptr);
}
}
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
}
else
{
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
if (!s)
{
RestartModel(p);
return;
}
*s = *ONE_STATE(c);
c->Stats = REF(s);
if (s->Freq < MAX_FREQ / 4 - 1)
s->Freq <<= 1;
else
s->Freq = MAX_FREQ - 4;
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
}
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
sf = (UInt32)s0 + c->SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf) + (cf >= 4 * sf);
c->SummFreq += 3;
}
else
{
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
c->SummFreq = (UInt16)(c->SummFreq + cf);
}
{
CPpmd_State *s = STATS(c) + ns1;
SetSuccessor(s, successor);
s->Symbol = p->FoundState->Symbol;
s->Freq = (Byte)cf;
c->NumStats = (UInt16)(ns1 + 1);
}
}
p->MaxContext = p->MinContext = CTX(fSuccessor);
}
static void Rescale(CPpmd7 *p)
{
unsigned i, adder, sumFreq, escFreq;
CPpmd_State *stats = STATS(p->MinContext);
CPpmd_State *s = p->FoundState;
{
CPpmd_State tmp = *s;
for (; s != stats; s--)
s[0] = s[-1];
*s = tmp;
}
escFreq = p->MinContext->SummFreq - s->Freq;
s->Freq += 4;
adder = (p->OrderFall != 0);
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq = s->Freq;
i = p->MinContext->NumStats - 1;
do
{
escFreq -= (++s)->Freq;
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq += s->Freq;
if (s[0].Freq > s[-1].Freq)
{
CPpmd_State *s1 = s;
CPpmd_State tmp = *s1;
do
s1[0] = s1[-1];
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
*s1 = tmp;
}
}
while (--i);
if (s->Freq == 0)
{
unsigned numStats = p->MinContext->NumStats;
unsigned n0, n1;
do { i++; } while ((--s)->Freq == 0);
escFreq += i;
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
if (p->MinContext->NumStats == 1)
{
CPpmd_State tmp = *stats;
do
{
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
escFreq >>= 1;
}
while (escFreq > 1);
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
return;
}
n0 = (numStats + 1) >> 1;
n1 = (p->MinContext->NumStats + 1) >> 1;
if (n0 != n1)
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
}
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
p->FoundState = STATS(p->MinContext);
}
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
{
CPpmd_See *see;
unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256)
{
see = p->See[p->NS2Indx[nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (numMasked > nonMasked) +
p->HiBitsFlag;
{
unsigned r = (see->Summ >> see->Shift);
see->Summ = (UInt16)(see->Summ - r);
*escFreq = r + (r == 0);
}
}
else
{
see = &p->DummySee;
*escFreq = 1;
}
return see;
}
static void NextContext(CPpmd7 *p)
{
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
if (p->OrderFall == 0 && (Byte *)c > p->Text)
p->MinContext = p->MaxContext = c;
else
UpdateModel(p);
}
void Ppmd7_Update1(CPpmd7 *p)
{
CPpmd_State *s = p->FoundState;
s->Freq += 4;
p->MinContext->SummFreq += 4;
if (s[0].Freq > s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
p->FoundState = --s;
if (s->Freq > MAX_FREQ)
Rescale(p);
}
NextContext(p);
}
void Ppmd7_Update1_0(CPpmd7 *p)
{
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
p->RunLength += p->PrevSuccess;
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
NextContext(p);
}
void Ppmd7_UpdateBin(CPpmd7 *p)
{
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
p->PrevSuccess = 1;
p->RunLength++;
NextContext(p);
}
void Ppmd7_Update2(CPpmd7 *p)
{
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
p->RunLength = p->InitRL;
UpdateModel(p);
}

140
C/Ppmd7.h Executable file
View File

@@ -0,0 +1,140 @@
/* Ppmd7.h -- PPMdH compression codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
#ifndef __PPMD7_H
#define __PPMD7_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD7_MIN_ORDER 2
#define PPMD7_MAX_ORDER 64
#define PPMD7_MIN_MEM_SIZE (1 << 11)
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
struct CPpmd7_Context_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Context_ *
#else
UInt32
#endif
CPpmd7_Context_Ref;
typedef struct CPpmd7_Context_
{
UInt16 NumStats;
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
typedef struct
{
CPpmd7_Context *MinContext, *MaxContext;
CPpmd_State *FoundState;
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
Int32 RunLength, InitRL; /* must be 32-bit at least */
UInt32 Size;
UInt32 GlueCount;
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
UInt32 AlignOffset;
Byte Indx2Units[PPMD_NUM_INDEXES];
Byte Units2Indx[128];
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
CPpmd_See DummySee, See[25][16];
UInt16 BinSumm[128][64];
} CPpmd7;
void Ppmd7_Construct(CPpmd7 *p);
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
extern const Byte PPMD7_kExpEscape[16];
#ifdef PPMD_32BIT
#define Ppmd7_GetPtr(p, ptr) (ptr)
#define Ppmd7_GetContext(p, ptr) (ptr)
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
#else
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
#endif
void Ppmd7_Update1(CPpmd7 *p);
void Ppmd7_Update1_0(CPpmd7 *p);
void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
typedef struct
{
UInt32 (*GetThreshold)(void *p, UInt32 total);
void (*Decode)(void *p, UInt32 start, UInt32 size);
UInt32 (*DecodeBit)(void *p, UInt32 size0);
} IPpmd7_RangeDec;
typedef struct
{
IPpmd7_RangeDec p;
UInt32 Range;
UInt32 Code;
IByteIn *Stream;
} CPpmd7z_RangeDec;
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
/* ---------- Encode ---------- */
typedef struct
{
UInt64 Low;
UInt32 Range;
Byte Cache;
UInt64 CacheSize;
IByteOut *Stream;
} CPpmd7z_RangeEnc;
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
EXTERN_C_END
#endif

187
C/Ppmd7Dec.c Executable file
View File

@@ -0,0 +1,187 @@
/* Ppmd7Dec.c -- PPMdH Decoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Ppmd7.h"
#define kTopValue (1 << 24)
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
{
unsigned i;
p->Code = 0;
p->Range = 0xFFFFFFFF;
if (p->Stream->Read((void *)p->Stream) != 0)
return False;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
return (p->Code < 0xFFFFFFFF);
}
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
return (p->Code) / (p->Range /= total);
}
static void Range_Normalize(CPpmd7z_RangeDec *p)
{
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
}
}
}
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
p->Code -= start * p->Range;
p->Range *= size;
Range_Normalize(p);
}
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
UInt32 newBound = (p->Range >> 14) * size0;
UInt32 symbol;
if (p->Code < newBound)
{
symbol = 0;
p->Range = newBound;
}
else
{
symbol = 1;
p->Code -= newBound;
p->Range -= newBound;
}
Range_Normalize(p);
return symbol;
}
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
{
p->p.GetThreshold = Range_GetThreshold;
p->p.Decode = Range_Decode;
p->p.DecodeBit = Range_DecodeBit;
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
{
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
unsigned i;
UInt32 count, hiCnt;
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
{
Byte symbol;
rc->Decode(rc, 0, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1_0(p);
return symbol;
}
p->PrevSuccess = 0;
i = p->MinContext->NumStats - 1;
do
{
if ((hiCnt += (++s)->Freq) > count)
{
Byte symbol;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1(p);
return symbol;
}
}
while (--i);
if (count >= p->MinContext->SummFreq)
return -2;
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats - 1;
do { MASK((--s)->Symbol) = 0; } while (--i);
}
else
{
UInt16 *prob = Ppmd7_GetBinSumm(p);
if (rc->DecodeBit(rc, *prob) == 0)
{
Byte symbol;
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
Ppmd7_UpdateBin(p);
return symbol;
}
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
p->PrevSuccess = 0;
}
for (;;)
{
CPpmd_State *ps[256], *s;
UInt32 freqSum, count, hiCnt;
CPpmd_See *see;
unsigned i, num, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return -1;
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
hiCnt = 0;
s = Ppmd7_GetStats(p, p->MinContext);
i = 0;
num = p->MinContext->NumStats - numMasked;
do
{
int k = (int)(MASK(s->Symbol));
hiCnt += (s->Freq & k);
ps[i] = s++;
i -= k;
}
while (i != num);
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
freqSum += hiCnt;
count = rc->GetThreshold(rc, freqSum);
if (count < hiCnt)
{
Byte symbol;
CPpmd_State **pps = ps;
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
s = *pps;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
Ppmd_See_Update(see);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update2(p);
return symbol;
}
if (count >= freqSum)
return -2;
rc->Decode(rc, hiCnt, freqSum - hiCnt);
see->Summ = (UInt16)(see->Summ + freqSum);
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
}
}

185
C/Ppmd7Enc.c Executable file
View File

@@ -0,0 +1,185 @@
/* Ppmd7Enc.c -- PPMdH Encoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Ppmd7.h"
#define kTopValue (1 << 24)
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
{
p->Low = 0;
p->Range = 0xFFFFFFFF;
p->Cache = 0;
p->CacheSize = 1;
}
static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
{
if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
{
Byte temp = p->Cache;
do
{
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF;
}
while(--p->CacheSize != 0);
p->Cache = (Byte)((UInt32)p->Low >> 24);
}
p->CacheSize++;
p->Low = (UInt32)p->Low << 8;
}
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
{
p->Low += start * (p->Range /= total);
p->Range *= size;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
{
p->Range = (p->Range >> 14) * size0;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
{
UInt32 newBound = (p->Range >> 14) * size0;
p->Low += newBound;
p->Range -= newBound;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
{
unsigned i;
for (i = 0; i < 5; i++)
RangeEnc_ShiftLow(p);
}
#define MASK(sym) ((signed char *)charMask)[sym]
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
{
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
UInt32 sum;
unsigned i;
if (s->Symbol == symbol)
{
RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd7_Update1_0(p);
return;
}
p->PrevSuccess = 0;
sum = s->Freq;
i = p->MinContext->NumStats - 1;
do
{
if ((++s)->Symbol == symbol)
{
RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd7_Update1(p);
return;
}
sum += s->Freq;
}
while (--i);
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats - 1;
do { MASK((--s)->Symbol) = 0; } while (--i);
RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
}
else
{
UInt16 *prob = Ppmd7_GetBinSumm(p);
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
if (s->Symbol == symbol)
{
RangeEnc_EncodeBit_0(rc, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
p->FoundState = s;
Ppmd7_UpdateBin(p);
return;
}
else
{
RangeEnc_EncodeBit_1(rc, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
p->PrevSuccess = 0;
}
}
for (;;)
{
UInt32 escFreq;
CPpmd_See *see;
CPpmd_State *s;
UInt32 sum;
unsigned i, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return; /* EndMarker (symbol = -1) */
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
s = Ppmd7_GetStats(p, p->MinContext);
sum = 0;
i = p->MinContext->NumStats;
do
{
int cur = s->Symbol;
if (cur == symbol)
{
UInt32 low = sum;
CPpmd_State *s1 = s;
do
{
sum += (s->Freq & (int)(MASK(s->Symbol)));
s++;
}
while (--i);
RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
Ppmd_See_Update(see);
p->FoundState = s1;
Ppmd7_Update2(p);
return;
}
sum += (s->Freq & (int)(MASK(cur)));
MASK(cur) = 0;
s++;
}
while (--i);
RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
see->Summ = (UInt16)(see->Summ + sum + escFreq);
}
}

1116
C/Ppmd8.c Executable file
View File

File diff suppressed because it is too large Load Diff

132
C/Ppmd8.h Executable file
View File

@@ -0,0 +1,132 @@
/* Ppmd8.h -- PPMdI codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#ifndef __PPMD8_H
#define __PPMD8_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD8_MIN_ORDER 2
#define PPMD8_MAX_ORDER 16
struct CPpmd8_Context_;
typedef
#ifdef PPMD_32BIT
struct CPpmd8_Context_ *
#else
UInt32
#endif
CPpmd8_Context_Ref;
typedef struct CPpmd8_Context_
{
Byte NumStats;
Byte Flags;
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd8_Context_Ref Suffix;
} CPpmd8_Context;
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
/* There is some bug in FREEZE mode (including original code,
so we disable FREEZE mode support */
enum
{
PPMD8_RESTORE_METHOD_RESTART,
PPMD8_RESTORE_METHOD_CUT_OFF
#ifdef PPMD8_FREEZE_SUPPORT
, PPMD8_RESTORE_METHOD_FREEZE
#endif
};
typedef struct
{
CPpmd8_Context *MinContext, *MaxContext;
CPpmd_State *FoundState;
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;
Int32 RunLength, InitRL; /* must be 32-bit at least */
UInt32 Size;
UInt32 GlueCount;
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
UInt32 AlignOffset;
unsigned RestoreMethod;
/* Range Coder */
UInt32 Range;
UInt32 Code;
UInt32 Low;
union
{
IByteIn *In;
IByteOut *Out;
} Stream;
Byte Indx2Units[PPMD_NUM_INDEXES];
Byte Units2Indx[128];
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
UInt32 Stamps[PPMD_NUM_INDEXES];
Byte NS2BSIndx[256], NS2Indx[260];
CPpmd_See DummySee, See[24][32];
UInt16 BinSumm[25][64];
} CPpmd8;
void Ppmd8_Construct(CPpmd8 *p);
Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc);
void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc);
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
extern const Byte PPMD8_kExpEscape[16];
#ifdef PPMD_32BIT
#define Ppmd8_GetPtr(p, ptr) (ptr)
#define Ppmd8_GetContext(p, ptr) (ptr)
#define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)
#else
#define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))
#define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
#endif
void Ppmd8_Update1(CPpmd8 *p);
void Ppmd8_Update1_0(CPpmd8 *p);
void Ppmd8_Update2(CPpmd8 *p);
void Ppmd8_UpdateBin(CPpmd8 *p);
#define Ppmd8_GetBinSumm(p) \
&p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
/* ---------- Encode ---------- */
#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
EXTERN_C_END
#endif

155
C/Ppmd8Dec.c Executable file
View File

@@ -0,0 +1,155 @@
/* Ppmd8Dec.c -- PPMdI Decoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "Ppmd8.h"
#define kTop (1 << 24)
#define kBot (1 << 15)
Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
{
unsigned i;
p->Low = 0;
p->Range = 0xFFFFFFFF;
p->Code = 0;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
return (p->Code < 0xFFFFFFFF);
}
static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
{
return p->Code / (p->Range /= total);
}
static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
{
start *= p->Range;
p->Low += start;
p->Code -= start;
p->Range *= size;
while ((p->Low ^ (p->Low + p->Range)) < kTop ||
p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))
{
p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
p->Range <<= 8;
p->Low <<= 8;
}
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd8_DecodeSymbol(CPpmd8 *p)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 0)
{
CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
unsigned i;
UInt32 count, hiCnt;
if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
{
Byte symbol;
RangeDec_Decode(p, 0, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update1_0(p);
return symbol;
}
p->PrevSuccess = 0;
i = p->MinContext->NumStats;
do
{
if ((hiCnt += (++s)->Freq) > count)
{
Byte symbol;
RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update1(p);
return symbol;
}
}
while (--i);
if (count >= p->MinContext->SummFreq)
return -2;
RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats;
do { MASK((--s)->Symbol) = 0; } while (--i);
}
else
{
UInt16 *prob = Ppmd8_GetBinSumm(p);
if (((p->Code / (p->Range >>= 14)) < *prob))
{
Byte symbol;
RangeDec_Decode(p, 0, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
Ppmd8_UpdateBin(p);
return symbol;
}
RangeDec_Decode(p, *prob, (1 << 14) - *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
p->PrevSuccess = 0;
}
for (;;)
{
CPpmd_State *ps[256], *s;
UInt32 freqSum, count, hiCnt;
CPpmd_See *see;
unsigned i, num, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return -1;
p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
hiCnt = 0;
s = Ppmd8_GetStats(p, p->MinContext);
i = 0;
num = p->MinContext->NumStats - numMasked;
do
{
int k = (int)(MASK(s->Symbol));
hiCnt += (s->Freq & k);
ps[i] = s++;
i -= k;
}
while (i != num);
see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
freqSum += hiCnt;
count = RangeDec_GetThreshold(p, freqSum);
if (count < hiCnt)
{
Byte symbol;
CPpmd_State **pps = ps;
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
s = *pps;
RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
Ppmd_See_Update(see);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update2(p);
return symbol;
}
if (count >= freqSum)
return -2;
RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
see->Summ = (UInt16)(see->Summ + freqSum);
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
}
}

161
C/Ppmd8Enc.c Executable file
View File

@@ -0,0 +1,161 @@
/* Ppmd8Enc.c -- PPMdI Encoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "Ppmd8.h"
#define kTop (1 << 24)
#define kBot (1 << 15)
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p)
{
unsigned i;
for (i = 0; i < 4; i++, p->Low <<= 8 )
p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));
}
static void RangeEnc_Normalize(CPpmd8 *p)
{
while ((p->Low ^ (p->Low + p->Range)) < kTop ||
p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))
{
p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));
p->Range <<= 8;
p->Low <<= 8;
}
}
static void RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)
{
p->Low += start * (p->Range /= total);
p->Range *= size;
RangeEnc_Normalize(p);
}
static void RangeEnc_EncodeBit_0(CPpmd8 *p, UInt32 size0)
{
p->Range >>= 14;
p->Range *= size0;
RangeEnc_Normalize(p);
}
static void RangeEnc_EncodeBit_1(CPpmd8 *p, UInt32 size0)
{
p->Low += size0 * (p->Range >>= 14);
p->Range *= ((1 << 14) - size0);
RangeEnc_Normalize(p);
}
#define MASK(sym) ((signed char *)charMask)[sym]
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 0)
{
CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
UInt32 sum;
unsigned i;
if (s->Symbol == symbol)
{
RangeEnc_Encode(p, 0, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd8_Update1_0(p);
return;
}
p->PrevSuccess = 0;
sum = s->Freq;
i = p->MinContext->NumStats;
do
{
if ((++s)->Symbol == symbol)
{
RangeEnc_Encode(p, sum, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd8_Update1(p);
return;
}
sum += s->Freq;
}
while (--i);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats;
do { MASK((--s)->Symbol) = 0; } while (--i);
RangeEnc_Encode(p, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
}
else
{
UInt16 *prob = Ppmd8_GetBinSumm(p);
CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);
if (s->Symbol == symbol)
{
RangeEnc_EncodeBit_0(p, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
p->FoundState = s;
Ppmd8_UpdateBin(p);
return;
}
else
{
RangeEnc_EncodeBit_1(p, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
p->PrevSuccess = 0;
}
}
for (;;)
{
UInt32 escFreq;
CPpmd_See *see;
CPpmd_State *s;
UInt32 sum;
unsigned i, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return; /* EndMarker (symbol = -1) */
p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);
s = Ppmd8_GetStats(p, p->MinContext);
sum = 0;
i = p->MinContext->NumStats + 1;
do
{
int cur = s->Symbol;
if (cur == symbol)
{
UInt32 low = sum;
CPpmd_State *s1 = s;
do
{
sum += (s->Freq & (int)(MASK(s->Symbol)));
s++;
}
while (--i);
RangeEnc_Encode(p, low, s1->Freq, sum + escFreq);
Ppmd_See_Update(see);
p->FoundState = s1;
Ppmd8_Update2(p);
return;
}
sum += (s->Freq & (int)(MASK(cur)));
MASK(cur) = 0;
s++;
}
while (--i);
RangeEnc_Encode(p, sum, escFreq, sum + escFreq);
see->Summ = (UInt16)(see->Summ + sum + escFreq);
}
}

View File

@@ -1,5 +1,5 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2009-11-23 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@@ -122,6 +122,16 @@ typedef int Bool;
/* The following interfaces use first parameter as pointer to structure */ /* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct typedef struct
{ {
SRes (*Read)(void *p, void *buf, size_t *size); SRes (*Read)(void *p, void *buf, size_t *size);
@@ -156,7 +166,7 @@ typedef struct
typedef struct typedef struct
{ {
SRes (*Look)(void *p, void **buf, size_t *size); SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed (output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */

View File

@@ -113,6 +113,7 @@ SOURCE=..\..\7zCrcOpt.c
# Begin Source File # Begin Source File
SOURCE=..\..\7zDec.c SOURCE=..\..\7zDec.c
# ADD CPP /D "_7ZIP_PPMD_SUPPPORT"
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -172,6 +173,24 @@ SOURCE=..\..\LzmaDec.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Ppmd.h
# End Source File
# Begin Source File
SOURCE=..\..\Ppmd7.c
# SUBTRACT CPP /YX
# End Source File
# Begin Source File
SOURCE=..\..\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\Ppmd7Dec.c
# SUBTRACT CPP /YX
# End Source File
# Begin Source File
SOURCE=..\..\Types.h SOURCE=..\..\Types.h
# End Source File # End Source File
# End Group # End Group

View File

@@ -1,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2009-11-24 : Igor Pavlov : Public domain */ 2010-03-12 : Igor Pavlov : Public domain */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -183,23 +183,38 @@ static void PrintString(const UInt16 *s)
} }
} }
static void UInt64ToStr(UInt64 value, char *s)
static void ConvertNumberToString(UInt64 value, char *s)
{ {
char temp[32]; char temp[32];
int pos = 0; int pos = 0;
do do
{ {
temp[pos++] = (char)('0' + (int)(value % 10)); temp[pos++] = (char)('0' + (unsigned)(value % 10));
value /= 10; value /= 10;
} }
while (value != 0); while (value != 0);
do do
*s++ = temp[--pos]; *s++ = temp[--pos];
while (pos > 0); while (pos);
*s = '\0'; *s = '\0';
} }
static char *UIntToStr(char *s, unsigned value, int numDigits)
{
char temp[16];
int pos = 0;
do
temp[pos++] = (char)('0' + (value % 10));
while (value /= 10);
for (numDigits -= pos; numDigits > 0; numDigits--)
*s++ = '0';
do
*s++ = temp[--pos];
while (pos);
*s = '\0';
return s;
}
#define PERIOD_4 (4 * 365 + 1) #define PERIOD_4 (4 * 365 + 1)
#define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_100 (PERIOD_4 * 25 - 1)
#define PERIOD_400 (PERIOD_100 * 4 + 1) #define PERIOD_400 (PERIOD_100 * 4 + 1)
@@ -207,40 +222,22 @@ static void ConvertNumberToString(UInt64 value, char *s)
static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s) static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)
{ {
unsigned year, mon, day, hour, min, sec; unsigned year, mon, day, hour, min, sec;
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000;
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned temp; unsigned t;
UInt32 v; UInt32 v;
v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60;
sec = (unsigned)(v64 % 60); min = (unsigned)(v64 % 60); v64 /= 60;
v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24;
min = (unsigned)(v64 % 60);
v64 /= 60;
hour = (unsigned)(v64 % 24);
v64 /= 24;
v = (UInt32)v64; v = (UInt32)v64;
year = (unsigned)(1601 + v / PERIOD_400 * 400); year = (unsigned)(1601 + v / PERIOD_400 * 400);
v %= PERIOD_400; v %= PERIOD_400;
temp = (unsigned)(v / PERIOD_100); t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
if (temp == 4) t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
temp = 3; t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
year += temp * 100;
v -= temp * PERIOD_100;
temp = v / PERIOD_4;
if (temp == 25)
temp = 24;
year += temp * 4;
v -= temp * PERIOD_4;
temp = v / 365;
if (temp == 4)
temp = 3;
year += temp;
v -= temp * 365;
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
ms[1] = 29; ms[1] = 29;
@@ -252,7 +249,12 @@ static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)
v -= s; v -= s;
} }
day = (unsigned)v + 1; day = (unsigned)v + 1;
sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); s = UIntToStr(s, year, 4); *s++ = '-';
s = UIntToStr(s, mon, 2); *s++ = '-';
s = UIntToStr(s, day, 2); *s++ = ' ';
s = UIntToStr(s, hour, 2); *s++ = ':';
s = UIntToStr(s, min, 2); *s++ = ':';
s = UIntToStr(s, sec, 2);
} }
void PrintError(char *sz) void PrintError(char *sz)
@@ -260,6 +262,24 @@ void PrintError(char *sz)
printf("\nERROR: %s\n", sz); printf("\nERROR: %s\n", sz);
} }
#ifdef USE_WINDOWS_FILE
#define kEmptyAttribChar '.'
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
{
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar);
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar);
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar);
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar);
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar);
s[5] = '\0';
}
#else
static void GetAttribString(UInt32, Bool, char *s)
{
s[0] = '\0';
}
#endif
int MY_CDECL main(int numargs, char *args[]) int MY_CDECL main(int numargs, char *args[])
{ {
CFileInStream archiveStream; CFileInStream archiveStream;
@@ -362,14 +382,22 @@ int MY_CDECL main(int numargs, char *args[])
SzArEx_GetFileNameUtf16(&db, i, temp); SzArEx_GetFileNameUtf16(&db, i, temp);
if (listCommand) if (listCommand)
{ {
char s[32], t[32]; char attr[8], s[32], t[32];
ConvertNumberToString(f->Size, s);
GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);
UInt64ToStr(f->Size, s);
if (f->MTimeDefined) if (f->MTimeDefined)
ConvertFileTimeToString(&f->MTime, t); ConvertFileTimeToString(&f->MTime, t);
else else
strcpy(t, " "); {
size_t j;
for (j = 0; j < 19; j++)
t[j] = ' ';
t[j] = '\0';
}
printf("%s %10s ", t, s); printf("%s %s %10s ", t, attr, s);
PrintString(temp); PrintString(temp);
if (f->IsDir) if (f->IsDir)
printf("/"); printf("/");
@@ -436,6 +464,10 @@ int MY_CDECL main(int numargs, char *args[])
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
} }
#ifdef USE_WINDOWS_FILE
if (f->AttribDefined)
SetFileAttributesW(destPath, f->Attrib);
#endif
} }
printf("\n"); printf("\n");
} }

View File

@@ -1,4 +1,5 @@
MY_STATIC_LINK=1 MY_STATIC_LINK=1
CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT
PROG = 7zDec.exe PROG = 7zDec.exe
@@ -16,6 +17,8 @@ C_OBJS = \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
7Z_OBJS = \ 7Z_OBJS = \
$O\7zAlloc.obj \ $O\7zAlloc.obj \

View File

@@ -4,7 +4,7 @@ LIB =
RM = rm -f RM = rm -f
CFLAGS = -c -O2 -Wall CFLAGS = -c -O2 -Wall
OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
all: $(PROG) all: $(PROG)
@@ -30,7 +30,7 @@ $(PROG): $(OBJS)
$(CXX) $(CFLAGS) ../../7zCrcOpt.c $(CXX) $(CFLAGS) ../../7zCrcOpt.c
7zDec.o: ../../7zDec.c 7zDec.o: ../../7zDec.c
$(CXX) $(CFLAGS) ../../7zDec.c $(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c
7zIn.o: ../../7zIn.c 7zIn.o: ../../7zIn.c
$(CXX) $(CFLAGS) ../../7zIn.c $(CXX) $(CFLAGS) ../../7zIn.c
@@ -50,6 +50,12 @@ Bra86.o: ../../Bra86.c
Bcj2.o: ../../Bcj2.c Bcj2.o: ../../Bcj2.c
$(CXX) $(CFLAGS) ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c
Ppmd7.o: ../../Ppmd7.c
$(CXX) $(CFLAGS) ../../Ppmd7.c
Ppmd7Dec.o: ../../Ppmd7Dec.c
$(CXX) $(CFLAGS) ../../Ppmd7Dec.c
7zFile.o: ../../7zFile.c 7zFile.o: ../../7zFile.c
$(CXX) $(CFLAGS) ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c

View File

@@ -44,6 +44,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{ {
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;

View File

@@ -174,8 +174,9 @@ bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
return true; return true;
} }
static UString ConvertName(const Byte *p) static UString ConvertName(const Byte *p, bool &isMsi)
{ {
isMsi = false;
UString s; UString s;
for (int i = 0; i < kNameSizeMax; i += 2) for (int i = 0; i < kNameSizeMax; i += 2)
{ {
@@ -186,10 +187,19 @@ static UString ConvertName(const Byte *p)
} }
UString msiName; UString msiName;
if (CompoundMsiNameToFileName(s, msiName)) if (CompoundMsiNameToFileName(s, msiName))
{
isMsi = true;
return msiName; return msiName;
}
return CompoundNameToFileName(s); return CompoundNameToFileName(s);
} }
static UString ConvertName(const Byte *p)
{
bool isMsi;
return ConvertName(p, isMsi);
}
UString CDatabase::GetItemPath(UInt32 index) const UString CDatabase::GetItemPath(UInt32 index) const
{ {
UString s; UString s;
@@ -207,6 +217,7 @@ UString CDatabase::GetItemPath(UInt32 index) const
HRESULT CDatabase::Open(IInStream *inStream) HRESULT CDatabase::Open(IInStream *inStream)
{ {
MainSubfile = -1;
static const UInt32 kHeaderSize = 512; static const UInt32 kHeaderSize = 512;
Byte p[kHeaderSize]; Byte p[kHeaderSize];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
@@ -353,7 +364,26 @@ HRESULT CDatabase::Open(IInStream *inStream)
} }
} }
return AddNode(-1, root.SonDid); RINOK(AddNode(-1, root.SonDid));
unsigned numCabs = 0;
for (int i = 0; i < Refs.Size(); i++)
{
const CItem &item = Items[Refs[i].Did];
if (item.IsDir() || numCabs > 1)
continue;
bool isMsiName;
UString msiName = ConvertName(item.Name, isMsiName);
if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0)
{
numCabs++;
MainSubfile = i;
}
}
if (numCabs > 1)
MainSubfile = -1;
return S_OK;
} }
}} }}

View File

@@ -88,6 +88,8 @@ public:
int SectorSizeBits; int SectorSizeBits;
int MiniSectorSizeBits; int MiniSectorSizeBits;
Int32 MainSubfile;
void Clear(); void Clear();
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
UString GetItemPath(UInt32 index) const; UString GetItemPath(UInt32 index) const;

View File

@@ -68,10 +68,10 @@ struct CItem
class CInArchive class CInArchive
{ {
CMyComPtr<IInStream> m_Stream; CMyComPtr<IInStream> m_Stream;
UInt64 m_Position;
HRESULT GetNextItemReal(bool &filled, CItem &itemInfo); HRESULT GetNextItemReal(bool &filled, CItem &itemInfo);
public: public:
UInt64 m_Position;
HRESULT Open(IInStream *inStream); HRESULT Open(IInStream *inStream);
HRESULT GetNextItem(bool &filled, CItem &itemInfo); HRESULT GetNextItem(bool &filled, CItem &itemInfo);
HRESULT SkipData(UInt64 dataSize); HRESULT SkipData(UInt64 dataSize);
@@ -155,9 +155,9 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item)
size_t processedSize = sizeof(header); size_t processedSize = sizeof(header);
item.HeaderPos = m_Position; item.HeaderPos = m_Position;
RINOK(ReadStream(m_Stream, header, &processedSize)); RINOK(ReadStream(m_Stream, header, &processedSize));
m_Position += processedSize;
if (processedSize != sizeof(header)) if (processedSize != sizeof(header))
return S_OK; return S_OK;
m_Position += processedSize;
char tempString[NHeader::kNameSize + 1]; char tempString[NHeader::kNameSize + 1];
MyStrNCpy(tempString, cur, NHeader::kNameSize); MyStrNCpy(tempString, cur, NHeader::kNameSize);
@@ -212,14 +212,20 @@ class CHandler:
{ {
CObjectVector<CItem> _items; CObjectVector<CItem> _items;
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
Int32 _mainSubfile;
UInt64 _phySize;
public: public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;) INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
}; };
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidPhySize, VT_UI8}
};
STATPROPSTG kProps[] = static STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI8},
@@ -227,7 +233,7 @@ STATPROPSTG kProps[] =
}; };
IMP_IInArchive_Props IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */, const UInt64 * /* maxCheckStartPosition */,
@@ -235,6 +241,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
{ {
_mainSubfile = -1;
CInArchive archive; CInArchive archive;
if (archive.Open(stream) != S_OK) if (archive.Open(stream) != S_OK)
return S_FALSE; return S_FALSE;
@@ -258,6 +265,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
return S_FALSE; return S_FALSE;
if (!filled) if (!filled)
break; break;
if (item.Name.Left(5) == "data.")
_mainSubfile = _items.Size();
_items.Add(item); _items.Add(item);
archive.SkipData(item.Size); archive.SkipData(item.Size);
if (openArchiveCallback != NULL) if (openArchiveCallback != NULL)
@@ -267,6 +276,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
} }
} }
_stream = stream; _stream = stream;
_phySize = archive.m_Position;
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
@@ -285,6 +295,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: prop = _phySize; break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN

View File

@@ -259,8 +259,9 @@ struct CSection
// UInt16 NumRelocs; // UInt16 NumRelocs;
bool IsDebug; bool IsDebug;
bool IsRealSect; bool IsRealSect;
bool IsAdditionalSection;
CSection(): IsRealSect(false), IsDebug(false) {} CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
UInt64 GetPackSize() const { return PSize; } UInt64 GetPackSize() const { return PSize; }
void UpdateTotalSize(UInt32 &totalSize) void UpdateTotalSize(UInt32 &totalSize)
@@ -448,6 +449,7 @@ struct CResItem
bool IsBmp() const { return Type == 2; } bool IsBmp() const { return Type == 2; }
bool IsIcon() const { return Type == 3; } bool IsIcon() const { return Type == 3; }
bool IsString() const { return Type == 6; } bool IsString() const { return Type == 6; }
bool IsRcData() const { return Type == 10; }
}; };
struct CStringItem struct CStringItem
@@ -530,6 +532,7 @@ class CHandler:
COptHeader _optHeader; COptHeader _optHeader;
UInt32 _totalSize; UInt32 _totalSize;
UInt32 _totalSizeLimited; UInt32 _totalSizeLimited;
Int32 _mainSubfile;
CRecordVector<CResItem> _items; CRecordVector<CResItem> _items;
CObjectVector<CStringItem> _strings; CObjectVector<CStringItem> _strings;
@@ -648,7 +651,7 @@ STATPROPSTG kArcProps[] =
{ L"Stack Commit", kpidStackCommit, VT_UI8}, { L"Stack Commit", kpidStackCommit, VT_UI8},
{ L"Heap Reserve", kpidHeapReserve, VT_UI8}, { L"Heap Reserve", kpidHeapReserve, VT_UI8},
{ L"Heap Commit", kpidHeapCommit, VT_UI8}, { L"Heap Commit", kpidHeapCommit, VT_UI8},
}; };
STATPROPSTG kProps[] = STATPROPSTG kProps[] =
{ {
@@ -689,7 +692,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidLinkerVer: case kpidLinkerVer:
{ {
CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor }; CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };
VerToProp(v, prop); break; VerToProp(v, prop);
break; break;
} }
@@ -716,6 +719,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidStackCommit: prop = _optHeader.StackCommit; break; case kpidStackCommit: prop = _optHeader.StackCommit; break;
case kpidHeapReserve: prop = _optHeader.HeapReserve; break; case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
case kpidHeapCommit: prop = _optHeader.HeapCommit; break; case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
@@ -1240,16 +1244,26 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe
{ {
UInt32 mask = (1 << numBits) - 1; UInt32 mask = (1 << numBits) - 1;
size_t end = ((maxOffset + mask) & ~mask); size_t end = ((maxOffset + mask) & ~mask);
if (end < sect.VSize) if (end < sect.VSize && end <= sect.PSize)
{ {
CSection sect2; CSection sect2;
sect2.Flags = 0; sect2.Flags = 0;
// we skip Zeros to start of aligned block
size_t i;
for (i = maxOffset; i < end; i++)
if (_buf[i] != 0)
break;
if (i == end)
maxOffset = end;
sect2.Pa = sect.Pa + (UInt32)maxOffset; sect2.Pa = sect.Pa + (UInt32)maxOffset;
sect2.Va = sect.Va + (UInt32)maxOffset; sect2.Va = sect.Va + (UInt32)maxOffset;
sect2.PSize = sect.VSize - (UInt32)maxOffset; sect2.PSize = sect.VSize - (UInt32)maxOffset;
sect2.VSize = sect2.PSize; sect2.VSize = sect2.PSize;
sect2.Name = ".rsrc_1"; sect2.Name = ".rsrc_1";
sect2.Time = 0; sect2.Time = 0;
sect2.IsAdditionalSection = true;
_sections.Add(sect2); _sections.Add(sect2);
} }
} }
@@ -1262,6 +1276,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
const UInt32 kBufSize = 1 << 18; const UInt32 kBufSize = 1 << 18;
const UInt32 kSigSize = 2; const UInt32 kSigSize = 2;
_mainSubfile = -1;
CByteBuffer buffer; CByteBuffer buffer;
buffer.SetCapacity(kBufSize); buffer.SetCapacity(kBufSize);
Byte *buf = buffer; Byte *buf = buffer;
@@ -1358,6 +1374,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
CSection s2; CSection s2;
s2.Pa = s2.Va = limit; s2.Pa = s2.Va = limit;
s2.PSize = s2.VSize = s.Pa - limit; s2.PSize = s2.VSize = s.Pa - limit;
s2.IsAdditionalSection = true;
s2.Name = '['; s2.Name = '[';
s2.Name += GetDecString(num++); s2.Name += GetDecString(num++);
s2.Name += ']'; s2.Name += ']';
@@ -1374,6 +1391,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
_parseResources = true; _parseResources = true;
UInt64 mainSize = 0, mainSize2 = 0;
for (int i = 0; i < _sections.Size(); i++) for (int i = 0; i < _sections.Size(); i++)
{ {
const CSection &sect = _sections[i]; const CSection &sect = _sections[i];
@@ -1386,12 +1404,26 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{ {
_resourceFileName = GetUnicodeString(sect.Name); _resourceFileName = GetUnicodeString(sect.Name);
for (int j = 0; j < _items.Size(); j++) for (int j = 0; j < _items.Size(); j++)
if (_items[j].Enabled) {
const CResItem &item = _items[j];
if (item.Enabled)
{ {
mixItem.ResourceIndex = j; mixItem.ResourceIndex = j;
mixItem.StringIndex = -1; mixItem.StringIndex = -1;
if (item.IsRcData())
{
if (item.Size >= mainSize)
{
mainSize2 = mainSize;
mainSize = item.Size;
_mainSubfile = _mixItems.Size();
}
else if (item.Size >= mainSize2)
mainSize2 = item.Size;
}
_mixItems.Add(mixItem); _mixItems.Add(mixItem);
} }
}
if (sect.PSize > sect.VSize) if (sect.PSize > sect.VSize)
{ {
int numBits = _optHeader.GetNumFileAlignBits(); int numBits = _optHeader.GetNumFileAlignBits();
@@ -1410,6 +1442,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
sect2.VSize = sect2.PSize; sect2.VSize = sect2.PSize;
sect2.Name = ".rsrc_2"; sect2.Name = ".rsrc_2";
sect2.Time = 0; sect2.Time = 0;
sect2.IsAdditionalSection = true;
_sections.Add(sect2); _sections.Add(sect2);
} }
} }
@@ -1422,8 +1455,21 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
} }
mixItem.StringIndex = -1; mixItem.StringIndex = -1;
mixItem.ResourceIndex = -1; mixItem.ResourceIndex = -1;
if (sect.IsAdditionalSection)
{
if (sect.PSize >= mainSize)
{
mainSize2 = mainSize;
mainSize = sect.PSize;
_mainSubfile = _mixItems.Size();
}
else
mainSize2 = sect.PSize;
}
_mixItems.Add(mixItem); _mixItems.Add(mixItem);
} }
if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)
_mainSubfile = -1;
return S_OK; return S_OK;
} }

456
CPP/7zip/Archive/PpmdHandler.cpp Executable file
View File

@@ -0,0 +1,456 @@
/* PpmdHandler.c -- PPMd format handler
2010-03-10 : Igor Pavlov : Public domain
This code is based on:
PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../../../C/Alloc.h"
#include "../../../C/Ppmd7.h"
#include "../../../C/Ppmd8.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
#include "Windows/Time.h"
#include "../Common/CWrappers.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
using namespace NWindows;
namespace NArchive {
namespace NPpmd {
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 kBufSize = (1 << 20);
struct CBuf
{
Byte *Buf;
CBuf(): Buf(0) {}
~CBuf() { ::MidFree(Buf); }
bool Alloc()
{
if (!Buf)
Buf = (Byte *)::MidAlloc(kBufSize);
return (Buf != 0);
}
};
static const UInt32 kHeaderSize = 16;
static const UInt32 kSignature = 0x84ACAF8F;
static const unsigned kNewHeaderVer = 8;
struct CItem
{
UInt32 Attrib;
UInt32 Time;
AString Name;
unsigned Order;
unsigned MemInMB;
unsigned Ver;
unsigned Restor;
HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);
bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); }
};
HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
{
Byte h[kHeaderSize];
RINOK(ReadStream_FALSE(s, h, kHeaderSize));
if (GetUi32(h) != kSignature)
return S_FALSE;
Attrib = GetUi32(h + 4);
Time = GetUi32(h + 12);
unsigned info = GetUi16(h + 8);
Order = (info & 0xF) + 1;
MemInMB = ((info >> 4) & 0xFF) + 1;
Ver = info >> 12;
UInt32 nameLen = GetUi16(h + 10);
Restor = nameLen >> 14;
if (Restor > 2)
return S_FALSE;
if (Ver >= kNewHeaderVer)
nameLen &= 0x3FFF;
if (nameLen > (1 << 9))
return S_FALSE;
char *name = Name.GetBuffer(nameLen + 1);
HRESULT res = ReadStream_FALSE(s, name, nameLen);
name[nameLen] = 0;
headerSize = kHeaderSize + nameLen;
Name.ReleaseBuffer();
return res;
}
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
public CMyUnknownImp
{
CItem _item;
UInt32 _headerSize;
UInt64 _packSize;
bool _packSizeDefined;
CMyComPtr<ISequentialInStream> _stream;
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
};
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
{ NULL, kpidMethod, VT_BSTR}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
static void UIntToString(AString &s, const char *prefix, unsigned value)
{
s += prefix;
char temp[16];
::ConvertUInt32ToString((UInt32)value, temp);
s += temp;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break;
case kpidMTime:
{
FILETIME utc;
if (NTime::DosTimeToFileTime(_item.Time, utc))
prop = utc;
break;
}
case kpidAttrib: prop = _item.Attrib; break;
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
case kpidMethod:
{
AString s = "PPMd";
s += (char)('A' + _item.Ver);
UIntToString(s, ":o", _item.Order);
UIntToString(s, ":mem", _item.MemInMB);
s += 'm';
if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
UIntToString(s, ":r", _item.Restor);
prop = s;
}
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
{
return OpenSeq(stream);
}
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
{
COM_TRY_BEGIN
HRESULT res;
try
{
Close();
res = _item.ReadHeader(stream, _headerSize);
}
catch(...) { res = S_FALSE; }
if (res == S_OK)
_stream = stream;
else
Close();
return res;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_packSizeDefined = false;
_stream.Release();
return S_OK;
}
static const UInt32 kTopValue = (1 << 24);
static const UInt32 kBot = (1 << 15);
struct CRangeDecoder
{
IPpmd7_RangeDec s;
UInt32 Range;
UInt32 Code;
UInt32 Low;
CByteInBufWrap *Stream;
public:
bool Init()
{
Code = 0;
Low = 0;
Range = 0xFFFFFFFF;
for (int i = 0; i < 4; i++)
Code = (Code << 8) | Stream->ReadByte();
return Code < 0xFFFFFFFF;
}
void Normalize()
{
while ((Low ^ (Low + Range)) < kTopValue ||
Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
{
Code = (Code << 8) | Stream->ReadByte();
Range <<= 8;
Low <<= 8;
}
}
CRangeDecoder();
};
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;
}
struct CPpmdCpp
{
unsigned Ver;
CRangeDecoder _rc;
CPpmd7 _ppmd7;
CPpmd8 _ppmd8;
CPpmdCpp(unsigned version)
{
Ver = version;
Ppmd7_Construct(&_ppmd7);
Ppmd8_Construct(&_ppmd8);
}
~CPpmdCpp()
{
Ppmd7_Free(&_ppmd7, &g_BigAlloc);
Ppmd8_Free(&_ppmd8, &g_BigAlloc);
}
bool Alloc(UInt32 memInMB)
{
memInMB <<= 20;
if (Ver == 7)
return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0;
return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0;
}
void Init(unsigned order, unsigned restor)
{
if (Ver == 7)
Ppmd7_Init(&_ppmd7, order);
else
Ppmd8_Init(&_ppmd8, order, restor);;
}
bool InitRc(CByteInBufWrap *inStream)
{
if (Ver == 7)
{
_rc.Stream = inStream;
return _rc.Init();
}
else
{
_ppmd8.Stream.In = &inStream->p;
return Ppmd8_RangeDec_Init(&_ppmd8) != 0;
}
}
bool IsFinishedOK()
{
if (Ver == 7)
return Ppmd7z_RangeDec_IsFinishedOK(&_rc);
return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);
}
};
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
// extractCallback->SetTotal(_packSize);
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
CByteInBufWrap inBuf;
if (!inBuf.Alloc(1 << 20))
return E_OUTOFMEMORY;
inBuf.Stream = _stream;
CBuf outBuf;
if (!outBuf.Alloc())
return E_OUTOFMEMORY;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
CPpmdCpp ppmd(_item.Ver);
if (!ppmd.Alloc(_item.MemInMB))
return E_OUTOFMEMORY;
Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod;
if (_item.IsSupported())
{
opRes = NExtract::NOperationResult::kDataError;
ppmd.Init(_item.Order, _item.Restor);
inBuf.Init();
UInt64 outSize = 0;
if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK)
for (;;)
{
lps->InSize = _packSize = inBuf.GetProcessed();
lps->OutSize = outSize;
RINOK(lps->SetCur());
size_t i;
int sym = 0;
if (ppmd.Ver == 7)
{
for (i = 0; i < kBufSize; i++)
{
sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s);
if (inBuf.Extra || sym < 0)
break;
outBuf.Buf[i] = (Byte)sym;
}
}
else
{
for (i = 0; i < kBufSize; i++)
{
sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);
if (inBuf.Extra || sym < 0)
break;
outBuf.Buf[i] = (Byte)sym;
}
}
outSize += i;
_packSize = _headerSize + inBuf.GetProcessed();
_packSizeDefined = true;
if (realOutStream)
{
RINOK(WriteStream(realOutStream, outBuf.Buf, i));
}
if (sym < 0)
{
if (sym == -1 && ppmd.IsFinishedOK())
opRes = NExtract::NOperationResult::kOK;
break;
}
}
RINOK(inBuf.Res);
}
realOutStream.Release();
return extractCallback->SetOperationResult(opRes);
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 };
REGISTER_ARC(Ppmd)
}}

View File

@@ -15,6 +15,7 @@
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaEncoder.h" #include "../../Compress/LzmaEncoder.h"
#include "../../Compress/PpmdZip.h"
#include "../Common/InStreamWithCRC.h" #include "../Common/InStreamWithCRC.h"
@@ -169,13 +170,14 @@ HRESULT CAddCommon::Compress(
else else
{ {
if (!_cryptoStreamSpec->Filter) if (!_cryptoStreamSpec->Filter)
{
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
RINOK(_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length())); _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length());
}
UInt32 crc = 0; UInt32 crc = 0;
RINOK(GetStreamCRC(inStream, crc)); RINOK(GetStreamCRC(inStream, crc));
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(_filterSpec->CryptoSetCRC(crc)); RINOK(_filterSpec->WriteHeader(outStream, crc));
RINOK(_filterSpec->WriteHeader(outStream));
} }
RINOK(_cryptoStreamSpec->SetOutStream(outStream)); RINOK(_cryptoStreamSpec->SetOutStream(outStream));
outStreamReleaser.FilterCoder = _cryptoStreamSpec; outStreamReleaser.FilterCoder = _cryptoStreamSpec;
@@ -235,6 +237,26 @@ HRESULT CAddCommon::Compress(
numProps--; numProps--;
RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps)); RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));
} }
else if (method == NFileHeader::NCompressionMethod::kPPMd)
{
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
NWindows::NCOM::CPropVariant props[] =
{
// _options.Algo,
_options.MemSize,
_options.Order
};
PROPID propIDs[] =
{
// NCoderPropID::kAlgorithm,
NCoderPropID::kUsedMemorySize,
NCoderPropID::kOrder
};
RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
else else
{ {
CMethodId methodId; CMethodId methodId;

View File

@@ -18,6 +18,9 @@ struct CCompressionMethodMode
bool NumMatchFinderCyclesDefined; bool NumMatchFinderCyclesDefined;
UInt32 NumMatchFinderCycles; UInt32 NumMatchFinderCycles;
UInt32 DicSize; UInt32 DicSize;
UInt32 MemSize;
UInt32 Order;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
UInt32 NumThreads; UInt32 NumThreads;
#endif #endif

View File

@@ -18,6 +18,7 @@
#include "../../Compress/CopyCoder.h" #include "../../Compress/CopyCoder.h"
#include "../../Compress/LzmaDecoder.h" #include "../../Compress/LzmaDecoder.h"
#include "../../Compress/ImplodeDecoder.h" #include "../../Compress/ImplodeDecoder.h"
#include "../../Compress/PpmdZip.h"
#include "../../Compress/ShrinkDecoder.h" #include "../../Compress/ShrinkDecoder.h"
#include "../../Crypto/WzAes.h" #include "../../Crypto/WzAes.h"
@@ -595,6 +596,8 @@ HRESULT CZipDecoder::Decode(
mi.Coder = new NCompress::NImplode::NDecoder::CCoder; mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
else if (methodId == NFileHeader::NCompressionMethod::kLZMA) else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
mi.Coder = new CLzmaDecoder; mi.Coder = new CLzmaDecoder;
else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
else else
{ {
CMethodId szMethodID; CMethodId szMethodID;

View File

@@ -53,6 +53,9 @@ private:
UInt32 m_NumPasses; UInt32 m_NumPasses;
UInt32 m_NumFastBytes; UInt32 m_NumFastBytes;
UInt32 m_NumMatchFinderCycles; UInt32 m_NumMatchFinderCycles;
UInt32 m_MemSize;
UInt32 m_Order;
bool m_NumMatchFinderCyclesDefined; bool m_NumMatchFinderCyclesDefined;
bool m_ForceAesMode; bool m_ForceAesMode;
@@ -77,6 +80,8 @@ private:
m_DicSize = m_DicSize =
m_NumPasses = m_NumPasses =
m_NumFastBytes = m_NumFastBytes =
m_Order =
m_MemSize =
m_NumMatchFinderCycles = 0xFFFFFFFF; m_NumMatchFinderCycles = 0xFFFFFFFF;
m_NumMatchFinderCyclesDefined = false; m_NumMatchFinderCyclesDefined = false;
m_ForceAesMode = false; m_ForceAesMode = false;

View File

@@ -51,6 +51,18 @@ static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaDicSizeX9 = 1 << 26;
static const UInt32 kPpmdMemSizeX1 = (1 << 20);
static const UInt32 kPpmdMemSizeX3 = (1 << 22);
static const UInt32 kPpmdMemSizeX5 = (1 << 24);
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
static const UInt32 kPpmdMemSizeX9 = (1 << 27);
static const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kPpmdOrderX3 = 6;
static const UInt32 kPpmdOrderX5 = 8;
static const UInt32 kPpmdOrderX7 = 10;
static const UInt32 kPpmdOrderX9 = 16;
static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX1 = 1;
static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2NumPassesX9 = 7;
@@ -290,13 +302,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
(mainMethod == NFileHeader::NCompressionMethod::kDeflated64); (mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA); bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
bool isLz = (isLZMA || isDeflate); bool isLz = (isLZMA || isDeflate);
bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2);
options.NumPasses = m_NumPasses; options.NumPasses = m_NumPasses;
options.DicSize = m_DicSize; options.DicSize = m_DicSize;
options.NumFastBytes = m_NumFastBytes; options.NumFastBytes = m_NumFastBytes;
options.NumMatchFinderCycles = m_NumMatchFinderCycles; options.NumMatchFinderCycles = m_NumMatchFinderCycles;
options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined; options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
options.Algo = m_Algo; options.Algo = m_Algo;
options.MemSize = m_MemSize;
options.Order = m_Order;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
options.NumThreads = _numThreads; options.NumThreads = _numThreads;
#endif #endif
@@ -336,7 +349,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.Algo = (level >= 5 ? kLzAlgoX5 : options.Algo = (level >= 5 ? kLzAlgoX5 :
kLzAlgoX1); kLzAlgoX1);
} }
if (isBZip2) if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
{ {
if (options.NumPasses == 0xFFFFFFFF) if (options.NumPasses == 0xFFFFFFFF)
options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
@@ -347,6 +360,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
(level >= 3 ? kBZip2DicSizeX3 : (level >= 3 ? kBZip2DicSizeX3 :
kBZip2DicSizeX1)); kBZip2DicSizeX1));
} }
if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
{
if (options.MemSize == 0xFFFFFFFF)
options.MemSize =
(level >= 9 ? kPpmdMemSizeX9 :
(level >= 7 ? kPpmdMemSizeX7 :
(level >= 5 ? kPpmdMemSizeX5 :
(level >= 3 ? kPpmdMemSizeX3 :
kPpmdMemSizeX1))));
if (options.Order == 0xFFFFFFFF)
options.Order =
(level >= 9 ? kPpmdOrderX9 :
(level >= 7 ? kPpmdOrderX7 :
(level >= 5 ? kPpmdOrderX5 :
(level >= 3 ? kPpmdOrderX3 :
kPpmdOrderX1))));
options.Algo = 0;
}
return Update( return Update(
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
@@ -389,6 +422,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64; else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2; else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA; else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;
else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;
else return E_INVALIDARG; else return E_INVALIDARG;
} }
else if (prop.vt == VT_UI4) else if (prop.vt == VT_UI4)
@@ -446,6 +480,18 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
m_DicSize = dicSize; m_DicSize = dicSize;
} }
else if (name.Left(3) == L"MEM")
{
UInt32 memSize = kPpmdMemSizeX5;
RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
m_MemSize = memSize;
}
else if (name[0] == L'O')
{
UInt32 order = kPpmdOrderX5;
RINOK(ParsePropValue(name.Mid(1), prop, order));
m_Order = order;
}
else if (name.Left(4) == L"PASS") else if (name.Left(4) == L"PASS")
{ {
UInt32 num = kDeflateNumPassesX9; UInt32 num = kDeflateNumPassesX9;

View File

@@ -89,6 +89,7 @@ namespace NFileHeader
const Byte kExtractVersion_BZip2 = 46; const Byte kExtractVersion_BZip2 = 46;
const Byte kExtractVersion_Aes = 51; const Byte kExtractVersion_Aes = 51;
const Byte kExtractVersion_LZMA = 63; const Byte kExtractVersion_LZMA = 63;
const Byte kExtractVersion_PPMd = 63;
// const Byte kSupportedVersion = 20; // const Byte kSupportedVersion = 20;
} }

View File

@@ -148,6 +148,14 @@ SOURCE=..\..\UI\Console\ArError.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\UI\Console\BenchCon.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\BenchCon.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\CompressionMode.h SOURCE=..\..\UI\Console\CompressionMode.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -176,14 +184,6 @@ SOURCE=..\..\UI\Console\List.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\UI\Console\BenchCon.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\BenchCon.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\Main.cpp SOURCE=..\..\UI\Console\Main.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -1018,6 +1018,14 @@ SOURCE=..\..\Compress\PpmdSubAlloc.h
SOURCE=..\..\Compress\PpmdType.h SOURCE=..\..\Compress\PpmdType.h
# End Source File # End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdZip.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdZip.h
# End Source File
# End Group # End Group
# Begin Group "RangeCoder" # Begin Group "RangeCoder"
@@ -1637,6 +1645,14 @@ SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\UI\Common\Bench.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\Bench.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\DefaultName.cpp SOURCE=..\..\UI\Common\DefaultName.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -1677,14 +1693,6 @@ SOURCE=..\..\UI\Common\LoadCodecs.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\UI\Common\Bench.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\Bench.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\OpenArchive.cpp SOURCE=..\..\UI\Common\OpenArchive.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2669,6 +2677,162 @@ SOURCE=..\..\..\..\C\MtCoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\Ppmd.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Dec.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Enc.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8Dec.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8Enc.c
!IF "$(CFG)" == "Alone - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\RotateDefs.h SOURCE=..\..\..\..\C\RotateDefs.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -97,6 +97,7 @@ AR_OBJS = \
$O\DeflateProps.obj \ $O\DeflateProps.obj \
$O\GzHandler.obj \ $O\GzHandler.obj \
$O\LzmaHandler.obj \ $O\LzmaHandler.obj \
$O\PpmdHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\XzHandler.obj \ $O\XzHandler.obj \
$O\ZHandler.obj \ $O\ZHandler.obj \
@@ -195,6 +196,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \ $O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \ $O\PpmdEncoder.obj \
$O\PpmdRegister.obj \ $O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \ $O\QuantumDecoder.obj \
$O\ShrinkDecoder.obj \ $O\ShrinkDecoder.obj \
$O\ZDecoder.obj \ $O\ZDecoder.obj \
@@ -228,6 +230,12 @@ C_OBJS = \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\LzmaEnc.obj \ $O\LzmaEnc.obj \
$O\MtCoder.obj \ $O\MtCoder.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Ppmd7Enc.obj \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Sort.obj \ $O\Sort.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -176,6 +176,7 @@ AR_OBJS = \
$O\MubHandler.obj \ $O\MubHandler.obj \
$O\NtfsHandler.obj \ $O\NtfsHandler.obj \
$O\PeHandler.obj \ $O\PeHandler.obj \
$O\PpmdHandler.obj \
$O\RpmHandler.obj \ $O\RpmHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\SwfHandler.obj \ $O\SwfHandler.obj \
@@ -375,6 +376,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \ $O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \ $O\PpmdEncoder.obj \
$O\PpmdRegister.obj \ $O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \ $O\QuantumDecoder.obj \
$O\Rar1Decoder.obj \ $O\Rar1Decoder.obj \
$O\Rar2Decoder.obj \ $O\Rar2Decoder.obj \
@@ -419,6 +421,12 @@ C_OBJS = \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\LzmaEnc.obj \ $O\LzmaEnc.obj \
$O\MtCoder.obj \ $O\MtCoder.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Ppmd7Enc.obj \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Sort.obj \ $O\Sort.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -112,7 +112,6 @@ CRYPTO_OBJS = \
$O\Sha1.obj \ $O\Sha1.obj \
C_OBJS = \ C_OBJS = \
$O\Aes.obj \
$O\Alloc.obj \ $O\Alloc.obj \
$O\Bra.obj \ $O\Bra.obj \
$O\Bra86.obj \ $O\Bra86.obj \
@@ -128,6 +127,9 @@ C_OBJS = \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\LzmaEnc.obj \ $O\LzmaEnc.obj \
$O\MtCoder.obj \ $O\MtCoder.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Ppmd7Enc.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Sort.obj \ $O\Sort.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -98,6 +98,8 @@ C_OBJS = \
$O\Delta.obj \ $O\Delta.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -349,15 +349,17 @@ SOURCE=..\..\..\Common\Wildcard.h
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\PpmdContext.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdDecode.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdDecoder.cpp SOURCE=..\..\Compress\PpmdDecoder.cpp
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
!ENDIF
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -365,11 +367,17 @@ SOURCE=..\..\Compress\PpmdDecoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\PpmdEncode.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdEncoder.cpp SOURCE=..\..\Compress\PpmdEncoder.cpp
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
!ENDIF
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -434,6 +442,16 @@ SOURCE=..\..\Compress\Rar2Decoder.h
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\Rar3Decoder.cpp SOURCE=..\..\Compress\Rar3Decoder.cpp
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
!ENDIF
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -545,6 +563,14 @@ SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\PpmdZip.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdZip.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\ShrinkDecoder.cpp SOURCE=..\..\Compress\ShrinkDecoder.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -1487,6 +1513,114 @@ SOURCE=..\..\..\..\C\MtCoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\Ppmd.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Dec.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Enc.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8Dec.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd8Enc.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\RotateDefs.h SOURCE=..\..\..\..\C\RotateDefs.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2264,6 +2398,20 @@ SOURCE=..\..\Archive\PeHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Archive\PpmdHandler.cpp
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\Archive\RpmHandler.cpp SOURCE=..\..\Archive\RpmHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -73,6 +73,7 @@ AR_OBJS = \
$O\MubHandler.obj \ $O\MubHandler.obj \
$O\NtfsHandler.obj \ $O\NtfsHandler.obj \
$O\PeHandler.obj \ $O\PeHandler.obj \
$O\PpmdHandler.obj \
$O\RpmHandler.obj \ $O\RpmHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\SwfHandler.obj \ $O\SwfHandler.obj \
@@ -226,6 +227,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \ $O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \ $O\PpmdEncoder.obj \
$O\PpmdRegister.obj \ $O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \ $O\QuantumDecoder.obj \
$O\Rar1Decoder.obj \ $O\Rar1Decoder.obj \
$O\Rar2Decoder.obj \ $O\Rar2Decoder.obj \
@@ -270,6 +272,12 @@ C_OBJS = \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\LzmaEnc.obj \ $O\LzmaEnc.obj \
$O\MtCoder.obj \ $O\MtCoder.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Ppmd7Enc.obj \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Sort.obj \ $O\Sort.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -513,6 +513,14 @@ SOURCE=..\..\Common\CreateCoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Common\CWrappers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CWrappers.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilePathAutoRename.cpp SOURCE=..\..\Common\FilePathAutoRename.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -770,6 +778,20 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha256.c SOURCE=..\..\..\..\C\Sha256.c
# SUBTRACT CPP /YX /Yc /Yu # SUBTRACT CPP /YX /Yc /Yu
# End Source File # End Source File

View File

@@ -42,6 +42,7 @@ WIN_OBJS = \
7ZIP_COMMON_OBJS = \ 7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \ $O\CreateCoder.obj \
$O\CWrappers.obj \
$O\FilePathAutoRename.obj \ $O\FilePathAutoRename.obj \
$O\FileStreams.obj \ $O\FileStreams.obj \
$O\InBuffer.obj \ $O\InBuffer.obj \
@@ -108,6 +109,8 @@ C_OBJS = \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -273,6 +273,18 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Register.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaDecoder.cpp SOURCE=..\..\Compress\LzmaDecoder.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -682,6 +694,15 @@ SOURCE=..\..\..\..\C\CpuArch.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.c SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu # SUBTRACT CPP /YX /Yc /Yu
# End Source File # End Source File

View File

@@ -86,6 +86,8 @@ COMPRESS_OBJS = \
$O\BcjRegister.obj \ $O\BcjRegister.obj \
$O\CopyCoder.obj \ $O\CopyCoder.obj \
$O\CopyRegister.obj \ $O\CopyRegister.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \ $O\LzmaDecoder.obj \
$O\LzmaRegister.obj \ $O\LzmaRegister.obj \
@@ -93,6 +95,7 @@ C_OBJS = \
$O\Alloc.obj \ $O\Alloc.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -357,6 +357,14 @@ SOURCE=..\..\Common\CreateCoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Common\CWrappers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CWrappers.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilePathAutoRename.cpp SOURCE=..\..\Common\FilePathAutoRename.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -830,6 +838,20 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha256.c SOURCE=..\..\..\..\C\Sha256.c
# SUBTRACT CPP /YX /Yc /Yu # SUBTRACT CPP /YX /Yc /Yu
# End Source File # End Source File

View File

@@ -48,6 +48,7 @@ WIN_CTRL_OBJS = \
7ZIP_COMMON_OBJS = \ 7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \ $O\CreateCoder.obj \
$O\CWrappers.obj \
$O\FilePathAutoRename.obj \ $O\FilePathAutoRename.obj \
$O\FileStreams.obj \ $O\FileStreams.obj \
$O\InBuffer.obj \ $O\InBuffer.obj \
@@ -125,6 +126,8 @@ C_OBJS = \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Sha256.obj \ $O\Sha256.obj \
$O\Threads.obj \ $O\Threads.obj \

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "CWrappers.h" #include "CWrappers.h"
#include "StreamUtils.h" #include "StreamUtils.h"
@@ -125,3 +127,100 @@ CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream)
p.Seek = InStreamWrap_Seek; p.Seek = InStreamWrap_Seek;
Res = S_OK; Res = S_OK;
} }
/* ---------- CByteInBufWrap ---------- */
void CByteInBufWrap::Free()
{
::MidFree(Buf);
Buf = 0;
}
bool CByteInBufWrap::Alloc(UInt32 size)
{
if (Buf == 0 || size != Size)
{
Free();
Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);
Size = size;
}
return (Buf != 0);
}
Byte CByteInBufWrap::ReadByteFromNewBlock()
{
if (Res == S_OK)
{
UInt32 avail;
Processed += (Cur - Buf);
Res = Stream->Read(Buf, Size, &avail);
Cur = Buf;
Lim = Buf + avail;
if (avail != 0)
return *Cur++;
}
Extra = true;
return 0;
}
extern "C" static Byte Wrap_ReadByte(void *pp)
{
CByteInBufWrap *p = (CByteInBufWrap *)pp;
if (p->Cur != p->Lim)
return *p->Cur++;
return p->ReadByteFromNewBlock();
}
CByteInBufWrap::CByteInBufWrap(): Buf(0)
{
p.Read = Wrap_ReadByte;
}
/* ---------- CByteOutBufWrap ---------- */
void CByteOutBufWrap::Free()
{
::MidFree(Buf);
Buf = 0;
}
bool CByteOutBufWrap::Alloc(size_t size)
{
if (Buf == 0 || size != Size)
{
Free();
Buf = (Byte *)::MidAlloc(size);
Size = size;
}
return (Buf != 0);
}
HRESULT CByteOutBufWrap::Flush()
{
if (Res == S_OK)
{
size_t size = (Cur - Buf);
Res = WriteStream(Stream, Buf, size);
if (Res == S_OK)
Processed += size;
Cur = Buf;
}
return Res;
}
extern "C" static void Wrap_WriteByte(void *pp, Byte b)
{
CByteOutBufWrap *p = (CByteOutBufWrap *)pp;
Byte *dest = p->Cur;
*dest = b;
p->Cur = ++dest;
if (dest == p->Lim)
p->Flush();
}
CByteOutBufWrap::CByteOutBufWrap(): Buf(0)
{
p.Write = Wrap_WriteByte;
}

View File

@@ -3,8 +3,6 @@
#ifndef __C_WRAPPERS_H #ifndef __C_WRAPPERS_H
#define __C_WRAPPERS_H #define __C_WRAPPERS_H
#include "../../../C/Types.h"
#include "../ICoder.h" #include "../ICoder.h"
#include "../../Common/MyCom.h" #include "../../Common/MyCom.h"
@@ -43,4 +41,69 @@ struct CSeqOutStreamWrap
HRESULT SResToHRESULT(SRes res); HRESULT SResToHRESULT(SRes res);
struct CByteInBufWrap
{
IByteIn p;
const Byte *Cur;
const Byte *Lim;
Byte *Buf;
UInt32 Size;
ISequentialInStream *Stream;
UInt64 Processed;
bool Extra;
HRESULT Res;
CByteInBufWrap();
~CByteInBufWrap() { Free(); }
void Free();
bool Alloc(UInt32 size);
void Init()
{
Lim = Cur = Buf;
Processed = 0;
Extra = false;
Res = S_OK;
}
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
Byte ReadByteFromNewBlock();
Byte ReadByte()
{
if (Cur != Lim)
return *Cur++;
return ReadByteFromNewBlock();
}
};
struct CByteOutBufWrap
{
IByteOut p;
Byte *Cur;
const Byte *Lim;
Byte *Buf;
size_t Size;
ISequentialOutStream *Stream;
UInt64 Processed;
HRESULT Res;
CByteOutBufWrap();
~CByteOutBufWrap() { Free(); }
void Free();
bool Alloc(size_t size);
void Init()
{
Cur = Buf;
Lim = Buf + Size;
Processed = 0;
Res = S_OK;
}
UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
HRESULT Flush();
void WriteByte(Byte b)
{
*Cur++ = b;
if (Cur == Lim)
Flush();
}
};
#endif #endif

View File

@@ -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

View File

@@ -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

View File

@@ -1,154 +1,130 @@
// PpmdDecoder.cpp // PpmdDecoder.cpp
// 2009-05-30 : Igor Pavlov : Public domain // 2009-03-11 : Igor Pavlov : Public domain
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/Defs.h" #include "../../../C/Alloc.h"
#include "Windows/Defs.h" #include "../../../C/CpuArch.h"
#include "../Common/StreamUtils.h"
#include "PpmdDecoder.h" #include "PpmdDecoder.h"
namespace NCompress { namespace NCompress {
namespace NPpmd { namespace NPpmd {
const int kLenIdFinished = -1; static const UInt32 kBufSize = (1 << 20);
const int kLenIdNeedInit = -2;
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) 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 *props, UInt32 size)
{ {
if (size < 5) if (size < 5)
return E_INVALIDARG; return E_INVALIDARG;
_order = properties[0]; _order = props[0];
_usedMemorySize = 0; UInt32 memSize = GetUi32(props + 1);
for (int i = 0; i < 4; i++) if (_order < PPMD7_MIN_ORDER ||
_usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8); _order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE ||
if (_usedMemorySize > kMaxMemBlockSize) memSize > PPMD7_MAX_MEM_SIZE)
return E_NOTIMPL; return E_NOTIMPL;
if (!_inStream.Alloc(1 << 20))
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
return S_OK; return S_OK;
} }
class CDecoderFlusher HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
{ {
CDecoder *_coder; switch(_status)
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}
~CDecoderFlusher()
{ {
if (NeedFlush) case kStatus_Finished: return S_OK;
_coder->Flush(); case kStatus_Error: return S_FALSE;
_coder->ReleaseStreams(); 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) if (_outSizeDefined)
{ {
const UInt64 rem = _outSize - _processedSize; const UInt64 rem = _outSize - _processedSize;
if (size > rem) if (size > rem)
size = (UInt32)rem; size = (UInt32)rem;
} }
const UInt32 startSize = size;
if (_remainLen == kLenIdFinished) UInt32 i;
return S_OK; int sym = 0;
if (_remainLen == kLenIdNeedInit) for (i = 0; i != size; i++)
{ {
_rangeDecoder.Init(); sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p);
_remainLen = 0; if (_inStream.Extra || sym < 0)
_info.MaxOrder = 0;
_info.StartModelRare(_order);
}
while (size != 0)
{
int symbol = _info.DecodeSymbol(&_rangeDecoder);
if (symbol < 0)
{
_remainLen = kLenIdFinished;
break; break;
} memStream[i] = (Byte)sym;
if (memStream != 0)
*memStream++ = (Byte)symbol;
else
_outStream.WriteByte((Byte)symbol);
size--;
} }
_processedSize += startSize - size;
_processedSize += i;
if (_inStream.Extra)
{
_status = kStatus_Error;
return _inStream.Res;
}
if (sym < 0)
_status = (sym < -1) ? kStatus_Error : kStatus_Finished;
return S_OK; return S_OK;
} }
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
if (!_outStream.Create(1 << 20))
return E_OUTOFMEMORY;
SetInStream(inStream);
_outStream.SetStream(outStream);
SetOutStreamSize(outSize);
CDecoderFlusher flusher(this);
for (;;)
{
_processedSize = _outStream.GetProcessedSize();
UInt32 curSize = (1 << 18);
RINOK(CodeSpec(curSize, NULL));
if (_remainLen == kLenIdFinished)
break;
if (progress != NULL)
{
UInt64 inSize = _rangeDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
}
if (_outSizeDefined)
if (_outStream.GetProcessedSize() >= _outSize)
break;
}
flusher.NeedFlush = false;
return Flush();
}
#ifdef _NO_EXCEPTIONS
#define PPMD_TRY_BEGIN
#define PPMD_TRY_END
#else
#define PPMD_TRY_BEGIN try {
#define PPMD_TRY_END } \
catch(const CInBufferException &e) { return e.ErrorCode; } \
catch(const COutBufferException &e) { return e.ErrorCode; } \
catch(...) { return S_FALSE; }
#endif
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{ {
PPMD_TRY_BEGIN if (!_outBuf)
return CodeReal(inStream, outStream, inSize, outSize, progress); {
PPMD_TRY_END _outBuf = (Byte *)::MidAlloc(kBufSize);
} if (!_outBuf)
return E_OUTOFMEMORY;
}
_inStream.Stream = inStream;
SetOutStreamSize(outSize);
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) do
{ {
_rangeDecoder.SetStream(inStream); const UInt64 startPos = _processedSize;
return S_OK; HRESULT res = CodeSpec(_outBuf, kBufSize);
} size_t processed = (size_t)(_processedSize - startPos);
RINOK(WriteStream(outStream, _outBuf, processed));
STDMETHODIMP CDecoder::ReleaseInStream() RINOK(res);
{ if (_status == kStatus_Finished)
_rangeDecoder.ReleaseStream(); break;
if (progress)
{
UInt64 inSize = _inStream.GetProcessed();
RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
}
}
while (!_outSizeDefined || _processedSize < _outSize);
return S_OK; return S_OK;
} }
@@ -158,24 +134,32 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
if (_outSizeDefined) if (_outSizeDefined)
_outSize = *outSize; _outSize = *outSize;
_processedSize = 0; _processedSize = 0;
_remainLen = kLenIdNeedInit; _status = kStatus_NeedInit;
_outStream.Init();
return S_OK; return S_OK;
} }
#ifndef NO_READ_FROM_CODER #ifndef NO_READ_FROM_CODER
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
{
InSeqStream = inStream;
_inStream.Stream = inStream;
return S_OK;
}
STDMETHODIMP CDecoder::ReleaseInStream()
{
InSeqStream.Release();
return S_OK;
}
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
PPMD_TRY_BEGIN
if (processedSize)
*processedSize = 0;
const UInt64 startPos = _processedSize; const UInt64 startPos = _processedSize;
RINOK(CodeSpec(size, (Byte *)data)); HRESULT res = CodeSpec((Byte *)data, size);
if (processedSize) if (processedSize)
*processedSize = (UInt32)(_processedSize - startPos); *processedSize = (UInt32)(_processedSize - startPos);
return Flush(); return res;
PPMD_TRY_END
} }
#endif #endif

View File

@@ -1,18 +1,17 @@
// PpmdDecoder.h // PpmdDecoder.h
// 2009-05-30 : Igor Pavlov : Public domain // 2009-03-11 : Igor Pavlov : Public domain
#ifndef __COMPRESS_PPMD_DECODER_H #ifndef __COMPRESS_PPMD_DECODER_H
#define __COMPRESS_PPMD_DECODER_H #define __COMPRESS_PPMD_DECODER_H
#include "../../../C/Ppmd7.h"
#include "../../Common/MyCom.h" #include "../../Common/MyCom.h"
#include "../Common/CWrappers.h"
#include "../ICoder.h" #include "../ICoder.h"
#include "../Common/OutBuffer.h"
#include "PpmdDecode.h"
#include "RangeCoder.h"
namespace NCompress { namespace NCompress {
namespace NPpmd { namespace NPpmd {
@@ -26,25 +25,23 @@ class CDecoder :
#endif #endif
public CMyUnknownImp public CMyUnknownImp
{ {
CRangeDecoder _rangeDecoder; Byte *_outBuf;
CPpmd7z_RangeDec _rangeDec;
COutBuffer _outStream; CByteInBufWrap _inStream;
CPpmd7 _ppmd;
CDecodeInfo _info;
Byte _order; Byte _order;
UInt32 _usedMemorySize;
int _remainLen;
UInt64 _outSize;
bool _outSizeDefined; bool _outSizeDefined;
int _status;
UInt64 _outSize;
UInt64 _processedSize; UInt64 _processedSize;
HRESULT CodeSpec(UInt32 num, Byte *memStream); HRESULT CodeSpec(Byte *memStream, UInt32 size);
public: public:
#ifndef NO_READ_FROM_CODER #ifndef NO_READ_FROM_CODER
CMyComPtr<ISequentialInStream> InSeqStream;
MY_UNKNOWN_IMP4( MY_UNKNOWN_IMP4(
ICompressSetDecoderProperties2, ICompressSetDecoderProperties2,
ICompressSetInStream, ICompressSetInStream,
@@ -55,31 +52,25 @@ public:
ICompressSetDecoderProperties2) ICompressSetDecoderProperties2)
#endif #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, STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifndef NO_READ_FROM_CODER #ifndef NO_READ_FROM_CODER
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif #endif
CDecoder(): _outSizeDefined(false) {} CDecoder(): _outBuf(NULL), _outSizeDefined(false)
{
Ppmd7z_RangeDec_CreateVTable(&_rangeDec);
_rangeDec.Stream = &_inStream.p;
Ppmd7_Construct(&_ppmd);
}
~CDecoder();
}; };
}} }}

View File

@@ -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

View File

@@ -1,10 +1,10 @@
// PpmdEncoder.cpp // PpmdEncoder.cpp
// 2009-05-30 : Igor Pavlov : Public domain // 2009-03-11 : Igor Pavlov : Public domain
#include "StdAfx.h" #include "StdAfx.h"
// #include <fstream.h> #include "../../../C/Alloc.h"
// #include <iomanip.h> #include "../../../C/CpuArch.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
@@ -13,55 +13,46 @@
namespace NCompress { namespace NCompress {
namespace NPpmd { namespace NPpmd {
const UInt32 kMinMemSize = (1 << 11); static const UInt32 kBufSize = (1 << 20);
const UInt32 kMinOrder = 2;
/* static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
UInt32 g_NumInner = 0; static void SzBigFree(void *, void *address) { BigFree(address); }
UInt32 g_InnerCycles = 0; static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
UInt32 g_Encode2 = 0; CEncoder::CEncoder():
UInt32 g_Encode2Cycles = 0; _inBuf(NULL),
UInt32 g_Encode2Cycles2 = 0; _usedMemSize(1 << 24),
_order(6)
class CCounter
{ {
public: _rangeEnc.Stream = &_outStream.p;
CCounter() {} Ppmd7_Construct(&_ppmd);
~CCounter() }
{
ofstream ofs("Res.dat"); CEncoder::~CEncoder()
ofs << "innerEncode1 = " << setw(10) << g_NumInner << endl; {
ofs << "g_InnerCycles = " << setw(10) << g_InnerCycles << endl; ::MidFree(_inBuf);
ofs << "g_Encode2 = " << setw(10) << g_Encode2 << endl; Ppmd7_Free(&_ppmd, &g_BigAlloc);
ofs << "g_Encode2Cycles = " << setw(10) << g_Encode2Cycles << endl; }
ofs << "g_Encode2Cycles2= " << setw(10) << g_Encode2Cycles2 << endl;
}
};
CCounter g_Counter;
*/
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{ {
for (UInt32 i = 0; i < numProps; i++) for (UInt32 i = 0; i < numProps; i++)
{ {
const PROPVARIANT &prop = props[i]; const PROPVARIANT &prop = props[i];
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch(propIDs[i]) switch(propIDs[i])
{ {
case NCoderPropID::kUsedMemorySize: case NCoderPropID::kUsedMemorySize:
if (prop.vt != VT_UI4) if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)
return E_INVALIDARG; return E_INVALIDARG;
if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize) _usedMemSize = v;
return E_INVALIDARG;
_usedMemorySize = (UInt32)prop.ulVal;
break; break;
case NCoderPropID::kOrder: case NCoderPropID::kOrder:
if (prop.vt != VT_UI4) if (v < 2 || v > 32)
return E_INVALIDARG; return E_INVALIDARG;
if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress) _order = (Byte)v;
return E_INVALIDARG;
_order = (Byte)prop.ulVal;
break; break;
default: default:
return E_INVALIDARG; return E_INVALIDARG;
@@ -75,74 +66,54 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
const UInt32 kPropSize = 5; const UInt32 kPropSize = 5;
Byte props[kPropSize]; Byte props[kPropSize];
props[0] = _order; props[0] = _order;
for (int i = 0; i < 4; i++) SetUi32(props + 1, _usedMemSize);
props[1 + i] = Byte(_usedMemorySize >> (8 * i));
return WriteStream(outStream, props, kPropSize); return WriteStream(outStream, props, kPropSize);
} }
const UInt32 kUsedMemorySizeDefault = (1 << 24); HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const int kOrderDefault = 6; const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
CEncoder::CEncoder():
_usedMemorySize(kUsedMemorySizeDefault),
_order(kOrderDefault)
{ {
} if (!_inBuf)
{
_inBuf = (Byte *)::MidAlloc(kBufSize);
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, if (!_inBuf)
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) return E_OUTOFMEMORY;
{ }
if (!_inStream.Create(1 << 20)) if (!_outStream.Alloc(1 << 20))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (!_rangeEncoder.Create(1 << 20)) if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))
return E_OUTOFMEMORY;
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
_inStream.SetStream(inStream); _outStream.Stream = outStream;
_inStream.Init(); _outStream.Init();
_rangeEncoder.SetStream(outStream); Ppmd7z_RangeEnc_Init(&_rangeEnc);
_rangeEncoder.Init(); Ppmd7_Init(&_ppmd, _order);
CEncoderFlusher flusher(this);
_info.MaxOrder = 0;
_info.StartModelRare(_order);
UInt64 processed = 0;
for (;;) for (;;)
{ {
UInt32 size = (1 << 18); UInt32 size;
do RINOK(inStream->Read(_inBuf, kBufSize, &size));
if (size == 0)
{ {
Byte symbol; // We don't write EndMark in PPMD-7z.
if (!_inStream.ReadByte(symbol)) // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1);
{ Ppmd7z_RangeEnc_FlushData(&_rangeEnc);
// here we can write End Mark for stream version. return _outStream.Flush();
// In current version this feature is not used.
// _info.EncodeSymbol(-1, &_rangeEncoder);
return S_OK;
}
_info.EncodeSymbol(symbol, &_rangeEncoder);
} }
while (--size != 0); for (UInt32 i = 0; i < size; i++)
if (progress != NULL)
{ {
UInt64 inSize = _inStream.GetProcessedSize(); Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]);
UInt64 outSize = _rangeEncoder.GetProcessedSize(); RINOK(_outStream.Res);
RINOK(progress->SetRatioInfo(&inSize, &outSize)); }
processed += size;
if (progress)
{
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; }
}
}} }}

View File

@@ -1,17 +1,16 @@
// PpmdEncoder.h // PpmdEncoder.h
// 2009-05-30 : Igor Pavlov : Public domain // 2009-03-11 : Igor Pavlov : Public domain
#ifndef __COMPRESS_PPMD_ENCODER_H #ifndef __COMPRESS_PPMD_ENCODER_H
#define __COMPRESS_PPMD_ENCODER_H #define __COMPRESS_PPMD_ENCODER_H
#include "../../../C/Ppmd7.h"
#include "../../Common/MyCom.h" #include "../../Common/MyCom.h"
#include "../ICoder.h" #include "../ICoder.h"
#include "../Common/InBuffer.h" #include "../Common/CWrappers.h"
#include "PpmdEncode.h"
#include "RangeCoder.h"
namespace NCompress { namespace NCompress {
namespace NPpmd { namespace NPpmd {
@@ -22,56 +21,26 @@ class CEncoder :
public ICompressWriteCoderProperties, public ICompressWriteCoderProperties,
public CMyUnknownImp public CMyUnknownImp
{ {
public: Byte *_inBuf;
CInBuffer _inStream; CByteOutBufWrap _outStream;
CPpmd7z_RangeEnc _rangeEnc;
CPpmd7 _ppmd;
NRangeCoder::CEncoder _rangeEncoder; UInt32 _usedMemSize;
CEncodeInfo _info;
UInt32 _usedMemorySize;
Byte _order; 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: public:
MY_UNKNOWN_IMP2( MY_UNKNOWN_IMP2(
ICompressSetCoderProperties, ICompressSetCoderProperties,
ICompressWriteCoderProperties) ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
CEncoder(); CEncoder();
~CEncoder();
}; };
}} }}

View File

@@ -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

View File

@@ -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

223
CPP/7zip/Compress/PpmdZip.cpp Executable file
View File

@@ -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));
}
}
}
}}

74
CPP/7zip/Compress/PpmdZip.h Executable file
View File

@@ -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

View File

@@ -1,9 +1,13 @@
// Rar3Decoder.cpp // Rar3Decoder.cpp
// According to unRAR license, this code may not be used to develop // According to unRAR license, this code may not be used to develop
// a program that creates RAR archives // a program that creates RAR archives
/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
#include "Rar3Decoder.h" #include "Rar3Decoder.h"
@@ -11,6 +15,10 @@
namespace NCompress { namespace NCompress {
namespace NRar3 { 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 kNumAlignReps = 15;
static const UInt32 kSymbolReadTable = 256; static const UInt32 kSymbolReadTable = 256;
@@ -38,6 +46,48 @@ static const UInt32 kNormalMatchMinLen = 3;
static const UInt32 kVmDataSizeMax = 1 << 16; static const UInt32 kVmDataSizeMax = 1 << 16;
static const UInt32 kVmCodeSizeMax = 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(): CDecoder::CDecoder():
_window(0), _window(0),
_winPos(0), _winPos(0),
@@ -48,6 +98,7 @@ CDecoder::CDecoder():
_vmCode(0), _vmCode(0),
m_IsSolid(false) m_IsSolid(false)
{ {
Ppmd7_Construct(&_ppmd);
} }
CDecoder::~CDecoder() CDecoder::~CDecoder()
@@ -55,6 +106,7 @@ CDecoder::~CDecoder()
InitFilters(); InitFilters();
::MidFree(_vmData); ::MidFree(_vmData);
::MidFree(_window); ::MidFree(_window);
Ppmd7_Free(&_ppmd, &g_BigAlloc);
} }
HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size) HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
@@ -294,39 +346,39 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
bool CDecoder::ReadVmCodeLZ() bool CDecoder::ReadVmCodeLZ()
{ {
UInt32 firstByte = m_InBitStream.ReadBits(8); UInt32 firstByte = ReadBits(8);
UInt32 length = (firstByte & 7) + 1; UInt32 length = (firstByte & 7) + 1;
if (length == 7) if (length == 7)
length = m_InBitStream.ReadBits(8) + 7; length = ReadBits(8) + 7;
else if (length == 8) else if (length == 8)
length = m_InBitStream.ReadBits(16); length = ReadBits(16);
if (length > kVmDataSizeMax) if (length > kVmDataSizeMax)
return false; return false;
for (UInt32 i = 0; i < length; i++) for (UInt32 i = 0; i < length; i++)
_vmData[i] = (Byte)m_InBitStream.ReadBits(8); _vmData[i] = (Byte)ReadBits(8);
return AddVmCode(firstByte, length); return AddVmCode(firstByte, length);
} }
bool CDecoder::ReadVmCodePPM() bool CDecoder::ReadVmCodePPM()
{ {
int firstByte = DecodePpmSymbol(); int firstByte = DecodePpmSymbol();
if (firstByte == -1) if (firstByte < 0)
return false; return false;
UInt32 length = (firstByte & 7) + 1; UInt32 length = (firstByte & 7) + 1;
if (length == 7) if (length == 7)
{ {
int b1 = DecodePpmSymbol(); int b1 = DecodePpmSymbol();
if (b1 == -1) if (b1 < 0)
return false; return false;
length = b1 + 7; length = b1 + 7;
} }
else if (length == 8) else if (length == 8)
{ {
int b1 = DecodePpmSymbol(); int b1 = DecodePpmSymbol();
if (b1 == -1) if (b1 < 0)
return false; return false;
int b2 = DecodePpmSymbol(); int b2 = DecodePpmSymbol();
if (b2 == -1) if (b2 < 0)
return false; return false;
length = b1 * 256 + b2; length = b1 * 256 + b2;
} }
@@ -335,7 +387,7 @@ bool CDecoder::ReadVmCodePPM()
for (UInt32 i = 0; i < length; i++) for (UInt32 i = 0; i < length; i++)
{ {
int b = DecodePpmSymbol(); int b = DecodePpmSymbol();
if (b == -1) if (b < 0)
return false; return false;
_vmData[i] = (Byte)b; _vmData[i] = (Byte)b;
} }
@@ -344,7 +396,7 @@ bool CDecoder::ReadVmCodePPM()
#define RIF(x) { if (!(x)) return S_FALSE; } #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 // PPM
@@ -359,7 +411,7 @@ HRESULT CDecoder::InitPPM()
maxMB = (Byte)ReadBits(8); maxMB = (Byte)ReadBits(8);
else else
{ {
if (_ppm.SubAllocator.GetSubAllocatorSize()== 0) if (PpmError || !Ppmd7_WasAllocated(&_ppmd))
return S_FALSE; return S_FALSE;
} }
if (maxOrder & 0x40) if (maxOrder & 0x40)
@@ -371,34 +423,30 @@ HRESULT CDecoder::InitPPM()
*/ */
if (reset) if (reset)
{ {
PpmError = true;
maxOrder = (maxOrder & 0x1F) + 1; maxOrder = (maxOrder & 0x1F) + 1;
if (maxOrder > 16) if (maxOrder > 16)
maxOrder = 16 + (maxOrder - 16) * 3; maxOrder = 16 + (maxOrder - 16) * 3;
if (maxOrder == 1) if (maxOrder == 1)
{ {
// SubAlloc.StopSubAllocator(); Ppmd7_Free(&_ppmd, &g_BigAlloc);
_ppm.SubAllocator.StopSubAllocator();
return S_FALSE; return S_FALSE;
} }
// SubAlloc.StartSubAllocator(MaxMB+1); if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))
// StartModelRare(maxOrder);
if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
_ppm.MaxOrder = 0; Ppmd7_Init(&_ppmd, maxOrder);
_ppm.StartModelRare(maxOrder); PpmError = false;
} }
// return (minContext != NULL);
return S_OK; 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) HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
{ {
keepDecompressing = false; keepDecompressing = false;
if (PpmError)
return S_FALSE;
do do
{ {
if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
@@ -411,15 +459,19 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
} }
} }
int c = DecodePpmSymbol(); int c = DecodePpmSymbol();
if (c == -1) if (c < 0)
{ {
// Original code sets PPMError=true here and then it returns S_OK. Why ??? PpmError = true;
// return S_OK;
return S_FALSE; return S_FALSE;
} }
if (c == PpmEscChar) if (c == PpmEscChar)
{ {
int nextCh = DecodePpmSymbol(); int nextCh = DecodePpmSymbol();
if (nextCh < 0)
{
PpmError = true;
return S_FALSE;
}
if (nextCh == 0) if (nextCh == 0)
return ReadTables(keepDecompressing); return ReadTables(keepDecompressing);
if (nextCh == 2 || nextCh == -1) if (nextCh == 2 || nextCh == -1)
@@ -427,7 +479,10 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
if (nextCh == 3) if (nextCh == 3)
{ {
if (!ReadVmCodePPM()) if (!ReadVmCodePPM())
{
PpmError = true;
return S_FALSE; return S_FALSE;
}
continue; continue;
} }
if (nextCh == 4 || nextCh == 5) if (nextCh == 4 || nextCh == 5)
@@ -439,16 +494,22 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
int c = DecodePpmSymbol(); int c = DecodePpmSymbol();
if (c == -1) if (c < 0)
return S_OK; {
PpmError = true;
return S_FALSE;
}
distance = (distance << 8) + (Byte)c; distance = (distance << 8) + (Byte)c;
} }
distance++; distance++;
length += 28; length += 28;
} }
int c = DecodePpmSymbol(); int c = DecodePpmSymbol();
if (c == -1) if (c < 0)
return S_OK; {
PpmError = true;
return S_FALSE;
}
length += c; length += c;
if (distance >= _lzSize) if (distance >= _lzSize)
return S_FALSE; return S_FALSE;
@@ -471,7 +532,7 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
HRESULT CDecoder::ReadTables(bool &keepDecompressing) HRESULT CDecoder::ReadTables(bool &keepDecompressing)
{ {
keepDecompressing = true; keepDecompressing = true;
ReadBits((8 - m_InBitStream.GetBitPosition()) & 7); ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7);
if (ReadBits(1) != 0) if (ReadBits(1) != 0)
{ {
_lzMode = false; _lzMode = false;
@@ -510,7 +571,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
i = 0; i = 0;
while (i < kTablesSizesSum) while (i < kTablesSizesSum)
{ {
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < 16) if (number < 16)
{ {
newLevels[i] = Byte((number + m_LastLevels[i]) & 15); newLevels[i] = Byte((number + m_LastLevels[i]) & 15);
@@ -620,7 +681,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
return S_OK; return S_OK;
} }
} }
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < 256) if (number < 256)
{ {
PutByte((Byte)number); PutByte((Byte)number);
@@ -664,10 +725,10 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
rep0 = distance; rep0 = distance;
} }
UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream); UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number >= kLenTableSize) if (number >= kLenTableSize)
return S_FALSE; return S_FALSE;
length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);
} }
else else
{ {
@@ -677,14 +738,14 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
if (number < 271) if (number < 271)
{ {
number -= 263; number -= 263;
rep0 = kLen2DistStarts[number] + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]);
length = 2; length = 2;
} }
else if (number < 299) else if (number < 299)
{ {
number -= 271; number -= 271;
length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);
UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream); UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number >= kDistTableSize) if (number >= kDistTableSize)
return S_FALSE; return S_FALSE;
rep0 = kDistStart[number]; rep0 = kDistStart[number];
@@ -692,7 +753,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
if (number >= (kNumAlignBits * 2) + 2) if (number >= (kNumAlignBits * 2) + 2)
{ {
if (numBits > kNumAlignBits) if (numBits > kNumAlignBits)
rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits); rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
if (PrevAlignCount > 0) if (PrevAlignCount > 0)
{ {
PrevAlignCount--; PrevAlignCount--;
@@ -700,7 +761,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
} }
else else
{ {
UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream); UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);
if (number < (1 << kNumAlignBits)) if (number < (1 << kNumAlignBits))
{ {
rep0 += number; rep0 += number;
@@ -716,7 +777,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
} }
} }
else else
rep0 += m_InBitStream.ReadBits(numBits); rep0 += m_InBitStream.bitDecoder.ReadBits(numBits);
length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31);
} }
else else
@@ -749,6 +810,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
memset(m_LastLevels, 0, kTablesSizesSum); memset(m_LastLevels, 0, kTablesSizesSum);
TablesRead = false; TablesRead = false;
PpmEscChar = 2; PpmEscChar = 2;
PpmError = true;
InitFilters(); InitFilters();
} }
if (!m_IsSolid || !TablesRead) if (!m_IsSolid || !TablesRead)
@@ -770,7 +832,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
{ {
RINOK(DecodePPM(1 << 18, keepDecompressing)) RINOK(DecodePPM(1 << 18, keepDecompressing))
} }
UInt64 packSize = m_InBitStream.GetProcessedSize(); UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (!keepDecompressing) if (!keepDecompressing)
break; break;
@@ -804,14 +866,14 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
if (_window == 0) if (_window == 0)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
if (!m_InBitStream.Create(1 << 20)) if (!m_InBitStream.bitDecoder.Create(1 << 20))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (!_vm.Create()) if (!_vm.Create())
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
m_InBitStream.SetStream(inStream); m_InBitStream.bitDecoder.SetStream(inStream);
m_InBitStream.Init(); m_InBitStream.bitDecoder.Init();
_outStream = outStream; _outStream = outStream;
CCoderReleaser coderReleaser(this); CCoderReleaser coderReleaser(this);

View File

@@ -2,9 +2,13 @@
// According to unRAR license, this code may not be used to develop // According to unRAR license, this code may not be used to develop
// a program that creates RAR archives // a program that creates RAR archives
/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#ifndef __COMPRESS_RAR3_DECODER_H #ifndef __COMPRESS_RAR3_DECODER_H
#define __COMPRESS_RAR3_DECODER_H #define __COMPRESS_RAR3_DECODER_H
#include "../../../C/Ppmd7.h"
#include "../../Common/MyCom.h" #include "../../Common/MyCom.h"
#include "../ICoder.h" #include "../ICoder.h"
@@ -13,7 +17,6 @@
#include "BitmDecoder.h" #include "BitmDecoder.h"
#include "HuffmanDecoder.h" #include "HuffmanDecoder.h"
#include "PpmdDecode.h"
#include "Rar3Vm.h" #include "Rar3Vm.h"
namespace NCompress { namespace NCompress {
@@ -38,8 +41,8 @@ const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize
class CBitDecoder class CBitDecoder
{ {
UInt32 m_Value; UInt32 m_Value;
unsigned m_BitPos;
public: public:
UInt32 m_BitPos;
CInBuffer m_Stream; CInBuffer m_Stream;
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}
@@ -50,26 +53,13 @@ public:
m_Stream.Init(); m_Stream.Init();
m_BitPos = 0; m_BitPos = 0;
m_Value = 0; m_Value = 0;
// m_BitPos = kNumBigValueBits;
// Normalize();
} }
UInt64 GetProcessedSize() const UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }
{ return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }
UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); } UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); }
/* UInt32 GetValue(unsigned numBits)
void Normalize()
{ {
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) if (m_BitPos < numBits)
{ {
m_BitPos += 8; m_BitPos += 8;
@@ -83,13 +73,13 @@ public:
return m_Value >> (m_BitPos - numBits); return m_Value >> (m_BitPos - numBits);
} }
void MovePos(UInt32 numBits) void MovePos(unsigned numBits)
{ {
m_BitPos -= numBits; m_BitPos -= numBits;
m_Value = m_Value & ((1 << m_BitPos) - 1); m_Value = m_Value & ((1 << m_BitPos) - 1);
} }
UInt32 ReadBits(UInt32 numBits) UInt32 ReadBits(unsigned numBits)
{ {
UInt32 res = GetValue(numBits); UInt32 res = GetValue(numBits);
MovePos(numBits); MovePos(numBits);
@@ -97,67 +87,42 @@ public:
} }
}; };
const int kNumTopBits = 24; const UInt32 kTopValue = (1 << 24);
const UInt32 kTopValue = (1 << kNumTopBits);
const UInt32 kBot = (1 << 15); const UInt32 kBot = (1 << 15);
class CRangeDecoder:public NPpmd::CRangeDecoderVirt, public CBitDecoder struct CRangeDecoder
{ {
public: IPpmd7_RangeDec s;
UInt32 Range; UInt32 Range;
UInt32 Low;
UInt32 Code; UInt32 Code;
UInt32 Low;
CBitDecoder bitDecoder;
SRes Res;
public:
void InitRangeCoder()
{
Code = 0;
Low = 0;
Range = 0xFFFFFFFF;
for (int i = 0; i < 4; i++)
Code = (Code << 8) | bitDecoder.ReadBits(8);
}
void Normalize() void Normalize()
{ {
while ((Low ^ (Low + Range)) < kTopValue || while ((Low ^ (Low + Range)) < kTopValue ||
Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
{ {
Code = (Code << 8) | m_Stream.ReadByte(); Code = (Code << 8) | bitDecoder.m_Stream.ReadByte();
Range <<= 8; Range <<= 8;
Low <<= 8; Low <<= 8;
} }
} }
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) CRangeDecoder();
{
return (Code - Low) / ( Range /= total);
}
virtual void Decode(UInt32 start, UInt32 size)
{
Low += start * Range;
Range *= size;
Normalize();
}
virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
{
if (((Code - Low) / (Range >>= numTotalBits)) < size0)
{
Decode(0, size0);
return 0;
}
else
{
Decode(size0, (1 << numTotalBits) - size0);
return 1;
}
}
// UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); }
}; };
struct CFilter: public NVm::CProgram struct CFilter: public NVm::CProgram
{ {
CRecordVector<Byte> GlobalData; CRecordVector<Byte> GlobalData;
@@ -219,8 +184,9 @@ class CDecoder:
bool TablesRead; bool TablesRead;
NPpmd::CDecodeInfo _ppm; CPpmd7 _ppmd;
int PpmEscChar; int PpmEscChar;
bool PpmError;
HRESULT WriteDataToStream(const Byte *data, UInt32 size); HRESULT WriteDataToStream(const Byte *data, UInt32 size);
HRESULT WriteData(const Byte *data, UInt32 size); HRESULT WriteData(const Byte *data, UInt32 size);
@@ -252,7 +218,7 @@ public:
void ReleaseStreams() void ReleaseStreams()
{ {
_outStream.Release(); _outStream.Release();
m_InBitStream.ReleaseStream(); m_InBitStream.bitDecoder.ReleaseStream();
} }
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

View File

@@ -15,18 +15,26 @@ namespace NZip {
void CCipher::UpdateKeys(Byte b) void CCipher::UpdateKeys(Byte b)
{ {
Keys[0] = CRC_UPDATE_BYTE(Keys[0], b); Keys[0] = CRC_UPDATE_BYTE(Keys[0], b);
Keys[1] += Keys[0] & 0xff; Keys[1] = (Keys[1] + (Keys[0] & 0xFF)) * 0x8088405 + 1;
Keys[1] = Keys[1] * 134775813L + 1;
Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24)); Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24));
} }
void CCipher::SetPassword(const Byte *password, UInt32 passwordLen) STDMETHODIMP CCipher::CryptoSetPassword(const Byte *password, UInt32 passwordLen)
{ {
Keys[0] = 305419896L; Keys[0] = 0x12345678;
Keys[1] = 591751049L; Keys[1] = 0x23456789;
Keys[2] = 878082192L; Keys[2] = 0x34567890;
for (UInt32 i = 0; i < passwordLen; i++) UInt32 i;
for (i = 0; i < passwordLen; i++)
UpdateKeys(password[i]); UpdateKeys(password[i]);
for (i = 0; i < 3; i++)
Keys2[i] = Keys[i];
return S_OK;
}
STDMETHODIMP CCipher::Init()
{
return S_OK;
} }
Byte CCipher::DecryptByteSpec() Byte CCipher::DecryptByteSpec()
@@ -35,94 +43,46 @@ Byte CCipher::DecryptByteSpec()
return (Byte)((temp * (temp ^ 1)) >> 8); return (Byte)((temp * (temp ^ 1)) >> 8);
} }
Byte CCipher::DecryptByte(Byte b) HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc)
{ {
Byte c = (Byte)(b ^ DecryptByteSpec()); Byte h[kHeaderSize];
UpdateKeys(c); g_RandomGenerator.Generate(h, kHeaderSize - 2);
return c; h[kHeaderSize - 1] = (Byte)(crc >> 24);
} h[kHeaderSize - 2] = (Byte)(crc >> 16);
RestoreKeys();
Byte CCipher::EncryptByte(Byte b) Filter(h, kHeaderSize);
{ return WriteStream(outStream, h, kHeaderSize);
Byte c = (Byte)(b ^ DecryptByteSpec());
UpdateKeys(b);
return c;
}
void CCipher::DecryptHeader(Byte *buf)
{
for (unsigned i = 0; i < kHeaderSize; i++)
buf[i] = DecryptByte(buf[i]);
}
void CCipher::EncryptHeader(Byte *buf)
{
for (unsigned i = 0; i < kHeaderSize; i++)
buf[i] = EncryptByte(buf[i]);
}
STDMETHODIMP CEncoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
_cipher.SetPassword(data, size);
return S_OK;
}
STDMETHODIMP CEncoder::CryptoSetCRC(UInt32 crc)
{
_crc = crc;
return S_OK;
}
STDMETHODIMP CEncoder::Init()
{
return S_OK;
}
HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)
{
Byte header[kHeaderSize];
g_RandomGenerator.Generate(header, kHeaderSize - 2);
header[kHeaderSize - 1] = Byte(_crc >> 24);
header[kHeaderSize - 2] = Byte(_crc >> 16);
_cipher.EncryptHeader(header);
return WriteStream(outStream, header, kHeaderSize);
} }
STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
{ {
UInt32 i; for (UInt32 i = 0; i < size; i++)
for (i = 0; i < size; i++) {
data[i] = _cipher.EncryptByte(data[i]); Byte b = data[i];
return i; data[i] = (Byte)(b ^ DecryptByteSpec());;
} UpdateKeys(b);
}
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) return size;
{
_cipher.SetPassword(data, size);
return S_OK;
} }
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)
{ {
Byte header[kHeaderSize]; Byte h[kHeaderSize];
RINOK(ReadStream_FAIL(inStream, header, kHeaderSize)); RINOK(ReadStream_FAIL(inStream, h, kHeaderSize));
_cipher.DecryptHeader(header); RestoreKeys();
return S_OK; Filter(h, kHeaderSize);
}
STDMETHODIMP CDecoder::Init()
{
return S_OK; return S_OK;
} }
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{ {
UInt32 i; for (UInt32 i = 0; i < size; i++)
for (i = 0; i < size; i++) {
data[i] = _cipher.DecryptByte(data[i]); Byte c = (Byte)(data[i] ^ DecryptByteSpec());
return i; UpdateKeys(c);
data[i] = c;
}
return size;
} }
}} }}

View File

@@ -13,58 +13,43 @@ namespace NZip {
const unsigned kHeaderSize = 12; const unsigned kHeaderSize = 12;
class CCipher class CCipher:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{ {
UInt32 Keys[3]; UInt32 Keys[3];
UInt32 Keys2[3];
protected:
void UpdateKeys(Byte b); void UpdateKeys(Byte b);
Byte DecryptByteSpec(); Byte DecryptByteSpec();
public: void RestoreKeys()
void SetPassword(const Byte *password, UInt32 passwordLen); {
Byte DecryptByte(Byte b); for (int i = 0; i < 3; i++)
Byte EncryptByte(Byte b); Keys[i] = Keys2[i];
void DecryptHeader(Byte *buf); }
void EncryptHeader(Byte *buf);
};
class CEncoder :
public ICompressFilter,
public ICryptoSetPassword,
public ICryptoSetCRC,
public CMyUnknownImp
{
CCipher _cipher;
UInt32 _crc;
public: public:
MY_UNKNOWN_IMP2(
ICryptoSetPassword,
ICryptoSetCRC
)
STDMETHOD(Init)(); STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
STDMETHOD(CryptoSetCRC)(UInt32 crc);
HRESULT WriteHeader(ISequentialOutStream *outStream);
}; };
class CEncoder: public CCipher
class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{ {
CCipher _cipher;
public: public:
MY_UNKNOWN_IMP1(ICryptoSetPassword) MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); HRESULT WriteHeader(ISequentialOutStream *outStream, UInt32 crc);
HRESULT ReadHeader(ISequentialInStream *inStream);
}; };
class CDecoder: public CCipher
{
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream);
};
}} }}

View File

@@ -124,6 +124,7 @@ Handler GUIDs:
0A lzma 0A lzma
0B lzma86 0B lzma86
0C xz 0C xz
0D ppmd
D4 APM D4 APM
D5 Mslz D5 Mslz

View File

@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 10 #define MY_VER_MINOR 11
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.10 beta" #define MY_VERSION "9.11 beta"
#define MY_7ZIP_VERSION "7-Zip 9.10 beta" #define MY_7ZIP_VERSION "7-Zip 9.11 beta"
#define MY_DATE "2009-12-22" #define MY_DATE "2010-03-15"
#define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE

View File

@@ -55,8 +55,9 @@ static HRESULT DecompressArchive(
UString outDir = options.OutputDir; UString outDir = options.OutputDir;
outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));
#ifdef _WIN32 #ifdef _WIN32
outDir.TrimRight(); // GetCorrectFullFsPath doesn't like "..".
outDir = GetCorrectFullFsPath(outDir); // outDir.TrimRight();
// outDir = GetCorrectFullFsPath(outDir);
#endif #endif
if (!outDir.IsEmpty()) if (!outDir.IsEmpty())

View File

@@ -590,9 +590,14 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
{ {
if (archiveLink.VolumePaths.Size() != 0) if (archiveLink.VolumePaths.Size() != 0)
arcPackSize += archiveLink.VolumesSize; arcPackSize += archiveLink.VolumesSize;
totalPackSize = arcPackSize; totalPackSize = (numFiles == 0) ? 0 : arcPackSize;
totalPackSizePointer = &totalPackSize; totalPackSizePointer = &totalPackSize;
} }
if (totalUnPackSizePointer == 0 && numFiles == 0)
{
totalUnPackSize = 0;
totalUnPackSizePointer = &totalUnPackSize;
}
if (enableHeaders && !techMode) if (enableHeaders && !techMode)
{ {
fieldPrinter.PrintTitleLines(); fieldPrinter.PrintTitleLines();

View File

@@ -118,6 +118,12 @@ STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message)
return S_OK; return S_OK;
} }
static void ReduceString(UString &s, int size)
{
if (s.Length() > size)
s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2);
}
STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted) STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted)
{ {
switch(operationResult) switch(operationResult)
@@ -145,10 +151,11 @@ STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool
default: default:
return E_FAIL; return E_FAIL;
} }
char buffer[512]; UString name = m_CurrentFilePath;
const AString s = UnicodeStringToMultiByte(m_CurrentFilePath, m_CodePage); ReduceString(name, 70);
sprintf(buffer, g_StartupInfo.GetMsgString(idMessage), (const char *)s); AString s = g_StartupInfo.GetMsgString(idMessage);
if (g_StartupInfo.ShowMessage(buffer) == -1) s.Replace(" '%s'", "");
if (g_StartupInfo.ShowMessageLines(s + (AString)("\n") + UnicodeStringToMultiByte(name, m_CodePage)) == -1)
return E_ABORT; return E_ABORT;
} }
} }

View File

@@ -29,6 +29,16 @@ struct CVolSeqName
UString ChangedPart; UString ChangedPart;
CVolSeqName(): ChangedPart(L"000") {}; CVolSeqName(): ChangedPart(L"000") {};
void SetNumDigits(UInt64 numVolumes)
{
ChangedPart = L"000";
while (numVolumes > 999)
{
numVolumes /= 10;
ChangedPart += L'0';
}
}
bool ParseName(const UString &name) bool ParseName(const UString &name)
{ {
if (name.Right(2) != L"01") if (name.Right(2) != L"01")
@@ -81,6 +91,7 @@ class CThreadSplit: public CProgressThreadVirt
public: public:
UString FilePath; UString FilePath;
UString VolBasePath; UString VolBasePath;
UInt64 NumVolumes;
CRecordVector<UInt64> VolumeSizes; CRecordVector<UInt64> VolumeSizes;
}; };
@@ -96,6 +107,7 @@ HRESULT CThreadSplit::ProcessVirt()
Byte *buffer = (Byte *)(void *)bufferObject; Byte *buffer = (Byte *)(void *)bufferObject;
UInt64 curVolSize = 0; UInt64 curVolSize = 0;
CVolSeqName seqName; CVolSeqName seqName;
seqName.SetNumDigits(NumVolumes);
UInt64 length; UInt64 length;
if (!inFile.GetLength(length)) if (!inFile.GetLength(length))
return GetLastError(); return GetLastError();
@@ -226,6 +238,7 @@ void CApp::Split()
{ {
CThreadSplit spliter; CThreadSplit spliter;
spliter.NumVolumes = numVolumes;
CProgressDialog &progressDialog = spliter.ProgressDialog; CProgressDialog &progressDialog = spliter.ProgressDialog;
@@ -241,7 +254,7 @@ void CApp::Split()
spliter.FilePath = srcPath + itemName; spliter.FilePath = srcPath + itemName;
spliter.VolBasePath = path + itemName; spliter.VolBasePath = path + itemName;
spliter.VolumeSizes = splitDialog.VolumeSizes; spliter.VolumeSizes = splitDialog.VolumeSizes;
// if (splitDialog.VolumeSizes.Size() == 0) return; // if (splitDialog.VolumeSizes.Size() == 0) return;

View File

@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName% InstallDir = %CE1%\%AppName%
[Strings] [Strings]
AppVer = "9.10" AppVer = "9.11"
AppDate = "2009-12-22" AppDate = "2010-03-14"
[CEDevice] [CEDevice]
; ProcessorType = 2577 ; ARM ; ProcessorType = 2577 ; ARM

View File

@@ -2,7 +2,7 @@
;Defines ;Defines
!define VERSION_MAJOR 9 !define VERSION_MAJOR 9
!define VERSION_MINOR 10 !define VERSION_MINOR 11
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64
@@ -216,6 +216,7 @@ Section
File it.txt File it.txt
File ja.txt File ja.txt
File ka.txt File ka.txt
File kk.txt
File ko.txt File ko.txt
File ku.txt File ku.txt
File ku-ckb.txt File ku-ckb.txt
@@ -405,6 +406,7 @@ Section "Uninstall"
Delete $INSTDIR\Lang\it.txt Delete $INSTDIR\Lang\it.txt
Delete $INSTDIR\Lang\ja.txt Delete $INSTDIR\Lang\ja.txt
Delete $INSTDIR\Lang\ka.txt Delete $INSTDIR\Lang\ka.txt
Delete $INSTDIR\Lang\kk.txt
Delete $INSTDIR\Lang\ko.txt Delete $INSTDIR\Lang\ko.txt
Delete $INSTDIR\Lang\ku.txt Delete $INSTDIR\Lang\ku.txt
Delete $INSTDIR\Lang\ku-ckb.txt Delete $INSTDIR\Lang\ku-ckb.txt

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "9" ?> <?define VerMajor = "9" ?>
<?define VerMinor = "10" ?> <?define VerMinor = "11" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
@@ -258,6 +258,7 @@
<File Id="it.txt" Name="it.txt" /> <File Id="it.txt" Name="it.txt" />
<File Id="ja.txt" Name="ja.txt" /> <File Id="ja.txt" Name="ja.txt" />
<File Id="ka.txt" Name="ka.txt" /> <File Id="ka.txt" Name="ka.txt" />
<File Id="kk.txt" Name="kk.txt" />
<File Id="ko.txt" Name="ko.txt" /> <File Id="ko.txt" Name="ko.txt" />
<File Id="ku.txt" Name="ku.txt" /> <File Id="ku.txt" Name="ku.txt" />
<File Id="ku_ckb.txt" Name="ku-ckb.txt" /> <File Id="ku_ckb.txt" Name="ku-ckb.txt" />

View File

@@ -3,7 +3,7 @@
License for use and distribution License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-Zip Copyright (C) 1999-2009 Igor Pavlov. 7-Zip Copyright (C) 1999-2010 Igor Pavlov.
Licenses for files are: Licenses for files are:

View File

@@ -1,4 +1,4 @@
LZMA SDK 9.10 LZMA SDK 9.11
------------- -------------
LZMA SDK provides the documentation, samples, header files, libraries, LZMA SDK provides the documentation, samples, header files, libraries,
@@ -20,6 +20,10 @@ LICENSE
LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK is written and placed in the public domain by Igor Pavlov.
Some code in LZMA is based on public domain code from another developers:
1) PPMd var.H (2001): Dmitry Shkarin
2) SHA-256: Wei Dai (Crypto++ library)
LZMA SDK Contents LZMA SDK Contents
----------------- -----------------
@@ -547,8 +551,8 @@ Return code:
LZMA Defines Defines
------------ -------
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
@@ -560,6 +564,9 @@ _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.
C++ LZMA Encoder/Decoder C++ LZMA Encoder/Decoder
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
C++ LZMA code use COM-like interfaces. So if you want to use it, C++ LZMA code use COM-like interfaces. So if you want to use it,

View File

@@ -1,9 +1,9 @@
7-Zip 9.10 Sources 7-Zip 9.11 Sources
------------------ ------------------
7-Zip is a file archiver for Windows. 7-Zip is a file archiver for Windows.
7-Zip Copyright (C) 1999-2009 Igor Pavlov. 7-Zip Copyright (C) 1999-2010 Igor Pavlov.
License Info License Info