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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

@@ -15,6 +15,7 @@
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaEncoder.h"
#include "../../Compress/PpmdZip.h"
#include "../Common/InStreamWithCRC.h"
@@ -169,13 +170,14 @@ HRESULT CAddCommon::Compress(
else
{
if (!_cryptoStreamSpec->Filter)
{
_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;
RINOK(GetStreamCRC(inStream, crc));
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(_filterSpec->CryptoSetCRC(crc));
RINOK(_filterSpec->WriteHeader(outStream));
RINOK(_filterSpec->WriteHeader(outStream, crc));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
@@ -235,6 +237,26 @@ HRESULT CAddCommon::Compress(
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
{
CMethodId methodId;

View File

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

View File

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

View File

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

View File

@@ -51,6 +51,18 @@ static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 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 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7;
@@ -290,13 +302,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
(mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
bool isLz = (isLZMA || isDeflate);
bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2);
options.NumPasses = m_NumPasses;
options.DicSize = m_DicSize;
options.NumFastBytes = m_NumFastBytes;
options.NumMatchFinderCycles = m_NumMatchFinderCycles;
options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
options.Algo = m_Algo;
options.MemSize = m_MemSize;
options.Order = m_Order;
#ifndef _7ZIP_ST
options.NumThreads = _numThreads;
#endif
@@ -336,7 +349,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.Algo = (level >= 5 ? kLzAlgoX5 :
kLzAlgoX1);
}
if (isBZip2)
if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
{
if (options.NumPasses == 0xFFFFFFFF)
options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
@@ -347,6 +360,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
(level >= 3 ? kBZip2DicSizeX3 :
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(
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"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
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 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));
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")
{
UInt32 num = kDeflateNumPassesX9;

View File

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

View File

@@ -148,6 +148,14 @@ SOURCE=..\..\UI\Console\ArError.h
# End 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
# End Source File
# Begin Source File
@@ -176,14 +184,6 @@ SOURCE=..\..\UI\Console\List.h
# End 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
# End Source File
# Begin Source File
@@ -1018,6 +1018,14 @@ SOURCE=..\..\Compress\PpmdSubAlloc.h
SOURCE=..\..\Compress\PpmdType.h
# 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
# Begin Group "RangeCoder"
@@ -1637,6 +1645,14 @@ SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
# End 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
# End Source File
# Begin Source File
@@ -1677,14 +1693,6 @@ SOURCE=..\..\UI\Common\LoadCodecs.h
# End 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
# End Source File
# Begin Source File
@@ -2669,6 +2677,162 @@ SOURCE=..\..\..\..\C\MtCoder.h
# End 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
# End Source File
# Begin Source File

View File

@@ -97,6 +97,7 @@ AR_OBJS = \
$O\DeflateProps.obj \
$O\GzHandler.obj \
$O\LzmaHandler.obj \
$O\PpmdHandler.obj \
$O\SplitHandler.obj \
$O\XzHandler.obj \
$O\ZHandler.obj \
@@ -195,6 +196,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \
$O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \
$O\ShrinkDecoder.obj \
$O\ZDecoder.obj \
@@ -228,6 +230,12 @@ C_OBJS = \
$O\LzmaDec.obj \
$O\LzmaEnc.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\Sort.obj \
$O\Threads.obj \

View File

@@ -176,6 +176,7 @@ AR_OBJS = \
$O\MubHandler.obj \
$O\NtfsHandler.obj \
$O\PeHandler.obj \
$O\PpmdHandler.obj \
$O\RpmHandler.obj \
$O\SplitHandler.obj \
$O\SwfHandler.obj \
@@ -375,6 +376,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \
$O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \
$O\Rar1Decoder.obj \
$O\Rar2Decoder.obj \
@@ -419,6 +421,12 @@ C_OBJS = \
$O\LzmaDec.obj \
$O\LzmaEnc.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\Sort.obj \
$O\Threads.obj \

View File

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

View File

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

View File

@@ -349,15 +349,17 @@ SOURCE=..\..\..\Common\Wildcard.h
# PROP Default_Filter ""
# 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
!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
@@ -365,11 +367,17 @@ SOURCE=..\..\Compress\PpmdDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdEncode.h
# End Source File
# Begin Source File
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
# Begin Source File
@@ -434,6 +442,16 @@ SOURCE=..\..\Compress\Rar2Decoder.h
# Begin Source File
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
# Begin Source File
@@ -545,6 +563,14 @@ SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h
# End 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
# End Source File
# Begin Source File
@@ -1487,6 +1513,114 @@ SOURCE=..\..\..\..\C\MtCoder.h
# End 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
# End Source File
# Begin Source File
@@ -2264,6 +2398,20 @@ SOURCE=..\..\Archive\PeHandler.cpp
# End 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
# End Source File
# Begin Source File

View File

@@ -73,6 +73,7 @@ AR_OBJS = \
$O\MubHandler.obj \
$O\NtfsHandler.obj \
$O\PeHandler.obj \
$O\PpmdHandler.obj \
$O\RpmHandler.obj \
$O\SplitHandler.obj \
$O\SwfHandler.obj \
@@ -226,6 +227,7 @@ COMPRESS_OBJS = \
$O\PpmdDecoder.obj \
$O\PpmdEncoder.obj \
$O\PpmdRegister.obj \
$O\PpmdZip.obj \
$O\QuantumDecoder.obj \
$O\Rar1Decoder.obj \
$O\Rar2Decoder.obj \
@@ -270,6 +272,12 @@ C_OBJS = \
$O\LzmaDec.obj \
$O\LzmaEnc.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\Sort.obj \
$O\Threads.obj \

View File

@@ -513,6 +513,14 @@ SOURCE=..\..\Common\CreateCoder.h
# End 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
# End Source File
# Begin Source File
@@ -770,6 +778,20 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End 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
# SUBTRACT CPP /YX /Yc /Yu
# End Source File

View File

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

View File

@@ -273,6 +273,18 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End 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
# End Source File
# Begin Source File
@@ -682,6 +694,15 @@ SOURCE=..\..\..\..\C\CpuArch.h
# End 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
# SUBTRACT CPP /YX /Yc /Yu
# End Source File

View File

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

View File

@@ -357,6 +357,14 @@ SOURCE=..\..\Common\CreateCoder.h
# End 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
# End Source File
# Begin Source File
@@ -830,6 +838,20 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End 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
# SUBTRACT CPP /YX /Yc /Yu
# End Source File

View File

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

View File

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

View File

@@ -3,8 +3,6 @@
#ifndef __C_WRAPPERS_H
#define __C_WRAPPERS_H
#include "../../../C/Types.h"
#include "../ICoder.h"
#include "../../Common/MyCom.h"
@@ -43,4 +41,69 @@ struct CSeqOutStreamWrap
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

View File

@@ -1,490 +0,0 @@
// PpmdContext.h
// 2009-05-30 : Igor Pavlov : Public domain
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
#ifndef __COMPRESS_PPMD_CONTEXT_H
#define __COMPRESS_PPMD_CONTEXT_H
#include "../../Common/Types.h"
#include "PpmdSubAlloc.h"
#include "RangeCoder.h"
namespace NCompress {
namespace NPpmd {
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
struct SEE2_CONTEXT
{
// SEE-contexts for PPM-contexts with masked symbols
UInt16 Summ;
Byte Shift, Count;
void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }
unsigned int getMean()
{
unsigned int RetVal=(Summ >> Shift);
Summ = (UInt16)(Summ - RetVal);
return RetVal+(RetVal == 0);
}
void update()
{
if (Shift < PERIOD_BITS && --Count == 0)
{
Summ <<= 1;
Count = (Byte)(3 << Shift++);
}
}
};
struct PPM_CONTEXT
{
UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)
UInt16 SummFreq;
struct STATE
{
Byte Symbol, Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }
void SetSuccessor(UInt32 v)
{
SuccessorLow = (UInt16)(v & 0xFFFF);
SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);
}
};
UInt32 Stats;
UInt32 Suffix;
PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
{
PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
if (pc)
{
pc->NumStats = 1;
pc->oneState() = FirstState;
pc->Suffix = subAllocator.GetOffset(this);
pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
}
return pc;
}
STATE& oneState() const { return (STATE&) SummFreq; }
};
/////////////////////////////////
const UInt16 InitBinEsc[] =
{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
struct CInfo
{
CSubAllocator SubAllocator;
SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
PPM_CONTEXT * MinContext, * MaxContext;
PPM_CONTEXT::STATE* FoundState; // found next state transition
int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
UInt16 BinSumm[128][64]; // binary SEE-contexts
UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
return BinSumm[rs.Freq - 1][
PrevSuccess + NS2BSIndx[numStates - 1] +
HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
((RunLength >> 26) & 0x20)];
}
PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }
PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
void RestartModelRare()
{
int i, k, m;
memset(CharMask,0,sizeof(CharMask));
SubAllocator.InitSubAllocator();
InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
MinContext->Suffix = 0;
OrderFall = MaxOrder;
MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);
FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
PrevSuccess = 0;
for (RunLength = InitRL, i = 0; i < 256; i++)
{
PPM_CONTEXT::STATE &state = FoundState[i];
state.Symbol = (Byte)i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
for ( m=0; m < 64; m += 8)
BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
SEE2Cont[i][k].init(5*i+10);
}
void StartModelRare(int maxOrder)
{
int i, k, m ,Step;
EscCount=PrintCount=1;
if (maxOrder < 2)
{
memset(CharMask,0,sizeof(CharMask));
OrderFall = MaxOrder;
MinContext = MaxContext;
while (MinContext->Suffix != 0)
{
MinContext = GetContextNoCheck(MinContext->Suffix);
OrderFall--;
}
FoundState = GetState(MinContext->Stats);
MinContext = MaxContext;
}
else
{
MaxOrder = maxOrder;
RestartModelRare();
NS2BSIndx[0] = 2 * 0;
NS2BSIndx[1] = 2 * 1;
memset(NS2BSIndx + 2, 2 * 2, 9);
memset(NS2BSIndx + 11, 2 * 3, 256 - 11);
for (i = 0; i < 3; i++)
NS2Indx[i] = (Byte)i;
for (m = i, k = Step = 1; i < 256; i++)
{
NS2Indx[i] = (Byte)m;
if ( !--k )
{
k = ++Step;
m++;
}
}
memset(HB2Flag, 0, 0x40);
memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);
DummySEE2Cont.Shift = PERIOD_BITS;
}
}
PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
{
// static UpState declaration bypasses IntelC bug
// static PPM_CONTEXT::STATE UpState;
PPM_CONTEXT::STATE UpState;
PPM_CONTEXT *pc = MinContext;
PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
if ( !skip )
{
*pps++ = FoundState;
if ( !pc->Suffix )
goto NO_LOOP;
}
if ( p1 )
{
p = p1;
pc = GetContext(pc->Suffix);
goto LOOP_ENTRY;
}
do
{
pc = GetContext(pc->Suffix);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
do { p++; } while (p->Symbol != FoundState->Symbol);
}
else
p = &(pc->oneState());
LOOP_ENTRY:
if (GetContext(p->GetSuccessor()) != UpBranch)
{
pc = GetContext(p->GetSuccessor());
break;
}
*pps++ = p;
}
while ( pc->Suffix );
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol = *(Byte*) UpBranch;
UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)
do { p++; } while (p->Symbol != UpState.Symbol);
unsigned int cf = p->Freq-1;
unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :
((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
else
UpState.Freq = pc->oneState().Freq;
do
{
pc = pc->createChild(SubAllocator, *--pps, UpState);
if ( !pc )
return NULL;
}
while (pps != ps);
return pc;
}
void UpdateModel()
{
PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
PPM_CONTEXT* pc, * Successor;
unsigned int ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)
{
pc = GetContextNoCheck(MinContext->Suffix);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)
{
do { p++; } while (p->Symbol != fs.Symbol);
if (p[0].Freq >= p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
p--;
}
}
if (p->Freq < MAX_FREQ-9)
{
p->Freq += 2;
pc->SummFreq += 2;
}
}
else
{
p = &(pc->oneState());
p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0));
}
}
if ( !OrderFall )
{
MinContext = MaxContext = CreateSuccessors(true, p);
FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));
if (MinContext == 0)
goto RESTART_MODEL;
return;
}
*SubAllocator.pText++ = fs.Symbol;
Successor = (PPM_CONTEXT*) SubAllocator.pText;
if (SubAllocator.pText >= SubAllocator.UnitsStart)
goto RESTART_MODEL;
if (fs.GetSuccessor() != 0)
{
if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)
{
PPM_CONTEXT* cs = CreateSuccessors(false, p);
fs.SetSuccessor(SubAllocator.GetOffset(cs));
if (cs == NULL)
goto RESTART_MODEL;
}
if ( !--OrderFall )
{
Successor = GetContext(fs.GetSuccessor());
SubAllocator.pText -= (MaxContext != MinContext);
}
}
else
{
FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));
fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));
}
s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);
for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))
{
if ((ns1 = pc->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);
pc->Stats = SubAllocator.GetOffset(ppp);
if (!ppp)
goto RESTART_MODEL;
}
pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &
(pc->SummFreq <= 8 * ns1)));
}
else
{
p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);
if ( !p )
goto RESTART_MODEL;
*p = pc->oneState();
pc->Stats = SubAllocator.GetOffsetNoCheck(p);
if (p->Freq < MAX_FREQ / 4 - 1)
p->Freq <<= 1;
else
p->Freq = MAX_FREQ - 4;
pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3));
}
cf = 2 * fs.Freq * (pc->SummFreq+6);
sf = s0 + pc->SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf)+(cf >= 4 * sf);
pc->SummFreq += 3;
}
else
{
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
pc->SummFreq = (UInt16)(pc->SummFreq + cf);
}
p = GetState(pc->Stats) + ns1;
p->SetSuccessor(SubAllocator.GetOffset(Successor));
p->Symbol = fs.Symbol;
p->Freq = (Byte)cf;
pc->NumStats = (UInt16)++ns1;
}
MaxContext = MinContext = GetContext(fs.GetSuccessor());
return;
RESTART_MODEL:
RestartModelRare();
EscCount = 0;
PrintCount = 0xFF;
}
void ClearMask()
{
EscCount = 1;
memset(CharMask, 0, sizeof(CharMask));
// if (++PrintCount == 0)
// PrintInfo(DecodedFile,EncodedFile);
}
void update1(PPM_CONTEXT::STATE* p)
{
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p[0].Freq > p[-1].Freq)
{
_PPMD_SWAP(p[0],p[-1]);
FoundState = --p;
if (p->Freq > MAX_FREQ)
rescale();
}
}
void update2(PPM_CONTEXT::STATE* p)
{
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p->Freq > MAX_FREQ)
rescale();
EscCount++;
RunLength = InitRL;
}
SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)
{
SEE2_CONTEXT* psee2c;
if (MinContext->NumStats != 256)
{
psee2c = SEE2Cont[NS2Indx[Diff-1]] +
(Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +
2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +
4 * (NumMasked > Diff) +
HiBitsFlag;
scale = psee2c->getMean();
}
else
{
psee2c = &DummySEE2Cont;
scale = 1;
}
return psee2c;
}
void rescale()
{
int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;
PPM_CONTEXT::STATE* p1, * p;
PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);
for (p = FoundState; p != stats; p--)
_PPMD_SWAP(p[0], p[-1]);
stats->Freq += 4;
MinContext->SummFreq += 4;
EscFreq = MinContext->SummFreq - p->Freq;
Adder = (OrderFall != 0);
p->Freq = (Byte)((p->Freq + Adder) >> 1);
MinContext->SummFreq = p->Freq;
do
{
EscFreq -= (++p)->Freq;
p->Freq = (Byte)((p->Freq + Adder) >> 1);
MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq);
if (p[0].Freq > p[-1].Freq)
{
PPM_CONTEXT::STATE tmp = *(p1 = p);
do
{
p1[0] = p1[-1];
}
while (--p1 != stats && tmp.Freq > p1[-1].Freq);
*p1 = tmp;
}
}
while ( --i );
if (p->Freq == 0)
{
do { i++; } while ((--p)->Freq == 0);
EscFreq += i;
MinContext->NumStats = (UInt16)(MinContext->NumStats - i);
if (MinContext->NumStats == 1)
{
PPM_CONTEXT::STATE tmp = *stats;
do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1);
SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);
*(FoundState = &MinContext->oneState()) = tmp; return;
}
}
EscFreq -= (EscFreq >> 1);
MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq);
int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;
if (n0 != n1)
MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));
FoundState = GetState(MinContext->Stats);
}
void NextContext()
{
PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());
if (!OrderFall && (Byte *)c > SubAllocator.pText)
MinContext = MaxContext = c;
else
{
UpdateModel();
if (EscCount == 0)
ClearMask();
}
}
};
// Tabulated escapes for exponential symbol distribution
const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
}}
#endif

