diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2011-04-11 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:05 +0300 |
commit | 35596517f203f1c4970413b3b5b2e216b849e462 (patch) | |
tree | 93240df3eb4ddbd8eebbe6a5fc65e93f2ccb6495 /CPP/7zip/Compress | |
parent | de4f8c22fe4b9e59b60495b84db2e81de50999a9 (diff) |
9.219.21
Diffstat (limited to 'CPP/7zip/Compress')
-rwxr-xr-x | CPP/7zip/Compress/BZip2Encoder.cpp | 89 | ||||
-rwxr-xr-x | CPP/7zip/Compress/BZip2Encoder.h | 21 | ||||
-rwxr-xr-x | CPP/7zip/Compress/DeflateEncoder.cpp | 134 | ||||
-rwxr-xr-x | CPP/7zip/Compress/DeflateEncoder.h | 21 | ||||
-rwxr-xr-x | CPP/7zip/Compress/DeltaFilter.cpp | 17 | ||||
-rwxr-xr-x | CPP/7zip/Compress/DllExports2.cpp | 9 | ||||
-rwxr-xr-x | CPP/7zip/Compress/LzmaEncoder.cpp | 29 | ||||
-rwxr-xr-x | CPP/7zip/Compress/LzxDecoder.cpp | 3 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdEncoder.cpp | 67 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdEncoder.h | 23 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdZip.cpp | 92 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PpmdZip.h | 27 | ||||
-rwxr-xr-x | CPP/7zip/Compress/QuantumDecoder.cpp | 22 | ||||
-rwxr-xr-x | CPP/7zip/Compress/QuantumDecoder.h | 2 |
14 files changed, 372 insertions, 184 deletions
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index eaa10855..6dafc45f 100755 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -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 diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index a863172f..5aa8a786 100755 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -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 diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 35a81cae..813b6de4 100755 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -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; } diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index 71c39e4e..f25d802e 100755 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -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(); diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp index 2e421acf..d8378a60 100755 --- a/CPP/7zip/Compress/DeltaFilter.cpp +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -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; diff --git a/CPP/7zip/Compress/DllExports2.cpp b/CPP/7zip/Compress/DllExports2.cpp index 836f3fa4..286ef08b 100755 --- a/CPP/7zip/Compress/DllExports2.cpp +++ b/CPP/7zip/Compress/DllExports2.cpp @@ -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); } - diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 9bdedaeb..80e12f18 100755 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -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)); } diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp index d1027f1f..924229e9 100755 --- a/CPP/7zip/Compress/LzxDecoder.cpp +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -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; diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index d823ffe8..5bf83529 100755 --- 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 (;;) diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index ed8b3713..fb74cf57 100755 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -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(); }; diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp index e83d979c..036f3c72 100755 --- a/CPP/7zip/Compress/PpmdZip.cpp +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -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; + 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; + 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) +*/ + }} diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h index c2288b5a..e15a060d 100755 --- a/CPP/7zip/Compress/PpmdZip.h +++ b/CPP/7zip/Compress/PpmdZip.h @@ -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(); }; diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp index 501bd0e1..63da32cc 100755 --- a/CPP/7zip/Compress/QuantumDecoder.cpp +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -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; } diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h index e9ab023b..a5f78358 100755 --- a/CPP/7zip/Compress/QuantumDecoder.h +++ b/CPP/7zip/Compress/QuantumDecoder.h @@ -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() {} |