--- /dev/null
+// InBuffer.h\r
+\r
+#ifndef __INBUFFER_H\r
+#define __INBUFFER_H\r
+\r
+#include "../IStream.h"\r
+#include "../../Common/MyCom.h"\r
+\r
+#ifndef _NO_EXCEPTIONS\r
+class CInBufferException\r
+{\r
+public:\r
+ HRESULT ErrorCode;\r
+ CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {}\r
+};\r
+#endif\r
+\r
+class CInBuffer\r
+{\r
+ Byte *_buffer;\r
+ Byte *_bufferLimit;\r
+ Byte *_bufferBase;\r
+ CMyComPtr<ISequentialInStream> _stream;\r
+ UInt64 _processedSize;\r
+ UInt32 _bufferSize;\r
+ bool _wasFinished;\r
+\r
+ bool ReadBlock();\r
+ Byte ReadBlock2();\r
+\r
+public:\r
+ #ifdef _NO_EXCEPTIONS\r
+ HRESULT ErrorCode;\r
+ #endif\r
+\r
+ CInBuffer();\r
+ ~CInBuffer() { Free(); }\r
+\r
+ bool Create(UInt32 bufferSize);\r
+ void Free();\r
+ \r
+ void SetStream(ISequentialInStream *stream);\r
+ void Init();\r
+ void ReleaseStream() { _stream.Release(); }\r
+\r
+ bool ReadByte(Byte &b)\r
+ {\r
+ if(_buffer >= _bufferLimit)\r
+ if(!ReadBlock())\r
+ return false;\r
+ b = *_buffer++;\r
+ return true;\r
+ }\r
+ Byte ReadByte()\r
+ {\r
+ if(_buffer >= _bufferLimit)\r
+ return ReadBlock2();\r
+ return *_buffer++;\r
+ }\r
+ void ReadBytes(void *data, UInt32 size, UInt32 &processedSize)\r
+ {\r
+ for(processedSize = 0; processedSize < size; processedSize++)\r
+ if (!ReadByte(((Byte *)data)[processedSize]))\r
+ return;\r
+ }\r
+ bool ReadBytes(void *data, UInt32 size)\r
+ {\r
+ UInt32 processedSize;\r
+ ReadBytes(data, size, processedSize);\r
+ return (processedSize == size);\r
+ }\r
+ UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }\r
+ bool WasFinished() const { return _wasFinished; }\r
+};\r
+\r
+#endif\r
--- /dev/null
+// OutByte.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "OutBuffer.h"\r
+\r
+#include "../../Common/Alloc.h"\r
+\r
+bool COutBuffer::Create(UInt32 bufferSize)\r
+{\r
+ const UInt32 kMinBlockSize = 1;\r
+ if (bufferSize < kMinBlockSize)\r
+ bufferSize = kMinBlockSize;\r
+ if (_buffer != 0 && _bufferSize == bufferSize)\r
+ return true;\r
+ Free();\r
+ _bufferSize = bufferSize;\r
+ _buffer = (Byte *)::MidAlloc(bufferSize);\r
+ return (_buffer != 0);\r
+}\r
+\r
+void COutBuffer::Free()\r
+{\r
+ ::MidFree(_buffer);\r
+ _buffer = 0;\r
+}\r
+\r
+void COutBuffer::SetStream(ISequentialOutStream *stream)\r
+{\r
+ _stream = stream;\r
+}\r
+\r
+void COutBuffer::Init()\r
+{\r
+ _streamPos = 0;\r
+ _limitPos = _bufferSize;\r
+ _pos = 0;\r
+ _processedSize = 0;\r
+ _overDict = false;\r
+ #ifdef _NO_EXCEPTIONS\r
+ ErrorCode = S_OK;\r
+ #endif\r
+}\r
+\r
+UInt64 COutBuffer::GetProcessedSize() const\r
+{ \r
+ UInt64 res = _processedSize + _pos - _streamPos;\r
+ if (_streamPos > _pos) \r
+ res += _bufferSize;\r
+ return res;\r
+}\r
+\r
+\r
+HRESULT COutBuffer::FlushPart()\r
+{\r
+ // _streamPos < _bufferSize\r
+ UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);\r
+ HRESULT result = S_OK;\r
+ #ifdef _NO_EXCEPTIONS\r
+ result = ErrorCode;\r
+ #endif\r
+ if (_buffer2 != 0)\r
+ {\r
+ memmove(_buffer2, _buffer + _streamPos, size);\r
+ _buffer2 += size;\r
+ }\r
+\r
+ if (_stream != 0\r
+ #ifdef _NO_EXCEPTIONS\r
+ && (ErrorCode == S_OK)\r
+ #endif\r
+ )\r
+ {\r
+ UInt32 processedSize = 0;\r
+ result = _stream->Write(_buffer + _streamPos, size, &processedSize);\r
+ size = processedSize;\r
+ }\r
+ _streamPos += size;\r
+ if (_streamPos == _bufferSize)\r
+ _streamPos = 0;\r
+ if (_pos == _bufferSize)\r
+ {\r
+ _overDict = true;\r
+ _pos = 0;\r
+ }\r
+ _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;\r
+ _processedSize += size;\r
+ return result;\r
+}\r
+\r
+HRESULT COutBuffer::Flush()\r
+{\r
+ #ifdef _NO_EXCEPTIONS\r
+ if (ErrorCode != S_OK)\r
+ return ErrorCode;\r
+ #endif\r
+\r
+ while(_streamPos != _pos)\r
+ {\r
+ HRESULT result = FlushPart();\r
+ if (result != S_OK)\r
+ return result;\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+void COutBuffer::FlushWithCheck()\r
+{\r
+ HRESULT result = FlushPart();\r
+ #ifdef _NO_EXCEPTIONS\r
+ ErrorCode = result;\r
+ #else\r
+ if (result != S_OK)\r
+ throw COutBufferException(result);\r
+ #endif\r
+}\r
--- /dev/null
+// OutBuffer.h\r
+\r
+#ifndef __OUTBUFFER_H\r
+#define __OUTBUFFER_H\r
+\r
+#include "../IStream.h"\r
+#include "../../Common/MyCom.h"\r
+\r
+#ifndef _NO_EXCEPTIONS\r
+struct COutBufferException\r
+{\r
+ HRESULT ErrorCode;\r
+ COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {}\r
+};\r
+#endif\r
+\r
+class COutBuffer\r
+{\r
+protected:\r
+ Byte *_buffer;\r
+ UInt32 _pos;\r
+ UInt32 _limitPos;\r
+ UInt32 _streamPos;\r
+ UInt32 _bufferSize;\r
+ CMyComPtr<ISequentialOutStream> _stream;\r
+ UInt64 _processedSize;\r
+ Byte *_buffer2;\r
+ bool _overDict;\r
+\r
+ HRESULT FlushPart();\r
+ void FlushWithCheck();\r
+public:\r
+ #ifdef _NO_EXCEPTIONS\r
+ HRESULT ErrorCode;\r
+ #endif\r
+\r
+ COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}\r
+ ~COutBuffer() { Free(); }\r
+ \r
+ bool Create(UInt32 bufferSize);\r
+ void Free();\r
+\r
+ void SetMemStream(Byte *buffer) { _buffer2 = buffer; }\r
+ void SetStream(ISequentialOutStream *stream);\r
+ void Init();\r
+ HRESULT Flush();\r
+ void ReleaseStream() { _stream.Release(); }\r
+\r
+ void WriteByte(Byte b)\r
+ {\r
+ _buffer[_pos++] = b;\r
+ if(_pos == _limitPos)\r
+ FlushWithCheck();\r
+ }\r
+ void WriteBytes(const void *data, size_t size)\r
+ {\r
+ for (size_t i = 0; i < size; i++)\r
+ WriteByte(((const Byte *)data)[i]);\r
+ }\r
+\r
+ UInt64 GetProcessedSize() const;\r
+};\r
+\r
+#endif\r
--- /dev/null
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+#include "../../Common/NewHandler.h"\r
+\r
+#endif \r
--- /dev/null
+// StreamUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "StreamUtils.h"\r
+\r
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+ if (processedSize != 0)\r
+ *processedSize = 0;\r
+ while(size != 0)\r
+ {\r
+ UInt32 processedSizeLoc; \r
+ HRESULT res = stream->Read(data, size, &processedSizeLoc);\r
+ if (processedSize != 0)\r
+ *processedSize += processedSizeLoc;\r
+ data = (Byte *)((Byte *)data + processedSizeLoc);\r
+ size -= processedSizeLoc;\r
+ RINOK(res);\r
+ if (processedSizeLoc == 0)\r
+ return S_OK;\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+ if (processedSize != 0)\r
+ *processedSize = 0;\r
+ while(size != 0)\r
+ {\r
+ UInt32 processedSizeLoc; \r
+ HRESULT res = stream->Write(data, size, &processedSizeLoc);\r
+ if (processedSize != 0)\r
+ *processedSize += processedSizeLoc;\r
+ data = (const void *)((const Byte *)data + processedSizeLoc);\r
+ size -= processedSizeLoc;\r
+ RINOK(res);\r
+ if (processedSizeLoc == 0)\r
+ break;\r
+ }\r
+ return S_OK;\r
+}\r
--- /dev/null
+// StreamUtils.h\r
+\r
+#ifndef __STREAMUTILS_H\r
+#define __STREAMUTILS_H\r
+\r
+#include "../IStream.h"\r
+\r
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize);\r
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+#endif\r
--- /dev/null
+// BinTree.h\r
+\r
+#include "../LZInWindow.h"\r
+#include "../IMatchFinder.h"\r
+ \r
+namespace BT_NAMESPACE {\r
+\r
+typedef UInt32 CIndex;\r
+const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;\r
+\r
+class CMatchFinder: \r
+ public IMatchFinder,\r
+ public CLZInWindow,\r
+ public CMyUnknownImp,\r
+ public IMatchFinderSetNumPasses\r
+{\r
+ UInt32 _cyclicBufferPos;\r
+ UInt32 _cyclicBufferSize; // it must be historySize + 1\r
+ UInt32 _matchMaxLen;\r
+ CIndex *_hash;\r
+ CIndex *_son;\r
+ UInt32 _hashMask;\r
+ UInt32 _cutValue;\r
+ UInt32 _hashSizeSum;\r
+\r
+ void Normalize();\r
+ void FreeThisClassMemory();\r
+ void FreeMemory();\r
+\r
+ MY_UNKNOWN_IMP\r
+\r
+ STDMETHOD(SetStream)(ISequentialInStream *inStream);\r
+ STDMETHOD_(void, ReleaseStream)();\r
+ STDMETHOD(Init)();\r
+ HRESULT MovePos();\r
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index);\r
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);\r
+ STDMETHOD_(UInt32, GetNumAvailableBytes)();\r
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)();\r
+ STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes);\r
+ STDMETHOD_(void, ChangeBufferPos)();\r
+\r
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, \r
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);\r
+ STDMETHOD(GetMatches)(UInt32 *distances);\r
+ STDMETHOD(Skip)(UInt32 num);\r
+\r
+public:\r
+ CMatchFinder();\r
+ virtual ~CMatchFinder();\r
+ virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; }\r
+};\r
+\r
+}\r
--- /dev/null
+// BinTree2.h\r
+\r
+#ifndef __BINTREE2_H\r
+#define __BINTREE2_H\r
+\r
+#define BT_NAMESPACE NBT2\r
+\r
+#include "BinTreeMain.h"\r
+\r
+#undef BT_NAMESPACE\r
+\r
+#endif\r
--- /dev/null
+// BinTree3.h\r
+\r
+#ifndef __BINTREE3_H\r
+#define __BINTREE3_H\r
+\r
+#define BT_NAMESPACE NBT3\r
+\r
+#define HASH_ARRAY_2\r
+\r
+#include "BinTreeMain.h"\r
+\r
+#undef HASH_ARRAY_2\r
+\r
+#undef BT_NAMESPACE\r
+\r
+#endif\r
--- /dev/null
+// BinTree4.h\r
+\r
+#ifndef __BINTREE4_H\r
+#define __BINTREE4_H\r
+\r
+#define BT_NAMESPACE NBT4\r
+\r
+#define HASH_ARRAY_2\r
+#define HASH_ARRAY_3\r
+\r
+#include "BinTreeMain.h"\r
+\r
+#undef HASH_ARRAY_2\r
+#undef HASH_ARRAY_3\r
+\r
+#undef BT_NAMESPACE\r
+\r
+#endif\r
--- /dev/null
+// BinTreeMain.h\r
+\r
+#include "../../../../Common/Defs.h"\r
+#include "../../../../Common/CRC.h"\r
+#include "../../../../Common/Alloc.h"\r
+\r
+#include "BinTree.h"\r
+\r
+// #include <xmmintrin.h>\r
+// It's for prefetch\r
+// But prefetch doesn't give big gain in K8.\r
+\r
+namespace BT_NAMESPACE {\r
+\r
+#ifdef HASH_ARRAY_2\r
+ static const UInt32 kHash2Size = 1 << 10;\r
+ #define kNumHashDirectBytes 0\r
+ #ifdef HASH_ARRAY_3\r
+ static const UInt32 kNumHashBytes = 4;\r
+ static const UInt32 kHash3Size = 1 << 16;\r
+ #else\r
+ static const UInt32 kNumHashBytes = 3;\r
+ #endif\r
+ static const UInt32 kHashSize = 0;\r
+ static const UInt32 kMinMatchCheck = kNumHashBytes;\r
+ static const UInt32 kStartMaxLen = 1;\r
+#else\r
+ #ifdef HASH_ZIP \r
+ #define kNumHashDirectBytes 0\r
+ static const UInt32 kNumHashBytes = 3;\r
+ static const UInt32 kHashSize = 1 << 16;\r
+ static const UInt32 kMinMatchCheck = kNumHashBytes;\r
+ static const UInt32 kStartMaxLen = 1;\r
+ #else\r
+ #define kNumHashDirectBytes 2\r
+ static const UInt32 kNumHashBytes = 2;\r
+ static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);\r
+ static const UInt32 kMinMatchCheck = kNumHashBytes + 1;\r
+ static const UInt32 kStartMaxLen = 1;\r
+ #endif\r
+#endif\r
+\r
+#ifdef HASH_ARRAY_2\r
+#ifdef HASH_ARRAY_3\r
+static const UInt32 kHash3Offset = kHash2Size;\r
+#endif\r
+#endif\r
+\r
+static const UInt32 kFixHashSize = 0\r
+ #ifdef HASH_ARRAY_2\r
+ + kHash2Size\r
+ #ifdef HASH_ARRAY_3\r
+ + kHash3Size\r
+ #endif\r
+ #endif\r
+ ;\r
+\r
+CMatchFinder::CMatchFinder():\r
+ _hash(0)\r
+{\r
+}\r
+\r
+void CMatchFinder::FreeThisClassMemory()\r
+{\r
+ BigFree(_hash);\r
+ _hash = 0;\r
+}\r
+\r
+void CMatchFinder::FreeMemory()\r
+{\r
+ FreeThisClassMemory();\r
+ CLZInWindow::Free();\r
+}\r
+\r
+CMatchFinder::~CMatchFinder()\r
+{ \r
+ FreeMemory();\r
+}\r
+\r
+STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, \r
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)\r
+{\r
+ if (historySize > kMaxValForNormalize - 256)\r
+ {\r
+ FreeMemory();\r
+ return E_INVALIDARG;\r
+ }\r
+ _cutValue = \r
+ #ifdef _HASH_CHAIN\r
+ 8 + (matchMaxLen >> 2);\r
+ #else\r
+ 16 + (matchMaxLen >> 1);\r
+ #endif\r
+ UInt32 sizeReserv = (historySize + keepAddBufferBefore + \r
+ matchMaxLen + keepAddBufferAfter) / 2 + 256;\r
+ if (CLZInWindow::Create(historySize + keepAddBufferBefore, \r
+ matchMaxLen + keepAddBufferAfter, sizeReserv))\r
+ {\r
+ _matchMaxLen = matchMaxLen;\r
+ UInt32 newCyclicBufferSize = historySize + 1;\r
+ if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)\r
+ return S_OK;\r
+ FreeThisClassMemory();\r
+ _cyclicBufferSize = newCyclicBufferSize; // don't change it\r
+\r
+ UInt32 hs = kHashSize;\r
+\r
+ #ifdef HASH_ARRAY_2\r
+ hs = historySize - 1;\r
+ hs |= (hs >> 1);\r
+ hs |= (hs >> 2);\r
+ hs |= (hs >> 4);\r
+ hs |= (hs >> 8);\r
+ hs >>= 1;\r
+ hs |= 0xFFFF;\r
+ if (hs > (1 << 24))\r
+ {\r
+ #ifdef HASH_ARRAY_3\r
+ hs >>= 1;\r
+ #else\r
+ hs = (1 << 24) - 1;\r
+ #endif\r
+ }\r
+ _hashMask = hs;\r
+ hs++;\r
+ #endif\r
+ _hashSizeSum = hs + kFixHashSize;\r
+ UInt32 numItems = _hashSizeSum + _cyclicBufferSize\r
+ #ifndef _HASH_CHAIN\r
+ * 2\r
+ #endif\r
+ ;\r
+ size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);\r
+ if (sizeInBytes / sizeof(CIndex) != numItems)\r
+ return E_OUTOFMEMORY;\r
+ _hash = (CIndex *)BigAlloc(sizeInBytes);\r
+ _son = _hash + _hashSizeSum;\r
+ if (_hash != 0)\r
+ return S_OK;\r
+ }\r
+ FreeMemory();\r
+ return E_OUTOFMEMORY;\r
+}\r
+\r
+static const UInt32 kEmptyHashValue = 0;\r
+\r
+STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)\r
+{\r
+ CLZInWindow::SetStream(stream);\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP CMatchFinder::Init()\r
+{\r
+ RINOK(CLZInWindow::Init());\r
+ for(UInt32 i = 0; i < _hashSizeSum; i++)\r
+ _hash[i] = kEmptyHashValue;\r
+ _cyclicBufferPos = 0;\r
+ ReduceOffsets(-1);\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(void) CMatchFinder::ReleaseStream()\r
+{ \r
+ // ReleaseStream(); \r
+}\r
+\r
+#ifdef HASH_ARRAY_2\r
+#ifdef HASH_ARRAY_3\r
+\r
+#define HASH_CALC { \\r
+ UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \\r
+ hash2Value = temp & (kHash2Size - 1); \\r
+ hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \\r
+ hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }\r
+ \r
+#else // no HASH_ARRAY_3\r
+#define HASH_CALC { \\r
+ UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \\r
+ hash2Value = temp & (kHash2Size - 1); \\r
+ hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }\r
+#endif // HASH_ARRAY_3\r
+#else // no HASH_ARRAY_2\r
+#ifdef HASH_ZIP \r
+inline UInt32 Hash(const Byte *pointer)\r
+{\r
+ return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);\r
+}\r
+#else // no HASH_ZIP \r
+inline UInt32 Hash(const Byte *pointer)\r
+{\r
+ return pointer[0] ^ (UInt32(pointer[1]) << 8);\r
+}\r
+#endif // HASH_ZIP\r
+#endif // HASH_ARRAY_2\r
+\r
+STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)\r
+{\r
+ UInt32 lenLimit;\r
+ if (_pos + _matchMaxLen <= _streamPos)\r
+ lenLimit = _matchMaxLen;\r
+ else\r
+ {\r
+ lenLimit = _streamPos - _pos;\r
+ if(lenLimit < kMinMatchCheck)\r
+ {\r
+ distances[0] = 0;\r
+ return MovePos(); \r
+ }\r
+ }\r
+\r
+ int offset = 1;\r
+\r
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\r
+ const Byte *cur = _buffer + _pos;\r
+\r
+ UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;\r
+\r
+ #ifdef HASH_ARRAY_2\r
+ UInt32 hash2Value;\r
+ #ifdef HASH_ARRAY_3\r
+ UInt32 hash3Value;\r
+ #endif\r
+ UInt32 hashValue;\r
+ HASH_CALC;\r
+ #else\r
+ UInt32 hashValue = Hash(cur);\r
+ #endif\r
+\r
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];\r
+ #ifdef HASH_ARRAY_2\r
+ UInt32 curMatch2 = _hash[hash2Value];\r
+ #ifdef HASH_ARRAY_3\r
+ UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];\r
+ #endif\r
+ _hash[hash2Value] = _pos;\r
+ if(curMatch2 > matchMinPos)\r
+ if (_buffer[curMatch2] == cur[0])\r
+ {\r
+ distances[offset++] = maxLen = 2;\r
+ distances[offset++] = _pos - curMatch2 - 1;\r
+ }\r
+\r
+ #ifdef HASH_ARRAY_3\r
+ _hash[kHash3Offset + hash3Value] = _pos;\r
+ if(curMatch3 > matchMinPos)\r
+ if (_buffer[curMatch3] == cur[0])\r
+ {\r
+ if (curMatch3 == curMatch2)\r
+ offset -= 2;\r
+ distances[offset++] = maxLen = 3;\r
+ distances[offset++] = _pos - curMatch3 - 1;\r
+ curMatch2 = curMatch3;\r
+ }\r
+ #endif\r
+ if (offset != 1 && curMatch2 == curMatch)\r
+ {\r
+ offset -= 2;\r
+ maxLen = kStartMaxLen;\r
+ }\r
+ #endif\r
+\r
+ _hash[kFixHashSize + hashValue] = _pos;\r
+\r
+ CIndex *son = _son;\r
+\r
+ #ifdef _HASH_CHAIN\r
+ son[_cyclicBufferPos] = curMatch;\r
+ #else\r
+ CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
+ CIndex *ptr1 = son + (_cyclicBufferPos << 1);\r
+\r
+ UInt32 len0, len1;\r
+ len0 = len1 = kNumHashDirectBytes;\r
+ #endif\r
+\r
+ #if kNumHashDirectBytes != 0\r
+ if(curMatch > matchMinPos)\r
+ {\r
+ if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])\r
+ {\r
+ distances[offset++] = maxLen = kNumHashDirectBytes;\r
+ distances[offset++] = _pos - curMatch - 1;\r
+ }\r
+ }\r
+ #endif\r
+ UInt32 count = _cutValue;\r
+ while(true)\r
+ {\r
+ if(curMatch <= matchMinPos || count-- == 0)\r
+ {\r
+ #ifndef _HASH_CHAIN\r
+ *ptr0 = *ptr1 = kEmptyHashValue;\r
+ #endif\r
+ break;\r
+ }\r
+ UInt32 delta = _pos - curMatch;\r
+ UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?\r
+ (_cyclicBufferPos - delta):\r
+ (_cyclicBufferPos - delta + _cyclicBufferSize);\r
+ CIndex *pair = son + \r
+ #ifdef _HASH_CHAIN\r
+ cyclicPos;\r
+ #else\r
+ (cyclicPos << 1);\r
+ #endif\r
+ \r
+ // _mm_prefetch((const char *)pair, _MM_HINT_T0);\r
+ \r
+ const Byte *pb = _buffer + curMatch;\r
+ UInt32 len = \r
+ #ifdef _HASH_CHAIN\r
+ kNumHashDirectBytes;\r
+ if (pb[maxLen] == cur[maxLen])\r
+ #else\r
+ MyMin(len0, len1);\r
+ #endif\r
+ if (pb[len] == cur[len])\r
+ {\r
+ while(++len != lenLimit)\r
+ if (pb[len] != cur[len])\r
+ break;\r
+ if (maxLen < len)\r
+ {\r
+ distances[offset++] = maxLen = len;\r
+ distances[offset++] = delta - 1;\r
+ if (len == lenLimit)\r
+ {\r
+ #ifndef _HASH_CHAIN\r
+ *ptr1 = pair[0];\r
+ *ptr0 = pair[1];\r
+ #endif\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ #ifdef _HASH_CHAIN\r
+ curMatch = *pair;\r
+ #else\r
+ if (pb[len] < cur[len])\r
+ {\r
+ *ptr1 = curMatch;\r
+ ptr1 = pair + 1;\r
+ curMatch = *ptr1;\r
+ len1 = len;\r
+ }\r
+ else\r
+ {\r
+ *ptr0 = curMatch;\r
+ ptr0 = pair;\r
+ curMatch = *ptr0;\r
+ len0 = len;\r
+ }\r
+ #endif\r
+ }\r
+ distances[0] = offset - 1;\r
+ if (++_cyclicBufferPos == _cyclicBufferSize)\r
+ _cyclicBufferPos = 0;\r
+ RINOK(CLZInWindow::MovePos());\r
+ if (_pos == kMaxValForNormalize)\r
+ Normalize();\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP CMatchFinder::Skip(UInt32 num)\r
+{\r
+ do\r
+ {\r
+ #ifdef _HASH_CHAIN\r
+ if (_streamPos - _pos < kNumHashBytes)\r
+ {\r
+ RINOK(MovePos()); \r
+ continue;\r
+ }\r
+ #else\r
+ UInt32 lenLimit;\r
+ if (_pos + _matchMaxLen <= _streamPos)\r
+ lenLimit = _matchMaxLen;\r
+ else\r
+ {\r
+ lenLimit = _streamPos - _pos;\r
+ if(lenLimit < kMinMatchCheck)\r
+ {\r
+ RINOK(MovePos());\r
+ continue;\r
+ }\r
+ }\r
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\r
+ #endif\r
+ const Byte *cur = _buffer + _pos;\r
+\r
+ #ifdef HASH_ARRAY_2\r
+ UInt32 hash2Value;\r
+ #ifdef HASH_ARRAY_3\r
+ UInt32 hash3Value;\r
+ UInt32 hashValue;\r
+ HASH_CALC;\r
+ _hash[kHash3Offset + hash3Value] = _pos;\r
+ #else\r
+ UInt32 hashValue;\r
+ HASH_CALC;\r
+ #endif\r
+ _hash[hash2Value] = _pos;\r
+ #else\r
+ UInt32 hashValue = Hash(cur);\r
+ #endif\r
+\r
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];\r
+ _hash[kFixHashSize + hashValue] = _pos;\r
+\r
+ #ifdef _HASH_CHAIN\r
+ _son[_cyclicBufferPos] = curMatch;\r
+ #else\r
+ CIndex *son = _son;\r
+ CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
+ CIndex *ptr1 = son + (_cyclicBufferPos << 1);\r
+\r
+ UInt32 len0, len1;\r
+ len0 = len1 = kNumHashDirectBytes;\r
+ UInt32 count = _cutValue;\r
+ while(true)\r
+ {\r
+ if(curMatch <= matchMinPos || count-- == 0)\r
+ {\r
+ *ptr0 = *ptr1 = kEmptyHashValue;\r
+ break;\r
+ }\r
+ \r
+ UInt32 delta = _pos - curMatch;\r
+ UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?\r
+ (_cyclicBufferPos - delta):\r
+ (_cyclicBufferPos - delta + _cyclicBufferSize);\r
+ CIndex *pair = son + (cyclicPos << 1);\r
+ \r
+ // _mm_prefetch((const char *)pair, _MM_HINT_T0);\r
+ \r
+ const Byte *pb = _buffer + curMatch;\r
+ UInt32 len = MyMin(len0, len1);\r
+ \r
+ if (pb[len] == cur[len])\r
+ {\r
+ while(++len != lenLimit)\r
+ if (pb[len] != cur[len])\r
+ break;\r
+ if (len == lenLimit)\r
+ {\r
+ *ptr1 = pair[0];\r
+ *ptr0 = pair[1];\r
+ break;\r
+ }\r
+ }\r
+ if (pb[len] < cur[len])\r
+ {\r
+ *ptr1 = curMatch;\r
+ ptr1 = pair + 1;\r
+ curMatch = *ptr1;\r
+ len1 = len;\r
+ }\r
+ else\r
+ {\r
+ *ptr0 = curMatch;\r
+ ptr0 = pair;\r
+ curMatch = *ptr0;\r
+ len0 = len;\r
+ }\r
+ }\r
+ #endif\r
+ if (++_cyclicBufferPos == _cyclicBufferSize)\r
+ _cyclicBufferPos = 0;\r
+ RINOK(CLZInWindow::MovePos());\r
+ if (_pos == kMaxValForNormalize)\r
+ Normalize();\r
+ }\r
+ while(--num != 0);\r
+ return S_OK;\r
+}\r
+\r
+void CMatchFinder::Normalize()\r
+{\r
+ UInt32 subValue = _pos - _cyclicBufferSize;\r
+ CIndex *items = _hash;\r
+ UInt32 numItems = (_hashSizeSum + _cyclicBufferSize \r
+ #ifndef _HASH_CHAIN\r
+ * 2\r
+ #endif\r
+ );\r
+ for (UInt32 i = 0; i < numItems; i++)\r
+ {\r
+ UInt32 value = items[i];\r
+ if (value <= subValue)\r
+ value = kEmptyHashValue;\r
+ else\r
+ value -= subValue;\r
+ items[i] = value;\r
+ }\r
+ ReduceOffsets(subValue);\r
+}\r
+\r
+HRESULT CMatchFinder::MovePos()\r
+{\r
+ if (++_cyclicBufferPos == _cyclicBufferSize)\r
+ _cyclicBufferPos = 0;\r
+ RINOK(CLZInWindow::MovePos());\r
+ if (_pos == kMaxValForNormalize)\r
+ Normalize();\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)\r
+ { return CLZInWindow::GetIndexByte(index); }\r
+\r
+STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, \r
+ UInt32 back, UInt32 limit)\r
+ { return CLZInWindow::GetMatchLen(index, back, limit); }\r
+\r
+STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()\r
+ { return CLZInWindow::GetNumAvailableBytes(); }\r
+\r
+STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()\r
+ { return CLZInWindow::GetPointerToCurrentPos(); }\r
+\r
+STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)\r
+ { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }\r
+\r
+STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()\r
+ { CLZInWindow::MoveBlock();}\r
+\r
+#undef HASH_CALC\r
+#undef kNumHashDirectBytes\r
+ \r
+}\r
--- /dev/null
+// HC4.h\r
+\r
+#ifndef __HC4_H\r
+#define __HC4_H\r
+\r
+#define BT_NAMESPACE NHC4\r
+\r
+#define HASH_ARRAY_2\r
+#define HASH_ARRAY_3\r
+\r
+#include "HCMain.h"\r
+\r
+#undef HASH_ARRAY_2\r
+#undef HASH_ARRAY_3\r
+\r
+#undef BT_NAMESPACE\r
+\r
+#endif\r
+\r
--- /dev/null
+// HCMain.h\r
+\r
+#define _HASH_CHAIN\r
+#include "../BinTree/BinTreeMain.h"\r
+#undef _HASH_CHAIN\r
+\r
--- /dev/null
+// MatchFinders/IMatchFinder.h\r
+\r
+#ifndef __IMATCHFINDER_H\r
+#define __IMATCHFINDER_H\r
+\r
+struct IInWindowStream: public IUnknown\r
+{\r
+ STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE;\r
+ STDMETHOD_(void, ReleaseStream)() PURE;\r
+ STDMETHOD(Init)() PURE;\r
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE;\r
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE;\r
+ STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE;\r
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE;\r
+ STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE;\r
+ STDMETHOD_(void, ChangeBufferPos)() PURE;\r
+};\r
+ \r
+struct IMatchFinder: public IInWindowStream\r
+{\r
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, \r
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE;\r
+ STDMETHOD(GetMatches)(UInt32 *distances) PURE;\r
+ STDMETHOD(Skip)(UInt32 num) PURE;\r
+};\r
+\r
+struct IMatchFinderSetNumPasses\r
+{\r
+ //virtual ~IMatchFinderSetNumPasses(){}\r
+ virtual void SetNumPasses(UInt32 numPasses) PURE;\r
+};\r
+\r
+#endif\r
--- /dev/null
+// LZInWindow.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LZInWindow.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../../Common/Alloc.h"\r
+\r
+void CLZInWindow::Free()\r
+{\r
+ ::BigFree(_bufferBase);\r
+ _bufferBase = 0;\r
+}\r
+\r
+bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)\r
+{\r
+ _keepSizeBefore = keepSizeBefore;\r
+ _keepSizeAfter = keepSizeAfter;\r
+ UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;\r
+ if (_bufferBase == 0 || _blockSize != blockSize)\r
+ {\r
+ Free();\r
+ _blockSize = blockSize;\r
+ if (_blockSize != 0)\r
+ _bufferBase = (Byte *)::BigAlloc(_blockSize);\r
+ }\r
+ _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter;\r
+ if (_blockSize == 0)\r
+ return true;\r
+ return (_bufferBase != 0);\r
+}\r
+\r
+void CLZInWindow::SetStream(ISequentialInStream *stream)\r
+{\r
+ _stream = stream;\r
+}\r
+\r
+HRESULT CLZInWindow::Init()\r
+{\r
+ _buffer = _bufferBase;\r
+ _pos = 0;\r
+ _streamPos = 0;\r
+ _streamEndWasReached = false;\r
+ return ReadBlock();\r
+}\r
+\r
+/*\r
+void CLZInWindow::ReleaseStream()\r
+{\r
+ _stream.Release();\r
+}\r
+*/\r
+\r
+///////////////////////////////////////////\r
+// ReadBlock\r
+\r
+// In State:\r
+// (_buffer + _streamPos) <= (_bufferBase + _blockSize)\r
+// Out State:\r
+// _posLimit <= _blockSize - _keepSizeAfter;\r
+// if(_streamEndWasReached == false):\r
+// _streamPos >= _pos + _keepSizeAfter\r
+// _posLimit = _streamPos - _keepSizeAfter;\r
+// else\r
+// \r
+ \r
+HRESULT CLZInWindow::ReadBlock()\r
+{\r
+ if(_streamEndWasReached)\r
+ return S_OK;\r
+ while(true)\r
+ {\r
+ UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos;\r
+ if(size == 0)\r
+ return S_OK;\r
+ UInt32 numReadBytes;\r
+ RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes));\r
+ if(numReadBytes == 0)\r
+ {\r
+ _posLimit = _streamPos;\r
+ const Byte *pointerToPostion = _buffer + _posLimit;\r
+ if(pointerToPostion > _pointerToLastSafePosition)\r
+ _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer);\r
+ _streamEndWasReached = true;\r
+ return S_OK;\r
+ }\r
+ _streamPos += numReadBytes;\r
+ if(_streamPos >= _pos + _keepSizeAfter)\r
+ {\r
+ _posLimit = _streamPos - _keepSizeAfter;\r
+ return S_OK;\r
+ }\r
+ }\r
+}\r
+\r
+void CLZInWindow::MoveBlock()\r
+{\r
+ UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore;\r
+ // we need one additional byte, since MovePos moves on 1 byte.\r
+ if (offset > 0)\r
+ offset--; \r
+ UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset;\r
+ memmove(_bufferBase, _bufferBase + offset, numBytes);\r
+ _buffer -= offset;\r
+}\r
--- /dev/null
+// LZInWindow.h\r
+\r
+#ifndef __LZ_IN_WINDOW_H\r
+#define __LZ_IN_WINDOW_H\r
+\r
+#include "../../IStream.h"\r
+\r
+class CLZInWindow\r
+{\r
+ Byte *_bufferBase; // pointer to buffer with data\r
+ ISequentialInStream *_stream;\r
+ UInt32 _posLimit; // offset (from _buffer) when new block reading must be done\r
+ bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream\r
+ const Byte *_pointerToLastSafePosition;\r
+protected:\r
+ Byte *_buffer; // Pointer to virtual Buffer begin\r
+ UInt32 _blockSize; // Size of Allocated memory block\r
+ UInt32 _pos; // offset (from _buffer) of curent byte\r
+ UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos\r
+ UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos\r
+ UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream\r
+\r
+ void MoveBlock();\r
+ HRESULT ReadBlock();\r
+ void Free();\r
+public:\r
+ CLZInWindow(): _bufferBase(0) {}\r
+ virtual ~CLZInWindow() { Free(); }\r
+\r
+ // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G)\r
+ bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17));\r
+\r
+ void SetStream(ISequentialInStream *stream);\r
+ HRESULT Init();\r
+ // void ReleaseStream();\r
+\r
+ Byte *GetBuffer() const { return _buffer; }\r
+\r
+ const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; }\r
+\r
+ HRESULT MovePos()\r
+ {\r
+ _pos++;\r
+ if (_pos > _posLimit)\r
+ {\r
+ const Byte *pointerToPostion = _buffer + _pos;\r
+ if(pointerToPostion > _pointerToLastSafePosition)\r
+ MoveBlock();\r
+ return ReadBlock();\r
+ }\r
+ else\r
+ return S_OK;\r
+ }\r
+ Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; }\r
+\r
+ // index + limit have not to exceed _keepSizeAfter;\r
+ // -2G <= index < 2G\r
+ UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const\r
+ { \r
+ if(_streamEndWasReached)\r
+ if ((_pos + index) + limit > _streamPos)\r
+ limit = _streamPos - (_pos + index);\r
+ distance++;\r
+ const Byte *pby = _buffer + (size_t)_pos + index;\r
+ UInt32 i;\r
+ for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);\r
+ return i;\r
+ }\r
+\r
+ UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; }\r
+\r
+ void ReduceOffsets(Int32 subValue)\r
+ {\r
+ _buffer += subValue;\r
+ _posLimit -= subValue;\r
+ _pos -= subValue;\r
+ _streamPos -= subValue;\r
+ }\r
+\r
+ bool NeedMove(UInt32 numCheckBytes)\r
+ {\r
+ UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos);\r
+ return (reserv <= numCheckBytes);\r
+ }\r
+};\r
+\r
+#endif\r
--- /dev/null
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#endif \r
--- /dev/null
+// LZMA.h\r
+\r
+#ifndef __LZMA_H\r
+#define __LZMA_H\r
+\r
+namespace NCompress {\r
+namespace NLZMA {\r
+\r
+const UInt32 kNumRepDistances = 4;\r
+\r
+const int kNumStates = 12;\r
+\r
+const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};\r
+const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\r
+const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\r
+const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\r
+\r
+class CState\r
+{\r
+public:\r
+ Byte Index;\r
+ void Init() { Index = 0; }\r
+ void UpdateChar() { Index = kLiteralNextStates[Index]; }\r
+ void UpdateMatch() { Index = kMatchNextStates[Index]; }\r
+ void UpdateRep() { Index = kRepNextStates[Index]; }\r
+ void UpdateShortRep() { Index = kShortRepNextStates[Index]; }\r
+ bool IsCharState() const { return Index < 7; }\r
+};\r
+\r
+const int kNumPosSlotBits = 6; \r
+const int kDicLogSizeMin = 0; \r
+const int kDicLogSizeMax = 32; \r
+const int kDistTableSizeMax = kDicLogSizeMax * 2; \r
+\r
+const UInt32 kNumLenToPosStates = 4;\r
+\r
+inline UInt32 GetLenToPosState(UInt32 len)\r
+{\r
+ len -= 2;\r
+ if (len < kNumLenToPosStates)\r
+ return len;\r
+ return kNumLenToPosStates - 1;\r
+}\r
+\r
+namespace NLength {\r
+\r
+const int kNumPosStatesBitsMax = 4;\r
+const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax);\r
+\r
+const int kNumPosStatesBitsEncodingMax = 4;\r
+const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);\r
+\r
+const int kNumLowBits = 3;\r
+const int kNumMidBits = 3;\r
+const int kNumHighBits = 8;\r
+const UInt32 kNumLowSymbols = 1 << kNumLowBits;\r
+const UInt32 kNumMidSymbols = 1 << kNumMidBits;\r
+const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);\r
+\r
+}\r
+\r
+const UInt32 kMatchMinLen = 2;\r
+const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;\r
+\r
+const int kNumAlignBits = 4;\r
+const UInt32 kAlignTableSize = 1 << kNumAlignBits;\r
+const UInt32 kAlignMask = (kAlignTableSize - 1);\r
+\r
+const UInt32 kStartPosModelIndex = 4;\r
+const UInt32 kEndPosModelIndex = 14;\r
+const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;\r
+\r
+const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2);\r
+\r
+const int kNumLitPosStatesBitsEncodingMax = 4;\r
+const int kNumLitContextBitsMax = 8;\r
+\r
+const int kNumMoveBits = 5;\r
+\r
+}}\r
+\r
+#endif\r
--- /dev/null
+// LZMA/Encoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../Common/Defs.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "LZMAEncoder.h"\r
+\r
+// for minimal compressing code size define these:\r
+// #define COMPRESS_MF_BT\r
+// #define COMPRESS_MF_BT4\r
+\r
+#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC)\r
+#define COMPRESS_MF_BT\r
+#define COMPRESS_MF_HC\r
+#endif\r
+\r
+#ifdef COMPRESS_MF_BT\r
+#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4)\r
+#define COMPRESS_MF_BT2\r
+#define COMPRESS_MF_BT3\r
+#define COMPRESS_MF_BT4\r
+#endif\r
+#ifdef COMPRESS_MF_BT2\r
+#include "../LZ/BinTree/BinTree2.h"\r
+#endif\r
+#ifdef COMPRESS_MF_BT3\r
+#include "../LZ/BinTree/BinTree3.h"\r
+#endif\r
+#ifdef COMPRESS_MF_BT4\r
+#include "../LZ/BinTree/BinTree4.h"\r
+#endif\r
+#endif\r
+\r
+#ifdef COMPRESS_MF_HC\r
+#include "../LZ/HashChain/HC4.h"\r
+#endif\r
+\r
+#ifdef COMPRESS_MF_MT\r
+#include "../LZ/MT/MT.h"\r
+#endif\r
+\r
+namespace NCompress {\r
+namespace NLZMA {\r
+\r
+const int kDefaultDictionaryLogSize = 22;\r
+const UInt32 kNumFastBytesDefault = 0x20;\r
+\r
+enum \r
+{\r
+ kBT2,\r
+ kBT3,\r
+ kBT4,\r
+ kHC4\r
+};\r
+\r
+static const wchar_t *kMatchFinderIDs[] = \r
+{\r
+ L"BT2",\r
+ L"BT3",\r
+ L"BT4",\r
+ L"HC4"\r
+};\r
+\r
+Byte g_FastPos[1 << 11];\r
+\r
+class CFastPosInit\r
+{\r
+public:\r
+ CFastPosInit() { Init(); }\r
+ void Init()\r
+ {\r
+ const Byte kFastSlots = 22;\r
+ int c = 2;\r
+ g_FastPos[0] = 0;\r
+ g_FastPos[1] = 1;\r
+\r
+ for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)\r
+ {\r
+ UInt32 k = (1 << ((slotFast >> 1) - 1));\r
+ for (UInt32 j = 0; j < k; j++, c++)\r
+ g_FastPos[c] = slotFast;\r
+ }\r
+ }\r
+} g_FastPosInit;\r
+\r
+\r
+void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)\r
+{\r
+ UInt32 context = 1;\r
+ int i = 8;\r
+ do \r
+ {\r
+ i--;\r
+ UInt32 bit = (symbol >> i) & 1;\r
+ _encoders[context].Encode(rangeEncoder, bit);\r
+ context = (context << 1) | bit;\r
+ }\r
+ while(i != 0);\r
+}\r
+\r
+void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, \r
+ Byte matchByte, Byte symbol)\r
+{\r
+ UInt32 context = 1;\r
+ int i = 8;\r
+ do \r
+ {\r
+ i--;\r
+ UInt32 bit = (symbol >> i) & 1;\r
+ UInt32 matchBit = (matchByte >> i) & 1;\r
+ _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);\r
+ context = (context << 1) | bit;\r
+ if (matchBit != bit)\r
+ {\r
+ while(i != 0)\r
+ {\r
+ i--;\r
+ UInt32 bit = (symbol >> i) & 1;\r
+ _encoders[context].Encode(rangeEncoder, bit);\r
+ context = (context << 1) | bit;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ while(i != 0);\r
+}\r
+\r
+UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const\r
+{\r
+ UInt32 price = 0;\r
+ UInt32 context = 1;\r
+ int i = 8;\r
+ if (matchMode)\r
+ {\r
+ do \r
+ {\r
+ i--;\r
+ UInt32 matchBit = (matchByte >> i) & 1;\r
+ UInt32 bit = (symbol >> i) & 1;\r
+ price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);\r
+ context = (context << 1) | bit;\r
+ if (matchBit != bit)\r
+ break;\r
+ }\r
+ while (i != 0);\r
+ }\r
+ while(i != 0)\r
+ {\r
+ i--;\r
+ UInt32 bit = (symbol >> i) & 1;\r
+ price += _encoders[context].GetPrice(bit);\r
+ context = (context << 1) | bit;\r
+ }\r
+ return price;\r
+};\r
+\r
+\r
+namespace NLength {\r
+\r
+void CEncoder::Init(UInt32 numPosStates)\r
+{\r
+ _choice.Init();\r
+ _choice2.Init();\r
+ for (UInt32 posState = 0; posState < numPosStates; posState++)\r
+ {\r
+ _lowCoder[posState].Init();\r
+ _midCoder[posState].Init();\r
+ }\r
+ _highCoder.Init();\r
+}\r
+\r
+void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)\r
+{\r
+ if(symbol < kNumLowSymbols)\r
+ {\r
+ _choice.Encode(rangeEncoder, 0);\r
+ _lowCoder[posState].Encode(rangeEncoder, symbol);\r
+ }\r
+ else\r
+ {\r
+ _choice.Encode(rangeEncoder, 1);\r
+ if(symbol < kNumLowSymbols + kNumMidSymbols)\r
+ {\r
+ _choice2.Encode(rangeEncoder, 0);\r
+ _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);\r
+ }\r
+ else\r
+ {\r
+ _choice2.Encode(rangeEncoder, 1);\r
+ _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);\r
+ }\r
+ }\r
+}\r
+\r
+void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const\r
+{\r
+ UInt32 a0 = _choice.GetPrice0();\r
+ UInt32 a1 = _choice.GetPrice1();\r
+ UInt32 b0 = a1 + _choice2.GetPrice0();\r
+ UInt32 b1 = a1 + _choice2.GetPrice1();\r
+ UInt32 i = 0;\r
+ for (i = 0; i < kNumLowSymbols; i++)\r
+ {\r
+ if (i >= numSymbols)\r
+ return;\r
+ prices[i] = a0 + _lowCoder[posState].GetPrice(i);\r
+ }\r
+ for (; i < kNumLowSymbols + kNumMidSymbols; i++)\r
+ {\r
+ if (i >= numSymbols)\r
+ return;\r
+ prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);\r
+ }\r
+ for (; i < numSymbols; i++)\r
+ prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);\r
+}\r
+\r
+}\r
+CEncoder::CEncoder():\r
+ _numFastBytes(kNumFastBytesDefault),\r
+ _distTableSize(kDefaultDictionaryLogSize * 2),\r
+ _posStateBits(2),\r
+ _posStateMask(4 - 1),\r
+ _numLiteralPosStateBits(0),\r
+ _numLiteralContextBits(3),\r
+ _dictionarySize(1 << kDefaultDictionaryLogSize),\r
+ _dictionarySizePrev(UInt32(-1)),\r
+ _numFastBytesPrev(UInt32(-1)),\r
+ _matchFinderCycles(0),\r
+ _matchFinderIndex(kBT4),\r
+ #ifdef COMPRESS_MF_MT\r
+ _multiThread(false),\r
+ #endif\r
+ _writeEndMark(false),\r
+ setMfPasses(0)\r
+{\r
+ // _maxMode = false;\r
+ _fastMode = false;\r
+}\r
+\r
+HRESULT CEncoder::Create()\r
+{\r
+ if (!_rangeEncoder.Create(1 << 20))\r
+ return E_OUTOFMEMORY;\r
+ if (!_matchFinder)\r
+ {\r
+ switch(_matchFinderIndex)\r
+ {\r
+ #ifdef COMPRESS_MF_BT\r
+ #ifdef COMPRESS_MF_BT2\r
+ case kBT2:\r
+ {\r
+ NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder;\r
+ setMfPasses = mfSpec;\r
+ _matchFinder = mfSpec;\r
+ break;\r
+ }\r
+ #endif\r
+ #ifdef COMPRESS_MF_BT3\r
+ case kBT3:\r
+ {\r
+ NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder;\r
+ setMfPasses = mfSpec;\r
+ _matchFinder = mfSpec;\r
+ break;\r
+ }\r
+ #endif\r
+ #ifdef COMPRESS_MF_BT4\r
+ case kBT4:\r
+ {\r
+ NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder;\r
+ setMfPasses = mfSpec;\r
+ _matchFinder = mfSpec;\r
+ break;\r
+ }\r
+ #endif\r
+ #endif\r
+ \r
+ #ifdef COMPRESS_MF_HC\r
+ case kHC4:\r
+ {\r
+ NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder;\r
+ setMfPasses = mfSpec;\r
+ _matchFinder = mfSpec;\r
+ break;\r
+ }\r
+ #endif\r
+ }\r
+ if (_matchFinder == 0)\r
+ return E_OUTOFMEMORY;\r
+\r
+ #ifdef COMPRESS_MF_MT\r
+ if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4)))\r
+ {\r
+ CMatchFinderMT *mfSpec = new CMatchFinderMT;\r
+ if (mfSpec == 0)\r
+ return E_OUTOFMEMORY;\r
+ CMyComPtr<IMatchFinder> mf = mfSpec;\r
+ RINOK(mfSpec->SetMatchFinder(_matchFinder));\r
+ _matchFinder.Release();\r
+ _matchFinder = mf;\r
+ }\r
+ #endif\r
+ }\r
+ \r
+ if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))\r
+ return E_OUTOFMEMORY;\r
+\r
+ if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)\r
+ return S_OK;\r
+ RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes\r
+ if (_matchFinderCycles != 0 && setMfPasses != 0)\r
+ setMfPasses->SetNumPasses(_matchFinderCycles);\r
+ _dictionarySizePrev = _dictionarySize;\r
+ _numFastBytesPrev = _numFastBytes;\r
+ return S_OK;\r
+}\r
+\r
+static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)\r
+{\r
+ while (true)\r
+ {\r
+ wchar_t c = *testString;\r
+ if (c >= 'a' && c <= 'z')\r
+ c -= 0x20;\r
+ if (*base != c)\r
+ return false;\r
+ if (c == 0)\r
+ return true;\r
+ base++;\r
+ testString++;\r
+ }\r
+}\r
+\r
+static int FindMatchFinder(const wchar_t *s)\r
+{\r
+ for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++)\r
+ if (AreStringsEqual(kMatchFinderIDs[m], s))\r
+ return m;\r
+ return -1;\r
+}\r
+\r
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, \r
+ const PROPVARIANT *properties, UInt32 numProperties)\r
+{\r
+ for (UInt32 i = 0; i < numProperties; i++)\r
+ {\r
+ const PROPVARIANT &prop = properties[i];\r
+ switch(propIDs[i])\r
+ {\r
+ case NCoderPropID::kNumFastBytes:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 numFastBytes = prop.ulVal;\r
+ if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)\r
+ return E_INVALIDARG;\r
+ _numFastBytes = numFastBytes;\r
+ break;\r
+ }\r
+ case NCoderPropID::kMatchFinderCycles:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ _matchFinderCycles = prop.ulVal;\r
+ break;\r
+ }\r
+ case NCoderPropID::kAlgorithm:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 maximize = prop.ulVal;\r
+ _fastMode = (maximize == 0); \r
+ // _maxMode = (maximize >= 2);\r
+ break;\r
+ }\r
+ case NCoderPropID::kMatchFinder:\r
+ {\r
+ if (prop.vt != VT_BSTR)\r
+ return E_INVALIDARG;\r
+ int matchFinderIndexPrev = _matchFinderIndex;\r
+ int m = FindMatchFinder(prop.bstrVal);\r
+ if (m < 0)\r
+ return E_INVALIDARG;\r
+ _matchFinderIndex = m;\r
+ if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex)\r
+ {\r
+ _dictionarySizePrev = (UInt32)-1;\r
+ ReleaseMatchFinder();\r
+ }\r
+ break;\r
+ }\r
+ #ifdef COMPRESS_MF_MT\r
+ case NCoderPropID::kMultiThread:\r
+ {\r
+ if (prop.vt != VT_BOOL)\r
+ return E_INVALIDARG;\r
+ bool newMultiThread = (prop.boolVal == VARIANT_TRUE);\r
+ if (newMultiThread != _multiThread)\r
+ {\r
+ _dictionarySizePrev = (UInt32)-1;\r
+ ReleaseMatchFinder();\r
+ _multiThread = newMultiThread;\r
+ }\r
+ break;\r
+ }\r
+ case NCoderPropID::kNumThreads:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ bool newMultiThread = (prop.ulVal > 1);\r
+ if (newMultiThread != _multiThread)\r
+ {\r
+ _dictionarySizePrev = (UInt32)-1;\r
+ ReleaseMatchFinder();\r
+ _multiThread = newMultiThread;\r
+ }\r
+ break;\r
+ }\r
+ #endif\r
+ case NCoderPropID::kDictionarySize:\r
+ {\r
+ const int kDicLogSizeMaxCompress = 30;\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 dictionarySize = prop.ulVal;\r
+ if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||\r
+ dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))\r
+ return E_INVALIDARG;\r
+ _dictionarySize = dictionarySize;\r
+ UInt32 dicLogSize;\r
+ for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)\r
+ if (dictionarySize <= (UInt32(1) << dicLogSize))\r
+ break;\r
+ _distTableSize = dicLogSize * 2;\r
+ break;\r
+ }\r
+ case NCoderPropID::kPosStateBits:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 value = prop.ulVal;\r
+ if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)\r
+ return E_INVALIDARG;\r
+ _posStateBits = value;\r
+ _posStateMask = (1 << _posStateBits) - 1;\r
+ break;\r
+ }\r
+ case NCoderPropID::kLitPosBits:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 value = prop.ulVal;\r
+ if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)\r
+ return E_INVALIDARG;\r
+ _numLiteralPosStateBits = value;\r
+ break;\r
+ }\r
+ case NCoderPropID::kLitContextBits:\r
+ {\r
+ if (prop.vt != VT_UI4)\r
+ return E_INVALIDARG;\r
+ UInt32 value = prop.ulVal;\r
+ if (value > (UInt32)kNumLitContextBitsMax)\r
+ return E_INVALIDARG;\r
+ _numLiteralContextBits = value;\r
+ break;\r
+ }\r
+ case NCoderPropID::kEndMarker:\r
+ {\r
+ if (prop.vt != VT_BOOL)\r
+ return E_INVALIDARG;\r
+ SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);\r
+ break;\r
+ }\r
+ default:\r
+ return E_INVALIDARG;\r
+ }\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{ \r
+ const UInt32 kPropSize = 5;\r
+ Byte properties[kPropSize];\r
+ properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits;\r
+ for (int i = 0; i < 4; i++)\r
+ properties[1 + i] = Byte(_dictionarySize >> (8 * i));\r
+ return WriteStream(outStream, properties, kPropSize, NULL);\r
+}\r
+\r
+STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)\r
+{\r
+ _rangeEncoder.SetStream(outStream);\r
+ return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::ReleaseOutStream()\r
+{\r
+ _rangeEncoder.ReleaseStream();\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::Init()\r
+{\r
+ CBaseState::Init();\r
+\r
+ // RINOK(_matchFinder->Init(inStream));\r
+ _rangeEncoder.Init();\r
+\r
+ for(int i = 0; i < kNumStates; i++)\r
+ {\r
+ for (UInt32 j = 0; j <= _posStateMask; j++)\r
+ {\r
+ _isMatch[i][j].Init();\r
+ _isRep0Long[i][j].Init();\r
+ }\r
+ _isRep[i].Init();\r
+ _isRepG0[i].Init();\r
+ _isRepG1[i].Init();\r
+ _isRepG2[i].Init();\r
+ }\r
+\r
+ _literalEncoder.Init();\r
+\r
+ {\r
+ for(UInt32 i = 0; i < kNumLenToPosStates; i++)\r
+ _posSlotEncoder[i].Init();\r
+ }\r
+ {\r
+ for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)\r
+ _posEncoders[i].Init();\r
+ }\r
+\r
+ _lenEncoder.Init(1 << _posStateBits);\r
+ _repMatchLenEncoder.Init(1 << _posStateBits);\r
+\r
+ _posAlignEncoder.Init();\r
+\r
+ _longestMatchWasFound = false;\r
+ _optimumEndIndex = 0;\r
+ _optimumCurrentIndex = 0;\r
+ _additionalOffset = 0;\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::MovePos(UInt32 num)\r
+{\r
+ if (num == 0)\r
+ return S_OK;\r
+ _additionalOffset += num;\r
+ return _matchFinder->Skip(num);\r
+}\r
+\r
+UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)\r
+{\r
+ _optimumEndIndex = cur;\r
+ UInt32 posMem = _optimum[cur].PosPrev;\r
+ UInt32 backMem = _optimum[cur].BackPrev;\r
+ do\r
+ {\r
+ if (_optimum[cur].Prev1IsChar)\r
+ {\r
+ _optimum[posMem].MakeAsChar();\r
+ _optimum[posMem].PosPrev = posMem - 1;\r
+ if (_optimum[cur].Prev2)\r
+ {\r
+ _optimum[posMem - 1].Prev1IsChar = false;\r
+ _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;\r
+ _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;\r
+ }\r
+ }\r
+ UInt32 posPrev = posMem;\r
+ UInt32 backCur = backMem;\r
+\r
+ backMem = _optimum[posPrev].BackPrev;\r
+ posMem = _optimum[posPrev].PosPrev;\r
+\r
+ _optimum[posPrev].BackPrev = backCur;\r
+ _optimum[posPrev].PosPrev = cur;\r
+ cur = posPrev;\r
+ }\r
+ while(cur != 0);\r
+ backRes = _optimum[0].BackPrev;\r
+ _optimumCurrentIndex = _optimum[0].PosPrev;\r
+ return _optimumCurrentIndex; \r
+}\r
+\r
+/*\r
+Out:\r
+ (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal\r
+*/\r
+\r
+HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)\r
+{\r
+ if(_optimumEndIndex != _optimumCurrentIndex)\r
+ {\r
+ const COptimal &optimum = _optimum[_optimumCurrentIndex];\r
+ lenRes = optimum.PosPrev - _optimumCurrentIndex;\r
+ backRes = optimum.BackPrev;\r
+ _optimumCurrentIndex = optimum.PosPrev;\r
+ return S_OK;\r
+ }\r
+ _optimumCurrentIndex = _optimumEndIndex = 0;\r
+ \r
+ UInt32 lenMain, numDistancePairs;\r
+ if (!_longestMatchWasFound)\r
+ {\r
+ RINOK(ReadMatchDistances(lenMain, numDistancePairs));\r
+ }\r
+ else\r
+ {\r
+ lenMain = _longestMatchLength;\r
+ numDistancePairs = _numDistancePairs;\r
+ _longestMatchWasFound = false;\r
+ }\r
+\r
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;\r
+ UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;\r
+ if (numAvailableBytes < 2)\r
+ {\r
+ backRes = (UInt32)(-1);\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+ if (numAvailableBytes > kMatchMaxLen)\r
+ numAvailableBytes = kMatchMaxLen;\r
+\r
+ UInt32 reps[kNumRepDistances];\r
+ UInt32 repLens[kNumRepDistances];\r
+ UInt32 repMaxIndex = 0;\r
+ UInt32 i;\r
+ for(i = 0; i < kNumRepDistances; i++)\r
+ {\r
+ reps[i] = _repDistances[i];\r
+ UInt32 backOffset = reps[i] + 1;\r
+ if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset])\r
+ {\r
+ repLens[i] = 0;\r
+ continue;\r
+ }\r
+ UInt32 lenTest;\r
+ for (lenTest = 2; lenTest < numAvailableBytes && \r
+ data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++);\r
+ repLens[i] = lenTest;\r
+ if (lenTest > repLens[repMaxIndex])\r
+ repMaxIndex = i;\r
+ }\r
+ if(repLens[repMaxIndex] >= _numFastBytes)\r
+ {\r
+ backRes = repMaxIndex;\r
+ lenRes = repLens[repMaxIndex];\r
+ return MovePos(lenRes - 1);\r
+ }\r
+\r
+ UInt32 *matchDistances = _matchDistances + 1;\r
+ if(lenMain >= _numFastBytes)\r
+ {\r
+ backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; \r
+ lenRes = lenMain;\r
+ return MovePos(lenMain - 1);\r
+ }\r
+ Byte currentByte = *data;\r
+ Byte matchByte = data[(size_t)0 - reps[0] - 1];\r
+\r
+ if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)\r
+ {\r
+ backRes = (UInt32)-1;\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+\r
+ _optimum[0].State = _state;\r
+\r
+ UInt32 posState = (position & _posStateMask);\r
+\r
+ _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + \r
+ _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);\r
+ _optimum[1].MakeAsChar();\r
+\r
+ UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();\r
+ UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();\r
+\r
+ if(matchByte == currentByte)\r
+ {\r
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);\r
+ if(shortRepPrice < _optimum[1].Price)\r
+ {\r
+ _optimum[1].Price = shortRepPrice;\r
+ _optimum[1].MakeAsShortRep();\r
+ }\r
+ }\r
+ UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);\r
+\r
+ if(lenEnd < 2)\r
+ {\r
+ backRes = _optimum[1].BackPrev;\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+\r
+ _optimum[1].PosPrev = 0;\r
+ for (i = 0; i < kNumRepDistances; i++)\r
+ _optimum[0].Backs[i] = reps[i];\r
+\r
+ UInt32 len = lenEnd;\r
+ do\r
+ _optimum[len--].Price = kIfinityPrice;\r
+ while (len >= 2);\r
+\r
+ for(i = 0; i < kNumRepDistances; i++)\r
+ {\r
+ UInt32 repLen = repLens[i];\r
+ if (repLen < 2)\r
+ continue;\r
+ UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);\r
+ do\r
+ {\r
+ UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);\r
+ COptimal &optimum = _optimum[repLen];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = 0;\r
+ optimum.BackPrev = i;\r
+ optimum.Prev1IsChar = false;\r
+ }\r
+ }\r
+ while(--repLen >= 2);\r
+ }\r
+\r
+ UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();\r
+\r
+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\r
+ if (len <= lenMain)\r
+ {\r
+ UInt32 offs = 0;\r
+ while (len > matchDistances[offs])\r
+ offs += 2;\r
+ for(; ; len++)\r
+ {\r
+ UInt32 distance = matchDistances[offs + 1];\r
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);\r
+ COptimal &optimum = _optimum[len];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = 0;\r
+ optimum.BackPrev = distance + kNumRepDistances;\r
+ optimum.Prev1IsChar = false;\r
+ }\r
+ if (len == matchDistances[offs])\r
+ {\r
+ offs += 2;\r
+ if (offs == numDistancePairs)\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ UInt32 cur = 0;\r
+\r
+ while(true)\r
+ {\r
+ cur++;\r
+ if(cur == lenEnd)\r
+ {\r
+ lenRes = Backward(backRes, cur);\r
+ return S_OK;\r
+ }\r
+ UInt32 newLen, numDistancePairs;\r
+ RINOK(ReadMatchDistances(newLen, numDistancePairs));\r
+ if(newLen >= _numFastBytes)\r
+ {\r
+ _numDistancePairs = numDistancePairs;\r
+ _longestMatchLength = newLen;\r
+ _longestMatchWasFound = true;\r
+ lenRes = Backward(backRes, cur);\r
+ return S_OK;\r
+ }\r
+ position++;\r
+ COptimal &curOptimum = _optimum[cur];\r
+ UInt32 posPrev = curOptimum.PosPrev;\r
+ CState state;\r
+ if (curOptimum.Prev1IsChar)\r
+ {\r
+ posPrev--;\r
+ if (curOptimum.Prev2)\r
+ {\r
+ state = _optimum[curOptimum.PosPrev2].State;\r
+ if (curOptimum.BackPrev2 < kNumRepDistances)\r
+ state.UpdateRep();\r
+ else\r
+ state.UpdateMatch();\r
+ }\r
+ else\r
+ state = _optimum[posPrev].State;\r
+ state.UpdateChar();\r
+ }\r
+ else\r
+ state = _optimum[posPrev].State;\r
+ if (posPrev == cur - 1)\r
+ {\r
+ if (curOptimum.IsShortRep())\r
+ state.UpdateShortRep();\r
+ else\r
+ state.UpdateChar();\r
+ }\r
+ else\r
+ {\r
+ UInt32 pos;\r
+ if (curOptimum.Prev1IsChar && curOptimum.Prev2)\r
+ {\r
+ posPrev = curOptimum.PosPrev2;\r
+ pos = curOptimum.BackPrev2;\r
+ state.UpdateRep();\r
+ }\r
+ else\r
+ {\r
+ pos = curOptimum.BackPrev;\r
+ if (pos < kNumRepDistances)\r
+ state.UpdateRep();\r
+ else\r
+ state.UpdateMatch();\r
+ }\r
+ const COptimal &prevOptimum = _optimum[posPrev];\r
+ if (pos < kNumRepDistances)\r
+ {\r
+ reps[0] = prevOptimum.Backs[pos];\r
+ UInt32 i;\r
+ for(i = 1; i <= pos; i++)\r
+ reps[i] = prevOptimum.Backs[i - 1];\r
+ for(; i < kNumRepDistances; i++)\r
+ reps[i] = prevOptimum.Backs[i];\r
+ }\r
+ else\r
+ {\r
+ reps[0] = (pos - kNumRepDistances);\r
+ for(UInt32 i = 1; i < kNumRepDistances; i++)\r
+ reps[i] = prevOptimum.Backs[i - 1];\r
+ }\r
+ }\r
+ curOptimum.State = state;\r
+ for(UInt32 i = 0; i < kNumRepDistances; i++)\r
+ curOptimum.Backs[i] = reps[i];\r
+ UInt32 curPrice = curOptimum.Price; \r
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;\r
+ const Byte currentByte = *data;\r
+ const Byte matchByte = data[(size_t)0 - reps[0] - 1];\r
+\r
+ UInt32 posState = (position & _posStateMask);\r
+\r
+ UInt32 curAnd1Price = curPrice +\r
+ _isMatch[state.Index][posState].GetPrice0() +\r
+ _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte);\r
+\r
+ COptimal &nextOptimum = _optimum[cur + 1];\r
+\r
+ bool nextIsChar = false;\r
+ if (curAnd1Price < nextOptimum.Price) \r
+ {\r
+ nextOptimum.Price = curAnd1Price;\r
+ nextOptimum.PosPrev = cur;\r
+ nextOptimum.MakeAsChar();\r
+ nextIsChar = true;\r
+ }\r
+\r
+ UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();\r
+ UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();\r
+ \r
+ if(matchByte == currentByte &&\r
+ !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))\r
+ {\r
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);\r
+ if(shortRepPrice <= nextOptimum.Price)\r
+ {\r
+ nextOptimum.Price = shortRepPrice;\r
+ nextOptimum.PosPrev = cur;\r
+ nextOptimum.MakeAsShortRep();\r
+ nextIsChar = true;\r
+ }\r
+ }\r
+ /*\r
+ if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?\r
+ continue;\r
+ */\r
+\r
+ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1;\r
+ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);\r
+ UInt32 numAvailableBytes = numAvailableBytesFull;\r
+\r
+ if (numAvailableBytes < 2)\r
+ continue;\r
+ if (numAvailableBytes > _numFastBytes)\r
+ numAvailableBytes = _numFastBytes;\r
+ if (!nextIsChar && matchByte != currentByte) // speed optimization\r
+ {\r
+ // try Literal + rep0\r
+ UInt32 backOffset = reps[0] + 1;\r
+ UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1);\r
+ UInt32 temp;\r
+ for (temp = 1; temp < limit && \r
+ data[temp] == data[(size_t)temp - backOffset]; temp++);\r
+ UInt32 lenTest2 = temp - 1;\r
+ if (lenTest2 >= 2)\r
+ {\r
+ CState state2 = state;\r
+ state2.UpdateChar();\r
+ UInt32 posStateNext = (position + 1) & _posStateMask;\r
+ UInt32 nextRepMatchPrice = curAnd1Price + \r
+ _isMatch[state2.Index][posStateNext].GetPrice1() +\r
+ _isRep[state2.Index].GetPrice1();\r
+ // for (; lenTest2 >= 2; lenTest2--)\r
+ {\r
+ UInt32 offset = cur + 1 + lenTest2;\r
+ while(lenEnd < offset)\r
+ _optimum[++lenEnd].Price = kIfinityPrice;\r
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(\r
+ 0, lenTest2, state2, posStateNext);\r
+ COptimal &optimum = _optimum[offset];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = cur + 1;\r
+ optimum.BackPrev = 0;\r
+ optimum.Prev1IsChar = true;\r
+ optimum.Prev2 = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ UInt32 startLen = 2; // speed optimization \r
+ for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)\r
+ {\r
+ // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;\r
+ UInt32 backOffset = reps[repIndex] + 1;\r
+ if (data[0] != data[(size_t)0 - backOffset] ||\r
+ data[1] != data[(size_t)1 - backOffset])\r
+ continue;\r
+ UInt32 lenTest;\r
+ for (lenTest = 2; lenTest < numAvailableBytes && \r
+ data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++);\r
+ while(lenEnd < cur + lenTest)\r
+ _optimum[++lenEnd].Price = kIfinityPrice;\r
+ UInt32 lenTestTemp = lenTest;\r
+ UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);\r
+ do\r
+ {\r
+ UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);\r
+ COptimal &optimum = _optimum[cur + lenTest];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = cur;\r
+ optimum.BackPrev = repIndex;\r
+ optimum.Prev1IsChar = false;\r
+ }\r
+ }\r
+ while(--lenTest >= 2);\r
+ lenTest = lenTestTemp;\r
+ \r
+ if (repIndex == 0)\r
+ startLen = lenTest + 1;\r
+ \r
+ // if (_maxMode)\r
+ {\r
+ UInt32 lenTest2 = lenTest + 1;\r
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);\r
+ for (; lenTest2 < limit && \r
+ data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);\r
+ lenTest2 -= lenTest + 1;\r
+ if (lenTest2 >= 2)\r
+ {\r
+ CState state2 = state;\r
+ state2.UpdateRep();\r
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;\r
+ UInt32 curAndLenCharPrice = \r
+ price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + \r
+ _isMatch[state2.Index][posStateNext].GetPrice0() +\r
+ _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice(\r
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);\r
+ state2.UpdateChar();\r
+ posStateNext = (position + lenTest + 1) & _posStateMask;\r
+ UInt32 nextRepMatchPrice = curAndLenCharPrice + \r
+ _isMatch[state2.Index][posStateNext].GetPrice1() +\r
+ _isRep[state2.Index].GetPrice1();\r
+ \r
+ // for(; lenTest2 >= 2; lenTest2--)\r
+ {\r
+ UInt32 offset = cur + lenTest + 1 + lenTest2;\r
+ while(lenEnd < offset)\r
+ _optimum[++lenEnd].Price = kIfinityPrice;\r
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(\r
+ 0, lenTest2, state2, posStateNext);\r
+ COptimal &optimum = _optimum[offset];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = cur + lenTest + 1;\r
+ optimum.BackPrev = 0;\r
+ optimum.Prev1IsChar = true;\r
+ optimum.Prev2 = true;\r
+ optimum.PosPrev2 = cur;\r
+ optimum.BackPrev2 = repIndex;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)\r
+ if (newLen > numAvailableBytes)\r
+ {\r
+ newLen = numAvailableBytes;\r
+ for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);\r
+ matchDistances[numDistancePairs] = newLen;\r
+ numDistancePairs += 2;\r
+ }\r
+ if (newLen >= startLen)\r
+ {\r
+ UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();\r
+ while(lenEnd < cur + newLen)\r
+ _optimum[++lenEnd].Price = kIfinityPrice;\r
+\r
+ UInt32 offs = 0;\r
+ while(startLen > matchDistances[offs])\r
+ offs += 2;\r
+ UInt32 curBack = matchDistances[offs + 1];\r
+ UInt32 posSlot = GetPosSlot2(curBack);\r
+ for(UInt32 lenTest = /*2*/ startLen; ; lenTest++)\r
+ {\r
+ UInt32 curAndLenPrice = normalMatchPrice;\r
+ UInt32 lenToPosState = GetLenToPosState(lenTest);\r
+ if (curBack < kNumFullDistances)\r
+ curAndLenPrice += _distancesPrices[lenToPosState][curBack];\r
+ else\r
+ curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask];\r
+ \r
+ curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);\r
+ \r
+ COptimal &optimum = _optimum[cur + lenTest];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = cur;\r
+ optimum.BackPrev = curBack + kNumRepDistances;\r
+ optimum.Prev1IsChar = false;\r
+ }\r
+\r
+ if (/*_maxMode && */lenTest == matchDistances[offs])\r
+ {\r
+ // Try Match + Literal + Rep0\r
+ UInt32 backOffset = curBack + 1;\r
+ UInt32 lenTest2 = lenTest + 1;\r
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);\r
+ for (; lenTest2 < limit && \r
+ data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);\r
+ lenTest2 -= lenTest + 1;\r
+ if (lenTest2 >= 2)\r
+ {\r
+ CState state2 = state;\r
+ state2.UpdateMatch();\r
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;\r
+ UInt32 curAndLenCharPrice = curAndLenPrice + \r
+ _isMatch[state2.Index][posStateNext].GetPrice0() +\r
+ _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( \r
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);\r
+ state2.UpdateChar();\r
+ posStateNext = (posStateNext + 1) & _posStateMask;\r
+ UInt32 nextRepMatchPrice = curAndLenCharPrice + \r
+ _isMatch[state2.Index][posStateNext].GetPrice1() +\r
+ _isRep[state2.Index].GetPrice1();\r
+ \r
+ // for(; lenTest2 >= 2; lenTest2--)\r
+ {\r
+ UInt32 offset = cur + lenTest + 1 + lenTest2;\r
+ while(lenEnd < offset)\r
+ _optimum[++lenEnd].Price = kIfinityPrice;\r
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);\r
+ COptimal &optimum = _optimum[offset];\r
+ if (curAndLenPrice < optimum.Price) \r
+ {\r
+ optimum.Price = curAndLenPrice;\r
+ optimum.PosPrev = cur + lenTest + 1;\r
+ optimum.BackPrev = 0;\r
+ optimum.Prev1IsChar = true;\r
+ optimum.Prev2 = true;\r
+ optimum.PosPrev2 = cur;\r
+ optimum.BackPrev2 = curBack + kNumRepDistances;\r
+ }\r
+ }\r
+ }\r
+ offs += 2;\r
+ if (offs == numDistancePairs)\r
+ break;\r
+ curBack = matchDistances[offs + 1];\r
+ if (curBack >= kNumFullDistances)\r
+ posSlot = GetPosSlot2(curBack);\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)\r
+{\r
+ return ((bigDist >> 7) > smallDist);\r
+}\r
+\r
+\r
+HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs)\r
+{\r
+ lenRes = 0;\r
+ RINOK(_matchFinder->GetMatches(_matchDistances));\r
+ numDistancePairs = _matchDistances[0];\r
+ if (numDistancePairs > 0)\r
+ {\r
+ lenRes = _matchDistances[1 + numDistancePairs - 2];\r
+ if (lenRes == _numFastBytes)\r
+ lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1], \r
+ kMatchMaxLen - lenRes);\r
+ }\r
+ _additionalOffset++;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)\r
+{\r
+ UInt32 lenMain, numDistancePairs;\r
+ if (!_longestMatchWasFound)\r
+ {\r
+ RINOK(ReadMatchDistances(lenMain, numDistancePairs));\r
+ }\r
+ else\r
+ {\r
+ lenMain = _longestMatchLength;\r
+ numDistancePairs = _numDistancePairs;\r
+ _longestMatchWasFound = false;\r
+ }\r
+\r
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;\r
+ UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;\r
+ if (numAvailableBytes > kMatchMaxLen)\r
+ numAvailableBytes = kMatchMaxLen;\r
+ if (numAvailableBytes < 2)\r
+ {\r
+ backRes = (UInt32)(-1);\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+\r
+ UInt32 repLens[kNumRepDistances];\r
+ UInt32 repMaxIndex = 0;\r
+\r
+ for(UInt32 i = 0; i < kNumRepDistances; i++)\r
+ {\r
+ UInt32 backOffset = _repDistances[i] + 1;\r
+ if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset])\r
+ {\r
+ repLens[i] = 0;\r
+ continue;\r
+ }\r
+ UInt32 len;\r
+ for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);\r
+ if(len >= _numFastBytes)\r
+ {\r
+ backRes = i;\r
+ lenRes = len;\r
+ return MovePos(lenRes - 1);\r
+ }\r
+ repLens[i] = len;\r
+ if (len > repLens[repMaxIndex])\r
+ repMaxIndex = i;\r
+ }\r
+ UInt32 *matchDistances = _matchDistances + 1;\r
+ if(lenMain >= _numFastBytes)\r
+ {\r
+ backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; \r
+ lenRes = lenMain;\r
+ return MovePos(lenMain - 1);\r
+ }\r
+\r
+ UInt32 backMain = 0;\r
+ if (lenMain >= 2)\r
+ {\r
+ backMain = matchDistances[numDistancePairs - 1];\r
+ while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)\r
+ {\r
+ if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))\r
+ break;\r
+ numDistancePairs -= 2;\r
+ lenMain = matchDistances[numDistancePairs - 2];\r
+ backMain = matchDistances[numDistancePairs - 1];\r
+ }\r
+ if (lenMain == 2 && backMain >= 0x80)\r
+ lenMain = 1;\r
+ }\r
+\r
+ if (repLens[repMaxIndex] >= 2)\r
+ {\r
+ if (repLens[repMaxIndex] + 1 >= lenMain || \r
+ repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||\r
+ repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))\r
+ {\r
+ backRes = repMaxIndex;\r
+ lenRes = repLens[repMaxIndex];\r
+ return MovePos(lenRes - 1);\r
+ }\r
+ }\r
+ \r
+ if (lenMain >= 2 && numAvailableBytes > 2)\r
+ {\r
+ RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs));\r
+ if (_longestMatchLength >= 2)\r
+ {\r
+ UInt32 newDistance = matchDistances[_numDistancePairs - 1];\r
+ if (_longestMatchLength >= lenMain && newDistance < backMain || \r
+ _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||\r
+ _longestMatchLength > lenMain + 1 ||\r
+ _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))\r
+ {\r
+ _longestMatchWasFound = true;\r
+ backRes = UInt32(-1);\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+ }\r
+ data++;\r
+ numAvailableBytes--;\r
+ for(UInt32 i = 0; i < kNumRepDistances; i++)\r
+ {\r
+ UInt32 backOffset = _repDistances[i] + 1;\r
+ if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset])\r
+ {\r
+ repLens[i] = 0;\r
+ continue;\r
+ }\r
+ UInt32 len;\r
+ for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);\r
+ if (len + 1 >= lenMain)\r
+ {\r
+ _longestMatchWasFound = true;\r
+ backRes = UInt32(-1);\r
+ lenRes = 1;\r
+ return S_OK;\r
+ }\r
+ }\r
+ backRes = backMain + kNumRepDistances; \r
+ lenRes = lenMain;\r
+ return MovePos(lenMain - 2);\r
+ }\r
+ backRes = UInt32(-1);\r
+ lenRes = 1;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::Flush(UInt32 nowPos)\r
+{\r
+ ReleaseMFStream();\r
+ WriteEndMarker(nowPos & _posStateMask);\r
+ _rangeEncoder.FlushData();\r
+ return _rangeEncoder.FlushStream();\r
+}\r
+\r
+void CEncoder::WriteEndMarker(UInt32 posState)\r
+{\r
+ // This function for writing End Mark for stream version of LZMA. \r
+ // In current version this feature is not used.\r
+ if (!_writeEndMark)\r
+ return;\r
+\r
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);\r
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);\r
+ _state.UpdateMatch();\r
+ UInt32 len = kMatchMinLen; // kMatchMaxLen;\r
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);\r
+ UInt32 posSlot = (1 << kNumPosSlotBits) - 1;\r
+ UInt32 lenToPosState = GetLenToPosState(len);\r
+ _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);\r
+ UInt32 footerBits = 30;\r
+ UInt32 posReduced = (UInt32(1) << footerBits) - 1;\r
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);\r
+}\r
+\r
+HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, \r
+ const UInt64 *inSize, const UInt64 *outSize,\r
+ ICompressProgressInfo *progress)\r
+{\r
+ _needReleaseMFStream = false;\r
+ CCoderReleaser coderReleaser(this);\r
+ RINOK(SetStreams(inStream, outStream, inSize, outSize));\r
+ while(true)\r
+ {\r
+ UInt64 processedInSize;\r
+ UInt64 processedOutSize;\r
+ Int32 finished;\r
+ RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));\r
+ if (finished != 0)\r
+ return S_OK;\r
+ if (progress != 0)\r
+ {\r
+ RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));\r
+ }\r
+ }\r
+}\r
+\r
+HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, \r
+ const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+ _inStream = inStream;\r
+ _finished = false;\r
+ RINOK(Create());\r
+ RINOK(SetOutStream(outStream));\r
+ RINOK(Init());\r
+ \r
+ // CCoderReleaser releaser(this);\r
+\r
+ /*\r
+ if (_matchFinder->GetNumAvailableBytes() == 0)\r
+ return Flush();\r
+ */\r
+\r
+ if (!_fastMode)\r
+ {\r
+ FillDistancesPrices();\r
+ FillAlignPrices();\r
+ }\r
+\r
+ _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);\r
+ _lenEncoder.UpdateTables(1 << _posStateBits);\r
+ _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);\r
+ _repMatchLenEncoder.UpdateTables(1 << _posStateBits);\r
+\r
+ nowPos64 = 0;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)\r
+{\r
+ if (_inStream != 0)\r
+ {\r
+ RINOK(_matchFinder->SetStream(_inStream));\r
+ RINOK(_matchFinder->Init());\r
+ _needReleaseMFStream = true;\r
+ _inStream = 0;\r
+ }\r
+\r
+\r
+ *finished = 1;\r
+ if (_finished)\r
+ return S_OK;\r
+ _finished = true;\r
+\r
+ if (nowPos64 == 0)\r
+ {\r
+ if (_matchFinder->GetNumAvailableBytes() == 0)\r
+ return Flush(UInt32(nowPos64));\r
+ UInt32 len, numDistancePairs;\r
+ RINOK(ReadMatchDistances(len, numDistancePairs));\r
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;\r
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);\r
+ _state.UpdateChar();\r
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);\r
+ _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);\r
+ _previousByte = curByte;\r
+ _additionalOffset--;\r
+ nowPos64++;\r
+ }\r
+\r
+ UInt32 nowPos32 = (UInt32)nowPos64;\r
+ UInt32 progressPosValuePrev = nowPos32;\r
+\r
+ if (_matchFinder->GetNumAvailableBytes() == 0)\r
+ return Flush(nowPos32);\r
+\r
+ while(true)\r
+ {\r
+ #ifdef _NO_EXCEPTIONS\r
+ if (_rangeEncoder.Stream.ErrorCode != S_OK)\r
+ return _rangeEncoder.Stream.ErrorCode;\r
+ #endif\r
+ UInt32 pos, len;\r
+ HRESULT result;\r
+ if (_fastMode)\r
+ result = GetOptimumFast(nowPos32, pos, len);\r
+ else\r
+ result = GetOptimum(nowPos32, pos, len);\r
+ RINOK(result);\r
+\r
+ UInt32 posState = nowPos32 & _posStateMask;\r
+ if(len == 1 && pos == 0xFFFFFFFF)\r
+ {\r
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);\r
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);\r
+ CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);\r
+ if(_state.IsCharState())\r
+ subCoder->Encode(&_rangeEncoder, curByte);\r
+ else\r
+ {\r
+ Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);\r
+ subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);\r
+ }\r
+ _state.UpdateChar();\r
+ _previousByte = curByte;\r
+ }\r
+ else\r
+ {\r
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);\r
+ if(pos < kNumRepDistances)\r
+ {\r
+ _isRep[_state.Index].Encode(&_rangeEncoder, 1);\r
+ if(pos == 0)\r
+ {\r
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);\r
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));\r
+ }\r
+ else\r
+ {\r
+ UInt32 distance = _repDistances[pos];\r
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);\r
+ if (pos == 1)\r
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);\r
+ else\r
+ {\r
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);\r
+ _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);\r
+ if (pos == 3)\r
+ _repDistances[3] = _repDistances[2];\r
+ _repDistances[2] = _repDistances[1];\r
+ }\r
+ _repDistances[1] = _repDistances[0];\r
+ _repDistances[0] = distance;\r
+ }\r
+ if (len == 1)\r
+ _state.UpdateShortRep();\r
+ else\r
+ {\r
+ _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);\r
+ _state.UpdateRep();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);\r
+ _state.UpdateMatch();\r
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);\r
+ pos -= kNumRepDistances;\r
+ UInt32 posSlot = GetPosSlot(pos);\r
+ _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);\r
+ \r
+ if (posSlot >= kStartPosModelIndex)\r
+ {\r
+ UInt32 footerBits = ((posSlot >> 1) - 1);\r
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
+ UInt32 posReduced = pos - base;\r
+\r
+ if (posSlot < kEndPosModelIndex)\r
+ NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, \r
+ &_rangeEncoder, footerBits, posReduced);\r
+ else\r
+ {\r
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);\r
+ _alignPriceCount++;\r
+ }\r
+ }\r
+ _repDistances[3] = _repDistances[2];\r
+ _repDistances[2] = _repDistances[1];\r
+ _repDistances[1] = _repDistances[0];\r
+ _repDistances[0] = pos;\r
+ _matchPriceCount++;\r
+ }\r
+ _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);\r
+ }\r
+ _additionalOffset -= len;\r
+ nowPos32 += len;\r
+ if (_additionalOffset == 0)\r
+ {\r
+ if (!_fastMode)\r
+ {\r
+ if (_matchPriceCount >= (1 << 7))\r
+ FillDistancesPrices();\r
+ if (_alignPriceCount >= kAlignTableSize)\r
+ FillAlignPrices();\r
+ }\r
+ if (_matchFinder->GetNumAvailableBytes() == 0)\r
+ return Flush(nowPos32);\r
+ if (nowPos32 - progressPosValuePrev >= (1 << 14))\r
+ {\r
+ nowPos64 += nowPos32 - progressPosValuePrev;\r
+ *inSize = nowPos64;\r
+ *outSize = _rangeEncoder.GetProcessedSize();\r
+ _finished = false;\r
+ *finished = 0;\r
+ return S_OK;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+ ICompressProgressInfo *progress)\r
+{\r
+ #ifndef _NO_EXCEPTIONS\r
+ try \r
+ { \r
+ #endif\r
+ return CodeReal(inStream, outStream, inSize, outSize, progress); \r
+ #ifndef _NO_EXCEPTIONS\r
+ }\r
+ catch(const COutBufferException &e) { return e.ErrorCode; }\r
+ catch(...) { return E_FAIL; }\r
+ #endif\r
+}\r
+ \r
+void CEncoder::FillDistancesPrices()\r
+{\r
+ UInt32 tempPrices[kNumFullDistances];\r
+ for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)\r
+ { \r
+ UInt32 posSlot = GetPosSlot(i);\r
+ UInt32 footerBits = ((posSlot >> 1) - 1);\r
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
+ tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + \r
+ base - posSlot - 1, footerBits, i - base);\r
+ }\r
+\r
+ for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)\r
+ {\r
+ UInt32 posSlot;\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];\r
+ UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];\r
+ for (posSlot = 0; posSlot < _distTableSize; posSlot++)\r
+ posSlotPrices[posSlot] = encoder.GetPrice(posSlot);\r
+ for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)\r
+ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);\r
+\r
+ UInt32 *distancesPrices = _distancesPrices[lenToPosState];\r
+ UInt32 i;\r
+ for (i = 0; i < kStartPosModelIndex; i++)\r
+ distancesPrices[i] = posSlotPrices[i];\r
+ for (; i < kNumFullDistances; i++)\r
+ distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];\r
+ }\r
+ _matchPriceCount = 0;\r
+}\r
+\r
+void CEncoder::FillAlignPrices()\r
+{\r
+ for (UInt32 i = 0; i < kAlignTableSize; i++)\r
+ _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);\r
+ _alignPriceCount = 0;\r
+}\r
+\r
+}}\r
--- /dev/null
+// LZMA/Encoder.h\r
+\r
+#ifndef __LZMA_ENCODER_H\r
+#define __LZMA_ENCODER_H\r
+\r
+#include "../../../Common/MyCom.h"\r
+#include "../../../Common/Alloc.h"\r
+#include "../../ICoder.h"\r
+#include "../LZ/IMatchFinder.h"\r
+#include "../RangeCoder/RangeCoderBitTree.h"\r
+\r
+#include "LZMA.h"\r
+\r
+namespace NCompress {\r
+namespace NLZMA {\r
+\r
+typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;\r
+\r
+class CBaseState\r
+{\r
+protected:\r
+ CState _state;\r
+ Byte _previousByte;\r
+ UInt32 _repDistances[kNumRepDistances];\r
+ void Init()\r
+ {\r
+ _state.Init();\r
+ _previousByte = 0;\r
+ for(UInt32 i = 0 ; i < kNumRepDistances; i++)\r
+ _repDistances[i] = 0;\r
+ }\r
+};\r
+\r
+struct COptimal\r
+{\r
+ CState State;\r
+\r
+ bool Prev1IsChar;\r
+ bool Prev2;\r
+\r
+ UInt32 PosPrev2;\r
+ UInt32 BackPrev2; \r
+\r
+ UInt32 Price; \r
+ UInt32 PosPrev; // posNext;\r
+ UInt32 BackPrev; \r
+ UInt32 Backs[kNumRepDistances];\r
+ void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }\r
+ void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }\r
+ bool IsShortRep() { return (BackPrev == 0); }\r
+};\r
+\r
+\r
+extern Byte g_FastPos[1 << 11];\r
+inline UInt32 GetPosSlot(UInt32 pos)\r
+{\r
+ if (pos < (1 << 11))\r
+ return g_FastPos[pos];\r
+ if (pos < (1 << 21))\r
+ return g_FastPos[pos >> 10] + 20;\r
+ return g_FastPos[pos >> 20] + 40;\r
+}\r
+\r
+inline UInt32 GetPosSlot2(UInt32 pos)\r
+{\r
+ if (pos < (1 << 17))\r
+ return g_FastPos[pos >> 6] + 12;\r
+ if (pos < (1 << 27))\r
+ return g_FastPos[pos >> 16] + 32;\r
+ return g_FastPos[pos >> 26] + 52;\r
+}\r
+\r
+const UInt32 kIfinityPrice = 0xFFFFFFF;\r
+\r
+const UInt32 kNumOpts = 1 << 12;\r
+\r
+\r
+class CLiteralEncoder2\r
+{\r
+ CMyBitEncoder _encoders[0x300];\r
+public:\r
+ void Init()\r
+ {\r
+ for (int i = 0; i < 0x300; i++)\r
+ _encoders[i].Init();\r
+ }\r
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);\r
+ void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);\r
+ UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;\r
+};\r
+\r
+class CLiteralEncoder\r
+{\r
+ CLiteralEncoder2 *_coders;\r
+ int _numPrevBits;\r
+ int _numPosBits;\r
+ UInt32 _posMask;\r
+public:\r
+ CLiteralEncoder(): _coders(0) {}\r
+ ~CLiteralEncoder() { Free(); }\r
+ void Free()\r
+ { \r
+ MyFree(_coders);\r
+ _coders = 0;\r
+ }\r
+ bool Create(int numPosBits, int numPrevBits)\r
+ {\r
+ if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))\r
+ {\r
+ Free();\r
+ UInt32 numStates = 1 << (numPosBits + numPrevBits);\r
+ _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));\r
+ }\r
+ _numPosBits = numPosBits;\r
+ _posMask = (1 << numPosBits) - 1;\r
+ _numPrevBits = numPrevBits;\r
+ return (_coders != 0);\r
+ }\r
+ void Init()\r
+ {\r
+ UInt32 numStates = 1 << (_numPrevBits + _numPosBits);\r
+ for (UInt32 i = 0; i < numStates; i++)\r
+ _coders[i].Init();\r
+ }\r
+ CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)\r
+ { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }\r
+};\r
+\r
+namespace NLength {\r
+\r
+class CEncoder\r
+{\r
+ CMyBitEncoder _choice;\r
+ CMyBitEncoder _choice2;\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;\r
+public:\r
+ void Init(UInt32 numPosStates);\r
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);\r
+ void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;\r
+};\r
+\r
+const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;\r
+\r
+class CPriceTableEncoder: public CEncoder\r
+{\r
+ UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];\r
+ UInt32 _tableSize;\r
+ UInt32 _counters[kNumPosStatesEncodingMax];\r
+public:\r
+ void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }\r
+ UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }\r
+ void UpdateTable(UInt32 posState)\r
+ {\r
+ SetPrices(posState, _tableSize, _prices[posState]);\r
+ _counters[posState] = _tableSize;\r
+ }\r
+ void UpdateTables(UInt32 numPosStates)\r
+ {\r
+ for (UInt32 posState = 0; posState < numPosStates; posState++)\r
+ UpdateTable(posState);\r
+ }\r
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)\r
+ {\r
+ CEncoder::Encode(rangeEncoder, symbol, posState);\r
+ if (updatePrice)\r
+ if (--_counters[posState] == 0)\r
+ UpdateTable(posState);\r
+ }\r
+};\r
+\r
+}\r
+\r
+class CEncoder : \r
+ public ICompressCoder,\r
+ public ICompressSetOutStream,\r
+ public ICompressSetCoderProperties,\r
+ public ICompressWriteCoderProperties,\r
+ public CBaseState,\r
+ public CMyUnknownImp\r
+{\r
+ COptimal _optimum[kNumOpts];\r
+ CMyComPtr<IMatchFinder> _matchFinder; // test it\r
+ NRangeCoder::CEncoder _rangeEncoder;\r
+\r
+ CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];\r
+ CMyBitEncoder _isRep[kNumStates];\r
+ CMyBitEncoder _isRepG0[kNumStates];\r
+ CMyBitEncoder _isRepG1[kNumStates];\r
+ CMyBitEncoder _isRepG2[kNumStates];\r
+ CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];\r
+\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];\r
+\r
+ CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];\r
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;\r
+ \r
+ NLength::CPriceTableEncoder _lenEncoder;\r
+ NLength::CPriceTableEncoder _repMatchLenEncoder;\r
+\r
+ CLiteralEncoder _literalEncoder;\r
+\r
+ UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];\r
+\r
+ bool _fastMode;\r
+ // bool _maxMode;\r
+ UInt32 _numFastBytes;\r
+ UInt32 _longestMatchLength; \r
+ UInt32 _numDistancePairs;\r
+\r
+ UInt32 _additionalOffset;\r
+\r
+ UInt32 _optimumEndIndex;\r
+ UInt32 _optimumCurrentIndex;\r
+\r
+ bool _longestMatchWasFound;\r
+\r
+ UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\r
+ \r
+ UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];\r
+\r
+ UInt32 _alignPrices[kAlignTableSize];\r
+ UInt32 _alignPriceCount;\r
+\r
+ UInt32 _distTableSize;\r
+\r
+ UInt32 _posStateBits;\r
+ UInt32 _posStateMask;\r
+ UInt32 _numLiteralPosStateBits;\r
+ UInt32 _numLiteralContextBits;\r
+\r
+ UInt32 _dictionarySize;\r
+\r
+ UInt32 _dictionarySizePrev;\r
+ UInt32 _numFastBytesPrev;\r
+\r
+ UInt32 _matchPriceCount;\r
+ UInt64 nowPos64;\r
+ bool _finished;\r
+ ISequentialInStream *_inStream;\r
+\r
+ UInt32 _matchFinderCycles;\r
+ int _matchFinderIndex;\r
+ #ifdef COMPRESS_MF_MT\r
+ bool _multiThread;\r
+ #endif\r
+\r
+ bool _writeEndMark;\r
+\r
+ bool _needReleaseMFStream;\r
+\r
+ IMatchFinderSetNumPasses *setMfPasses;\r
+\r
+ void ReleaseMatchFinder()\r
+ {\r
+ setMfPasses = 0;\r
+ _matchFinder.Release();\r
+ }\r
+ \r
+ HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);\r
+\r
+ HRESULT MovePos(UInt32 num);\r
+ UInt32 GetRepLen1Price(CState state, UInt32 posState) const\r
+ {\r
+ return _isRepG0[state.Index].GetPrice0() +\r
+ _isRep0Long[state.Index][posState].GetPrice0();\r
+ }\r
+ \r
+ UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const\r
+ {\r
+ UInt32 price;\r
+ if(repIndex == 0)\r
+ {\r
+ price = _isRepG0[state.Index].GetPrice0();\r
+ price += _isRep0Long[state.Index][posState].GetPrice1();\r
+ }\r
+ else\r
+ {\r
+ price = _isRepG0[state.Index].GetPrice1();\r
+ if (repIndex == 1)\r
+ price += _isRepG1[state.Index].GetPrice0();\r
+ else\r
+ {\r
+ price += _isRepG1[state.Index].GetPrice1();\r
+ price += _isRepG2[state.Index].GetPrice(repIndex - 2);\r
+ }\r
+ }\r
+ return price;\r
+ }\r
+ UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const\r
+ {\r
+ return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +\r
+ GetPureRepPrice(repIndex, state, posState);\r
+ }\r
+ /*\r
+ UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const\r
+ {\r
+ if (pos >= kNumFullDistances)\r
+ return kIfinityPrice;\r
+ return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);\r
+ }\r
+ UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const\r
+ {\r
+ UInt32 price;\r
+ UInt32 lenToPosState = GetLenToPosState(len);\r
+ if (pos < kNumFullDistances)\r
+ price = _distancesPrices[lenToPosState][pos];\r
+ else\r
+ price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + \r
+ _alignPrices[pos & kAlignMask];\r
+ return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);\r
+ }\r
+ */\r
+ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const\r
+ {\r
+ UInt32 price;\r
+ UInt32 lenToPosState = GetLenToPosState(len);\r
+ if (pos < kNumFullDistances)\r
+ price = _distancesPrices[lenToPosState][pos];\r
+ else\r
+ price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + \r
+ _alignPrices[pos & kAlignMask];\r
+ return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);\r
+ }\r
+\r
+ UInt32 Backward(UInt32 &backRes, UInt32 cur);\r
+ HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);\r
+ HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);\r
+\r
+ void FillDistancesPrices();\r
+ void FillAlignPrices();\r
+ \r
+ void ReleaseMFStream()\r
+ {\r
+ if (_matchFinder && _needReleaseMFStream)\r
+ {\r
+ _matchFinder->ReleaseStream();\r
+ _needReleaseMFStream = false;\r
+ }\r
+ }\r
+\r
+ void ReleaseStreams()\r
+ {\r
+ ReleaseMFStream();\r
+ ReleaseOutStream();\r
+ }\r
+\r
+ HRESULT Flush(UInt32 nowPos);\r
+ class CCoderReleaser\r
+ {\r
+ CEncoder *_coder;\r
+ public:\r
+ CCoderReleaser(CEncoder *coder): _coder(coder) {}\r
+ ~CCoderReleaser()\r
+ {\r
+ _coder->ReleaseStreams();\r
+ }\r
+ };\r
+ friend class CCoderReleaser;\r
+\r
+ void WriteEndMarker(UInt32 posState);\r
+\r
+public:\r
+ CEncoder();\r
+ void SetWriteEndMarkerMode(bool writeEndMarker)\r
+ { _writeEndMark= writeEndMarker; }\r
+\r
+ HRESULT Create();\r
+\r
+ MY_UNKNOWN_IMP3(\r
+ ICompressSetOutStream,\r
+ ICompressSetCoderProperties,\r
+ ICompressWriteCoderProperties\r
+ )\r
+ \r
+ HRESULT Init();\r
+ \r
+ // ICompressCoder interface\r
+ HRESULT SetStreams(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream,\r
+ const UInt64 *inSize, const UInt64 *outSize);\r
+ HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);\r
+\r
+ HRESULT CodeReal(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, \r
+ const UInt64 *inSize, const UInt64 *outSize,\r
+ ICompressProgressInfo *progress);\r
+\r
+ // ICompressCoder interface\r
+ STDMETHOD(Code)(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, \r
+ const UInt64 *inSize, const UInt64 *outSize,\r
+ ICompressProgressInfo *progress);\r
+\r
+ // ICompressSetCoderProperties2\r
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, \r
+ const PROPVARIANT *properties, UInt32 numProperties);\r
+ \r
+ // ICompressWriteCoderProperties\r
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+\r
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);\r
+ STDMETHOD(ReleaseOutStream)();\r
+\r
+ virtual ~CEncoder() {}\r
+};\r
+\r
+}}\r
+\r
+#endif\r
--- /dev/null
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
--- /dev/null
+// Compress/RangeCoder/RangeCoder.h\r
+\r
+#ifndef __COMPRESS_RANGECODER_H\r
+#define __COMPRESS_RANGECODER_H\r
+\r
+#include "../../Common/InBuffer.h"\r
+#include "../../Common/OutBuffer.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+const int kNumTopBits = 24;\r
+const UInt32 kTopValue = (1 << kNumTopBits);\r
+\r
+class CEncoder\r
+{\r
+ UInt32 _cacheSize;\r
+ Byte _cache;\r
+public:\r
+ UInt64 Low;\r
+ UInt32 Range;\r
+ COutBuffer Stream;\r
+ bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+\r
+ void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }\r
+ void Init()\r
+ {\r
+ Stream.Init();\r
+ Low = 0;\r
+ Range = 0xFFFFFFFF;\r
+ _cacheSize = 1;\r
+ _cache = 0;\r
+ }\r
+\r
+ void FlushData()\r
+ {\r
+ // Low += 1; \r
+ for(int i = 0; i < 5; i++)\r
+ ShiftLow();\r
+ }\r
+\r
+ HRESULT FlushStream() { return Stream.Flush(); }\r
+\r
+ void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+ void Encode(UInt32 start, UInt32 size, UInt32 total)\r
+ {\r
+ Low += start * (Range /= total);\r
+ Range *= size;\r
+ while (Range < kTopValue)\r
+ {\r
+ Range <<= 8;\r
+ ShiftLow();\r
+ }\r
+ }\r
+\r
+ void ShiftLow()\r
+ {\r
+ if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) \r
+ {\r
+ Byte temp = _cache;\r
+ do\r
+ {\r
+ Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));\r
+ temp = 0xFF;\r
+ }\r
+ while(--_cacheSize != 0);\r
+ _cache = (Byte)((UInt32)Low >> 24); \r
+ } \r
+ _cacheSize++; \r
+ Low = (UInt32)Low << 8; \r
+ }\r
+ \r
+ void EncodeDirectBits(UInt32 value, int numTotalBits)\r
+ {\r
+ for (int i = numTotalBits - 1; i >= 0; i--)\r
+ {\r
+ Range >>= 1;\r
+ if (((value >> i) & 1) == 1)\r
+ Low += Range;\r
+ if (Range < kTopValue)\r
+ {\r
+ Range <<= 8;\r
+ ShiftLow();\r
+ }\r
+ }\r
+ }\r
+\r
+ void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)\r
+ {\r
+ UInt32 newBound = (Range >> numTotalBits) * size0;\r
+ if (symbol == 0)\r
+ Range = newBound;\r
+ else\r
+ {\r
+ Low += newBound;\r
+ Range -= newBound;\r
+ }\r
+ while (Range < kTopValue)\r
+ {\r
+ Range <<= 8;\r
+ ShiftLow();\r
+ }\r
+ }\r
+\r
+ UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }\r
+};\r
+\r
+class CDecoder\r
+{\r
+public:\r
+ CInBuffer Stream;\r
+ UInt32 Range;\r
+ UInt32 Code;\r
+ bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+\r
+ void Normalize()\r
+ {\r
+ while (Range < kTopValue)\r
+ {\r
+ Code = (Code << 8) | Stream.ReadByte();\r
+ Range <<= 8;\r
+ }\r
+ }\r
+ \r
+ void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }\r
+ void Init()\r
+ {\r
+ Stream.Init();\r
+ Code = 0;\r
+ Range = 0xFFFFFFFF;\r
+ for(int i = 0; i < 5; i++)\r
+ Code = (Code << 8) | Stream.ReadByte();\r
+ }\r
+\r
+ void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+ UInt32 GetThreshold(UInt32 total)\r
+ {\r
+ return (Code) / ( Range /= total);\r
+ }\r
+\r
+ void Decode(UInt32 start, UInt32 size)\r
+ {\r
+ Code -= start * Range;\r
+ Range *= size;\r
+ Normalize();\r
+ }\r
+\r
+ UInt32 DecodeDirectBits(int numTotalBits)\r
+ {\r
+ UInt32 range = Range;\r
+ UInt32 code = Code; \r
+ UInt32 result = 0;\r
+ for (int i = numTotalBits; i != 0; i--)\r
+ {\r
+ range >>= 1;\r
+ /*\r
+ result <<= 1;\r
+ if (code >= range)\r
+ {\r
+ code -= range;\r
+ result |= 1;\r
+ }\r
+ */\r
+ UInt32 t = (code - range) >> 31;\r
+ code -= range & (t - 1);\r
+ result = (result << 1) | (1 - t);\r
+\r
+ if (range < kTopValue)\r
+ {\r
+ code = (code << 8) | Stream.ReadByte();\r
+ range <<= 8; \r
+ }\r
+ }\r
+ Range = range;\r
+ Code = code;\r
+ return result;\r
+ }\r
+\r
+ UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)\r
+ {\r
+ UInt32 newBound = (Range >> numTotalBits) * size0;\r
+ UInt32 symbol;\r
+ if (Code < newBound)\r
+ {\r
+ symbol = 0;\r
+ Range = newBound;\r
+ }\r
+ else\r
+ {\r
+ symbol = 1;\r
+ Code -= newBound;\r
+ Range -= newBound;\r
+ }\r
+ Normalize();\r
+ return symbol;\r
+ }\r
+\r
+ UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
--- /dev/null
+// Compress/RangeCoder/RangeCoderBit.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "RangeCoderBit.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
+static CPriceTables g_PriceTables;\r
+\r
+CPriceTables::CPriceTables() { Init(); }\r
+\r
+void CPriceTables::Init()\r
+{\r
+ const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);\r
+ for(int i = kNumBits - 1; i >= 0; i--)\r
+ {\r
+ UInt32 start = 1 << (kNumBits - i - 1);\r
+ UInt32 end = 1 << (kNumBits - i);\r
+ for (UInt32 j = start; j < end; j++)\r
+ ProbPrices[j] = (i << kNumBitPriceShiftBits) + \r
+ (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));\r
+ }\r
+\r
+ /*\r
+ // simplest: bad solution\r
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)\r
+ ProbPrices[i] = kBitPrice;\r
+ */\r
+ \r
+ /*\r
+ const double kDummyMultMid = (1.0 / kBitPrice) / 2;\r
+ const double kDummyMultMid = 0;\r
+ // float solution\r
+ double ln2 = log(double(2));\r
+ double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits));\r
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)\r
+ ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice);\r
+ */\r
+ \r
+ /*\r
+ // experimental, slow, solution:\r
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)\r
+ {\r
+ const int kCyclesBits = 5;\r
+ const UInt32 kCycles = (1 << kCyclesBits);\r
+\r
+ UInt32 range = UInt32(-1);\r
+ UInt32 bitCount = 0;\r
+ for (UInt32 j = 0; j < kCycles; j++)\r
+ {\r
+ range >>= (kNumBitModelTotalBits - kNumMoveReducingBits);\r
+ range *= i;\r
+ while(range < (1 << 31))\r
+ {\r
+ range <<= 1;\r
+ bitCount++;\r
+ }\r
+ }\r
+ bitCount <<= kNumBitPriceShiftBits;\r
+ range -= (1 << 31);\r
+ for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--)\r
+ {\r
+ range <<= 1;\r
+ if (range > (1 << 31))\r
+ {\r
+ bitCount += (1 << k);\r
+ range -= (1 << 31);\r
+ }\r
+ }\r
+ ProbPrices[i] = (bitCount \r
+ // + (1 << (kCyclesBits - 1))\r
+ ) >> kCyclesBits;\r
+ }\r
+ */\r
+}\r
+\r
+}}\r
--- /dev/null
+// Compress/RangeCoder/RangeCoderBit.h\r
+\r
+#ifndef __COMPRESS_RANGECODER_BIT_H\r
+#define __COMPRESS_RANGECODER_BIT_H\r
+\r
+#include "RangeCoder.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+const int kNumBitModelTotalBits = 11;\r
+const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);\r
+\r
+const int kNumMoveReducingBits = 2;\r
+\r
+const int kNumBitPriceShiftBits = 6;\r
+const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;\r
+\r
+class CPriceTables\r
+{\r
+public:\r
+ static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
+ static void Init();\r
+ CPriceTables();\r
+};\r
+\r
+template <int numMoveBits>\r
+class CBitModel\r
+{\r
+public:\r
+ UInt32 Prob;\r
+ void UpdateModel(UInt32 symbol)\r
+ {\r
+ /*\r
+ Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;\r
+ Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);\r
+ */\r
+ if (symbol == 0)\r
+ Prob += (kBitModelTotal - Prob) >> numMoveBits;\r
+ else\r
+ Prob -= (Prob) >> numMoveBits;\r
+ }\r
+public:\r
+ void Init() { Prob = kBitModelTotal / 2; }\r
+};\r
+\r
+template <int numMoveBits>\r
+class CBitEncoder: public CBitModel<numMoveBits>\r
+{\r
+public:\r
+ void Encode(CEncoder *encoder, UInt32 symbol)\r
+ {\r
+ /*\r
+ encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);\r
+ this->UpdateModel(symbol);\r
+ */\r
+ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;\r
+ if (symbol == 0)\r
+ {\r
+ encoder->Range = newBound;\r
+ this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;\r
+ }\r
+ else\r
+ {\r
+ encoder->Low += newBound;\r
+ encoder->Range -= newBound;\r
+ this->Prob -= (this->Prob) >> numMoveBits;\r
+ }\r
+ if (encoder->Range < kTopValue)\r
+ {\r
+ encoder->Range <<= 8;\r
+ encoder->ShiftLow();\r
+ }\r
+ }\r
+ UInt32 GetPrice(UInt32 symbol) const\r
+ {\r
+ return CPriceTables::ProbPrices[\r
+ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];\r
+ }\r
+ UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }\r
+ UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }\r
+};\r
+\r
+\r
+template <int numMoveBits>\r
+class CBitDecoder: public CBitModel<numMoveBits>\r
+{\r
+public:\r
+ UInt32 Decode(CDecoder *decoder)\r
+ {\r
+ UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;\r
+ if (decoder->Code < newBound)\r
+ {\r
+ decoder->Range = newBound;\r
+ this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;\r
+ if (decoder->Range < kTopValue)\r
+ {\r
+ decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();\r
+ decoder->Range <<= 8;\r
+ }\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ decoder->Range -= newBound;\r
+ decoder->Code -= newBound;\r
+ this->Prob -= (this->Prob) >> numMoveBits;\r
+ if (decoder->Range < kTopValue)\r
+ {\r
+ decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();\r
+ decoder->Range <<= 8;\r
+ }\r
+ return 1;\r
+ }\r
+ }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
--- /dev/null
+// Compress/RangeCoder/RangeCoderBitTree.h\r
+\r
+#ifndef __COMPRESS_RANGECODER_BIT_TREE_H\r
+#define __COMPRESS_RANGECODER_BIT_TREE_H\r
+\r
+#include "RangeCoderBit.h"\r
+#include "RangeCoderOpt.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+template <int numMoveBits, int NumBitLevels>\r
+class CBitTreeEncoder\r
+{\r
+ CBitEncoder<numMoveBits> Models[1 << NumBitLevels];\r
+public:\r
+ void Init()\r
+ {\r
+ for(UInt32 i = 1; i < (1 << NumBitLevels); i++)\r
+ Models[i].Init();\r
+ }\r
+ void Encode(CEncoder *rangeEncoder, UInt32 symbol)\r
+ {\r
+ UInt32 modelIndex = 1;\r
+ for (int bitIndex = NumBitLevels; bitIndex != 0 ;)\r
+ {\r
+ bitIndex--;\r
+ UInt32 bit = (symbol >> bitIndex) & 1;\r
+ Models[modelIndex].Encode(rangeEncoder, bit);\r
+ modelIndex = (modelIndex << 1) | bit;\r
+ }\r
+ };\r
+ void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol)\r
+ {\r
+ UInt32 modelIndex = 1;\r
+ for (int i = 0; i < NumBitLevels; i++)\r
+ {\r
+ UInt32 bit = symbol & 1;\r
+ Models[modelIndex].Encode(rangeEncoder, bit);\r
+ modelIndex = (modelIndex << 1) | bit;\r
+ symbol >>= 1;\r
+ }\r
+ }\r
+ UInt32 GetPrice(UInt32 symbol) const\r
+ {\r
+ symbol |= (1 << NumBitLevels);\r
+ UInt32 price = 0;\r
+ while (symbol != 1)\r
+ {\r
+ price += Models[symbol >> 1].GetPrice(symbol & 1);\r
+ symbol >>= 1;\r
+ }\r
+ return price;\r
+ }\r
+ UInt32 ReverseGetPrice(UInt32 symbol) const\r
+ {\r
+ UInt32 price = 0;\r
+ UInt32 modelIndex = 1;\r
+ for (int i = NumBitLevels; i != 0; i--)\r
+ {\r
+ UInt32 bit = symbol & 1;\r
+ symbol >>= 1;\r
+ price += Models[modelIndex].GetPrice(bit);\r
+ modelIndex = (modelIndex << 1) | bit;\r
+ }\r
+ return price;\r
+ }\r
+};\r
+\r
+template <int numMoveBits, int NumBitLevels>\r
+class CBitTreeDecoder\r
+{\r
+ CBitDecoder<numMoveBits> Models[1 << NumBitLevels];\r
+public:\r
+ void Init()\r
+ {\r
+ for(UInt32 i = 1; i < (1 << NumBitLevels); i++)\r
+ Models[i].Init();\r
+ }\r
+ UInt32 Decode(CDecoder *rangeDecoder)\r
+ {\r
+ UInt32 modelIndex = 1;\r
+ RC_INIT_VAR\r
+ for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)\r
+ {\r
+ // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder);\r
+ RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex)\r
+ }\r
+ RC_FLUSH_VAR\r
+ return modelIndex - (1 << NumBitLevels);\r
+ };\r
+ UInt32 ReverseDecode(CDecoder *rangeDecoder)\r
+ {\r
+ UInt32 modelIndex = 1;\r
+ UInt32 symbol = 0;\r
+ RC_INIT_VAR\r
+ for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)\r
+ {\r
+ // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);\r
+ // modelIndex <<= 1;\r
+ // modelIndex += bit;\r
+ // symbol |= (bit << bitIndex);\r
+ RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))\r
+ }\r
+ RC_FLUSH_VAR\r
+ return symbol;\r
+ }\r
+};\r
+\r
+template <int numMoveBits>\r
+void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, \r
+ CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol)\r
+{\r
+ UInt32 modelIndex = 1;\r
+ for (int i = 0; i < NumBitLevels; i++)\r
+ {\r
+ UInt32 bit = symbol & 1;\r
+ Models[modelIndex].Encode(rangeEncoder, bit);\r
+ modelIndex = (modelIndex << 1) | bit;\r
+ symbol >>= 1;\r
+ }\r
+}\r
+\r
+template <int numMoveBits>\r
+UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, \r
+ UInt32 NumBitLevels, UInt32 symbol)\r
+{\r
+ UInt32 price = 0;\r
+ UInt32 modelIndex = 1;\r
+ for (int i = NumBitLevels; i != 0; i--)\r
+ {\r
+ UInt32 bit = symbol & 1;\r
+ symbol >>= 1;\r
+ price += Models[modelIndex].GetPrice(bit);\r
+ modelIndex = (modelIndex << 1) | bit;\r
+ }\r
+ return price;\r
+}\r
+\r
+template <int numMoveBits>\r
+UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, \r
+ CDecoder *rangeDecoder, int NumBitLevels)\r
+{\r
+ UInt32 modelIndex = 1;\r
+ UInt32 symbol = 0;\r
+ RC_INIT_VAR\r
+ for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)\r
+ {\r
+ // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);\r
+ // modelIndex <<= 1;\r
+ // modelIndex += bit;\r
+ // symbol |= (bit << bitIndex);\r
+ RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))\r
+ }\r
+ RC_FLUSH_VAR\r
+ return symbol;\r
+}\r
+\r
+}}\r
+\r
+#endif\r
--- /dev/null
+// Compress/RangeCoder/RangeCoderOpt.h\r
+\r
+#ifndef __COMPRESS_RANGECODER_OPT_H\r
+#define __COMPRESS_RANGECODER_OPT_H\r
+\r
+#define RC_INIT_VAR \\r
+ UInt32 range = rangeDecoder->Range; \\r
+ UInt32 code = rangeDecoder->Code; \r
+\r
+#define RC_FLUSH_VAR \\r
+ rangeDecoder->Range = range; \\r
+ rangeDecoder->Code = code;\r
+\r
+#define RC_NORMALIZE \\r
+ if (range < NCompress::NRangeCoder::kTopValue) \\r
+ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; }\r
+\r
+#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \\r
+ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \\r
+ if (code < bound) \\r
+ { A0; range = bound; \\r
+ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \\r
+ mi <<= 1; } \\r
+ else \\r
+ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \\r
+ mi = (mi + mi) + 1; }} \\r
+ RC_NORMALIZE\r
+\r
+#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;)\r
+\r
+#endif\r
--- /dev/null
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#endif\r
--- /dev/null
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
--- /dev/null
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef SizeT
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+#define SizeT size_t
+#else
+#define SizeT UInt32
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
--- /dev/null
+// ICoder.h\r
+\r
+#ifndef __ICODER_H\r
+#define __ICODER_H\r
+\r
+#include "IStream.h"\r
+\r
+// "23170F69-40C1-278A-0000-000400xx0000"\r
+#define CODER_INTERFACE(i, x) \\r
+DEFINE_GUID(IID_ ## i, \\r
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \\r
+struct i: public IUnknown\r
+\r
+CODER_INTERFACE(ICompressProgressInfo, 0x04)\r
+{\r
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressCoder, 0x05)\r
+{\r
+ STDMETHOD(Code)(ISequentialInStream *inStream,\r
+ ISequentialOutStream *outStream, \r
+ const UInt64 *inSize, \r
+ const UInt64 *outSize,\r
+ ICompressProgressInfo *progress) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressCoder2, 0x18)\r
+{\r
+ STDMETHOD(Code)(ISequentialInStream **inStreams,\r
+ const UInt64 **inSizes, \r
+ UInt32 numInStreams,\r
+ ISequentialOutStream **outStreams, \r
+ const UInt64 **outSizes,\r
+ UInt32 numOutStreams,\r
+ ICompressProgressInfo *progress) PURE;\r
+};\r
+\r
+namespace NCoderPropID\r
+{\r
+ enum EEnum\r
+ {\r
+ kDictionarySize = 0x400,\r
+ kUsedMemorySize,\r
+ kOrder,\r
+ kPosStateBits = 0x440,\r
+ kLitContextBits,\r
+ kLitPosBits,\r
+ kNumFastBytes = 0x450,\r
+ kMatchFinder,\r
+ kMatchFinderCycles,\r
+ kNumPasses = 0x460, \r
+ kAlgorithm = 0x470,\r
+ kMultiThread = 0x480,\r
+ kNumThreads,\r
+ kEndMarker = 0x490\r
+ };\r
+}\r
+\r
+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)\r
+{\r
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, \r
+ const PROPVARIANT *properties, UInt32 numProperties) PURE;\r
+};\r
+\r
+/*\r
+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)\r
+{\r
+ STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;\r
+};\r
+*/\r
+\r
+CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)\r
+{\r
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)\r
+{\r
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)\r
+{\r
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetCoderMt, 0x25)\r
+{\r
+ STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)\r
+{\r
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetInStream, 0x31)\r
+{\r
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;\r
+ STDMETHOD(ReleaseInStream)() PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetOutStream, 0x32)\r
+{\r
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;\r
+ STDMETHOD(ReleaseOutStream)() PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetInStreamSize, 0x33)\r
+{\r
+ STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)\r
+{\r
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressFilter, 0x40)\r
+{\r
+ STDMETHOD(Init)() PURE;\r
+ STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;\r
+ // Filter return outSize (UInt32)\r
+ // if (outSize <= size): Filter have converted outSize bytes\r
+ // if (outSize > size): Filter have not converted anything.\r
+ // and it needs at least outSize bytes to convert one block \r
+ // (it's for crypto block algorithms).\r
+};\r
+\r
+CODER_INTERFACE(ICryptoProperties, 0x80)\r
+{\r
+ STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;\r
+ STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICryptoSetPassword, 0x90)\r
+{\r
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICryptoSetCRC, 0xA0)\r
+{\r
+ STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;\r
+};\r
+\r
+//////////////////////\r
+// It's for DLL file\r
+namespace NMethodPropID\r
+{\r
+ enum EEnum\r
+ {\r
+ kID,\r
+ kName,\r
+ kDecoder,\r
+ kEncoder,\r
+ kInStreams,\r
+ kOutStreams,\r
+ kDescription\r
+ };\r
+}\r
+\r
+#endif\r
--- /dev/null
+// IStream.h\r
+\r
+#ifndef __ISTREAM_H\r
+#define __ISTREAM_H\r
+\r
+#include "../Common/MyUnknown.h"\r
+#include "../Common/Types.h"\r
+\r
+// "23170F69-40C1-278A-0000-000300xx0000"\r
+\r
+#define STREAM_INTERFACE_SUB(i, b, x) \\r
+DEFINE_GUID(IID_ ## i, \\r
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \\r
+struct i: public b\r
+\r
+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)\r
+\r
+STREAM_INTERFACE(ISequentialInStream, 0x01)\r
+{\r
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;\r
+ /*\r
+ Out: if size != 0, return_value = S_OK and (*processedSize == 0),\r
+ then there are no more bytes in stream.\r
+ if (size > 0) && there are bytes in stream, \r
+ this function must read at least 1 byte.\r
+ This function is allowed to read less than number of remaining bytes in stream.\r
+ You must call Read function in loop, if you need exact amount of data\r
+ */\r
+};\r
+\r
+STREAM_INTERFACE(ISequentialOutStream, 0x02)\r
+{\r
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;\r
+ /*\r
+ if (size > 0) this function must write at least 1 byte.\r
+ This function is allowed to write less than "size".\r
+ You must call Write function in loop, if you need to write exact amount of data\r
+ */\r
+};\r
+\r
+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)\r
+{\r
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;\r
+};\r
+\r
+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)\r
+{\r
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;\r
+ STDMETHOD(SetSize)(Int64 newSize) PURE;\r
+};\r
+\r
+STREAM_INTERFACE(IStreamGetSize, 0x06)\r
+{\r
+ STDMETHOD(GetSize)(UInt64 *size) PURE;\r
+};\r
+\r
+STREAM_INTERFACE(IOutStreamFlush, 0x07)\r
+{\r
+ STDMETHOD(Flush)() PURE;\r
+};\r
+\r
+#endif\r
--- /dev/null
+// Common/Alloc.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifdef _WIN32\r
+#include "MyWindows.h"\r
+#else\r
+#include <stdlib.h>\r
+#endif\r
+\r
+#include "Alloc.h"\r
+\r
+/* #define _SZ_ALLOC_DEBUG */\r
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */\r
+#ifdef _SZ_ALLOC_DEBUG\r
+#include <stdio.h>\r
+int g_allocCount = 0;\r
+int g_allocCountMid = 0;\r
+int g_allocCountBig = 0;\r
+#endif\r
+\r
+void *MyAlloc(size_t size) throw()\r
+{\r
+ if (size == 0)\r
+ return 0;\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);\r
+ #endif\r
+ return ::malloc(size);\r
+}\r
+\r
+void MyFree(void *address) throw()\r
+{\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ if (address != 0)\r
+ fprintf(stderr, "\nFree; count = %10d", --g_allocCount);\r
+ #endif\r
+ \r
+ ::free(address);\r
+}\r
+\r
+#ifdef _WIN32\r
+\r
+void *MidAlloc(size_t size) throw()\r
+{\r
+ if (size == 0)\r
+ return 0;\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);\r
+ #endif\r
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+}\r
+\r
+void MidFree(void *address) throw()\r
+{\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ if (address != 0)\r
+ fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);\r
+ #endif\r
+ if (address == 0)\r
+ return;\r
+ ::VirtualFree(address, 0, MEM_RELEASE);\r
+}\r
+\r
+static SIZE_T g_LargePageSize = \r
+ #ifdef _WIN64\r
+ (1 << 21);\r
+ #else\r
+ (1 << 22);\r
+ #endif\r
+\r
+typedef SIZE_T (WINAPI *GetLargePageMinimumP)();\r
+\r
+bool SetLargePageSize()\r
+{\r
+ GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)\r
+ ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");\r
+ if (largePageMinimum == 0)\r
+ return false;\r
+ SIZE_T size = largePageMinimum();\r
+ if (size == 0 || (size & (size - 1)) != 0)\r
+ return false;\r
+ g_LargePageSize = size;\r
+ return true;\r
+}\r
+\r
+\r
+void *BigAlloc(size_t size) throw()\r
+{\r
+ if (size == 0)\r
+ return 0;\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);\r
+ #endif\r
+ \r
+ if (size >= (1 << 18))\r
+ {\r
+ void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), \r
+ MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);\r
+ if (res != 0)\r
+ return res;\r
+ }\r
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+}\r
+\r
+void BigFree(void *address) throw()\r
+{\r
+ #ifdef _SZ_ALLOC_DEBUG\r
+ if (address != 0)\r
+ fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);\r
+ #endif\r
+ \r
+ if (address == 0)\r
+ return;\r
+ ::VirtualFree(address, 0, MEM_RELEASE);\r
+}\r
+\r
+#endif\r
--- /dev/null
+// Common/Alloc.h\r
+\r
+#ifndef __COMMON_ALLOC_H\r
+#define __COMMON_ALLOC_H\r
+\r
+#include <stddef.h>\r
+\r
+void *MyAlloc(size_t size) throw();\r
+void MyFree(void *address) throw();\r
+\r
+#ifdef _WIN32\r
+\r
+bool SetLargePageSize();\r
+\r
+void *MidAlloc(size_t size) throw();\r
+void MidFree(void *address) throw();\r
+void *BigAlloc(size_t size) throw();\r
+void BigFree(void *address) throw();\r
+\r
+#else\r
+\r
+#define MidAlloc(size) MyAlloc(size)\r
+#define MidFree(address) MyFree(address)\r
+#define BigAlloc(size) MyAlloc(size)\r
+#define BigFree(address) MyFree(address)\r
+\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+// Common/CRC.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CRC.h"\r
+\r
+static const UInt32 kCRCPoly = 0xEDB88320;\r
+\r
+UInt32 CCRC::Table[256];\r
+\r
+void CCRC::InitTable()\r
+{\r
+ for (UInt32 i = 0; i < 256; i++)\r
+ {\r
+ UInt32 r = i;\r
+ for (int j = 0; j < 8; j++)\r
+ if (r & 1) \r
+ r = (r >> 1) ^ kCRCPoly;\r
+ else \r
+ r >>= 1;\r
+ CCRC::Table[i] = r;\r
+ }\r
+}\r
+\r
+class CCRCTableInit\r
+{\r
+public:\r
+ CCRCTableInit() { CCRC::InitTable(); }\r
+} g_CRCTableInit;\r
+\r
+void CCRC::UpdateByte(Byte b)\r
+{\r
+ _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8);\r
+}\r
+\r
+void CCRC::UpdateUInt16(UInt16 v)\r
+{\r
+ UpdateByte(Byte(v));\r
+ UpdateByte(Byte(v >> 8));\r
+}\r
+\r
+void CCRC::UpdateUInt32(UInt32 v)\r
+{\r
+ for (int i = 0; i < 4; i++)\r
+ UpdateByte((Byte)(v >> (8 * i)));\r
+}\r
+\r
+void CCRC::UpdateUInt64(UInt64 v)\r
+{\r
+ for (int i = 0; i < 8; i++)\r
+ UpdateByte((Byte)(v >> (8 * i)));\r
+}\r
+\r
+void CCRC::Update(const void *data, size_t size)\r
+{\r
+ UInt32 v = _value;\r
+ const Byte *p = (const Byte *)data;\r
+ for (; size > 0 ; size--, p++)\r
+ v = Table[((Byte)(v)) ^ *p] ^ (v >> 8);\r
+ _value = v;\r
+}\r
--- /dev/null
+// Common/CRC.h\r
+\r
+#ifndef __COMMON_CRC_H\r
+#define __COMMON_CRC_H\r
+\r
+#include <stddef.h>\r
+#include "Types.h"\r
+\r
+class CCRC\r
+{\r
+ UInt32 _value;\r
+public:\r
+ static UInt32 Table[256];\r
+ static void InitTable();\r
+\r
+ CCRC(): _value(0xFFFFFFFF){};\r
+ void Init() { _value = 0xFFFFFFFF; }\r
+ void UpdateByte(Byte v);\r
+ void UpdateUInt16(UInt16 v);\r
+ void UpdateUInt32(UInt32 v);\r
+ void UpdateUInt64(UInt64 v);\r
+ void Update(const void *data, size_t size);\r
+ UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } \r
+ static UInt32 CalculateDigest(const void *data, size_t size)\r
+ {\r
+ CCRC crc;\r
+ crc.Update(data, size);\r
+ return crc.GetDigest();\r
+ }\r
+ static bool VerifyDigest(UInt32 digest, const void *data, size_t size)\r
+ {\r
+ return (CalculateDigest(data, size) == digest);\r
+ }\r
+};\r
+\r
+#endif\r
--- /dev/null
+// Common/Defs.h\r
+\r
+#ifndef __COMMON_DEFS_H\r
+#define __COMMON_DEFS_H\r
+\r
+template <class T> inline T MyMin(T a, T b)\r
+ { return a < b ? a : b; }\r
+template <class T> inline T MyMax(T a, T b)\r
+ { return a > b ? a : b; }\r
+\r
+template <class T> inline int MyCompare(T a, T b)\r
+ { return a < b ? -1 : (a == b ? 0 : 1); }\r
+\r
+inline int BoolToInt(bool value)\r
+ { return (value ? 1: 0); }\r
+\r
+inline bool IntToBool(int value)\r
+ { return (value != 0); }\r
+\r
+#endif\r
--- /dev/null
+// MyCom.h\r
+\r
+#ifndef __MYCOM_H\r
+#define __MYCOM_H\r
+\r
+#include "MyWindows.h"\r
+\r
+#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; }\r
+\r
+template <class T>\r
+class CMyComPtr\r
+{\r
+ T* _p;\r
+public:\r
+ // typedef T _PtrClass;\r
+ CMyComPtr() { _p = NULL;}\r
+ CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }\r
+ CMyComPtr(const CMyComPtr<T>& lp)\r
+ {\r
+ if ((_p = lp._p) != NULL)\r
+ _p->AddRef();\r
+ }\r
+ ~CMyComPtr() { if (_p) _p->Release(); }\r
+ void Release() { if (_p) { _p->Release(); _p = NULL; } }\r
+ operator T*() const { return (T*)_p; }\r
+ // T& operator*() const { return *_p; }\r
+ T** operator&() { return &_p; }\r
+ T* operator->() const { return _p; }\r
+ T* operator=(T* p) \r
+ { \r
+ if (p != 0)\r
+ p->AddRef();\r
+ if (_p) \r
+ _p->Release();\r
+ _p = p;\r
+ return p;\r
+ }\r
+ T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }\r
+ bool operator!() const { return (_p == NULL); }\r
+ // bool operator==(T* pT) const { return _p == pT; }\r
+ // Compare two objects for equivalence\r
+ void Attach(T* p2)\r
+ {\r
+ Release();\r
+ _p = p2;\r
+ }\r
+ T* Detach()\r
+ {\r
+ T* pt = _p;\r
+ _p = NULL;\r
+ return pt;\r
+ }\r
+ #ifdef _WIN32\r
+ HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\r
+ {\r
+ return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);\r
+ }\r
+ #endif\r
+ /*\r
+ HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\r
+ {\r
+ CLSID clsid;\r
+ HRESULT hr = CLSIDFromProgID(szProgID, &clsid);\r
+ ATLASSERT(_p == NULL);\r
+ if (SUCCEEDED(hr))\r
+ hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);\r
+ return hr;\r
+ }\r
+ */\r
+ template <class Q>\r
+ HRESULT QueryInterface(REFGUID iid, Q** pp) const\r
+ {\r
+ return _p->QueryInterface(iid, (void**)pp);\r
+ }\r
+};\r
+\r
+//////////////////////////////////////////////////////////\r
+\r
+class CMyComBSTR\r
+{\r
+public:\r
+ BSTR m_str;\r
+ CMyComBSTR() { m_str = NULL; }\r
+ CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); }\r
+ // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }\r
+ // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }\r
+ CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }\r
+ /*\r
+ CMyComBSTR(REFGUID src)\r
+ {\r
+ LPOLESTR szGuid;\r
+ StringFromCLSID(src, &szGuid);\r
+ m_str = ::SysAllocString(szGuid);\r
+ CoTaskMemFree(szGuid);\r
+ }\r
+ */\r
+ ~CMyComBSTR() { ::SysFreeString(m_str); }\r
+ CMyComBSTR& operator=(const CMyComBSTR& src)\r
+ {\r
+ if (m_str != src.m_str)\r
+ {\r
+ if (m_str)\r
+ ::SysFreeString(m_str);\r
+ m_str = src.MyCopy();\r
+ }\r
+ return *this;\r
+ }\r
+ CMyComBSTR& operator=(LPCOLESTR pSrc)\r
+ {\r
+ ::SysFreeString(m_str);\r
+ m_str = ::SysAllocString(pSrc);\r
+ return *this;\r
+ }\r
+ unsigned int Length() const { return ::SysStringLen(m_str); }\r
+ operator BSTR() const { return m_str; }\r
+ BSTR* operator&() { return &m_str; }\r
+ BSTR MyCopy() const \r
+ { \r
+ int byteLen = ::SysStringByteLen(m_str);\r
+ BSTR res = ::SysAllocStringByteLen(NULL, byteLen);\r
+ memmove(res, m_str, byteLen);\r
+ return res;\r
+ }\r
+ void Attach(BSTR src) { m_str = src; }\r
+ BSTR Detach()\r
+ {\r
+ BSTR s = m_str;\r
+ m_str = NULL;\r
+ return s;\r
+ }\r
+ void Empty()\r
+ {\r
+ ::SysFreeString(m_str);\r
+ m_str = NULL;\r
+ }\r
+ bool operator!() const { return (m_str == NULL); }\r
+};\r
+\r
+\r
+//////////////////////////////////////////////////////////\r
+\r
+class CMyUnknownImp\r
+{\r
+public:\r
+ ULONG __m_RefCount;\r
+ CMyUnknownImp(): __m_RefCount(0) {}\r
+};\r
+\r
+#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \\r
+ (REFGUID iid, void **outObject) { \r
+\r
+#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \\r
+ { *outObject = (void *)(i *)this; AddRef(); return S_OK; }\r
+\r
+#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }\r
+\r
+#define MY_ADDREF_RELEASE \\r
+STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \\r
+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \\r
+ return __m_RefCount; delete this; return 0; }\r
+\r
+#define MY_UNKNOWN_IMP_SPEC(i) \\r
+ MY_QUERYINTERFACE_BEGIN \\r
+ i \\r
+ MY_QUERYINTERFACE_END \\r
+ MY_ADDREF_RELEASE\r
+\r
+\r
+#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \\r
+ MY_QUERYINTERFACE_END \\r
+ MY_ADDREF_RELEASE\r
+\r
+#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \\r
+ MY_QUERYINTERFACE_ENTRY(i) \\r
+ )\r
+\r
+#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \\r
+ MY_QUERYINTERFACE_ENTRY(i1) \\r
+ MY_QUERYINTERFACE_ENTRY(i2) \\r
+ )\r
+\r
+#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \\r
+ MY_QUERYINTERFACE_ENTRY(i1) \\r
+ MY_QUERYINTERFACE_ENTRY(i2) \\r
+ MY_QUERYINTERFACE_ENTRY(i3) \\r
+ )\r
+\r
+#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \\r
+ MY_QUERYINTERFACE_ENTRY(i1) \\r
+ MY_QUERYINTERFACE_ENTRY(i2) \\r
+ MY_QUERYINTERFACE_ENTRY(i3) \\r
+ MY_QUERYINTERFACE_ENTRY(i4) \\r
+ )\r
+\r
+#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \\r
+ MY_QUERYINTERFACE_ENTRY(i1) \\r
+ MY_QUERYINTERFACE_ENTRY(i2) \\r
+ MY_QUERYINTERFACE_ENTRY(i3) \\r
+ MY_QUERYINTERFACE_ENTRY(i4) \\r
+ MY_QUERYINTERFACE_ENTRY(i5) \\r
+ )\r
+\r
+#endif\r
--- /dev/null
+// Common/MyGuidDef.h\r
+\r
+#ifndef GUID_DEFINED\r
+#define GUID_DEFINED\r
+\r
+#include "Types.h"\r
+\r
+typedef struct {\r
+ UInt32 Data1;\r
+ UInt16 Data2;\r
+ UInt16 Data3;\r
+ unsigned char Data4[8];\r
+} GUID;\r
+\r
+#ifdef __cplusplus\r
+#define REFGUID const GUID &\r
+#else\r
+#define REFGUID const GUID *\r
+#endif\r
+\r
+#define REFCLSID REFGUID\r
+#define REFIID REFGUID\r
+\r
+#ifdef __cplusplus\r
+inline bool operator==(REFGUID g1, REFGUID g2)\r
+{ \r
+ for (int i = 0; i < (int)sizeof(g1); i++)\r
+ if (((const unsigned char *)&g1)[i] != ((const unsigned char *)&g2)[i])\r
+ return false;\r
+ return true;\r
+}\r
+inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+ #define MY_EXTERN_C extern "C"\r
+#else\r
+ #define MY_EXTERN_C extern\r
+#endif\r
+\r
+#endif // GUID_DEFINED\r
+\r
+\r
+#ifdef DEFINE_GUID\r
+#undef DEFINE_GUID\r
+#endif\r
+\r
+#ifdef INITGUID\r
+ #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
+ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }\r
+#else\r
+ #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
+ MY_EXTERN_C const GUID name\r
+#endif\r
--- /dev/null
+// Common/MyInitGuid.h\r
+\r
+#ifndef __COMMON_MYINITGUID_H\r
+#define __COMMON_MYINITGUID_H\r
+\r
+#ifdef _WIN32\r
+#include <initguid.h>\r
+#else\r
+#define INITGUID\r
+#include "MyGuidDef.h"\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+// MyUnknown.h\r
+\r
+#ifndef __MYUNKNOWN_H\r
+#define __MYUNKNOWN_H\r
+\r
+#ifdef _WIN32\r
+\r
+#ifdef _WIN32_WCE\r
+#if (_WIN32_WCE > 300)\r
+#include <basetyps.h>\r
+#else\r
+#define MIDL_INTERFACE(x) struct \r
+#endif\r
+#else\r
+#include <basetyps.h>\r
+#endif\r
+\r
+#include <unknwn.h>\r
+\r
+#else \r
+#include "MyWindows.h"\r
+#endif\r
+ \r
+#endif\r
--- /dev/null
+// MyWindows.h\r
+\r
+#ifndef __MYWINDOWS_H\r
+#define __MYWINDOWS_H\r
+\r
+#ifdef _WIN32\r
+\r
+#include <windows.h>\r
+\r
+#define CHAR_PATH_SEPARATOR '\\'\r
+#define WCHAR_PATH_SEPARATOR L'\\'\r
+#define STRING_PATH_SEPARATOR "\\"\r
+#define WSTRING_PATH_SEPARATOR L"\\"\r
+\r
+#else\r
+\r
+#define CHAR_PATH_SEPARATOR '/'\r
+#define WCHAR_PATH_SEPARATOR L'/'\r
+#define STRING_PATH_SEPARATOR "/"\r
+#define WSTRING_PATH_SEPARATOR L"/"\r
+\r
+#include <stddef.h> // for wchar_t\r
+#include <string.h>\r
+\r
+#include "MyGuidDef.h"\r
+\r
+typedef char CHAR;\r
+typedef unsigned char UCHAR;\r
+\r
+#undef BYTE\r
+typedef unsigned char BYTE;\r
+\r
+typedef short SHORT;\r
+typedef unsigned short USHORT;\r
+\r
+#undef WORD\r
+typedef unsigned short WORD;\r
+typedef short VARIANT_BOOL;\r
+\r
+typedef int INT;\r
+typedef Int32 INT32;\r
+typedef unsigned int UINT;\r
+typedef UInt32 UINT32;\r
+typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit\r
+typedef UINT32 ULONG;\r
+\r
+#undef DWORD\r
+typedef UINT32 DWORD;\r
+\r
+typedef Int64 LONGLONG;\r
+typedef UInt64 ULONGLONG;\r
+\r
+typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;\r
+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;\r
+\r
+typedef const CHAR *LPCSTR;\r
+typedef CHAR TCHAR;\r
+typedef const TCHAR *LPCTSTR;\r
+typedef wchar_t WCHAR;\r
+typedef WCHAR OLECHAR;\r
+typedef const WCHAR *LPCWSTR;\r
+typedef OLECHAR *BSTR;\r
+typedef const OLECHAR *LPCOLESTR;\r
+typedef OLECHAR *LPOLESTR;\r
+\r
+typedef struct _FILETIME\r
+{\r
+ DWORD dwLowDateTime;\r
+ DWORD dwHighDateTime;\r
+}FILETIME;\r
+\r
+#define HRESULT LONG\r
+#define FAILED(Status) ((HRESULT)(Status)<0)\r
+typedef ULONG PROPID;\r
+typedef LONG SCODE;\r
+\r
+#define S_OK ((HRESULT)0x00000000L)\r
+#define S_FALSE ((HRESULT)0x00000001L)\r
+#define E_NOTIMPL ((HRESULT)0x80004001L)\r
+#define E_NOINTERFACE ((HRESULT)0x80004002L)\r
+#define E_ABORT ((HRESULT)0x80004004L)\r
+#define E_FAIL ((HRESULT)0x80004005L)\r
+#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)\r
+#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)\r
+#define E_INVALIDARG ((HRESULT)0x80070057L)\r
+\r
+#ifdef _MSC_VER\r
+#define STDMETHODCALLTYPE __stdcall \r
+#else\r
+#define STDMETHODCALLTYPE \r
+#endif\r
+\r
+#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f\r
+#define STDMETHOD(f) STDMETHOD_(HRESULT, f)\r
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE\r
+#define STDMETHODIMP STDMETHODIMP_(HRESULT)\r
+\r
+#define PURE = 0\r
+\r
+#define MIDL_INTERFACE(x) struct \r
+\r
+struct IUnknown\r
+{\r
+ //virtual ~IUnknown() {}\r
+ STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;\r
+ STDMETHOD_(ULONG, AddRef)() PURE;\r
+ STDMETHOD_(ULONG, Release)() PURE;\r
+};\r
+\r
+typedef IUnknown *LPUNKNOWN;\r
+\r
+#define VARIANT_TRUE ((VARIANT_BOOL)-1)\r
+#define VARIANT_FALSE ((VARIANT_BOOL)0)\r
+\r
+enum VARENUM\r
+{ \r
+ VT_EMPTY = 0,\r
+ VT_NULL = 1,\r
+ VT_I2 = 2,\r
+ VT_I4 = 3,\r
+ VT_R4 = 4,\r
+ VT_R8 = 5,\r
+ VT_CY = 6,\r
+ VT_DATE = 7,\r
+ VT_BSTR = 8,\r
+ VT_DISPATCH = 9,\r
+ VT_ERROR = 10,\r
+ VT_BOOL = 11,\r
+ VT_VARIANT = 12,\r
+ VT_UNKNOWN = 13,\r
+ VT_DECIMAL = 14,\r
+ VT_I1 = 16,\r
+ VT_UI1 = 17,\r
+ VT_UI2 = 18,\r
+ VT_UI4 = 19,\r
+ VT_I8 = 20,\r
+ VT_UI8 = 21,\r
+ VT_INT = 22,\r
+ VT_UINT = 23,\r
+ VT_VOID = 24,\r
+ VT_HRESULT = 25,\r
+ VT_FILETIME = 64\r
+};\r
+\r
+typedef unsigned short VARTYPE;\r
+typedef WORD PROPVAR_PAD1;\r
+typedef WORD PROPVAR_PAD2;\r
+typedef WORD PROPVAR_PAD3;\r
+\r
+typedef struct tagPROPVARIANT\r
+{\r
+ VARTYPE vt;\r
+ PROPVAR_PAD1 wReserved1;\r
+ PROPVAR_PAD2 wReserved2;\r
+ PROPVAR_PAD3 wReserved3;\r
+ union \r
+ {\r
+ CHAR cVal;\r
+ UCHAR bVal;\r
+ SHORT iVal;\r
+ USHORT uiVal;\r
+ LONG lVal;\r
+ ULONG ulVal;\r
+ INT intVal;\r
+ UINT uintVal;\r
+ LARGE_INTEGER hVal;\r
+ ULARGE_INTEGER uhVal;\r
+ VARIANT_BOOL boolVal;\r
+ SCODE scode;\r
+ FILETIME filetime;\r
+ BSTR bstrVal;\r
+ };\r
+} PROPVARIANT;\r
+\r
+typedef PROPVARIANT tagVARIANT;\r
+typedef tagVARIANT VARIANT;\r
+typedef VARIANT VARIANTARG;\r
+\r
+MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);\r
+MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);\r
+MY_EXTERN_C void SysFreeString(BSTR bstr);\r
+MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);\r
+MY_EXTERN_C UINT SysStringLen(BSTR bstr);\r
+\r
+MY_EXTERN_C DWORD GetLastError();\r
+MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);\r
+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);\r
+MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);\r
+\r
+#define CP_ACP 0\r
+#define CP_OEMCP 1\r
+\r
+typedef enum tagSTREAM_SEEK\r
+{ \r
+ STREAM_SEEK_SET = 0,\r
+ STREAM_SEEK_CUR = 1,\r
+ STREAM_SEEK_END = 2\r
+} STREAM_SEEK;\r
+\r
+#endif\r
+#endif\r
--- /dev/null
+// Common/NewHandler.h\r
+\r
+#ifndef __COMMON_NEWHANDLER_H\r
+#define __COMMON_NEWHANDLER_H\r
+\r
+class CNewException {};\r
+\r
+#ifdef _WIN32\r
+void \r
+#ifdef _MSC_VER\r
+__cdecl \r
+#endif\r
+operator delete(void *p) throw();\r
+#endif \r
+\r
+#endif \r
--- /dev/null
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+// #include "MyWindows.h"\r
+#include "NewHandler.h"\r
+\r
+#endif \r
--- /dev/null
+// Common/Types.h\r
+\r
+#ifndef __COMMON_TYPES_H\r
+#define __COMMON_TYPES_H\r
+\r
+typedef unsigned char Byte;\r
+typedef short Int16;\r
+typedef unsigned short UInt16;\r
+typedef int Int32;\r
+typedef unsigned int UInt32;\r
+#ifdef _MSC_VER\r
+typedef __int64 Int64;\r
+typedef unsigned __int64 UInt64;\r
+#else\r
+typedef long long int Int64;\r
+typedef unsigned long long int UInt64;\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE\r
+ Version 2.1, February 1999\r
+\r
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.\r
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+[This is the first released version of the Lesser GPL. It also counts\r
+ as the successor of the GNU Library Public License, version 2, hence\r
+ the version number 2.1.]\r
+\r
+ Preamble\r
+\r
+ The licenses for most software are designed to take away your\r
+freedom to share and change it. By contrast, the GNU General Public\r
+Licenses are intended to guarantee your freedom to share and change\r
+free software--to make sure the software is free for all its users.\r
+\r
+ This license, the Lesser General Public License, applies to some\r
+specially designated software packages--typically libraries--of the\r
+Free Software Foundation and other authors who decide to use it. You\r
+can use it too, but we suggest you first think carefully about whether\r
+this license or the ordinary General Public License is the better\r
+strategy to use in any particular case, based on the explanations below.\r
+\r
+ When we speak of free software, we are referring to freedom of use,\r
+not price. Our General Public Licenses are designed to make sure that\r
+you have the freedom to distribute copies of free software (and charge\r
+for this service if you wish); that you receive source code or can get\r
+it if you want it; that you can change the software and use pieces of\r
+it in new free programs; and that you are informed that you can do\r
+these things.\r
+\r
+ To protect your rights, we need to make restrictions that forbid\r
+distributors to deny you these rights or to ask you to surrender these\r
+rights. These restrictions translate to certain responsibilities for\r
+you if you distribute copies of the library or if you modify it.\r
+\r
+ For example, if you distribute copies of the library, whether gratis\r
+or for a fee, you must give the recipients all the rights that we gave\r
+you. You must make sure that they, too, receive or can get the source\r
+code. If you link other code with the library, you must provide\r
+complete object files to the recipients, so that they can relink them\r
+with the library after making changes to the library and recompiling\r
+it. And you must show them these terms so they know their rights.\r
+\r
+ We protect your rights with a two-step method: (1) we copyright the\r
+library, and (2) we offer you this license, which gives you legal\r
+permission to copy, distribute and/or modify the library.\r
+\r
+ To protect each distributor, we want to make it very clear that\r
+there is no warranty for the free library. Also, if the library is\r
+modified by someone else and passed on, the recipients should know\r
+that what they have is not the original version, so that the original\r
+author's reputation will not be affected by problems that might be\r
+introduced by others.\r
+\f\r
+ Finally, software patents pose a constant threat to the existence of\r
+any free program. We wish to make sure that a company cannot\r
+effectively restrict the users of a free program by obtaining a\r
+restrictive license from a patent holder. Therefore, we insist that\r
+any patent license obtained for a version of the library must be\r
+consistent with the full freedom of use specified in this license.\r
+\r
+ Most GNU software, including some libraries, is covered by the\r
+ordinary GNU General Public License. This license, the GNU Lesser\r
+General Public License, applies to certain designated libraries, and\r
+is quite different from the ordinary General Public License. We use\r
+this license for certain libraries in order to permit linking those\r
+libraries into non-free programs.\r
+\r
+ When a program is linked with a library, whether statically or using\r
+a shared library, the combination of the two is legally speaking a\r
+combined work, a derivative of the original library. The ordinary\r
+General Public License therefore permits such linking only if the\r
+entire combination fits its criteria of freedom. The Lesser General\r
+Public License permits more lax criteria for linking other code with\r
+the library.\r
+\r
+ We call this license the "Lesser" General Public License because it\r
+does Less to protect the user's freedom than the ordinary General\r
+Public License. It also provides other free software developers Less\r
+of an advantage over competing non-free programs. These disadvantages\r
+are the reason we use the ordinary General Public License for many\r
+libraries. However, the Lesser license provides advantages in certain\r
+special circumstances.\r
+\r
+ For example, on rare occasions, there may be a special need to\r
+encourage the widest possible use of a certain library, so that it becomes\r
+a de-facto standard. To achieve this, non-free programs must be\r
+allowed to use the library. A more frequent case is that a free\r
+library does the same job as widely used non-free libraries. In this\r
+case, there is little to gain by limiting the free library to free\r
+software only, so we use the Lesser General Public License.\r
+\r
+ In other cases, permission to use a particular library in non-free\r
+programs enables a greater number of people to use a large body of\r
+free software. For example, permission to use the GNU C Library in\r
+non-free programs enables many more people to use the whole GNU\r
+operating system, as well as its variant, the GNU/Linux operating\r
+system.\r
+\r
+ Although the Lesser General Public License is Less protective of the\r
+users' freedom, it does ensure that the user of a program that is\r
+linked with the Library has the freedom and the wherewithal to run\r
+that program using a modified version of the Library.\r
+\r
+ The precise terms and conditions for copying, distribution and\r
+modification follow. Pay close attention to the difference between a\r
+"work based on the library" and a "work that uses the library". The\r
+former contains code derived from the library, whereas the latter must\r
+be combined with the library in order to run.\r
+\f\r
+ GNU LESSER GENERAL PUBLIC LICENSE\r
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+ 0. This License Agreement applies to any software library or other\r
+program which contains a notice placed by the copyright holder or\r
+other authorized party saying it may be distributed under the terms of\r
+this Lesser General Public License (also called "this License").\r
+Each licensee is addressed as "you".\r
+\r
+ A "library" means a collection of software functions and/or data\r
+prepared so as to be conveniently linked with application programs\r
+(which use some of those functions and data) to form executables.\r
+\r
+ The "Library", below, refers to any such software library or work\r
+which has been distributed under these terms. A "work based on the\r
+Library" means either the Library or any derivative work under\r
+copyright law: that is to say, a work containing the Library or a\r
+portion of it, either verbatim or with modifications and/or translated\r
+straightforwardly into another language. (Hereinafter, translation is\r
+included without limitation in the term "modification".)\r
+\r
+ "Source code" for a work means the preferred form of the work for\r
+making modifications to it. For a library, complete source code means\r
+all the source code for all modules it contains, plus any associated\r
+interface definition files, plus the scripts used to control compilation\r
+and installation of the library.\r
+\r
+ Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope. The act of\r
+running a program using the Library is not restricted, and output from\r
+such a program is covered only if its contents constitute a work based\r
+on the Library (independent of the use of the Library in a tool for\r
+writing it). Whether that is true depends on what the Library does\r
+and what the program that uses the Library does.\r
+ \r
+ 1. You may copy and distribute verbatim copies of the Library's\r
+complete source code as you receive it, in any medium, provided that\r
+you conspicuously and appropriately publish on each copy an\r
+appropriate copyright notice and disclaimer of warranty; keep intact\r
+all the notices that refer to this License and to the absence of any\r
+warranty; and distribute a copy of this License along with the\r
+Library.\r
+\r
+ You may charge a fee for the physical act of transferring a copy,\r
+and you may at your option offer warranty protection in exchange for a\r
+fee.\r
+\f\r
+ 2. You may modify your copy or copies of the Library or any portion\r
+of it, thus forming a work based on the Library, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+ a) The modified work must itself be a software library.\r
+\r
+ b) You must cause the files modified to carry prominent notices\r
+ stating that you changed the files and the date of any change.\r
+\r
+ c) You must cause the whole of the work to be licensed at no\r
+ charge to all third parties under the terms of this License.\r
+\r
+ d) If a facility in the modified Library refers to a function or a\r
+ table of data to be supplied by an application program that uses\r
+ the facility, other than as an argument passed when the facility\r
+ is invoked, then you must make a good faith effort to ensure that,\r
+ in the event an application does not supply such function or\r
+ table, the facility still operates, and performs whatever part of\r
+ its purpose remains meaningful.\r
+\r
+ (For example, a function in a library to compute square roots has\r
+ a purpose that is entirely well-defined independent of the\r
+ application. Therefore, Subsection 2d requires that any\r
+ application-supplied function or table used by this function must\r
+ be optional: if the application does not supply it, the square\r
+ root function must still compute square roots.)\r
+\r
+These requirements apply to the modified work as a whole. If\r
+identifiable sections of that work are not derived from the Library,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works. But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Library, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote\r
+it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Library.\r
+\r
+In addition, mere aggregation of another work not based on the Library\r
+with the Library (or with a work based on the Library) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+ 3. You may opt to apply the terms of the ordinary GNU General Public\r
+License instead of this License to a given copy of the Library. To do\r
+this, you must alter all the notices that refer to this License, so\r
+that they refer to the ordinary GNU General Public License, version 2,\r
+instead of to this License. (If a newer version than version 2 of the\r
+ordinary GNU General Public License has appeared, then you can specify\r
+that version instead if you wish.) Do not make any other change in\r
+these notices.\r
+\f\r
+ Once this change is made in a given copy, it is irreversible for\r
+that copy, so the ordinary GNU General Public License applies to all\r
+subsequent copies and derivative works made from that copy.\r
+\r
+ This option is useful when you wish to copy part of the code of\r
+the Library into a program that is not a library.\r
+\r
+ 4. You may copy and distribute the Library (or a portion or\r
+derivative of it, under Section 2) in object code or executable form\r
+under the terms of Sections 1 and 2 above provided that you accompany\r
+it with the complete corresponding machine-readable source code, which\r
+must be distributed under the terms of Sections 1 and 2 above on a\r
+medium customarily used for software interchange.\r
+\r
+ If distribution of object code is made by offering access to copy\r
+from a designated place, then offering equivalent access to copy the\r
+source code from the same place satisfies the requirement to\r
+distribute the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\r
+ 5. A program that contains no derivative of any portion of the\r
+Library, but is designed to work with the Library by being compiled or\r
+linked with it, is called a "work that uses the Library". Such a\r
+work, in isolation, is not a derivative work of the Library, and\r
+therefore falls outside the scope of this License.\r
+\r
+ However, linking a "work that uses the Library" with the Library\r
+creates an executable that is a derivative of the Library (because it\r
+contains portions of the Library), rather than a "work that uses the\r
+library". The executable is therefore covered by this License.\r
+Section 6 states terms for distribution of such executables.\r
+\r
+ When a "work that uses the Library" uses material from a header file\r
+that is part of the Library, the object code for the work may be a\r
+derivative work of the Library even though the source code is not.\r
+Whether this is true is especially significant if the work can be\r
+linked without the Library, or if the work is itself a library. The\r
+threshold for this to be true is not precisely defined by law.\r
+\r
+ If such an object file uses only numerical parameters, data\r
+structure layouts and accessors, and small macros and small inline\r
+functions (ten lines or less in length), then the use of the object\r
+file is unrestricted, regardless of whether it is legally a derivative\r
+work. (Executables containing this object code plus portions of the\r
+Library will still fall under Section 6.)\r
+\r
+ Otherwise, if the work is a derivative of the Library, you may\r
+distribute the object code for the work under the terms of Section 6.\r
+Any executables containing that work also fall under Section 6,\r
+whether or not they are linked directly with the Library itself.\r
+\f\r
+ 6. As an exception to the Sections above, you may also combine or\r
+link a "work that uses the Library" with the Library to produce a\r
+work containing portions of the Library, and distribute that work\r
+under terms of your choice, provided that the terms permit\r
+modification of the work for the customer's own use and reverse\r
+engineering for debugging such modifications.\r
+\r
+ You must give prominent notice with each copy of the work that the\r
+Library is used in it and that the Library and its use are covered by\r
+this License. You must supply a copy of this License. If the work\r
+during execution displays copyright notices, you must include the\r
+copyright notice for the Library among them, as well as a reference\r
+directing the user to the copy of this License. Also, you must do one\r
+of these things:\r
+\r
+ a) Accompany the work with the complete corresponding\r
+ machine-readable source code for the Library including whatever\r
+ changes were used in the work (which must be distributed under\r
+ Sections 1 and 2 above); and, if the work is an executable linked\r
+ with the Library, with the complete machine-readable "work that\r
+ uses the Library", as object code and/or source code, so that the\r
+ user can modify the Library and then relink to produce a modified\r
+ executable containing the modified Library. (It is understood\r
+ that the user who changes the contents of definitions files in the\r
+ Library will not necessarily be able to recompile the application\r
+ to use the modified definitions.)\r
+\r
+ b) Use a suitable shared library mechanism for linking with the\r
+ Library. A suitable mechanism is one that (1) uses at run time a\r
+ copy of the library already present on the user's computer system,\r
+ rather than copying library functions into the executable, and (2)\r
+ will operate properly with a modified version of the library, if\r
+ the user installs one, as long as the modified version is\r
+ interface-compatible with the version that the work was made with.\r
+\r
+ c) Accompany the work with a written offer, valid for at\r
+ least three years, to give the same user the materials\r
+ specified in Subsection 6a, above, for a charge no more\r
+ than the cost of performing this distribution.\r
+\r
+ d) If distribution of the work is made by offering access to copy\r
+ from a designated place, offer equivalent access to copy the above\r
+ specified materials from the same place.\r
+\r
+ e) Verify that the user has already received a copy of these\r
+ materials or that you have already sent this user a copy.\r
+\r
+ For an executable, the required form of the "work that uses the\r
+Library" must include any data and utility programs needed for\r
+reproducing the executable from it. However, as a special exception,\r
+the materials to be distributed need not include anything that is\r
+normally distributed (in either source or binary form) with the major\r
+components (compiler, kernel, and so on) of the operating system on\r
+which the executable runs, unless that component itself accompanies\r
+the executable.\r
+\r
+ It may happen that this requirement contradicts the license\r
+restrictions of other proprietary libraries that do not normally\r
+accompany the operating system. Such a contradiction means you cannot\r
+use both them and the Library together in an executable that you\r
+distribute.\r
+\f\r
+ 7. You may place library facilities that are a work based on the\r
+Library side-by-side in a single library together with other library\r
+facilities not covered by this License, and distribute such a combined\r
+library, provided that the separate distribution of the work based on\r
+the Library and of the other library facilities is otherwise\r
+permitted, and provided that you do these two things:\r
+\r
+ a) Accompany the combined library with a copy of the same work\r
+ based on the Library, uncombined with any other library\r
+ facilities. This must be distributed under the terms of the\r
+ Sections above.\r
+\r
+ b) Give prominent notice with the combined library of the fact\r
+ that part of it is a work based on the Library, and explaining\r
+ where to find the accompanying uncombined form of the same work.\r
+\r
+ 8. You may not copy, modify, sublicense, link with, or distribute\r
+the Library except as expressly provided under this License. Any\r
+attempt otherwise to copy, modify, sublicense, link with, or\r
+distribute the Library is void, and will automatically terminate your\r
+rights under this License. However, parties who have received copies,\r
+or rights, from you under this License will not have their licenses\r
+terminated so long as such parties remain in full compliance.\r
+\r
+ 9. You are not required to accept this License, since you have not\r
+signed it. However, nothing else grants you permission to modify or\r
+distribute the Library or its derivative works. These actions are\r
+prohibited by law if you do not accept this License. Therefore, by\r
+modifying or distributing the Library (or any work based on the\r
+Library), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Library or works based on it.\r
+\r
+ 10. Each time you redistribute the Library (or any work based on the\r
+Library), the recipient automatically receives a license from the\r
+original licensor to copy, distribute, link with or modify the Library\r
+subject to these terms and conditions. You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties with\r
+this License.\r
+\f\r
+ 11. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License. If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Library at all. For example, if a patent\r
+license would not permit royalty-free redistribution of the Library by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Library.\r
+\r
+If any portion of this section is held invalid or unenforceable under any\r
+particular circumstance, the balance of the section is intended to apply,\r
+and the section as a whole is intended to apply in other circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system which is\r
+implemented by public license practices. Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\r
+ 12. If the distribution and/or use of the Library is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Library under this License may add\r
+an explicit geographical distribution limitation excluding those countries,\r
+so that distribution is permitted only in or among countries not thus\r
+excluded. In such case, this License incorporates the limitation as if\r
+written in the body of this License.\r
+\r
+ 13. The Free Software Foundation may publish revised and/or new\r
+versions of the Lesser General Public License from time to time.\r
+Such new versions will be similar in spirit to the present version,\r
+but may differ in detail to address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number. If the Library\r
+specifies a version number of this License which applies to it and\r
+"any later version", you have the option of following the terms and\r
+conditions either of that version or of any later version published by\r
+the Free Software Foundation. If the Library does not specify a\r
+license version number, you may choose any version ever published by\r
+the Free Software Foundation.\r
+\f\r
+ 14. If you wish to incorporate parts of the Library into other free\r
+programs whose distribution conditions are incompatible with these,\r
+write to the author to ask for permission. For software which is\r
+copyrighted by the Free Software Foundation, write to the Free\r
+Software Foundation; we sometimes make exceptions for this. Our\r
+decision will be guided by the two goals of preserving the free status\r
+of all derivatives of our free software and of promoting the sharing\r
+and reuse of software generally.\r
+\r
+ NO WARRANTY\r
+\r
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\r
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\r
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\r
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY\r
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\r
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\r
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
+\r
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\r
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\r
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\r
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\r
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\r
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\r
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\r
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\r
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+DAMAGES.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\f\r
+ How to Apply These Terms to Your New Libraries\r
+\r
+ If you develop a new library, and you want it to be of the greatest\r
+possible use to the public, we recommend making it free software that\r
+everyone can redistribute and change. You can do so by permitting\r
+redistribution under these terms (or, alternatively, under the terms of the\r
+ordinary General Public License).\r
+\r
+ To apply these terms, attach the following notices to the library. It is\r
+safest to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least the\r
+"copyright" line and a pointer to where the full notice is found.\r
+\r
+ <one line to give the library's name and a brief idea of what it does.>\r
+ Copyright (C) <year> <name of author>\r
+\r
+ This library is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU Lesser General Public\r
+ License as published by the Free Software Foundation; either\r
+ version 2.1 of the License, or (at your option) any later version.\r
+\r
+ This library is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ Lesser General Public License for more details.\r
+\r
+ You should have received a copy of the GNU Lesser General Public\r
+ License along with this library; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the library, if\r
+necessary. Here is a sample; alter the names:\r
+\r
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the\r
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.\r
+\r
+ <signature of Ty Coon>, 1 April 1990\r
+ Ty Coon, President of Vice\r
+\r
+That's all there is to it!\r
+\r
+\r
--- /dev/null
+The contents of this directory are extracted from
+the official LZMA SDK, version lzma442.tar.bz2 ,
+for the use in mkcromfs.
--- /dev/null
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+LZMA_OBJ := $(obj)/util/lzma/LZMAEncoder.o $(obj)/util/lzma/LZInWindow.o
+LZMA_OBJ += $(obj)/util/lzma/RangeCoderBit.o $(obj)/util/lzma/StreamUtils.o
+LZMA_OBJ += $(obj)/util/lzma/OutBuffer.o $(obj)/util/lzma/Alloc.o
+LZMA_OBJ += $(obj)/util/lzma/CRC.o
+
+$(obj)/util/lzma/lzma: $(obj)/util/lzma/ $(LZMA_OBJ) $(obj)/util/lzma/minilzma.o
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ $(LZMA_OBJ) $(obj)/util/lzma/minilzma.o
+
+$(obj)/util/lzma/lzma-compress.o: $(src)/util/lzma/minilzma.cc
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c -DCOMPACT $<
+
+$(obj)/util/lzma/:
+ $(Q)printf " BUILD LZMA\n"
+ $(Q)mkdir -p $(obj)/util/lzma/
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/7zip/Compress/LZMA/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/7zip/Compress/LZ/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/7zip/Compress/RangeCoder/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/7zip/Decompress/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/7zip/Common/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/C/Common/%.cpp
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
+$(obj)/util/lzma/%.o: $(src)/util/lzma/%.cc
+ $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ -c $<
+
--- /dev/null
+/*
+ * minimal lzma implementation
+ *
+ * Copyright (C) 2002 Eric Biederman
+ * Copyright (C) 2005 Joel Yliluoma
+ * Copyright (C) 2007 coresystems GmbH
+ * (Adapted by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
+ * Copyright (C) 2007 Patrick Georgi <patrick@georgi-clan.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "C/Common/MyInitGuid.h"
+#include "C/7zip/Compress/LZMA/LZMAEncoder.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <cctype>
+
+#include <vector>
+#include <algorithm>
+#include <stdint.h>
+
+const std::vector<unsigned char> LZMACompress
+ (const std::vector<unsigned char>& buf);
+
+const std::vector<unsigned char> LZMADeCompress
+ (const std::vector<unsigned char>& buf);
+
+static inline uint16_t R16(const void* p)
+{
+ const unsigned char* data = (const unsigned char*)p;
+ return (data[0] << 0) | (data[1] << 8);
+}
+static inline uint32_t R32(const void* p)
+{
+ const unsigned char* data = (const unsigned char*)p;
+ return R16(data) | (R16(data+2) << 16);
+}
+
+#define L (uint64_t)
+
+static inline uint64_t R64(const void* p)
+{
+ const unsigned char* data = (const unsigned char*)p;
+ return (L R32(data)) | ((L R32(data+4)) << 32);
+}
+
+#undef L
+
+static UInt32 SelectDictionarySizeFor(unsigned datasize)
+{
+ #if 1
+ return datasize;
+ #else
+#ifdef __GNUC__
+ /* gnu c can optimize this switch statement into a fast binary
+ * search, but it cannot do so for the list of the if statements.
+ */
+ switch(datasize)
+ {
+ case 0 ... 512 : return 512;
+ case 513 ... 1024: return 2048;
+ case 1025 ... 4096: return 8192;
+ case 4097 ... 16384: return 32768;
+ case 16385 ... 65536: return 528288;
+ case 65537 ... 528288: return 1048576*4;
+ case 528289 ... 786432: return 1048576*16;
+ default: return 1048576*32;
+ }
+#else
+ if(datasize <= 512) return 512;
+ if(datasize <= 1024) return 1024;
+ if(datasize <= 4096) return 4096;
+ if(datasize <= 16384) return 32768;
+ if(datasize <= 65536) return 528288;
+ if(datasize <= 528288) return 1048576*4;
+ if(datasize <= 786432) reutrn 1048576*16;
+ return 32*1048576;
+#endif
+ #endif
+}
+
+
+class CInStreamRam: public ISequentialInStream, public CMyUnknownImp
+{
+ const std::vector<unsigned char>& input;
+ size_t Pos;
+public:
+ MY_UNKNOWN_IMP
+
+ CInStreamRam(const std::vector<unsigned char>& buf) : input(buf), Pos(0)
+ {
+ }
+ virtual ~CInStreamRam() {}
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 remain = input.size() - Pos;
+ if (size > remain) size = remain;
+
+ std::memcpy(data, &input[Pos], size);
+ Pos += size;
+
+ if(processedSize != NULL) *processedSize = size;
+
+ return S_OK;
+}
+
+class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp
+{
+ std::vector<Byte> result;
+ size_t Pos;
+public:
+ MY_UNKNOWN_IMP
+
+ COutStreamRam(): result(), Pos(0) { }
+ virtual ~COutStreamRam() { }
+
+ void Reserve(unsigned n) { result.reserve(n); }
+ const std::vector<Byte>& Get() const { return result; }
+
+ HRESULT WriteByte(Byte b)
+ {
+ if(Pos >= result.size()) result.resize(Pos+1);
+ result[Pos++] = b;
+ return S_OK;
+ }
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(Pos+size > result.size()) result.resize(Pos+size);
+
+ std::memcpy(&result[Pos], data, size);
+ if(processedSize != NULL) *processedSize = size;
+ Pos += size;
+ return S_OK;
+}
+
+const std::vector<unsigned char> LZMACompress(const std::vector<unsigned char>& buf)
+{
+ if(buf.empty()) return buf;
+
+ const UInt32 dictionarysize = SelectDictionarySizeFor(buf.size());
+
+ NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+ const PROPID propIDs[] =
+ {
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kNumFastBytes,
+ };
+ const unsigned kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+ PROPVARIANT properties[kNumProps];
+ properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)2;
+ properties[1].vt = VT_UI4; properties[1].ulVal = (UInt32)dictionarysize;
+ properties[2].vt = VT_UI4; properties[2].ulVal = (UInt32)64;
+
+ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+ {
+ Error:
+ return std::vector<unsigned char> ();
+ }
+
+ COutStreamRam *const outStreamSpec = new COutStreamRam;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ CInStreamRam *const inStreamSpec = new CInStreamRam(buf);
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+ outStreamSpec->Reserve(buf.size());
+
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK) goto Error;
+
+ for (unsigned i = 0; i < 8; i++)
+ {
+ UInt64 t = (UInt64)buf.size();
+ outStreamSpec->WriteByte((Byte)((t) >> (8 * i)));
+ }
+
+ HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
+ if (lzmaResult != S_OK) goto Error;
+
+ return outStreamSpec->Get();
+}
+
+#undef RC_NORMALIZE
+
+#include "C/7zip/Decompress/LzmaDecode.h"
+#include "C/7zip/Decompress/LzmaDecode.c"
+
+const std::vector<unsigned char> LZMADeCompress
+ (const std::vector<unsigned char>& buf)
+{
+ if(buf.size() <= 5+8) return std::vector<unsigned char> ();
+
+ uint_least64_t out_sizemax = R64(&buf[5]);
+
+ std::vector<unsigned char> result(out_sizemax);
+
+ CLzmaDecoderState state;
+ LzmaDecodeProperties(&state.Properties, &buf[0], LZMA_PROPERTIES_SIZE);
+ state.Probs = new CProb[LzmaGetNumProbs(&state.Properties)];
+
+ SizeT in_done;
+ SizeT out_done;
+ LzmaDecode(&state, &buf[13], buf.size()-13, &in_done,
+ &result[0], result.size(), &out_done);
+
+ delete[] state.Probs;
+
+ result.resize(out_done);
+ return result;
+}
+
+#ifndef COMPACT
+int main(int argc, char *argv[])
+{
+ char *s;
+ FILE *f, *infile, *outfile;
+ int c;
+
+ if (argc != 4) {
+ std::fprintf(stderr, "'lzma e file1 file2' encodes file1 into file2.\n"
+ "'lzma d file2 file1' decodes file2 into file1.\n");
+
+ return EXIT_FAILURE;
+ }
+ if (argc == 4) {
+ if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
+ || (s = argv[2], (infile = fopen(s, "rb")) == NULL)
+ || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
+ std::fprintf(stderr, "??? %s\n", s);
+ return EXIT_FAILURE;
+ }
+ }
+
+ struct stat fs;
+ int si;
+ if (fstat(fileno(infile), &fs)) {
+ std::perror(strerror(errno));
+ return EXIT_FAILURE;
+ }
+ si=fs.st_size;
+
+ char *Buf=(char *)malloc(si);
+ fread(Buf,si, 1, infile);
+
+ std::vector<unsigned char> result;
+ if (toupper(*argv[1]) == 'E')
+ result = LZMACompress(std::vector<unsigned char>(Buf,Buf+si));
+ else
+ result = LZMADeCompress(std::vector<unsigned char>(Buf,Buf+si));
+
+ fwrite(&result[0], result.size(), 1, outfile);
+ fclose(infile);
+ fclose(outfile);
+ return EXIT_SUCCESS;
+}
+#else
+extern "C" {
+
+/**
+ * Compress a buffer with lzma
+ * Don't copy the result back if it is too large.
+ * @param in a pointer to the buffer
+ * @param in_len the length in bytes
+ * @param out a pointer to a buffer of at least size in_len
+ * @param out_len a pointer to the compressed length of in
+ */
+
+void do_lzma_compress(char *in, int in_len, char *out, int *out_len) {
+ std::vector<unsigned char> result;
+ result = LZMACompress(std::vector<unsigned char>(in, in + in_len));
+ *out_len = result.size();
+ if (*out_len < in_len)
+ std::memcpy(out, &result[0], *out_len);
+}
+
+void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) {
+ std::vector<unsigned char> result;
+ result = LZMADeCompress(std::vector<unsigned char>(src, src + src_len));
+ if (result.size() <= dst_len)
+ std::memcpy(dst, &result[0], result.size());
+ else
+ {
+ fprintf(stderr, "Not copying %d bytes to %d-byte buffer!\n",
+ result.size(), dst_len);
+ exit(1);
+ }
+}
+
+}
+#endif
+