- 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
This commit is contained in:
kichik 2003-11-24 00:08:58 +00:00
parent 320cefa4b0
commit 594c3ed0f6
84 changed files with 8083 additions and 41 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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<IMatchFinderCallback> _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

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -0,0 +1,8 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#endif

View file

@ -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

View file

@ -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;
}
}}

View file

@ -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<kNumMoveBits> 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<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
NRangeCoder::CReverseBitTreeDecoder2<kNumMoveBits> _posDecoders[kNumPosModels];
NRangeCoder::CReverseBitTreeDecoder<kNumMoveBits, kNumAlignBits> _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

File diff suppressed because it is too large Load diff

View file

@ -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<kNumMoveBits> 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<IMatchFinder> _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<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
NRangeCoder::CReverseBitTreeEncoder2<kNumMoveBits> _posEncoders[kNumPosModels];
NRangeCoder::CReverseBitTreeEncoder2<kNumMoveBits> _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

View file

@ -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;
}
}}}

View file

@ -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<kNumMoveBits> _choice;
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLenBits> _lowCoder[kNumPosStatesEncodingMax];
NRangeCoder::CBitEncoder<kNumMoveBits> _choice2;
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _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<kNumMoveBits> _choice;
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLenBits> _lowCoder[kNumPosStatesMax];
NRangeCoder::CBitDecoder<kNumMoveBits> _choice2;
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax];
NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _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

View file

@ -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;
};
}}}

View file

@ -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<kNumMoveBits> _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<kNumMoveBits> _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

View file

@ -0,0 +1,8 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#endif

View file

@ -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

View file

@ -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

View file

@ -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 <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "../../../../exehead/util.h"
#ifdef __cplusplus
}
#endif
#define LZMAAlloc my_GlobalAlloc
#define LZMAFree GlobalFree
#define LZMAMemCopy mini_memcpy
#endif

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,39 @@
#include <Windows.h>
#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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,17 @@
// Common/Types.h
#ifndef __COMMON_TYPES_H
#define __COMMON_TYPES_H
#ifdef WIN32
#include <basetsd.h>
#else
typedef unsigned int UINT32;
#endif
#ifndef _WINDOWS_
typedef unsigned char BYTE;
#endif
#endif

View file

@ -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

View file

@ -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;
}}

View file

@ -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 <int aNumMoveBits>
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 <int aNumMoveBits>
class CBitEncoder: public CBitModel<aNumMoveBits>
{
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 <int aNumMoveBits>
class CBitDecoder: public CBitModel<aNumMoveBits>
{
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

View file

@ -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 <int numMoveBits> class CMyBitEncoder:
public NCompression::NArithmetic::CBitEncoder<numMoveBits> {};
template <int numMoveBits> class CMyBitDecoder:
public NCompression::NArithmetic::CBitDecoder<numMoveBits> {};
*/
//////////////////////////
// CBitTreeEncoder
template <int numMoveBits, UINT32 NumBitLevels>
class CBitTreeEncoder
{
CBitEncoder<numMoveBits> 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 <int numMoveBits, UINT32 NumBitLevels>
class CBitTreeDecoder
{
CBitDecoder<numMoveBits> 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 <int numMoveBits>
class CReverseBitTreeEncoder2
{
CBitEncoder<numMoveBits> *Models;
UINT32 NumBitLevels;
public:
CReverseBitTreeEncoder2(): Models(0) { }
~CReverseBitTreeEncoder2() { delete []Models; }
void Create(UINT32 numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new CBitEncoder<numMoveBits>[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 <int numMoveBits, int numBitLevels>
class CReverseBitTreeEncoder: public CReverseBitTreeEncoder2<numMoveBits>
{
public:
CReverseBitTreeEncoder()
{ Create(numBitLevels); }
};
*/
////////////////////////////////
// CReverseBitTreeDecoder
template <int numMoveBits>
class CReverseBitTreeDecoder2
{
CBitDecoder<numMoveBits> *Models;
UINT32 NumBitLevels;
public:
CReverseBitTreeDecoder2(): Models(0) { }
~CReverseBitTreeDecoder2() { delete []Models; }
void Create(UINT32 numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new CBitDecoder<numMoveBits>[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 <int numMoveBits, UINT32 NumBitLevels>
class CReverseBitTreeDecoder
{
CBitDecoder<numMoveBits> 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 <int numMoveBits>
class CBitTreeEncoder2
{
NCompression::NArithmetic::CBitEncoder<numMoveBits> *Models;
UINT32 NumBitLevels;
public:
bool Create(UINT32 numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new NCompression::NArithmetic::CBitEncoder<numMoveBits>[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 <int numMoveBits>
class CBitTreeDecoder2
{
NCompression::NArithmetic::CBitDecoder<numMoveBits> *Models;
UINT32 NumBitLevels;
public:
bool Create(UINT32 numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new NCompression::NArithmetic::CBitDecoder<numMoveBits>[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

View file

@ -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

View file

@ -0,0 +1,8 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#endif