diff --git a/Source/7zip/7zip/Common/InBuffer.cpp b/Source/7zip/7zip/Common/InBuffer.cpp index a7020df0..02f2adfa 100644 --- a/Source/7zip/7zip/Common/InBuffer.cpp +++ b/Source/7zip/7zip/Common/InBuffer.cpp @@ -7,11 +7,11 @@ #include "../../Common/Alloc.h" CInBuffer::CInBuffer(): - _bufferBase(0), - _bufferSize(0), _buffer(0), _bufferLimit(0), - _stream(0) + _bufferBase(0), + _stream(0), + _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) @@ -23,19 +23,23 @@ bool CInBuffer::Create(UInt32 bufferSize) return true; Free(); _bufferSize = bufferSize; - _bufferBase = (Byte *)::BigAlloc(bufferSize); + _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { - BigFree(_bufferBase); + ::MidFree(_bufferBase); _bufferBase = 0; } -void CInBuffer::Init(ISequentialInStream *stream) +void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; +} + +void CInBuffer::Init() +{ _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; @@ -55,7 +59,7 @@ bool CInBuffer::ReadBlock() return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; - HRESULT result = _stream->ReadPart(_bufferBase, _bufferSize, &numProcessedBytes); + HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else @@ -67,3 +71,10 @@ bool CInBuffer::ReadBlock() _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } + +Byte CInBuffer::ReadBlock2() +{ + if(!ReadBlock()) + return 0xFF; + return *_buffer++; +} diff --git a/Source/7zip/7zip/Common/InBuffer.h b/Source/7zip/7zip/Common/InBuffer.h index 3a1c8318..057caa16 100644 --- a/Source/7zip/7zip/Common/InBuffer.h +++ b/Source/7zip/7zip/Common/InBuffer.h @@ -4,6 +4,7 @@ #define __INBUFFER_H #include "../IStream.h" +#include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS class CInBufferException @@ -16,15 +17,16 @@ public: class CInBuffer { - UInt64 _processedSize; - Byte *_bufferBase; - UInt32 _bufferSize; Byte *_buffer; Byte *_bufferLimit; - ISequentialInStream *_stream; + Byte *_bufferBase; + CMyComPtr _stream; + UInt64 _processedSize; + UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); + Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS @@ -37,8 +39,9 @@ public: bool Create(UInt32 bufferSize); void Free(); - void Init(ISequentialInStream *stream); - // void ReleaseStream() { _stream.Release(); } + void SetStream(ISequentialInStream *stream); + void Init(); + void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { @@ -51,8 +54,7 @@ public: Byte ReadByte() { if(_buffer >= _bufferLimit) - if(!ReadBlock()) - return 0xFF; + return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) diff --git a/Source/7zip/7zip/Common/OutBuffer.cpp b/Source/7zip/7zip/Common/OutBuffer.cpp index d95cce03..a73fa7c5 100644 --- a/Source/7zip/7zip/Common/OutBuffer.cpp +++ b/Source/7zip/7zip/Common/OutBuffer.cpp @@ -15,48 +15,98 @@ bool COutBuffer::Create(UInt32 bufferSize) return true; Free(); _bufferSize = bufferSize; - _buffer = (Byte *)::BigAlloc(bufferSize); + _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { - BigFree(_buffer); + ::MidFree(_buffer); _buffer = 0; } -void COutBuffer::Init(ISequentialOutStream *stream) +void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; - _processedSize = 0; +} + +void COutBuffer::Init() +{ + _streamPos = 0; + _limitPos = _bufferSize; _pos = 0; + _processedSize = 0; + _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } -HRESULT COutBuffer::Flush() -{ - if (_pos == 0) - return S_OK; - UInt32 processedSize; - HRESULT result = _stream->Write(_buffer, _pos, &processedSize); - if (result != S_OK) - return result; - if (_pos != processedSize) - return E_FAIL; - _processedSize += processedSize; - _pos = 0; - return S_OK; +UInt64 COutBuffer::GetProcessedSize() const +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufferSize; + return res; } -void COutBuffer::WriteBlock() + +HRESULT COutBuffer::FlushPart() +{ + // _streamPos < _bufferSize + UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + result = ErrorCode; + #endif + if (_buffer2 != 0) + { + memmove(_buffer2, _buffer + _streamPos, size); + _buffer2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode == S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buffer + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + if (_streamPos == _bufferSize) + _streamPos = 0; + if (_pos == _bufferSize) + { + _overDict = true; + _pos = 0; + } + _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) - return; + return ErrorCode; #endif - HRESULT result = Flush(); + + while(_streamPos != _pos) + { + HRESULT result = FlushPart(); + if (result != S_OK) + return result; + } + return S_OK; +} + +void COutBuffer::FlushWithCheck() +{ + HRESULT result = FlushPart(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else diff --git a/Source/7zip/7zip/Common/OutBuffer.h b/Source/7zip/7zip/Common/OutBuffer.h index 9a377e2e..0ce54e21 100644 --- a/Source/7zip/7zip/Common/OutBuffer.h +++ b/Source/7zip/7zip/Common/OutBuffer.h @@ -4,6 +4,7 @@ #define __OUTBUFFER_H #include "../IStream.h" +#include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS struct COutBufferException @@ -15,55 +16,49 @@ struct COutBufferException class COutBuffer { +protected: Byte *_buffer; UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; UInt32 _bufferSize; - ISequentialOutStream *_stream; + CMyComPtr _stream; UInt64 _processedSize; + Byte *_buffer2; + bool _overDict; - void WriteBlock(); + HRESULT FlushPart(); + void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif - COutBuffer(): _buffer(0), _pos(0), _stream(0) {} + COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); - void Init(ISequentialOutStream *stream); + void SetMemStream(Byte *buffer) { _buffer2 = buffer; } + void SetStream(ISequentialOutStream *stream); + void Init(); HRESULT Flush(); - // void ReleaseStream(); { _stream.Release(); } - - /* - void *GetBuffer(UInt32 &sizeAvail) - { - sizeAvail = _bufferSize - _pos; - return _buffer + _pos; - } - void MovePos(UInt32 num) - { - _pos += num; - if(_pos >= _bufferSize) - WriteBlock(); - } - */ + void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; - if(_pos >= _bufferSize) - WriteBlock(); + if(_pos == _limitPos) + FlushWithCheck(); } - void WriteBytes(const void *data, UInt32 size) + void WriteBytes(const void *data, size_t size) { - for (UInt32 i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } - UInt64 GetProcessedSize() const { return _processedSize + _pos; } + UInt64 GetProcessedSize() const; }; #endif diff --git a/Source/7zip/7zip/Common/StdAfx.h b/Source/7zip/7zip/Common/StdAfx.h index b0290866..2736abc0 100644 --- a/Source/7zip/7zip/Common/StdAfx.h +++ b/Source/7zip/7zip/Common/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../Platform.h" +#include "../../Common/MyWindows.h" #endif diff --git a/Source/7zip/7zip/Common/StreamUtils.cpp b/Source/7zip/7zip/Common/StreamUtils.cpp new file mode 100644 index 00000000..a5d9ac0e --- /dev/null +++ b/Source/7zip/7zip/Common/StreamUtils.cpp @@ -0,0 +1,44 @@ +// StreamUtils.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" +#include "StreamUtils.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Read(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (Byte *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return S_OK; + } + return S_OK; +} + +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Write(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (const void *)((const Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + break; + } + return S_OK; +} diff --git a/Source/7zip/7zip/Common/StreamUtils.h b/Source/7zip/7zip/Common/StreamUtils.h new file mode 100644 index 00000000..59f88733 --- /dev/null +++ b/Source/7zip/7zip/Common/StreamUtils.h @@ -0,0 +1,11 @@ +// StreamUtils.h + +#ifndef __STREAMUTILS_H +#define __STREAMUTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h index 429ae609..b3b3f13a 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h @@ -1,92 +1,54 @@ // BinTree.h -// #ifndef __BINTREE_H -// #define __BINTREE_H - #include "../LZInWindow.h" +#include "../IMatchFinder.h" namespace BT_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; -// #define HASH_ARRAY_2 - -// #ifdef HASH_ARRAY_2 - -// #define HASH_ARRAY_3 - -// #else - -// #define HASH_ZIP - -// #endif - -struct CPair -{ - CIndex Left; - CIndex Right; -}; - -/* -const int kNumBundleBits = 2; -const UInt32 kNumPairsInBundle = 1 << kNumBundleBits; -const UInt32 kBundleMask = kNumPairsInBundle - 1; -const UInt32 kNumBundleBytes = kNumPairsInBundle * sizeof(CPair); - -struct CBundle -{ - CPair Pairs[kNumPairsInBundle]; - Byte Bytes[kNumBundleBytes]; -}; -*/ - -class CInTree: public CLZInWindow +class CMatchFinder: + public IMatchFinder, + public CLZInWindow, + public CMyUnknownImp, + public IMatchFinderSetNumPasses { UInt32 _cyclicBufferPos; - UInt32 _cyclicBufferSize; - UInt32 _historySize; + UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; - CIndex *_hash; - - #ifdef HASH_ARRAY_2 - CIndex *_hash2; - #ifdef HASH_ARRAY_3 - CIndex *_hash3; - #endif - #endif - - // CBundle *_son; - CPair *_son; - + CIndex *_son; + UInt32 _hashMask; UInt32 _cutValue; + UInt32 _hashSizeSum; - void NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue); void Normalize(); + void FreeThisClassMemory(); void FreeMemory(); + MY_UNKNOWN_IMP + + STDMETHOD(SetStream)(ISequentialInStream *inStream); + STDMETHOD_(void, ReleaseStream)(); + STDMETHOD(Init)(); + HRESULT MovePos(); + STDMETHOD_(Byte, GetIndexByte)(Int32 index); + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); + STDMETHOD_(UInt32, GetNumAvailableBytes)(); + STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes); + STDMETHOD_(void, ChangeBufferPos)(); + + STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + STDMETHOD(GetMatches)(UInt32 *distances); + STDMETHOD(Skip)(UInt32 num); + public: - CInTree(); - ~CInTree(); - HRESULT Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, - UInt32 keepAddBufferAfter, UInt32 sizeReserv = (1<<17)); - HRESULT Init(ISequentialInStream *stream); - void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } - UInt32 GetLongestMatch(UInt32 *distances); - void DummyLongestMatch(); - HRESULT MovePos() - { - _cyclicBufferPos++; - if (_cyclicBufferPos >= _cyclicBufferSize) - _cyclicBufferPos = 0; - RINOK(CLZInWindow::MovePos()); - if (_pos == kMaxValForNormalize) - Normalize(); - return S_OK; - } + CMatchFinder(); + virtual ~CMatchFinder(); + virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; } }; } - -// #endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h index 47ef302b..74ca8d9d 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h @@ -1,16 +1,12 @@ // BinTree2.h -#ifndef __BINTREE2__H -#define __BINTREE2__H +#ifndef __BINTREE2_H +#define __BINTREE2_H -#undef BT_CLSID -#define BT_CLSID CLSID_CMatchFinderBT2 - -#undef BT_NAMESPACE #define BT_NAMESPACE NBT2 -#include "BinTreeMF.h" -#include "BinTreeMFMain.h" +#include "BinTreeMain.h" + +#undef BT_NAMESPACE #endif - diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h index dcc3f475..76bd9ddd 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h @@ -1,20 +1,16 @@ // BinTree3.h -#ifndef __BINTREE3__H -#define __BINTREE3__H +#ifndef __BINTREE3_H +#define __BINTREE3_H -#undef BT_CLSID -#define BT_CLSID CLSID_CMatchFinderBT3 - -#undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 -#include "BinTreeMF.h" -#include "BinTreeMFMain.h" +#include "BinTreeMain.h" #undef HASH_ARRAY_2 -#endif +#undef BT_NAMESPACE +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h index 3a2d962a..d2c092b4 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h @@ -1,17 +1,16 @@ // BinTree3Z.h -#ifndef __BINTREE3Z__H -#define __BINTREE3Z__H +#ifndef __BINTREE3Z_H +#define __BINTREE3Z_H -#undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP -#include "BinTree.h" -// #include "BinTreeMain.h" +#include "BinTreeMain.h" #undef HASH_ZIP -#endif +#undef BT_NAMESPACE +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h index 1a41d1d7..08e2d1ce 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h @@ -1,22 +1,18 @@ // BinTree4.h -#ifndef __BINTREE4__H -#define __BINTREE4__H +#ifndef __BINTREE4_H +#define __BINTREE4_H -#undef BT_CLSID -#define BT_CLSID CLSID_CMatchFinderBT4 - -#undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 -#include "BinTreeMF.h" -#include "BinTreeMFMain.h" +#include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 -#endif +#undef BT_NAMESPACE +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h index e6265a95..7a6f621a 100644 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h @@ -4,163 +4,187 @@ #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" +#include "BinTree.h" + +// #include +// It's for prefetch +// But prefetch doesn't give big gain in K8. + namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; + #define kNumHashDirectBytes 0 #ifdef HASH_ARRAY_3 - static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; - static const UInt32 kHash3Size = 1 << 18; - #ifdef HASH_BIG - static const UInt32 kHashSize = 1 << 23; - #else - static const UInt32 kHashSize = 1 << 20; - #endif + static const UInt32 kHash3Size = 1 << 16; #else - static const UInt32 kNumHashDirectBytes = 3; static const UInt32 kNumHashBytes = 3; - static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif + static const UInt32 kHashSize = 0; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; #else #ifdef HASH_ZIP - static const UInt32 kNumHashDirectBytes = 0; + #define kNumHashDirectBytes 0 static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; #else - static const UInt32 kNumHashDirectBytes = 2; + #define kNumHashDirectBytes 2 static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); + static const UInt32 kMinMatchCheck = kNumHashBytes + 1; + static const UInt32 kStartMaxLen = 1; #endif #endif +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 +static const UInt32 kHash3Offset = kHash2Size; +#endif +#endif -CInTree::CInTree(): - _hash(0), - #ifdef HASH_ARRAY_2 - _hash2(0), - #ifdef HASH_ARRAY_3 - _hash3(0), - #endif - #endif - _son(0), - _cutValue(0xFF) +static const UInt32 kFixHashSize = 0 + #ifdef HASH_ARRAY_2 + + kHash2Size + #ifdef HASH_ARRAY_3 + + kHash3Size + #endif + #endif + ; + +CMatchFinder::CMatchFinder(): + _hash(0) { } -void CInTree::FreeMemory() +void CMatchFinder::FreeThisClassMemory() { - BigFree(_son); - _son = 0; BigFree(_hash); _hash = 0; +} + +void CMatchFinder::FreeMemory() +{ + FreeThisClassMemory(); CLZInWindow::Free(); } -CInTree::~CInTree() +CMatchFinder::~CMatchFinder() { FreeMemory(); } -HRESULT CInTree::Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore, - UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 sizeReserv) +STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { - FreeMemory(); - if (!CLZInWindow::Create(sizeHistory + keepAddBufferBefore, - matchMaxLen + keepAddBufferAfter, sizeReserv)) - return E_OUTOFMEMORY; - - if (_blockSize + 256 > kMaxValForNormalize) + if (historySize > kMaxValForNormalize - 256) + { + FreeMemory(); return E_INVALIDARG; - - _historySize = sizeHistory; - _matchMaxLen = matchMaxLen; - - _cyclicBufferSize = sizeHistory + 1; - - - UInt32 size = kHashSize; - #ifdef HASH_ARRAY_2 - size += kHash2Size; - #ifdef HASH_ARRAY_3 - size += kHash3Size; - #endif - #endif - - _son = (CPair *)BigAlloc((_cyclicBufferSize + 1) * sizeof(CPair)); - if (_son == 0) - { - FreeMemory(); - return E_OUTOFMEMORY; } - - // UInt32 numBundles = (_cyclicBufferSize + kNumPairsInBundle) >> kNumBundleBits; - // _son = (CBundle *)::VirtualAlloc(0, numBundles * sizeof(CBundle), MEM_COMMIT, PAGE_READWRITE); - _hash = (CIndex *)BigAlloc((size + 1) * sizeof(CIndex)); - if (_hash == 0) + _cutValue = + #ifdef _HASH_CHAIN + 8 + (matchMaxLen >> 2); + #else + 16 + (matchMaxLen >> 1); + #endif + UInt32 sizeReserv = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + if (CLZInWindow::Create(historySize + keepAddBufferBefore, + matchMaxLen + keepAddBufferAfter, sizeReserv)) { - FreeMemory(); - return E_OUTOFMEMORY; + _matchMaxLen = matchMaxLen; + UInt32 newCyclicBufferSize = historySize + 1; + if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) + return S_OK; + FreeThisClassMemory(); + _cyclicBufferSize = newCyclicBufferSize; // don't change it + + UInt32 hs = kHashSize; + + #ifdef HASH_ARRAY_2 + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + { + #ifdef HASH_ARRAY_3 + hs >>= 1; + #else + hs = (1 << 24) - 1; + #endif + } + _hashMask = hs; + hs++; + #endif + _hashSizeSum = hs + kFixHashSize; + UInt32 numItems = _hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ; + size_t sizeInBytes = (size_t)numItems * sizeof(CIndex); + if (sizeInBytes / sizeof(CIndex) != numItems) + return E_OUTOFMEMORY; + _hash = (CIndex *)BigAlloc(sizeInBytes); + _son = _hash + _hashSizeSum; + if (_hash != 0) + return S_OK; } - - // _hash = &m_RightBase[_blockSize]; - #ifdef HASH_ARRAY_2 - _hash2 = &_hash[kHashSize]; - #ifdef HASH_ARRAY_3 - _hash3 = &_hash2[kHash2Size]; - #endif - #endif - return S_OK; + FreeMemory(); + return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; -HRESULT CInTree::Init(ISequentialInStream *stream) +STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream) { - RINOK(CLZInWindow::Init(stream)); - UInt32 i; - for(i = 0; i < kHashSize; i++) + CLZInWindow::SetStream(stream); + return S_OK; +} + +STDMETHODIMP CMatchFinder::Init() +{ + RINOK(CLZInWindow::Init()); + for(UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; - - #ifdef HASH_ARRAY_2 - for(i = 0; i < kHash2Size; i++) - _hash2[i] = kEmptyHashValue; - #ifdef HASH_ARRAY_3 - for(i = 0; i < kHash3Size; i++) - _hash3[i] = kEmptyHashValue; - #endif - #endif - _cyclicBufferPos = 0; - ReduceOffsets(-1); return S_OK; } +STDMETHODIMP_(void) CMatchFinder::ReleaseStream() +{ + // ReleaseStream(); +} #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 -inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) -{ - UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; - hash2Value = temp & (kHash2Size - 1); - hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); - return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & - (kHashSize - 1); -} + +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; } + #else // no HASH_ARRAY_3 -inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) -{ - hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1); - return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2]; -} +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { - return ((UInt32(pointer[0]) << 8) ^ - CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); + return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) @@ -170,7 +194,7 @@ inline UInt32 Hash(const Byte *pointer) #endif // HASH_ZIP #endif // HASH_ARRAY_2 -UInt32 CInTree::GetLongestMatch(UInt32 *distances) +STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) @@ -178,346 +202,288 @@ UInt32 CInTree::GetLongestMatch(UInt32 *distances) else { lenLimit = _streamPos - _pos; - if(lenLimit < kNumHashBytes) - return 0; + if(lenLimit < kMinMatchCheck) + { + distances[0] = 0; + return MovePos(); + } } - UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; - Byte *cur = _buffer + _pos; + int offset = 1; - /* - if ((_cyclicBufferPos & kBundleMask) == 0) - { - Byte *bytes = _son[_cyclicBufferPos >> kNumBundleBits].Bytes; - UInt32 bundleLimit = kNumBundleBytes; - if (bundleLimit > lenLimit) - bundleLimit = lenLimit; - for (UInt32 i = 0; i < bundleLimit; i++) - bytes[i] = cur[i]; - } - */ - - UInt32 matchHashLenMax = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + const Byte *cur = _buffer + _pos; + + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; - UInt32 hashValue = Hash(cur, hash2Value, hash3Value); - #else - UInt32 hashValue = Hash(cur, hash2Value); #endif + UInt32 hashValue; + HASH_CALC; #else UInt32 hashValue = Hash(cur); #endif - UInt32 curMatch = _hash[hashValue]; + UInt32 curMatch = _hash[kFixHashSize + hashValue]; #ifdef HASH_ARRAY_2 - UInt32 curMatch2 = _hash2[hash2Value]; + UInt32 curMatch2 = _hash[hash2Value]; #ifdef HASH_ARRAY_3 - UInt32 curMatch3 = _hash3[hash3Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; #endif - _hash2[hash2Value] = _pos; - bool matchLen2Exist = false; - UInt32 len2Distance = 0; - if(curMatch2 >= matchMinPos) - { + _hash[hash2Value] = _pos; + if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { - len2Distance = _pos - curMatch2 - 1; - matchHashLenMax = 2; - matchLen2Exist = true; + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; } - } #ifdef HASH_ARRAY_3 - _hash3[hash3Value] = _pos; - UInt32 matchLen3Exist = false; - UInt32 len3Distance = 0; - if(curMatch3 >= matchMinPos) - { + _hash[kHash3Offset + hash3Value] = _pos; + if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { - len3Distance = _pos - curMatch3 - 1; - matchHashLenMax = 3; - matchLen3Exist = true; - if (matchLen2Exist) - { - if (len3Distance < len2Distance) - len2Distance = len3Distance; - } - else - { - len2Distance = len3Distance; - matchLen2Exist = true; - } + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + #endif + if (offset != 1 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + #endif + + _hash[kFixHashSize + hashValue] = _pos; + + CIndex *son = _son; + + #ifdef _HASH_CHAIN + son[_cyclicBufferPos] = curMatch; + #else + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + #endif + + #if kNumHashDirectBytes != 0 + if(curMatch > matchMinPos) + { + if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; } } #endif - #endif - - _hash[hashValue] = _pos; - - // UInt32 bi = _cyclicBufferPos >> kNumBundleBits; - // UInt32 bo = _cyclicBufferPos & kBundleMask; - // CPair &pair = _son[bi].Pairs[bo]; - CPair &pair = _son[_cyclicBufferPos]; - if(curMatch < matchMinPos) + UInt32 count = _cutValue; + while(true) { - pair.Left = kEmptyHashValue; - pair.Right = kEmptyHashValue; - - #ifdef HASH_ARRAY_2 - distances[2] = len2Distance; - #ifdef HASH_ARRAY_3 - distances[3] = len3Distance; - #endif - #endif - - return matchHashLenMax; - } - CIndex *ptrLeft = &pair.Right; - CIndex *ptrRight = &pair.Left; - - UInt32 maxLen, minLeft, minRight; - maxLen = minLeft = minRight = kNumHashDirectBytes; - - #ifdef HASH_ARRAY_2 - #ifndef HASH_ARRAY_3 - if (matchLen2Exist) - distances[2] = len2Distance; - else - if (kNumHashDirectBytes >= 2) - distances[2] = _pos - curMatch - 1; - #endif - #endif - - distances[maxLen] = _pos - curMatch - 1; - - for(UInt32 count = _cutValue; count > 0; count--) - { - /* - UInt32 delta = _pos - curMatch; - UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? - (_cyclicBufferPos - delta): - (_cyclicBufferPos - delta + _cyclicBufferSize); - - CBundle &bundle = _son[cyclicPos >> kNumBundleBits]; - UInt32 bo = cyclicPos & kBundleMask; - CPair &pair = bundle.Pairs[bo]; - - Byte *pby1 = bundle.Bytes + bo; - UInt32 bundleLimit = kNumBundleBytes - bo; - UInt32 currentLen = minSame; - if (bundleLimit > lenLimit) - bundleLimit = lenLimit; - for(; currentLen < bundleLimit; currentLen++) - if (pby1[currentLen] != cur[currentLen]) - break; - if (currentLen >= bundleLimit) + if(curMatch <= matchMinPos || count-- == 0) { - pby1 = _buffer + curMatch; - for(; currentLen < lenLimit; currentLen++) - if (pby1[currentLen] != cur[currentLen]) - break; - } - */ - Byte *pby1 = _buffer + curMatch; - // CIndex left = pair.Left; // it's prefetch - UInt32 currentLen = MyMin(minLeft, minRight); - for(; currentLen < lenLimit; currentLen++) - if (pby1[currentLen] != cur[currentLen]) - break; - UInt32 delta = _pos - curMatch; - while (currentLen > maxLen) - distances[++maxLen] = delta - 1; - - UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? - (_cyclicBufferPos - delta): - (_cyclicBufferPos - delta + _cyclicBufferSize); - CPair &pair = _son[cyclicPos]; - - if (currentLen != lenLimit) - { - if (pby1[currentLen] < cur[currentLen]) - { - *ptrRight = curMatch; - ptrRight = &pair.Right; - curMatch = pair.Right; - if(currentLen > minLeft) - minLeft = currentLen; - } - else - { - *ptrLeft = curMatch; - ptrLeft = &pair.Left; - curMatch = pair.Left; - if(currentLen > minRight) - minRight = currentLen; - } - } - else - { - if(currentLen < _matchMaxLen) - { - *ptrLeft = curMatch; - ptrLeft = &pair.Left; - curMatch = pair.Left; - if(currentLen > minRight) - minRight = currentLen; - } - else - { - *ptrLeft = pair.Right; - *ptrRight = pair.Left; - - #ifdef HASH_ARRAY_2 - if (matchLen2Exist && len2Distance < distances[2]) - distances[2] = len2Distance; - #ifdef HASH_ARRAY_3 - if (matchLen3Exist && len3Distance < distances[3]) - distances[3] = len3Distance; - #endif - #endif - - return maxLen; - } - } - if(curMatch < matchMinPos) + #ifndef _HASH_CHAIN + *ptr0 = *ptr1 = kEmptyHashValue; + #endif break; - } - *ptrLeft = kEmptyHashValue; - *ptrRight = kEmptyHashValue; - #ifdef HASH_ARRAY_2 - if (matchLen2Exist) - { - if (maxLen < 2) - { - distances[2] = len2Distance; - maxLen = 2; } - else if (len2Distance < distances[2]) - distances[2] = len2Distance; - } - #ifdef HASH_ARRAY_3 - if (matchLen3Exist) - { - if (maxLen < 3) + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + + #ifdef _HASH_CHAIN + cyclicPos; + #else + (cyclicPos << 1); + #endif + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = + #ifdef _HASH_CHAIN + kNumHashDirectBytes; + if (pb[maxLen] == cur[maxLen]) + #else + MyMin(len0, len1); + #endif + if (pb[len] == cur[len]) { - distances[3] = len3Distance; - maxLen = 3; + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + #ifndef _HASH_CHAIN + *ptr1 = pair[0]; + *ptr0 = pair[1]; + #endif + break; + } + } } - else if (len3Distance < distances[3]) - distances[3] = len3Distance; + #ifdef _HASH_CHAIN + curMatch = *pair; + #else + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + #endif } - #endif - #endif - return maxLen; + distances[0] = offset - 1; + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; } -void CInTree::DummyLongestMatch() +STDMETHODIMP CMatchFinder::Skip(UInt32 num) { + do + { + #ifdef _HASH_CHAIN + if (_streamPos - _pos < kNumHashBytes) + { + RINOK(MovePos()); + continue; + } + #else UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; - if(lenLimit < kNumHashBytes) - return; + if(lenLimit < kMinMatchCheck) + { + RINOK(MovePos()); + continue; + } } - UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; - Byte *cur = _buffer + _pos; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + #endif + const Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; - UInt32 hashValue = Hash(cur, hash2Value, hash3Value); - _hash3[hash3Value] = _pos; + UInt32 hashValue; + HASH_CALC; + _hash[kHash3Offset + hash3Value] = _pos; #else - UInt32 hashValue = Hash(cur, hash2Value); + UInt32 hashValue; + HASH_CALC; #endif - _hash2[hash2Value] = _pos; + _hash[hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif - UInt32 curMatch = _hash[hashValue]; - _hash[hashValue] = _pos; + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; - CPair &pair = _son[_cyclicBufferPos]; + #ifdef _HASH_CHAIN + _son[_cyclicBufferPos] = curMatch; + #else + CIndex *son = _son; + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); - if(curMatch < matchMinPos) + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + UInt32 count = _cutValue; + while(true) { - pair.Left = kEmptyHashValue; - pair.Right = kEmptyHashValue; - return; - } - CIndex *ptrLeft = &pair.Right; - CIndex *ptrRight = &pair.Left; - - UInt32 maxLen, minLeft, minRight; - maxLen = minLeft = minRight = kNumHashDirectBytes; - for(UInt32 count = _cutValue; count > 0; count--) - { - Byte *pby1 = _buffer + curMatch; - UInt32 currentLen = MyMin(minLeft, minRight); - for(; currentLen < lenLimit; currentLen++) - if (pby1[currentLen] != cur[currentLen]) - break; - + if(curMatch <= matchMinPos || count-- == 0) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? - (_cyclicBufferPos - delta): - (_cyclicBufferPos - delta + _cyclicBufferSize); - CPair &pair = _son[cyclicPos]; - - if (currentLen != lenLimit) + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + (cyclicPos << 1); + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = MyMin(len0, len1); + + if (pb[len] == cur[len]) { - if (pby1[currentLen] < cur[currentLen]) + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (len == lenLimit) { - *ptrRight = curMatch; - ptrRight = &pair.Right; - curMatch = pair.Right; - if(currentLen > minLeft) - minLeft = currentLen; - } - else - { - *ptrLeft = curMatch; - ptrLeft = &pair.Left; - curMatch = pair.Left; - if(currentLen > minRight) - minRight = currentLen; + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; } } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } else { - if(currentLen < _matchMaxLen) - { - *ptrLeft = curMatch; - ptrLeft = &pair.Left; - curMatch = pair.Left; - if(currentLen > minRight) - minRight = currentLen; - } - else - { - *ptrLeft = pair.Right; - *ptrRight = pair.Left; - return; - } + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; } - if(curMatch < matchMinPos) - break; } - *ptrLeft = kEmptyHashValue; - *ptrRight = kEmptyHashValue; + #endif + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + } + while(--num != 0); + return S_OK; } -void CInTree::NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue) +void CMatchFinder::Normalize() { + UInt32 subValue = _pos - _cyclicBufferSize; + CIndex *items = _hash; + UInt32 numItems = (_hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ); for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; @@ -527,25 +493,39 @@ void CInTree::NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue) value -= subValue; items[i] = value; } -} - -void CInTree::Normalize() -{ - UInt32 startItem = _pos - _historySize; - UInt32 subValue = startItem - 1; - // NormalizeLinks((CIndex *)(_son + startItem), _historySize * 2, subValue); - NormalizeLinks((CIndex *)_son, _cyclicBufferSize * 2, subValue); - - NormalizeLinks(_hash, kHashSize, subValue); - - #ifdef HASH_ARRAY_2 - NormalizeLinks(_hash2, kHash2Size, subValue); - #ifdef HASH_ARRAY_3 - NormalizeLinks(_hash3, kHash3Size, subValue); - #endif - #endif - ReduceOffsets(subValue); } + +HRESULT CMatchFinder::MovePos() +{ + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; +} + +STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index) + { return CLZInWindow::GetIndexByte(index); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, + UInt32 back, UInt32 limit) + { return CLZInWindow::GetMatchLen(index, back, limit); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes() + { return CLZInWindow::GetNumAvailableBytes(); } + +STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos() + { return CLZInWindow::GetPointerToCurrentPos(); } + +STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes) + { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; } + +STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos() + { CLZInWindow::MoveBlock();} + +#undef HASH_CALC +#undef kNumHashDirectBytes } diff --git a/Source/7zip/7zip/Compress/LZ/IMatchFinder.h b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h index bb42f60a..528b7b1c 100644 --- a/Source/7zip/7zip/Compress/LZ/IMatchFinder.h +++ b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h @@ -3,61 +3,30 @@ #ifndef __IMATCHFINDER_H #define __IMATCHFINDER_H -// {23170F69-40C1-278A-0000-000200010000} -DEFINE_GUID(IID_IInWindowStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000") -IInWindowStream: public IUnknown +struct IInWindowStream: public IUnknown { - STDMETHOD(Init)(ISequentialInStream *inStream) PURE; + STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE; STDMETHOD_(void, ReleaseStream)() PURE; - STDMETHOD(MovePos)() PURE; + STDMETHOD(Init)() PURE; STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE; + STDMETHOD_(void, ChangeBufferPos)() PURE; }; -// {23170F69-40C1-278A-0000-000200020000} -DEFINE_GUID(IID_IMatchFinder, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000") -IMatchFinder: public IInWindowStream +struct IMatchFinder: public IInWindowStream { STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; - STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE; - STDMETHOD_(void, DummyLongestMatch)() PURE; + STDMETHOD(GetMatches)(UInt32 *distances) PURE; + STDMETHOD(Skip)(UInt32 num) PURE; }; -// {23170F69-40C1-278A-0000-000200020100} -DEFINE_GUID(IID_IMatchFinderCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100") -IMatchFinderCallback: public IUnknown +struct IMatchFinderSetNumPasses { - STDMETHOD(BeforeChangingBufferPos)() PURE; - STDMETHOD(AfterChangingBufferPos)() PURE; + virtual void SetNumPasses(UInt32 numPasses) PURE; }; -// {23170F69-40C1-278A-0000-000200020200} -DEFINE_GUID(IID_IMatchFinderSetCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200") -IMatchFinderSetCallback: public IUnknown -{ - STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE; -}; - -/* -// {23170F69-40C1-278A-0000-000200030000} -DEFINE_GUID(IID_IInitMatchFinder, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000") -IMatchFinderInit: public IUnknown -{ - STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE; -}; -*/ - #endif diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp index 0c76788f..0e65c425 100644 --- a/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp @@ -16,22 +16,27 @@ bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 kee { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; - _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == 0 || _blockSize != blockSize) { Free(); _blockSize = blockSize; - _bufferBase = (Byte *)::BigAlloc(_blockSize); + if (_blockSize != 0) + _bufferBase = (Byte *)::BigAlloc(_blockSize); } _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; + if (_blockSize == 0) + return true; return (_bufferBase != 0); } - -HRESULT CLZInWindow::Init(ISequentialInStream *stream) +void CLZInWindow::SetStream(ISequentialInStream *stream) { _stream = stream; +} + +HRESULT CLZInWindow::Init() +{ _buffer = _bufferBase; _pos = 0; _streamPos = 0; @@ -65,11 +70,11 @@ HRESULT CLZInWindow::ReadBlock() return S_OK; while(true) { - UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos; + UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos; if(size == 0) return S_OK; UInt32 numReadBytes; - RINOK(_stream->ReadPart(_buffer + _streamPos, size, &numReadBytes)); + RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; @@ -90,10 +95,11 @@ HRESULT CLZInWindow::ReadBlock() void CLZInWindow::MoveBlock() { - BeforeMoveBlock(); - UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore; - UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset; + UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset; memmove(_bufferBase, _bufferBase + offset, numBytes); _buffer -= offset; - AfterMoveBlock(); } diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.h b/Source/7zip/7zip/Compress/LZ/LZInWindow.h index a9cb7320..54f2cb7b 100644 --- a/Source/7zip/7zip/Compress/LZ/LZInWindow.h +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.h @@ -9,7 +9,7 @@ class CLZInWindow { Byte *_bufferBase; // pointer to buffer with data ISequentialInStream *_stream; - UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + UInt32 _posLimit; // offset (from _buffer) when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream const Byte *_pointerToLastSafePosition; protected: @@ -18,22 +18,20 @@ protected: UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos - UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream - virtual void BeforeMoveBlock() {}; - virtual void AfterMoveBlock() {}; void MoveBlock(); - virtual HRESULT ReadBlock(); + HRESULT ReadBlock(); void Free(); public: CLZInWindow(): _bufferBase(0) {} virtual ~CLZInWindow() { Free(); } - bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, - UInt32 keepSizeReserv = (1<<17)); + // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G) + bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); - HRESULT Init(ISequentialInStream *stream); + void SetStream(ISequentialInStream *stream); + HRESULT Init(); // void ReleaseStream(); Byte *GetBuffer() const { return _buffer; } @@ -53,17 +51,17 @@ public: else return S_OK; } - Byte GetIndexByte(Int32 index)const - { return _buffer[(size_t)_pos + index]; } + Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; } // index + limit have not to exceed _keepSizeAfter; + // -2G <= index < 2G UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const { if(_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; - Byte *pby = _buffer + (size_t)_pos + index; + const Byte *pby = _buffer + (size_t)_pos + index; UInt32 i; for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); return i; @@ -79,6 +77,11 @@ public: _streamPos -= subValue; } + bool NeedMove(UInt32 numCheckBytes) + { + UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos); + return (reserv <= numCheckBytes); + } }; #endif diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp index 2b503413..e2d6aba1 100644 --- a/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp @@ -5,84 +5,13 @@ #include "../../../Common/Alloc.h" #include "LZOutWindow.h" -bool CLZOutWindow::Create(UInt32 windowSize) +void CLZOutWindow::Init(bool solid) { - _pos = 0; - _streamPos = 0; - const UInt32 kMinBlockSize = 1; - if (windowSize < kMinBlockSize) - windowSize = kMinBlockSize; - if (_buffer != 0 && _windowSize == windowSize) - return true; - Free(); - _windowSize = windowSize; - _buffer = (Byte *)::BigAlloc(windowSize); - return (_buffer != 0); -} - -void CLZOutWindow::Free() -{ - ::BigFree(_buffer); - _buffer = 0; -} - -void CLZOutWindow::Init(ISequentialOutStream *stream, bool solid) -{ - // ReleaseStream(); - _stream = stream; - // _stream->AddRef(); - if(!solid) - { - _streamPos = 0; - _pos = 0; - } + COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } -/* -void CLZOutWindow::ReleaseStream() -{ - if(_stream != 0) - { - // Flush(); // Test it - _stream->Release(); - _stream = 0; - } -} -*/ -void CLZOutWindow::FlushWithCheck() -{ - HRESULT result = Flush(); - #ifdef _NO_EXCEPTIONS - ErrorCode = result; - #else - if (result != S_OK) - throw CLZOutWindowException(result); - #endif -} - -HRESULT CLZOutWindow::Flush() -{ - UInt32 size = _pos - _streamPos; - if(size == 0) - return S_OK; - #ifdef _NO_EXCEPTIONS - if (ErrorCode != S_OK) - return ErrorCode; - #endif - - UInt32 processedSize; - HRESULT result = _stream->Write(_buffer + _streamPos, size, &processedSize); - if (result != S_OK) - return result; - if (size != processedSize) - return E_FAIL; - if (_pos >= _windowSize) - _pos = 0; - _streamPos = _pos; - return S_OK; -} diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.h b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h index fb6aba7c..3c50c6e7 100644 --- a/Source/7zip/7zip/Compress/LZ/LZOutWindow.h +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h @@ -4,66 +4,51 @@ #define __LZ_OUT_WINDOW_H #include "../../IStream.h" +#include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS -class CLZOutWindowException -{ -public: - HRESULT ErrorCode; - CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {} -}; +typedef COutBufferException CLZOutWindowException; #endif -class CLZOutWindow +class CLZOutWindow: public COutBuffer { - Byte *_buffer; - UInt32 _pos; - UInt32 _windowSize; - UInt32 _streamPos; - ISequentialOutStream *_stream; - void FlushWithCheck(); public: - #ifdef _NO_EXCEPTIONS - HRESULT ErrorCode; - #endif - - void Free(); - CLZOutWindow(): _buffer(0), _stream(0) {} - ~CLZOutWindow() { Free(); /* ReleaseStream(); */ } - bool Create(UInt32 windowSize); + void Init(bool solid = false); - void Init(ISequentialOutStream *stream, bool solid = false); - HRESULT Flush(); - // void ReleaseStream(); - - void CopyBlock(UInt32 distance, UInt32 len) + // distance >= 0, len > 0, + bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; - if (pos >= _windowSize) - pos += _windowSize; - for(; len > 0; len--) + if (distance >= _pos) { - if (pos >= _windowSize) + if (!_overDict || distance >= _bufferSize) + return false; + pos += _bufferSize; + } + do + { + if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; - if (_pos >= _windowSize) + if (_pos == _limitPos) FlushWithCheck(); - // PutOneByte(GetOneByte(distance)); } + while(--len != 0); + return true; } void PutByte(Byte b) { _buffer[_pos++] = b; - if (_pos >= _windowSize) + if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; - if (pos >= _windowSize) - pos += _windowSize; + if (pos >= _bufferSize) + pos += _bufferSize; return _buffer[pos]; } }; diff --git a/Source/7zip/7zip/Compress/LZ/StdAfx.h b/Source/7zip/7zip/Compress/LZ/StdAfx.h index ceced164..3ff6d8a2 100644 --- a/Source/7zip/7zip/Compress/LZ/StdAfx.h +++ b/Source/7zip/7zip/Compress/LZ/StdAfx.h @@ -3,6 +3,4 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../../Platform.h" - #endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMA.h b/Source/7zip/7zip/Compress/LZMA/LZMA.h index 760d304e..7bc4c438 100644 --- a/Source/7zip/7zip/Compress/LZMA/LZMA.h +++ b/Source/7zip/7zip/Compress/LZMA/LZMA.h @@ -24,6 +24,7 @@ public: void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } + bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp index 71fc9abf..55c668e8 100644 --- a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" @@ -10,18 +11,16 @@ // #define COMPRESS_MF_BT // #define COMPRESS_MF_BT4 -#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC) +#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC) #define COMPRESS_MF_BT -#define COMPRESS_MF_PAT #define COMPRESS_MF_HC #endif #ifdef COMPRESS_MF_BT -#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B) +#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) #define COMPRESS_MF_BT2 #define COMPRESS_MF_BT3 #define COMPRESS_MF_BT4 -#define COMPRESS_MF_BT4B #endif #ifdef COMPRESS_MF_BT2 #include "../LZ/BinTree/BinTree2.h" @@ -32,21 +31,9 @@ #ifdef COMPRESS_MF_BT4 #include "../LZ/BinTree/BinTree4.h" #endif -#ifdef COMPRESS_MF_BT4B -#include "../LZ/BinTree/BinTree4b.h" -#endif -#endif - -#ifdef COMPRESS_MF_PAT -#include "../LZ/Patricia/Pat2.h" -#include "../LZ/Patricia/Pat2H.h" -#include "../LZ/Patricia/Pat3H.h" -#include "../LZ/Patricia/Pat4H.h" -#include "../LZ/Patricia/Pat2R.h" #endif #ifdef COMPRESS_MF_HC -#include "../LZ/HashChain/HC3.h" #include "../LZ/HashChain/HC4.h" #endif @@ -57,7 +44,7 @@ namespace NCompress { namespace NLZMA { -const int kDefaultDictionaryLogSize = 20; +const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; enum @@ -65,32 +52,18 @@ enum kBT2, kBT3, kBT4, - kBT4B, - kPat2, - kPat2H, - kPat3H, - kPat4H, - kPat2R, - kHC3, kHC4 }; -static const wchar_t *kMatchFinderIDs[] = +/*static const wchar_t *kMatchFinderIDs[] = { L"BT2", L"BT3", L"BT4", - L"BT4B", - L"PAT2", - L"PAT2H", - L"PAT3H", - L"PAT4H", - L"PAT2R", - L"HC3", L"HC4" -}; +};*/ -Byte g_FastPos[1024]; +Byte g_FastPos[1 << 11]; class CFastPosInit { @@ -98,7 +71,7 @@ public: CFastPosInit() { Init(); } void Init() { - const Byte kFastSlots = 20; + const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; @@ -116,57 +89,66 @@ public: void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; - for (int i = 7; i >= 0; i--) + int i = 8; + do { + i--; UInt32 bit = (symbol >> i) & 1; - UInt32 state = context; - _encoders[state].Encode(rangeEncoder, bit); + _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } + while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; - bool same = true; - for (int i = 7; i >= 0; i--) + int i = 8; + do { + i--; UInt32 bit = (symbol >> i) & 1; - UInt32 state = context; - if (same) - { - UInt32 matchBit = (matchByte >> i) & 1; - state += (1 + matchBit) << 8; - same = (matchBit == bit); - } - _encoders[state].Encode(rangeEncoder, bit); + UInt32 matchBit = (matchByte >> i) & 1; + _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; + if (matchBit != bit) + { + while(i != 0) + { + i--; + UInt32 bit = (symbol >> i) & 1; + _encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + break; + } } + while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; - int i = 7; + int i = 8; if (matchMode) { - for (; i >= 0; i--) + do { + i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; - price += _encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) - { - i--; break; - } } + while (i != 0); } - for (; i >= 0; i--) + while(i != 0) { + i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; @@ -180,12 +162,12 @@ namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); + _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } - _choice2.Init(); _highCoder.Init(); } @@ -198,45 +180,41 @@ void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 } else { - symbol -= kNumLowSymbols; _choice.Encode(rangeEncoder, 1); - if(symbol < kNumMidSymbols) + if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); - _midCoder[posState].Encode(rangeEncoder, symbol); + _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); - _highCoder.Encode(rangeEncoder, symbol - kNumMidSymbols); + _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } -UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const +void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const { - UInt32 price = 0; - if(symbol < kNumLowSymbols) + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < kNumLowSymbols; i++) { - price += _choice.GetPrice(0); - price += _lowCoder[posState].GetPrice(symbol); + if (i >= numSymbols) + return; + prices[i] = a0 + _lowCoder[posState].GetPrice(i); } - else + for (; i < kNumLowSymbols + kNumMidSymbols; i++) { - symbol -= kNumLowSymbols; - price += _choice.GetPrice(1); - if(symbol < kNumMidSymbols) - { - price += _choice2.GetPrice(0); - price += _midCoder[posState].GetPrice(symbol); - } - else - { - price += _choice2.GetPrice(1); - price += _highCoder.GetPrice(symbol - kNumMidSymbols); - } + if (i >= numSymbols) + return; + prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); } - return price; + for (; i < numSymbols; i++) + prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); } } @@ -250,13 +228,15 @@ CEncoder::CEncoder(): _dictionarySize(1 << kDefaultDictionaryLogSize), _dictionarySizePrev(UInt32(-1)), _numFastBytesPrev(UInt32(-1)), + _matchFinderCycles(0), _matchFinderIndex(kBT4), #ifdef COMPRESS_MF_MT _multiThread(false), #endif - _writeEndMark(false) + _writeEndMark(false), + setMfPasses(0) { - _maxMode = false; + // _maxMode = false; _fastMode = false; } @@ -271,57 +251,52 @@ HRESULT CEncoder::Create() #ifdef COMPRESS_MF_BT #ifdef COMPRESS_MF_BT2 case kBT2: - _matchFinder = new NBT2::CMatchFinderBinTree; + { + NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; break; + } #endif #ifdef COMPRESS_MF_BT3 case kBT3: - _matchFinder = new NBT3::CMatchFinderBinTree; + { + NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; break; + } #endif #ifdef COMPRESS_MF_BT4 case kBT4: - _matchFinder = new NBT4::CMatchFinderBinTree; - break; - #endif - #ifdef COMPRESS_MF_BT4B - case kBT4B: - _matchFinder = new NBT4B::CMatchFinderBinTree; + { + NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; break; + } #endif #endif - #ifdef COMPRESS_MF_PAT - case kPat2: - _matchFinder = new NPat2::CPatricia; - break; - case kPat2H: - _matchFinder = new NPat2H::CPatricia; - break; - case kPat3H: - _matchFinder = new NPat3H::CPatricia; - break; - case kPat4H: - _matchFinder = new NPat4H::CPatricia; - break; - case kPat2R: - _matchFinder = new NPat2R::CPatricia; - break; - #endif - #ifdef COMPRESS_MF_HC - case kHC3: - _matchFinder = new NHC3::CMatchFinderHC; - break; case kHC4: - _matchFinder = new NHC4::CMatchFinderHC; + { + NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; break; + } #endif } + if (_matchFinder == 0) + return E_OUTOFMEMORY; + #ifdef COMPRESS_MF_MT - if (_multiThread) + if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4))) { CMatchFinderMT *mfSpec = new CMatchFinderMT; + if (mfSpec == 0) + return E_OUTOFMEMORY; CMyComPtr mf = mfSpec; RINOK(mfSpec->SetMatchFinder(_matchFinder)); _matchFinder.Release(); @@ -335,14 +310,15 @@ HRESULT CEncoder::Create() if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return S_OK; - RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, - kMatchMaxLen - _numFastBytes)); + RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes + if (_matchFinderCycles != 0 && setMfPasses != 0) + setMfPasses->SetNumPasses(_matchFinderCycles); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; return S_OK; } -static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) +/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) { while (true) { @@ -364,7 +340,7 @@ static int FindMatchFinder(const wchar_t *s) if (AreStringsEqual(kMatchFinderIDs[m], s)) return m; return -1; -} +}*/ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) @@ -379,35 +355,43 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; - if(numFastBytes < 2 || numFastBytes > kMatchMaxLen) + if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } + case NCoderPropID::kMatchFinderCycles: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + _matchFinderCycles = prop.ulVal; + break; + } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); - _maxMode = (maximize >= 2); + // _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { - if (prop.vt != VT_BSTR) + return E_NOTIMPL; + /*if (prop.vt != VT_BSTR) return E_INVALIDARG; int matchFinderIndexPrev = _matchFinderIndex; int m = FindMatchFinder(prop.bstrVal); if (m < 0) return E_INVALIDARG; _matchFinderIndex = m; - if (!_matchFinder && matchFinderIndexPrev != _matchFinderIndex) + if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) { - _dictionarySizePrev = UInt32(-1); - _matchFinder.Release(); + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); } - break; + break;*/ } #ifdef COMPRESS_MF_MT case NCoderPropID::kMultiThread: @@ -417,16 +401,29 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { - _dictionarySizePrev = UInt32(-1); - _matchFinder.Release(); + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + break; + } + case NCoderPropID::kNumThreads: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + bool newMultiThread = (prop.ulVal > 1); + if (newMultiThread != _multiThread) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; } - _multiThread = newMultiThread; break; } #endif case NCoderPropID::kDictionarySize: { - const int kDicLogSizeMaxCompress = 28; + const int kDicLogSizeMaxCompress = 30; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; @@ -488,23 +485,32 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { - Byte firstByte = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; - RINOK(outStream->Write(&firstByte, sizeof(firstByte), NULL)); + const UInt32 kPropSize = 5; + Byte properties[kPropSize]; + properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) - { - Byte b = Byte(_dictionarySize >> (8 * i)); - RINOK(outStream->Write(&b, sizeof(b), NULL)); - } + properties[1 + i] = Byte(_dictionarySize >> (8 * i)); + return WriteStream(outStream, properties, kPropSize, NULL); +} + +STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) +{ + _rangeEncoder.SetStream(outStream); return S_OK; } -STDMETHODIMP CEncoder::Init( - ISequentialOutStream *outStream) +STDMETHODIMP CEncoder::ReleaseOutStream() +{ + _rangeEncoder.ReleaseStream(); + return S_OK; +} + +HRESULT CEncoder::Init() { CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); - _rangeEncoder.Init(outStream); + _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { @@ -521,8 +527,6 @@ STDMETHODIMP CEncoder::Init( _literalEncoder.Init(); - // _repMatchLenEncoder.Init(); - { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); @@ -547,13 +551,10 @@ STDMETHODIMP CEncoder::Init( HRESULT CEncoder::MovePos(UInt32 num) { - for (;num > 0; num--) - { - _matchFinder->DummyLongestMatch(); - RINOK(_matchFinder->MovePos()); - _additionalOffset++; - } - return S_OK; + if (num == 0) + return S_OK; + _additionalOffset += num; + return _matchFinder->Skip(num); } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) @@ -584,44 +585,51 @@ UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) _optimum[posPrev].PosPrev = cur; cur = posPrev; } - while(cur > 0); + while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* -inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit) -{ - back++; - for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++); - return i; -} +Out: + (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { if(_optimumEndIndex != _optimumCurrentIndex) { - lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; - backRes = _optimum[_optimumCurrentIndex].BackPrev; - _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + const COptimal &optimum = _optimum[_optimumCurrentIndex]; + lenRes = optimum.PosPrev - _optimumCurrentIndex; + backRes = optimum.BackPrev; + _optimumCurrentIndex = optimum.PosPrev; return S_OK; } - _optimumCurrentIndex = 0; - _optimumEndIndex = 0; // test it; + _optimumCurrentIndex = _optimumEndIndex = 0; - UInt32 lenMain; + UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { - RINOK(ReadMatchDistances(lenMain)); + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); } else { lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; @@ -630,48 +638,53 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; - repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen); - if (i == 0 || repLens[i] > repLens[repMaxIndex]) + UInt32 backOffset = reps[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 lenTest; + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } - if(repLens[repMaxIndex] > _numFastBytes) + if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; - MovePos(lenRes - 1); - return S_OK; + return MovePos(lenRes - 1); } - if(lenMain > _numFastBytes) + UInt32 *matchDistances = _matchDistances + 1; + if(lenMain >= _numFastBytes) { - UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : - _matchDistances[_numFastBytes]; - backRes = backMain + kNumRepDistances; - MovePos(lenMain - 1); + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; lenRes = lenMain; + return MovePos(lenMain - 1); + } + Byte currentByte = *data; + Byte matchByte = data[(size_t)0 - reps[0] - 1]; + + if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)-1; + lenRes = 1; return S_OK; } - Byte currentByte = _matchFinder->GetIndexByte(0 - 1); _optimum[0].State = _state; - Byte matchByte; - - matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); - UInt32 posState = (position & _posStateMask); - _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice(0) + - _literalEncoder.GetPrice(position, _previousByte, _peviousIsMatch, matchByte, currentByte); + _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); - _optimum[1].PosPrev = 0; - - for (i = 0; i < kNumRepDistances; i++) - _optimum[0].Backs[i] = reps[i]; - - UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice(1); - UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice(1); + UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { @@ -682,43 +695,34 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) _optimum[1].MakeAsShortRep(); } } - if(lenMain < 2) + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } - - UInt32 normalMatchPrice = matchPrice + - _isRep[_state.Index].GetPrice(0); + _optimum[1].PosPrev = 0; + for (i = 0; i < kNumRepDistances; i++) + _optimum[0].Backs[i] = reps[i]; - if (lenMain <= repLens[repMaxIndex]) - lenMain = 0; - - UInt32 len; - for(len = 2; len <= lenMain; len++) - { - _optimum[len].PosPrev = 0; - _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; - _optimum[len].Price = normalMatchPrice + - GetPosLenPrice(_matchDistances[len], len, posState); - _optimum[len].Prev1IsChar = false; - } - - if (lenMain < repLens[repMaxIndex]) - lenMain = repLens[repMaxIndex]; - - for (; len <= lenMain; len++) - _optimum[len].Price = kIfinityPrice; + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; - for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++) + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do { - UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); - COptimal &optimum = _optimum[lenTest]; + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; @@ -727,10 +731,39 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) optimum.Prev1IsChar = false; } } + while(--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > matchDistances[offs]) + offs += 2; + for(; ; len++) + { + UInt32 distance = matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + COptimal &optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } } UInt32 cur = 0; - UInt32 lenEnd = lenMain; while(true) { @@ -740,16 +773,27 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) lenRes = Backward(backRes, cur); return S_OK; } + UInt32 newLen, numDistancePairs; + RINOK(ReadMatchDistances(newLen, numDistancePairs)); + if(newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + lenRes = Backward(backRes, cur); + return S_OK; + } position++; - UInt32 posPrev = _optimum[cur].PosPrev; + COptimal &curOptimum = _optimum[cur]; + UInt32 posPrev = curOptimum.PosPrev; CState state; - if (_optimum[cur].Prev1IsChar) + if (curOptimum.Prev1IsChar) { posPrev--; - if (_optimum[cur].Prev2) + if (curOptimum.Prev2) { - state = _optimum[_optimum[cur].PosPrev2].State; - if (_optimum[cur].BackPrev2 < kNumRepDistances) + state = _optimum[curOptimum.PosPrev2].State; + if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); @@ -760,83 +804,60 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) } else state = _optimum[posPrev].State; - bool prevWasMatch; if (posPrev == cur - 1) { - if (_optimum[cur].IsShortRep()) - { - prevWasMatch = true; + if (curOptimum.IsShortRep()) state.UpdateShortRep(); - } else - { - prevWasMatch = false; state.UpdateChar(); - } - /* - if (_optimum[cur].Prev1IsChar) - for(int i = 0; i < kNumRepDistances; i++) - reps[i] = _optimum[posPrev].Backs[i]; - */ } else { - prevWasMatch = true; UInt32 pos; - if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + if (curOptimum.Prev1IsChar && curOptimum.Prev2) { - posPrev = _optimum[cur].PosPrev2; - pos = _optimum[cur].BackPrev2; + posPrev = curOptimum.PosPrev2; + pos = curOptimum.BackPrev2; state.UpdateRep(); } else { - pos = _optimum[cur].BackPrev; + pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } + const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { - reps[0] = _optimum[posPrev].Backs[pos]; + reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) - reps[i] = _optimum[posPrev].Backs[i - 1]; + reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) - reps[i] = _optimum[posPrev].Backs[i]; + reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) - reps[i] = _optimum[posPrev].Backs[i - 1]; + reps[i] = prevOptimum.Backs[i - 1]; } } - _optimum[cur].State = state; + curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) - _optimum[cur].Backs[i] = reps[i]; - UInt32 newLen; - RINOK(ReadMatchDistances(newLen)); - if(newLen > _numFastBytes) - { - _longestMatchLength = newLen; - _longestMatchWasFound = true; - lenRes = Backward(backRes, cur); - return S_OK; - } - UInt32 curPrice = _optimum[cur].Price; - // Byte currentByte = _matchFinder->GetIndexByte(0 - 1); - // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); + curOptimum.Backs[i] = reps[i]; + UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; - Byte currentByte = *data; - Byte matchByte = data[(size_t)0 - reps[0] - 1]; + const Byte currentByte = *data; + const Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + - _isMatch[state.Index][posState].GetPrice(0) + - _literalEncoder.GetPrice(position, data[(size_t)0 - 1], prevWasMatch, matchByte, currentByte); + _isMatch[state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; @@ -849,8 +870,8 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) nextIsChar = true; } - UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice(1); - UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice(1); + UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) @@ -861,28 +882,30 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); - // nextIsChar = false; + nextIsChar = true; } } /* - if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? + if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ - UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; - numAvailableBytes = MyMin(kNumOpts - 1 - cur, numAvailableBytes); + UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; + numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); + UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; - if (numAvailableBytes >= 3 && !nextIsChar) + if (!nextIsChar && matchByte != currentByte) // speed optimization { + // try Literal + rep0 UInt32 backOffset = reps[0] + 1; + UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; - for (temp = 1; temp < numAvailableBytes; temp++) - if (data[temp] != data[(size_t)temp - backOffset]) - break; + for (temp = 1; temp < limit && + data[temp] == data[(size_t)temp - backOffset]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { @@ -890,15 +913,16 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + - _isMatch[state2.Index][posStateNext].GetPrice(1) + - _isRep[state2.Index].GetPrice(1); + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { - while(lenEnd < cur + 1 + lenTest2) + UInt32 offset = cur + 1 + lenTest2; + while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); - COptimal &optimum = _optimum[cur + 1 + lenTest2]; + COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; @@ -910,19 +934,25 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) } } } + + UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; + if (data[0] != data[(size_t)0 - backOffset] || + data[1] != data[(size_t)1 - backOffset]) + continue; UInt32 lenTest; - for (lenTest = 0; lenTest < numAvailableBytes; lenTest++) - if (data[lenTest] != data[(size_t)lenTest - backOffset]) - break; - for(; lenTest >= 2; lenTest--) + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + while(lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 lenTestTemp = lenTest; + UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); + do { - while(lenEnd < cur + lenTest) - _optimum[++lenEnd].Price = kIfinityPrice; - UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { @@ -931,37 +961,44 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } - - /* - if (_maxMode) + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) { - UInt32 temp; - for (temp = lenTest + 1; temp < numAvailableBytes; temp++) - if (data[temp] != data[(size_t)temp - backOffset]) - break; - UInt32 lenTest2 = temp - (lenTest + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; - UInt32 curAndLenCharPrice = curAndLenPrice + - _isMatch[state2.Index][posStateNext].GetPrice(0) + - _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], + UInt32 curAndLenCharPrice = + price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; - UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice(1); - UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice(1); + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { - UInt32 offset = lenTest + 1 + lenTest2; - while(lenEnd < cur + offset) + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); - COptimal &optimum = _optimum[cur + offset]; + COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; @@ -975,26 +1012,38 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) } } } - */ } - } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) - newLen = numAvailableBytes; - if (newLen >= 2) { - if (newLen == 2 && _matchDistances[2] >= 0x80) - continue; - UInt32 normalMatchPrice = matchPrice + - _isRep[state.Index].GetPrice(0); + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); + matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; - for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--) + UInt32 offs = 0; + while(startLen > matchDistances[offs]) + offs += 2; + UInt32 curBack = matchDistances[offs + 1]; + UInt32 posSlot = GetPosSlot2(curBack); + for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { - UInt32 curBack = _matchDistances[lenTest]; - UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + UInt32 curAndLenPrice = normalMatchPrice; + UInt32 lenToPosState = GetLenToPosState(lenTest); + if (curBack < kNumFullDistances) + curAndLenPrice += _distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; + + curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); + COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { @@ -1004,36 +1053,37 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) optimum.Prev1IsChar = false; } - if (_maxMode) + if (/*_maxMode && */lenTest == matchDistances[offs]) { + // Try Match + Literal + Rep0 UInt32 backOffset = curBack + 1; - UInt32 temp; - for (temp = lenTest + 1; temp < numAvailableBytes; temp++) - if (data[temp] != data[(size_t)temp - backOffset]) - break; - UInt32 lenTest2 = temp - (lenTest + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + - _isMatch[state2.Index][posStateNext].GetPrice(0) + - _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); - posStateNext = (position + lenTest + 1) & _posStateMask; - UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice(1); - UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice(1); + posStateNext = (posStateNext + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { - UInt32 offset = lenTest + 1 + lenTest2; - while(lenEnd < cur + offset) + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; - UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( - 0, lenTest2, state2, posStateNext); - COptimal &optimum = _optimum[cur + offset]; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; @@ -1046,6 +1096,12 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) } } } + offs += 2; + if (offs == numDistancePairs) + break; + curBack = matchDistances[offs + 1]; + if (curBack >= kNumFullDistances) + posSlot = GetPosSlot2(curBack); } } } @@ -1054,102 +1110,140 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { - const int kDif = 7; - return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif)); + return ((bigDist >> 7) > smallDist); } -HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes) +HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs) { - lenRes = _matchFinder->GetLongestMatch(_matchDistances); - if (lenRes == _numFastBytes) - lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes], - kMatchMaxLen - lenRes); + lenRes = 0; + RINOK(_matchFinder->GetMatches(_matchDistances)); + numDistancePairs = _matchDistances[0]; + if (numDistancePairs > 0) + { + lenRes = _matchDistances[1 + numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1], + kMatchMaxLen - lenRes); + } _additionalOffset++; - return _matchFinder->MovePos(); + return S_OK; } HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { - UInt32 lenMain; + UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { - RINOK(ReadMatchDistances(lenMain)); + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); } else { lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } + + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; + for(UInt32 i = 0; i < kNumRepDistances; i++) { - repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); - if (i == 0 || repLens[i] > repLens[repMaxIndex]) + UInt32 backOffset = _repDistances[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if(len >= _numFastBytes) + { + backRes = i; + lenRes = len; + return MovePos(lenRes - 1); + } + repLens[i] = len; + if (len > repLens[repMaxIndex]) repMaxIndex = i; } - if(repLens[repMaxIndex] >= _numFastBytes) - { - backRes = repMaxIndex; - lenRes = repLens[repMaxIndex]; - MovePos(lenRes - 1); - return S_OK; - } + UInt32 *matchDistances = _matchDistances + 1; if(lenMain >= _numFastBytes) { - backRes = _matchDistances[_numFastBytes] + kNumRepDistances; - MovePos(lenMain - 1); + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; lenRes = lenMain; - return S_OK; + return MovePos(lenMain - 1); + } + + UInt32 backMain = 0; // for GCC + if (lenMain >= 2) + { + backMain = matchDistances[numDistancePairs - 1]; + while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) + { + if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) + break; + numDistancePairs -= 2; + lenMain = matchDistances[numDistancePairs - 2]; + backMain = matchDistances[numDistancePairs - 1]; + } + if (lenMain == 2 && backMain >= 0x80) + lenMain = 1; } - while (lenMain > 2) - { - if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) - break; - lenMain--; - } - if (lenMain == 2 && _matchDistances[2] >= 0x80) - lenMain = 1; - UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || - repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12))) + repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || + repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; - MovePos(lenRes - 1); - return S_OK; + return MovePos(lenRes - 1); } } - - if (lenMain >= 2) + if (lenMain >= 2 && numAvailableBytes > 2) { - RINOK(ReadMatchDistances(_longestMatchLength)); - if (_longestMatchLength >= 2 && - ( - (_longestMatchLength >= lenMain && - _matchDistances[lenMain] < backMain) || - _longestMatchLength == lenMain + 1 && - !ChangePair(backMain, _matchDistances[_longestMatchLength]) || - _longestMatchLength > lenMain + 1 || - _longestMatchLength + 1 >= lenMain && - ChangePair(_matchDistances[lenMain - 1], backMain) - ) - ) + RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs)); + if (_longestMatchLength >= 2) { - _longestMatchWasFound = true; - backRes = UInt32(-1); - lenRes = 1; - return S_OK; + UInt32 newDistance = matchDistances[_numDistancePairs - 1]; + if (_longestMatchLength >= lenMain && newDistance < backMain || + _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || + _longestMatchLength > lenMain + 1 || + _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) + { + _longestMatchWasFound = true; + backRes = UInt32(-1); + lenRes = 1; + return S_OK; + } } + data++; + numAvailableBytes--; for(UInt32 i = 0; i < kNumRepDistances; i++) { - UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); - if (repLen >= 2 && repLen + 1 >= lenMain) + UInt32 backOffset = _repDistances[i] + 1; + if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if (len + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); @@ -1158,23 +1252,18 @@ HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRe } } backRes = backMain + kNumRepDistances; - MovePos(lenMain - 2); lenRes = lenMain; - return S_OK; + return MovePos(lenMain - 2); } backRes = UInt32(-1); lenRes = 1; return S_OK; } -STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder) -{ - _matchFinder = matchFinder; - return S_OK; -} - -HRESULT CEncoder::Flush() +HRESULT CEncoder::Flush(UInt32 nowPos) { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } @@ -1190,7 +1279,7 @@ void CEncoder::WriteEndMarker(UInt32 posState) _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; - _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); @@ -1230,7 +1319,8 @@ HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, _inStream = inStream; _finished = false; RINOK(Create()); - RINOK(Init(outStream)); + RINOK(SetOutStream(outStream)); + RINOK(Init()); // CCoderReleaser releaser(this); @@ -1241,17 +1331,15 @@ HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, if (!_fastMode) { - FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } - _lenEncoder.SetTableSize(_numFastBytes); + _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); - _repMatchLenEncoder.SetTableSize(_numFastBytes); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); - lastPosSlotFillingPos = 0; nowPos64 = 0; return S_OK; } @@ -1260,7 +1348,8 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { - RINOK(_matchFinder->Init(_inStream)); + RINOK(_matchFinder->SetStream(_inStream)); + RINOK(_matchFinder->Init()); _needReleaseMFStream = true; _inStream = 0; } @@ -1271,18 +1360,12 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) return S_OK; _finished = true; - - UInt64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder->GetNumAvailableBytes() == 0) - { - ReleaseStreams(); - WriteEndMarker(UInt32(nowPos64) & _posStateMask); - return Flush(); - } - UInt32 len; // it's not used - RINOK(ReadMatchDistances(len)); + return Flush(UInt32(nowPos64)); + UInt32 len, numDistancePairs; + RINOK(ReadMatchDistances(len, numDistancePairs)); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); @@ -1292,48 +1375,45 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) _additionalOffset--; nowPos64++; } + + UInt32 nowPos32 = (UInt32)nowPos64; + UInt32 progressPosValuePrev = nowPos32; + if (_matchFinder->GetNumAvailableBytes() == 0) - { - ReleaseStreams(); - WriteEndMarker(UInt32(nowPos64) & _posStateMask); - return Flush(); - } + return Flush(nowPos32); + while(true) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif - UInt32 pos; - UInt32 posState = UInt32(nowPos64) & _posStateMask; - - UInt32 len; + UInt32 pos, len; HRESULT result; if (_fastMode) - result = GetOptimumFast(UInt32(nowPos64), pos, len); + result = GetOptimumFast(nowPos32, pos, len); else - result = GetOptimum(UInt32(nowPos64), pos, len); + result = GetOptimum(nowPos32, pos, len); RINOK(result); + UInt32 posState = nowPos32 & _posStateMask; if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); - _state.UpdateChar(); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); - CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte); - if(_peviousIsMatch) + CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); + if(_state.IsCharState()) + subCoder->Encode(&_rangeEncoder, curByte); + else { Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } - else - subCoder->Encode(&_rangeEncoder, curByte); + _state.UpdateChar(); _previousByte = curByte; - _peviousIsMatch = false; } else { - _peviousIsMatch = true; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { @@ -1341,13 +1421,11 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); - if(len == 1) - _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0); - else - _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1); + _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); } else { + UInt32 distance = _repDistances[pos]; _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); @@ -1355,34 +1433,29 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); + if (pos == 3) + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; } + _repDistances[1] = _repDistances[0]; + _repDistances[0] = distance; } if (len == 1) _state.UpdateShortRep(); else { - _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); _state.UpdateRep(); } - - - UInt32 distance = _repDistances[pos]; - if (pos != 0) - { - for(UInt32 i = pos; i >= 1; i--) - _repDistances[i] = _repDistances[i - 1]; - _repDistances[0] = distance; - } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); - _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); - UInt32 lenToPosState = GetLenToPosState(len); - _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); + _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { @@ -1397,39 +1470,35 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); - if (!_fastMode) - if (--_alignPriceCount == 0) - FillAlignPrices(); + _alignPriceCount++; } } - UInt32 distance = pos; - for(UInt32 i = kNumRepDistances - 1; i >= 1; i--) - _repDistances[i] = _repDistances[i - 1]; - _repDistances[0] = distance; + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; + _repDistances[1] = _repDistances[0]; + _repDistances[0] = pos; + _matchPriceCount++; } _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; - nowPos64 += len; - if (!_fastMode) - if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) - { - FillPosSlotPrices(); - FillDistancesPrices(); - lastPosSlotFillingPos = nowPos64; - } + nowPos32 += len; if (_additionalOffset == 0) { - *inSize = nowPos64; - *outSize = _rangeEncoder.GetProcessedSize(); - if (_matchFinder->GetNumAvailableBytes() == 0) + if (!_fastMode) { - ReleaseStreams(); - WriteEndMarker(UInt32(nowPos64) & _posStateMask); - return Flush(); + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= kAlignTableSize) + FillAlignPrices(); } - if (nowPos64 - progressPosValuePrev >= (1 << 12)) + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(nowPos32); + if (nowPos32 - progressPosValuePrev >= (1 << 14)) { + nowPos64 += nowPos32 - progressPosValuePrev; + *inSize = nowPos64; + *outSize = _rangeEncoder.GetProcessedSize(); _finished = false; *finished = 0; return S_OK; @@ -1454,45 +1523,43 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, #endif } -void CEncoder::FillPosSlotPrices() +void CEncoder::FillDistancesPrices() { + UInt32 tempPrices[kNumFullDistances]; + for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + + base - posSlot - 1, footerBits, i - base); + } + for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; - for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++) - _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); - for (; posSlot < _distTableSize; posSlot++) - _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + - ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); - } -} + NRangeCoder::CBitTreeEncoder &encoder = _posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] = encoder.GetPrice(posSlot); + for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); -void CEncoder::FillDistancesPrices() -{ - for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) - { + UInt32 *distancesPrices = _distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) - _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; + distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) - { - UInt32 posSlot = GetPosSlot(i); - UInt32 footerBits = ((posSlot >> 1) - 1); - UInt32 base = ((2 | (posSlot & 1)) << footerBits); - - _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + - NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + - base - posSlot - 1, footerBits, i - base); - - } + distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; } + _matchPriceCount = 0; } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); - _alignPriceCount = kAlignTableSize; + _alignPriceCount = 0; } }} diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h index c6c9708f..f4c2c151 100644 --- a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h @@ -21,13 +21,11 @@ class CBaseState protected: CState _state; Byte _previousByte; - bool _peviousIsMatch; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; - _peviousIsMatch = false; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } @@ -53,23 +51,23 @@ struct COptimal }; -extern Byte g_FastPos[1024]; +extern Byte g_FastPos[1 << 11]; inline UInt32 GetPosSlot(UInt32 pos) { - if (pos < (1 << 10)) + if (pos < (1 << 11)) return g_FastPos[pos]; - if (pos < (1 << 19)) - return g_FastPos[pos >> 9] + 18; - return g_FastPos[pos >> 18] + 36; + if (pos < (1 << 21)) + return g_FastPos[pos >> 10] + 20; + return g_FastPos[pos >> 20] + 40; } inline UInt32 GetPosSlot2(UInt32 pos) { - if (pos < (1 << 16)) + if (pos < (1 << 17)) return g_FastPos[pos >> 6] + 12; - if (pos < (1 << 25)) - return g_FastPos[pos >> 15] + 30; - return g_FastPos[pos >> 24] + 48; + if (pos < (1 << 27)) + return g_FastPos[pos >> 16] + 32; + return g_FastPos[pos >> 26] + 52; } const UInt32 kIfinityPrice = 0xFFFFFFF; @@ -107,8 +105,7 @@ public: } bool Create(int numPosBits, int numPrevBits) { - if (_coders == 0 || (numPosBits + numPrevBits) != - (_numPrevBits + _numPosBits) ) + if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); @@ -125,21 +122,8 @@ public: for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } - UInt32 GetState(UInt32 pos, Byte prevByte) const - { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) - { return &_coders[GetState(pos, prevByte)]; } - /* - void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, - Byte symbol) - { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); } - void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, - Byte matchByte, Byte symbol) - { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, - matchByte, symbol); } - */ - UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const - { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); } + { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } }; namespace NLength { @@ -147,31 +131,29 @@ namespace NLength { class CEncoder { CMyBitEncoder _choice; - NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; - CMyBitEncoder _choice2; - NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; - NRangeCoder::CBitTreeEncoder _highCoder; + CMyBitEncoder _choice2; + NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); - UInt32 GetPrice(UInt32 symbol, UInt32 posState) const; + void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { - UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; + UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } - UInt32 GetPrice(UInt32 symbol, UInt32 posState) const - { return _prices[symbol][posState]; } + UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } void UpdateTable(UInt32 posState) { - for (UInt32 len = 0; len < _tableSize; len++) - _prices[len][posState] = CEncoder::GetPrice(len, posState); + SetPrices(posState, _tableSize, _prices[posState]); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) @@ -179,20 +161,20 @@ public: for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } - void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) + void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) { CEncoder::Encode(rangeEncoder, symbol, posState); - if (--_counters[posState] == 0) - UpdateTable(posState); + if (updatePrice) + if (--_counters[posState] == 0) + UpdateTable(posState); } }; } - class CEncoder : public ICompressCoder, - // public IInitMatchFinder, + public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, @@ -201,8 +183,6 @@ class CEncoder : COptimal _optimum[kNumOpts]; CMyComPtr _matchFinder; // test it NRangeCoder::CEncoder _rangeEncoder; -public: -private: CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; @@ -221,12 +201,13 @@ private: CLiteralEncoder _literalEncoder; - UInt32 _matchDistances[kMatchMaxLen + 1]; + UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; bool _fastMode; - bool _maxMode; + // bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; + UInt32 _numDistancePairs; UInt32 _additionalOffset; @@ -254,11 +235,12 @@ private: UInt32 _dictionarySizePrev; UInt32 _numFastBytesPrev; - UInt64 lastPosSlotFillingPos; + UInt32 _matchPriceCount; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; + UInt32 _matchFinderCycles; int _matchFinderIndex; #ifdef COMPRESS_MF_MT bool _multiThread; @@ -267,36 +249,50 @@ private: bool _writeEndMark; bool _needReleaseMFStream; + + IMatchFinderSetNumPasses *setMfPasses; + + void ReleaseMatchFinder() + { + setMfPasses = 0; + _matchFinder.Release(); + } - HRESULT ReadMatchDistances(UInt32 &len); + HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs); HRESULT MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { - return _isRepG0[state.Index].GetPrice(0) + - _isRep0Long[state.Index][posState].GetPrice(0); + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[state.Index][posState].GetPrice0(); } - UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const + + UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const { - UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState); + UInt32 price; if(repIndex == 0) { - price += _isRepG0[state.Index].GetPrice(0); - price += _isRep0Long[state.Index][posState].GetPrice(1); + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[state.Index][posState].GetPrice1(); } else { - price += _isRepG0[state.Index].GetPrice(1); + price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) - price += _isRepG1[state.Index].GetPrice(0); + price += _isRepG1[state.Index].GetPrice0(); else { - price += _isRepG1[state.Index].GetPrice(1); + price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const + { + return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + + GetPureRepPrice(repIndex, state, posState); + } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { @@ -318,8 +314,6 @@ private: */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { - if (len == 2 && pos >= 0x80) - return kIfinityPrice; UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) @@ -334,21 +328,25 @@ private: HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); - void FillPosSlotPrices(); void FillDistancesPrices(); void FillAlignPrices(); - void ReleaseStreams() + void ReleaseMFStream() { if (_matchFinder && _needReleaseMFStream) { _matchFinder->ReleaseStream(); _needReleaseMFStream = false; } - // _rangeEncoder.ReleaseStream(); } - HRESULT Flush(); + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; @@ -370,13 +368,13 @@ public: HRESULT Create(); - MY_UNKNOWN_IMP2( + MY_UNKNOWN_IMP3( + ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) - STDMETHOD(Init)( - ISequentialOutStream *outStream); + HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, @@ -395,9 +393,6 @@ public: const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - // IInitMatchFinder interface - STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder); - // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); @@ -405,6 +400,9 @@ public: // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + virtual ~CEncoder() {} }; diff --git a/Source/7zip/7zip/Compress/LZMA/StdAfx.h b/Source/7zip/7zip/Compress/LZMA/StdAfx.h index ceced164..e7fb6986 100644 --- a/Source/7zip/7zip/Compress/LZMA/StdAfx.h +++ b/Source/7zip/7zip/Compress/LZMA/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../../Platform.h" +#include "../../../Common/MyWindows.h" -#endif +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h index c50426db..bbb2ba82 100644 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h @@ -14,20 +14,21 @@ const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { - UInt64 Low; - UInt32 Range; - UInt32 _ffNum; + UInt32 _cacheSize; Byte _cache; public: + UInt64 Low; + UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } - void Init(ISequentialOutStream *stream) + void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } + void Init() { - Stream.Init(stream); + Stream.Init(); Low = 0; Range = 0xFFFFFFFF; - _ffNum = 0; + _cacheSize = 1; _cache = 0; } @@ -40,10 +41,7 @@ public: HRESULT FlushStream() { return Stream.Flush(); } - /* - void ReleaseStream() - { Stream.ReleaseStream(); } - */ + void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { @@ -56,36 +54,21 @@ public: } } - /* - void EncodeDirectBitsDiv(UInt32 value, UInt32 numTotalBits) - { - Low += value * (Range >>= numTotalBits); - Normalize(); - } - - void EncodeDirectBitsDiv2(UInt32 value, UInt32 numTotalBits) - { - if (numTotalBits <= kNumBottomBits) - EncodeDirectBitsDiv(value, numTotalBits); - else - { - EncodeDirectBitsDiv(value >> kNumBottomBits, (numTotalBits - kNumBottomBits)); - EncodeDirectBitsDiv(value & ((1 << kBottomValueBits) - 1), kNumBottomBits); - } - } - */ void ShiftLow() { - if (Low < (UInt32)0xFF000000 || UInt32(Low >> 32) == 1) + if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { - Stream.WriteByte(Byte(_cache + Byte(Low >> 32))); - for (;_ffNum != 0; _ffNum--) - Stream.WriteByte(Byte(0xFF + Byte(Low >> 32))); - _cache = Byte(UInt32(Low) >> 24); + Byte temp = _cache; + do + { + Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (Byte)((UInt32)Low >> 24); } - else - _ffNum++; - Low = UInt32(Low) << 8; + _cacheSize++; + Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) @@ -120,7 +103,7 @@ public: } } - UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _ffNum; } + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder @@ -140,16 +123,17 @@ public: } } - void Init(ISequentialInStream *stream) + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void Init() { - Stream.Init(stream); + Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } - // void ReleaseStream() { Stream.ReleaseStream(); } + void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { @@ -163,32 +147,12 @@ public: Normalize(); } - /* - UInt32 DecodeDirectBitsDiv(UInt32 numTotalBits) - { - Range >>= numTotalBits; - UInt32 threshold = Code / Range; - Code -= threshold * Range; - - Normalize(); - return threshold; - } - - UInt32 DecodeDirectBitsDiv2(UInt32 numTotalBits) - { - if (numTotalBits <= kNumBottomBits) - return DecodeDirectBitsDiv(numTotalBits); - UInt32 result = DecodeDirectBitsDiv(numTotalBits - kNumBottomBits) << kNumBottomBits; - return (result | DecodeDirectBitsDiv(kNumBottomBits)); - } - */ - - UInt32 DecodeDirectBits(UInt32 numTotalBits) + UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; - for (UInt32 i = numTotalBits; i > 0; i--) + for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* @@ -201,7 +165,6 @@ public: */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); - // range = rangeTmp + ((range & 1) & (1 - t)); result = (result << 1) | (1 - t); if (range < kTopValue) diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h index cdbe27dc..624f887c 100644 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h @@ -50,9 +50,10 @@ class CBitEncoder: public CBitModel public: void Encode(CEncoder *encoder, UInt32 symbol) { + /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); - /* + */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { @@ -65,18 +66,19 @@ public: encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } - while (encoder->Range < kTopValue) + if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } - */ } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } + UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } + UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h index ccd1f152..4f0c78b4 100644 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h @@ -9,7 +9,7 @@ namespace NCompress { namespace NRangeCoder { -template +template class CBitTreeEncoder { CBitEncoder Models[1 << NumBitLevels]; @@ -22,7 +22,7 @@ public: void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; - for (UInt32 bitIndex = NumBitLevels; bitIndex > 0 ;) + for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; @@ -33,7 +33,7 @@ public: void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; - for (UInt32 i = 0; i < NumBitLevels; i++) + for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); @@ -43,14 +43,12 @@ public: } UInt32 GetPrice(UInt32 symbol) const { + symbol |= (1 << NumBitLevels); UInt32 price = 0; - UInt32 modelIndex = 1; - for (UInt32 bitIndex = NumBitLevels; bitIndex > 0 ;) + while (symbol != 1) { - bitIndex--; - UInt32 bit = (symbol >> bitIndex) & 1; - price += Models[modelIndex].GetPrice(bit); - modelIndex = (modelIndex << 1) + bit; + price += Models[symbol >> 1].GetPrice(symbol & 1); + symbol >>= 1; } return price; } @@ -58,7 +56,7 @@ public: { UInt32 price = 0; UInt32 modelIndex = 1; - for (UInt32 i = NumBitLevels; i > 0; i--) + for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; @@ -69,7 +67,7 @@ public: } }; -template +template class CBitTreeDecoder { CBitDecoder Models[1 << NumBitLevels]; @@ -83,7 +81,7 @@ public: { UInt32 modelIndex = 1; RC_INIT_VAR - for(UInt32 bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) @@ -96,7 +94,7 @@ public: UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR - for(UInt32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; @@ -111,10 +109,10 @@ public: template void ReverseBitTreeEncode(CBitEncoder *Models, - CEncoder *rangeEncoder, UInt32 NumBitLevels, UInt32 symbol) + CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; - for (UInt32 i = 0; i < NumBitLevels; i++) + for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); @@ -129,7 +127,7 @@ UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, { UInt32 price = 0; UInt32 modelIndex = 1; - for (UInt32 i = NumBitLevels; i > 0; i--) + for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; @@ -141,12 +139,12 @@ UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, template UInt32 ReverseBitTreeDecode(CBitDecoder *Models, - CDecoder *rangeDecoder, UInt32 NumBitLevels) + CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR - for(UInt32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; diff --git a/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h index ceced164..b637fd40 100644 --- a/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h +++ b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h @@ -3,6 +3,4 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../../../Platform.h" - -#endif +#endif diff --git a/Source/7zip/7zip/ICoder.h b/Source/7zip/7zip/ICoder.h index 6b81dd29..d84575dc 100644 --- a/Source/7zip/7zip/ICoder.h +++ b/Source/7zip/7zip/ICoder.h @@ -5,33 +5,27 @@ #include "IStream.h" -// {23170F69-40C1-278A-0000-000200040000} -DEFINE_GUID(IID_ICompressProgressInfo, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200040000") -ICompressProgressInfo: public IUnknown +// "23170F69-40C1-278A-0000-000400xx0000" +#define CODER_INTERFACE(i, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ +struct i: public IUnknown + +CODER_INTERFACE(ICompressProgressInfo, 0x04) { - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) = 0; + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; -// {23170F69-40C1-278A-0000-000200050000} -DEFINE_GUID(IID_ICompressCoder, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200050000") -ICompressCoder: public IUnknown +CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) = 0; + ICompressProgressInfo *progress) PURE; }; -// {23170F69-40C1-278A-0000-000200180000} -DEFINE_GUID(IID_ICompressCoder2, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200180000") -ICompressCoder2: public IUnknown +CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, @@ -54,75 +48,100 @@ namespace NCoderPropID kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, + kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, + kNumThreads, kEndMarker = 0x490 }; } -// {23170F69-40C1-278A-0000-000200200000} -DEFINE_GUID(IID_ICompressSetCoderProperties, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200200000") -ICompressSetCoderProperties: public IUnknown +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; -// {23170F69-40C1-278A-0000-000200210000} -DEFINE_GUID(IID_ICompressSetDecoderProperties, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200210000") -ICompressSetDecoderProperties: public IUnknown +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; +*/ -// {23170F69-40C1-278A-0000-000200230000} -DEFINE_GUID(IID_ICompressWriteCoderProperties, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x23, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200230000") -ICompressWriteCoderProperties: public IUnknown +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; -// {23170F69-40C1-278A-0000-000200240000} -DEFINE_GUID(IID_ICompressGetInStreamProcessedSize, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200240000") -ICompressGetInStreamProcessedSize: public IUnknown +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; -// {23170F69-40C1-278A-0000-000200250000} -DEFINE_GUID(IID_ICompressGetSubStreamSize, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200250000") -ICompressGetSubStreamSize: public IUnknown +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; -// {23170F69-40C1-278A-0000-000200260000} -DEFINE_GUID(IID_ICompressSetInStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x26, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200260000") -ICompressSetInStream: public IUnknown +CODER_INTERFACE(ICompressSetInStream, 0x31) { - STDMETHOD(SetInStream)(ISequentialInStream *inStream, const UInt64 *inSize) PURE; + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; }; -// {23170F69-40C1-278A-0000-000200270000} -DEFINE_GUID(IID_ICompressSetOutStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x27, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000200270000") -ICompressSetOutStream: public IUnknown +CODER_INTERFACE(ICompressSetOutStream, 0x32) { - STDMETHOD(SetOutStream)(ISequentialOutStream *outStream, const UInt64 *outSize) PURE; + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + STDMETHOD(Init)() PURE; + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; + // Filter return outSize (UInt32) + // if (outSize <= size): Filter have converted outSize bytes + // if (outSize > size): Filter have not converted anything. + // and it needs at least outSize bytes to convert one block + // (it's for crypto block algorithms). +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// diff --git a/Source/7zip/7zip/IStream.h b/Source/7zip/7zip/IStream.h index 64dab3c5..bba21a31 100644 --- a/Source/7zip/7zip/IStream.h +++ b/Source/7zip/7zip/IStream.h @@ -1,79 +1,62 @@ // IStream.h -#ifndef __ISTREAMS_H -#define __ISTREAMS_H +#ifndef __ISTREAM_H +#define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" -// {23170F69-40C1-278A-0000-000000010000} -DEFINE_GUID(IID_ISequentialInStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000010000") -ISequentialInStream : public IUnknown +// "23170F69-40C1-278A-0000-000300xx0000" + +#define STREAM_INTERFACE_SUB(i, b, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ +struct i: public b + +#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) + +STREAM_INTERFACE(ISequentialInStream, 0x01) { -public: - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) = 0; - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) = 0; - - // For both function Out: if (processedSize == 0) then there are - // no more bytes in stream. - // Read function always tries to read "size" bytes from stream. It - // can read less only if it reaches end of stream. - // ReadPart function can read X bytes: (0<=X<="size") and X can - // be less than number of remaining bytes in stream. + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + Out: if size != 0, return_value = S_OK and (*processedSize == 0), + then there are no more bytes in stream. + if (size > 0) && there are bytes in stream, + this function must read at least 1 byte. + This function is allowed to read less than number of remaining bytes in stream. + You must call Read function in loop, if you need exact amount of data + */ }; -// {23170F69-40C1-278A-0000-000000020000} -DEFINE_GUID(IID_ISequentialOutStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000020000") -ISequentialOutStream : public IUnknown +STREAM_INTERFACE(ISequentialOutStream, 0x02) { -public: - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) = 0; - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) = 0; + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + if (size > 0) this function must write at least 1 byte. + This function is allowed to write less than "size". + You must call Write function in loop, if you need to write exact amount of data + */ }; -// {23170F69-40C1-278A-0000-000000030000} -DEFINE_GUID(IID_IInStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000030000") -IInStream : public ISequentialInStream +STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { -public: - STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) = 0; + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; -// {23170F69-40C1-278A-0000-000000040000} -DEFINE_GUID(IID_IOutStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000040000") -IOutStream : public ISequentialOutStream +STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { -public: - STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) = 0; - STDMETHOD(SetSize)(Int64 newSize) = 0; + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; + STDMETHOD(SetSize)(Int64 newSize) PURE; }; -// {23170F69-40C1-278A-0000-000000060000} -DEFINE_GUID(IID_IStreamGetSize, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000060000") -IStreamGetSize : public IUnknown +STREAM_INTERFACE(IStreamGetSize, 0x06) { -public: - STDMETHOD(GetSize)(UInt64 *size) = 0; + STDMETHOD(GetSize)(UInt64 *size) PURE; }; -// {23170F69-40C1-278A-0000-000000070000} -DEFINE_GUID(IID_IOutStreamFlush, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000070000") -IOutStreamFlush : public IUnknown +STREAM_INTERFACE(IOutStreamFlush, 0x07) { -public: - STDMETHOD(Flush)() = 0; + STDMETHOD(Flush)() PURE; }; #endif diff --git a/Source/7zip/Common/Alloc.cpp b/Source/7zip/Common/Alloc.cpp index 4015d3e5..e2b8c3d2 100644 --- a/Source/7zip/Common/Alloc.cpp +++ b/Source/7zip/Common/Alloc.cpp @@ -2,51 +2,117 @@ #include "StdAfx.h" -#ifndef WIN32 +#ifdef _WIN32 +#include "MyWindows.h" +#else #include #endif #include "Alloc.h" -// #include "NewHandler.h" -void *MyAlloc(size_t size) +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) throw() { + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); + #endif return ::malloc(size); } -void MyFree(void *address) +void MyFree(void *address) throw() { + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d", --g_allocCount); + #endif + ::free(address); } -void *BigAlloc(size_t size) +#ifdef _WIN32 + +void *MidAlloc(size_t size) throw() { - #ifdef WIN32 - return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); - #else - return ::malloc(size); + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } -void BigFree(void *address) +void MidFree(void *address) throw() { + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif if (address == 0) return; - #ifdef WIN32 ::VirtualFree(address, 0, MEM_RELEASE); - #else - ::free(address); - #endif } -/* -void *BigAllocE(size_t size) +static SIZE_T g_LargePageSize = + #ifdef _WIN64 + (1 << 21); + #else + (1 << 22); + #endif + +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); + +bool SetLargePageSize() { - void *res = BigAlloc(size); - #ifndef _NO_EXCEPTIONS - if (res == 0) - throw CNewException(); - #endif - return res; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return false; + SIZE_T size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return false; + g_LargePageSize = size; + return true; } -*/ + + +void *BigAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + if (size >= (1 << 18)) + { + void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + ::VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/Source/7zip/Common/Alloc.h b/Source/7zip/Common/Alloc.h index 881af966..d444f631 100644 --- a/Source/7zip/Common/Alloc.h +++ b/Source/7zip/Common/Alloc.h @@ -5,10 +5,25 @@ #include -void *MyAlloc(size_t size); -void MyFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); -// void *BigAllocE(size_t size); +void *MyAlloc(size_t size) throw(); +void MyFree(void *address) throw(); + +#ifdef _WIN32 + +bool SetLargePageSize(); + +void *MidAlloc(size_t size) throw(); +void MidFree(void *address) throw(); +void *BigAlloc(size_t size) throw(); +void BigFree(void *address) throw(); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif #endif diff --git a/Source/7zip/Common/CRC.cpp b/Source/7zip/Common/CRC.cpp index ab0905bf..35e1a187 100644 --- a/Source/7zip/Common/CRC.cpp +++ b/Source/7zip/Common/CRC.cpp @@ -28,24 +28,30 @@ public: CCRCTableInit() { CCRC::InitTable(); } } g_CRCTableInit; -void CCRC::Update(Byte b) +void CCRC::UpdateByte(Byte b) { _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); } -void CCRC::Update(UInt32 v) +void CCRC::UpdateUInt16(UInt16 v) +{ + UpdateByte(Byte(v)); + UpdateByte(Byte(v >> 8)); +} + +void CCRC::UpdateUInt32(UInt32 v) { for (int i = 0; i < 4; i++) - Update((Byte)(v >> (8 * i))); + UpdateByte((Byte)(v >> (8 * i))); } -void CCRC::Update(const UInt64 &v) +void CCRC::UpdateUInt64(UInt64 v) { for (int i = 0; i < 8; i++) - Update((Byte)(v >> (8 * i))); + UpdateByte((Byte)(v >> (8 * i))); } -void CCRC::Update(const void *data, UInt32 size) +void CCRC::Update(const void *data, size_t size) { UInt32 v = _value; const Byte *p = (const Byte *)data; diff --git a/Source/7zip/Common/CRC.h b/Source/7zip/Common/CRC.h index 01034085..6b4f1b79 100644 --- a/Source/7zip/Common/CRC.h +++ b/Source/7zip/Common/CRC.h @@ -3,6 +3,7 @@ #ifndef __COMMON_CRC_H #define __COMMON_CRC_H +#include #include "Types.h" class CCRC @@ -14,18 +15,19 @@ public: CCRC(): _value(0xFFFFFFFF){}; void Init() { _value = 0xFFFFFFFF; } - void Update(Byte v); - void Update(UInt32 v); - void Update(const UInt64 &v); - void Update(const void *data, UInt32 size); + void UpdateByte(Byte v); + void UpdateUInt16(UInt16 v); + void UpdateUInt32(UInt32 v); + void UpdateUInt64(UInt64 v); + void Update(const void *data, size_t size); UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } - static UInt32 CalculateDigest(const void *data, UInt32 size) + static UInt32 CalculateDigest(const void *data, size_t size) { CCRC crc; crc.Update(data, size); return crc.GetDigest(); } - static bool VerifyDigest(UInt32 digest, const void *data, UInt32 size) + static bool VerifyDigest(UInt32 digest, const void *data, size_t size) { return (CalculateDigest(data, size) == digest); } diff --git a/Source/7zip/Common/MyCom.h b/Source/7zip/Common/MyCom.h index a2788844..e9034930 100644 --- a/Source/7zip/Common/MyCom.h +++ b/Source/7zip/Common/MyCom.h @@ -50,7 +50,7 @@ public: _p = NULL; return pt; } - #ifdef WIN32 + #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); @@ -148,8 +148,10 @@ public: #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { + #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } + #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ @@ -164,7 +166,9 @@ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ MY_ADDREF_RELEASE -#define MY_UNKNOWN_IMP MY_UNKNOWN_IMP_SPEC(;) +#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i) \ @@ -174,11 +178,13 @@ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) + #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) + #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ diff --git a/Source/7zip/Common/MyGuidDef.h b/Source/7zip/Common/MyGuidDef.h new file mode 100644 index 00000000..2c954f81 --- /dev/null +++ b/Source/7zip/Common/MyGuidDef.h @@ -0,0 +1,54 @@ +// Common/MyGuidDef.h + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "Types.h" + +typedef struct { + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +#define REFCLSID REFGUID +#define REFIID REFGUID + +#ifdef __cplusplus +inline bool operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < (int)sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return false; + return true; +} +inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } +#endif + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#endif // GUID_DEFINED + + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif diff --git a/Source/7zip/Common/MyUnknown.h b/Source/7zip/Common/MyUnknown.h index 912ff93e..d28d8542 100644 --- a/Source/7zip/Common/MyUnknown.h +++ b/Source/7zip/Common/MyUnknown.h @@ -3,9 +3,8 @@ #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H -#ifdef WIN32 +#ifdef _WIN32 -// #include #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include diff --git a/Source/7zip/Common/MyWindows.h b/Source/7zip/Common/MyWindows.h index 7181de70..6cb04308 100644 --- a/Source/7zip/Common/MyWindows.h +++ b/Source/7zip/Common/MyWindows.h @@ -3,21 +3,71 @@ #ifndef __MYWINDOWS_H #define __MYWINDOWS_H -#ifndef WIN32 - -#include - #include "../../Platform.h" -#include "Types.h" +#ifdef _WIN32 +#include + +/* +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" +*/ + +#else + +/* +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#include // for wchar_t +#include +*/ +#include "MyGuidDef.h" +/* +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; typedef short VARIANT_BOOL; -typedef wchar_t OLECHAR; +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; - +*/ typedef struct _FILETIME { DWORD dwLowDateTime; @@ -31,6 +81,7 @@ typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) @@ -51,46 +102,7 @@ typedef LONG SCODE; #define PURE = 0 -typedef struct { - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -} GUID; - -#ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern -#endif - -#ifdef INITGUID - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#else - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - MY_EXTERN_C const GUID name -#endif - -#ifdef __cplusplus -#define REFGUID const GUID & -#else -#define REFGUID const GUID * __MIDL_CONST -#endif - -#define REFCLSID REFGUID -#define REFIID REFGUID - #define MIDL_INTERFACE(x) struct -inline bool operator==(REFGUID g1, REFGUID g2) -{ - for (size_t i = 0; i < sizeof(g1); i++) - if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) - return false; - return true; -} -inline bool operator!=(REFGUID g1, REFGUID g2) - { return !(g1 == g2); } struct IUnknown { @@ -164,20 +176,20 @@ typedef struct tagPROPVARIANT }; } PROPVARIANT; -typedef tagPROPVARIANT tagVARIANT; +typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; -BSTR SysAllocStringByteLen(LPCSTR psz, unsigned int len); -BSTR SysAllocString(const OLECHAR *sz); -void SysFreeString(BSTR bstr); -UINT SysStringByteLen(BSTR bstr); -UINT SysStringLen(BSTR bstr); +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); -DWORD GetLastError(); -HRESULT VariantClear(VARIANTARG *prop); -HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); -LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 diff --git a/Source/7zip/Common/StdAfx.h b/Source/7zip/Common/StdAfx.h index 359dcee7..38c17215 100644 --- a/Source/7zip/Common/StdAfx.h +++ b/Source/7zip/Common/StdAfx.h @@ -3,6 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../../Platform.h" +// #include "MyWindows.h" #endif diff --git a/Source/7zip/Common/Types.h b/Source/7zip/Common/Types.h index 0bf66e08..41d785e9 100644 --- a/Source/7zip/Common/Types.h +++ b/Source/7zip/Common/Types.h @@ -3,17 +3,55 @@ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_INT16_DEFINED +#define _7ZIP_INT16_DEFINED typedef short Int16; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_INT32_DEFINED +#define _7ZIP_INT32_DEFINED typedef int Int32; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED typedef unsigned int UInt32; +#endif + #ifdef _MSC_VER + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED typedef __int64 Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED typedef unsigned __int64 UInt64; +#endif + #else + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED typedef long long int Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED typedef unsigned long long int UInt64; +#endif + #endif #endif diff --git a/Source/7zip/sdk.diff b/Source/7zip/sdk.diff new file mode 100644 index 00000000..647ed11c --- /dev/null +++ b/Source/7zip/sdk.diff @@ -0,0 +1,167 @@ +Only in 7zip: 7zGuids.cpp +Only in 7zip-orig/7zip: Archive +Only in 7zip/7zip: CVS +Only in 7zip/7zip/Common: CVS +Only in 7zip-orig/7zip/Common: FileStreams.cpp +Only in 7zip-orig/7zip/Common: FileStreams.h +diff -ru 7zip-orig/7zip/Common/StdAfx.h 7zip/7zip/Common/StdAfx.h +--- 7zip-orig/7zip/Common/StdAfx.h Mon Jul 11 15:14:54 2005 ++++ 7zip/7zip/Common/StdAfx.h Mon Oct 16 10:39:10 2006 +@@ -4,6 +4,5 @@ + #define __STDAFX_H + + #include "../../Common/MyWindows.h" +-#include "../../Common/NewHandler.h" + + #endif +Only in 7zip-orig/7zip/Compress: Branch +Only in 7zip/7zip/Compress: CVS +Only in 7zip/7zip/Compress/LZ/BinTree: BinTree3ZMain.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTree4b.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMF.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMFMain.h +Only in 7zip/7zip/Compress/LZ/BinTree: CVS +Only in 7zip/7zip/Compress/LZ: CVS +Only in 7zip-orig/7zip/Compress/LZ: HashChain +Only in 7zip/7zip/Compress/LZMA: CVS +Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.cpp +Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.h +diff -ru 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp +--- 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp Sat May 20 08:23:48 2006 ++++ 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp Mon Oct 16 10:26:43 2006 +@@ -55,13 +55,13 @@ + kHC4 + }; + +-static const wchar_t *kMatchFinderIDs[] = ++/*static const wchar_t *kMatchFinderIDs[] = + { + L"BT2", + L"BT3", + L"BT4", + L"HC4" +-}; ++};*/ + + Byte g_FastPos[1 << 11]; + +@@ -318,7 +318,7 @@ + return S_OK; + } + +-static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) ++/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) + { + while (true) + { +@@ -340,7 +340,7 @@ + if (AreStringsEqual(kMatchFinderIDs[m], s)) + return m; + return -1; +-} ++}*/ + + STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) +@@ -378,7 +378,8 @@ + } + case NCoderPropID::kMatchFinder: + { +- if (prop.vt != VT_BSTR) ++ return E_NOTIMPL; ++ /*if (prop.vt != VT_BSTR) + return E_INVALIDARG; + int matchFinderIndexPrev = _matchFinderIndex; + int m = FindMatchFinder(prop.bstrVal); +@@ -390,7 +391,7 @@ + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + } +- break; ++ break;*/ + } + #ifdef COMPRESS_MF_MT + case NCoderPropID::kMultiThread: +Only in 7zip-orig/7zip/Compress: LZMA_Alone +Only in 7zip-orig/7zip/Compress: LZMA_C +Only in 7zip/7zip/Compress/RangeCoder: CVS +Only in 7zip: CVS +Only in 7zip/Common: CVS +Only in 7zip-orig/Common: C_FileIO.cpp +Only in 7zip-orig/Common: C_FileIO.h +Only in 7zip-orig/Common: ComTry.h +Only in 7zip-orig/Common: CommandLineParser.cpp +Only in 7zip-orig/Common: CommandLineParser.h +Only in 7zip-orig/Common: MyInitGuid.h +diff -ru 7zip-orig/Common/MyWindows.h 7zip/Common/MyWindows.h +--- 7zip-orig/Common/MyWindows.h Sun Apr 16 16:53:43 2006 ++++ 7zip/Common/MyWindows.h Mon Oct 16 10:20:04 2006 +@@ -3,17 +3,22 @@ + #ifndef __MYWINDOWS_H + #define __MYWINDOWS_H + ++#include "../../Platform.h" ++ + #ifdef _WIN32 + + #include + ++/* + #define CHAR_PATH_SEPARATOR '\\' + #define WCHAR_PATH_SEPARATOR L'\\' + #define STRING_PATH_SEPARATOR "\\" + #define WSTRING_PATH_SEPARATOR L"\\" ++*/ + + #else + ++/* + #define CHAR_PATH_SEPARATOR '/' + #define WCHAR_PATH_SEPARATOR L'/' + #define STRING_PATH_SEPARATOR "/" +@@ -21,9 +26,9 @@ + + #include // for wchar_t + #include +- ++*/ + #include "MyGuidDef.h" +- ++/* + typedef char CHAR; + typedef unsigned char UCHAR; + +@@ -62,7 +67,7 @@ + typedef OLECHAR *BSTR; + typedef const OLECHAR *LPCOLESTR; + typedef OLECHAR *LPOLESTR; +- ++*/ + typedef struct _FILETIME + { + DWORD dwLowDateTime; +Only in 7zip-orig/Common: NewHandler.cpp +Only in 7zip-orig/Common: NewHandler.h +diff -ru 7zip-orig/Common/StdAfx.h 7zip/Common/StdAfx.h +--- 7zip-orig/Common/StdAfx.h Mon Jul 11 15:16:00 2005 ++++ 7zip/Common/StdAfx.h Mon Oct 16 10:39:16 2006 +@@ -4,6 +4,5 @@ + #define __STDAFX_H + + // #include "MyWindows.h" +-#include "NewHandler.h" + + #endif +Only in 7zip-orig/Common: String.cpp +Only in 7zip-orig/Common: String.h +Only in 7zip-orig/Common: StringConvert.cpp +Only in 7zip-orig/Common: StringConvert.h +Only in 7zip-orig/Common: StringToInt.cpp +Only in 7zip-orig/Common: StringToInt.h +Only in 7zip-orig/Common: Vector.cpp +Only in 7zip-orig/Common: Vector.h +Only in 7zip: LZMADecode.c +Only in 7zip: LZMADecode.h +Only in 7zip-orig: Windows +Only in 7zip: copying.txt +Only in 7zip: readme.txt diff --git a/Source/Platform.h b/Source/Platform.h index ca9067a3..fd0327c9 100644 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -28,13 +28,14 @@ typedef unsigned long ULONG; typedef long long INT64, LARGE_INTEGER; typedef unsigned long long UINT64, ULARGE_INTEGER; typedef int BOOL, *LPBOOL; +typedef short VARIANT_BOOL; typedef void VOID; typedef void *LPVOID; typedef char CHAR, *PCHAR, *LPCH, *PCH, *NPSTR, *LPSTR, *PSTR; typedef unsigned char UCHAR; typedef const char *LPCCH, *PCSTR, *LPCSTR; -typedef unsigned short WCHAR, *PWCHAR, *LPWCH, *PWCH, *NWPSTR, *LPWSTR, *PWSTR; -typedef const unsigned short *LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR; +typedef unsigned short WCHAR, OLECHAR, *PWCHAR, *LPWCH, *PWCH, *NWPSTR, *LPWSTR, *PWSTR, *BSTR; +typedef const unsigned short *LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR, *LPCOLESTR; typedef unsigned int UINT_PTR; // basic stuff typedef void * HANDLE; diff --git a/Source/SConscript b/Source/SConscript index 9802f809..7e69c0f2 100644 --- a/Source/SConscript +++ b/Source/SConscript @@ -35,12 +35,13 @@ bzip2_files = Split(""" lzma_files = Split(""" 7zip/7zGuids.cpp - 7zip/Common/CRC.cpp + 7zip/7zip/Common/OutBuffer.cpp + 7zip/7zip/Common/StreamUtils.cpp 7zip/7zip/Compress/LZ/LZInWindow.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp - 7zip/7zip/Common/OutBuffer.cpp 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp 7zip/Common/Alloc.cpp + 7zip/Common/CRC.cpp """) zlib_files = Split("""