View File

@@ -1,155 +0,0 @@
// PpmdDecode.h
// 2009-05-30 : Igor Pavlov : Public domain
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
#ifndef __COMPRESS_PPMD_DECODE_H
#define __COMPRESS_PPMD_DECODE_H
#include "PpmdContext.h"
namespace NCompress {
namespace NPpmd {
class CRangeDecoderVirt
{
public:
virtual UInt32 GetThreshold(UInt32 total) = 0;
virtual void Decode(UInt32 start, UInt32 size) = 0;
virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) = 0;
};
typedef NRangeCoder::CDecoder CRangeDecoderMy;
class CRangeDecoder:public CRangeDecoderVirt, public CRangeDecoderMy
{
UInt32 GetThreshold(UInt32 total) { return CRangeDecoderMy::GetThreshold(total); }
void Decode(UInt32 start, UInt32 size) { CRangeDecoderMy::Decode(start, size); }
UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { return CRangeDecoderMy::DecodeBit(size0, numTotalBits); }
};
struct CDecodeInfo: public CInfo
{
void DecodeBinSymbol(CRangeDecoderVirt *rangeDecoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0)
{
FoundState = &rs;
rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0));
bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2));
PrevSuccess = 1;
RunLength++;
}
else
{
bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
PrevSuccess = 0;
FoundState = NULL;
}
}
void DecodeSymbol1(CRangeDecoderVirt *rangeDecoder)
{
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats);
int i, count, hiCnt;
if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq))
{
PrevSuccess = (2 * hiCnt > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq);
(FoundState = p)->Freq = (Byte)(hiCnt += 4);
MinContext->SummFreq += 4;
if (hiCnt > MAX_FREQ)
rescale();
return;
}
PrevSuccess = 0;
i = MinContext->NumStats - 1;
while ((hiCnt += (++p)->Freq) <= count)
if (--i == 0)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt); // , MinContext->SummFreq);
CharMask[p->Symbol] = EscCount;
i = (NumMasked = MinContext->NumStats)-1;
FoundState = NULL;
do { CharMask[(--p)->Symbol] = EscCount; } while ( --i );
return;
}
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq);
update1(p);
}
void DecodeSymbol2(CRangeDecoderVirt *rangeDecoder)
{
int count, hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 freqSum;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum);
PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1;
hiCnt = 0;
do
{
do { p++; } while (CharMask[p->Symbol] == EscCount);
hiCnt += p->Freq;
*pps++ = p;
}
while ( --i );
freqSum += hiCnt;
count = rangeDecoder->GetThreshold(freqSum);
p = *(pps = ps);
if (count < hiCnt)
{
hiCnt = 0;
while ((hiCnt += p->Freq) <= count)
p=*++pps;
rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum);
psee2c->update();
update2(p);
}
else
{
rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum);
i = MinContext->NumStats - NumMasked;
pps--;
do { CharMask[(*++pps)->Symbol] = EscCount; } while ( --i );
psee2c->Summ = (UInt16)(psee2c->Summ + freqSum);
NumMasked = MinContext->NumStats;
}
}
int DecodeSymbol(CRangeDecoderVirt *rangeDecoder)
{
if (MinContext->NumStats != 1)
DecodeSymbol1(rangeDecoder);
else
DecodeBinSymbol(rangeDecoder);
while ( !FoundState )
{
do
{
OrderFall++;
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return -1;
}
while (MinContext->NumStats == NumMasked);
DecodeSymbol2(rangeDecoder);
}
Byte symbol = FoundState->Symbol;
NextContext();
return symbol;
}
};
}}
#endif

