mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
9.11
This commit is contained in:
committed by
Kornel Lesiński
parent
db5eb6d638
commit
993daef9cb
4
C/7z.h
4
C/7z.h
@@ -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
164
C/7zDec.c
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
23
C/7zIn.c
23
C/7zIn.c
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
12
C/CpuArch.h
12
C/CpuArch.h
@@ -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
81
C/Ppmd.h
Executable 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
708
C/Ppmd7.c
Executable 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
140
C/Ppmd7.h
Executable 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
187
C/Ppmd7Dec.c
Executable 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
185
C/Ppmd7Enc.c
Executable 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
132
C/Ppmd8.h
Executable file
132
C/Ppmd8.h
Executable 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
155
C/Ppmd8Dec.c
Executable 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
161
C/Ppmd8Enc.c
Executable 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
C/Types.h
14
C/Types.h
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 § = _sections[i];
|
const CSection § = _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
456
CPP/7zip/Archive/PpmdHandler.cpp
Executable 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(¤tTotalPacked));
|
||||||
|
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)
|
||||||
|
|
||||||
|
}}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
223
CPP/7zip/Compress/PpmdZip.cpp
Executable 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
74
CPP/7zip/Compress/PpmdZip.h
Executable 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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
13
DOC/lzma.txt
13
DOC/lzma.txt
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user