From 594c3ed0f6918823f196855f43c39d63f5212402 Mon Sep 17 00:00:00 2001 From: kichik Date: Mon, 24 Nov 2003 00:08:58 +0000 Subject: [PATCH] - First LZMA enhanced NSIS version - experimental - Added SetCompressorDictSize (only works for LZMA) - Added SetCompressionLevel (only "works" for zlib and bzip2) - doesn't work for now - Section is only supposed to get 4 parameters if /o is specified - Updated version numbers git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3190 212acab6-be3b-0410-9dea-997c60f758d6 --- Examples/makensis.nsi | 6 +- Source/7zip/7zGuids.cpp | 9 + Source/7zip/7zip/Common/InBuffer.cpp | 41 + Source/7zip/7zip/Common/InBuffer.h | 69 + Source/7zip/7zip/Common/OutBuffer.cpp | 53 + Source/7zip/7zip/Common/OutBuffer.h | 49 + Source/7zip/7zip/Common/StdAfx.h | 8 + .../7zip/7zip/Compress/LZ/BinTree/BinTree.h | 116 ++ .../7zip/7zip/Compress/LZ/BinTree/BinTree2.h | 18 + .../7zip/7zip/Compress/LZ/BinTree/BinTree3.h | 22 + .../7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h | 19 + .../7zip/Compress/LZ/BinTree/BinTree3ZMain.h | 18 + .../7zip/7zip/Compress/LZ/BinTree/BinTree4.h | 24 + .../7zip/7zip/Compress/LZ/BinTree/BinTree4b.h | 26 + .../7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h | 110 ++ .../7zip/Compress/LZ/BinTree/BinTreeMFMain.h | 81 ++ .../7zip/Compress/LZ/BinTree/BinTreeMain.h | 542 +++++++ Source/7zip/7zip/Compress/LZ/IMatchFinder.h | 65 + Source/7zip/7zip/Compress/LZ/LZInWindow.cpp | 98 ++ Source/7zip/7zip/Compress/LZ/LZInWindow.h | 89 ++ Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp | 83 ++ Source/7zip/7zip/Compress/LZ/LZOutWindow.h | 78 + Source/7zip/7zip/Compress/LZ/StdAfx.h | 8 + Source/7zip/7zip/Compress/LZMA/LZMA.h | 96 ++ .../7zip/7zip/Compress/LZMA/LZMADecoder.cpp | 356 +++++ Source/7zip/7zip/Compress/LZMA/LZMADecoder.h | 107 ++ .../7zip/7zip/Compress/LZMA/LZMAEncoder.cpp | 1264 +++++++++++++++++ Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h | 294 ++++ Source/7zip/7zip/Compress/LZMA/LZMALen.cpp | 74 + Source/7zip/7zip/Compress/LZMA/LZMALen.h | 114 ++ .../7zip/7zip/Compress/LZMA/LZMALiteral.cpp | 69 + Source/7zip/7zip/Compress/LZMA/LZMALiteral.h | 166 +++ Source/7zip/7zip/Compress/LZMA/StdAfx.h | 8 + .../7zip/7zip/Compress/LZMA_SMALL/InBuffer.h | 29 + Source/7zip/7zip/Compress/LZMA_SMALL/LZMA.h | 62 + .../7zip/7zip/Compress/LZMA_SMALL/LZMAConf.h | 25 + .../7zip/Compress/LZMA_SMALL/LZMADecoder.cpp | 183 +++ .../7zip/Compress/LZMA_SMALL/LZMADecoder.h | 82 ++ .../7zip/Compress/LZMA_SMALL/LZMALenCoder.h | 53 + .../Compress/LZMA_SMALL/LZMALiteralCoder.h | 107 ++ .../7zip/7zip/Compress/LZMA_SMALL/LZMAState.h | 39 + .../7zip/Compress/LZMA_SMALL/LZOutWindow.h | 76 + .../7zip/Compress/LZMA_SMALL/RangeCoder.h | 87 ++ .../7zip/Compress/LZMA_SMALL/RangeCoderBit.h | 64 + .../Compress/LZMA_SMALL/RangeCoderBitTree.h | 183 +++ .../7zip/Compress/LZMA_SMALL/RangeCoderOpt.h | 41 + Source/7zip/7zip/Compress/LZMA_SMALL/Types.h | 17 + .../7zip/Compress/RangeCoder/RangeCoder.h | 244 ++++ .../Compress/RangeCoder/RangeCoderBit.cpp | 77 + .../7zip/Compress/RangeCoder/RangeCoderBit.h | 107 ++ .../Compress/RangeCoder/RangeCoderBitTree.h | 303 ++++ .../7zip/Compress/RangeCoder/RangeCoderOpt.h | 43 + Source/7zip/7zip/Compress/RangeCoder/StdAfx.h | 8 + Source/7zip/7zip/ICoder.h | 127 ++ Source/7zip/7zip/IMyUnknown.h | 71 + Source/7zip/7zip/IStream.h | 64 + Source/7zip/Common/CRC.cpp | 110 ++ Source/7zip/Common/CRC.h | 31 + Source/7zip/Common/ComTry.h | 14 + Source/7zip/Common/Defs.h | 22 + Source/7zip/Common/MyCom.h | 187 +++ Source/7zip/Common/StdAfx.h | 8 + Source/7zip/Common/Types.h | 19 + Source/7zip/copying.txt | 504 +++++++ Source/7zip/lzmaNSIS.cpp | 165 +++ Source/7zip/lzmaNSIS.h | 20 + Source/7zip/readme.txt | 31 + Source/build.cpp | 39 +- Source/build.h | 10 +- Source/cbzip2.h | 2 +- Source/clzma.h | 259 ++++ Source/compressor.h | 2 +- Source/czlib.h | 2 +- Source/exedata.cpp | 3 + Source/exedata.h | 2 + Source/exehead/config.h | 40 +- Source/exehead/exehead-lzma.dsp | 227 +++ Source/exehead/fileform.c | 14 +- Source/makenssi.cpp | 3 +- Source/makenssi.dsp | 50 +- Source/makenssi.dsw | 15 + Source/script.cpp | 67 +- Source/tokens.cpp | 4 +- Source/tokens.h | 2 + 84 files changed, 8083 insertions(+), 41 deletions(-) create mode 100644 Source/7zip/7zGuids.cpp create mode 100644 Source/7zip/7zip/Common/InBuffer.cpp create mode 100644 Source/7zip/7zip/Common/InBuffer.h create mode 100644 Source/7zip/7zip/Common/OutBuffer.cpp create mode 100644 Source/7zip/7zip/Common/OutBuffer.h create mode 100644 Source/7zip/7zip/Common/StdAfx.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h create mode 100644 Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h create mode 100644 Source/7zip/7zip/Compress/LZ/IMatchFinder.h create mode 100644 Source/7zip/7zip/Compress/LZ/LZInWindow.cpp create mode 100644 Source/7zip/7zip/Compress/LZ/LZInWindow.h create mode 100644 Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp create mode 100644 Source/7zip/7zip/Compress/LZ/LZOutWindow.h create mode 100644 Source/7zip/7zip/Compress/LZ/StdAfx.h create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMA.h create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMADecoder.cpp create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMADecoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMALen.cpp create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMALen.h create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMALiteral.cpp create mode 100644 Source/7zip/7zip/Compress/LZMA/LZMALiteral.h create mode 100644 Source/7zip/7zip/Compress/LZMA/StdAfx.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/InBuffer.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMA.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMAConf.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.cpp create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMALenCoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMALiteralCoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZMAState.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/LZOutWindow.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoder.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBit.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBitTree.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderOpt.h create mode 100644 Source/7zip/7zip/Compress/LZMA_SMALL/Types.h create mode 100644 Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h create mode 100644 Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp create mode 100644 Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h create mode 100644 Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h create mode 100644 Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h create mode 100644 Source/7zip/7zip/Compress/RangeCoder/StdAfx.h create mode 100644 Source/7zip/7zip/ICoder.h create mode 100644 Source/7zip/7zip/IMyUnknown.h create mode 100644 Source/7zip/7zip/IStream.h create mode 100644 Source/7zip/Common/CRC.cpp create mode 100644 Source/7zip/Common/CRC.h create mode 100644 Source/7zip/Common/ComTry.h create mode 100644 Source/7zip/Common/Defs.h create mode 100644 Source/7zip/Common/MyCom.h create mode 100644 Source/7zip/Common/StdAfx.h create mode 100644 Source/7zip/Common/Types.h create mode 100644 Source/7zip/copying.txt create mode 100644 Source/7zip/lzmaNSIS.cpp create mode 100644 Source/7zip/lzmaNSIS.h create mode 100644 Source/7zip/readme.txt create mode 100644 Source/clzma.h create mode 100644 Source/exehead/exehead-lzma.dsp diff --git a/Examples/makensis.nsi b/Examples/makensis.nsi index 6e6e4d3a..c1f4996e 100644 --- a/Examples/makensis.nsi +++ b/Examples/makensis.nsi @@ -5,8 +5,8 @@ !define VER_REVISION 0 !define VER_BUILD 12 -!define VER_FILE "20b4" -!define VER_DISPLAY "2.0 beta 4" +!define VER_FILE "20b5" +!define VER_DISPLAY "2.0 beta 5 (CVS)" ;-------------------------------- ;Compile CVS Data Setup @@ -19,7 +19,7 @@ ;Configuration OutFile ..\nsis${VER_FILE}.exe -SetCompressor bzip2 +SetCompressor lzma InstType "Full (w/ Source and Contrib)" InstType "Normal (w/ Contrib, w/o Source)" diff --git a/Source/7zip/7zGuids.cpp b/Source/7zip/7zGuids.cpp new file mode 100644 index 00000000..bd5f9398 --- /dev/null +++ b/Source/7zip/7zGuids.cpp @@ -0,0 +1,9 @@ +// DLLExports.cpp + +// #include "StdAfx.h" + +#include +#include +#include "7zip/ICoder.h" +#include "7zip/Compress/LZ/IMatchFinder.h" + diff --git a/Source/7zip/7zip/Common/InBuffer.cpp b/Source/7zip/7zip/Common/InBuffer.cpp new file mode 100644 index 00000000..2d56e44d --- /dev/null +++ b/Source/7zip/7zip/Common/InBuffer.cpp @@ -0,0 +1,41 @@ +// InBuffer.cpp + +#include "stdafx.h" + +#include "InBuffer.h" + +CInBuffer::CInBuffer(UINT32 bufferSize): + _bufferSize(bufferSize), + _bufferBase(0) +{ + _bufferBase = new BYTE[_bufferSize]; +} + +CInBuffer::~CInBuffer() +{ + delete []_bufferBase; +} + +void CInBuffer::Init(ISequentialInStream *stream) +{ + _stream = stream; + _processedSize = 0; + _buffer = _bufferBase; + _bufferLimit = _buffer; + _streamWasExhausted = false; +} + +bool CInBuffer::ReadBlock() +{ + if (_streamWasExhausted) + return false; + _processedSize += (_buffer - _bufferBase); + UINT32 numProcessedBytes; + HRESULT result = _stream->ReadPart(_bufferBase, _bufferSize, &numProcessedBytes); + if (result != S_OK) + throw CInBufferException(result); + _buffer = _bufferBase; + _bufferLimit = _buffer + numProcessedBytes; + _streamWasExhausted = (numProcessedBytes == 0); + return (!_streamWasExhausted); +} diff --git a/Source/7zip/7zip/Common/InBuffer.h b/Source/7zip/7zip/Common/InBuffer.h new file mode 100644 index 00000000..73cbd639 --- /dev/null +++ b/Source/7zip/7zip/Common/InBuffer.h @@ -0,0 +1,69 @@ +// InBuffer.h + +// #pragma once + +#ifndef __INBUFFER_H +#define __INBUFFER_H + +#include "../IStream.h" + +class CInBufferException +{ +public: + HRESULT ErrorCode; + CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +class CInBuffer +{ + UINT64 _processedSize; + BYTE *_bufferBase; + UINT32 _bufferSize; + BYTE *_buffer; + BYTE *_bufferLimit; + ISequentialInStream *_stream; + bool _streamWasExhausted; + + bool ReadBlock(); + +public: + CInBuffer(UINT32 bufferSize = 0x100000); + ~CInBuffer(); + + void Init(ISequentialInStream *stream); + /* + void ReleaseStream() + { _stream.Release(); } + */ + + bool ReadByte(BYTE &b) + { + if(_buffer >= _bufferLimit) + if(!ReadBlock()) + return false; + b = *_buffer++; + return true; + } + BYTE ReadByte() + { + if(_buffer >= _bufferLimit) + if(!ReadBlock()) + return 0x0; + return *_buffer++; + } + void ReadBytes(void *data, UINT32 size, UINT32 &processedSize) + { + for(processedSize = 0; processedSize < size; processedSize++) + if (!ReadByte(((BYTE *)data)[processedSize])) + return; + } + bool ReadBytes(void *data, UINT32 size) + { + UINT32 processedSize; + ReadBytes(data, size, processedSize); + return (processedSize == size); + } + UINT64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } +}; + +#endif diff --git a/Source/7zip/7zip/Common/OutBuffer.cpp b/Source/7zip/7zip/Common/OutBuffer.cpp new file mode 100644 index 00000000..a5fc005d --- /dev/null +++ b/Source/7zip/7zip/Common/OutBuffer.cpp @@ -0,0 +1,53 @@ +// Stream/OutByte.cpp + +#include "StdAfx.h" + +#include "OutBuffer.h" + +COutBuffer::COutBuffer(UINT32 bufferSize): + _bufferSize(bufferSize) +{ + _buffer = new BYTE[_bufferSize]; +} + +COutBuffer::~COutBuffer() +{ + delete []_buffer; +} + +void COutBuffer::Init(ISequentialOutStream *stream) +{ + _stream = stream; + _processedSize = 0; + _pos = 0; +} + +/* +void COutBuffer::ReleaseStream() +{ + _stream.Release(); +} +*/ + + +HRESULT COutBuffer::Flush() +{ + if (_pos == 0) + return S_OK; + UINT32 processedSize; + HRESULT result = _stream->Write(_buffer, _pos, &processedSize); + if (result != S_OK) + return result; + if (_pos != processedSize) + return E_FAIL; + _processedSize += processedSize; + _pos = 0; + return S_OK; +} + +void COutBuffer::WriteBlock() +{ + HRESULT result = Flush(); + if (result != S_OK) + throw COutBufferException(result); +} diff --git a/Source/7zip/7zip/Common/OutBuffer.h b/Source/7zip/7zip/Common/OutBuffer.h new file mode 100644 index 00000000..321fea92 --- /dev/null +++ b/Source/7zip/7zip/Common/OutBuffer.h @@ -0,0 +1,49 @@ +// OutBuffer.h + +// #pragma once + +#ifndef __OUTBUFFER_H +#define __OUTBUFFER_H + +#include "../IStream.h" + +class COutBufferException +{ +public: + HRESULT ErrorCode; + COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +class COutBuffer +{ + BYTE *_buffer; + UINT32 _pos; + UINT32 _bufferSize; + ISequentialOutStream *_stream; + UINT64 _processedSize; + + void WriteBlock(); +public: + COutBuffer(UINT32 bufferSize = (1 << 20)); + ~COutBuffer(); + + void Init(ISequentialOutStream *stream); + HRESULT Flush(); + // void ReleaseStream(); + + void WriteByte(BYTE b) + { + _buffer[_pos++] = b; + if(_pos >= _bufferSize) + WriteBlock(); + } + void WriteBytes(const void *data, UINT32 size) + { + for (UINT32 i = 0; i < size; i++) + WriteByte(((const BYTE *)data)[i]); + } + + UINT64 GetProcessedSize() const { return _processedSize + _pos; } +}; + +#endif diff --git a/Source/7zip/7zip/Common/StdAfx.h b/Source/7zip/7zip/Common/StdAfx.h new file mode 100644 index 00000000..a32fbed6 --- /dev/null +++ b/Source/7zip/7zip/Common/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h new file mode 100644 index 00000000..9096fe70 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h @@ -0,0 +1,116 @@ +// BinTree.h + +// #pragma once + +// #ifndef __BINTREE_H +// #define __BINTREE_H + +#include "../LZInWindow.h" +// #include "Common/Types.h" +// #include "Windows/Defs.h" + +namespace BT_NAMESPACE { + +// #define __USE_3_BYTES + +#ifdef __USE_3_BYTES + +#pragma pack(push, PragmaBinTree, 1) + +struct CIndex +{ + BYTE Data[3]; + CIndex(){} + CIndex(UINT32 value) + { + Data[0] = value & 0xFF; + Data[1] = (value >> 8) & 0xFF; + Data[2] = (value >> 16) & 0xFF; + } + operator UINT32() const { return (*((const UINT32 *)Data)) & 0xFFFFFF; } +}; +const UINT32 kMaxValForNormalize = CIndex(-1); + +#pragma pack(pop, PragmaBinTree) + +#else + +typedef UINT32 CIndex; +const UINT32 kMaxValForNormalize = (UINT32(1) << 31) - 1; + +#endif + + + +// #define HASH_ARRAY_2 + +// #ifdef HASH_ARRAY_2 + +// #define HASH_ARRAY_3 + +// #else + +// #define HASH_ZIP + +// #endif + +#pragma pack(push, PragmaBinTreePair, 1) +// #pragma pack(push, 1) + +struct CPair +{ + CIndex Left; + CIndex Right; +}; + +// #pragma pack(pop) +#pragma pack(pop, PragmaBinTreePair) + +class CInTree: public CLZInWindow +{ + UINT32 _cyclicBufferPos; + UINT32 _cyclicBufferSize; + UINT32 _historySize; + UINT32 _matchMaxLen; + + CIndex *_hash; + + #ifdef HASH_ARRAY_2 + CIndex *_hash2; + #ifdef HASH_ARRAY_3 + CIndex *_hash3; + #endif + #endif + + CPair *_son; + + UINT32 _cutValue; + + void NormalizeLinks(CIndex *array, UINT32 numItems, UINT32 subValue); + void Normalize(); + void FreeMemory(); + +public: + CInTree(); + ~CInTree(); + HRESULT Create(UINT32 sizeHistory, UINT32 keepAddBufferBefore, UINT32 matchMaxLen, + UINT32 keepAddBufferAfter, UINT32 sizeReserv = (1<<17)); + HRESULT Init(ISequentialInStream *stream); + void SetCutValue(UINT32 cutValue) { _cutValue = cutValue; } + UINT32 GetLongestMatch(UINT32 *distances); + void DummyLongestMatch(); + HRESULT MovePos() + { + _cyclicBufferPos++; + if (_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; + } +}; + +} + +// #endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h new file mode 100644 index 00000000..2a93e8b2 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h @@ -0,0 +1,18 @@ +// BinTree2.h + +// #pragma once + +#ifndef __BINTREE2__H +#define __BINTREE2__H + +#undef BT_CLSID +#define BT_CLSID CLSID_CMatchFinderBT2 + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT2 + +#include "BinTreeMF.h" +#include "BinTreeMFMain.h" + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h new file mode 100644 index 00000000..69bb8711 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h @@ -0,0 +1,22 @@ +// BinTree3.h + +// #pragma once + +#ifndef __BINTREE3__H +#define __BINTREE3__H + +#undef BT_CLSID +#define BT_CLSID CLSID_CMatchFinderBT3 + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT3 + +#define HASH_ARRAY_2 + +#include "BinTreeMF.h" +#include "BinTreeMFMain.h" + +#undef HASH_ARRAY_2 + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h new file mode 100644 index 00000000..9217d9fe --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h @@ -0,0 +1,19 @@ +// BinTree3Z.h + +// #pragma once + +#ifndef __BINTREE3Z__H +#define __BINTREE3Z__H + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT3Z + +#define HASH_ZIP + +#include "BinTree.h" +// #include "BinTreeMain.h" + +#undef HASH_ZIP + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h new file mode 100644 index 00000000..ded819f1 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h @@ -0,0 +1,18 @@ +// BinTree3ZMain.h + +// #pragma once + +#ifndef __BINTREE3ZMAIN__H +#define __BINTREE3ZMAIN__H + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT3Z + +#define HASH_ZIP + +#include "BinTreeMain.h" + +#undef HASH_ZIP + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h new file mode 100644 index 00000000..c5cc2a76 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h @@ -0,0 +1,24 @@ +// BinTree4.h + +// #pragma once + +#ifndef __BINTREE4__H +#define __BINTREE4__H + +#undef BT_CLSID +#define BT_CLSID CLSID_CMatchFinderBT4 + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT4 + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 + +#include "BinTreeMF.h" +#include "BinTreeMFMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h new file mode 100644 index 00000000..0128f32c --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h @@ -0,0 +1,26 @@ +// BinTree4b.h + +// #pragma once + +#ifndef __BINTREE4B__H +#define __BINTREE4B__H + +#undef BT_CLSID +#define BT_CLSID CLSID_CMatchFinderBT4b + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT4B + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 +#define HASH_BIG + +#include "BinTreeMF.h" +#include "BinTreeMFMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 +#undef HASH_BIG + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h new file mode 100644 index 00000000..9903db4f --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h @@ -0,0 +1,110 @@ +// BinTreeMF.h + +// #pragma once + +// #ifndef __BINTREEMF_H +// #define __BINTREEMF_H + +#include "../../../ICoder.h" +#include "BinTree.h" + +namespace BT_NAMESPACE { + +#undef kIDByte +#undef kIDString + +#ifdef HASH_ARRAY_2 + #ifdef HASH_ARRAY_3 + #ifdef HASH_BIG + #define kIDByte 0x4 + #define kIDString TEXT("4b") + #else + #define kIDByte 0x3 + #define kIDString TEXT("4") + #endif + #else + #define kIDByte 0x2 + #define kIDString TEXT("3") + #endif +#else + #ifdef HASH_ZIP + #define kIDByte 0x0 + #define kIDString TEXT("3Z") + #else + #define kIDByte 0x1 + #define kIDString TEXT("2") + #endif +#endif + +#undef kIDUse3BytesByte +#undef kIDUse3BytesString + +#ifdef __USE_3_BYTES + #define kIDUse3BytesByte 0x80 + #define kIDUse3BytesString TEXT("T") +#else + #define kIDUse3BytesByte 0x00 + #define kIDUse3BytesString TEXT("") +#endif + +// #undef kIDStringFull + +// #define kIDStringFull TEXT("Compress.MatchFinderBT") kIDString kIDUse3BytesString + +// {23170F69-40C1-278C-02XX-0000000000} +DEFINE_GUID(BT_CLSID, +0x23170F69, 0x40C1, 0x278C, 0x02, kIDByte | kIDUse3BytesByte, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +class CInTree2: public CInTree +{ + CMyComPtr _callback; + virtual void BeforeMoveBlock(); + virtual void AfterMoveBlock(); +public: + void SetCallback(IMatchFinderCallback *callback) + { + _callback = callback; + } +}; + +class CMatchFinderBinTree: + public IMatchFinder, + public IMatchFinderSetCallback, + public CMyUnknownImp +{ + MY_UNKNOWN_IMP1(IMatchFinderSetCallback) + + STDMETHOD(Init)(ISequentialInStream *stream); + STDMETHOD_(void, ReleaseStream)(); + STDMETHOD(MovePos)(); + STDMETHOD_(BYTE, GetIndexByte)(UINT32 index); + STDMETHOD_(UINT32, GetMatchLen)(UINT32 index, UINT32 back, UINT32 limit); + STDMETHOD_(UINT32, GetNumAvailableBytes)(); + STDMETHOD_(const BYTE *, GetPointerToCurrentPos)(); + STDMETHOD(Create)(UINT32 sizeHistory, + UINT32 keepAddBufferBefore, UINT32 matchMaxLen, + UINT32 keepAddBufferAfter); + STDMETHOD_(UINT32, GetLongestMatch)(UINT32 *distances); + STDMETHOD_(void, DummyLongestMatch)(); + + // IMatchFinderSetCallback + STDMETHOD(SetCallback)(IMatchFinderCallback *callback); + +private: + // UINT32 m_WindowReservSize; + CInTree2 _matchFinder; +public: + // CMatchFinderBinTree(): m_WindowReservSize((1 << 19) + 256) {}; + void SetCutValue(UINT32 cutValue) + { _matchFinder.SetCutValue(cutValue); } + /* + void SetWindowReservSize(UINT32 reservWindowSize) + { m_WindowReservSize = reservWindowSize; } + */ +}; + +} + +// #endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h new file mode 100644 index 00000000..499686ba --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h @@ -0,0 +1,81 @@ +// BinTreeMFMain.h + +// #include "StdAfx.h" + +// #include "BinTreeMF.h" +#include "BinTreeMain.h" + +namespace BT_NAMESPACE { + +void CInTree2::BeforeMoveBlock() +{ + if (_callback) + _callback->BeforeChangingBufferPos(); + CInTree::BeforeMoveBlock(); +} + +void CInTree2::AfterMoveBlock() +{ + CInTree::AfterMoveBlock(); + if (_callback) + _callback->AfterChangingBufferPos(); +} + +STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream) + { return _matchFinder.Init(stream); } + +STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream() +{ + // _matchFinder.ReleaseStream(); +} + +STDMETHODIMP CMatchFinderBinTree::MovePos() + { return _matchFinder.MovePos(); } + +STDMETHODIMP_(BYTE) CMatchFinderBinTree::GetIndexByte(UINT32 index) + { return _matchFinder.GetIndexByte(index); } + +STDMETHODIMP_(UINT32) CMatchFinderBinTree::GetMatchLen(UINT32 index, + UINT32 back, UINT32 limit) + { return _matchFinder.GetMatchLen(index, back, limit); } + +STDMETHODIMP_(UINT32) CMatchFinderBinTree::GetNumAvailableBytes() + { return _matchFinder.GetNumAvailableBytes(); } + +STDMETHODIMP CMatchFinderBinTree::Create(UINT32 sizeHistory, + UINT32 keepAddBufferBefore, UINT32 matchMaxLen, + UINT32 keepAddBufferAfter) +{ + UINT32 windowReservSize = (sizeHistory + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + try + { + return _matchFinder.Create(sizeHistory, keepAddBufferBefore, + matchMaxLen, keepAddBufferAfter, windowReservSize); + } + catch(...) + { + return E_OUTOFMEMORY; + } +} + +STDMETHODIMP_(UINT32) CMatchFinderBinTree::GetLongestMatch(UINT32 *distances) + { return _matchFinder.GetLongestMatch(distances); } + +STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch() + { _matchFinder.DummyLongestMatch(); } + +STDMETHODIMP_(const BYTE *) CMatchFinderBinTree::GetPointerToCurrentPos() +{ + return _matchFinder.GetPointerToCurrentPos(); +} + +// IMatchFinderSetCallback +STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback) +{ + _matchFinder.SetCallback(callback); + return S_OK; +} + + +} diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h new file mode 100644 index 00000000..6657d07d --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h @@ -0,0 +1,542 @@ +// BinTreemain.h + +// #include "StdAfx.h" + +// #include "BinTree.h" +// #include "Common/NewHandler.h" + +#include "../../../../Common/Defs.h" +#include "../../../../Common/CRC.h" + +namespace BT_NAMESPACE { + +#ifdef HASH_ARRAY_2 + static const UINT32 kHash2Size = 1 << 10; + #ifdef HASH_ARRAY_3 + static const UINT32 kNumHashDirectBytes = 0; + static const UINT32 kNumHashBytes = 4; + static const UINT32 kHash3Size = 1 << 18; + #ifdef HASH_BIG + static const UINT32 kHashSize = 1 << 23; + #else + static const UINT32 kHashSize = 1 << 20; + #endif + #else + static const UINT32 kNumHashDirectBytes = 3; + static const UINT32 kNumHashBytes = 3; + static const UINT32 kHashSize = 1 << (8 * kNumHashBytes); + #endif +#else + #ifdef HASH_ZIP + static const UINT32 kNumHashDirectBytes = 0; + static const UINT32 kNumHashBytes = 3; + static const UINT32 kHashSize = 1 << 16; + #else + static const UINT32 kNumHashDirectBytes = 2; + static const UINT32 kNumHashBytes = 2; + static const UINT32 kHashSize = 1 << (8 * kNumHashBytes); + #endif +#endif + + +CInTree::CInTree(): + #ifdef HASH_ARRAY_2 + _hash2(0), + #ifdef HASH_ARRAY_3 + _hash3(0), + #endif + #endif + _hash(0), + _son(0), + _cutValue(0xFF) +{ +} + +void CInTree::FreeMemory() +{ + #ifdef WIN32 + if (_son != 0) + VirtualFree(_son, 0, MEM_RELEASE); + if (_hash != 0) + VirtualFree(_hash, 0, MEM_RELEASE); + #else + delete []_son; + delete []_hash; + #endif + _son = 0; + _hash = 0; + CLZInWindow::Free(); +} + +CInTree::~CInTree() +{ + FreeMemory(); +} + +HRESULT CInTree::Create(UINT32 sizeHistory, UINT32 keepAddBufferBefore, + UINT32 matchMaxLen, UINT32 keepAddBufferAfter, UINT32 sizeReserv) +{ + FreeMemory(); + try + { + CLZInWindow::Create(sizeHistory + keepAddBufferBefore, + matchMaxLen + keepAddBufferAfter, sizeReserv); + + if (_blockSize + 256 > kMaxValForNormalize) + return E_INVALIDARG; + + _historySize = sizeHistory; + _matchMaxLen = matchMaxLen; + + _cyclicBufferSize = sizeHistory + 1; + + + UINT32 size = kHashSize; + #ifdef HASH_ARRAY_2 + size += kHash2Size; + #ifdef HASH_ARRAY_3 + size += kHash3Size; + #endif + #endif + + #ifdef WIN32 + _son = (CPair *)::VirtualAlloc(0, (_cyclicBufferSize + 1) * sizeof(CPair), MEM_COMMIT, PAGE_READWRITE); + if (_son == 0) + throw 1; // CNewException(); + _hash = (CIndex *)::VirtualAlloc(0, (size + 1) * sizeof(CIndex), MEM_COMMIT, PAGE_READWRITE); + if (_hash == 0) + throw 1; // CNewException(); + #else + _son = new CPair[_cyclicBufferSize + 1]; + _hash = new CIndex[size + 1]; + #endif + + // m_RightBase = &m_LeftBase[_blockSize]; + + // _hash = &m_RightBase[_blockSize]; + #ifdef HASH_ARRAY_2 + _hash2 = &_hash[kHashSize]; + #ifdef HASH_ARRAY_3 + _hash3 = &_hash2[kHash2Size]; + #endif + #endif + return S_OK; + } + catch(...) + { + FreeMemory(); + return E_OUTOFMEMORY; + } +} + +static const UINT32 kEmptyHashValue = 0; + +HRESULT CInTree::Init(ISequentialInStream *stream) +{ + RINOK(CLZInWindow::Init(stream)); + int i; + for(i = 0; i < kHashSize; i++) + _hash[i] = kEmptyHashValue; + + #ifdef HASH_ARRAY_2 + for(i = 0; i < kHash2Size; i++) + _hash2[i] = kEmptyHashValue; + #ifdef HASH_ARRAY_3 + for(i = 0; i < kHash3Size; i++) + _hash3[i] = kEmptyHashValue; + #endif + #endif + + _cyclicBufferPos = 0; + + ReduceOffsets(0 - 1); + return S_OK; +} + + +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 +inline UINT32 Hash(const BYTE *pointer, UINT32 &hash2Value, UINT32 &hash3Value) +{ + UINT32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; + hash2Value = temp & (kHash2Size - 1); + hash3Value = (temp ^ (UINT32(pointer[2]) << 8)) & (kHash3Size - 1); + return (temp ^ (UINT32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & + (kHashSize - 1); +} +#else // no HASH_ARRAY_3 +inline UINT32 Hash(const BYTE *pointer, UINT32 &hash2Value) +{ + hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1); + return (*((const UINT32 *)pointer)) & 0xFFFFFF; +} +#endif // HASH_ARRAY_3 +#else // no HASH_ARRAY_2 +#ifdef HASH_ZIP +inline UINT32 Hash(const BYTE *pointer) +{ + return ((UINT32(pointer[0]) << 8) ^ + CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); +} +#else // no HASH_ZIP +inline UINT32 Hash(const BYTE *pointer) +{ + return pointer[0] ^ (UINT32(pointer[1]) << 8); +} +#endif // HASH_ZIP +#endif // HASH_ARRAY_2 + +UINT32 CInTree::GetLongestMatch(UINT32 *distances) +{ + UINT32 currentLimit; + if (_pos + _matchMaxLen <= _streamPos) + currentLimit = _matchMaxLen; + else + { + currentLimit = _streamPos - _pos; + if(currentLimit < kNumHashBytes) + return 0; + } + + UINT32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; + BYTE *cur = _buffer + _pos; + + UINT32 matchHashLenMax = 0; + + #ifdef HASH_ARRAY_2 + UINT32 hash2Value; + #ifdef HASH_ARRAY_3 + UINT32 hash3Value; + UINT32 hashValue = Hash(cur, hash2Value, hash3Value); + #else + UINT32 hashValue = Hash(cur, hash2Value); + #endif + #else + UINT32 hashValue = Hash(cur); + #endif + + UINT32 curMatch = _hash[hashValue]; + #ifdef HASH_ARRAY_2 + UINT32 curMatch2 = _hash2[hash2Value]; + #ifdef HASH_ARRAY_3 + UINT32 curMatch3 = _hash3[hash3Value]; + #endif + _hash2[hash2Value] = _pos; + bool matchLen2Exist = false; + UINT32 len2Distance = 0; + if(curMatch2 >= matchMinPos) + { + if (_buffer[curMatch2] == cur[0]) + { + len2Distance = _pos - curMatch2 - 1; + matchHashLenMax = 2; + matchLen2Exist = true; + } + } + + #ifdef HASH_ARRAY_3 + _hash3[hash3Value] = _pos; + UINT32 matchLen3Exist = false; + UINT32 len3Distance = 0; + if(curMatch3 >= matchMinPos) + { + if (_buffer[curMatch3] == cur[0]) + { + len3Distance = _pos - curMatch3 - 1; + matchHashLenMax = 3; + matchLen3Exist = true; + if (matchLen2Exist) + { + if (len3Distance < len2Distance) + len2Distance = len3Distance; + } + else + { + len2Distance = len3Distance; + matchLen2Exist = true; + } + } + } + #endif + #endif + + _hash[hashValue] = _pos; + + if(curMatch < matchMinPos) + { + _son[_cyclicBufferPos].Left = kEmptyHashValue; + _son[_cyclicBufferPos].Right = kEmptyHashValue; + + #ifdef HASH_ARRAY_2 + distances[2] = len2Distance; + #ifdef HASH_ARRAY_3 + distances[3] = len3Distance; + #endif + #endif + + return matchHashLenMax; + } + CIndex *ptrLeft = &_son[_cyclicBufferPos].Right; + CIndex *ptrRight = &_son[_cyclicBufferPos].Left; + + UINT32 maxLen, minSameLeft, minSameRight, minSame; + maxLen = minSameLeft = minSameRight = minSame = kNumHashDirectBytes; + + #ifdef HASH_ARRAY_2 + #ifndef HASH_ARRAY_3 + if (matchLen2Exist) + distances[2] = len2Distance; + else + if (kNumHashDirectBytes >= 2) + distances[2] = _pos - curMatch - 1; + #endif + #endif + + distances[maxLen] = _pos - curMatch - 1; + + for(UINT32 count = _cutValue; count > 0; count--) + { + BYTE *pby1 = _buffer + curMatch; + // CIndex left = _son[curMatch].Left; // it's prefetch + UINT32 currentLen; + for(currentLen = minSame; currentLen < currentLimit; currentLen++/*, dwComps++*/) + if (pby1[currentLen] != cur[currentLen]) + break; + while (currentLen > maxLen) + distances[++maxLen] = _pos - curMatch - 1; + + UINT32 delta = _pos - curMatch; + UINT32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + + if (currentLen != currentLimit) + { + if (pby1[currentLen] < cur[currentLen]) + { + *ptrRight = curMatch; + ptrRight = &_son[cyclicPos].Right; + curMatch = _son[cyclicPos].Right; + if(currentLen > minSameLeft) + { + minSameLeft = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + else + { + *ptrLeft = curMatch; + ptrLeft = &_son[cyclicPos].Left; + // curMatch = left; + curMatch = _son[cyclicPos].Left; + if(currentLen > minSameRight) + { + minSameRight = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + } + else + { + if(currentLen < _matchMaxLen) + { + *ptrLeft = curMatch; + ptrLeft = &_son[cyclicPos].Left; + curMatch = _son[cyclicPos].Left; + if(currentLen > minSameRight) + { + minSameRight = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + else + { + *ptrLeft = _son[cyclicPos].Right; + *ptrRight = _son[cyclicPos].Left; + + #ifdef HASH_ARRAY_2 + if (matchLen2Exist && len2Distance < distances[2]) + distances[2] = len2Distance; + #ifdef HASH_ARRAY_3 + if (matchLen3Exist && len3Distance < distances[3]) + distances[3] = len3Distance; + #endif + #endif + + return maxLen; + } + } + if(curMatch < matchMinPos) + break; + } + *ptrLeft = kEmptyHashValue; + *ptrRight = kEmptyHashValue; + #ifdef HASH_ARRAY_2 + if (matchLen2Exist) + { + if (maxLen < 2) + { + distances[2] = len2Distance; + maxLen = 2; + } + else if (len2Distance < distances[2]) + distances[2] = len2Distance; + } + #ifdef HASH_ARRAY_3 + if (matchLen3Exist) + { + if (maxLen < 3) + { + distances[3] = len3Distance; + maxLen = 3; + } + else if (len3Distance < distances[3]) + distances[3] = len3Distance; + } + #endif + #endif + return maxLen; +} + +void CInTree::DummyLongestMatch() +{ + UINT32 currentLimit; + if (_pos + _matchMaxLen <= _streamPos) + currentLimit = _matchMaxLen; + else + { + currentLimit = _streamPos - _pos; + if(currentLimit < kNumHashBytes) + return; + } + UINT32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; + BYTE *cur = _buffer + _pos; + + #ifdef HASH_ARRAY_2 + UINT32 hash2Value; + #ifdef HASH_ARRAY_3 + UINT32 hash3Value; + UINT32 hashValue = Hash(cur, hash2Value, hash3Value); + _hash3[hash3Value] = _pos; + #else + UINT32 hashValue = Hash(cur, hash2Value); + #endif + _hash2[hash2Value] = _pos; + #else + UINT32 hashValue = Hash(cur); + #endif + + UINT32 curMatch = _hash[hashValue]; + _hash[hashValue] = _pos; + + if(curMatch < matchMinPos) + { + _son[_cyclicBufferPos].Left = kEmptyHashValue; + _son[_cyclicBufferPos].Right = kEmptyHashValue; + return; + } + CIndex *ptrLeft = &_son[_cyclicBufferPos].Right; + CIndex *ptrRight = &_son[_cyclicBufferPos].Left; + + UINT32 maxLen, minSameLeft, minSameRight, minSame; + maxLen = minSameLeft = minSameRight = minSame = kNumHashDirectBytes; + for(UINT32 count = _cutValue; count > 0; count--) + { + BYTE *pby1 = _buffer + curMatch; + // CIndex left = _son[curMatch].Left; // it's prefetch + UINT32 currentLen; + for(currentLen = minSame; currentLen < currentLimit; currentLen++/*, dwComps++*/) + if (pby1[currentLen] != cur[currentLen]) + break; + + UINT32 delta = _pos - curMatch; + UINT32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + + if (currentLen != currentLimit) + { + if (pby1[currentLen] < cur[currentLen]) + { + *ptrRight = curMatch; + ptrRight = &_son[cyclicPos].Right; + curMatch = _son[cyclicPos].Right; + if(currentLen > minSameLeft) + { + minSameLeft = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + else + { + *ptrLeft = curMatch; + ptrLeft = &_son[cyclicPos].Left; + curMatch = _son[cyclicPos].Left; + // curMatch = left; + if(currentLen > minSameRight) + { + minSameRight = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + } + else + { + if(currentLen < _matchMaxLen) + { + *ptrLeft = curMatch; + ptrLeft = &_son[cyclicPos].Left; + curMatch = _son[cyclicPos].Left; + if(currentLen > minSameRight) + { + minSameRight = currentLen; + minSame = MyMin(minSameLeft, minSameRight); + } + } + else + { + *ptrLeft = _son[cyclicPos].Right; + *ptrRight = _son[cyclicPos].Left; + return; + } + } + if(curMatch < matchMinPos) + break; + } + *ptrLeft = kEmptyHashValue; + *ptrRight = kEmptyHashValue; +} + +void CInTree::NormalizeLinks(CIndex *array, UINT32 numItems, UINT32 subValue) +{ + for (UINT32 i = 0; i < numItems; i++) + { + UINT32 value = array[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + array[i] = value; + } +} + +void CInTree::Normalize() +{ + UINT32 startItem = _pos - _historySize; + UINT32 subValue = startItem - 1; + // NormalizeLinks((CIndex *)(_son + startItem), _historySize * 2, subValue); + NormalizeLinks((CIndex *)_son, _cyclicBufferSize * 2, subValue); + + NormalizeLinks(_hash, kHashSize, subValue); + + #ifdef HASH_ARRAY_2 + NormalizeLinks(_hash2, kHash2Size, subValue); + #ifdef HASH_ARRAY_3 + NormalizeLinks(_hash3, kHash3Size, subValue); + #endif + #endif + + ReduceOffsets(subValue); +} + +} diff --git a/Source/7zip/7zip/Compress/LZ/IMatchFinder.h b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h new file mode 100644 index 00000000..6efa8941 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h @@ -0,0 +1,65 @@ +// MatchFinders/IMatchFinder.h + +// #pragma once + +#ifndef __IMATCHFINDER_H +#define __IMATCHFINDER_H + +// {23170F69-40C1-278A-0000-000200010000} +DEFINE_GUID(IID_IInWindowStream, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000") +IInWindowStream: public IUnknown +{ + STDMETHOD(Init)(ISequentialInStream *inStream) PURE; + STDMETHOD_(void, ReleaseStream)() PURE; + STDMETHOD(MovePos)() PURE; + STDMETHOD_(BYTE, GetIndexByte)(UINT32 index) PURE; + STDMETHOD_(UINT32, GetMatchLen)(UINT32 index, UINT32 distance, UINT32 limit) PURE; + STDMETHOD_(UINT32, GetNumAvailableBytes)() PURE; + STDMETHOD_(const BYTE *, GetPointerToCurrentPos)() PURE; +}; + +// {23170F69-40C1-278A-0000-000200020000} +DEFINE_GUID(IID_IMatchFinder, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000") +IMatchFinder: public IInWindowStream +{ + STDMETHOD(Create)(UINT32 historySize, UINT32 keepAddBufferBefore, + UINT32 matchMaxLen, UINT32 keepAddBufferAfter) PURE; + STDMETHOD_(UINT32, GetLongestMatch)(UINT32 *distances) PURE; + STDMETHOD_(void, DummyLongestMatch)() PURE; +}; + +// {23170F69-40C1-278A-0000-000200020100} +DEFINE_GUID(IID_IMatchFinderCallback, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100") +IMatchFinderCallback: public IUnknown +{ + STDMETHOD(BeforeChangingBufferPos)() PURE; + STDMETHOD(AfterChangingBufferPos)() PURE; +}; + +// {23170F69-40C1-278A-0000-000200020200} +DEFINE_GUID(IID_IMatchFinderSetCallback, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200") +IMatchFinderSetCallback: public IUnknown +{ + STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE; +}; + +/* +// {23170F69-40C1-278A-0000-000200030000} +DEFINE_GUID(IID_IInitMatchFinder, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000") +IMatchFinderInit: public IUnknown +{ + STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE; +}; +*/ + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp new file mode 100644 index 00000000..817ef800 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp @@ -0,0 +1,98 @@ +// LZInWindow.cpp + +#include "StdAfx.h" + +#include "LZInWindow.h" +#include "../../../Common/MyCom.h" + +CLZInWindow::~CLZInWindow() +{ + Free(); +} + +void CLZInWindow::Free() +{ + delete []_bufferBase; + _bufferBase = 0; +} + +void CLZInWindow::Create(UINT32 keepSizeBefore, UINT32 keepSizeAfter, UINT32 keepSizeReserv) +{ + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + _keepSizeReserv = keepSizeReserv; + _blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + Free(); + _bufferBase = new BYTE[_blockSize]; + _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; +} + + +HRESULT CLZInWindow::Init(ISequentialInStream *stream) +{ + _stream = stream; + _buffer = _bufferBase; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + return ReadBlock(); +} + +/* +void CLZInWindow::ReleaseStream() +{ + _stream.Release(); +} +*/ + +/////////////////////////////////////////// +// ReadBlock + +// In State: +// (_buffer + _streamPos) <= (_bufferBase + _blockSize) +// Out State: +// _posLimit <= _blockSize - _keepSizeAfter; +// if(_streamEndWasReached == false): +// _streamPos >= _pos + _keepSizeAfter +// _posLimit = _streamPos - _keepSizeAfter; +// else +// + +HRESULT CLZInWindow::ReadBlock() +{ + if(_streamEndWasReached) + return S_OK; + while(true) + { + UINT32 size = (_bufferBase + _blockSize) - (_buffer + _streamPos); + if(size == 0) + return S_OK; + UINT32 numReadBytes; + RINOK(_stream->ReadPart(_buffer + _streamPos, size, &numReadBytes)); + if(numReadBytes == 0) + { + _posLimit = _streamPos; + const BYTE *pointerToPostion = _buffer + _posLimit; + if(pointerToPostion > _pointerToLastSafePosition) + _posLimit = _pointerToLastSafePosition - _buffer; + _streamEndWasReached = true; + return S_OK; + } + _streamPos += numReadBytes; + if(_streamPos >= _pos + _keepSizeAfter) + { + _posLimit = _streamPos - _keepSizeAfter; + return S_OK; + } + } +} + +void CLZInWindow::MoveBlock() +{ + BeforeMoveBlock(); + UINT32 offset = (_buffer + _pos - _keepSizeBefore) - _bufferBase; + UINT32 numBytes = (_buffer + _streamPos) - (_bufferBase + offset); + memmove(_bufferBase, _bufferBase + offset, numBytes); + _buffer -= offset; + AfterMoveBlock(); +} diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.h b/Source/7zip/7zip/Compress/LZ/LZInWindow.h new file mode 100644 index 00000000..6ae2da16 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.h @@ -0,0 +1,89 @@ +// LZInWindow.h + +// #pragma once + +#ifndef __LZ_IN_WINDOW_H +#define __LZ_IN_WINDOW_H + +#include "../../IStream.h" + +class CLZInWindow +{ + BYTE *_bufferBase; // pointer to buffer with data + ISequentialInStream *_stream; + UINT32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + const BYTE *_pointerToLastSafePosition; +protected: + BYTE *_buffer; // Pointer to virtual Buffer begin + UINT32 _blockSize; // Size of Allocated memory block + UINT32 _pos; // offset (from _buffer) of curent byte + UINT32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UINT32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + UINT32 _keepSizeReserv; // how many BYTEs must be kept as reserv + UINT32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + virtual void BeforeMoveBlock() {}; + virtual void AfterMoveBlock() {}; + void MoveBlock(); + virtual HRESULT ReadBlock(); + void Free(); +public: + CLZInWindow(): _bufferBase(0) {} + ~CLZInWindow(); + void Create(UINT32 keepSizeBefore, UINT32 keepSizeAfter, + UINT32 keepSizeReserv = (1<<17)); + + HRESULT Init(ISequentialInStream *stream); + // void ReleaseStream(); + + BYTE *GetBuffer() const { return _buffer; } + + const BYTE *GetPointerToCurrentPos() const { return _buffer + _pos; } + + HRESULT MovePos() + { + _pos++; + if (_pos > _posLimit) + { + const BYTE *pointerToPostion = _buffer + _pos; + if(pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + return ReadBlock(); + } + else + return S_OK; + } + // BYTE GetCurrentByte()const; + BYTE GetIndexByte(UINT32 index)const + { return _buffer[_pos + index]; } + + // UINT32 GetCurPos()const { return _pos;}; + // BYTE *GetBufferBeg()const { return _buffer;}; + + // index + limit have not to exceed _keepSizeAfter; + UINT32 GetMatchLen(UINT32 index, UINT32 back, UINT32 limit) const + { + if(_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (_pos + index); + back++; + BYTE *pby = _buffer + _pos + index; + UINT32 i; + for(i = 0; i < limit && pby[i] == pby[i - back]; i++); + return i; + } + + UINT32 GetNumAvailableBytes() const { return _streamPos - _pos; } + + void ReduceOffsets(UINT32 subValue) + { + _buffer += subValue; + _posLimit -= subValue; + _pos -= subValue; + _streamPos -= subValue; + } + +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp new file mode 100644 index 00000000..22fb4c04 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp @@ -0,0 +1,83 @@ +// LZOutWindow.cpp + +#include "StdAfx.h" + +#include "LZOutWindow.h" + +void CLZOutWindow::Create(UINT32 windowSize) +{ + _pos = 0; + _streamPos = 0; + UINT32 newBlockSize = windowSize; + const UINT32 kMinBlockSize = 1; + if (newBlockSize < kMinBlockSize) + newBlockSize = kMinBlockSize; + if (_buffer != 0 && _windowSize == newBlockSize) + return; + delete []_buffer; + _buffer = 0; + _windowSize = newBlockSize; + _buffer = new BYTE[_windowSize]; +} + +CLZOutWindow::~CLZOutWindow() +{ + // ReleaseStream(); + delete []_buffer; +} + +/* +void CLZOutWindow::SetWindowSize(UINT32 windowSize) +{ + _windowSize = windowSize; +} +*/ + +void CLZOutWindow::Init(ISequentialOutStream *stream, bool solid) +{ + // ReleaseStream(); + _stream = stream; + // _stream->AddRef(); + + if(!solid) + { + _streamPos = 0; + _pos = 0; + } +} + +/* +void CLZOutWindow::ReleaseStream() +{ + if(_stream != 0) + { + // Flush(); // Test it + _stream->Release(); + _stream = 0; + } +} +*/ + +void CLZOutWindow::FlushWithCheck() +{ + HRESULT result = Flush(); + if (result != S_OK) + throw CLZOutWindowException(result); +} + +HRESULT CLZOutWindow::Flush() +{ + UINT32 size = _pos - _streamPos; + if(size == 0) + return S_OK; + UINT32 processedSize; + HRESULT result = _stream->Write(_buffer + _streamPos, size, &processedSize); + if (result != S_OK) + return result; + if (size != processedSize) + return E_FAIL; + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + return S_OK; +} diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.h b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h new file mode 100644 index 00000000..d0b392c3 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h @@ -0,0 +1,78 @@ +// LZOutWindow.h + +// #pragma once + +#ifndef __LZ_OUT_WINDOW_H +#define __LZ_OUT_WINDOW_H + +#include "../../IStream.h" + +// m_KeepSizeBefore: how mach BYTEs must be in buffer before _pos; +// m_KeepSizeAfter: how mach BYTEs must be in buffer after _pos; +// m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv; +// must be >= aKeepSizeAfter; // test it + +class CLZOutWindowException +{ +public: + HRESULT ErrorCode; + CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +class CLZOutWindow +{ + BYTE *_buffer; + UINT32 _pos; + UINT32 _windowSize; + UINT32 _streamPos; + ISequentialOutStream *_stream; + void FlushWithCheck(); + +public: + CLZOutWindow(): _buffer(0), _stream(0) {} + ~CLZOutWindow(); + void Create(UINT32 windowSize); + bool IsCreated() const { return _buffer != 0; } + + void Init(ISequentialOutStream *stream, bool solid = false); + HRESULT Flush(); + // void ReleaseStream(); + + // UINT32 GetCurPos() const { return _pos; } + // const BYTE *GetPointerToCurrentPos() const { return _buffer + _pos;}; + + void CopyBackBlock(UINT32 distance, UINT32 len) + { + UINT32 pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for(; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + FlushWithCheck(); + // PutOneByte(GetOneByte(0 - distance)); + } + } + + void PutOneByte(BYTE b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + FlushWithCheck(); + } + + BYTE GetOneByte(UINT32 index) const + { + UINT32 pos = _pos + index; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + + // BYTE *GetBuffer() const { return _buffer; } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/StdAfx.h b/Source/7zip/7zip/Compress/LZ/StdAfx.h new file mode 100644 index 00000000..a32fbed6 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZ/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMA.h b/Source/7zip/7zip/Compress/LZMA/LZMA.h new file mode 100644 index 00000000..f6e2d8d3 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMA.h @@ -0,0 +1,96 @@ +// LZMA.h + +// #pragma once + +#include "LZMALen.h" + +#ifndef __LZMA_H +#define __LZMA_H + +namespace NCompress { +namespace NLZMA { + +const UINT32 kNumRepDistances = 4; + +const BYTE kNumStates = 12; + +const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +class CState +{ +public: + BYTE Index; + void Init() + { Index = 0; } + void UpdateChar() + { Index = kLiteralNextStates[Index]; } + void UpdateMatch() + { Index = kMatchNextStates[Index]; } + void UpdateRep() + { Index = kRepNextStates[Index]; } + void UpdateShortRep() + { Index = kShortRepNextStates[Index]; } +}; + +class CBaseCoder +{ +protected: + CState _state; + BYTE _previousByte; + bool _peviousIsMatch; + UINT32 _repDistances[kNumRepDistances]; + void Init() + { + _state.Init(); + _previousByte = 0; + _peviousIsMatch = false; + for(int i = 0 ; i < kNumRepDistances; i++) + _repDistances[i] = 0; + } +}; + +const int kNumPosSlotBits = 6; +const int kDicLogSizeMin = 0; +const int kDicLogSizeMax = 32; +const int kDistTableSizeMax = kDicLogSizeMax * 2; + +const UINT32 kNumLenToPosStates = 4; +inline UINT32 GetLenToPosState(UINT32 len) +{ + len -= 2; + if (len < kNumLenToPosStates) + return len; + return kNumLenToPosStates - 1; +} + +const UINT32 kMatchMinLen = 2; + +const UINT32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; + +const int kNumAlignBits = 4; +const UINT32 kAlignTableSize = 1 << kNumAlignBits; +const UINT32 kAlignMask = (kAlignTableSize - 1); + +const UINT32 kStartPosModelIndex = 4; +const UINT32 kEndPosModelIndex = 14; +const UINT32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + +const UINT32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); + +const UINT32 kMainChoiceLiteralIndex = 0; +const UINT32 kMainChoiceMatchIndex = 1; + +const UINT32 kMatchChoiceDistanceIndex= 0; +const UINT32 kMatchChoiceRepetitionIndex = 1; + +const int kNumMoveBits = 5; + +const int kNumLitPosStatesBitsEncodingMax = 4; +const int kNumLitContextBitsMax = 8; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMADecoder.cpp b/Source/7zip/7zip/Compress/LZMA/LZMADecoder.cpp new file mode 100644 index 00000000..e6ad7823 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMADecoder.cpp @@ -0,0 +1,356 @@ +// LZMADecoder.cpp + +#include "StdAfx.h" + +#include "LZMADecoder.h" +#include "../../../Common/Defs.h" +#include "../../../Common/ComTry.h" + +/* +#include "fstream.h" +#include "iomanip.h" + +ofstream ofs("res.dat"); + +const kNumCounters = 3; +UINT32 g_Counter[kNumCounters]; +class C1 +{ +public: + ~C1() + { + for (int i = 0; i < kNumCounters; i++) + ofs << setw(10) << g_Counter[i] << endl; + } +} g_C1; +*/ + +/* +const UINT32 kLenTableMax = 20; +const UINT32 kNumDists = NCompress::NLZMA::kDistTableSizeMax / 2; +UINT32 g_Counts[kLenTableMax][kNumDists]; +class C1 +{ +public: + ~C1 () + { + UINT32 sums[kLenTableMax]; + for (int len = 2; len < kLenTableMax; len++) + { + sums[len] = 0; + for (int dist = 0; dist < kNumDists; dist++) + sums[len] += g_Counts[len][dist]; + if (sums[len] == 0) + sums[len] = 1; + } + for (int dist = 0; dist < kNumDists; dist++) + { + ofs << setw(4) << dist << " "; + for (int len = 2; len < kLenTableMax; len++) + { + ofs << setw(4) << g_Counts[len][dist] * 1000 / sums[len]; + } + ofs << endl; + } + } +} g_Class; + +void UpdateStat(UINT32 len, UINT32 dist) +{ + if (len >= kLenTableMax) + len = kLenTableMax - 1; + g_Counts[len][dist / 2]++; +} +*/ + +namespace NCompress { +namespace NLZMA { + +HRESULT CDecoder::SetDictionarySize(UINT32 dictionarySize) +{ + if (_dictionarySize != dictionarySize) + { + _dictionarySize = dictionarySize; + _dictionarySizeCheck = MyMax(_dictionarySize, UINT32(1)); + UINT32 blockSize = MyMax(_dictionarySizeCheck, UINT32(1 << 12)); + try + { + _outWindowStream.Create(blockSize /*, kMatchMaxLen */); + } + catch(...) + { + return E_OUTOFMEMORY; + } + } + return S_OK; +} + +HRESULT CDecoder::SetLiteralProperties( + UINT32 numLiteralPosStateBits, UINT32 numLiteralContextBits) +{ + if (numLiteralPosStateBits > 8) + return E_INVALIDARG; + if (numLiteralContextBits > 8) + return E_INVALIDARG; + _literalDecoder.Create(numLiteralPosStateBits, numLiteralContextBits); + return S_OK; +} + +HRESULT CDecoder::SetPosBitsProperties(UINT32 numPosStateBits) +{ + if (numPosStateBits > NLength::kNumPosStatesBitsMax) + return E_INVALIDARG; + UINT32 numPosStates = 1 << numPosStateBits; + _lenDecoder.Create(numPosStates); + _repMatchLenDecoder.Create(numPosStates); + _posStateMask = numPosStates - 1; + return S_OK; +} + +CDecoder::CDecoder(): + _dictionarySize((UINT32)-1) +{ + Create(); +} + +HRESULT CDecoder::Create() +{ + COM_TRY_BEGIN + for(int i = 0; i < kNumPosModels; i++) + _posDecoders[i].Create(((kStartPosModelIndex + i) >> 1) - 1); + COM_TRY_END + return S_OK; +} + + +HRESULT CDecoder::Init(ISequentialInStream *inStream, + ISequentialOutStream *outStream) +{ + _rangeDecoder.Init(inStream); + + _outWindowStream.Init(outStream); + + int i; + for(i = 0; i < kNumStates; i++) + { + for (UINT32 j = 0; j <= _posStateMask; j++) + { + _mainChoiceDecoders[i][j].Init(); + _matchRepShortChoiceDecoders[i][j].Init(); + } + _matchChoiceDecoders[i].Init(); + _matchRepChoiceDecoders[i].Init(); + _matchRep1ChoiceDecoders[i].Init(); + _matchRep2ChoiceDecoders[i].Init(); + } + + _literalDecoder.Init(); + + // _repMatchLenDecoder.Init(); + + for (i = 0; i < kNumLenToPosStates; i++) + _posSlotDecoder[i].Init(); + + for(i = 0; i < kNumPosModels; i++) + _posDecoders[i].Init(); + + _lenDecoder.Init(); + _repMatchLenDecoder.Init(); + + _posAlignDecoder.Init(); + return S_OK; + +} + + + +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress) +{ + /* + if (outSize == NULL) + return E_INVALIDARG; + */ + + Init(inStream, outStream); + CDecoderFlusher flusher(this); + + CState state; + state.Init(); + bool peviousIsMatch = false; + BYTE previousByte = 0; + UINT32 repDistances[kNumRepDistances]; + for(int i = 0 ; i < kNumRepDistances; i++) + repDistances[i] = 0; + + UINT64 nowPos64 = 0; + UINT64 size = (outSize == NULL) ? (UINT64)(INT64)(-1) : *outSize; + while(nowPos64 < size) + { + UINT64 nextPos = MyMin(nowPos64 + (1 << 18), size); + while(nowPos64 < nextPos) + { + UINT32 posState = UINT32(nowPos64) & _posStateMask; + if (_mainChoiceDecoders[state.Index][posState].Decode(&_rangeDecoder) == kMainChoiceLiteralIndex) + { + state.UpdateChar(); + if(peviousIsMatch) + { + BYTE matchByte = _outWindowStream.GetOneByte(0 - repDistances[0] - 1); + previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, + UINT32(nowPos64), previousByte, matchByte); + peviousIsMatch = false; + } + else + previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, + UINT32(nowPos64), previousByte); + _outWindowStream.PutOneByte(previousByte); + nowPos64++; + } + else + { + peviousIsMatch = true; + UINT32 distance, len; + if(_matchChoiceDecoders[state.Index].Decode(&_rangeDecoder) == + kMatchChoiceRepetitionIndex) + { + if(_matchRepChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0) + { + if(_matchRepShortChoiceDecoders[state.Index][posState].Decode(&_rangeDecoder) == 0) + { + state.UpdateShortRep(); + previousByte = _outWindowStream.GetOneByte(0 - repDistances[0] - 1); + _outWindowStream.PutOneByte(previousByte); + nowPos64++; + continue; + } + distance = repDistances[0]; + } + else + { + if(_matchRep1ChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0) + distance = repDistances[1]; + else + { + if (_matchRep2ChoiceDecoders[state.Index].Decode(&_rangeDecoder) == 0) + distance = repDistances[2]; + else + { + distance = repDistances[3]; + repDistances[3] = repDistances[2]; + } + repDistances[2] = repDistances[1]; + } + repDistances[1] = repDistances[0]; + repDistances[0] = distance; + } + len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; + state.UpdateRep(); + } + else + { + len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); + state.UpdateMatch(); + UINT32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); + if (posSlot >= kStartPosModelIndex) + { + UINT32 numDirectBits = (posSlot >> 1) - 1; + distance = ((2 | (posSlot & 1)) << numDirectBits); + + if (posSlot < kEndPosModelIndex) + distance += _posDecoders[posSlot - kStartPosModelIndex].Decode(&_rangeDecoder); + else + { + distance += (_rangeDecoder.DecodeDirectBits( + numDirectBits - kNumAlignBits) << kNumAlignBits); + distance += _posAlignDecoder.Decode(&_rangeDecoder); + } + } + else + distance = posSlot; + + repDistances[3] = repDistances[2]; + repDistances[2] = repDistances[1]; + repDistances[1] = repDistances[0]; + repDistances[0] = distance; + // UpdateStat(len, posSlot); + } + if (distance >= nowPos64 || distance >= _dictionarySizeCheck) + { + if (distance == (UINT32)(-1) && size == (UINT64)(INT64)(-1)) + { + flusher.NeedFlush = false; + return Flush(); + } + throw "data error"; + } + _outWindowStream.CopyBackBlock(distance, len); + nowPos64 += len; + previousByte = _outWindowStream.GetOneByte(0 - 1); + } + } + if (progress != NULL) + { + UINT64 inSize = _rangeDecoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLZOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + + +static HRESULT DecodeProperties(ISequentialInStream *inStream, + UINT32 &numPosStateBits, + UINT32 &numLiteralPosStateBits, + UINT32 &numLiteralContextBits, + UINT32 &dictionarySize) +{ + UINT32 processesedSize; + + BYTE firstByte; + RINOK(inStream->Read(&firstByte, sizeof(firstByte), &processesedSize)); + if (processesedSize != sizeof(firstByte)) + return E_INVALIDARG; + + numLiteralContextBits = firstByte % 9; + BYTE remainder = firstByte / 9; + numLiteralPosStateBits = remainder % 5; + numPosStateBits = remainder / 5; + + RINOK(inStream->Read(&dictionarySize, sizeof(dictionarySize), &processesedSize)); + if (processesedSize != sizeof(dictionarySize)) + return E_INVALIDARG; + return S_OK; +} + +STDMETHODIMP CDecoder::SetDecoderProperties(ISequentialInStream *inStream) +{ + UINT32 numPosStateBits; + UINT32 numLiteralPosStateBits; + UINT32 numLiteralContextBits; + UINT32 dictionarySize; + RINOK(DecodeProperties(inStream, + numPosStateBits, + numLiteralPosStateBits, + numLiteralContextBits, + dictionarySize)); + RINOK(SetDictionarySize(dictionarySize)); + RINOK(SetLiteralProperties(numLiteralPosStateBits, numLiteralContextBits)); + RINOK(SetPosBitsProperties(numPosStateBits)); + return S_OK; +} + +}} diff --git a/Source/7zip/7zip/Compress/LZMA/LZMADecoder.h b/Source/7zip/7zip/Compress/LZMA/LZMADecoder.h new file mode 100644 index 00000000..28350963 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMADecoder.h @@ -0,0 +1,107 @@ +// LZMA/Decoder.h + +// #pragma once + +#ifndef __LZMA_DECODER_H +#define __LZMA_DECODER_H + +#include "../../ICoder.h" +#include "../../../Common/MyCom.h" +#include "../LZ/LZOutWindow.h" + +#include "LZMA.h" +#include "LZMALen.h" +#include "LZMALiteral.h" + +namespace NCompress { +namespace NLZMA { + +typedef NRangeCoder::CBitDecoder CMyBitDecoder; + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties, + public CMyUnknownImp +{ + CLZOutWindow _outWindowStream; + NRangeCoder::CDecoder _rangeDecoder; + + CMyBitDecoder _mainChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; + CMyBitDecoder _matchChoiceDecoders[kNumStates]; + CMyBitDecoder _matchRepChoiceDecoders[kNumStates]; + CMyBitDecoder _matchRep1ChoiceDecoders[kNumStates]; + CMyBitDecoder _matchRep2ChoiceDecoders[kNumStates]; + CMyBitDecoder _matchRepShortChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; + + NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; + + NRangeCoder::CReverseBitTreeDecoder2 _posDecoders[kNumPosModels]; + NRangeCoder::CReverseBitTreeDecoder _posAlignDecoder; + + NLength::CDecoder _lenDecoder; + NLength::CDecoder _repMatchLenDecoder; + + NLiteral::CDecoder _literalDecoder; + + UINT32 _dictionarySize; + UINT32 _dictionarySizeCheck; + + UINT32 _posStateMask; + +public: + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties) + + CDecoder(); + HRESULT Create(); + + + HRESULT Init(ISequentialInStream *inStream, + ISequentialOutStream *outStream); + /* + void ReleaseStreams() + { + _outWindowStream.ReleaseStream(); + _rangeDecoder.ReleaseStream(); + } + */ + + class CDecoderFlusher + { + CDecoder *_decoder; + public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): + _decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _decoder->Flush(); + // _decoder->ReleaseStreams(); + } + }; + + HRESULT Flush() + { return _outWindowStream.Flush(); } + + // ICompressCoder interface + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress); + + // ICompressSetDecoderProperties + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream); + + HRESULT SetDictionarySize(UINT32 dictionarySize); + HRESULT SetLiteralProperties(UINT32 numLiteralPosStateBits, + UINT32 numLiteralContextBits); + HRESULT SetPosBitsProperties(UINT32 numPosStateBits); +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp new file mode 100644 index 00000000..7febc184 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp @@ -0,0 +1,1264 @@ +// LZMA/Encoder.cpp + +#include "StdAfx.h" + +#include "../../../Common/Defs.h" + +#include "LZMAEncoder.h" + +#ifdef COMPRESS_MF_BT +#include "../LZ/BinTree/BinTree2.h" +#include "../LZ/BinTree/BinTree3.h" +#include "../LZ/BinTree/BinTree4.h" +#include "../LZ/BinTree/BinTree4b.h" +#endif + +#ifdef COMPRESS_MF_PAT +#include "../LZ/Patricia/Pat2.h" +#include "../LZ/Patricia/Pat2H.h" +#include "../LZ/Patricia/Pat3H.h" +#include "../LZ/Patricia/Pat4H.h" +#include "../LZ/Patricia/Pat2R.h" +#endif + +#ifdef COMPRESS_MF_HC +#include "../LZ/HashChain/HC3.h" +#include "../LZ/HashChain/HC4.h" +#endif + +#ifdef COMPRESS_MF_MT +#include "../LZ/MT/MT.h" +#endif + +namespace NCompress { +namespace NLZMA { + +enum +{ + kBT2, + kBT3, + kBT4, + kBT4B, + kPat2, + kPat2H, + kPat3H, + kPat4H, + kPat2R, + kHC3, + kHC4 +}; + +static const wchar_t *kMatchFinderIDs[] = +{ + L"BT2", + L"BT3", + L"BT4", + L"BT4B", + L"PAT2", + L"PAT2H", + L"PAT3H", + L"PAT4H", + L"PAT2R", + L"HC3", + L"HC4" +}; + +BYTE g_FastPos[1024]; + +class CFastPosInit +{ +public: + CFastPosInit() + { + const BYTE kFastSlots = 20; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (BYTE slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UINT32 k = (1 << ((slotFast >> 1) - 1)); + for (UINT32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } +} g_FastPosInit; + +const int kDefaultDictionaryLogSize = 20; +const UINT32 kNumFastBytesDefault = 0x20; + +CEncoder::CEncoder(): + _dictionarySize(1 << kDefaultDictionaryLogSize), + _dictionarySizePrev(UINT32(-1)), + _numFastBytes(kNumFastBytesDefault), + _numFastBytesPrev(UINT32(-1)), + _distTableSize(kDefaultDictionaryLogSize * 2), + _posStateBits(2), + _posStateMask(4 - 1), + _numLiteralPosStateBits(0), + _numLiteralContextBits(3), + #ifdef COMPRESS_MF_MT + _multiThread(false), + #endif + _matchFinderIndex(kBT4), + _writeEndMark(false) +{ + _maxMode = false; + _fastMode = false; + _posAlignEncoder.Create(kNumAlignBits); + for(int i = 0; i < kNumPosModels; i++) + _posEncoders[i].Create(((kStartPosModelIndex + i) >> 1) - 1); +} + +HRESULT CEncoder::Create() +{ + if (!_matchFinder) + { + switch(_matchFinderIndex) + { + #ifdef COMPRESS_MF_BT + case kBT2: + _matchFinder = new NBT2::CMatchFinderBinTree; + break; + case kBT3: + _matchFinder = new NBT3::CMatchFinderBinTree; + break; + case kBT4: + _matchFinder = new NBT4::CMatchFinderBinTree; + break; + case kBT4B: + _matchFinder = new NBT4B::CMatchFinderBinTree; + break; + #endif + + #ifdef COMPRESS_MF_PAT + case kPat2: + _matchFinder = new NPat2::CPatricia; + break; + case kPat2H: + _matchFinder = new NPat2H::CPatricia; + break; + case kPat3H: + _matchFinder = new NPat3H::CPatricia; + break; + case kPat4H: + _matchFinder = new NPat4H::CPatricia; + break; + case kPat2R: + _matchFinder = new NPat2R::CPatricia; + break; + #endif + + #ifdef COMPRESS_MF_HC + case kHC3: + _matchFinder = new NHC3::CMatchFinderHC; + break; + case kHC4: + _matchFinder = new NHC4::CMatchFinderHC; + break; + #endif + } + #ifdef COMPRESS_MF_MT + if (_multiThread) + { + CMatchFinderMT *mfSpec = new CMatchFinderMT; + CMyComPtr mf = mfSpec; + RINOK(mfSpec->SetMatchFinder(_matchFinder)); + _matchFinder.Release(); + _matchFinder = mf; + } + #endif + } + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return S_OK; + RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, + kMatchMaxLen - _numFastBytes)); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + _lenEncoder.Create(1 << _posStateBits); + _repMatchLenEncoder.Create(1 << _posStateBits); + return S_OK; +} + +inline AreStringsEqual(const wchar_t *s, const wchar_t *testString) +{ + while (true) + { + wchar_t c = *testString; + if (c >= 'a' && c <= 'z') + c -= 0x20; + if (*s != c) + return false; + if (c == 0) + return true; + s++; + testString++; + } +} + +// ICompressSetEncoderProperties2 +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UINT32 numProperties) +{ + for (UINT32 i = 0; i < numProperties; i++) + { + const PROPVARIANT &prop = properties[i]; + switch(propIDs[i]) + { + case NCoderPropID::kNumFastBytes: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 numFastBytes = prop.ulVal; + if(numFastBytes < 2 || numFastBytes > kMatchMaxLen) + return E_INVALIDARG; + _numFastBytes = numFastBytes; + break; + } + case NCoderPropID::kAlgorithm: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 maximize = prop.ulVal; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + break; + } + case NCoderPropID::kMatchFinder: + { + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + int matchFinderIndexPrev = _matchFinderIndex; + _matchFinderIndex = 0; + const kNumMFs = sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0]); + for (int m = 0; m < kNumMFs; m++) + { + if (AreStringsEqual(kMatchFinderIDs[m], prop.bstrVal)) + { + _matchFinderIndex = m; + break; + } + } + if (m == kNumMFs) + return E_INVALIDARG; + if (!_matchFinder && matchFinderIndexPrev != _matchFinderIndex) + _matchFinder.Release(); + break; + } + #ifdef COMPRESS_MF_MT + case NCoderPropID::kMultiThread: + { + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + _multiThread = (prop.boolVal != VARIANT_FALSE); + break; + } + #endif + case NCoderPropID::kDictionarySize: + { + const int kDicLogSizeMaxCompress = 28; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 dictionarySize = prop.ulVal; + if (dictionarySize < UINT32(1 << kDicLogSizeMin) || + dictionarySize > UINT32(1 << kDicLogSizeMaxCompress)) + return E_INVALIDARG; + _dictionarySize = dictionarySize; + UINT32 dicLogSize; + for(dicLogSize = 0; dicLogSize < kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= (UINT32(1) << dicLogSize)) + break; + _distTableSize = dicLogSize * 2; + break; + } + case NCoderPropID::kPosStateBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 value = prop.ulVal; + if (value > NLength::kNumPosStatesBitsEncodingMax) + return E_INVALIDARG; + _posStateBits = value; + _posStateMask = (1 << _posStateBits) - 1; + break; + } + case NCoderPropID::kLitPosBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 value = prop.ulVal; + if (value > kNumLitPosStatesBitsEncodingMax) + return E_INVALIDARG; + _numLiteralPosStateBits = value; + break; + } + case NCoderPropID::kLitContextBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UINT32 value = prop.ulVal; + if (value > kNumLitContextBitsMax) + return E_INVALIDARG; + _numLiteralContextBits = value; + break; + } + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + BYTE firstByte = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; + RINOK(outStream->Write(&firstByte, sizeof(firstByte), NULL)); + return outStream->Write(&_dictionarySize, sizeof(_dictionarySize), NULL); +} + +STDMETHODIMP CEncoder::Init( + ISequentialOutStream *outStream) +{ + CBaseCoder::Init(); + + // RINOK(_matchFinder->Init(inStream)); + _rangeEncoder.Init(outStream); + + int i; + for(i = 0; i < kNumStates; i++) + { + for (UINT32 j = 0; j <= _posStateMask; j++) + { + _mainChoiceEncoders[i][j].Init(); + _matchRepShortChoiceEncoders[i][j].Init(); + } + _matchChoiceEncoders[i].Init(); + _matchRepChoiceEncoders[i].Init(); + _matchRep1ChoiceEncoders[i].Init(); + _matchRep2ChoiceEncoders[i].Init(); + } + + _literalEncoder.Init(); + + // _repMatchLenEncoder.Init(); + + for(i = 0; i < kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + + for(i = 0; i < kNumPosModels; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init(); + _repMatchLenEncoder.Init(); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + + return S_OK; +} + +void CEncoder::MovePos(UINT32 num) +{ + for (;num > 0; num--) + { + _matchFinder->DummyLongestMatch(); + HRESULT result = _matchFinder->MovePos(); + if (result != S_OK) + throw CMatchFinderException(result); + _additionalOffset++; + } +} + +UINT32 CEncoder::Backward(UINT32 &backRes, UINT32 cur) +{ + _optimumEndIndex = cur; + UINT32 posMem = _optimum[cur].PosPrev; + UINT32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UINT32 posPrev = posMem; + UINT32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while(cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; +} + +/* +inline UINT32 GetMatchLen(const BYTE *data, UINT32 back, UINT32 limit) +{ + back++; + for(UINT32 i = 0; i < limit && data[i] == data[i - back]; i++); + return i; +} +*/ + +UINT32 CEncoder::GetOptimum(UINT32 &backRes, UINT32 position) +{ + if(_optimumEndIndex != _optimumCurrentIndex) + { + UINT32 len = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return len; + } + _optimumCurrentIndex = 0; + _optimumEndIndex = 0; // test it; + + UINT32 lenMain; + if (!_longestMatchWasFound) + lenMain = ReadMatchDistances(); + else + { + lenMain = _longestMatchLength; + _longestMatchWasFound = false; + } + + + UINT32 reps[kNumRepDistances]; + UINT32 repLens[kNumRepDistances]; + UINT32 repMaxIndex = 0; + int i; + for(i = 0; i < kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen); + if (i == 0 || repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if(repLens[repMaxIndex] > _numFastBytes) + { + backRes = repMaxIndex; + MovePos(repLens[repMaxIndex] - 1); + return repLens[repMaxIndex]; + } + + if(lenMain > _numFastBytes) + { + UINT32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : + _matchDistances[_numFastBytes]; + backRes = backMain + kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + BYTE currentByte = _matchFinder->GetIndexByte(0 - 1); + + _optimum[0].State = _state; + + BYTE matchByte; + + matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); + + UINT32 posState = (position & _posStateMask); + + _optimum[1].Price = _mainChoiceEncoders[_state.Index][posState].GetPrice(kMainChoiceLiteralIndex) + + _literalEncoder.GetPrice(position, _previousByte, _peviousIsMatch, matchByte, currentByte); + _optimum[1].MakeAsChar(); + + _optimum[1].PosPrev = 0; + + for (i = 0; i < kNumRepDistances; i++) + _optimum[0].Backs[i] = reps[i]; + + UINT32 matchPrice = _mainChoiceEncoders[_state.Index][posState].GetPrice(kMainChoiceMatchIndex); + UINT32 repMatchPrice = matchPrice + + _matchChoiceEncoders[_state.Index].GetPrice(kMatchChoiceRepetitionIndex); + + if(matchByte == currentByte) + { + UINT32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if(shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + if(lenMain < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + + UINT32 normalMatchPrice = matchPrice + + _matchChoiceEncoders[_state.Index].GetPrice(kMatchChoiceDistanceIndex); + + if (lenMain <= repLens[repMaxIndex]) + lenMain = 0; + + UINT32 len; + for(len = 2; len <= lenMain; len++) + { + _optimum[len].PosPrev = 0; + _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; + _optimum[len].Price = normalMatchPrice + + GetPosLenPrice(_matchDistances[len], len, posState); + _optimum[len].Prev1IsChar = false; + } + + if (lenMain < repLens[repMaxIndex]) + lenMain = repLens[repMaxIndex]; + + for (; len <= lenMain; len++) + _optimum[len].Price = kIfinityPrice; + + for(i = 0; i < kNumRepDistances; i++) + { + UINT repLen = repLens[i]; + for(UINT32 lenTest = 2; lenTest <= repLen; lenTest++) + { + UINT32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); + COptimal &optimum = _optimum[lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + } + + UINT32 cur = 0; + UINT32 lenEnd = lenMain; + + while(true) + { + cur++; + if(cur == lenEnd) + return Backward(backRes, cur); + position++; + UINT32 posPrev = _optimum[cur].PosPrev; + CState state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + bool prevWasMatch; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + { + prevWasMatch = true; + state.UpdateShortRep(); + } + else + { + prevWasMatch = false; + state.UpdateChar(); + } + /* + if (_optimum[cur].Prev1IsChar) + for(int i = 0; i < kNumRepDistances; i++) + reps[i] = _optimum[posPrev].Backs[i]; + */ + } + else + { + prevWasMatch = true; + UINT32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + if (pos < kNumRepDistances) + { + reps[0] = _optimum[posPrev].Backs[pos]; + UINT32 i; + for(i = 1; i <= pos; i++) + reps[i] = _optimum[posPrev].Backs[i - 1]; + for(; i < kNumRepDistances; i++) + reps[i] = _optimum[posPrev].Backs[i]; + } + else + { + reps[0] = (pos - kNumRepDistances); + for(UINT32 i = 1; i < kNumRepDistances; i++) + reps[i] = _optimum[posPrev].Backs[i - 1]; + } + } + _optimum[cur].State = state; + for(UINT32 i = 0; i < kNumRepDistances; i++) + _optimum[cur].Backs[i] = reps[i]; + UINT32 newLen = ReadMatchDistances(); + if(newLen > _numFastBytes) + { + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(backRes, cur); + } + UINT32 curPrice = _optimum[cur].Price; + // BYTE currentByte = _matchFinder->GetIndexByte(0 - 1); + // BYTE matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); + const BYTE *data = _matchFinder->GetPointerToCurrentPos() - 1; + BYTE currentByte = *data; + BYTE matchByte = data[0 - reps[0] - 1]; + + UINT32 posState = (position & _posStateMask); + + UINT32 curAnd1Price = curPrice + + _mainChoiceEncoders[state.Index][posState].GetPrice(kMainChoiceLiteralIndex) + + _literalEncoder.GetPrice(position, data[-1], prevWasMatch, matchByte, currentByte); + + COptimal &nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + UINT32 matchPrice = curPrice + _mainChoiceEncoders[state.Index][posState].GetPrice(kMainChoiceMatchIndex); + UINT32 repMatchPrice = matchPrice + _matchChoiceEncoders[state.Index].GetPrice(kMatchChoiceRepetitionIndex); + + if(matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UINT32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if(shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + // nextIsChar = false; + } + } + /* + if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? + continue; + */ + + UINT32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + numAvailableBytes = MyMin(kNumOpts - 1 - cur, numAvailableBytes); + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (numAvailableBytes >= 3 && !nextIsChar) + { + UINT32 backOffset = reps[0] + 1; + UINT32 temp; + for (temp = 1; temp < numAvailableBytes; temp++) + if (data[temp] != data[temp - backOffset]) + break; + UINT32 lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateChar(); + UINT32 posStateNext = (position + 1) & _posStateMask; + UINT32 nextRepMatchPrice = curAnd1Price + + _mainChoiceEncoders[state2.Index][posStateNext].GetPrice(kMainChoiceMatchIndex) + + _matchChoiceEncoders[state2.Index].GetPrice(kMatchChoiceRepetitionIndex); + // for (; lenTest2 >= 2; lenTest2--) + { + while(lenEnd < cur + 1 + lenTest2) + _optimum[++lenEnd].Price = kIfinityPrice; + UINT32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[cur + 1 + lenTest2]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + for(UINT32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) + { + // UINT32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; + UINT32 backOffset = reps[repIndex] + 1; + UINT32 lenTest; + for (lenTest = 0; lenTest < numAvailableBytes; lenTest++) + if (data[lenTest] != data[lenTest - backOffset]) + break; + for(; lenTest >= 2; lenTest--) + { + while(lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UINT32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + + /* + if (_maxMode) + { + UINT32 temp; + for (temp = lenTest + 1; temp < numAvailableBytes; temp++) + if (data[temp] != data[temp - backOffset]) + break; + UINT32 lenTest2 = temp - (lenTest + 1); + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateRep(); + UINT32 posStateNext = (position + lenTest) & _posStateMask; + UINT32 curAndLenCharPrice = curAndLenPrice + + _mainChoiceEncoders[state2.Index][posStateNext].GetPrice(kMainChoiceLiteralIndex) + + _literalEncoder.GetPrice(position + lenTest, data[lenTest - 1], + true, data[lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UINT32 nextMatchPrice = curAndLenCharPrice + _mainChoiceEncoders[state2.Index][posStateNext].GetPrice(kMainChoiceMatchIndex); + UINT32 nextRepMatchPrice = nextMatchPrice + _matchChoiceEncoders[state2.Index].GetPrice(kMatchChoiceRepetitionIndex); + + // for(; lenTest2 >= 2; lenTest2--) + { + UINT32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UINT32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + */ + } + } + + // for(UINT32 lenTest = 2; lenTest <= newLen; lenTest++) + if (newLen > numAvailableBytes) + newLen = numAvailableBytes; + if (newLen >= 2) + { + if (newLen == 2 && _matchDistances[2] >= 0x80) + continue; + UINT32 normalMatchPrice = matchPrice + + _matchChoiceEncoders[state.Index].GetPrice(kMatchChoiceDistanceIndex); + while(lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + for(UINT32 lenTest = newLen; lenTest >= 2; lenTest--) + { + UINT32 curBack = _matchDistances[lenTest]; + UINT32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (_maxMode) + { + UINT32 backOffset = curBack + 1; + UINT32 temp; + for (temp = lenTest + 1; temp < numAvailableBytes; temp++) + if (data[temp] != data[temp - backOffset]) + break; + UINT32 lenTest2 = temp - (lenTest + 1); + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateMatch(); + UINT32 posStateNext = (position + lenTest) & _posStateMask; + UINT32 curAndLenCharPrice = curAndLenPrice + + _mainChoiceEncoders[state2.Index][posStateNext].GetPrice(kMainChoiceLiteralIndex) + + _literalEncoder.GetPrice(position + lenTest, data[lenTest - 1], + true, data[lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UINT32 nextMatchPrice = curAndLenCharPrice + _mainChoiceEncoders[state2.Index][posStateNext].GetPrice(kMainChoiceMatchIndex); + UINT32 nextRepMatchPrice = nextMatchPrice + _matchChoiceEncoders[state2.Index].GetPrice(kMatchChoiceRepetitionIndex); + + // for(; lenTest2 >= 2; lenTest2--) + { + UINT32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UINT32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + kNumRepDistances; + } + } + } + } + } + } + } +} + +static bool inline ChangePair(UINT32 smallDist, UINT32 bigDist) +{ + const int kDif = 7; + return (smallDist < (UINT32(1) << (32-kDif)) && bigDist >= (smallDist << kDif)); +} + + +UINT32 CEncoder::GetOptimumFast(UINT32 &backRes, UINT32 position) +{ + UINT32 lenMain; + if (!_longestMatchWasFound) + lenMain = ReadMatchDistances(); + else + { + lenMain = _longestMatchLength; + _longestMatchWasFound = false; + } + UINT32 repLens[kNumRepDistances]; + UINT32 repMaxIndex = 0; + for(int i = 0; i < kNumRepDistances; i++) + { + repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); + if (i == 0 || repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if(repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + MovePos(repLens[repMaxIndex] - 1); + return repLens[repMaxIndex]; + } + if(lenMain >= _numFastBytes) + { + backRes = _matchDistances[_numFastBytes] + kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + while (lenMain > 2) + { + if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) + break; + lenMain--; + } + if (lenMain == 2 && _matchDistances[2] >= 0x80) + lenMain = 1; + + UINT32 backMain = _matchDistances[lenMain]; + if (repLens[repMaxIndex] >= 2) + { + if (repLens[repMaxIndex] + 1 >= lenMain || + repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12))) + { + backRes = repMaxIndex; + MovePos(repLens[repMaxIndex] - 1); + return repLens[repMaxIndex]; + } + } + + + if (lenMain >= 2) + { + _longestMatchLength = ReadMatchDistances(); + if (_longestMatchLength >= 2 && + ( + (_longestMatchLength >= lenMain && + _matchDistances[lenMain] < backMain) || + _longestMatchLength == lenMain + 1 && + !ChangePair(backMain, _matchDistances[_longestMatchLength]) || + _longestMatchLength > lenMain + 1 || + _longestMatchLength + 1 >= lenMain && + ChangePair(_matchDistances[lenMain - 1], backMain) + ) + ) + { + _longestMatchWasFound = true; + backRes = UINT32(-1); + return 1; + } + for(int i = 0; i < kNumRepDistances; i++) + { + UINT32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); + if (repLen >= 2 && repLen + 1 >= lenMain) + { + _longestMatchWasFound = true; + backRes = UINT32(-1); + return 1; + } + } + backRes = backMain + kNumRepDistances; + MovePos(lenMain - 2); + return lenMain; + } + backRes = UINT32(-1); + return 1; +} + +STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder) +{ + _matchFinder = matchFinder; + return S_OK; +} + +HRESULT CEncoder::Flush() +{ + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); +} + +void CEncoder::WriteEndMarker(UINT32 posState) +{ + // This function for writing End Mark for stream version of LZMA. + // In current version this feature is not used. + if (!_writeEndMark) + return; + + _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceMatchIndex); + _matchChoiceEncoders[_state.Index].Encode(&_rangeEncoder, kMatchChoiceDistanceIndex); + _state.UpdateMatch(); + UINT32 len = kMatchMinLen; // kMatchMaxLen; + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + UINT32 posSlot = (1 << kNumPosSlotBits) - 1; + UINT32 lenToPosState = GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); + UINT32 footerBits = 30; + UINT32 posReduced = (UINT32(1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.Encode(&_rangeEncoder, posReduced & kAlignMask); +} + +HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress) +{ + RINOK(SetStreams(inStream, outStream, inSize, outSize)); + while(true) + { + UINT64 processedInSize; + UINT64 processedOutSize; + INT32 finished; + RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); + if (finished != 0) + return S_OK; + if (progress != 0) + { + RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); + } + } +} + +HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize) +{ + _inStream = inStream; + _finished = false; + RINOK(Create()); + RINOK(Init(outStream)); + + // CCoderReleaser releaser(this); + + /* + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(); + */ + + if (!_fastMode) + { + FillPosSlotPrices(); + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes); + _lenEncoder.UpdateTables(); + _repMatchLenEncoder.SetTableSize(_numFastBytes); + _repMatchLenEncoder.UpdateTables(); + + lastPosSlotFillingPos = 0; + nowPos64 = 0; + return S_OK; +} + +HRESULT CEncoder::CodeOneBlock(UINT64 *inSize, UINT64 *outSize, INT32 *finished) +{ + if (_inStream != 0) + { + RINOK(_matchFinder->Init(_inStream)); + _inStream = 0; + } + + *finished = 1; + if (_finished) + { + return S_OK; + } + _finished = true; + + UINT64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder->GetNumAvailableBytes() == 0) + { + _matchFinder->ReleaseStream(); + WriteEndMarker(UINT32(nowPos64) & _posStateMask); + return Flush(); + } + ReadMatchDistances(); + UINT32 posState = UINT32(nowPos64) & _posStateMask; + _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceLiteralIndex); + _state.UpdateChar(); + BYTE curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + _literalEncoder.Encode(&_rangeEncoder, UINT32(nowPos64), _previousByte, + false, 0, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder->GetNumAvailableBytes() == 0) + { + _matchFinder->ReleaseStream(); + WriteEndMarker(UINT32(nowPos64) & _posStateMask); + return Flush(); + } + while(true) + { + UINT32 pos; + UINT32 posState = UINT32(nowPos64) & _posStateMask; + + UINT32 len; + if (_fastMode) + len = GetOptimumFast(pos, UINT32(nowPos64)); + else + len = GetOptimum(pos, UINT32(nowPos64)); + + if(len == 1 && pos == (-1)) + { + _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceLiteralIndex); + _state.UpdateChar(); + BYTE matchByte; + if(_peviousIsMatch) + matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); + BYTE curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + _literalEncoder.Encode(&_rangeEncoder, UINT32(nowPos64), _previousByte, _peviousIsMatch, + matchByte, curByte); + _previousByte = curByte; + _peviousIsMatch = false; + } + else + { + _peviousIsMatch = true; + _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceMatchIndex); + if(pos < kNumRepDistances) + { + _matchChoiceEncoders[_state.Index].Encode(&_rangeEncoder, kMatchChoiceRepetitionIndex); + if(pos == 0) + { + _matchRepChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 0); + if(len == 1) + _matchRepShortChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, 0); + else + _matchRepShortChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, 1); + } + else + { + _matchRepChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 1); + if (pos == 1) + _matchRep1ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 0); + else + { + _matchRep1ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 1); + _matchRep2ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + _state.UpdateRep(); + } + + + UINT32 distance = _repDistances[pos]; + if (pos != 0) + { + for(UINT32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _matchChoiceEncoders[_state.Index].Encode(&_rangeEncoder, kMatchChoiceDistanceIndex); + _state.UpdateMatch(); + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); + pos -= kNumRepDistances; + UINT32 posSlot = GetPosSlot(pos); + UINT32 lenToPosState = GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UINT32 footerBits = ((posSlot >> 1) - 1); + UINT32 posReduced = pos - ((2 | (posSlot & 1)) << footerBits); + + if (posSlot < kEndPosModelIndex) + _posEncoders[posSlot - kStartPosModelIndex].Encode(&_rangeEncoder, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.Encode(&_rangeEncoder, posReduced & kAlignMask); + if (!_fastMode) + if (--_alignPriceCount == 0) + FillAlignPrices(); + } + } + UINT32 distance = pos; + for(UINT32 i = kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); + } + _additionalOffset -= len; + nowPos64 += len; + if (!_fastMode) + if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) + { + FillPosSlotPrices(); + FillDistancesPrices(); + lastPosSlotFillingPos = nowPos64; + } + if (_additionalOffset == 0) + { + *inSize = nowPos64; + *outSize = _rangeEncoder.GetProcessedSize(); + if (_matchFinder->GetNumAvailableBytes() == 0) + { + _matchFinder->ReleaseStream(); + WriteEndMarker(UINT32(nowPos64) & _posStateMask); + return Flush(); + } + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + *finished = 0; + return S_OK; + } + } + } +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(CMatchFinderException &e) { return e.ErrorCode; } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } +} + +void CEncoder::FillPosSlotPrices() +{ + for (int lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UINT32 posSlot; + for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++) + _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); + for (; posSlot < _distTableSize; posSlot++) + _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + + ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); + } +} + +void CEncoder::FillDistancesPrices() +{ + for (int lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UINT32 i; + for (i = 0; i < kStartPosModelIndex; i++) + _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; + for (; i < kNumFullDistances; i++) + { + UINT32 posSlot = GetPosSlot(i); + _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + + _posEncoders[posSlot - kStartPosModelIndex].GetPrice(i - + ((2 | (posSlot & 1)) << (((posSlot >> 1) - 1)))); + } + } +} + +void CEncoder::FillAlignPrices() +{ + for (int i = 0; i < kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.GetPrice(i); + _alignPriceCount = kAlignTableSize; +} + +}} diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h new file mode 100644 index 00000000..7e29ee51 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h @@ -0,0 +1,294 @@ +// LZMA/Encoder.h + +// #pragma once + +#ifndef __LZMA_ENCODER_H +#define __LZMA_ENCODER_H + +#include "../../ICoder.h" +#include "../../../Common/MyCom.h" +#include "../LZ/IMatchFinder.h" + +#include "LZMA.h" +#include "LZMALen.h" +#include "LZMALiteral.h" + +namespace NCompress { +namespace NLZMA { + +class CMatchFinderException +{ +public: + HRESULT ErrorCode; + CMatchFinderException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +struct COptimal +{ + CState State; + + bool Prev1IsChar; + bool Prev2; + + UINT32 PosPrev2; + UINT32 BackPrev2; + + UINT32 Price; + UINT32 PosPrev; // posNext; + UINT32 BackPrev; + UINT32 Backs[kNumRepDistances]; + void MakeAsChar() { BackPrev = UINT32(-1); Prev1IsChar = false; } + void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + bool IsShortRep() { return (BackPrev == 0); } +}; + + +extern BYTE g_FastPos[1024]; +inline UINT32 GetPosSlot(UINT32 pos) +{ + if (pos < (1 << 10)) + return g_FastPos[pos]; + if (pos < (1 << 19)) + return g_FastPos[pos >> 9] + 18; + return g_FastPos[pos >> 18] + 36; +} + +inline UINT32 GetPosSlot2(UINT32 pos) +{ + if (pos < (1 << 16)) + return g_FastPos[pos >> 6] + 12; + if (pos < (1 << 25)) + return g_FastPos[pos >> 15] + 30; + return g_FastPos[pos >> 24] + 48; +} + +const UINT32 kIfinityPrice = 0xFFFFFFF; + +typedef NRangeCoder::CBitEncoder CMyBitEncoder; + +const UINT32 kNumOpts = 1 << 12; + +class CEncoder : + public ICompressCoder, + // public IInitMatchFinder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CBaseCoder, + public CMyUnknownImp +{ + COptimal _optimum[kNumOpts]; +public: + CMyComPtr _matchFinder; // test it + NRangeCoder::CEncoder _rangeEncoder; +private: + + CMyBitEncoder _mainChoiceEncoders[kNumStates][NLength::kNumPosStatesEncodingMax]; + CMyBitEncoder _matchChoiceEncoders[kNumStates]; + CMyBitEncoder _matchRepChoiceEncoders[kNumStates]; + CMyBitEncoder _matchRep1ChoiceEncoders[kNumStates]; + CMyBitEncoder _matchRep2ChoiceEncoders[kNumStates]; + CMyBitEncoder _matchRepShortChoiceEncoders[kNumStates][NLength::kNumPosStatesEncodingMax]; + + NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; + + NRangeCoder::CReverseBitTreeEncoder2 _posEncoders[kNumPosModels]; + NRangeCoder::CReverseBitTreeEncoder2 _posAlignEncoder; + + NLength::CPriceTableEncoder _lenEncoder; + NLength::CPriceTableEncoder _repMatchLenEncoder; + + NLiteral::CEncoder _literalEncoder; + + UINT32 _matchDistances[kMatchMaxLen + 1]; + + bool _fastMode; + bool _maxMode; + UINT32 _numFastBytes; + UINT32 _longestMatchLength; + + UINT32 _additionalOffset; + + UINT32 _optimumEndIndex; + UINT32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UINT32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + + UINT32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + UINT32 _alignPrices[kAlignTableSize]; + UINT32 _alignPriceCount; + + UINT32 _distTableSize; + + UINT32 _posStateBits; + UINT32 _posStateMask; + UINT32 _numLiteralPosStateBits; + UINT32 _numLiteralContextBits; + + UINT32 _dictionarySize; + + UINT32 _dictionarySizePrev; + UINT32 _numFastBytesPrev; + + UINT64 lastPosSlotFillingPos; + UINT64 nowPos64; + bool _finished; + ISequentialInStream *_inStream; + + int _matchFinderIndex; + #ifdef COMPRESS_MF_MT + bool _multiThread; + #endif + + bool _writeEndMark; + + UINT32 ReadMatchDistances() + { + UINT32 len = _matchFinder->GetLongestMatch(_matchDistances); + if (len == _numFastBytes) + len += _matchFinder->GetMatchLen(len, _matchDistances[len], + kMatchMaxLen - len); + _additionalOffset++; + HRESULT result = _matchFinder->MovePos(); + if (result != S_OK) + throw CMatchFinderException(result); + return len; + } + + void MovePos(UINT32 num); + UINT32 GetRepLen1Price(CState state, UINT32 posState) const + { + return _matchRepChoiceEncoders[state.Index].GetPrice(0) + + _matchRepShortChoiceEncoders[state.Index][posState].GetPrice(0); + } + UINT32 GetRepPrice(UINT32 repIndex, UINT32 len, CState state, UINT32 posState) const + { + UINT32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState); + if(repIndex == 0) + { + price += _matchRepChoiceEncoders[state.Index].GetPrice(0); + price += _matchRepShortChoiceEncoders[state.Index][posState].GetPrice(1); + } + else + { + price += _matchRepChoiceEncoders[state.Index].GetPrice(1); + if (repIndex == 1) + price += _matchRep1ChoiceEncoders[state.Index].GetPrice(0); + else + { + price += _matchRep1ChoiceEncoders[state.Index].GetPrice(1); + price += _matchRep2ChoiceEncoders[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + /* + UINT32 GetPosLen2Price(UINT32 pos, UINT32 posState) const + { + if (pos >= kNumFullDistances) + return kIfinityPrice; + return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); + } + UINT32 GetPosLen3Price(UINT32 pos, UINT32 len, UINT32 posState) const + { + UINT32 price; + UINT32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + */ + UINT32 GetPosLenPrice(UINT32 pos, UINT32 len, UINT32 posState) const + { + if (len == 2 && pos >= 0x80) + return kIfinityPrice; + UINT32 price; + UINT32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + + UINT32 Backward(UINT32 &backRes, UINT32 cur); + UINT32 GetOptimum(UINT32 &backRes, UINT32 position); + UINT32 GetOptimumFast(UINT32 &backRes, UINT32 position); + + void FillPosSlotPrices(); + void FillDistancesPrices(); + void FillAlignPrices(); + + void ReleaseStreams() + { + _matchFinder->ReleaseStream(); + // _rangeEncoder.ReleaseStream(); + } + + HRESULT Flush(); + class CCoderReleaser + { + CEncoder *_coder; + public: + CCoderReleaser(CEncoder *coder): _coder(coder) {} + ~CCoderReleaser() + { + _coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + void WriteEndMarker(UINT32 posState); + +public: + CEncoder(); + void SetWriteEndMarkerMode(bool writeEndMarker) + { _writeEndMark= writeEndMarker; } + + HRESULT Create(); + + MY_UNKNOWN_IMP2( + ICompressSetCoderProperties, + ICompressWriteCoderProperties + ) + + STDMETHOD(Init)( + ISequentialOutStream *outStream); + + // ICompressCoder interface + HRESULT SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize); + HRESULT CodeOneBlock(UINT64 *inSize, UINT64 *outSize, INT32 *finished); + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress); + + // ICompressCoder interface + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, const UINT64 *outSize, + ICompressProgressInfo *progress); + + // IInitMatchFinder interface + STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder); + + // ICompressSetCoderProperties2 + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UINT32 numProperties); + + // ICompressWriteCoderProperties + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMALen.cpp b/Source/7zip/7zip/Compress/LZMA/LZMALen.cpp new file mode 100644 index 00000000..0a422605 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMALen.cpp @@ -0,0 +1,74 @@ +// LZMALen.cpp + +#include "StdAfx.h" + +#include "LZMALen.h" + +namespace NCompress { +namespace NLZMA { +namespace NLength { + +void CEncoder::Init() +{ + _choice.Init(); + for (UINT32 posState = 0; posState < _numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _choice2.Init(); + _highCoder.Init(); +} + +void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UINT32 symbol, UINT32 posState) +{ + if(symbol < kNumLowSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= kNumLowSymbols; + _choice.Encode(rangeEncoder, 1); + if(symbol < kNumMidSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - kNumMidSymbols); + } + } +} + +UINT32 CEncoder::GetPrice(UINT32 symbol, UINT32 posState) const +{ + UINT32 price = 0; + if(symbol < kNumLowSymbols) + { + price += _choice.GetPrice(0); + price += _lowCoder[posState].GetPrice(symbol); + } + else + { + symbol -= kNumLowSymbols; + price += _choice.GetPrice(1); + if(symbol < kNumMidSymbols) + { + price += _choice2.GetPrice(0); + price += _midCoder[posState].GetPrice(symbol); + } + else + { + price += _choice2.GetPrice(1); + price += _highCoder.GetPrice(symbol - kNumMidSymbols); + } + } + return price; +} + +}}} + diff --git a/Source/7zip/7zip/Compress/LZMA/LZMALen.h b/Source/7zip/7zip/Compress/LZMA/LZMALen.h new file mode 100644 index 00000000..c8b61f3d --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMALen.h @@ -0,0 +1,114 @@ +// LenCoder.h + +// #pragma once + +#ifndef __LENCODER_H +#define __LENCODER_H + +#include "../RangeCoder/RangeCoderBitTree.h" + +namespace NCompress { +namespace NLZMA { +namespace NLength { + +const int kNumMoveBits = 5; + +const int kNumPosStatesBitsMax = 4; +const UINT32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + +const int kNumPosStatesBitsEncodingMax = 4; +const UINT32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + +const int kNumLenBits = 3; +const UINT32 kNumLowSymbols = 1 << kNumLenBits; +const int kNumMidBits = 3; +const UINT32 kNumMidSymbols = 1 << kNumMidBits; + +const int kNumHighBits = 8; + +const UINT32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); + +class CEncoder +{ + NRangeCoder::CBitEncoder _choice; + NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitEncoder _choice2; + NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder _highCoder; +protected: + UINT32 _numPosStates; +public: + void Create(UINT32 numPosStates) + { _numPosStates = numPosStates; } + void Init(); + void Encode(NRangeCoder::CEncoder *rangeEncoder, UINT32 symbol, UINT32 posState); + UINT32 GetPrice(UINT32 symbol, UINT32 posState) const; +}; + +const UINT32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; + +class CPriceTableEncoder: public CEncoder +{ + UINT32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; + UINT32 _tableSize; + UINT32 _counters[kNumPosStatesEncodingMax]; +public: + void SetTableSize(UINT32 tableSize) + { _tableSize = tableSize; } + UINT32 GetPrice(UINT32 symbol, UINT32 posState) const + { return _prices[symbol][posState]; } + void UpdateTable(UINT32 posState) + { + for (UINT32 len = 0; len < _tableSize; len++) + _prices[len][posState] = CEncoder::GetPrice(len , posState); + _counters[posState] = _tableSize; + } + void UpdateTables() + { + for (UINT32 posState = 0; posState < _numPosStates; posState++) + UpdateTable(posState); + } + void Encode(NRangeCoder::CEncoder *rangeEncoder, UINT32 symbol, UINT32 posState) + { + CEncoder::Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } +}; + + +class CDecoder +{ + NRangeCoder::CBitDecoder _choice; + NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; + NRangeCoder::CBitDecoder _choice2; + NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; + NRangeCoder::CBitTreeDecoder _highCoder; + UINT32 _numPosStates; +public: + void Create(UINT32 numPosStates) + { _numPosStates = numPosStates; } + void Init() + { + _choice.Init(); + for (UINT32 posState = 0; posState < _numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _choice2.Init(); + _highCoder.Init(); + } + UINT32 Decode(NRangeCoder::CDecoder *rangeDecoder, UINT32 posState) + { + if(_choice.Decode(rangeDecoder) == 0) + return _lowCoder[posState].Decode(rangeDecoder); + if(_choice2.Decode(rangeDecoder) == 0) + return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); + return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); + } +}; + +}}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMALiteral.cpp b/Source/7zip/7zip/Compress/LZMA/LZMALiteral.cpp new file mode 100644 index 00000000..e35bdba2 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMALiteral.cpp @@ -0,0 +1,69 @@ +// LZMALiteral.cpp + +#include "StdAfx.h" + +#include "LZMALiteral.h" + +namespace NCompress { +namespace NLZMA { +namespace NLiteral { + +void CEncoder2::Init() +{ + for (int i = 0; i < 3; i++) + for (int j = 1; j < (1 << 8); j++) + _encoders[i][j].Init(); +} + +void CEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, + bool matchMode, BYTE matchByte, BYTE symbol) +{ + UINT32 context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + UINT32 bit = (symbol >> i) & 1; + UINT state; + if (matchMode && same) + { + UINT32 matchBit = (matchByte >> i) & 1; + state = 1 + matchBit; + same = (matchBit == bit); + } + else + state = 0; + _encoders[state][context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } +} + +UINT32 CEncoder2::GetPrice(bool matchMode, BYTE matchByte, BYTE symbol) const +{ + UINT32 price = 0; + UINT32 context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + UINT32 matchBit = (matchByte >> i) & 1; + UINT32 bit = (symbol >> i) & 1; + price += _encoders[1 + matchBit][context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + UINT32 bit = (symbol >> i) & 1; + price += _encoders[0][context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; +}; + +}}} diff --git a/Source/7zip/7zip/Compress/LZMA/LZMALiteral.h b/Source/7zip/7zip/Compress/LZMA/LZMALiteral.h new file mode 100644 index 00000000..09cf0c36 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/LZMALiteral.h @@ -0,0 +1,166 @@ +// LiteralCoder.h + +// #pragma once + +#ifndef __LITERALCODER_H +#define __LITERALCODER_H + +#include "../RangeCoder/RangeCoderBit.h" +#include "../RangeCoder/RangeCoderOpt.h" + +namespace NCompress { +namespace NLZMA { +namespace NLiteral { + +const int kNumMoveBits = 5; + +class CEncoder2 +{ + NRangeCoder::CBitEncoder _encoders[3][1 << 8]; +public: + void Init(); + void Encode(NRangeCoder::CEncoder *rangeEncoder, bool matchMode, BYTE matchByte, BYTE symbol); + UINT32 GetPrice(bool matchMode, BYTE matchByte, BYTE symbol) const; +}; + +class CDecoder2 +{ + NRangeCoder::CBitDecoder _decoders[3][1 << 8]; +public: + void Init() + { + for (int i = 0; i < 3; i++) + for (int j = 1; j < (1 << 8); j++) + _decoders[i][j].Init(); + } + + BYTE DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) + { + UINT32 symbol = 1; + RC_INIT_VAR + do + { + // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); + RC_GETBIT(kNumMoveBits, _decoders[0][symbol].Probability, symbol) + } + while (symbol < 0x100); + RC_FLUSH_VAR + return symbol; + } + + BYTE DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, BYTE matchByte) + { + UINT32 symbol = 1; + RC_INIT_VAR + do + { + UINT32 matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + // UINT32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); + // symbol = (symbol << 1) | bit; + UINT32 bit; + RC_GETBIT2(kNumMoveBits, _decoders[1 + matchBit][symbol].Probability, symbol, + bit = 0, bit = 1) + if (matchBit != bit) + { + while (symbol < 0x100) + { + // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); + RC_GETBIT(kNumMoveBits, _decoders[0][symbol].Probability, symbol) + } + break; + } + } + while (symbol < 0x100); + RC_FLUSH_VAR + return symbol; + } +}; + +/* +const UINT32 kNumPrevByteBits = 1; +const UINT32 kNumPrevByteStates = (1 << kNumPrevByteBits); + +inline UINT32 GetLiteralState(BYTE prevByte) + { return (prevByte >> (8 - kNumPrevByteBits)); } +*/ + +class CEncoder +{ + CEncoder2 *_coders; + UINT32 _numPrevBits; + UINT32 _numPosBits; + UINT32 _posMask; +public: + CEncoder(): _coders(0) {} + ~CEncoder() { Free(); } + void Free() + { + delete []_coders; + _coders = 0; + } + void Create(UINT32 numPosBits, UINT32 numPrevBits) + { + Free(); + _numPosBits = numPosBits; + _posMask = (1 << numPosBits) - 1; + _numPrevBits = numPrevBits; + UINT32 numStates = 1 << (_numPrevBits + _numPosBits); + _coders = new CEncoder2[numStates]; + } + void Init() + { + UINT32 numStates = 1 << (_numPrevBits + _numPosBits); + for (UINT32 i = 0; i < numStates; i++) + _coders[i].Init(); + } + UINT32 GetState(UINT32 pos, BYTE prevByte) const + { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } + void Encode(NRangeCoder::CEncoder *rangeEncoder, UINT32 pos, BYTE prevByte, + bool matchMode, BYTE matchByte, BYTE symbol) + { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, matchMode, + matchByte, symbol); } + UINT32 GetPrice(UINT32 pos, BYTE prevByte, bool matchMode, BYTE matchByte, BYTE symbol) const + { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); } +}; + +class CDecoder +{ + CDecoder2 *_coders; + UINT32 _numPrevBits; + UINT32 _numPosBits; + UINT32 _posMask; +public: + CDecoder(): _coders(0) {} + ~CDecoder() { Free(); } + void Free() + { + delete []_coders; + _coders = 0; + } + void Create(UINT32 numPosBits, UINT32 numPrevBits) + { + Free(); + _numPosBits = numPosBits; + _posMask = (1 << numPosBits) - 1; + _numPrevBits = numPrevBits; + UINT32 numStates = 1 << (_numPrevBits + _numPosBits); + _coders = new CDecoder2[numStates]; + } + void Init() + { + UINT32 numStates = 1 << (_numPrevBits + _numPosBits); + for (UINT32 i = 0; i < numStates; i++) + _coders[i].Init(); + } + UINT32 GetState(UINT32 pos, BYTE prevByte) const + { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } + BYTE DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UINT32 pos, BYTE prevByte) + { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + BYTE DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UINT32 pos, BYTE prevByte, BYTE matchByte) + { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } +}; + +}}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/StdAfx.h b/Source/7zip/7zip/Compress/LZMA/StdAfx.h new file mode 100644 index 00000000..a32fbed6 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/InBuffer.h b/Source/7zip/7zip/Compress/LZMA_SMALL/InBuffer.h new file mode 100644 index 00000000..2b311a93 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/InBuffer.h @@ -0,0 +1,29 @@ +// Stream/InByte.h + +#include "LZMAState.h" + +#ifndef __STREAM_INBYTE_H +#define __STREAM_INBYTE_H + +class CInBuffer +{ + CLZMAStateP m_lzmaState; +public: + void Init(CLZMAStateP lzmaState) + { + m_lzmaState = lzmaState; + } + BYTE ReadByte() + { + if (!m_lzmaState->avail_in) + { + LZMAGetIO(m_lzmaState); + } + if (!m_lzmaState->avail_in) + return 0; + m_lzmaState->avail_in--; + return *m_lzmaState->next_in++; + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMA.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMA.h new file mode 100644 index 00000000..28258e3b --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMA.h @@ -0,0 +1,62 @@ +// LZMA.h + +#include "LZMALenCoder.h" + +#ifndef __LZMA_H +#define __LZMA_H + +const int kNumRepDistances = 4; + +const int kNumStates = 12; + +const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +class CState +{ +public: + int Index; + void Init() { Index = 0; } + void UpdateChar() { Index = kLiteralNextStates[Index]; } + void UpdateMatch() { Index = kMatchNextStates[Index]; } + void UpdateRep() { Index = kRepNextStates[Index]; } + void UpdateShortRep() { Index = kShortRepNextStates[Index]; } +}; + +const int kNumPosSlotBits = 6; + +const int kNumLenToPosStates = 4; + +/* +inline int GetLenToPosState(int len) +{ + if (len < kNumLenToPosStates + 2) + return len - 2; + return kNumLenToPosStates - 1; +} +*/ + +inline int GetLenToPosState2(int len) +{ + if (len < kNumLenToPosStates) + return len; + return kNumLenToPosStates - 1; +} + +const int kMatchMinLen = 2; +const int kMatchMaxLen = kMatchMinLen + kLenNumSymbolsTotal - 1; + +const int kNumAlignBits = 4; +const int kAlignTableSize = 1 << kNumAlignBits; + +const int kStartPosModelIndex = 4; +const int kEndPosModelIndex = 14; +const int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; +const int kNumFullDistances = 1 << (kEndPosModelIndex / 2); + +const int kNumLitPosStatesBitsEncodingMax = 4; +const int kNumLitContextBitsMax = 8; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAConf.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAConf.h new file mode 100644 index 00000000..f46811df --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAConf.h @@ -0,0 +1,25 @@ +#ifndef __LZMACONF_H +#define __LZMACONF_H + +// define __LOC_OPT for some speed optimization: +// It converts some class-member variables to local variables +// before some loops and it use inline code substitution + +#define __LOC_OPT +// #define __UNROLL + +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "../../../../exehead/util.h" +#ifdef __cplusplus +} +#endif + +#define LZMAAlloc my_GlobalAlloc +#define LZMAFree GlobalFree +#define LZMAMemCopy mini_memcpy + +#endif \ No newline at end of file diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.cpp b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.cpp new file mode 100644 index 00000000..70209a5b --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.cpp @@ -0,0 +1,183 @@ +// LZMADecoder.cpp + +#include "LZMADecoder.h" + +UINT32 CLZMADecoder::Create(BYTE *memoryPointer, + int numLiteralContextBits, + int numLiteralPosStateBits, + int numPosStateBits) +{ + + int numPosStates = 1 << numPosStateBits; + m_PosStateMask = numPosStates - 1; + return m_LiteralDecoder.Create(memoryPointer, numLiteralPosStateBits, numLiteralContextBits); +} + +UINT32 CLZMADecoder::Code(CLZMAStateP lzmaState) +{ + m_RangeDecoder.Init(lzmaState); + m_OutWindowStream.Init(lzmaState); + + int i; + for(i = 0; i < kNumStates; i++) + { + for (int j = 0; j <= m_PosStateMask; j++) + { + m_MainChoiceDecoders[i][j].Init(); + m_MatchRepShortChoiceDecoders[i][j].Init(); + } + m_MatchChoiceDecoders[i].Init(); + m_MatchRepChoiceDecoders[i].Init(); + m_MatchRep1ChoiceDecoders[i].Init(); + m_MatchRep2ChoiceDecoders[i].Init(); + } + + m_LiteralDecoder.Init(); + + for (i = 0; i < kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + m_PosDecoder.Init(); + m_PosAlignDecoder.Init(); + + // m_LenDecoder.Init(m_PosStateMask + 1); + // m_RepMatchLenDecoder.Init(m_PosStateMask + 1); + m_LenDecoder.Init(); + m_RepMatchLenDecoder.Init(); + + + //////////////////////// + // code + + CState state; + state.Init(); + bool peviousIsMatch = false; + BYTE previousByte = 0; + // kNumRepDistances == 4 + UINT32 repDistances[kNumRepDistances] = {1, 1, 1, 1}; + + /*for(i = 0 ; i < kNumRepDistances; i++) + repDistances[i] = 1;*/ + + UINT32 nowPos = 0; + while(nowPos < 0xFFFFFFFF) + { + int posState = nowPos & m_PosStateMask; + if (m_MainChoiceDecoders[state.Index][posState].Decode(&m_RangeDecoder) == 0) + { + state.UpdateChar(); + if(peviousIsMatch) + { + #ifdef __STREAM_VERSION + BYTE matchByte = m_OutWindowStream.GetOneByte(0 - repDistances[0]); + #else + BYTE matchByte = *(outStream - repDistances[0]); + #endif + previousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, + nowPos, previousByte, matchByte); + peviousIsMatch = false; + } + else + previousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, + nowPos, previousByte); + + #ifdef __STREAM_VERSION + m_OutWindowStream.PutOneByte(previousByte); + #else + *outStream++ = previousByte; + #endif + + nowPos++; + } + else + { + peviousIsMatch = true; + UINT32 distance; + int len; + if(m_MatchChoiceDecoders[state.Index].Decode(&m_RangeDecoder) == 1) + { + if(m_MatchRepChoiceDecoders[state.Index].Decode(&m_RangeDecoder) == 0) + { + if(m_MatchRepShortChoiceDecoders[state.Index][posState].Decode(&m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + + #ifdef __STREAM_VERSION + previousByte = m_OutWindowStream.GetOneByte(0 - repDistances[0]); + m_OutWindowStream.PutOneByte(previousByte); + #else + previousByte = *(outStream - repDistances[0]); + *outStream++ = previousByte; + #endif + + nowPos++; + continue; + } + distance = repDistances[0]; + } + else + { + if(m_MatchRep1ChoiceDecoders[state.Index].Decode(&m_RangeDecoder) == 0) + distance = repDistances[1]; + else + { + if (m_MatchRep2ChoiceDecoders[state.Index].Decode(&m_RangeDecoder) == 0) + distance = repDistances[2]; + else + { + distance = repDistances[3]; + repDistances[3] = repDistances[2]; + } + repDistances[2] = repDistances[1]; + } + repDistances[1] = repDistances[0]; + repDistances[0] = distance; + } + len = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, posState); + state.UpdateRep(); + } + else + { + len = m_LenDecoder.Decode(&m_RangeDecoder, posState); + state.UpdateMatch(); + int posSlot = m_PosSlotDecoder[GetLenToPosState2(len)].Decode(&m_RangeDecoder); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + distance = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + distance += m_PosDecoder.Decode(&m_RangeDecoder, posSlot); + else + { + distance += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - kNumAlignBits) << kNumAlignBits); + distance += m_PosAlignDecoder.Decode(&m_RangeDecoder); + } + } + else + distance = posSlot; + distance++; + repDistances[3] = repDistances[2]; + repDistances[2] = repDistances[1]; + repDistances[1] = repDistances[0]; + repDistances[0] = distance; + } + if (distance > nowPos || distance == 0) + { + // it's for stream version (without knowing uncompressed size) + // if (distance >= _dictionarySizeCheck) + if (distance == (UINT32)(0)) + break; + return (-1); + } + + len += kMatchMinLen; + m_OutWindowStream.CopyBackBlock(m_OutWindowStream._pos - distance, len); + previousByte = m_OutWindowStream.GetOneByte((UINT32)(-1)); + + nowPos += len; + } + } + m_OutWindowStream._windowSize = 0; + m_OutWindowStream.Flush(); + return 0; +} diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.h new file mode 100644 index 00000000..991f20d4 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMADecoder.h @@ -0,0 +1,82 @@ +// LZMADecoder.h + +#ifndef __LZMADECODER_H +#define __LZMADECODER_H + +#include "LZMAConf.h" +#include "LZMAState.h" +#include "LZMA.h" +#include "LZMALiteralCoder.h" +#include "LZOutWindow.h" + +class CPosSpecDecoder +{ + CBitDecoder m_Models[kNumFullDistances - kEndPosModelIndex]; +public: + void Init() + { + for(int i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + m_Models[i].Init(); + } + int Decode(CRangeDecoder *rangeDecoder, int slot) + { + int numLeveles = (slot >> 1) - 1; + + CBitDecoder *models = + m_Models + (((2 | (slot & 1)) << numLeveles)) - slot - 1; + + int modelIndex = 1; + int symbol = 0; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + for(int bitIndex = 0; bitIndex < numLeveles; bitIndex++) + { + #ifdef __LOC_OPT + RC_GETBIT2(models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << bitIndex)) + #else + int bit = models[modelIndex].Decode(rangeDecoder); + modelIndex <<= 1; + modelIndex += bit; + symbol |= (bit << bitIndex); + #endif + } + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; + }; +}; + +class CLZMADecoder +{ + CLZOutWindow m_OutWindowStream; + CRangeDecoder m_RangeDecoder; + + CBitDecoder m_MainChoiceDecoders[kNumStates][kLenNumPosStatesMax]; + CBitDecoder m_MatchRepShortChoiceDecoders[kNumStates][kLenNumPosStatesMax]; + CBitDecoder m_MatchChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRepChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRep1ChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRep2ChoiceDecoders[kNumStates]; + + CLZMALiteralDecoder m_LiteralDecoder; + + CBitTreeDecoder6 m_PosSlotDecoder[kNumLenToPosStates]; + CPosSpecDecoder m_PosDecoder; + CReverseBitTreeDecoder4 m_PosAlignDecoder; + + CLZMALenDecoder m_LenDecoder; + CLZMALenDecoder m_RepMatchLenDecoder; + + int m_PosStateMask; + +public: + UINT32 Create(BYTE *memoryPointer, + int numLiteralContextBits, + int numLiteralPosStateBits, + int numPosStateBits); + UINT32 Code(CLZMAStateP lzmaState); +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALenCoder.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALenCoder.h new file mode 100644 index 00000000..2fc93a8a --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALenCoder.h @@ -0,0 +1,53 @@ +// LZMALenCoder.h + +#ifndef __LZMALENCODER_H +#define __LZMALENCODER_H + +#include "RangeCoderBitTree.h" + +const int kLenNumPosStatesBitsMax = 4; +const int kLenNumPosStatesMax = (1 << kLenNumPosStatesBitsMax); + +const int kLenNumPosStatesBitsEncodingMax = 4; +const int kLenNumPosStatesEncodingMax = (1 << kLenNumPosStatesBitsEncodingMax); + +const int kLenNumLowBits = 3; +const int kLenNumLowSymbols = 1 << kLenNumLowBits; +const int kLenNumMidBits = 3; +const int kLenNumMidSymbols = 1 << kLenNumMidBits; + +const int kLenNumHighBits = 8; +const int kLenNumSymbolsTotal = kLenNumLowSymbols + kLenNumMidSymbols + (1 << kLenNumHighBits); + +class CLZMALenDecoder +{ + CBitDecoder m_Choice; + CBitDecoder m_Choice2; + CBitTreeDecoder3 m_LowCoder[kLenNumPosStatesMax]; + CBitTreeDecoder3 m_MidCoder[kLenNumPosStatesMax]; + CBitTreeDecoder8 m_HighCoder; +public: + // void Init(int numPosStates) + void Init() + { + m_Choice.Init(); + m_Choice2.Init(); + // for (int posState = 0; posState < numPosStates; posState++) + for (int posState = 0; posState < kLenNumPosStatesMax; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_HighCoder.Init(); + } + int Decode(CRangeDecoder *rangeDecoder, int posState) + { + if(m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + if(m_Choice2.Decode(rangeDecoder) == 0) + return kLenNumLowSymbols + m_MidCoder[posState].Decode(rangeDecoder); + return kLenNumLowSymbols + kLenNumMidSymbols + m_HighCoder.Decode(rangeDecoder); + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALiteralCoder.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALiteralCoder.h new file mode 100644 index 00000000..9bf9129c --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMALiteralCoder.h @@ -0,0 +1,107 @@ +// LZMALiteralCoder.h + +#ifndef __LZMALITERALCODER_H +#define __LZMALITERALCODER_H + +#include "RangeCoderBit.h" +#include "RangeCoderOpt.h" + +class CLZMALiteralDecoder2 +{ + CBitDecoder m_Decoders[3][1 << 8]; +public: + void Init() + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < (1 << 8); j++) + m_Decoders[i][j].Init(); + } + BYTE DecodeNormal(CRangeDecoder *rangeDecoder) + { + int symbol = 1; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + do + { + #ifdef __LOC_OPT + RC_GETBIT(m_Decoders[0][symbol].Probability, symbol) + #else + symbol = (symbol + symbol) | m_Decoders[0][symbol].Decode(rangeDecoder); + #endif + } + while (symbol < 0x100); + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; + } + BYTE DecodeWithMatchByte(CRangeDecoder *rangeDecoder, BYTE matchByte) + { + int symbol = 1; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + do + { + int matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + #ifdef __LOC_OPT + int bit; + RC_GETBIT2(m_Decoders[1 + matchBit][symbol].Probability, symbol, + bit = 0, bit = 1) + #else + int bit = m_Decoders[1 + matchBit][symbol].Decode(rangeDecoder); + symbol = (symbol + symbol) | bit; + #endif + if (matchBit != bit) + { + while (symbol < 0x100) + { + #ifdef __LOC_OPT + RC_GETBIT(m_Decoders[0][symbol].Probability, symbol) + #else + symbol = (symbol + symbol) | m_Decoders[0][symbol].Decode(rangeDecoder); + #endif + } + break; + } + } + while (symbol < 0x100); + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; + } +}; + +class CLZMALiteralDecoder +{ + CLZMALiteralDecoder2 *m_Coders; + int m_NumPrevBits; + int m_PosMask; +public: + CLZMALiteralDecoder(): m_Coders(0) {} + UINT32 Create(BYTE *memory, int numPosBits, int numPrevBits) + { + m_PosMask = (1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + int numStates = 1 << (numPrevBits + numPosBits); + m_Coders = (CLZMALiteralDecoder2 *)memory; + return sizeof(CLZMALiteralDecoder2) * numStates; + } + void Init() + { + int numStates = (m_PosMask + 1) << m_NumPrevBits; + for (int i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + int GetState(int pos, BYTE prevByte) const + { return ((pos & m_PosMask) << m_NumPrevBits) + (prevByte >> (8 - m_NumPrevBits)); } + BYTE DecodeNormal(CRangeDecoder *rangeDecoder, int pos, BYTE prevByte) + { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + BYTE DecodeWithMatchByte(CRangeDecoder *rangeDecoder, int pos, BYTE prevByte, BYTE matchByte) + { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAState.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAState.h new file mode 100644 index 00000000..5c90f941 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZMAState.h @@ -0,0 +1,39 @@ +#include + +#ifndef __LZMA_STATE__H___ +#define __LZMA_STATE__H___ + +typedef struct +{ + void *lzmaDecoder; + void *DynamicData; + void *Dictionary; + UINT32 DictionarySize; + BYTE FirstProp; + + HANDLE hThread; /* decompression thread */ + + BYTE *next_in; /* next input byte */ + UINT avail_in; /* number of bytes available at next_in */ + + BYTE *next_out; /* next output byte should be put there */ + UINT avail_out; /* remaining free space at next_out */ + + CRITICAL_SECTION cs; + BOOL cs_initialized; + BOOL it_locked; /* installer thread locked */ + BOOL dt_locked; /* decompression thread locked */ + + BOOL finished; + int res; +} CLZMAState; + +typedef CLZMAState +#ifndef __cplusplus +FAR +#endif +*CLZMAStateP; + +void __stdcall LZMAGetIO(CLZMAStateP lzmaState); + +#endif \ No newline at end of file diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/LZOutWindow.h b/Source/7zip/7zip/Compress/LZMA_SMALL/LZOutWindow.h new file mode 100644 index 00000000..5f68cf12 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/LZOutWindow.h @@ -0,0 +1,76 @@ +// LZOutWindow.h + +#ifndef __LZOUTWINDOW_H +#define __LZOUTWINDOW_H + +#include "Types.h" +#include "LZMAState.h" +#include "LZMAConf.h" + +class CLZOutWindow +{ +public: + BYTE *_buffer; + UINT32 _pos; + UINT32 _windowSize; + UINT32 _streamPos; + CLZMAStateP m_lzmaState; + void Init(CLZMAStateP lzmaState) + { + m_lzmaState = lzmaState; + _buffer = (LPBYTE) lzmaState->Dictionary; + _windowSize = lzmaState->DictionarySize; + _streamPos = 0; + _pos = 0; + } + void CopyBackBlock(UINT32 fromPos, int len) + { + if (fromPos >= _windowSize) + fromPos += _windowSize; + while (len--) + { + _buffer[_pos++] = _buffer[fromPos++]; + if (fromPos >= _windowSize) + fromPos = 0; + Flush(); + } + } + void PutOneByte(BYTE b) + { + _buffer[_pos++] = b; + Flush(); + } + void Flush() + { + UINT32 size = _pos - _streamPos; + if (size < 65536 && _pos < _windowSize) + return; + + CLZMAStateP lzmaState = m_lzmaState; + while (size--) + { + if (!lzmaState->avail_out) + { + LZMAGetIO(lzmaState); + } + *lzmaState->next_out = _buffer[_streamPos]; + lzmaState->next_out++; + lzmaState->avail_out--; + _streamPos++; + } + if (_pos >= _windowSize) + { + _pos = 0; + _streamPos = 0; + } + } + BYTE GetOneByte(UINT32 index) const + { + UINT32 pos = _pos + index; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoder.h b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoder.h new file mode 100644 index 00000000..f60f7c2c --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoder.h @@ -0,0 +1,87 @@ +// Compression/RangeCoder.h + +#ifndef __COMPRESSION_RANGECODER_H +#define __COMPRESSION_RANGECODER_H + +#include "InBuffer.h" + +const int kNumTopBits = 24; +const UINT32 kTopValue = (1 << kNumTopBits); + +class CRangeDecoder +{ +public: + CInBuffer Stream; + UINT32 Range; + UINT32 Code; + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void Init(CLZMAStateP state) + { + Stream.Init(state); + Code = 0; + Range = UINT32(-1); + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + UINT32 DecodeDirectBits(int numTotalBits) + { + UINT32 range = Range; + UINT32 code = Code; + UINT32 result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UINT32 t = (code - range) >> 31; + code -= range & (t - 1); + // range = aRangeTmp + ((range & 1) & (1 - t)); + result = (result + result) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + int DecodeBit(UINT32 size0, int numTotalBits) + { + UINT32 newBound = (Range >> numTotalBits) * size0; + int symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBit.h b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBit.h new file mode 100644 index 00000000..7abb99c3 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBit.h @@ -0,0 +1,64 @@ +// RangeCoderBit.h + +#ifndef __RANGECODERBIT_H +#define __RANGECODERBIT_H + +#include "Types.h" +#include "RangeCoder.h" + +const int kNumBitModelTotalBits = 11; +const int kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveBits = 5; + +struct CBitModel +{ + UINT32 Probability; // it's fast version on 32-bit systems + // unsigned short Probability; // use it if you want to reduce memory twice + + void UpdateModel(int symbol) + { + /* + Probability -= (Probability + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; + Probability += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); + */ + if (symbol == 0) + Probability += (kBitModelTotal - Probability) >> kNumMoveBits; + else + Probability -= (Probability) >> kNumMoveBits; + } + void Init() { Probability = kBitModelTotal / 2; } +}; + +struct CBitDecoder: public CBitModel +{ + int Decode(CRangeDecoder *rangeDecoder) + { + UINT32 newBound = (rangeDecoder->Range >> kNumBitModelTotalBits) * Probability; + if (rangeDecoder->Code < newBound) + { + rangeDecoder->Range = newBound; + Probability += (kBitModelTotal - Probability) >> kNumMoveBits; + if (rangeDecoder->Range < kTopValue) + { + rangeDecoder->Code = (rangeDecoder->Code << 8) | rangeDecoder->Stream.ReadByte(); + rangeDecoder->Range <<= 8; + } + return 0; + } + else + { + rangeDecoder->Range -= newBound; + rangeDecoder->Code -= newBound; + Probability -= (Probability) >> kNumMoveBits; + if (rangeDecoder->Range < kTopValue) + { + rangeDecoder->Code = (rangeDecoder->Code << 8) | rangeDecoder->Stream.ReadByte(); + rangeDecoder->Range <<= 8; + } + return 1; + } + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBitTree.h b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBitTree.h new file mode 100644 index 00000000..55c9ea21 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderBitTree.h @@ -0,0 +1,183 @@ +// RangeCoderBitTree.h + +#ifndef __RANGECODERBITTREE_H +#define __RANGECODERBITTREE_H + +#include "RangeCoderBit.h" +#include "RangeCoderOpt.h" + +class CBitTreeDecoder3 +{ + CBitDecoder m_Models[1 << 3]; +public: + void Init() + { + for(int i = 1; i < (1 << 3); i++) + m_Models[i].Init(); + } + int Decode(CRangeDecoder *rangeDecoder) + { + int modelIndex = 1; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + #ifndef __UNROLL + for(int bitIndex = 3; bitIndex > 0; bitIndex--) + #endif + { + #ifdef __LOC_OPT + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + #ifdef __UNROLL + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + #endif + #else + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + #ifdef __UNROLL + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + #endif + #endif + } + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return modelIndex - (1 << 3); + }; +}; + +class CBitTreeDecoder6 +{ + CBitDecoder m_Models[1 << 6]; +public: + void Init() + { + for(int i = 1; i < (1 << 6); i++) + m_Models[i].Init(); + } + int Decode(CRangeDecoder *rangeDecoder) + { + int modelIndex = 1; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + #ifndef __UNROLL + for(int bitIndex = 6; bitIndex > 0; bitIndex--) + #endif + { + #ifdef __LOC_OPT + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + #ifdef __UNROLL + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + #endif + #else + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + #ifdef __UNROLL + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + #endif + #endif + } + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return modelIndex - (1 << 6); + }; +}; + +class CBitTreeDecoder8 +{ + CBitDecoder m_Models[1 << 8]; +public: + void Init() + { + for(int i = 1; i < (1 << 8); i++) + m_Models[i].Init(); + } + int Decode(CRangeDecoder *rangeDecoder) + { + int modelIndex = 1; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + for(int bitIndex = 8; bitIndex > 0; bitIndex--) + { + #ifdef __LOC_OPT + RC_GETBIT(m_Models[modelIndex].Probability, modelIndex) + #else + modelIndex = (modelIndex + modelIndex) + m_Models[modelIndex].Decode(rangeDecoder); + #endif + } + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return modelIndex - (1 << 8); + }; +}; + + +class CReverseBitTreeDecoder4 +{ + CBitDecoder m_Models[1 << 4]; +public: + void Init() + { + for(int i = 1; i < (1 << 4); i++) + m_Models[i].Init(); + } + int Decode(CRangeDecoder *rangeDecoder) + { + int modelIndex = 1; + int symbol = 0; + #ifdef __LOC_OPT + RC_INIT_VAR + #endif + #ifndef __UNROLL + for(int bitIndex = 0; bitIndex < 4; bitIndex++) + #endif + { + #ifdef __LOC_OPT + #ifndef __UNROLL + RC_GETBIT2(m_Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << bitIndex)) + #else + RC_GETBIT2(m_Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << 0)) + RC_GETBIT2(m_Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << 1)) + RC_GETBIT2(m_Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << 2)) + RC_GETBIT2(m_Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << 3)) + #endif + #else + #ifndef __UNROLL + int bit = m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = modelIndex + modelIndex + bit; + symbol |= (bit << bitIndex); + #else + int bit = m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = modelIndex + modelIndex + bit; + symbol |= (bit << 0); + bit = m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = modelIndex + modelIndex + bit; + symbol |= (bit << 1); + bit = m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = modelIndex + modelIndex + bit; + symbol |= (bit << 2); + bit = m_Models[modelIndex].Decode(rangeDecoder); + modelIndex = modelIndex + modelIndex + bit; + symbol |= (bit << 3); + #endif + #endif + } + #ifdef __LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderOpt.h b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderOpt.h new file mode 100644 index 00000000..15678514 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/RangeCoderOpt.h @@ -0,0 +1,41 @@ +// RangeCoderOpt.h + +#ifndef __RANGECODEROPT_H +#define __RANGECODEROPT_H + +#include "RangeCoderBit.h" + +#define RC_INIT_VAR \ + UINT32 range = rangeDecoder->Range; \ + UINT32 code = rangeDecoder->Code; + +#define RC_FLUSH_VAR \ + rangeDecoder->Range = range; \ + rangeDecoder->Code = code; + +#define RC_NORMALIZE \ + if (range < kTopValue) \ + { range <<= 8; code = (code << 8) | rangeDecoder->Stream.ReadByte(); } + +#define RC_GETBIT2(prob, modelIndex, Action0, Action1) \ + {UINT32 newBound = (range >> kNumBitModelTotalBits) * prob; \ + if (code < newBound) \ + { \ + Action0; \ + range = newBound; \ + prob += (kBitModelTotal - prob) >> kNumMoveBits; \ + modelIndex <<= 1; \ + } \ + else \ + { \ + Action1; \ + range -= newBound; \ + code -= newBound; \ + prob -= (prob) >> kNumMoveBits; \ + modelIndex = (modelIndex + modelIndex) + 1; \ + }} \ + RC_NORMALIZE + +#define RC_GETBIT(prob, modelIndex) RC_GETBIT2(prob, modelIndex, ; , ;) + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA_SMALL/Types.h b/Source/7zip/7zip/Compress/LZMA_SMALL/Types.h new file mode 100644 index 00000000..ac4dcfa1 --- /dev/null +++ b/Source/7zip/7zip/Compress/LZMA_SMALL/Types.h @@ -0,0 +1,17 @@ +// Common/Types.h + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#ifdef WIN32 +#include +#else +typedef unsigned int UINT32; +#endif + +#ifndef _WINDOWS_ +typedef unsigned char BYTE; +#endif + +#endif + diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h new file mode 100644 index 00000000..cb0292f9 --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h @@ -0,0 +1,244 @@ +// Compress/RangeCoder.h +// This code is based on Eugene Shelwien's Rangecoder code + +// #pragma once + +#ifndef __COMPRESS_RANGECODER_H +#define __COMPRESS_RANGECODER_H + +#include "../../Common/InBuffer.h" +#include "../../Common/OutBuffer.h" + +namespace NCompress { +namespace NRangeCoder { + +const UINT32 kNumTopBits = 24; +const UINT32 kTopValue = (1 << kNumTopBits); + +class CEncoder +{ + COutBuffer Stream; + UINT64 Low; + UINT32 Range; + UINT32 _ffNum; + BYTE _cache; + +public: + void Init(ISequentialOutStream *stream) + { + Stream.Init(stream); + Low = 0; + Range = UINT32(-1); + _ffNum = 0; + _cache = 0; + } + + void FlushData() + { + // Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() + { return Stream.Flush(); } + + /* + void ReleaseStream() + { Stream.ReleaseStream(); } + */ + + void Encode(UINT32 start, UINT32 size, UINT32 total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + /* + void EncodeDirectBitsDiv(UINT32 value, UINT32 numTotalBits) + { + Low += value * (Range >>= numTotalBits); + Normalize(); + } + + void EncodeDirectBitsDiv2(UINT32 value, UINT32 numTotalBits) + { + if (numTotalBits <= kNumBottomBits) + EncodeDirectBitsDiv(value, numTotalBits); + else + { + EncodeDirectBitsDiv(value >> kNumBottomBits, (numTotalBits - kNumBottomBits)); + EncodeDirectBitsDiv(value & ((1 << kBottomValueBits) - 1), kNumBottomBits); + } + } + */ + void ShiftLow() + { + if (Low < (UINT32)0xFF000000 || UINT32(Low >> 32) == 1) + { + Stream.WriteByte(_cache + BYTE(Low >> 32)); + for (;_ffNum != 0; _ffNum--) + Stream.WriteByte(0xFF + BYTE(Low >> 32)); + _cache = BYTE(UINT32(Low) >> 24); + } + else + _ffNum++; + Low = UINT32(Low) << 8; + } + + void EncodeDirectBits(UINT32 value, UINT32 numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((value >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UINT32 size0, UINT32 numTotalBits, UINT32 symbol) + { + UINT32 newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + UINT64 GetProcessedSize() { return Stream.GetProcessedSize() + _ffNum; } +}; + +class CDecoder +{ +public: + CInBuffer Stream; + UINT32 Range; + UINT32 Code; + // UINT32 m_Word; + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void Init(ISequentialInStream *stream) + { + Stream.Init(stream); + Code = 0; + Range = UINT32(-1); + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + // void ReleaseStream() { Stream.ReleaseStream(); } + + UINT32 GetThreshold(UINT32 total) + { + return (Code) / ( Range /= total); + } + + void Decode(UINT32 start, UINT32 size, UINT32 total) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + /* + UINT32 DecodeDirectBitsDiv(UINT32 numTotalBits) + { + Range >>= numTotalBits; + UINT32 threshold = Code / Range; + Code -= threshold * Range; + + Normalize(); + return threshold; + } + + UINT32 DecodeDirectBitsDiv2(UINT32 numTotalBits) + { + if (numTotalBits <= kNumBottomBits) + return DecodeDirectBitsDiv(numTotalBits); + UINT32 result = DecodeDirectBitsDiv(numTotalBits - kNumBottomBits) << kNumBottomBits; + return (result | DecodeDirectBitsDiv(kNumBottomBits)); + } + */ + + UINT32 DecodeDirectBits(UINT32 numTotalBits) + { + UINT32 range = Range; + UINT32 code = Code; + UINT32 result = 0; + for (UINT32 i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UINT32 t = (code - range) >> 31; + code -= range & (t - 1); + // range = rangeTmp + ((range & 1) & (1 - t)); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + UINT32 DecodeBit(UINT32 size0, UINT32 numTotalBits) + { + UINT32 newBound = (Range >> numTotalBits) * size0; + UINT32 symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + UINT64 GetProcessedSize() {return Stream.GetProcessedSize(); } +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp new file mode 100644 index 00000000..c8acf3cd --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp @@ -0,0 +1,77 @@ +// Compress/RangeCoder/RangeCoderBit.cpp + +#include "StdAfx.h" + +#include "RangeCoderBit.h" + +namespace NCompress { +namespace NRangeCoder { + +CPriceTables::CPriceTables() +{ + /* + // simplest: bad solution + for(UINT32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + StatePrices[i] = kBitPrice; + */ + + /* + const double kDummyMultMid = (1.0 / kBitPrice) / 2; + const double kDummyMultMid = 0; + // float solution + double ln2 = log(double(2)); + double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); + for(UINT32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + StatePrices[i] = UINT32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); + */ + + /* + // experimental, slow, solution: + for(UINT32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + { + const int kCyclesBits = 5; + const UINT32 kCycles = (1 << kCyclesBits); + + UINT32 range = UINT32(-1); + UINT32 bitCount = 0; + for (UINT32 j = 0; j < kCycles; j++) + { + range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); + range *= i; + while(range < (1 << 31)) + { + range <<= 1; + bitCount++; + } + } + bitCount <<= kNumBitPriceShiftBits; + range -= (1 << 31); + for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) + { + range <<= 1; + if (range > (1 << 31)) + { + bitCount += (1 << k); + range -= (1 << 31); + } + } + StatePrices[i] = (bitCount + // + (1 << (kCyclesBits - 1)) + ) >> kCyclesBits; + } + */ + + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for(int i = kNumBits - 1; i >= 0; i--) + { + UINT32 start = 1 << (kNumBits - i - 1); + UINT32 end = 1 << (kNumBits - i); + for (UINT32 j = start; j < end; j++) + StatePrices[j] = (i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } +} + +CPriceTables g_PriceTables; + +}} diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h new file mode 100644 index 00000000..2e49b304 --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h @@ -0,0 +1,107 @@ +// Compress/RangeCoder/RangeCoderBit.h + +// #pragma once + +#ifndef __COMPRESS_RANGECODER_BIT_TREE_H +#define __COMPRESS_RANGECODER_BIT_TREE_H + +#include "RangeCoder.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumBitModelTotalBits = 11; +const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveReducingBits = 2; + +const int kNumBitPriceShiftBits = 6; +const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits; + +class CPriceTables +{ +public: + UINT32 StatePrices[kBitModelTotal >> kNumMoveReducingBits]; + CPriceTables(); +}; + +extern CPriceTables g_PriceTables; + + +///////////////////////////// +// CBitModel + +template +class CBitModel +{ +public: + UINT32 Probability; + void UpdateModel(UINT32 symbol) + { + /* + Probability -= (Probability + ((symbol - 1) & ((1 << aNumMoveBits) - 1))) >> aNumMoveBits; + Probability += (1 - symbol) << (kNumBitModelTotalBits - aNumMoveBits); + */ + if (symbol == 0) + Probability += (kBitModelTotal - Probability) >> aNumMoveBits; + else + Probability -= (Probability) >> aNumMoveBits; + } +public: + void Init() { Probability = kBitModelTotal / 2; } +}; + +template +class CBitEncoder: public CBitModel +{ +public: + void Encode(CEncoder *encoder, UINT32 symbol) + { + encoder->EncodeBit(Probability, kNumBitModelTotalBits, symbol); + UpdateModel(symbol); + } + UINT32 GetPrice(UINT32 symbol) const + { + return g_PriceTables.StatePrices[ + (((Probability - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } +}; + + +template +class CBitDecoder: public CBitModel +{ +public: + UINT32 Decode(CDecoder *decoder) + { + UINT32 newBound = (decoder->Range >> kNumBitModelTotalBits) * Probability; + if (decoder->Code < newBound) + { + decoder->Range = newBound; + Probability += (kBitModelTotal - Probability) >> aNumMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 0; + } + else + { + decoder->Range -= newBound; + decoder->Code -= newBound; + Probability -= (Probability) >> aNumMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 1; + } + } +}; + +}} + + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h new file mode 100644 index 00000000..02c74cdb --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h @@ -0,0 +1,303 @@ +// Compress/RangeCoder/RangeCoderBitTree.h + +// #pragma once + +#ifndef __COMPRESS_RANGECODER_BIT_H +#define __COMPRESS_RANGECODER_BIT_H + +#include "RangeCoderBit.h" +#include "RangeCoderOpt.h" + +namespace NCompress { +namespace NRangeCoder { + +/* +template class CMyBitEncoder: + public NCompression::NArithmetic::CBitEncoder {}; +template class CMyBitDecoder: + public NCompression::NArithmetic::CBitDecoder {}; +*/ + +////////////////////////// +// CBitTreeEncoder + +template +class CBitTreeEncoder +{ + CBitEncoder Models[1 << NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + void Encode(CEncoder *rangeEncoder, UINT32 symbol) + { + UINT32 modelIndex = 1; + for (UINT32 bitIndex = NumBitLevels; bitIndex > 0 ;) + { + bitIndex--; + UINT32 bit = (symbol >> bitIndex ) & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + } + }; + UINT32 GetPrice(UINT32 symbol) const + { + UINT32 price = 0; + UINT32 modelIndex = 1; + for (UINT32 bitIndex = NumBitLevels; bitIndex > 0 ;) + { + bitIndex--; + UINT32 bit = (symbol >> bitIndex ) & 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) + bit; + } + return price; + } +}; + +////////////////////////// +// CBitTreeDecoder + +template +class CBitTreeDecoder +{ + CBitDecoder Models[1 << NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + UINT32 Decode(CDecoder *rangeDecoder) + { + UINT32 modelIndex = 1; + RC_INIT_VAR + for(UINT32 bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + { + // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); + RC_GETBIT(numMoveBits, Models[modelIndex].Probability, modelIndex) + } + RC_FLUSH_VAR + return modelIndex - (1 << NumBitLevels); + }; +}; + +//////////////////////////////// +// CReverseBitTreeEncoder + +template +class CReverseBitTreeEncoder2 +{ + CBitEncoder *Models; + UINT32 NumBitLevels; +public: + CReverseBitTreeEncoder2(): Models(0) { } + ~CReverseBitTreeEncoder2() { delete []Models; } + void Create(UINT32 numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new CBitEncoder[1 << numBitLevels]; + // return (Models != 0); + } + void Init() + { + UINT32 numModels = 1 << NumBitLevels; + for(UINT32 i = 1; i < numModels; i++) + Models[i].Init(); + } + void Encode(CEncoder *rangeEncoder, UINT32 symbol) + { + UINT32 modelIndex = 1; + for (UINT32 i = 0; i < NumBitLevels; i++) + { + UINT32 bit = symbol & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } + } + UINT32 GetPrice(UINT32 symbol) const + { + UINT32 price = 0; + UINT32 modelIndex = 1; + for (UINT32 i = NumBitLevels; i > 0; i--) + { + UINT32 bit = symbol & 1; + symbol >>= 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) | bit; + } + return price; + } +}; + +/* +template +class CReverseBitTreeEncoder: public CReverseBitTreeEncoder2 +{ +public: + CReverseBitTreeEncoder() + { Create(numBitLevels); } +}; +*/ +//////////////////////////////// +// CReverseBitTreeDecoder + +template +class CReverseBitTreeDecoder2 +{ + CBitDecoder *Models; + UINT32 NumBitLevels; +public: + CReverseBitTreeDecoder2(): Models(0) { } + ~CReverseBitTreeDecoder2() { delete []Models; } + void Create(UINT32 numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new CBitDecoder[1 << numBitLevels]; + // return (Models != 0); + } + void Init() + { + UINT32 numModels = 1 << NumBitLevels; + for(UINT32 i = 1; i < numModels; i++) + Models[i].Init(); + } + UINT32 Decode(CDecoder *rangeDecoder) + { + UINT32 modelIndex = 1; + UINT32 symbol = 0; + RC_INIT_VAR + for(UINT32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UINT32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; + }; +}; +//////////////////////////// +// CReverseBitTreeDecoder2 + +template +class CReverseBitTreeDecoder +{ + CBitDecoder Models[1 << NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + UINT32 Decode(CDecoder *rangeDecoder) + { + UINT32 modelIndex = 1; + UINT32 symbol = 0; + RC_INIT_VAR + for(UINT32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UINT32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Probability, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; + } +}; + +/* +////////////////////////// +// CBitTreeEncoder2 + +template +class CBitTreeEncoder2 +{ + NCompression::NArithmetic::CBitEncoder *Models; + UINT32 NumBitLevels; +public: + bool Create(UINT32 numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new NCompression::NArithmetic::CBitEncoder[1 << numBitLevels]; + return (Models != 0); + } + void Init() + { + UINT32 numModels = 1 << NumBitLevels; + for(UINT32 i = 1; i < numModels; i++) + Models[i].Init(); + } + void Encode(CMyRangeEncoder *rangeEncoder, UINT32 symbol) + { + UINT32 modelIndex = 1; + for (UINT32 bitIndex = NumBitLevels; bitIndex > 0 ;) + { + bitIndex--; + UINT32 bit = (symbol >> bitIndex ) & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + } + } + UINT32 GetPrice(UINT32 symbol) const + { + UINT32 price = 0; + UINT32 modelIndex = 1; + for (UINT32 bitIndex = NumBitLevels; bitIndex > 0 ;) + { + bitIndex--; + UINT32 bit = (symbol >> bitIndex ) & 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) + bit; + } + return price; + } +}; + + +////////////////////////// +// CBitTreeDecoder2 + +template +class CBitTreeDecoder2 +{ + NCompression::NArithmetic::CBitDecoder *Models; + UINT32 NumBitLevels; +public: + bool Create(UINT32 numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new NCompression::NArithmetic::CBitDecoder[1 << numBitLevels]; + return (Models != 0); + } + void Init() + { + UINT32 numModels = 1 << NumBitLevels; + for(UINT32 i = 1; i < numModels; i++) + Models[i].Init(); + } + UINT32 Decode(CMyRangeDecoder *rangeDecoder) + { + UINT32 modelIndex = 1; + RC_INIT_VAR + for(UINT32 bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + { + // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); + RC_GETBIT(numMoveBits, Models[modelIndex].Probability, modelIndex) + } + RC_FLUSH_VAR + return modelIndex - (1 << NumBitLevels); + } +}; +*/ + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h new file mode 100644 index 00000000..f251caa8 --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h @@ -0,0 +1,43 @@ +// Compress/RangeCoder/RangeCoderOpt.h + +// #pragma once + +#ifndef __COMPRESS_RANGECODER_OPT_H +#define __COMPRESS_RANGECODER_OPT_H + +#define RC_INIT_VAR \ + UINT32 range = rangeDecoder->Range; \ + UINT32 code = rangeDecoder->Code; + +#define RC_FLUSH_VAR \ + rangeDecoder->Range = range; \ + rangeDecoder->Code = code; + +#define RC_NORMALIZE \ + if (range < NCompress::NRangeCoder::kTopValue) \ + { \ + code = (code << 8) | rangeDecoder->Stream.ReadByte(); \ + range <<= 8; } + +#define RC_GETBIT2(numMoveBits, prob, modelIndex, Action0, Action1) \ + {UINT32 newBound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ + if (code < newBound) \ + { \ + Action0; \ + range = newBound; \ + prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ + modelIndex <<= 1; \ + } \ + else \ + { \ + Action1; \ + range -= newBound; \ + code -= newBound; \ + prob -= (prob) >> numMoveBits; \ + modelIndex = (modelIndex << 1) + 1; \ + }} \ + RC_NORMALIZE + +#define RC_GETBIT(numMoveBits, prob, modelIndex) RC_GETBIT2(numMoveBits, prob, modelIndex, ; , ;) + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h new file mode 100644 index 00000000..a32fbed6 --- /dev/null +++ b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include + +#endif diff --git a/Source/7zip/7zip/ICoder.h b/Source/7zip/7zip/ICoder.h new file mode 100644 index 00000000..0068bef0 --- /dev/null +++ b/Source/7zip/7zip/ICoder.h @@ -0,0 +1,127 @@ +// ICoder.h + +// #pragma once + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +// {23170F69-40C1-278A-0000-000200040000} +DEFINE_GUID(IID_ICompressProgressInfo, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200040000") +ICompressProgressInfo: public IUnknown +{ + STDMETHOD(SetRatioInfo)(const UINT64 *inSize, const UINT64 *outSize) = 0; +}; + +// {23170F69-40C1-278A-0000-000200050000} +DEFINE_GUID(IID_ICompressCoder, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200050000") +ICompressCoder: public IUnknown +{ + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UINT64 *inSize, + const UINT64 *outSize, + ICompressProgressInfo *progress) = 0; +}; + +// {23170F69-40C1-278A-0000-000200180000} +DEFINE_GUID(IID_ICompressCoder2, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200180000") +ICompressCoder2: public IUnknown +{ + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UINT64 **inSizes, + UINT32 numInStreams, + ISequentialOutStream **outStreams, + const UINT64 **outSizes, + UINT32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +namespace NCoderPropID +{ + enum EEnum + { + kDictionarySize = 0x400, + kUsedMemorySize, + kOrder, + kPosStateBits = 0x440, + kLitContextBits, + kLitPosBits, + kNumFastBytes = 0x450, + kMatchFinder, + kNumPasses = 0x460, + kAlgorithm = 0x470, + kMultiThread = 0x480 + }; +} + +// {23170F69-40C1-278A-0000-000200200000} +DEFINE_GUID(IID_ICompressSetCoderProperties, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200200000") +ICompressSetCoderProperties: public IUnknown +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UINT32 numProperties) PURE; +}; + +// {23170F69-40C1-278A-0000-000200210000} +DEFINE_GUID(IID_ICompressSetDecoderProperties, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200210000") +ICompressSetDecoderProperties: public IUnknown +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *anInStream) PURE; +}; + +// {23170F69-40C1-278A-0000-000200230000} +DEFINE_GUID(IID_ICompressWriteCoderProperties, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x23, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200230000") +ICompressWriteCoderProperties: public IUnknown +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; +}; + +// {23170F69-40C1-278A-0000-000200240000} +DEFINE_GUID(IID_ICompressGetInStreamProcessedSize, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200240000") +ICompressGetInStreamProcessedSize: public IUnknown +{ + STDMETHOD(GetInStreamProcessedSize)(UINT64 *value) PURE; +}; + +// {23170F69-40C1-278A-0000-000200250000} +DEFINE_GUID(IID_ICompressGetSubStreamSize, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000200250000") +ICompressGetSubStreamSize: public IUnknown +{ + STDMETHOD(GetSubStreamSize)(UINT64 subStream, UINT64 *value) PURE; +}; + +////////////////////// +// It's for DLL file +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kInStreams, + kOutStreams, + kDescription, + }; +} + +#endif diff --git a/Source/7zip/7zip/IMyUnknown.h b/Source/7zip/7zip/IMyUnknown.h new file mode 100644 index 00000000..d614d99a --- /dev/null +++ b/Source/7zip/7zip/IMyUnknown.h @@ -0,0 +1,71 @@ +// IMyUnknown.h + +// #pragma once + +#ifndef __MYUNKNOWN_H +#define __MYUNKNOWN_H + +#ifdef WIN32 + +// #include +#include + +#else + +#define HRESULT LONG +#define STDMETHODCALLTYPE __stdcall +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0; + +typedef struct { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#ifdef INITGUID + #define MY_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define MY_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * __MIDL_CONST +#endif + +#define MIDL_INTERFACE(x) struct +inline int operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return false; + return true; +} +inline int operator!=(REFGUID &g1, REFGUID &g2) + { return !(g1 == g2); } + +struct IUnknown +{ + STDMETHOD(QueryInterface) (const GUID *iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; +}; + +#endif + +#endif diff --git a/Source/7zip/7zip/IStream.h b/Source/7zip/7zip/IStream.h new file mode 100644 index 00000000..147be411 --- /dev/null +++ b/Source/7zip/7zip/IStream.h @@ -0,0 +1,64 @@ +// IStream.h + +// #pragma once + +#ifndef __ISTREAMS_H +#define __ISTREAMS_H + +#include "IMyUnknown.h" + +// {23170F69-40C1-278A-0000-000000010000} +DEFINE_GUID(IID_ISequentialInStream, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000010000") +ISequentialInStream : public IUnknown +{ +public: + // out: if (processedSize == 0) then there are no more bytes + STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize) = 0; + STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize) = 0; +}; + +// {23170F69-40C1-278A-0000-000000020000} +DEFINE_GUID(IID_ISequentialOutStream, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000020000") +ISequentialOutStream : public IUnknown +{ +public: + STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize) = 0; + STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize) = 0; +}; + +// {23170F69-40C1-278A-0000-000000030000} +DEFINE_GUID(IID_IInStream, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000030000") +IInStream : public ISequentialInStream +{ +public: + STDMETHOD(Seek)(INT64 offset, UINT32 seekOrigin, UINT64 *newPosition) = 0; +}; + +// {23170F69-40C1-278A-0000-000000040000} +DEFINE_GUID(IID_IOutStream, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000040000") +IOutStream : public ISequentialOutStream +{ +public: + STDMETHOD(Seek)(INT64 offset, UINT32 seekOrigin, UINT64 *newPosition) = 0; + STDMETHOD(SetSize)(INT64 aNewSize) = 0; +}; + +// {23170F69-40C1-278A-0000-000000060000} +DEFINE_GUID(IID_IStreamGetSize, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000060000") +IStreamGetSize : public IUnknown +{ +public: + STDMETHOD(GetSize)(UINT64 *size) = 0; +}; + +#endif diff --git a/Source/7zip/Common/CRC.cpp b/Source/7zip/Common/CRC.cpp new file mode 100644 index 00000000..006da6d9 --- /dev/null +++ b/Source/7zip/Common/CRC.cpp @@ -0,0 +1,110 @@ +// Common/CRC.cpp + +#include "StdAfx.h" + +#include "CRC.h" + +static const UINT32 kCRCPoly = 0xEDB88320; + +UINT32 CCRC::Table[256]; + +class CCRCTableInit +{ +public: +CCRCTableInit() +{ + for (UINT32 i = 0; i < 256; i++) + { + UINT32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = r; + } +} +} g_CRCTableInit; + +/* +const UINT32 CCRC::Table[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +*/ + +#define UPDATE valueLoc = Table[(BYTE)valueLoc] ^ (valueLoc >> 8) +#define UPDATE4 UPDATE; UPDATE; UPDATE; UPDATE; + +void CCRC::Update(const void *data, UINT32 size) +{ + UINT32 valueLoc = _value; + const BYTE *byteBuffer = (const BYTE *)data; + + for(; (UINT_PTR(byteBuffer) & 3) != 0 && size > 0; size--, byteBuffer++) + valueLoc = Table[(((BYTE)(valueLoc)) ^ (*byteBuffer))] ^ + (valueLoc >> 8); + + const UINT32 kBlockSize = 4; + while (size >= kBlockSize) + { + size -= kBlockSize; + valueLoc ^= *(const UINT32 *)byteBuffer; + UPDATE4 + byteBuffer += kBlockSize; + } + for(UINT32 i = 0; i < size; i++) + valueLoc = Table[(((BYTE)(valueLoc)) ^ (byteBuffer)[i])] ^ + (valueLoc >> 8); + _value = valueLoc; +} diff --git a/Source/7zip/Common/CRC.h b/Source/7zip/Common/CRC.h new file mode 100644 index 00000000..34514883 --- /dev/null +++ b/Source/7zip/Common/CRC.h @@ -0,0 +1,31 @@ +// Common/CRC.h + +// #pragma once + +#ifndef __COMMON_CRC_H +#define __COMMON_CRC_H + +#include "Types.h" + +class CCRC +{ + UINT32 _value; +public: + static UINT32 Table[256]; + CCRC(): _value(0xFFFFFFFF){}; + void Init() { _value = 0xFFFFFFFF; } + void Update(const void *data, UINT32 size); + UINT32 GetDigest() const { return _value ^ 0xFFFFFFFF; } + static UINT32 CalculateDigest(const void *data, UINT32 size) + { + CCRC crc; + crc.Update(data, size); + return crc.GetDigest(); + } + static bool VerifyDigest(UINT32 digest, const void *data, UINT32 size) + { + return (CalculateDigest(data, size) == digest); + } +}; + +#endif diff --git a/Source/7zip/Common/ComTry.h b/Source/7zip/Common/ComTry.h new file mode 100644 index 00000000..3162e502 --- /dev/null +++ b/Source/7zip/Common/ComTry.h @@ -0,0 +1,14 @@ +// ComTry.h + +// #pragma once + +#ifndef __Com_Try_H +#define __Com_Try_H + +#include "Exception.h" + +#define COM_TRY_BEGIN try { +#define COM_TRY_END } catch(const CSystemException &e) { return e.ErrorCode; }\ + catch(...) { return E_FAIL; } + +#endif diff --git a/Source/7zip/Common/Defs.h b/Source/7zip/Common/Defs.h new file mode 100644 index 00000000..bfaaa6c9 --- /dev/null +++ b/Source/7zip/Common/Defs.h @@ -0,0 +1,22 @@ +// Common/Defs.h + +// #pragma once + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template inline T MyMin(T a, T b) + { return a < b ? a : b; } +template inline T MyMax(T a, T b) + { return a > b ? a : b; } + +template inline int MyCompare(T a, T b) + { return a < b ? -1 : (a == b ? 0 : 1); } + +inline int BoolToInt(bool value) + { return (value ? 1: 0); } + +inline bool IntToBool(int value) + { return (value != 0); } + +#endif diff --git a/Source/7zip/Common/MyCom.h b/Source/7zip/Common/MyCom.h new file mode 100644 index 00000000..40e4ce29 --- /dev/null +++ b/Source/7zip/Common/MyCom.h @@ -0,0 +1,187 @@ +// MyCom.h + +// #pragma once + +#ifndef __MYCOM_H +#define __MYCOM_H + +#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } + +template +class CMyComPtr +{ + T* _p; +public: + // typedef T _PtrClass; + CMyComPtr() { _p = NULL;} + CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) + { + if ((_p = lp._p) != NULL) + _p->AddRef(); + } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p != 0) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + // Compare two objects for equivalence + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template + HRESULT QueryInterface(REFGUID iid, Q** pp) const + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +class CMyComBSTR +{ +public: + BSTR m_str; + CMyComBSTR() { m_str = NULL; } + CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + ~CMyComBSTR() { ::SysFreeString(m_str); } + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + CMyComBSTR& operator=(LPCOLESTR pSrc) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(pSrc); + return *this; + } + unsigned int Length() const { return ::SysStringLen(m_str); } + operator BSTR() const { return m_str; } + BSTR* operator&() { return &m_str; } + BSTR MyCopy() const + { + int byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + memmove(res, m_str, byteLen); + return res; + } + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } + bool operator!() const { return (m_str == NULL); } +}; + + +////////////////////////////////////////////////////////// + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} +}; + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ + (REFGUID iid, void **outObject) { +#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; AddRef(); return S_OK; } +#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP MY_UNKNOWN_IMP_SPEC(;) + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#endif diff --git a/Source/7zip/Common/StdAfx.h b/Source/7zip/Common/StdAfx.h new file mode 100644 index 00000000..a32fbed6 --- /dev/null +++ b/Source/7zip/Common/StdAfx.h @@ -0,0 +1,8 @@ +// stdafx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include + +#endif diff --git a/Source/7zip/Common/Types.h b/Source/7zip/Common/Types.h new file mode 100644 index 00000000..02853e0d --- /dev/null +++ b/Source/7zip/Common/Types.h @@ -0,0 +1,19 @@ +// Common/Types.h + +// #pragma once + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#include + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef short INT16; +#ifndef _WINDOWS_ + // typedef unsigned long UINT32; + typedef UINT8 BYTE; +#endif + +#endif + diff --git a/Source/7zip/copying.txt b/Source/7zip/copying.txt new file mode 100644 index 00000000..4c389012 --- /dev/null +++ b/Source/7zip/copying.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Source/7zip/lzmaNSIS.cpp b/Source/7zip/lzmaNSIS.cpp new file mode 100644 index 00000000..b3209e21 --- /dev/null +++ b/Source/7zip/lzmaNSIS.cpp @@ -0,0 +1,165 @@ +// lzmaNSIS.h + +#include + +#include "lzmaNSIS.h" +#include "7zip/Compress/LZMA_SMALL/LZMAConf.h" +#include "7zip/Compress/LZMA_SMALL/LZMADecoder.h" + +void __stdcall LZMAGetIO(CLZMAStateP lzmaState) +{ + LeaveCriticalSection(&lzmaState->cs); + while (!lzmaState->it_locked) + Sleep(0); + + lzmaState->dt_locked = FALSE; + + EnterCriticalSection(&lzmaState->cs); + lzmaState->dt_locked = TRUE; + + while (lzmaState->it_locked) + Sleep(0); +} + +extern "C" +{ + +void __stdcall lzmaInit(CLZMAStateP lzmaState) +{ + if (lzmaState->hThread) + { + CloseHandle(lzmaState->hThread); + lzmaState->hThread = NULL; + } + + if (!lzmaState->lzmaDecoder) + lzmaState->lzmaDecoder = LZMAAlloc(sizeof(CLZMADecoder)); + + if (!lzmaState->cs_initialized) + { + InitializeCriticalSection(&lzmaState->cs); + lzmaState->cs_initialized = TRUE; + } + + lzmaState->it_locked = TRUE; + lzmaState->dt_locked = FALSE; + + lzmaState->finished = FALSE; +} + +DWORD WINAPI lzmaDecompressThread(LPVOID lpParameter) +{ + CLZMAStateP lzmaState = (CLZMAStateP) lpParameter; + CLZMADecoder *lzmaDecodeder = (CLZMADecoder *) lzmaState->lzmaDecoder; + + EnterCriticalSection(&lzmaState->cs); + lzmaState->dt_locked = TRUE; + + while (lzmaState->it_locked) + Sleep(0); + + { + const kPropertiesSize = 5; + lzmaState->res = -4; + if (lzmaState->avail_in < kPropertiesSize) + { + goto finished; + } + LPBYTE properties = lzmaState->next_in; + lzmaState->avail_in -= kPropertiesSize; + lzmaState->next_in += kPropertiesSize; + + BYTE firstByte = properties[0]; + + if (firstByte > (9*5*5)) + { + goto finished; + } + + int numPosStateBits = firstByte / (9*5); + firstByte %= (9*5); + int numLiteralPosStateBits = firstByte / 9; + firstByte %= 9; + int numLiteralContextBits = firstByte; + + int memSize = + ((1 << (numLiteralContextBits + numLiteralPosStateBits))* + 256 * 3) * sizeof(CBitDecoder); + + if (lzmaState->DynamicData == 0 || firstByte != lzmaState->FirstProp) + { + if (lzmaState->DynamicData != 0) + LZMAFree(lzmaState->DynamicData); + lzmaState->DynamicData = LZMAAlloc(memSize); + lzmaState->FirstProp = firstByte; + } + + int memSizeReal = lzmaDecodeder->Create((BYTE *) lzmaState->DynamicData, + numLiteralContextBits, numLiteralPosStateBits, numPosStateBits); + + if (memSizeReal != memSize) + { + goto finished; + } + + UINT32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UINT32)properties[1 + i]) << (i * 8); + if (lzmaState->Dictionary == 0 || dictionarySize != lzmaState->DictionarySize) + { + if (lzmaState->Dictionary != 0) + LZMAFree(lzmaState->Dictionary); + lzmaState->Dictionary = LZMAAlloc(dictionarySize); + lzmaState->DictionarySize = dictionarySize; + } + + UINT32 res = lzmaDecodeder->Code(lzmaState); + + lzmaState->res = 1; + if (res != 0) + lzmaState->res = res; + } + +finished: + + lzmaState->finished = TRUE; + + LeaveCriticalSection(&lzmaState->cs); + lzmaState->dt_locked = FALSE; + return 0; +} + +int __stdcall lzmaDecompress(CLZMAStateP lzmaState) +{ + if (!lzmaState->hThread) + { + DWORD dwThreadId; + lzmaState->hThread = CreateThread(0, 0, lzmaDecompressThread, (LPVOID) lzmaState, 0, &dwThreadId); + if (!lzmaState->hThread) + return -4; + } + else + LeaveCriticalSection(&lzmaState->cs); + + while (!lzmaState->dt_locked) + Sleep(0); + + lzmaState->it_locked = FALSE; + + EnterCriticalSection(&lzmaState->cs); + lzmaState->it_locked = TRUE; + + while (lzmaState->dt_locked) + { + if (lzmaState->finished) + { + LeaveCriticalSection(&lzmaState->cs); + return lzmaState->res; + } + Sleep(0); + } + + return 0; +} + +} // extern "C" \ No newline at end of file diff --git a/Source/7zip/lzmaNSIS.h b/Source/7zip/lzmaNSIS.h new file mode 100644 index 00000000..8b8936ea --- /dev/null +++ b/Source/7zip/lzmaNSIS.h @@ -0,0 +1,20 @@ +// lzmaNSIS.h + +#include "7zip/Compress/LZMA_SMALL/LZMAState.h" + +#ifndef __LZMANSIS_H +#define __LZMANSIS_H + +#ifdef __cplusplus +extern "C" { +#endif + +void __stdcall lzmaInit(CLZMAStateP lzmaState); +int __stdcall lzmaDecompress(CLZMAStateP lzmaState); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Source/7zip/readme.txt b/Source/7zip/readme.txt new file mode 100644 index 00000000..3c3f87a4 --- /dev/null +++ b/Source/7zip/readme.txt @@ -0,0 +1,31 @@ +LZMA library for NSIS +--------------------- + + Copyright (c) 1999-2003 Igor Pavlov + + All files in this folder and it's subfolders are + licensed under GNU LGPL. + Most of these files were copied from source code + of 7-Zip compression program: + + http://www.7-zip.org + + LZMA is default and general compression method of 7z format in 7-Zip. + The main features of LZMA method: + - High compression ratio + - High decompressing speed: about 10-20 MB/s on 2 GHz CPU + - Small memory requirements for decompressing + - Small code size for decompressing: about 5 KB + If you need more information about 7-Zip, LZMA and licensing, + please write to support@7-zip.org + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. diff --git a/Source/build.cpp b/Source/build.cpp index d8846e49..b226ebaa 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -257,6 +257,9 @@ CEXEBuild::CEXEBuild() #else build_compress_whole = false; #endif + build_compress=1; + build_compress_level=9; + build_compress_dict_size=1<<23; cur_entries=&build_entries; cur_datablock=&build_datablock; @@ -288,7 +291,6 @@ CEXEBuild::CEXEBuild() #endif build_overwrite=build_last_overwrite=0; - build_compress=1; build_crcchk=1; build_datesave=1; build_optimize_datablock=1; @@ -770,7 +772,11 @@ int CEXEBuild::add_db_data(IMMap *map) // returns offset db->resize(st + bufferlen + sizeof(int)); int n; - if ((n = compressor->Init(9)) != C_OK) + if (compressor == &lzma_compressor) + n = ((CLZMA *) compressor)->Init(build_compress_level, build_compress_dict_size); + else + n = compressor->Init(build_compress_level); + if (n != C_OK) { ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n", n); extern void quit(); quit(); @@ -907,7 +913,11 @@ int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // retur dblock->resize(st+bufferlen+sizeof(int)); int n; - if ((n=compressor->Init(9)) != C_OK) + if (compressor == &lzma_compressor) + n = ((CLZMA *) compressor)->Init(build_compress_level, build_compress_dict_size); + else + n = compressor->Init(build_compress_level); + if (n != C_OK) { ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n",n); extern void quit(); quit(); @@ -2396,9 +2406,14 @@ int CEXEBuild::write_output(void) #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT if (build_compress_whole) { - if ((compressor->Init(9)) != C_OK) + int n; + if (compressor == &lzma_compressor) + n = ((CLZMA *) compressor)->Init(build_compress_level, build_compress_dict_size); + else + n = compressor->Init(build_compress_level); + if (n != C_OK) { - ERROR_MSG("Error: deflateInit() returned < 0\n"); + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n", n); return PS_ERROR; } } @@ -2581,7 +2596,8 @@ int CEXEBuild::write_output(void) int l = min(build_filebuflen, left); char *dbptr = (char *) build_datablock.get(dbl - left, l); #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT - if (build_compress_whole) { + if (build_compress_whole) + { if (deflateToFile(fp,dbptr,l)) { fclose(fp); @@ -2794,10 +2810,15 @@ int CEXEBuild::uninstall_generate() // compress uninstaller too { char obuf[65536]; - if ((compressor->Init(9)) != C_OK) + int n; + if (compressor == &lzma_compressor) + n = ((CLZMA *) compressor)->Init(build_compress_level, build_compress_dict_size); + else + n = compressor->Init(build_compress_level); + if (n != C_OK) { - ERROR_MSG("Error: deflateInit() returned < 0\n"); - return PS_ERROR; + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n", n); + extern void quit(); quit(); } compressor->SetNextIn((char*)uhd.get(), uhd.getlen()); diff --git a/Source/build.h b/Source/build.h index fa80aeea..68072d53 100644 --- a/Source/build.h +++ b/Source/build.h @@ -2,6 +2,7 @@ #define _BUILD_H_ #include + using namespace std; #include "strlist.h" @@ -26,6 +27,7 @@ using namespace std; #include "compressor.h" #include "czlib.h" #include "cbzip2.h" +#include "clzma.h" #endif//NSIS_CONFIG_COMPRESSION_SUPPORT @@ -264,18 +266,22 @@ class CEXEBuild { ICompressor *compressor; CZlib zlib_compressor; CBzip2 bzip2_compressor; + CLZMA lzma_compressor; #endif bool build_compressor_set; bool build_compressor_final; bool build_compress_whole; + int build_compress; + int build_compress_level; + int build_compress_dict_size; bool no_space_texts; int has_called_write_output; char build_packname[1024], build_packcmd[1024]; - int build_overwrite, build_last_overwrite, build_compress, - build_crcchk, build_datesave, build_optimize_datablock, + int build_overwrite, build_last_overwrite, build_crcchk, + build_datesave, build_optimize_datablock, build_allowskipfiles; // Added by ramon 23 May 2003 header build_header, build_uninst, *cur_header; diff --git a/Source/cbzip2.h b/Source/cbzip2.h index 58909f8a..32e313ba 100644 --- a/Source/cbzip2.h +++ b/Source/cbzip2.h @@ -44,7 +44,7 @@ class CBzip2 : public ICompressor { return stream->avail_out; } - char* GetName() { + const char* GetName() { return "bzip2"; } diff --git a/Source/clzma.h b/Source/clzma.h new file mode 100644 index 00000000..dd187d70 --- /dev/null +++ b/Source/clzma.h @@ -0,0 +1,259 @@ +#ifndef __CLZMA_H__ +#define __CLZMA_H__ + +#include "compressor.h" +#include "7zip/7zip/IStream.h" +#include "7zip/7zip/Compress/LZMA/LZMAEncoder.h" +#include "7zip/Common/MyCom.h" + +class CCyclicBuffer +{ + BYTE *Buffer; + UINT32 BufferSize; + UINT32 Pos; + UINT32 UsedSize; +public: + void Free() + { + if (Buffer != 0) + { + delete []Buffer; + Buffer = 0; + } + } + CCyclicBuffer(): Buffer(0) {} + ~CCyclicBuffer() { Free(); } + bool Create(UINT32 bufferSize) + { + if (Buffer != 0 && bufferSize == bufferSize) + return true; + Free(); + BufferSize = bufferSize; + Buffer = new BYTE[bufferSize]; + return (Buffer != 0); + } + void Init() + { + Pos = 0; + UsedSize = 0; + } + UINT32 GetUsedSize() const { return UsedSize; } + UINT32 GetAvailSize() const { return BufferSize - UsedSize; } + UINT32 Write(const BYTE *data, UINT32 size) + { + if (size > GetAvailSize()) + size = GetAvailSize(); + UINT32 size1 = size; + while(size1 > 0) + { + UINT32 writePos = Pos + UsedSize; + if (writePos >= BufferSize) + writePos -= BufferSize; + UINT32 size2 = size1; + if (size2 > BufferSize - writePos) + size2 = BufferSize - writePos; + memmove(Buffer + writePos, data, size2); + data += size2; + size1 -= size2; + UsedSize += size2; + } + return size; + } + UINT32 Read(BYTE *data, UINT32 size) + { + if (size > UsedSize) + size = UsedSize; + UINT32 size1 = size; + while (size1 > 0) + { + UINT32 size2 = size1; + if (size2 > BufferSize - Pos) + size2 = BufferSize - Pos; + memmove(data, Buffer + Pos, size2); + Pos += size2; + if (Pos >= BufferSize) + Pos -= BufferSize; + data += size2; + size1 -= size2; + UsedSize -= size2; + } + return size; + } +}; + +class CBufferInStream: + public ISequentialInStream, + public CMyUnknownImp, + public CCyclicBuffer +{ +public: + MY_UNKNOWN_IMP + STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize) + { + return ReadPart(data, size, processedSize); + } + STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize) + { + UINT32 temp = CCyclicBuffer::Read((BYTE *)data, size); + if (processedSize != 0) + *processedSize = temp; + return S_OK; + } +}; + +class CBufferOutStream: + public ISequentialOutStream, + public CMyUnknownImp, + public CCyclicBuffer +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize) + { + return WritePart(data, size, processedSize); + } + STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize) + { + UINT32 temp = CCyclicBuffer::Write((const BYTE *)data, size); + if (processedSize != 0) + *processedSize = temp; + return S_OK; + } +}; + +class CLZMA : public ICompressor +{ +public: + CLZMA(): _encoder(0) + { + _encoder = new NCompress::NLZMA::CEncoder(); + _encoder->SetWriteEndMarkerMode(true); + } + ~CLZMA() + { + if (_encoder != 0) + { + delete _encoder; + _encoder = 0; + } + } + + int Init(int level, UINT32 dicSize) + { + _inStream.Create(dicSize * 2 + (1 << 21)); + + // you must set it at least 1 MB and add 2 sizes of buffer from OutBuffer.h: + // COutBuffer::COutBuffer(UINT32 bufferSize = (1 << 20)); + _outStream.Create(3 << 20); + + _needWriteProperties = true; + _inStream.Init(); + _outStream.Init(); + + PROPID propdIDs [] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kDictionarySize, + NCoderPropID::kNumFastBytes + }; + const kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]); + PROPVARIANT props[kNumProps]; + // NCoderPropID::kAlgorithm + props[0].vt = VT_UI4; + props[0].ulVal = 2; + // NCoderPropID::kDictionarySize + props[1].vt = VT_UI4; + props[1].ulVal = dicSize; + // NCoderPropID::kNumFastBytes + props[2].vt = VT_UI4; + props[2].ulVal = 64; + if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0) + return -1; + return _encoder->SetStreams(&_inStream, &_outStream, 0, 0); + } + + int Init(int level) + { + // default dictionary size is 8MB + return Init(level, 1 << 23); + } + + int End() + { + _next_in = NULL; + _avail_in = 0; + _next_out = NULL; + _avail_out = 0; + _inStream.Free(); + _outStream.Free(); + return C_OK; + } + + int Compress(BOOL finish) + { + WriteToOutStream(); + if (_avail_in) + { + UINT32 written = _inStream.Write((const LPBYTE)_next_in, _avail_in); + _next_in += written; + _avail_in -= written; + } + while ((_inStream.GetAvailSize() == 0 || finish) && + _outStream.GetUsedSize() == 0) + { + UINT64 inSize, outSize; + INT32 finished; + if (_needWriteProperties) + { + if (_encoder->WriteCoderProperties(&_outStream) != 0) + return 1; + _needWriteProperties = false; + } + if (_encoder->CodeOneBlock(&inSize, &outSize, &finished) != 0) + return 1; + WriteToOutStream(); + if (finished != 0) + return C_OK; + if (_avail_out == 0) + return C_OK; + } + return C_OK; + } + + void SetNextIn(char *in, unsigned int size) + { + _next_in = in; + _avail_in = size; + } + + void SetNextOut(char *out, unsigned int size) + { + _next_out = out; + _avail_out = size; + } + + virtual char* GetNextOut() { return _next_out; } + virtual unsigned int GetAvailIn() { return _avail_in; } + virtual unsigned int GetAvailOut() { return _avail_out; } + const char* GetName() { return "lzma"; } + +private: + NCompress::NLZMA::CEncoder *_encoder; + CBufferInStream _inStream; + CBufferOutStream _outStream; + char *_next_in; + UINT32 _avail_in; + char *_next_out; + UINT32 _avail_out; + bool _needWriteProperties; + + void WriteToOutStream() + { + UINT32 temp = _outStream.Read((BYTE *)_next_out, _avail_out); + _next_out += temp; + _avail_out -= temp; + } +}; + +#endif \ No newline at end of file diff --git a/Source/compressor.h b/Source/compressor.h index 9eb38fff..c448680f 100644 --- a/Source/compressor.h +++ b/Source/compressor.h @@ -18,7 +18,7 @@ class ICompressor { virtual unsigned int GetAvailIn() = 0; virtual unsigned int GetAvailOut() = 0; - virtual char* GetName() = 0; + virtual const char* GetName() = 0; }; #endif \ No newline at end of file diff --git a/Source/czlib.h b/Source/czlib.h index 5ff87714..d5a82e22 100644 --- a/Source/czlib.h +++ b/Source/czlib.h @@ -44,7 +44,7 @@ class CZlib : public ICompressor { return stream->avail_out; } - char* GetName() { + const char* GetName() { return "zlib"; } diff --git a/Source/exedata.cpp b/Source/exedata.cpp index fd271e6e..b3333eeb 100644 --- a/Source/exedata.cpp +++ b/Source/exedata.cpp @@ -8,6 +8,7 @@ #include "exehead/Release-zlib/unicon.h" #include "exehead/Release-zlib/exehead_zlib.h" #include "exehead/Release-bzip2/exehead_bzip2.h" +#include "exehead/Release-lzma/exehead_lzma.h" /*#else #ifdef NSIS_CONFIG_COMPONENTPAGE #include "exehead/Debug-zlib/bitmap1.h" @@ -16,10 +17,12 @@ #include "exehead/Debug-zlib/unicon.h" #include "exehead/Debug-zlib/exehead_zlib.h" #include "exehead/Debug-bzip2/exehead_bzip2.h" +#include "exehead/Debug-lzma/exehead_lzma.h" #endif*/ int zlib_exeheader_size=sizeof(zlib_header_data); int bzip2_exeheader_size=sizeof(bzip2_header_data); +int lzma_exeheader_size=sizeof(lzma_header_data); int exeheader_size=0; int icondata_size=sizeof(icon_data)-22; diff --git a/Source/exedata.h b/Source/exedata.h index c4ed9db3..ceaf4872 100644 --- a/Source/exedata.h +++ b/Source/exedata.h @@ -3,12 +3,14 @@ extern int zlib_exeheader_size; extern int bzip2_exeheader_size; +extern int lzma_exeheader_size; extern int exeheader_size; extern int icondata_size; extern int unicondata_size; extern unsigned char zlib_header_data[]; extern unsigned char bzip2_header_data[]; +extern unsigned char lzma_header_data[]; extern unsigned char icon_data[]; extern unsigned char unicon_data[]; extern unsigned char bitmap1_data[630]; diff --git a/Source/exehead/config.h b/Source/exehead/config.h index e4309da6..8174ca27 100644 --- a/Source/exehead/config.h +++ b/Source/exehead/config.h @@ -74,6 +74,12 @@ // than zlib in whole mode usually. // #define NSIS_ZLIB_COMPRESS_WHOLE + // NSIS_LZMA_COMPRESS_WHOLE makes all install data in lzma installers + // compressed together. Runtime requirements are increased, but potential + // for compression is as well. Requires that the installer create a + // (potentially large) temporary file in the temp directory. + #define NSIS_LZMA_COMPRESS_WHOLE + // NSIS_BZIP2_COMPRESS_WHOLE makes all install data in bzip2 installers // compressed together. Runtime requirements are increased, but potential // for compression is as well. Requires that the installer create a @@ -286,7 +292,9 @@ #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT #ifndef NSIS_COMPRESS_USE_ZLIB #ifndef NSIS_COMPRESS_USE_BZIP2 - #error compression is enabled but both zlib and bzip2 are disabled. + #ifndef NSIS_COMPRESS_USE_LZMA + #error compression is enabled but zlib, bzip2 and lzma are disabled. + #endif #endif #endif #endif @@ -295,27 +303,39 @@ #ifdef NSIS_COMPRESS_USE_BZIP2 #error both zlib and bzip2 are enabled. #endif + #ifdef NSIS_COMPRESS_USE_LZMA + #error both zlib and lzma are enabled. + #endif + #endif + #ifdef NSIS_COMPRESS_USE_BZIP2 + #ifdef NSIS_COMPRESS_USE_LZMA + #error both bzip2 and lzma are enabled. + #endif #endif #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT #ifdef NSIS_COMPRESS_USE_ZLIB #ifdef NSIS_ZLIB_COMPRESS_WHOLE #define NSIS_COMPRESS_WHOLE - #ifdef NSIS_CONFIG_VISIBLE_SUPPORT - #ifndef _NSIS_CONFIG_VERIFYDIALOG - #define _NSIS_CONFIG_VERIFYDIALOG - #endif - #endif #endif #endif #ifdef NSIS_COMPRESS_USE_BZIP2 #ifdef NSIS_BZIP2_COMPRESS_WHOLE #define NSIS_COMPRESS_WHOLE - #ifdef NSIS_CONFIG_VISIBLE_SUPPORT - #ifndef _NSIS_CONFIG_VERIFYDIALOG - #define _NSIS_CONFIG_VERIFYDIALOG - #endif + #endif + #endif + + #ifdef NSIS_COMPRESS_USE_LZMA + #ifdef NSIS_LZMA_COMPRESS_WHOLE + #define NSIS_COMPRESS_WHOLE + #endif + #endif + + #ifdef NSIS_COMPRESS_WHOLE + #ifdef NSIS_CONFIG_VISIBLE_SUPPORT + #ifndef _NSIS_CONFIG_VERIFYDIALOG + #define _NSIS_CONFIG_VERIFYDIALOG #endif #endif #endif diff --git a/Source/exehead/exehead-lzma.dsp b/Source/exehead/exehead-lzma.dsp new file mode 100644 index 00000000..037e9007 --- /dev/null +++ b/Source/exehead/exehead-lzma.dsp @@ -0,0 +1,227 @@ +# Microsoft Developer Studio Project File - Name="exehead_lzma" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=exehead_lzma - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "exehead-lzma.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "exehead-lzma.mak" CFG="exehead_lzma - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "exehead_lzma - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release-lzma" +# PROP Intermediate_Dir "Release-lzma" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O1 /Oy /D "_WINDOWS" /D "EXEHEAD" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /D "NSIS_COMPRESS_USE_LZMA" /D ZEXPORT=__stdcall /FD /c +# SUBTRACT CPP /Fr /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib shell32.lib /nologo /entry:"WinMain" /subsystem:windows /pdb:none /map /machine:I386 /nodefaultlib /out:"Release-lzma/exehead_lzma.exe" /opt:nowin98 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=generating include file for makenssi +PostBuild_Cmds=bin2h Release-lzma\exehead_lzma.exe Release-lzma\exehead_lzma.h lzma_header_data +# End Special Build Tool +# Begin Target + +# Name "exehead_lzma - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "lzma" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\InBuffer.cpp +# ADD CPP /D "__STREAM_VERSION" +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZMA.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZMADecoder.cpp +# ADD CPP /D "__STREAM_VERSION" +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZMADecoder.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZMALenCoder.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZMALiteralCoder.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZOutWindow.cpp +# ADD CPP /D "__STREAM_VERSION" +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\LZOutWindow.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\RangeCoder.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\RangeCoderBit.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\RangeCoderBitTree.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\RangeCoderOpt.h +# End Source File +# Begin Source File + +SOURCE=..\7zip\7zip\Compress\LZMA_SMALL\Types.h +# End Source File +# End Group +# Begin Group "lzmaNSIS" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\7zip\lzmaNSIS.cpp +# ADD CPP /D "__STREAM_VERSION" +# End Source File +# Begin Source File + +SOURCE=..\7zip\lzmaNSIS.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\bgbg.c +# End Source File +# Begin Source File + +SOURCE=..\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\exec.c +# End Source File +# Begin Source File + +SOURCE=.\fileform.c +# End Source File +# Begin Source File + +SOURCE=.\Main.c +# End Source File +# Begin Source File + +SOURCE=.\Ui.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\exec.h +# End Source File +# Begin Source File + +SOURCE=.\fileform.h +# End Source File +# Begin Source File + +SOURCE=.\lang.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\state.h +# End Source File +# Begin Source File + +SOURCE=.\ui.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\nsis.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\uninst.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index ac9d2b66..1f12b628 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -12,6 +12,16 @@ #include "../zlib/zlib.h" #endif +#ifdef NSIS_COMPRESS_USE_LZMA +#include "../7zip/lzmaNSIS.h" +#define z_stream CLZMAState +#define inflateInit(x) lzmaInit(x) +#define inflateReset(x) lzmaInit(x) +#define inflate(x) lzmaDecompress(x) +#define Z_OK 0 +#define Z_STREAM_END 1 +#endif + #ifdef NSIS_COMPRESS_USE_BZIP2 #include "../bzip2/bzlib.h" @@ -353,7 +363,9 @@ int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen) ltc = tc; } - if (!u) break; + // if there's no output, more input is needed + if (!u) + break; if (!outbuf) { diff --git a/Source/makenssi.cpp b/Source/makenssi.cpp index 6f329b43..fc5c89d3 100644 --- a/Source/makenssi.cpp +++ b/Source/makenssi.cpp @@ -1,4 +1,4 @@ -const char *NSIS_VERSION="v2.0b4"; +const char *NSIS_VERSION="v2.0b5 (CVS)"; /* Nullsoft Scriptable Install System (NSIS) @@ -113,6 +113,7 @@ int main(int argc, char **argv) "\n" "Portions Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler (zlib).\n" "Includes portions derived from bzip2 (see documentation for details).\n" + "Portions Copyright (C) 1999-2003 Igor Pavlov (lzma).\n" "Contributors: nnop@newmail.ru, Ryan Geiss, Andras Varga, Drew Davidson, Peter Windridge, Dave Laundon, Robert Rainwater, Yaroslav Faybishenko, Jeff Doozan, Amir Szekely, Ximon Eighteen, et al.\n\n",NSIS_VERSION); fflush(g_output); } diff --git a/Source/makenssi.dsp b/Source/makenssi.dsp index 6b708ed3..cb3dfe8f 100644 --- a/Source/makenssi.dsp +++ b/Source/makenssi.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /FD /c # SUBTRACT CPP /Fr /YX /Yc /Yu # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /FD /c # SUBTRACT BASE CPP /Fr /YX /Yc /Yu -# ADD CPP /nologo /MLd /W3 /GX /ZI /Od /D "_CONSOLE" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fr /FD /Zm200 /c +# ADD CPP /nologo /MLd /W3 /GX /ZI /Od /D "_CONSOLE" /D "WIN32" /D "_DEBUG" /D "_MBCS" /Fr /FD /Zm200 /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -147,6 +147,48 @@ SOURCE=.\bzip2\compress.c SOURCE=.\bzip2\huffman.c # End Source File # End Group +# Begin Group "7zip" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\7zip\7zGuids.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zip\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Compress\LZ\LZInWindow.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Compress\LZMA\LZMAEncoder.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Compress\LZMA\LZMALen.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Compress\LZMA\LZMALiteral.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Common\OutBuffer.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# Begin Source File + +SOURCE=.\7zip\7zip\Compress\RangeCoder\RangeCoderBit.cpp +# ADD CPP /D "COMPRESS_MF_BT" +# End Source File +# End Group # Begin Source File SOURCE=.\build.cpp @@ -215,6 +257,10 @@ SOURCE=.\cbzip2.h # End Source File # Begin Source File +SOURCE=.\clzma.h +# End Source File +# Begin Source File + SOURCE=.\compressor.h # End Source File # Begin Source File diff --git a/Source/makenssi.dsw b/Source/makenssi.dsw index 3d044acb..ecf651d0 100644 --- a/Source/makenssi.dsw +++ b/Source/makenssi.dsw @@ -15,6 +15,18 @@ Package=<4> ############################################################################### +Project: "exehead_lzma"=".\exehead\exehead-lzma.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "exehead_zlib"=".\exehead\exehead-zlib.dsp" - Package Owner=<4> Package=<5> @@ -41,6 +53,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name exehead_zlib End Project Dependency + Begin Project Dependency + Project_Dep_Name exehead_lzma + End Project Dependency }}} ############################################################################### diff --git a/Source/script.cpp b/Source/script.cpp index faddf53c..288e7738 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -1934,7 +1934,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) if (k == -1) PRINTHELP() SCRIPT_MSG("XPStyle: %s\n", line.gettoken_str(1)); init_res_editor(); - char* szXPManifest = k ? 0 : "Nullsoft Install System v2.0b4"; + char* szXPManifest = k ? 0 : "Nullsoft Install System v2.0b5 (CVS)"; res_editor->UpdateResource(MAKEINTRESOURCE(24), MAKEINTRESOURCE(1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (unsigned char*)szXPManifest, k ? 0 : lstrlen(szXPManifest)); } catch (exception& err) { @@ -2201,7 +2201,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) ERROR_MSG("%s expects 2 parameters, got 3.\n",line.gettoken_str(0)); PRINTHELP(); } - int k=line.gettoken_enum(a,"zlib\0bzip2\0"); + int k=line.gettoken_enum(a,"zlib\0bzip2\0lzma\0"); switch (k) { case 0: // JF> should handle the state of going from bzip2 back to zlib: compressor = &zlib_compressor; @@ -2217,11 +2217,11 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } memcpy(header_data_new,zlib_header_data,zlib_exeheader_size); - #ifdef NSIS_ZLIB_COMPRESS_WHOLE +#ifdef NSIS_ZLIB_COMPRESS_WHOLE build_compress_whole=true; - #else +#else build_compress_whole=false; - #endif +#endif break; case 1: compressor=&bzip2_compressor; @@ -2237,12 +2237,32 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } memcpy(header_data_new,bzip2_header_data,bzip2_exeheader_size); - #ifdef NSIS_BZIP2_COMPRESS_WHOLE +#ifdef NSIS_BZIP2_COMPRESS_WHOLE build_compress_whole=true; - #else +#else build_compress_whole=false; - #endif +#endif break; + case 2: + compressor = &lzma_compressor; + free(header_data_new); + header_data_new=(unsigned char*)malloc(lzma_exeheader_size); + exeheader_size_new=lzma_exeheader_size; + exeheader_size=lzma_exeheader_size; + + if (!header_data_new) + { + ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n",exeheader_size_new); + extern void quit(); quit(); + } + + memcpy(header_data_new, lzma_header_data, lzma_exeheader_size); +#ifdef NSIS_LZMA_COMPRESS_WHOLE + build_compress_whole=true; +#else + build_compress_whole=false; +#endif + break; default: PRINTHELP(); } @@ -2590,6 +2610,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) unselected = 1; a++; } + else if (line.getnumtokens() > 3) + PRINTHELP(); SCRIPT_MSG("Section: \"%s\"",line.gettoken_str(a)); if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1)); SCRIPT_MSG("\n"); @@ -2764,6 +2786,33 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } SCRIPT_MSG("FileBufSize: %smb (%d bytes)\n",line.gettoken_str(1),build_filebuflen); return PS_OK; + case TOK_SETCOMPRESSIONLEVEL: + { + if (compressor == &lzma_compressor) + warning_fl("SetCompressionLevel: compressor is set to LZMA. Effectively ignored."); + if (build_compressor_set && build_compress_whole) + warning_fl("SetCompressionLevel: data already compressed in compress whole mode. Effectively ignored."); + + int s; + build_compress_level=line.gettoken_int(1,&s); + if (!s || build_compress_level < 0 || build_compress_level > 9) PRINTHELP(); + SCRIPT_MSG("SetCompressionLevel: %u\n", build_compress_level); + } + return PS_OK; + case TOK_SETCOMPRESSORDICTSIZE: + { + if (compressor != &lzma_compressor) + warning_fl("SetCompressorDictSize: compressor is not set to LZMA. Effectively ignored."); + if (build_compressor_set && build_compress_whole) + warning_fl("SetCompressorDictSize: data already compressed in compress whole mode. Effectively ignored."); + + int s; + build_compress_dict_size=line.gettoken_int(1,&s); + if (!s) PRINTHELP(); + SCRIPT_MSG("SetCompressorDictSize: %u mb\n", build_compress_dict_size); + build_compress_dict_size <<= 20; + } + return PS_OK; case TOK_ADDSIZE: { int s; @@ -4760,7 +4809,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) SCRIPT_MSG("/IMGID=%d ",ent.offsets[1]); } else if (!stricmp(line.gettoken_str(i),"/RESIZETOFIT")) { - ent.offsets[2]=1; + ent.offsets[2]=1; // must be 1 or 0 SCRIPT_MSG("/RESIZETOFIT "); } else if (!ent.offsets[0]) { diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 026aa5d2..746cea78 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -64,7 +64,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec"}, {TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)"}, {TOK_FILE,"File",1,-1,"[/nonfatal] [/a] ([/r] filespec [...]|/oname=outfile one_file_only)"}, -{TOK_FILEBUFSIZE,"FileBufSize",1,0,"buf_size"}, +{TOK_FILEBUFSIZE,"FileBufSize",1,0,"buf_size_mb"}, {TOK_FLUSHINI,"FlushINI",1,0,"ini_file"}, {TOK_RESERVEFILE,"ReserveFile",1,-1,"[/nonfatal] [/r] file [file...]"}, {TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)"}, @@ -157,6 +157,8 @@ static tokenType tokenlist[TOK__LAST] = {TOK_SETBRANDINGIMAGE,"SetBrandingImage",1,2,"[/IMGID=image_item_id_in_dialog] [/RESIZETOFIT] bitmap.bmp"}, {TOK_SETCOMPRESS,"SetCompress",1,0,"(off|auto|force)"}, {TOK_SETCOMPRESSOR,"SetCompressor",1,1,"[/FINAL] (zlib|bzip2)"}, +{TOK_SETCOMPRESSORDICTSIZE,"SetCompressorDictSize",1,0,"dict_size_mb"}, +{TOK_SETCOMPRESSIONLEVEL,"SetCompressionLevel",1,0,"level_0-9"}, {TOK_SETDATESAVE,"SetDateSave",1,0,"(off|on)"}, {TOK_SETDETAILSVIEW,"SetDetailsView",1,0,"(hide|show)"}, {TOK_SETDETAILSPRINT,"SetDetailsPrint",1,0,"(none|listonly|textonly|both)"}, diff --git a/Source/tokens.h b/Source/tokens.h index 5103bec6..abc37010 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -65,6 +65,8 @@ enum TOK_SETCOMPRESS, TOK_DBOPTIMIZE, TOK_SETCOMPRESSOR, + TOK_SETCOMPRESSORDICTSIZE, + TOK_SETCOMPRESSIONLEVEL, TOK_FILEBUFSIZE, // system "preprocessor"ish tokens