View File

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

View File

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

View File

@@ -1,142 +0,0 @@
// PpmdEncode.h
// 2009-05-30 : Igor Pavlov : Public domain
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
#ifndef __COMPRESS_PPMD_ENCODE_H
#define __COMPRESS_PPMD_ENCODE_H
#include "PpmdContext.h"
namespace NCompress {
namespace NPpmd {
struct CEncodeInfo: public CInfo
{
void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE& rs = MinContext->oneState();
UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats);
if (rs.Symbol == symbol)
{
FoundState = &rs;
rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0));
rangeEncoder->EncodeBit(bs, TOT_BITS, 0);
bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2));
PrevSuccess = 1;
RunLength++;
}
else
{
rangeEncoder->EncodeBit(bs, TOT_BITS, 1);
bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2));
InitEsc = ExpEscape[bs >> 10];
NumMasked = 1;
CharMask[rs.Symbol] = EscCount;
PrevSuccess = 0;
FoundState = NULL;
}
}
void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats);
if (p->Symbol == symbol)
{
PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq);
RunLength += PrevSuccess;
rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq);
(FoundState = p)->Freq += 4;
MinContext->SummFreq += 4;
if (p->Freq > MAX_FREQ)
rescale();
return;
}
PrevSuccess = 0;
int LoCnt = p->Freq, i = MinContext->NumStats - 1;
while ((++p)->Symbol != symbol)
{
LoCnt += p->Freq;
if (--i == 0)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
CharMask[p->Symbol] = EscCount;
i=(NumMasked = MinContext->NumStats)-1;
FoundState = NULL;
do { CharMask[(--p)->Symbol] = EscCount; } while ( --i );
rangeEncoder->Encode(LoCnt, MinContext->SummFreq - LoCnt, MinContext->SummFreq);
return;
}
}
rangeEncoder->Encode(LoCnt, p->Freq, MinContext->SummFreq);
update1(p);
}
void EncodeSymbol2(int symbol, NRangeCoder::CEncoder *rangeEncoder)
{
int hiCnt, i = MinContext->NumStats - NumMasked;
UInt32 scale;
SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale);
PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1;
hiCnt = 0;
do
{
do { p++; } while (CharMask[p->Symbol] == EscCount);
hiCnt += p->Freq;
if (p->Symbol == symbol)
goto SYMBOL_FOUND;
CharMask[p->Symbol] = EscCount;
}
while ( --i );
rangeEncoder->Encode(hiCnt, scale, hiCnt + scale);
scale += hiCnt;
psee2c->Summ = (UInt16)(psee2c->Summ + scale);
NumMasked = MinContext->NumStats;
return;
SYMBOL_FOUND:
UInt32 highCount = hiCnt;
UInt32 lowCount = highCount - p->Freq;
if ( --i )
{
PPM_CONTEXT::STATE* p1 = p;
do
{
do { p1++; } while (CharMask[p1->Symbol] == EscCount);
hiCnt += p1->Freq;
}
while ( --i );
}
// SubRange.scale += hiCnt;
scale += hiCnt;
rangeEncoder->Encode(lowCount, highCount - lowCount, scale);
psee2c->update();
update2(p);
}
void EncodeSymbol(int c, NRangeCoder::CEncoder *rangeEncoder)
{
if (MinContext->NumStats != 1)
EncodeSymbol1(c, rangeEncoder);
else
EncodeBinSymbol(c, rangeEncoder);
while ( !FoundState )
{
do
{
OrderFall++;
MinContext = GetContext(MinContext->Suffix);
if (MinContext == 0)
return; // S_OK;
}
while (MinContext->NumStats == NumMasked);
EncodeSymbol2(c, rangeEncoder);
}
NextContext();
}
};
}}
#endif

