4.44 beta

This commit is contained in:
Igor Pavlov
2007-01-20 00:00:00 +00:00
committed by Kornel Lesiński
parent 804edc5756
commit d9666cf046
1331 changed files with 10535 additions and 13791 deletions

61
CPP/7zip/Compress/Lzx/Lzx.h Executable file
View File

@@ -0,0 +1,61 @@
// Lzx.h
#ifndef __COMPRESS_LZX_H
#define __COMPRESS_LZX_H
namespace NCompress {
namespace NLzx {
const int kNumHuffmanBits = 16;
const UInt32 kNumRepDistances = 3;
const UInt32 kNumLenSlots = 8;
const UInt32 kMatchMinLen = 2;
const UInt32 kNumLenSymbols = 249;
const UInt32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1;
const int kNumAlignBits = 3;
const UInt32 kAlignTableSize = 1 << kNumAlignBits;
const UInt32 kNumPosSlots = 50;
const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots;
const UInt32 kMainTableSize = 256 + kNumPosLenSlots;
const UInt32 kLevelTableSize = 20;
const UInt32 kMaxTableSize = kMainTableSize;
const int kNumBlockTypeBits = 3;
const int kBlockTypeVerbatim = 1;
const int kBlockTypeAligned = 2;
const int kBlockTypeUncompressed = 3;
const int kUncompressedBlockSizeNumBits = 24;
const int kNumBitsForPreTreeLevel = 4;
const int kLevelSymbolZeros = 17;
const int kLevelSymbolZerosBig = 18;
const int kLevelSymbolSame = 19;
const int kLevelSymbolZerosStartValue = 4;
const int kLevelSymbolZerosNumBits = 4;
const int kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue +
(1 << kLevelSymbolZerosNumBits);
const int kLevelSymbolZerosBigNumBits = 5;
const int kLevelSymbolSameNumBits = 1;
const int kLevelSymbolSameStartValue = 4;
const int kNumBitsForAlignLevel = 3;
const int kNumDictionaryBitsMin = 15;
const int kNumDictionaryBitsMax = 21;
const UInt32 kDictionarySizeMax = (1 << kNumDictionaryBitsMax);
const int kNumLinearPosSlotBits = 17;
const UInt32 kNumPowerPosSlots = 0x26;
}}
#endif

View File

@@ -0,0 +1,90 @@
// Lzx86Converter.cpp
#include "StdAfx.h"
#include "Common/Defs.h"
#include "Lzx86Converter.h"
namespace NCompress {
namespace NLzx {
static const int kResidue = 6 + 4;
void Cx86ConvertOutStream::MakeTranslation()
{
if (m_Pos <= kResidue)
return;
UInt32 numBytes = m_Pos - kResidue;
Byte *buffer = m_Buffer;
for (UInt32 i = 0; i < numBytes;)
{
if (buffer[i++] == 0xE8)
{
Int32 absValue = 0;
int j;
for(j = 0; j < 4; j++)
absValue += (UInt32)buffer[i + j] << (j * 8);
Int32 pos = (Int32)(m_ProcessedSize + i - 1);
if (absValue >= -pos && absValue < (Int32)m_TranslationSize)
{
UInt32 offset = (absValue >= 0) ?
absValue - pos :
absValue + m_TranslationSize;
for(j = 0; j < 4; j++)
{
buffer[i + j] = (Byte)(offset & 0xFF);
offset >>= 8;
}
}
i += 4;
}
}
}
STDMETHODIMP Cx86ConvertOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize != NULL)
*processedSize = 0;
if (!m_TranslationMode)
return m_Stream->Write(data, size, processedSize);
UInt32 realProcessedSize = 0;
while (realProcessedSize < size)
{
UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - m_Pos);
memmove(m_Buffer + m_Pos, (const Byte *)data + realProcessedSize, writeSize);
m_Pos += writeSize;
realProcessedSize += writeSize;
if (m_Pos == kUncompressedBlockSize)
{
RINOK(Flush());
}
}
if (processedSize != NULL)
*processedSize = realProcessedSize;
return S_OK;
}
HRESULT Cx86ConvertOutStream::Flush()
{
if (m_Pos == 0)
return S_OK;
if (m_TranslationMode)
MakeTranslation();
UInt32 pos = 0;
do
{
UInt32 processed;
RINOK(m_Stream->Write(m_Buffer + pos, m_Pos - pos, &processed));
if (processed == 0)
return E_FAIL;
pos += processed;
}
while(pos < m_Pos);
m_ProcessedSize += m_Pos;
m_Pos = 0;
m_TranslationMode = (m_TranslationMode && (m_ProcessedSize < (1 << 30)));
return S_OK;
}
}}

View File

