aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Compress/PpmdEncoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Compress/PpmdEncoder.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Compress/PpmdEncoder.cpp67
1 files changed, 52 insertions, 15 deletions
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
index 3a8df78..e232077 100755..100644
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -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 };
+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),
- _usedMemSize(1 << 24),
- _order(6)
+ _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 (;;)