View File

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

View File

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

View File

@@ -1,293 +0,0 @@
// PpmdSubAlloc.h
// 2009-05-30 : Igor Pavlov : Public domain
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
#ifndef __COMPRESS_PPMD_SUB_ALLOC_H
#define __COMPRESS_PPMD_SUB_ALLOC_H
#include "../../../C/Alloc.h"
#include "PpmdType.h"
const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4;
// Extra 1 * UNIT_SIZE for NULL support
// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks()
const UInt32 kExtraSize = (UNIT_SIZE * 3);
const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize;
struct MEM_BLK
{
UInt16 Stamp, NU;
UInt32 Next, Prev;
void InsertAt(Byte *Base, UInt32 p)
{
Prev = p;
MEM_BLK *pp = (MEM_BLK *)(Base + p);
Next = pp->Next;
pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (UInt32)((Byte *)this - Base);
}
void Remove(Byte *Base)
{
((MEM_BLK *)(Base + Prev))->Next = Next;
((MEM_BLK *)(Base + Next))->Prev = Prev;
}
};
class CSubAllocator
{
UInt32 SubAllocatorSize;
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
UInt32 FreeList[N_INDEXES];
Byte *Base;
Byte *HeapStart, *LoUnit, *HiUnit;
public:
Byte *pText, *UnitsStart;
CSubAllocator():
SubAllocatorSize(0),
GlueCount(0),
LoUnit(0),
HiUnit(0),
pText(0),
UnitsStart(0)
{
memset(Indx2Units, 0, sizeof(Indx2Units));
memset(FreeList, 0, sizeof(FreeList));
}
~CSubAllocator()
{
StopSubAllocator();
};
void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); }
void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); }
UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); }
UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); }
MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); }
UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); }
void InsertNode(void* p, int indx)
{
*(UInt32 *)p = FreeList[indx];
FreeList[indx] = GetOffsetNoCheck(p);
}
void* RemoveNode(int indx)
{
UInt32 offset = FreeList[indx];
UInt32 *p = GetNode(offset);
FreeList[indx] = *p;
return (void *)p;
}
UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; }
void SplitBlock(void* pv, int oldIndx, int newIndx)
{
int i, UDiff = Indx2Units[oldIndx] - Indx2Units[newIndx];
Byte* p = ((Byte*)pv) + U2B(Indx2Units[newIndx]);
if (Indx2Units[i = Units2Indx[UDiff-1]] != UDiff)
{
InsertNode(p, --i);
p += U2B(i = Indx2Units[i]);
UDiff -= i;
}
InsertNode(p, Units2Indx[UDiff - 1]);
}
UInt32 GetUsedMemory() const
{
UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText);
for (UInt32 i = 0; i < N_INDEXES; i++)
for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE)
pn = *GetNode(pn);
return (RetVal >> 2);
}
UInt32 GetSubAllocatorSize() const { return SubAllocatorSize; }
void StopSubAllocator()
{
if (SubAllocatorSize != 0)
{
BigFree(Base);
SubAllocatorSize = 0;
Base = 0;
}
}
bool StartSubAllocator(UInt32 size)
{
if (SubAllocatorSize == size)
return true;
StopSubAllocator();
if (size == 0)
Base = 0;
else
{
if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0)
return false;
HeapStart = Base + UNIT_SIZE; // we need such code to support NULL;
}
SubAllocatorSize = size;
return true;
}
void InitSubAllocator()
{
int i, k;
memset(FreeList, 0, sizeof(FreeList));
HiUnit = (pText = HeapStart) + SubAllocatorSize;
UINT Diff = UNIT_SIZE * (SubAllocatorSize / 8 / UNIT_SIZE * 7);
LoUnit = UnitsStart = HiUnit - Diff;
for (i = 0, k=1; i < N1 ; i++, k += 1) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i] = (Byte)k;
for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i] = (Byte)k;
GlueCount = 0;
for (k = i = 0; k < 128; k++)
{
i += (Indx2Units[i] < k+1);
Units2Indx[k] = (Byte)i;
}
}
void GlueFreeBlocks()
{
UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base);
// We need add exta MEM_BLK with Stamp=0
GetBlk(s0)->Stamp = 0;
s0 += UNIT_SIZE;
MEM_BLK *ps0 = GetBlk(s0);
UInt32 p;
int i;
if (LoUnit != HiUnit)
*LoUnit=0;
ps0->Next = ps0->Prev = s0;
for (i = 0; i < N_INDEXES; i++)
while (FreeList[i] != 0)
{
MEM_BLK *pp = (MEM_BLK *)RemoveNode(i);
pp->InsertAt(Base, s0);
pp->Stamp = 0xFFFF;
pp->NU = Indx2Units[i];
}
for (p = ps0->Next; p != s0; p = GetBlk(p)->Next)
{
for (;;)
{
MEM_BLK *pp = GetBlk(p);
MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE);
if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000)
break;
pp1->Remove(Base);
pp->NU = (UInt16)(pp->NU + pp1->NU);
}
}
while ((p = ps0->Next) != s0)
{
MEM_BLK *pp = GetBlk(p);
pp->Remove(Base);
int sz;
for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE)
InsertNode(Base + p, N_INDEXES - 1);
if (Indx2Units[i = Units2Indx[sz-1]] != sz)
{
int k = sz - Indx2Units[--i];
InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1);
}
InsertNode(Base + p, i);
}
}
void* AllocUnitsRare(int indx)
{
if ( !GlueCount )
{
GlueCount = 255;
GlueFreeBlocks();
if (FreeList[indx] != 0)
return RemoveNode(indx);
}
int i = indx;
do
{
if (++i == N_INDEXES)
{
GlueCount--;
i = U2B(Indx2Units[indx]);
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
}
} while (FreeList[i] == 0);
void* RetVal = RemoveNode(i);
SplitBlock(RetVal, i, indx);
return RetVal;
}
void* AllocUnits(int NU)
{
int indx = Units2Indx[NU - 1];
if (FreeList[indx] != 0)
return RemoveNode(indx);
void* RetVal = LoUnit;
LoUnit += U2B(Indx2Units[indx]);
if (LoUnit <= HiUnit)
return RetVal;
LoUnit -= U2B(Indx2Units[indx]);
return AllocUnitsRare(indx);
}
void* AllocContext()
{
if (HiUnit != LoUnit)
return (HiUnit -= UNIT_SIZE);
if (FreeList[0] != 0)
return RemoveNode(0);
return AllocUnitsRare(0);
}
void* ExpandUnits(void* oldPtr, int oldNU)
{
int i0=Units2Indx[oldNU - 1], i1=Units2Indx[oldNU - 1 + 1];
if (i0 == i1)
return oldPtr;
void* ptr = AllocUnits(oldNU + 1);
if (ptr)
{
memcpy(ptr, oldPtr, U2B(oldNU));
InsertNode(oldPtr, i0);
}
return ptr;
}
void* ShrinkUnits(void* oldPtr, int oldNU, int newNU)
{
int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1];
if (i0 == i1)
return oldPtr;
if (FreeList[i1] != 0)
{
void* ptr = RemoveNode(i1);
memcpy(ptr, oldPtr, U2B(newNU));
InsertNode(oldPtr,i0);
return ptr;
}
else
{
SplitBlock(oldPtr, i0, i1);
return oldPtr;
}
}
void FreeUnits(void* ptr, int oldNU)
{
InsertNode(ptr, Units2Indx[oldNU - 1]);
}
};
#endif