@@ -0,0 +1,45 @@
// Lzx/x86Converter.h
#ifndef __LZX_X86CONVERTER_H
#define __LZX_X86CONVERTER_H
#include "Common/MyCom.h"
#include "../../IStream.h"
namespace NCompress {
namespace NLzx {
const int kUncompressedBlockSize = 1 << 15;
class Cx86ConvertOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> m_Stream;
UInt32 m_ProcessedSize;
UInt32 m_Pos;
UInt32 m_TranslationSize;
bool m_TranslationMode;
Byte m_Buffer[kUncompressedBlockSize];
void MakeTranslation();
public:
void SetStream(ISequentialOutStream *outStream) { m_Stream = outStream; }
void ReleaseStream() { m_Stream.Release(); }
void Init(bool translationMode, UInt32 translationSize)
{
m_TranslationMode = translationMode;
m_TranslationSize = translationSize;
m_ProcessedSize = 0;
m_Pos = 0;
}
HRESULT Flush();
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
}}
#endif

View File

@@ -0,0 +1,382 @@
// LzxDecoder.cpp
#include "StdAfx.h"
#include "LzxDecoder.h"
#include "Common/Defs.h"
#include "Common/Alloc.h"
#include "Windows/Defs.h"
namespace NCompress {
namespace NLzx {
const int kLenIdNeedInit = -2;
CDecoder::CDecoder():
_keepHistory(false),
m_AlignPos(0)
{
m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;
m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;
}
void CDecoder::ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
m_x86ConvertOutStreamSpec->ReleaseStream();
}
STDMETHODIMP CDecoder::Flush()
{
RINOK(m_OutWindowStream.Flush());
return m_x86ConvertOutStreamSpec->Flush();
}
UInt32 CDecoder::ReadBits(UInt32 numBits) { return m_InBitStream.ReadBits(numBits); }
#define RIF(x) { if (!(x)) return false; }
bool CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols)
{
Byte levelLevels[kLevelTableSize];
UInt32 i;
for (i = 0; i < kLevelTableSize; i++)
levelLevels[i] = (Byte)ReadBits(kNumBitsForPreTreeLevel);
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
int num = 0;
Byte symbol = 0;
for (i = 0; i < numSymbols;)
{
if (num != 0)
{
lastLevels[i] = newLevels[i] = symbol;
i++;
num--;
continue;
}
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number == kLevelSymbolZeros)
{
num = kLevelSymbolZerosStartValue + ReadBits(kLevelSymbolZerosNumBits);
symbol = 0;
}
else if (number == kLevelSymbolZerosBig)
{
num = kLevelSymbolZerosBigStartValue + ReadBits(kLevelSymbolZerosBigNumBits);
symbol = 0;
}
else if (number == kLevelSymbolSame || number <= kNumHuffmanBits)
{
if (number <= kNumHuffmanBits)
num = 1;
else
{
num = kLevelSymbolSameStartValue + ReadBits(kLevelSymbolSameNumBits);
number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number > kNumHuffmanBits)
return false;
}
symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1));
}
else
return false;
}
return true;
}
bool CDecoder::ReadTables(void)
{
Byte newLevels[kMaxTableSize];
{
int blockType = (int)ReadBits(kNumBlockTypeBits);
if (blockType > kBlockTypeUncompressed)
return false;
m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);
if (m_IsUncompressedBlock)
{
m_InBitStream.ReadBits(16 - m_InBitStream.GetBitPosition());
if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))
return false;
m_RepDistances[0]--;
for (int i = 1; i < kNumRepDistances; i++)
{
UInt32 rep = 0;
for (int j = 0; j < 4; j++)
rep |= (UInt32)m_InBitStream.DirectReadByte() << (8 * j);
m_RepDistances[i] = rep - 1;
}
return true;
}
m_AlignIsUsed = (blockType == kBlockTypeAligned);
if (m_AlignIsUsed)
{
for(int i = 0; i < kAlignTableSize; i++)
newLevels[i] = (Byte)ReadBits(kNumBitsForAlignLevel);
RIF(m_AlignDecoder.SetCodeLengths(newLevels));
}
}
RIF(ReadTable(m_LastMainLevels, newLevels, 256));
RIF(ReadTable(m_LastMainLevels + 256, newLevels + 256, m_NumPosLenSlots));
for (UInt32 i = 256 + m_NumPosLenSlots; i < kMainTableSize; i++)
newLevels[i] = 0;
RIF(m_MainDecoder.SetCodeLengths(newLevels));
RIF(ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols));
return m_LenDecoder.SetCodeLengths(newLevels);
}
class CDecoderFlusher
{
CDecoder *m_Decoder;
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {}
~CDecoderFlusher()
{
if (NeedFlush)
m_Decoder->Flush();
m_Decoder->ReleaseStreams();
}
};
void CDecoder::ClearPrevLevels()
{
int i;
for (i = 0; i < kMainTableSize; i++)
m_LastMainLevels[i] = 0;
for (i = 0; i < kNumLenSymbols; i++)
m_LastLenLevels[i] = 0;
};
HRESULT CDecoder::CodeSpec(UInt32 curSize)
{
if (_remainLen == kLenIdNeedInit)
{
_remainLen = 0;
if (_keepHistory && m_IsUncompressedBlock && m_UnCompressedBlockSize > 0)
m_InBitStream.InitDirect();
else
m_InBitStream.InitNormal();
if (!_keepHistory)
{
m_UnCompressedBlockSize = 0;
ClearPrevLevels();
UInt32 i86TranslationSize = 0;
bool translationMode = (ReadBits(1) != 0);
if (translationMode)
{
i86TranslationSize = ReadBits(16) << 16;
i86TranslationSize |= ReadBits(16);
}
m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
for(int i = 0 ; i < kNumRepDistances; i++)
m_RepDistances[i] = 0;
}
}
if (curSize == 0)
return S_OK;
while(_remainLen > 0 && curSize > 0)
{
m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0]));
_remainLen--;
curSize--;
}
while(curSize > 0)
{
if (m_UnCompressedBlockSize == 0)
if (!ReadTables())
return S_FALSE;
UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize);
curSize -= next;
m_UnCompressedBlockSize -= next;
if (m_IsUncompressedBlock)
{
while(next > 0)
{
m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte());
next--;
}
if (m_UnCompressedBlockSize == 0)
{
m_InBitStream.Align(m_AlignPos);
// m_AlignPos = 0;
}
}
else while(next > 0)
{
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number < 256)
{
m_OutWindowStream.PutByte((Byte)number);
next--;
}
else
{
UInt32 posLenSlot = number - 256;
if (posLenSlot >= m_NumPosLenSlots)
return S_FALSE;
UInt32 posSlot = posLenSlot / kNumLenSlots;
UInt32 lenSlot = posLenSlot % kNumLenSlots;
UInt32 len = kMatchMinLen + lenSlot;
if (lenSlot == kNumLenSlots - 1)
{
UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream);
if (lenTemp >= kNumLenSymbols)
return S_FALSE;
len += lenTemp;
}
if (posSlot < kNumRepDistances)
{
UInt32 distance = m_RepDistances[posSlot];
m_RepDistances[posSlot] = m_RepDistances[0];
m_RepDistances[0] = distance;
}
else
{
UInt32 distance;
int numDirectBits;
if (posSlot < kNumPowerPosSlots)
{
numDirectBits = (posSlot >> 1) - 1;
distance = ((2 | (posSlot & 1)) << numDirectBits);
}
else
{
numDirectBits = kNumLinearPosSlotBits;
distance = ((posSlot - 0x22) << kNumLinearPosSlotBits);
}
if (m_AlignIsUsed && numDirectBits >= kNumAlignBits)
{
distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits);
UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream);
if (alignTemp >= kAlignTableSize)
return S_FALSE;
distance += alignTemp;
}
else
distance += m_InBitStream.ReadBits(numDirectBits);
m_RepDistances[2] = m_RepDistances[1];
m_RepDistances[1] = m_RepDistances[0];
m_RepDistances[0] = distance - kNumRepDistances;
}
UInt32 locLen = len;
if (locLen > next)
locLen = next;
if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen))
return S_FALSE;
len -= locLen;
next -= locLen;
if (len != 0)
{
_remainLen = len;
return S_OK;
}
}
}
}
return S_OK;
}
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (outSize == NULL)
return E_INVALIDARG;
UInt64 size = *outSize;
RINOK(SetInStream(inStream));
m_x86ConvertOutStreamSpec->SetStream(outStream);
m_OutWindowStream.SetStream(m_x86ConvertOutStream);
RINOK(SetOutStreamSize(outSize));
CDecoderFlusher flusher(this);
const UInt64 start = m_OutWindowStream.GetProcessedSize();
for (;;)
{
UInt32 curSize = 1 << 18;
UInt64 rem = size - (m_OutWindowStream.GetProcessedSize() - start);
if (curSize > rem)
curSize = (UInt32)rem;
if (curSize == 0)
break;
RINOK(CodeSpec(curSize));
if (progress != NULL)
{
UInt64 inSize = m_InBitStream.GetProcessedSize();
UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
}
}
flusher.NeedFlush = false;
return Flush();
}
HRESULT CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
{
m_InBitStream.SetStream(inStream);
return S_OK;
}
STDMETHODIMP CDecoder::ReleaseInStream()
{
m_InBitStream.ReleaseStream();
return S_OK;
}
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
if (outSize == NULL)
return E_FAIL;
_remainLen = kLenIdNeedInit;
m_OutWindowStream.Init(_keepHistory);
return S_OK;
}
HRESULT CDecoder::SetParams(int numDictBits)
{
if (numDictBits < kNumDictionaryBitsMin || numDictBits > kNumDictionaryBitsMax)
return E_INVALIDARG;
UInt32 numPosSlots;
if (numDictBits < 20)
numPosSlots = 30 + (numDictBits - 15) * 2;
else if (numDictBits == 20)
numPosSlots = 42;
else
numPosSlots = 50;
m_NumPosLenSlots = numPosSlots * kNumLenSlots;
if (!m_OutWindowStream.Create(kDictionarySizeMax))
return E_OUTOFMEMORY;
if (!m_InBitStream.Create(1 << 16))
return E_OUTOFMEMORY;
return S_OK;
}
}}

