mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 08:07:09 -06:00
9.21
This commit is contained in:
committed by
Kornel Lesiński
parent
de4f8c22fe
commit
35596517f2
@@ -122,11 +122,24 @@ DWORD CThreadInfo::ThreadFunc()
|
||||
|
||||
#endif
|
||||
|
||||
CEncoder::CEncoder():
|
||||
NumPasses(1),
|
||||
m_OptimizeNumTables(false),
|
||||
m_BlockSizeMult(kBlockSizeMultMax)
|
||||
void CEncProps::Normalize(int level)
|
||||
{
|
||||
if (level < 0) level = 5;
|
||||
if (level > 9) level = 9;
|
||||
if (NumPasses == (UInt32)(Int32)-1)
|
||||
NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1));
|
||||
if (NumPasses < kBlockSizeMultMin) NumPasses = kBlockSizeMultMin;
|
||||
if (NumPasses > kBlockSizeMultMax) NumPasses = kBlockSizeMultMax;
|
||||
if (BlockSizeMult == (UInt32)(Int32)-1)
|
||||
BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
|
||||
if (BlockSizeMult == 0) BlockSizeMult = 1;
|
||||
if (BlockSizeMult > kNumPassesMax) BlockSizeMult = kNumPassesMax;
|
||||
}
|
||||
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
_props.Normalize(-1);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
ThreadsInfo = 0;
|
||||
m_NumThreadsPrev = 0;
|
||||
@@ -198,7 +211,7 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer)
|
||||
Byte prevByte;
|
||||
if (m_InStream.ReadByte(prevByte))
|
||||
{
|
||||
UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1;
|
||||
UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1;
|
||||
int numReps = 1;
|
||||
buffer[i++] = prevByte;
|
||||
while (i < blockSize) // "- 1" to support RLE
|
||||
@@ -678,7 +691,7 @@ HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)
|
||||
|
||||
m_NumCrcs = 0;
|
||||
|
||||
EncodeBlock2(m_Block, blockSize, Encoder->NumPasses);
|
||||
EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
if (Encoder->MtMode)
|
||||
@@ -738,7 +751,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
ti.Encoder = this;
|
||||
#endif
|
||||
|
||||
ti.m_OptimizeNumTables = m_OptimizeNumTables;
|
||||
ti.m_OptimizeNumTables = _props.DoOptimizeNumTables();
|
||||
|
||||
if (!ti.Alloc())
|
||||
return E_OUTOFMEMORY;
|
||||
@@ -770,7 +783,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
WriteByte(kArSig0);
|
||||
WriteByte(kArSig1);
|
||||
WriteByte(kArSig2);
|
||||
WriteByte((Byte)(kArSig3 + m_BlockSizeMult));
|
||||
WriteByte((Byte)(kArSig3 + _props.BlockSizeMult));
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
@@ -832,62 +845,46 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
for(UInt32 i = 0; i < numProps; i++)
|
||||
int level = -1;
|
||||
CEncProps props;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = props[i];
|
||||
switch(propIDs[i])
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID >= NCoderPropID::kReduceSize)
|
||||
continue;
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = (UInt32)prop.ulVal;
|
||||
switch (propID)
|
||||
{
|
||||
case NCoderPropID::kNumPasses:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 numPasses = prop.ulVal;
|
||||
if (numPasses == 0)
|
||||
numPasses = 1;
|
||||
if (numPasses > kNumPassesMax)
|
||||
numPasses = kNumPassesMax;
|
||||
NumPasses = numPasses;
|
||||
m_OptimizeNumTables = (NumPasses > 1);
|
||||
break;
|
||||
}
|
||||
case NCoderPropID::kDictionarySize:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 dictionary = prop.ulVal / kBlockSizeStep;
|
||||
if (dictionary < kBlockSizeMultMin)
|
||||
dictionary = kBlockSizeMultMin;
|
||||
else if (dictionary > kBlockSizeMultMax)
|
||||
dictionary = kBlockSizeMultMax;
|
||||
m_BlockSizeMult = dictionary;
|
||||
break;
|
||||
}
|
||||
case NCoderPropID::kNumPasses: props.NumPasses = v; break;
|
||||
case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break;
|
||||
case NCoderPropID::kLevel: level = v; break;
|
||||
case NCoderPropID::kNumThreads:
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
NumThreads = prop.ulVal;
|
||||
if (NumThreads < 1)
|
||||
NumThreads = 1;
|
||||
SetNumberOfThreads(v);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
props.Normalize(level);
|
||||
_props = props;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)
|
||||
{
|
||||
const UInt32 kNumThreadsMax = 64;
|
||||
if (numThreads < 1) numThreads = 1;
|
||||
if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;
|
||||
NumThreads = numThreads;
|
||||
if (NumThreads < 1)
|
||||
NumThreads = 1;
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -145,6 +145,20 @@ public:
|
||||
HRESULT EncodeBlock3(UInt32 blockSize);
|
||||
};
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
UInt32 BlockSizeMult;
|
||||
UInt32 NumPasses;
|
||||
|
||||
CEncProps()
|
||||
{
|
||||
BlockSizeMult = (UInt32)(Int32)-1;
|
||||
NumPasses = (UInt32)(Int32)-1;
|
||||
}
|
||||
void Normalize(int level);
|
||||
bool DoOptimizeNumTables() const { return NumPasses > 1; }
|
||||
};
|
||||
|
||||
class CEncoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
@@ -153,17 +167,12 @@ class CEncoder :
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt32 m_BlockSizeMult;
|
||||
bool m_OptimizeNumTables;
|
||||
|
||||
UInt32 m_NumPassesPrev;
|
||||
|
||||
UInt32 m_NumThreadsPrev;
|
||||
public:
|
||||
CInBuffer m_InStream;
|
||||
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
|
||||
CBitmEncoder<COutBuffer> m_OutStream;
|
||||
UInt32 NumPasses;
|
||||
CEncProps _props;
|
||||
CBZip2CombinedCrc CombinedCrc;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace NCompress {
|
||||
namespace NDeflate {
|
||||
namespace NEncoder {
|
||||
|
||||
const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
|
||||
const UInt32 kNumTables = (1 << kNumDivPassesMax);
|
||||
static const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
|
||||
static const UInt32 kNumTables = (1 << kNumDivPassesMax);
|
||||
|
||||
static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
|
||||
static UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
|
||||
static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
|
||||
static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
|
||||
static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
|
||||
static const UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
|
||||
|
||||
static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))
|
||||
static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))
|
||||
@@ -37,9 +37,9 @@ static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize
|
||||
static const int kMaxCodeBitLength = 11;
|
||||
static const int kMaxLevelBitLength = 7;
|
||||
|
||||
static Byte kNoLiteralStatPrice = 11;
|
||||
static Byte kNoLenStatPrice = 11;
|
||||
static Byte kNoPosStatPrice = 6;
|
||||
static const Byte kNoLiteralStatPrice = 11;
|
||||
static const Byte kNoLenStatPrice = 11;
|
||||
static const Byte kNoPosStatPrice = 6;
|
||||
|
||||
static Byte g_LenSlots[kNumLenSymbolsMax];
|
||||
static Byte g_FastPos[1 << 9];
|
||||
@@ -83,21 +83,61 @@ static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
void CEncProps::Normalize()
|
||||
{
|
||||
int level = Level;
|
||||
if (level < 0) level = 5;
|
||||
Level = level;
|
||||
if (algo < 0) algo = (level < 5 ? 0 : 1);
|
||||
if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128));
|
||||
if (btMode < 0) btMode = (algo == 0 ? 0 : 1);
|
||||
if (mc == 0) mc = (16 + (fb >> 1));
|
||||
if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10));
|
||||
}
|
||||
|
||||
void CCoder::SetProps(const CEncProps *props2)
|
||||
{
|
||||
CEncProps props = *props2;
|
||||
props.Normalize();
|
||||
|
||||
m_MatchFinderCycles = props.mc;
|
||||
{
|
||||
unsigned fb = props.fb;
|
||||
if (fb < kMatchMinLen)
|
||||
fb = kMatchMinLen;
|
||||
if (fb > m_MatchMaxLen)
|
||||
fb = m_MatchMaxLen;
|
||||
m_NumFastBytes = fb;
|
||||
}
|
||||
_fastMode = (props.algo == 0);
|
||||
_btMode = (props.btMode != 0);
|
||||
|
||||
m_NumDivPasses = props.numPasses;
|
||||
if (m_NumDivPasses == 0)
|
||||
m_NumDivPasses = 1;
|
||||
if (m_NumDivPasses == 1)
|
||||
m_NumPasses = 1;
|
||||
else if (m_NumDivPasses <= kNumDivPassesMax)
|
||||
m_NumPasses = 2;
|
||||
else
|
||||
{
|
||||
m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
|
||||
m_NumDivPasses = kNumDivPassesMax;
|
||||
}
|
||||
}
|
||||
|
||||
CCoder::CCoder(bool deflate64Mode):
|
||||
m_Deflate64Mode(deflate64Mode),
|
||||
m_NumPasses(1),
|
||||
m_NumDivPasses(1),
|
||||
m_NumFastBytes(32),
|
||||
_fastMode(false),
|
||||
_btMode(true),
|
||||
m_OnePosMatchesMemory(0),
|
||||
m_DistanceMemory(0),
|
||||
m_Created(false),
|
||||
m_Values(0),
|
||||
m_Tables(0),
|
||||
m_MatchFinderCycles(0)
|
||||
// m_SetMfPasses(0)
|
||||
m_Tables(0)
|
||||
{
|
||||
{
|
||||
CEncProps props;
|
||||
SetProps(&props);
|
||||
}
|
||||
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
|
||||
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
|
||||
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
|
||||
@@ -160,56 +200,30 @@ HRESULT CCoder::Create()
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
CEncProps props;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = props[i];
|
||||
switch(propIDs[i])
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID >= NCoderPropID::kReduceSize)
|
||||
continue;
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = (UInt32)prop.ulVal;
|
||||
switch (propID)
|
||||
{
|
||||
case NCoderPropID::kNumPasses:
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
m_NumDivPasses = prop.ulVal;
|
||||
if (m_NumDivPasses == 0)
|
||||
m_NumDivPasses = 1;
|
||||
if (m_NumDivPasses == 1)
|
||||
m_NumPasses = 1;
|
||||
else if (m_NumDivPasses <= kNumDivPassesMax)
|
||||
m_NumPasses = 2;
|
||||
else
|
||||
{
|
||||
m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
|
||||
m_NumDivPasses = kNumDivPassesMax;
|
||||
}
|
||||
break;
|
||||
case NCoderPropID::kNumFastBytes:
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
m_NumFastBytes = prop.ulVal;
|
||||
if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen)
|
||||
return E_INVALIDARG;
|
||||
break;
|
||||
case NCoderPropID::kMatchFinderCycles:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
m_MatchFinderCycles = prop.ulVal;
|
||||
break;
|
||||
}
|
||||
case NCoderPropID::kAlgorithm:
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 maximize = prop.ulVal;
|
||||
_fastMode = (maximize == 0);
|
||||
_btMode = !_fastMode;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
case NCoderPropID::kNumPasses: props.numPasses = v; break;
|
||||
case NCoderPropID::kNumFastBytes: props.fb = v; break;
|
||||
case NCoderPropID::kMatchFinderCycles: props.mc = v; break;
|
||||
case NCoderPropID::kAlgorithm: props.algo = v; break;
|
||||
case NCoderPropID::kLevel: props.Level = v; break;
|
||||
case NCoderPropID::kNumThreads: break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
SetProps(&props);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,25 @@ typedef struct _CSeqInStream
|
||||
CMyComPtr<ISequentialInStream> RealStream;
|
||||
} CSeqInStream;
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
int Level;
|
||||
int algo;
|
||||
int fb;
|
||||
int btMode;
|
||||
UInt32 mc;
|
||||
UInt32 numPasses;
|
||||
|
||||
CEncProps()
|
||||
{
|
||||
Level = -1;
|
||||
mc = 0;
|
||||
algo = fb = btMode = -1;
|
||||
numPasses = (UInt32)(Int32)-1;
|
||||
}
|
||||
void Normalize();
|
||||
};
|
||||
|
||||
class CCoder
|
||||
{
|
||||
CMatchFinder _lzInWindow;
|
||||
@@ -116,7 +135,6 @@ public:
|
||||
COptimal m_Optimum[kNumOpts];
|
||||
|
||||
UInt32 m_MatchFinderCycles;
|
||||
// IMatchFinderSetNumPasses *m_SetMfPasses;
|
||||
|
||||
void GetMatches();
|
||||
void MovePos(UInt32 num);
|
||||
@@ -164,6 +182,7 @@ public:
|
||||
UInt32 GetBlockPrice(int tableIndex, int numDivPasses);
|
||||
void CodeBlock(int tableIndex, bool finalBlock);
|
||||
|
||||
void SetProps(const CEncProps *props2);
|
||||
public:
|
||||
CCoder(bool deflate64Mode = false);
|
||||
~CCoder();
|
||||
|
||||
@@ -62,9 +62,22 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = props[i];
|
||||
if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256)
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID >= NCoderPropID::kReduceSize)
|
||||
continue;
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
delta = prop.ulVal;
|
||||
switch (propID)
|
||||
{
|
||||
case NCoderPropID::kDefaultProp:
|
||||
delta = (UInt32)prop.ulVal;
|
||||
if (delta < 1 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
break;
|
||||
case NCoderPropID::kNumThreads: break;
|
||||
case NCoderPropID::kLevel: break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
_delta = delta;
|
||||
return S_OK;
|
||||
|
||||
@@ -9,7 +9,13 @@
|
||||
#include "../Common/RegisterCodec.h"
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(
|
||||
#ifdef UNDER_CE
|
||||
HANDLE
|
||||
#else
|
||||
HINSTANCE
|
||||
#endif
|
||||
/* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -25,4 +31,3 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
return CreateCoder(clsid, iid, outObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;
|
||||
|
||||
HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
|
||||
{
|
||||
if (propID == NCoderPropID::kMatchFinder)
|
||||
@@ -81,18 +83,29 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
|
||||
return E_INVALIDARG;
|
||||
return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
if (propID > NCoderPropID::kReduceSize)
|
||||
return S_OK;
|
||||
if (propID == NCoderPropID::kReduceSize)
|
||||
{
|
||||
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
|
||||
ep.reduceSize = (UInt32)prop.uhVal.QuadPart;
|
||||
return S_OK;
|
||||
}
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = prop.ulVal;
|
||||
switch (propID)
|
||||
{
|
||||
case NCoderPropID::kNumFastBytes: ep.fb = v; break;
|
||||
case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;
|
||||
case NCoderPropID::kAlgorithm: ep.algo = v; break;
|
||||
case NCoderPropID::kDictionarySize: ep.dictSize = v; break;
|
||||
case NCoderPropID::kPosStateBits: ep.pb = v; break;
|
||||
case NCoderPropID::kLitPosBits: ep.lp = v; break;
|
||||
case NCoderPropID::kLitContextBits: ep.lc = v; break;
|
||||
case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break;
|
||||
SET_PROP_32(kLevel, level)
|
||||
SET_PROP_32(kNumFastBytes, fb)
|
||||
SET_PROP_32(kMatchFinderCycles, mc)
|
||||
SET_PROP_32(kAlgorithm, algo)
|
||||
SET_PROP_32(kDictionarySize, dictSize)
|
||||
SET_PROP_32(kPosStateBits, pb)
|
||||
SET_PROP_32(kLitPosBits, lp)
|
||||
SET_PROP_32(kLitContextBits, lc)
|
||||
SET_PROP_32(kNumThreads, numThreads)
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
return S_OK;
|
||||
@@ -112,8 +125,6 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
{
|
||||
case NCoderPropID::kEndMarker:
|
||||
if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;
|
||||
case NCoderPropID::kNumThreads:
|
||||
if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;
|
||||
default:
|
||||
RINOK(SetLzmaProp(propID, prop, props));
|
||||
}
|
||||
|
||||
@@ -360,6 +360,9 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
if (outSize == NULL)
|
||||
return E_FAIL;
|
||||
// flush calls m_x86ConvertOutStreamSpec->flush, so we must init x86Convert.
|
||||
if (!_keepHistory)
|
||||
m_x86ConvertOutStreamSpec->Init(false, 0);
|
||||
_remainLen = kLenIdNeedInit;
|
||||
m_OutWindowStream.Init(_keepHistory);
|
||||
return S_OK;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// PpmdEncoder.cpp
|
||||
// 2009-03-11 : Igor Pavlov : Public domain
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -19,11 +18,35 @@ static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
|
||||
static void SzBigFree(void *, void *address) { BigFree(address); }
|
||||
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
CEncoder::CEncoder():
|
||||
_inBuf(NULL),
|
||||
_usedMemSize(1 << 24),
|
||||
_order(6)
|
||||
static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };
|
||||
|
||||
void CEncProps::Normalize(int level)
|
||||
{
|
||||
if (level < 0) level = 5;
|
||||
if (level > 9) level = 9;
|
||||
if (MemSize == (UInt32)(Int32)-1)
|
||||
MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19));
|
||||
const unsigned kMult = 16;
|
||||
if (MemSize / kMult > ReduceSize)
|
||||
{
|
||||
for (unsigned i = 16; i <= 31; i++)
|
||||
{
|
||||
UInt32 m = (UInt32)1 << i;
|
||||
if (ReduceSize <= m / kMult)
|
||||
{
|
||||
if (MemSize > m)
|
||||
MemSize = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Order == -1) Order = kOrders[level];
|
||||
}
|
||||
|
||||
CEncoder::CEncoder():
|
||||
_inBuf(NULL)
|
||||
{
|
||||
_props.Normalize(-1);
|
||||
_rangeEnc.Stream = &_outStream.p;
|
||||
Ppmd7_Construct(&_ppmd);
|
||||
}
|
||||
@@ -34,30 +57,44 @@ CEncoder::~CEncoder()
|
||||
Ppmd7_Free(&_ppmd, &g_BigAlloc);
|
||||
}
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
int level = -1;
|
||||
CEncProps props;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = props[i];
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID > NCoderPropID::kReduceSize)
|
||||
continue;
|
||||
if (propID == NCoderPropID::kReduceSize)
|
||||
{
|
||||
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
|
||||
props.ReduceSize = (UInt32)prop.uhVal.QuadPart;
|
||||
continue;
|
||||
}
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = (UInt32)prop.ulVal;
|
||||
switch(propIDs[i])
|
||||
switch (propID)
|
||||
{
|
||||
case NCoderPropID::kUsedMemorySize:
|
||||
if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)
|
||||
return E_INVALIDARG;
|
||||
_usedMemSize = v;
|
||||
props.MemSize = v;
|
||||
break;
|
||||
case NCoderPropID::kOrder:
|
||||
if (v < 2 || v > 32)
|
||||
return E_INVALIDARG;
|
||||
_order = (Byte)v;
|
||||
props.Order = (Byte)v;
|
||||
break;
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
case NCoderPropID::kNumThreads: break;
|
||||
case NCoderPropID::kLevel: level = (int)v; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
props.Normalize(level);
|
||||
_props = props;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -65,8 +102,8 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
const UInt32 kPropSize = 5;
|
||||
Byte props[kPropSize];
|
||||
props[0] = _order;
|
||||
SetUi32(props + 1, _usedMemSize);
|
||||
props[0] = (Byte)_props.Order;
|
||||
SetUi32(props + 1, _props.MemSize);
|
||||
return WriteStream(outStream, props, kPropSize);
|
||||
}
|
||||
|
||||
@@ -81,14 +118,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
|
||||
}
|
||||
if (!_outStream.Alloc(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))
|
||||
if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
_outStream.Stream = outStream;
|
||||
_outStream.Init();
|
||||
|
||||
Ppmd7z_RangeEnc_Init(&_rangeEnc);
|
||||
Ppmd7_Init(&_ppmd, _order);
|
||||
Ppmd7_Init(&_ppmd, _props.Order);
|
||||
|
||||
UInt64 processed = 0;
|
||||
for (;;)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// PpmdEncoder.h
|
||||
// 2009-03-11 : Igor Pavlov : Public domain
|
||||
|
||||
#ifndef __COMPRESS_PPMD_ENCODER_H
|
||||
#define __COMPRESS_PPMD_ENCODER_H
|
||||
@@ -15,6 +14,21 @@
|
||||
namespace NCompress {
|
||||
namespace NPpmd {
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
UInt32 MemSize;
|
||||
UInt32 ReduceSize;
|
||||
int Order;
|
||||
|
||||
CEncProps()
|
||||
{
|
||||
MemSize = (UInt32)(Int32)-1;
|
||||
ReduceSize = (UInt32)(Int32)-1;
|
||||
Order = -1;
|
||||
}
|
||||
void Normalize(int level);
|
||||
};
|
||||
|
||||
class CEncoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
@@ -25,20 +39,15 @@ class CEncoder :
|
||||
CByteOutBufWrap _outStream;
|
||||
CPpmd7z_RangeEnc _rangeEnc;
|
||||
CPpmd7 _ppmd;
|
||||
|
||||
UInt32 _usedMemSize;
|
||||
Byte _order;
|
||||
|
||||
CEncProps _props;
|
||||
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();
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// PpmdZip.cpp
|
||||
// 2010-03-24 : Igor Pavlov : Public domain
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../Common/RegisterCodec.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "PpmdZip.h"
|
||||
@@ -128,69 +128,109 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
|
||||
// ---------- Encoder ----------
|
||||
|
||||
void CEncProps::Normalize(int level)
|
||||
{
|
||||
if (level < 0) level = 5;
|
||||
if (level == 0) level = 1;
|
||||
if (level > 9) level = 9;
|
||||
if (MemSizeMB == (UInt32)(Int32)-1)
|
||||
MemSizeMB = (1 << ((level > 8 ? 8 : level) - 1));
|
||||
const unsigned kMult = 16;
|
||||
if ((MemSizeMB << 20) / kMult > ReduceSize)
|
||||
{
|
||||
for (UInt32 m = (1 << 20); m <= (1 << 28); m <<= 1)
|
||||
{
|
||||
if (ReduceSize <= m / kMult)
|
||||
{
|
||||
m >>= 20;
|
||||
if (MemSizeMB > m)
|
||||
MemSizeMB = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Order == -1) Order = 3 + level;
|
||||
if (Restor == -1)
|
||||
Restor = level < 7 ?
|
||||
PPMD8_RESTORE_METHOD_RESTART :
|
||||
PPMD8_RESTORE_METHOD_CUT_OFF;
|
||||
}
|
||||
|
||||
CEncoder::~CEncoder()
|
||||
{
|
||||
Ppmd8_Free(&_ppmd, &g_BigAlloc);
|
||||
}
|
||||
|
||||
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
int level = -1;
|
||||
CEncProps props;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = props[i];
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID > NCoderPropID::kReduceSize)
|
||||
continue;
|
||||
if (propID == NCoderPropID::kReduceSize)
|
||||
{
|
||||
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
|
||||
props.ReduceSize = (UInt32)prop.uhVal.QuadPart;
|
||||
continue;
|
||||
}
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = (UInt32)prop.ulVal;
|
||||
switch(propIDs[i])
|
||||
switch (propID)
|
||||
{
|
||||
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;
|
||||
props.MemSizeMB = v >> 20;
|
||||
break;
|
||||
case NCoderPropID::kOrder:
|
||||
if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER)
|
||||
return E_INVALIDARG;
|
||||
_order = (Byte)v;
|
||||
props.Order = (Byte)v;
|
||||
break;
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
case NCoderPropID::kNumThreads: break;
|
||||
case NCoderPropID::kLevel: level = (int)v; break;
|
||||
case NCoderPropID::kAlgorithm:
|
||||
if (v > 1)
|
||||
return E_INVALIDARG;
|
||||
props.Restor = v;
|
||||
break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
props.Normalize(level);
|
||||
_props = props;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CEncoder::CEncoder():
|
||||
_usedMemInMB(16),
|
||||
_order(6),
|
||||
_restor(PPMD8_RESTORE_METHOD_RESTART)
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
_props.Normalize(-1);
|
||||
_ppmd.Stream.Out = &_outStream.p;
|
||||
Ppmd8_Construct(&_ppmd);
|
||||
}
|
||||
|
||||
HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
STDMETHODIMP 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))
|
||||
if (!Ppmd8_Alloc(&_ppmd, _props.MemSizeMB << 20, &g_BigAlloc))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
_outStream.Stream = outStream;
|
||||
_outStream.Init();
|
||||
|
||||
Ppmd8_RangeEnc_Init(&_ppmd);
|
||||
Ppmd8_Init(&_ppmd, _order, _restor);
|
||||
Ppmd8_Init(&_ppmd, _props.Order, _props.Restor);
|
||||
|
||||
UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12));
|
||||
UInt32 val = (UInt32)((_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + (_props.Restor << 12));
|
||||
_outStream.WriteByte((Byte)(val & 0xFF));
|
||||
_outStream.WriteByte((Byte)(val >> 8));
|
||||
RINOK(_outStream.Res);
|
||||
@@ -220,4 +260,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void *CreateCodec() { return (void *)(ICompressCoder *)(new CDecoder(false)); }
|
||||
static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new CEncoder); }
|
||||
|
||||
static CCodecInfo g_CodecInfo =
|
||||
{ CreateCodec, CreateCodecOut, 0x040162, L"PPMdZIP", 1, false };
|
||||
|
||||
REGISTER_CODEC(PPMdZIP)
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// PpmdZip.h
|
||||
// 2010-03-11 : Igor Pavlov : Public domain
|
||||
|
||||
#ifndef __COMPRESS_PPMD_ZIP_H
|
||||
#define __COMPRESS_PPMD_ZIP_H
|
||||
@@ -48,21 +47,37 @@ public:
|
||||
~CDecoder();
|
||||
};
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
UInt32 MemSizeMB;
|
||||
UInt32 ReduceSize;
|
||||
int Order;
|
||||
int Restor;
|
||||
|
||||
CEncProps()
|
||||
{
|
||||
MemSizeMB = (UInt32)(Int32)-1;
|
||||
ReduceSize = (UInt32)(Int32)-1;
|
||||
Order = -1;
|
||||
Restor = -1;
|
||||
}
|
||||
void Normalize(int level);
|
||||
};
|
||||
|
||||
class CEncoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteOutBufWrap _outStream;
|
||||
CBuf _inStream;
|
||||
CPpmd8 _ppmd;
|
||||
UInt32 _usedMemInMB;
|
||||
unsigned _order;
|
||||
unsigned _restor;
|
||||
CEncProps _props;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
CEncoder();
|
||||
~CEncoder();
|
||||
};
|
||||
|
||||
@@ -33,14 +33,6 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize)
|
||||
{
|
||||
if (_remainLen == kLenIdNeedInit)
|
||||
{
|
||||
if (!_keepHistory)
|
||||
{
|
||||
if (!_outWindowStream.Create((UInt32)1 << _numDictBits))
|
||||
return E_OUTOFMEMORY;
|
||||
Init();
|
||||
}
|
||||
if (!_rangeDecoder.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
_rangeDecoder.Init();
|
||||
_remainLen = 0;
|
||||
}
|
||||
@@ -169,6 +161,20 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
return E_FAIL;
|
||||
_remainLen = kLenIdNeedInit;
|
||||
_outWindowStream.Init(_keepHistory);
|
||||
if (!_keepHistory)
|
||||
Init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::SetParams(int numDictBits)
|
||||
{
|
||||
if (numDictBits > 21)
|
||||
return E_INVALIDARG;
|
||||
_numDictBits = numDictBits;
|
||||
if (!_outWindowStream.Create((UInt32)1 << _numDictBits))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_rangeDecoder.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
|
||||
void SetParams(int numDictBits) { _numDictBits = numDictBits; }
|
||||
HRESULT SetParams(int numDictBits);
|
||||
void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }
|
||||
CDecoder(): _keepHistory(false) {}
|
||||
virtual ~CDecoder() {}
|
||||
|
||||
Reference in New Issue
Block a user