View File

@@ -1,14 +0,0 @@
// PpmdType.h
// 2009-05-30 : Igor Pavlov : Public domain
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
#ifndef __COMPRESS_PPMD_TYPE_H
#define __COMPRESS_PPMD_TYPE_H
const int kMaxOrderCompress = 32;
const int MAX_O = 255; /* maximum allowed model order */
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; }
#endif

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

@@ -0,0 +1,223 @@
// PpmdZip.cpp
// 2010-03-11 : Igor Pavlov : Public domain
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../Common/StreamUtils.h"
#include "PpmdZip.h"
namespace NCompress {
namespace NPpmdZip {
static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
static void SzBigFree(void *, void *address) { BigFree(address); }
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
CDecoder::CDecoder(bool fullFileMode):
_fullFileMode(fullFileMode)
{
_ppmd.Stream.In = &_inStream.p;
Ppmd8_Construct(&_ppmd);
}
CDecoder::~CDecoder()
{
Ppmd8_Free(&_ppmd, &g_BigAlloc);
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
if (!_outStream.Alloc())
return E_OUTOFMEMORY;
if (!_inStream.Alloc(1 << 20))
return E_OUTOFMEMORY;
_inStream.Stream = inStream;
_inStream.Init();
{
Byte buf[2];
for (int i = 0; i < 2; i++)
buf[i] = _inStream.ReadByte();
if (_inStream.Extra)
return S_FALSE;
UInt32 val = GetUi16(buf);
UInt32 order = (val & 0xF) + 1;
UInt32 mem = ((val >> 4) & 0xFF) + 1;
UInt32 restor = (val >> 12);
if (order < 2 || restor > 2)
return S_FALSE;
#ifndef PPMD8_FREEZE_SUPPORT
if (restor == 2)
return E_NOTIMPL;
#endif
if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc))
return E_OUTOFMEMORY;
if (!Ppmd8_RangeDec_Init(&_ppmd))
return S_FALSE;
Ppmd8_Init(&_ppmd, order, restor);
}
bool wasFinished = false;
UInt64 processedSize = 0;
while (!outSize || processedSize < *outSize)
{
size_t size = kBufSize;
if (outSize != NULL)
{
const UInt64 rem = *outSize - processedSize;
if (size > rem)
size = (size_t)rem;
}
Byte *data = _outStream.Buf;
size_t i = 0;
int sym = 0;
do
{
sym = Ppmd8_DecodeSymbol(&_ppmd);
if (_inStream.Extra || sym < 0)
break;
data[i] = (Byte)sym;
}
while (++i != size);
processedSize += i;
RINOK(WriteStream(outStream, _outStream.Buf, i));
RINOK(_inStream.Res);
if (_inStream.Extra)
return S_FALSE;
if (sym < 0)
{
if (sym != -1)
return S_FALSE;
wasFinished = true;
break;
}
if (progress)
{
UInt64 inSize = _inStream.GetProcessed();
RINOK(progress->SetRatioInfo(&inSize, &processedSize));
}
}
RINOK(_inStream.Res);
if (_fullFileMode)
{
if (!wasFinished)
{
int res = Ppmd8_DecodeSymbol(&_ppmd);
RINOK(_inStream.Res);
if (_inStream.Extra || res != -1)
return S_FALSE;
}
if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd))
return S_FALSE;
}
return S_OK;
}
// ---------- Encoder ----------
CEncoder::~CEncoder()
{
Ppmd8_Free(&_ppmd, &g_BigAlloc);
}
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch(propIDs[i])
{
case NCoderPropID::kAlgorithm:
if (v > 1)
return E_INVALIDARG;
_restor = v;
break;
case NCoderPropID::kUsedMemorySize:
if (v < (1 << 20) || v > (1 << 28))
return E_INVALIDARG;
_usedMemInMB = v >> 20;
break;
case NCoderPropID::kOrder:
if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER)
return E_INVALIDARG;
_order = (Byte)v;
break;
default:
return E_INVALIDARG;
}
}
return S_OK;
}
CEncoder::CEncoder():
_usedMemInMB(16),
_order(6),
_restor(PPMD8_RESTORE_METHOD_RESTART)
{
_ppmd.Stream.Out = &_outStream.p;
Ppmd8_Construct(&_ppmd);
}
HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
{
if (!_inStream.Alloc())
return E_OUTOFMEMORY;
if (!_outStream.Alloc(1 << 20))
return E_OUTOFMEMORY;
if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc))
return E_OUTOFMEMORY;
_outStream.Stream = outStream;
_outStream.Init();
Ppmd8_RangeEnc_Init(&_ppmd);
Ppmd8_Init(&_ppmd, _order, _restor);
UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12));
_outStream.WriteByte((Byte)(val & 0xFF));
_outStream.WriteByte((Byte)(val >> 8));
RINOK(_outStream.Res);
UInt64 processed = 0;
for (;;)
{
UInt32 size;
RINOK(inStream->Read(_inStream.Buf, kBufSize, &size));
if (size == 0)
{
Ppmd8_EncodeSymbol(&_ppmd, -1);
Ppmd8_RangeEnc_FlushData(&_ppmd);
return _outStream.Flush();
}
for (UInt32 i = 0; i < size; i++)
{
Ppmd8_EncodeSymbol(&_ppmd, _inStream.Buf[i]);
RINOK(_outStream.Res);
}
processed += size;
if (progress != NULL)
{
UInt64 outSize = _outStream.GetProcessed();
RINOK(progress->SetRatioInfo(&processed, &outSize));
}
}
}
}}

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

@@ -0,0 +1,74 @@
// PpmdZip.h
// 2010-03-11 : Igor Pavlov : Public domain
#ifndef __COMPRESS_PPMD_ZIP_H
#define __COMPRESS_PPMD_ZIP_H
#include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "../../../C/Ppmd8.h"
#include "../../Common/MyCom.h"
#include "../Common/CWrappers.h"
#include "../ICoder.h"
namespace NCompress {
namespace NPpmdZip {
static const UInt32 kBufSize = (1 << 20);
struct CBuf
{
Byte *Buf;
CBuf(): Buf(0) {}
~CBuf() { ::MidFree(Buf); }
bool Alloc()
{
if (!Buf)
Buf = (Byte *)::MidAlloc(kBufSize);
return (Buf != 0);
}
};
class CDecoder :
public ICompressCoder,
public CMyUnknownImp
{
CByteInBufWrap _inStream;
CBuf _outStream;
CPpmd8 _ppmd;
bool _fullFileMode;
public:
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
CDecoder(bool fullFileMode);
~CDecoder();
};
class CEncoder :
public ICompressCoder,
public CMyUnknownImp
{
CByteOutBufWrap _outStream;
CBuf _inStream;
CPpmd8 _ppmd;
UInt32 _usedMemInMB;
unsigned _order;
unsigned _restor;
public:
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
CEncoder();
~CEncoder();
};
}}
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -118,6 +118,12 @@ STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message)
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)
{
switch(operationResult)
@@ -145,10 +151,11 @@ STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool
default:
return E_FAIL;
}
char buffer[512];
const AString s = UnicodeStringToMultiByte(m_CurrentFilePath, m_CodePage);
sprintf(buffer, g_StartupInfo.GetMsgString(idMessage), (const char *)s);
if (g_StartupInfo.ShowMessage(buffer) == -1)
UString name = m_CurrentFilePath;
ReduceString(name, 70);
AString s = g_StartupInfo.GetMsgString(idMessage);
s.Replace(" '%s'", "");
if (g_StartupInfo.ShowMessageLines(s + (AString)("\n") + UnicodeStringToMultiByte(name, m_CodePage)) == -1)
return E_ABORT;
}
}

View File

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