View File

@@ -0,0 +1,181 @@
// LzxDecoder.h
#ifndef __LZXDECODER_H
#define __LZXDECODER_H
#include "../../ICoder.h"
#include "../../Compress/Huffman/HuffmanDecoder.h"
#include "../../Compress/LZ/LZOutWindow.h"
#include "../../Common/InBuffer.h"
#include "Lzx.h"
#include "Lzx86Converter.h"
namespace NCompress {
namespace NLzx {
namespace NBitStream {
const int kNumBigValueBits = 8 * 4;
const int kNumValueBits = 17;
const UInt32 kBitDecoderValueMask = (1 << kNumValueBits) - 1;
class CDecoder
{
CInBuffer m_Stream;
UInt32 m_Value;
int m_BitPos;
public:
CDecoder() {}
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); }
void ReleaseStream() { m_Stream.ReleaseStream(); }
void InitNormal()
{
m_Stream.Init();
m_BitPos = kNumBigValueBits;
Normalize();
}
void InitDirect()
{
m_Stream.Init();
m_BitPos = kNumBigValueBits;
}
UInt64 GetProcessedSize() const
{ return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }
int GetBitPosition() const { return m_BitPos & 0xF; }
void Normalize()
{
for (;m_BitPos >= 16; m_BitPos -= 16)
{
Byte b0 = m_Stream.ReadByte();
Byte b1 = m_Stream.ReadByte();
m_Value = (m_Value << 8) | b1;
m_Value = (m_Value << 8) | b0;
}
}
UInt32 GetValue(int numBits) const
{
return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >>
(kNumValueBits - numBits);
}
void MovePos(UInt32 numBits)
{
m_BitPos += numBits;
Normalize();
}
UInt32 ReadBits(int numBits)
{
UInt32 res = GetValue(numBits);
MovePos(numBits);
return res;
}
UInt32 ReadBitsBig(int numBits)
{
UInt32 numBits0 = numBits / 2;
UInt32 numBits1 = numBits - numBits0;
UInt32 res = ReadBits(numBits0) << numBits1;
return res + ReadBits(numBits1);
}
bool ReadUInt32(UInt32 &v)
{
if (m_BitPos != 0)
return false;
v = ((m_Value >> 16) & 0xFFFF) | ((m_Value << 16) & 0xFFFF0000);
m_BitPos = kNumBigValueBits;
return true;
}
Byte DirectReadByte() { return m_Stream.ReadByte(); }
void Align(int alignPos)
{
if (((m_Stream.GetProcessedSize() + alignPos) & 1) != 0)
m_Stream.ReadByte();
Normalize();
}
};
}
class CDecoder :
public ICompressCoder,
public CMyUnknownImp
{
NBitStream::CDecoder m_InBitStream;
CLZOutWindow m_OutWindowStream;
UInt32 m_RepDistances[kNumRepDistances];
UInt32 m_NumPosLenSlots;
bool m_IsUncompressedBlock;
bool m_AlignIsUsed;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kNumLenSymbols> m_LenDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
Byte m_LastMainLevels[kMainTableSize];
Byte m_LastLenLevels[kNumLenSymbols];
Cx86ConvertOutStream *m_x86ConvertOutStreamSpec;
CMyComPtr<ISequentialOutStream> m_x86ConvertOutStream;
UInt32 m_UnCompressedBlockSize;
bool _keepHistory;
int _remainLen;
int m_AlignPos;
UInt32 ReadBits(UInt32 numBits);
bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols);
bool ReadTables();
void ClearPrevLevels();
HRESULT CodeSpec(UInt32 size);
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
public:
CDecoder();
MY_UNKNOWN_IMP
void ReleaseStreams();
STDMETHOD(Flush)();
// ICompressCoder interface
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
HRESULT SetParams(int numDictBits);
void SetKeepHistory(bool keepHistory, int alignPos)
{
_keepHistory = keepHistory;
m_AlignPos = alignPos;
}
};
}}
#endif

8
CPP/7zip/Compress/Lzx/StdAfx.h Executable file
View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif