4.33 beta

This commit is contained in:
Igor Pavlov
2006-02-05 00:00:00 +00:00
committed by Kornel Lesiński
parent e8d0636d7a
commit 02516d3fce
80 changed files with 2185 additions and 3957 deletions

View File

@@ -229,7 +229,7 @@ private:
_multiThread = false;
_copyMode = false;
_defaultDicSize = (1 << 21);
_defaultDicSize = (1 << 22);
_defaultAlgorithm = 1;
_defaultFastBytes = 32;
_defaultMatchFinder = L"BT4";

View File

@@ -67,30 +67,39 @@ const wchar_t *kPpmdMethodName = L"PPMd";
const wchar_t *kDeflateMethodName = L"Deflate";
const wchar_t *kDeflate64MethodName = L"Deflate64";
const UInt32 kAlgorithmForX7 = 2;
const UInt32 kDicSizeForX7 = 1 << 23;
const UInt32 kFastBytesForX7 = 64;
static const wchar_t *kMatchFinderX1 = L"HC4";
static const wchar_t *kMatchFinderX3 = L"HC4";
const UInt32 kAlgorithmForX9 = 2;
const UInt32 kDicSizeForX9 = 1 << 25;
const UInt32 kFastBytesForX9 = 64;
static const wchar_t *kMatchFinderForX9 = L"BT4b";
static const UInt32 kAlgorithmX1 = 0;
static const UInt32 kAlgorithmX3 = 0;
static const UInt32 kAlgorithmX7 = 1;
static const UInt32 kAlgorithmX9 = 1;
const UInt32 kAlgorithmForFast = 0;
const UInt32 kDicSizeForFast = 1 << 15;
static const wchar_t *kMatchFinderForFast = L"HC3";
static const UInt32 kDicSizeX1 = 1 << 16;
static const UInt32 kDicSizeX3 = 1 << 20;
static const UInt32 kDicSizeX7 = 1 << 24;
static const UInt32 kDicSizeX9 = 1 << 26;
const UInt32 kPpmdMemSizeX1 = (1 << 22);
const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kFastBytesX7 = 64;
static const UInt32 kFastBytesX9 = 64;
const UInt32 kPpmdMemSizeX7 = (1 << 26);
const UInt32 kPpmdOrderX7 = 16;
static const UInt32 kPpmdMemSizeX1 = (1 << 22);
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
static const UInt32 kPpmdMemSizeX9 = (192 << 20);
const UInt32 kPpmdMemSizeX9 = (192 << 20);
const UInt32 kPpmdOrderX9 = 32;
static const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kPpmdOrderX7 = 16;
static const UInt32 kPpmdOrderX9 = 32;
const UInt32 kDeflateFastBytesForX7 = 64;
const UInt32 kDeflatePassesForX7 = 3;
static const UInt32 kDeflateFastBytesX7 = 64;
static const UInt32 kDeflatePassesX7 = 3;
static const UInt32 kDeflateFastBytesX9 = 64;
static const UInt32 kDeflatePassesX9 = 10;
static const UInt32 kNumBZip2PassesX1 = 1;
static const UInt32 kNumBZip2PassesX7 = 2;
static const UInt32 kNumBZip2PassesX9 = 7;
const wchar_t *kDefaultMethodName = kLZMAMethodName;
@@ -221,7 +230,7 @@ HRESULT CHandler::SetCompressionMethod(
{
CProperty property;
property.PropID = NCoderPropID::kAlgorithm;
property.Value = kAlgorithmForX9;
property.Value = kAlgorithmX9;
oneMethodInfo.CoderProperties.Add(property);
}
{
@@ -1016,11 +1025,23 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
_copyMode = true;
_defaultBZip2Passes = 1;
}
else if (_level < 3)
{
_defaultAlgorithm = kAlgorithmX1;
_defaultDicSize = kDicSizeX1;
_defaultMatchFinder = kMatchFinderX1;
_defaultBZip2Passes = 1;
_defaultPpmdMemSize = kPpmdMemSizeX1;
_defaultPpmdOrder = kPpmdOrderX1;
}
else if (_level < 5)
{
_defaultAlgorithm = kAlgorithmForFast;
_defaultDicSize = kDicSizeForFast;
_defaultMatchFinder = kMatchFinderForFast;
_defaultAlgorithm = kAlgorithmX3;
_defaultDicSize = kDicSizeX3;
_defaultMatchFinder = kMatchFinderX3;
_defaultBZip2Passes = 1;
_defaultPpmdMemSize = kPpmdMemSizeX1;
@@ -1033,30 +1054,29 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else if(_level < 9)
{
_defaultAlgorithm = kAlgorithmForX7;
_defaultDicSize = kDicSizeForX7;
_defaultFastBytes = kFastBytesForX7;
_defaultBZip2Passes = 2;
_defaultAlgorithm = kAlgorithmX7;
_defaultDicSize = kDicSizeX7;
_defaultFastBytes = kFastBytesX7;
_defaultBZip2Passes = kNumBZip2PassesX7;
_defaultPpmdMemSize = kPpmdMemSizeX7;
_defaultPpmdOrder = kPpmdOrderX7;
_defaultDeflateFastBytes = kDeflateFastBytesForX7;
_defaultDeflatePasses = kDeflatePassesForX7;
_defaultDeflateFastBytes = kDeflateFastBytesX7;
_defaultDeflatePasses = kDeflatePassesX7;
}
else
{
_defaultAlgorithm = kAlgorithmForX9;
_defaultDicSize = kDicSizeForX9;
_defaultFastBytes = kFastBytesForX9;
_defaultMatchFinder = kMatchFinderForX9;
_defaultBZip2Passes = 7;
_defaultAlgorithm = kAlgorithmX9;
_defaultDicSize = kDicSizeX9;
_defaultFastBytes = kFastBytesX9;
_defaultBZip2Passes = kNumBZip2PassesX9;
_defaultPpmdMemSize = kPpmdMemSizeX9;
_defaultPpmdOrder = kPpmdOrderX9;
_defaultDeflateFastBytes = kDeflateFastBytesForX7;
_defaultDeflatePasses = kDeflatePassesForX7;
_defaultDeflateFastBytes = kDeflateFastBytesX9;
_defaultDeflatePasses = kDeflatePassesX9;
}
continue;
}

View File

@@ -244,7 +244,7 @@ private:
CRecordVector<bool> &digestsDefined,
CRecordVector<UInt32> &digests);
HRESULT CInArchive::ReadStreamsInfo(
HRESULT ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UInt64 &dataOffset,
CRecordVector<UInt64> &packSizes,

View File

@@ -65,10 +65,10 @@ private:
UInt64 m_PackSize;
CMyComPtr<IInStream> m_Stream;
CCompressionMethodMode m_Method;
UInt32 m_Level;
void InitMethodProperties()
{
m_Method.NumPasses = 1;
m_Method.NumFastBytes = 32;
m_Level = m_Method.NumPasses = m_Method.NumFastBytes = 0xFFFFFFFF;
}
};

View File

@@ -20,6 +20,15 @@ using namespace NTime;
namespace NArchive {
namespace NGZip {
static const UInt32 kNumPassesX1 = 1;
static const UInt32 kNumPassesX7 = 3;
static const UInt32 kNumPassesX9 = 10;
static const UInt32 kNumFastBytesX1 = 32;
static const UInt32 kNumFastBytesX7 = 64;
static const UInt32 kNumFastBytesX9 = 128;
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kUnix;
@@ -117,6 +126,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
size = propVariant.uhVal.QuadPart;
}
newItem.UnPackSize32 = (UInt32)size;
UInt32 level = m_Level;
if (level == 0xFFFFFFFF)
level = 5;
if (m_Method.NumPasses == 0xFFFFFFFF)
m_Method.NumPasses = (level >= 9 ? kNumPassesX9 : (level >= 7 ? kNumPassesX7 : kNumPassesX1));
if (m_Method.NumFastBytes == 0xFFFFFFFF)
m_Method.NumFastBytes = (level >= 9 ? kNumFastBytesX9 : (level >= 7 ? kNumFastBytesX7 : kNumFastBytesX1));
return UpdateArchive(m_Stream, size, outStream, newItem,
m_Method, itemIndex, updateCallback);
}
@@ -138,12 +157,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return CopyStreams(m_Stream, outStream, updateCallback);
}
static const UInt32 kMatchFastLenNormal = 32;
static const UInt32 kMatchFastLenMX = 64;
static const UInt32 kNumPassesNormal = 1;
static const UInt32 kNumPassesMX = 3;
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
InitMethodProperties();
@@ -176,15 +189,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else
return E_INVALIDARG;
if (level < 7)
{
InitMethodProperties();
}
else
{
m_Method.NumPasses = kNumPassesMX;
m_Method.NumFastBytes = kMatchFastLenMX;
}
m_Level = level;
continue;
}
else if (name == L"PASS")
@@ -192,7 +197,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_UI4)
return E_INVALIDARG;
m_Method.NumPasses = value.ulVal;
if (m_Method.NumPasses < 1 || m_Method.NumPasses > 10)
if (m_Method.NumPasses < 1)
return E_INVALIDARG;
}
else if (name == L"FB")
@@ -200,10 +205,6 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_UI4)
return E_INVALIDARG;
m_Method.NumFastBytes = value.ulVal;
/*
if (m_Method.NumFastBytes < 3 || m_Method.NumFastBytes > 255)
return E_INVALIDARG;
*/
}
else
return E_INVALIDARG;

View File

@@ -24,14 +24,16 @@ namespace NZip {
static const UInt32 kNumDeflatePassesX1 = 1;
static const UInt32 kNumDeflatePassesX7 = 3;
static const UInt32 kNumDeflatePassesX9 = 10;
static const UInt32 kNumFastBytesX1 = 32;
static const UInt32 kNumFastBytesX7 = 64;
static const UInt32 kNumFastBytesX9 = 128;
static const UInt32 kNumBZip2PassesX1 = 1;
static const UInt32 kNumBZip2PassesX7 = 2;
static const UInt32 kNumBZip2PassesX9 = 7;
static const UInt32 kNumFastBytesX1 = 32;
static const UInt32 kNumFastBytesX7 = 64;
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kDOS;
@@ -203,7 +205,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (options.NumPasses == 0xFFFFFFFF)
{
if (isDeflate)
options.NumPasses = (level >= 7 ? kNumDeflatePassesX7 : kNumDeflatePassesX1);
options.NumPasses = (level >= 9 ? kNumDeflatePassesX9 :
(level >= 7 ? kNumDeflatePassesX7 : kNumDeflatePassesX1));
else if (isBZip2)
options.NumPasses = (level >= 9 ? kNumBZip2PassesX9 :
(level >= 7 ? kNumBZip2PassesX7 : kNumBZip2PassesX1));
@@ -213,7 +216,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (options.NumFastBytes == 0xFFFFFFFF)
{
if (isDeflate)
options.NumFastBytes = (level >= 7 ? kNumFastBytesX7 : kNumFastBytesX1);
options.NumFastBytes = (level >= 9 ? kNumFastBytesX9 : (level >= 7 ? kNumFastBytesX7 : kNumFastBytesX1));
}
return Update(m_Items, updateItems, outStream,
@@ -295,7 +298,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
{
if (value.vt != VT_UI4)
return E_INVALIDARG;
if (value.ulVal < 1 || value.ulVal > 10)
if (value.ulVal < 1)
return E_INVALIDARG;
m_NumPasses = value.ulVal;
}

View File

@@ -167,7 +167,7 @@ static HRESULT UpdateOneFile(IInStream *inStream,
}
}
}
fileHeader.SetEncrypted(options.PasswordIsDefined);
fileHeader.SetEncrypted(!isDirectory && options.PasswordIsDefined);
/*
fileHeader.CommentSize = (updateItem.Commented) ?
WORD(updateItem.CommentRange.Size) : 0;

View File

@@ -8,39 +8,22 @@
namespace NStream {
namespace NLSBF {
void CEncoder::WriteBits(UInt32 value, UInt32 numBits)
void CEncoder::WriteBits(UInt32 value, int numBits)
{
while(numBits > 0)
{
UInt32 numNewBits = MyMin(numBits, m_BitPos);
numBits -= numNewBits;
UInt32 mask = (1 << numNewBits) - 1;
m_CurByte |= (value & mask) << (8 - m_BitPos);
value >>= numNewBits;
m_BitPos -= numNewBits;
if (m_BitPos == 0)
if (numBits < m_BitPos)
{
m_Stream.WriteByte(m_CurByte);
m_CurByte |= (value & ((1 << numBits) - 1)) << (8 - m_BitPos);
m_BitPos -= numBits;
return;
}
numBits -= m_BitPos;
m_Stream.WriteByte((Byte)(m_CurByte | (value << (8 - m_BitPos))));
value >>= m_BitPos;
m_BitPos = 8;
m_CurByte = 0;
}
}
}
void CReverseEncoder::WriteBits(UInt32 value, UInt32 numBits)
{
UInt32 reverseValue = 0;
for(UInt32 i = 0; i < numBits; i++)
{
reverseValue <<= 1;
reverseValue |= value & 1;
value >>= 1;
}
m_Encoder->WriteBits(reverseValue, numBits);
}
}}

View File

@@ -12,7 +12,7 @@ namespace NLSBF {
class CEncoder
{
COutBuffer m_Stream;
UInt32 m_BitPos;
int m_BitPos;
Byte m_CurByte;
public:
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
@@ -26,23 +26,25 @@ public:
}
HRESULT Flush()
{
if(m_BitPos < 8)
WriteBits(0, m_BitPos);
FlushByte();
return m_Stream.Flush();
}
void WriteBits(UInt32 value, UInt32 numBits);
void FlushByte()
{
if(m_BitPos < 8)
m_Stream.WriteByte(m_CurByte);
m_BitPos = 8;
m_CurByte = 0;
}
void WriteBits(UInt32 value, int numBits);
UInt32 GetBitPosition() const { return (8 - m_BitPos); }
UInt64 GetProcessedSize() const {
return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) /8; }
void WriteByte(Byte b) { m_Stream.WriteByte(b);}
};
class CReverseEncoder
{
CEncoder *m_Encoder;
public:
void Init(CEncoder *encoder) { m_Encoder = encoder; }
void WriteBits(UInt32 value, UInt32 numBits);
};
}}

View File

@@ -37,21 +37,17 @@ public:
{
while(numBits > 0)
{
int numNewBits = MyMin(numBits, m_BitPos);
numBits -= numNewBits;
m_CurByte <<= numNewBits;
UInt32 newBits = value >> numBits;
m_CurByte |= Byte(newBits);
value -= (newBits << numBits);
m_BitPos -= numNewBits;
if (m_BitPos == 0)
if (numBits < m_BitPos)
{
m_Stream.WriteByte(m_CurByte);
m_BitPos = 8;
m_CurByte |= ((Byte)value << (m_BitPos -= numBits));
return;
}
numBits -= m_BitPos;
UInt32 newBits = (value >> numBits);
value -= (newBits << numBits);
m_Stream.WriteByte(m_CurByte | (Byte)newBits);
m_BitPos = 8;
m_CurByte = 0;
}
}
UInt64 GetProcessedSize() const {

View File

@@ -58,7 +58,7 @@ class CCoder :
UInt32 c_table[CTABLESIZE];
UInt32 pt_table[PTABLESIZE];
void CCoder::ReleaseStreams()
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
@@ -79,8 +79,7 @@ class CCoder :
};
friend class CCoderReleaser;
void MakeTable(int nchar, Byte *bitlen, int tablebits,
UInt32 *table, int tablesize);
void MakeTable(int nchar, Byte *bitlen, int tablebits, UInt32 *table, int tablesize);
void read_c_len();
void read_pt_len(int nn, int nbit, int i_special);

View File

@@ -26,7 +26,7 @@ class CCoder :
CLZOutWindow m_OutWindowStream;
NStream::NMSBF::CDecoder<CInBuffer> m_InBitStream;
void CCoder::ReleaseStreams()
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();

View File

@@ -291,9 +291,5 @@ SOURCE=.\DeflateEncoder.cpp
SOURCE=.\DeflateEncoder.h
# End Source File
# Begin Source File
SOURCE=.\DeflateExtConst.h
# End Source File
# End Target
# End Project

View File

@@ -3,34 +3,34 @@
#ifndef __DEFLATE_CONST_H
#define __DEFLATE_CONST_H
#include "DeflateExtConst.h"
namespace NCompress {
namespace NDeflate {
const UInt32 kLenTableSize = 29;
const int kNumHuffmanBits = 15;
const UInt32 kStaticDistTableSize = 32;
const UInt32 kStaticLenTableSize = 31;
const UInt32 kHistorySize32 = (1 << 15);
const UInt32 kHistorySize64 = (1 << 16);
const UInt32 kReadTableNumber = 0x100;
const UInt32 kMatchNumber = kReadTableNumber + 1;
const UInt32 kDistTableSize32 = 30;
const UInt32 kDistTableSize64 = 32;
const UInt32 kMainTableSize = kMatchNumber + kLenTableSize; //298;
const UInt32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298;
const UInt32 kNumLenSymbols32 = 256;
const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255.
const UInt32 kNumLenSymbolsMax = kNumLenSymbols32;
const UInt32 kDistTableStart = kMainTableSize;
const UInt32 kNumLenSlots = 29;
const UInt32 kHeapTablesSizesSum32 = kMainTableSize + kDistTableSize32;
const UInt32 kHeapTablesSizesSum64 = kMainTableSize + kDistTableSize64;
const UInt32 kFixedDistTableSize = 32;
const UInt32 kFixedLenTableSize = 31;
const UInt32 kSymbolEndOfBlock = 0x100;
const UInt32 kSymbolMatch = kSymbolEndOfBlock + 1;
const UInt32 kMainTableSize = kSymbolMatch + kNumLenSlots;
const UInt32 kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize;
const UInt32 kLevelTableSize = 19;
const UInt32 kMaxTableSize32 = kHeapTablesSizesSum32; // test it
const UInt32 kMaxTableSize64 = kHeapTablesSizesSum64; // test it
const UInt32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize;
const UInt32 kTableDirectLevels = 16;
const UInt32 kTableLevelRepNumber = kTableDirectLevels;
const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
@@ -38,15 +38,15 @@ const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
const UInt32 kLevelMask = 0xF;
const Byte kLenStart32[kLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255};
const Byte kLenStart64[kLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0};
const Byte kLenStart32[kFixedLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255, 0, 0};
const Byte kLenStart64[kFixedLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0, 0, 0};
const Byte kLenDirectBits32[kLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
const Byte kLenDirectBits64[kLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16};
const Byte kLenDirectBits32[kFixedLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0};
const Byte kLenDirectBits64[kFixedLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, 0, 0};
const UInt32 kDistStart[kDistTableSize64] =
{0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,
@@ -54,13 +54,14 @@ const UInt32 kDistStart[kDistTableSize64] =
const Byte kDistDirectBits[kDistTableSize64] =
{0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14};
const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
const Byte kLevelDirectBits[3] = {2, 3, 7};
const Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
const UInt32 kMatchMinLen = 3;
const UInt32 kMatchMaxLen32 = kNumLenCombinations32 + kMatchMinLen - 1; //256 + 2; test it
const UInt32 kMatchMaxLen64 = kNumLenCombinations64 + kMatchMinLen - 1; //255 + 2; test it
const UInt32 kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2
const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2
const UInt32 kMatchMaxLen = kMatchMaxLen32;
const int kFinalBlockFieldSize = 1;
@@ -81,23 +82,52 @@ namespace NBlockType
{
kStored = 0,
kFixedHuffman = 1,
kDynamicHuffman = 2,
kReserved = 3
kDynamicHuffman = 2
};
}
const UInt32 kDeflateNumberOfLengthCodesFieldSize = 5;
const UInt32 kDeflateNumberOfDistanceCodesFieldSize = 5;
const UInt32 kDeflateNumberOfLevelCodesFieldSize = 4;
const int kNumLenCodesFieldSize = 5;
const int kNumDistCodesFieldSize = 5;
const int kNumLevelCodesFieldSize = 4;
const UInt32 kDeflateNumberOfLitLenCodesMin = 257;
const UInt32 kNumLitLenCodesMin = 257;
const UInt32 kNumDistCodesMin = 1;
const UInt32 kNumLevelCodesMin = 4;
const UInt32 kDeflateNumberOfDistanceCodesMin = 1;
const UInt32 kDeflateNumberOfLevelCodesMin = 4;
const int kLevelFieldSize = 3;
const UInt32 kDeflateLevelCodeFieldSize = 3;
const int kStoredBlockLengthFieldSize = 16;
const UInt32 kDeflateStoredBlockLengthFieldSizeSize = 16;
struct CLevels
{
Byte litLenLevels[kFixedMainTableSize];
Byte distLevels[kFixedDistTableSize];
void SubClear()
{
UInt32 i;
for(i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++)
litLenLevels[i] = 0;
for(i = 0; i < kFixedDistTableSize; i++)
distLevels[i] = 0;
}
void SetFixedLevels()
{
int i;
for (i = 0; i < 144; i++)
litLenLevels[i] = 8;
for (; i < 256; i++)
litLenLevels[i] = 9;
for (; i < 280; i++)
litLenLevels[i] = 7;
for (; i < 288; i++)
litLenLevels[i] = 8;
for (i = 0; i < kFixedDistTableSize; i++) // test it: InfoZip only uses kDistTableSize
distLevels[i] = 5;
}
};
}}

View File

@@ -8,47 +8,58 @@ namespace NCompress {
namespace NDeflate {
namespace NDecoder {
const int kLenIdFinished = -1;
const int kLenIdNeedInit = -2;
static const int kLenIdFinished = -1;
static const int kLenIdNeedInit = -2;
CCoder::CCoder(bool deflate64Mode): _deflate64Mode(deflate64Mode), _keepHistory(false) {}
void CCoder::DeCodeLevelTable(Byte *newLevels, int numLevels)
UInt32 CCoder::ReadBits(int numBits)
{
return m_InBitStream.ReadBits(numBits);
}
bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)
{
int i = 0;
while (i < numLevels)
do
{
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number < kTableDirectLevels)
newLevels[i++] = Byte(number);
else
values[i++] = (Byte)number;
else if (number < kLevelTableSize)
{
if (number == kTableLevelRepNumber)
{
int t = m_InBitStream.ReadBits(2) + 3;
for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)
newLevels[i] = newLevels[i - 1];
if (i == 0)
return false;
int num = ReadBits(2) + 3;
for (; num > 0 && i < numSymbols; num--, i++)
values[i] = values[i - 1];
}
else
{
int num;
if (number == kTableLevel0Number)
num = m_InBitStream.ReadBits(3) + 3;
num = ReadBits(3) + 3;
else
num = m_InBitStream.ReadBits(7) + 11;
for (;num > 0 && i < numLevels; num--)
newLevels[i++] = 0;
num = ReadBits(7) + 11;
for (;num > 0 && i < numSymbols; num--)
values[i++] = 0;
}
}
else
return false;
}
while(i < numSymbols);
return true;
}
#define RIF(x) { if (!(x)) return false; }
bool CCoder::ReadTables(void)
{
m_FinalBlock = (m_InBitStream.ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
int blockType = m_InBitStream.ReadBits(kBlockTypeFieldSize);
m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
UInt32 blockType = ReadBits(kBlockTypeFieldSize);
if (blockType > NBlockType::kDynamicHuffman)
return false;
@@ -56,67 +67,52 @@ bool CCoder::ReadTables(void)
{
m_StoredMode = true;
UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
UInt32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0;
if (numBitsForAlign > 0)
m_InBitStream.ReadBits(numBitsForAlign);
m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize);
UInt16 onesComplementReverse = ~(UInt16)(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize));
return (m_StoredBlockSize == onesComplementReverse);
int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
ReadBits(numBitsForAlign);
m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);
return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));
}
m_StoredMode = false;
Byte litLenLevels[kStaticMainTableSize];
Byte distLevels[kStaticDistTableSize];
CLevels levels;
if (blockType == NBlockType::kFixedHuffman)
{
int i;
for (i = 0; i < 144; i++)
litLenLevels[i] = 8;
for (; i < 256; i++)
litLenLevels[i] = 9;
for (; i < 280; i++)
litLenLevels[i] = 7;
for (; i < 288; i++) // make a complete, but wrong code set
litLenLevels[i] = 8;
for (i = 0; i < kStaticDistTableSize; i++) // test it: InfoZip only uses kDistTableSize
distLevels[i] = 5;
levels.SetFixedLevels();
_numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
}
else // (blockType == kDynamicHuffman)
else
{
int numLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) +
kDeflateNumberOfLitLenCodesMin;
int numDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) +
kDeflateNumberOfDistanceCodesMin;
int numLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) +
kDeflateNumberOfLevelCodesMin;
int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
_numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
int numLevels = _deflate64Mode ? kHeapTablesSizesSum64 : kHeapTablesSizesSum32;
if (!_deflate64Mode)
if (_numDistLevels > kDistTableSize32)
return false;
Byte levelLevels[kLevelTableSize];
for (int i = 0; i < kLevelTableSize; i++)
{
int position = kCodeLengthAlphabetOrder[i];
if(i < numLevelCodes)
levelLevels[position] = Byte(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize));
levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
else
levelLevels[position] = 0;
}
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
Byte tmpLevels[kStaticMaxTableSize];
DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels);
Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))
return false;
memmove(litLenLevels, tmpLevels, numLitLenLevels);
memset(litLenLevels + numLitLenLevels, 0, kStaticMainTableSize - numLitLenLevels);
memmove(distLevels, tmpLevels + numLitLenLevels, numDistLevels);
memset(distLevels + numDistLevels, 0, kStaticDistTableSize - numDistLevels);
levels.SubClear();
memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
}
RIF(m_MainDecoder.SetCodeLengths(litLenLevels));
return m_DistDecoder.SetCodeLengths(distLevels);
RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));
return m_DistDecoder.SetCodeLengths(levels.distLevels);
}
HRESULT CCoder::CodeSpec(UInt32 curSize)
@@ -126,10 +122,8 @@ HRESULT CCoder::CodeSpec(UInt32 curSize)
if (_remainLen == kLenIdNeedInit)
{
if (!_keepHistory)
{
if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
return E_OUTOFMEMORY;
}
if (!m_InBitStream.Create(1 << 17))
return E_OUTOFMEMORY;
m_OutWindowStream.Init(_keepHistory);
@@ -177,15 +171,20 @@ HRESULT CCoder::CodeSpec(UInt32 curSize)
return S_FALSE;
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number < 256)
if (number < 0x100)
{
m_OutWindowStream.PutByte((Byte)number);
curSize--;
continue;
}
else if (number >= kMatchNumber)
else if (number == kSymbolEndOfBlock)
{
number -= kMatchNumber;
_needReadTable = true;
break;
}
else if (number < kMainTableSize)
{
number -= kSymbolMatch;
UInt32 len;
{
int numBits;
@@ -205,7 +204,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize)
if (locLen > curSize)
locLen = (UInt32)curSize;
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
if (number >= kStaticDistTableSize)
if (number >= _numDistLevels)
return S_FALSE;
UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
if (!m_OutWindowStream.CopyBlock(distance, locLen))
@@ -214,16 +213,11 @@ HRESULT CCoder::CodeSpec(UInt32 curSize)
len -= locLen;
if (len != 0)
{
_remainLen = (int)len;
_remainLen = (Int32)len;
_rep0 = distance;
break;
}
}
else if (number == kReadTableNumber)
{
_needReadTable = true;
break;
}
else
return S_FALSE;
}
@@ -258,8 +252,8 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
break;
if (progress != NULL)
{
UInt64 inSize = m_InBitStream.GetProcessedSize();
UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
const UInt64 inSize = m_InBitStream.GetProcessedSize();
const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
}
}

View File

@@ -11,25 +11,12 @@
#include "../LZ/LZOutWindow.h"
#include "../Huffman/HuffmanDecoder.h"
#include "DeflateExtConst.h"
#include "DeflateConst.h"
namespace NCompress {
namespace NDeflate {
namespace NDecoder {
class CException
{
public:
enum ECauseType
{
kData
} m_Cause;
CException(ECauseType aCause): m_Cause(aCause) {}
};
typedef NStream::NLSBF::CDecoder<CInBuffer> CInBit;
class CCoder:
public ICompressCoder,
public ICompressGetInStreamProcessedSize,
@@ -41,26 +28,30 @@ class CCoder:
public CMyUnknownImp
{
CLZOutWindow m_OutWindowStream;
CInBit m_InBitStream;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticMainTableSize> m_MainDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticDistTableSize> m_DistDecoder;
NStream::NLSBF::CDecoder<CInBuffer> m_InBitStream;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize> m_MainDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedDistTableSize> m_DistDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
UInt32 m_StoredBlockSize;
bool m_FinalBlock;
bool m_StoredMode;
UInt32 _numDistLevels;
bool _deflate64Mode;
bool _keepHistory;
int _remainLen;
Int32 _remainLen;
UInt32 _rep0;
bool _needReadTable;
UInt32 ReadBits(int numBits);
void DeCodeLevelTable(Byte *newLevels, int numLevels);
bool DeCodeLevelTable(Byte *values, int numSymbols);
bool ReadTables();
void CCoder::ReleaseStreams()
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
ReleaseInStream();

View File

File diff suppressed because it is too large Load Diff

View File

@@ -18,25 +18,10 @@ namespace NEncoder {
struct CCodeValue
{
Byte Flag;
union
{
Byte Imm;
Byte Len;
};
UInt16 Len;
UInt16 Pos;
};
class COnePosMatches
{
public:
UInt16 *MatchDistances;
UInt16 LongestMatchLength;
UInt16 LongestMatchDistance;
void Init(UInt16 *matchDistances)
{
MatchDistances = matchDistances;
};
void SetAsLiteral() { Len = (1 << 15); }
bool IsLiteral() const { return ((Len & (1 << 15)) != 0); }
};
struct COptimal
@@ -46,76 +31,107 @@ struct COptimal
UInt16 BackPrev;
};
const int kNumOpts = 0x1000;
const UInt32 kNumOptsBase = 1 << 12;
const UInt32 kNumOpts = kNumOptsBase + kMatchMaxLen;
class CCoder;
struct CTables: public CLevels
{
bool UseSubBlocks;
bool StoreMode;
bool StaticMode;
UInt32 BlockSizeRes;
UInt32 m_Pos;
void InitStructures();
};
class CCoder
{
UInt32 m_FinderPos;
COptimal m_Optimum[kNumOpts];
CMyComPtr<IMatchFinder> m_MatchFinder;
NStream::NLSBF::CEncoder m_OutStream;
NStream::NLSBF::CReverseEncoder m_ReverseOutStream;
NCompression::NHuffman::CEncoder m_MainCoder;
NCompression::NHuffman::CEncoder m_DistCoder;
NCompression::NHuffman::CEncoder m_LevelCoder;
Byte m_LastLevels[kMaxTableSize64];
UInt32 m_ValueIndex;
public:
CCodeValue *m_Values;
UInt32 m_OptimumEndIndex;
UInt32 m_OptimumCurrentIndex;
UInt32 m_AdditionalOffset;
UInt32 m_LongestMatchLength;
UInt32 m_LongestMatchDistance;
UInt16 *m_MatchDistances;
UInt32 m_NumFastBytes;
Byte m_LiteralPrices[256];
Byte m_LenPrices[kNumLenCombinations32];
Byte m_PosPrices[kDistTableSize64];
UInt32 m_CurrentBlockUncompressedSize;
COnePosMatches *m_OnePosMatchesArray;
UInt16 *m_OnePosMatchesMemory;
UInt16 *m_DistanceMemory;
UInt32 m_Pos;
UInt64 m_BlockStartPostion;
int m_NumPasses;
int m_NumDivPasses;
bool m_CheckStatic;
bool m_IsMultiPass;
UInt32 m_ValueBlockSize;
bool m_Created;
bool _deflate64Mode;
UInt32 m_NumLenCombinations;
UInt32 m_MatchMaxLen;
const Byte *m_LenStart;
const Byte *m_LenDirectBits;
HRESULT Create();
void Free();
bool m_Created;
bool m_Deflate64Mode;
void GetBacks(UInt32 aPos);
NCompression::NHuffman::CEncoder MainCoder;
NCompression::NHuffman::CEncoder DistCoder;
NCompression::NHuffman::CEncoder LevelCoder;
void ReadGoodBacks();
Byte m_LevelLevels[kLevelTableSize];
int m_NumLitLenLevels;
int m_NumDistLevels;
UInt32 m_NumLevelCodes;
UInt32 m_ValueIndex;
bool m_SecondPass;
UInt32 m_AdditionalOffset;
UInt32 m_OptimumEndIndex;
UInt32 m_OptimumCurrentIndex;
Byte m_LiteralPrices[256];
Byte m_LenPrices[kNumLenSymbolsMax];
Byte m_PosPrices[kDistTableSize64];
CLevels m_NewLevels;
UInt32 BlockSizeRes;
CTables *m_Tables;
COptimal m_Optimum[kNumOpts];
void GetMatches();
void MovePos(UInt32 num);
UInt32 Backward(UInt32 &backRes, UInt32 cur);
UInt32 GetOptimal(UInt32 &backRes);
void InitStructures();
void CodeLevelTable(Byte *newLevels, int numLevels, bool codeMode);
int WriteTables(bool writeMode, bool finalBlock);
void CopyBackBlockOp(UInt32 distance, UInt32 length);
void CodeLevelTable(NStream::NLSBF::CEncoder *outStream, const Byte *levels, int numLevels);
void MakeTables();
UInt32 GetLzBlockPrice();
void TryBlock(bool staticMode);
UInt32 TryDynBlock(int tableIndex, UInt32 numPasses);
UInt32 TryFixedBlock(int tableIndex);
void SetPrices(const CLevels &levels);
void WriteBlock();
void WriteDynBlock(bool finalBlock);
void WriteFixedBlock(bool finalBlock);
HRESULT Create();
void Free();
void WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock);
void WriteTables(bool writeMode, bool finalBlock);
void WriteBlockData(bool writeMode, bool finalBlock);
void CCoder::ReleaseStreams()
void ReleaseStreams()
{
// m_MatchFinder.ReleaseStream();
m_OutStream.ReleaseStream();
@@ -129,6 +145,9 @@ class CCoder
};
friend class CCoderReleaser;
UInt32 GetBlockPrice(int tableIndex, int numDivPasses);
void CodeBlock(int tableIndex, bool finalBlock);
public:
CCoder(bool deflate64Mode = false);
~CCoder();

View File

@@ -1,25 +0,0 @@
// DeflateExtConst.h
#ifndef __DEFLATE_EXTCONST_H
#define __DEFLATE_EXTCONST_H
#include "Common/Types.h"
namespace NCompress {
namespace NDeflate {
// const UInt32 kDistTableSize = 30;
const UInt32 kDistTableSize32 = 30;
const UInt32 kDistTableSize64 = 32;
const UInt32 kHistorySize32 = 0x8000;
const UInt32 kHistorySize64 = 0x10000;
const UInt32 kNumLenCombinations32 = 256;
const UInt32 kNumLenCombinations64 = 255;
// don't change kNumLenCombinations64. It must be less than 255.
const UInt32 kNumHuffmanBits = 15;
}}
#endif

View File

@@ -315,4 +315,17 @@ void CEncoder::BuildTree(Byte *levels)
levels[n] = Byte(m_Items[n].Len);
}
void CEncoder::ReverseBits()
{
for (UInt32 symbol = 0; symbol < m_NumSymbols; symbol++)
{
CItem &item = m_Items[symbol];
UInt32 value = item.Code;
UInt32 reverseValue = 0;
for(UInt32 i = item.Len; i != 0; i--, value >>= 1)
reverseValue = (reverseValue << 1) | (value & 1);
item.Code = reverseValue;
}
}
}}

View File

@@ -55,12 +55,28 @@ public:
void AddSymbol(UInt32 symbol) { m_Items[symbol].Freq++; }
void SetFreqs(const UInt32 *freqs);
UInt32 GetPrice(const Byte *length) const
{
UInt32 price = 0;
for (UInt32 i = 0; i < m_NumSymbols; i++)
{
price += length[i] * m_Items[i].Freq;
if (m_ExtraBits && i >= m_ExtraBase)
price += m_ExtraBits[i - m_ExtraBase] * m_Items[i].Freq;
}
return price;
};
void SetFreq(UInt32 symbol, UInt32 value) { m_Items[symbol].Freq = value; };
void BuildTree(Byte *levels);
UInt32 GetBlockBitLength() const { return m_BlockBitLength; }
template <class TBitEncoder>
void CodeOneValue(TBitEncoder *bitEncoder, UInt32 symbol)
{ bitEncoder->WriteBits(m_Items[symbol].Code, m_Items[symbol].Len); }
void ReverseBits();
};
}}

View File

@@ -8,9 +8,8 @@ namespace BT_NAMESPACE {
typedef UInt32 CIndex;
const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
class CMatchFinderBinTree:
class CMatchFinder:
public IMatchFinder,
public IMatchFinderSetCallback,
public CLZInWindow,
public CMyUnknownImp
{
@@ -18,37 +17,36 @@ class CMatchFinderBinTree:
UInt32 _cyclicBufferSize; // it must be historySize + 1
UInt32 _matchMaxLen;
CIndex *_hash;
CIndex *_son;
UInt32 _hashMask;
UInt32 _cutValue;
CMyComPtr<IMatchFinderCallback> m_Callback;
UInt32 _hashSizeSum;
void Normalize();
void FreeThisClassMemory();
void FreeMemory();
MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
MY_UNKNOWN_IMP
STDMETHOD(Init)(ISequentialInStream *inStream);
STDMETHOD(SetStream)(ISequentialInStream *inStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(MovePos)();
STDMETHOD(Init)();
HRESULT MovePos();
STDMETHOD_(Byte, GetIndexByte)(Int32 index);
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
STDMETHOD_(UInt32, GetNumAvailableBytes)();
STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes);
STDMETHOD_(void, ChangeBufferPos)();
STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
STDMETHOD_(void, DummyLongestMatch)();
// IMatchFinderSetCallback
STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
virtual void BeforeMoveBlock();
virtual void AfterMoveBlock();
STDMETHOD(GetMatches)(UInt32 *distances);
STDMETHOD(Skip)(UInt32 num);
public:
CMatchFinderBinTree();
virtual ~CMatchFinderBinTree();
CMatchFinder();
virtual ~CMatchFinder();
void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
};

View File

@@ -3,10 +3,10 @@
#ifndef __BINTREE2_H
#define __BINTREE2_H
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT2
#include "BinTree.h"
#include "BinTreeMain.h"
#undef BT_NAMESPACE
#endif

View File

@@ -3,14 +3,14 @@
#ifndef __BINTREE3_H
#define __BINTREE3_H
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT3
#define HASH_ARRAY_2
#include "BinTree.h"
#include "BinTreeMain.h"
#undef HASH_ARRAY_2
#undef BT_NAMESPACE
#endif

View File

@@ -3,14 +3,14 @@
#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
#undef BT_NAMESPACE
#endif

View File

@@ -3,16 +3,16 @@
#ifndef __BINTREE4_H
#define __BINTREE4_H
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT4
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#include "BinTree.h"
#include "BinTreeMain.h"
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#undef BT_NAMESPACE
#endif

View File

@@ -1,20 +0,0 @@
// BinTree4b.h
#ifndef __BINTREE4B_H
#define __BINTREE4B_H
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT4B
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#define HASH_BIG
#include "BinTree.h"
#include "BinTreeMain.h"
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#undef HASH_BIG
#endif

View File

@@ -4,38 +4,49 @@
#include "../../../../Common/CRC.h"
#include "../../../../Common/Alloc.h"
#include "BinTree.h"
// #include <xmmintrin.h>
// It's for prefetch
// But prefetch doesn't give big gain in K8.
namespace BT_NAMESPACE {
#ifdef HASH_ARRAY_2
static const UInt32 kHash2Size = 1 << 10;
#define kNumHashDirectBytes 0
#ifdef HASH_ARRAY_3
static const UInt32 kNumHashDirectBytes = 0;
static const UInt32 kNumHashBytes = 4;
static const UInt32 kHash3Size = 1 << 18;
#ifdef HASH_BIG
static const UInt32 kHashSize = 1 << 23;
static const UInt32 kHash3Size = 1 << 16;
#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
static const UInt32 kHashSize = 0;
static const UInt32 kMinMatchCheck = kNumHashBytes;
static const UInt32 kStartMaxLen = 1;
#else
#ifdef HASH_ZIP
static const UInt32 kNumHashDirectBytes = 0;
#define kNumHashDirectBytes 0
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << 16;
static const UInt32 kMinMatchCheck = kNumHashBytes;
static const UInt32 kStartMaxLen = 1;
#else
#define THERE_ARE_DIRECT_HASH_BYTES
static const UInt32 kNumHashDirectBytes = 2;
#define kNumHashDirectBytes 2
static const UInt32 kNumHashBytes = 2;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
static const UInt32 kMinMatchCheck = kNumHashBytes + 1;
static const UInt32 kStartMaxLen = 1;
#endif
#endif
static const UInt32 kHashSizeSum = kHashSize
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
static const UInt32 kHash3Offset = kHash2Size;
#endif
#endif
static const UInt32 kFixHashSize = 0
#ifdef HASH_ARRAY_2
+ kHash2Size
#ifdef HASH_ARRAY_3
@@ -44,56 +55,86 @@ static const UInt32 kHashSizeSum = kHashSize
#endif
;
#ifdef HASH_ARRAY_2
static const UInt32 kHash2Offset = kHashSize;
#ifdef HASH_ARRAY_3
static const UInt32 kHash3Offset = kHashSize + kHash2Size;
#endif
#endif
CMatchFinderBinTree::CMatchFinderBinTree():
_hash(0),
_cutValue(0xFF)
CMatchFinder::CMatchFinder():
_hash(0)
{
}
void CMatchFinderBinTree::FreeThisClassMemory()
void CMatchFinder::FreeThisClassMemory()
{
BigFree(_hash);
_hash = 0;
}
void CMatchFinderBinTree::FreeMemory()
void CMatchFinder::FreeMemory()
{
FreeThisClassMemory();
CLZInWindow::Free();
}
CMatchFinderBinTree::~CMatchFinderBinTree()
CMatchFinder::~CMatchFinder()
{
FreeMemory();
}
STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
if (historySize > kMaxValForNormalize - 256)
{
FreeMemory();
return E_INVALIDARG;
}
_cutValue =
#ifdef _HASH_CHAIN
8 + (matchMaxLen >> 2);
#else
16 + (matchMaxLen >> 1);
#endif
UInt32 sizeReserv = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
if (CLZInWindow::Create(historySize + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter, sizeReserv))
{
if (historySize + 256 > kMaxValForNormalize)
{
FreeMemory();
return E_INVALIDARG;
}
_matchMaxLen = matchMaxLen;
UInt32 newCyclicBufferSize = historySize + 1;
if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
return S_OK;
FreeThisClassMemory();
_cyclicBufferSize = newCyclicBufferSize; // don't change it
_hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex));
UInt32 hs = kHashSize;
#ifdef HASH_ARRAY_2
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
{
#ifdef HASH_ARRAY_3
hs >>= 1;
#else
hs = (1 << 24) - 1;
#endif
}
_hashMask = hs;
hs++;
#endif
_hashSizeSum = hs + kFixHashSize;
UInt32 numItems = _hashSizeSum + _cyclicBufferSize
#ifndef _HASH_CHAIN
* 2
#endif
;
size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);
if (sizeInBytes / sizeof(CIndex) != numItems)
return E_OUTOFMEMORY;
_hash = (CIndex *)BigAlloc(sizeInBytes);
_son = _hash + _hashSizeSum;
if (_hash != 0)
return S_OK;
}
@@ -103,44 +144,47 @@ STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBuffe
static const UInt32 kEmptyHashValue = 0;
STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream)
STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)
{
RINOK(CLZInWindow::Init(stream));
for(UInt32 i = 0; i < kHashSizeSum; i++)
CLZInWindow::SetStream(stream);
return S_OK;
}
STDMETHODIMP CMatchFinder::Init()
{
RINOK(CLZInWindow::Init());
for(UInt32 i = 0; i < _hashSizeSum; i++)
_hash[i] = kEmptyHashValue;
_cyclicBufferPos = 0;
ReduceOffsets(-1);
return S_OK;
}
STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream()
STDMETHODIMP_(void) CMatchFinder::ReleaseStream()
{
// ReleaseStream();
}
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
{
UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
hash2Value = temp & (kHash2Size - 1);
hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
(kHashSize - 1);
}
#define HASH_CALC { \
UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \
hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }
#else // no HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
{
hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1);
return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2];
}
#define HASH_CALC { \
UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }
#endif // HASH_ARRAY_3
#else // no HASH_ARRAY_2
#ifdef HASH_ZIP
inline UInt32 Hash(const Byte *pointer)
{
return ((UInt32(pointer[0]) << 8) ^
CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
}
#else // no HASH_ZIP
inline UInt32 Hash(const Byte *pointer)
@@ -150,7 +194,7 @@ inline UInt32 Hash(const Byte *pointer)
#endif // HASH_ZIP
#endif // HASH_ARRAY_2
STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
@@ -158,104 +202,141 @@ STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
else
{
lenLimit = _streamPos - _pos;
if(lenLimit < kNumHashBytes)
return 0;
if(lenLimit < kMinMatchCheck)
{
distances[0] = 0;
return MovePos();
}
}
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
Byte *cur = _buffer + _pos;
int offset = 1;
UInt32 maxLen = 0;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
const Byte *cur = _buffer + _pos;
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
#ifdef HASH_ARRAY_2
UInt32 hash2Value;
#ifdef HASH_ARRAY_3
UInt32 hash3Value;
UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
#else
UInt32 hashValue = Hash(cur, hash2Value);
#endif
UInt32 hashValue;
HASH_CALC;
#else
UInt32 hashValue = Hash(cur);
#endif
UInt32 curMatch = _hash[hashValue];
UInt32 curMatch = _hash[kFixHashSize + hashValue];
#ifdef HASH_ARRAY_2
UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
UInt32 curMatch2 = _hash[hash2Value];
#ifdef HASH_ARRAY_3
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
#endif
_hash[kHash2Offset + hash2Value] = _pos;
distances[2] = 0xFFFFFFFF;
_hash[hash2Value] = _pos;
if(curMatch2 > matchMinPos)
if (_buffer[curMatch2] == cur[0])
{
distances[2] = _pos - curMatch2 - 1;
maxLen = 2;
distances[offset++] = maxLen = 2;
distances[offset++] = _pos - curMatch2 - 1;
}
#ifdef HASH_ARRAY_3
_hash[kHash3Offset + hash3Value] = _pos;
distances[3] = 0xFFFFFFFF;
if(curMatch3 > matchMinPos)
if (_buffer[curMatch3] == cur[0])
{
distances[3] = _pos - curMatch3 - 1;
maxLen = 3;
if (curMatch3 == curMatch2)
offset -= 2;
distances[offset++] = maxLen = 3;
distances[offset++] = _pos - curMatch3 - 1;
curMatch2 = curMatch3;
}
#endif
if (offset != 1 && curMatch2 == curMatch)
{
offset -= 2;
maxLen = kStartMaxLen;
}
#endif
_hash[hashValue] = _pos;
_hash[kFixHashSize + hashValue] = _pos;
CIndex *son = _hash + kHashSizeSum;
CIndex *son = _son;
#ifdef _HASH_CHAIN
son[_cyclicBufferPos] = curMatch;
#else
CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CIndex *ptr1 = son + (_cyclicBufferPos << 1);
distances[kNumHashBytes] = 0xFFFFFFFF;
#ifdef THERE_ARE_DIRECT_HASH_BYTES
if (lenLimit == kNumHashDirectBytes)
{
if(curMatch > matchMinPos)
while (maxLen < kNumHashDirectBytes)
distances[++maxLen] = _pos - curMatch - 1;
// We don't need tree in this case
}
else
#endif
{
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
#endif
#if kNumHashDirectBytes != 0
if(curMatch > matchMinPos)
{
if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])
{
distances[offset++] = maxLen = kNumHashDirectBytes;
distances[offset++] = _pos - curMatch - 1;
}
}
#endif
UInt32 count = _cutValue;
while(true)
{
if(curMatch <= matchMinPos || count-- == 0)
{
*ptr0 = kEmptyHashValue;
*ptr1 = kEmptyHashValue;
#ifndef _HASH_CHAIN
*ptr0 = *ptr1 = kEmptyHashValue;
#endif
break;
}
Byte *pb = _buffer + curMatch;
UInt32 len = MyMin(len0, len1);
do
{
if (pb[len] != cur[len])
break;
}
while(++len != lenLimit);
UInt32 delta = _pos - curMatch;
while (maxLen < len)
distances[++maxLen] = delta - 1;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CIndex *pair = son + (cyclicPos << 1);
CIndex *pair = son +
#ifdef _HASH_CHAIN
cyclicPos;
#else
(cyclicPos << 1);
#endif
if (len != lenLimit)
// _mm_prefetch((const char *)pair, _MM_HINT_T0);
const Byte *pb = _buffer + curMatch;
UInt32 len =
#ifdef _HASH_CHAIN
kNumHashDirectBytes;
if (pb[maxLen] == cur[maxLen])
#else
MyMin(len0, len1);
#endif
if (pb[len] == cur[len])
{
while(++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
distances[offset++] = maxLen = len;
distances[offset++] = delta - 1;
if (len == lenLimit)
{
#ifndef _HASH_CHAIN
*ptr1 = pair[0];
*ptr0 = pair[1];
#endif
break;
}
}
}
#ifdef _HASH_CHAIN
curMatch = *pair;
#else
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
@@ -270,80 +351,80 @@ STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
curMatch = *ptr0;
len0 = len;
}
}
else
{
*ptr1 = pair[0];
*ptr0 = pair[1];
break;
}
}
}
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
if (distances[4] < distances[3])
distances[3] = distances[4];
#endif
if (distances[3] < distances[2])
distances[2] = distances[3];
#endif
return maxLen;
}
distances[0] = offset - 1;
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
return S_OK;
}
STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
STDMETHODIMP CMatchFinder::Skip(UInt32 num)
{
do
{
#ifdef _HASH_CHAIN
if (_streamPos - _pos < kNumHashBytes)
{
RINOK(MovePos());
continue;
}
#else
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if(lenLimit < kNumHashBytes)
return;
if(lenLimit < kMinMatchCheck)
{
RINOK(MovePos());
continue;
}
}
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
Byte *cur = _buffer + _pos;
#endif
const Byte *cur = _buffer + _pos;
#ifdef HASH_ARRAY_2
UInt32 hash2Value;
#ifdef HASH_ARRAY_3
UInt32 hash3Value;
UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
UInt32 hashValue;
HASH_CALC;
_hash[kHash3Offset + hash3Value] = _pos;
#else
UInt32 hashValue = Hash(cur, hash2Value);
UInt32 hashValue;
HASH_CALC;
#endif
_hash[kHash2Offset + hash2Value] = _pos;
_hash[hash2Value] = _pos;
#else
UInt32 hashValue = Hash(cur);
#endif
UInt32 curMatch = _hash[hashValue];
_hash[hashValue] = _pos;
UInt32 curMatch = _hash[kFixHashSize + hashValue];
_hash[kFixHashSize + hashValue] = _pos;
CIndex *son = _hash + kHashSizeSum;
#ifdef _HASH_CHAIN
_son[_cyclicBufferPos] = curMatch;
#else
CIndex *son = _son;
CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CIndex *ptr1 = son + (_cyclicBufferPos << 1);
#ifdef THERE_ARE_DIRECT_HASH_BYTES
if (lenLimit != kNumHashDirectBytes)
#endif
{
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
UInt32 count = _cutValue;
while(true)
{
if(curMatch <= matchMinPos || count-- == 0)
break;
Byte *pb = _buffer + curMatch;
UInt32 len = MyMin(len0, len1);
do
{
if (pb[len] != cur[len])
*ptr0 = *ptr1 = kEmptyHashValue;
break;
}
while(++len != lenLimit);
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
@@ -351,8 +432,23 @@ STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
(_cyclicBufferPos - delta + _cyclicBufferSize);
CIndex *pair = son + (cyclicPos << 1);
if (len != lenLimit)
// _mm_prefetch((const char *)pair, _MM_HINT_T0);
const Byte *pb = _buffer + curMatch;
UInt32 len = MyMin(len0, len1);
if (pb[len] == cur[len])
{
while(++len != lenLimit)
if (pb[len] != cur[len])
break;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
break;
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
@@ -368,23 +464,22 @@ STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
len0 = len;
}
}
else
{
*ptr1 = pair[0];
*ptr0 = pair[1];
return;
#endif
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
}
}
}
*ptr0 = kEmptyHashValue;
*ptr1 = kEmptyHashValue;
while(--num != 0);
return S_OK;
}
void CMatchFinderBinTree::Normalize()
void CMatchFinder::Normalize()
{
UInt32 subValue = _pos - _cyclicBufferSize;
CIndex *items = _hash;
UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2);
UInt32 numItems = (_hashSizeSum + _cyclicBufferSize * 2);
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 value = items[i];
@@ -397,7 +492,7 @@ void CMatchFinderBinTree::Normalize()
ReduceOffsets(subValue);
}
STDMETHODIMP CMatchFinderBinTree::MovePos()
HRESULT CMatchFinder::MovePos()
{
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
@@ -407,38 +502,26 @@ STDMETHODIMP CMatchFinderBinTree::MovePos()
return S_OK;
}
STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index)
STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)
{ return CLZInWindow::GetIndexByte(index); }
STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index,
STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index,
UInt32 back, UInt32 limit)
{ return CLZInWindow::GetMatchLen(index, back, limit); }
STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes()
STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()
{ return CLZInWindow::GetNumAvailableBytes(); }
STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos()
STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()
{ return CLZInWindow::GetPointerToCurrentPos(); }
// IMatchFinderSetCallback
STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback)
{
m_Callback = callback;
return S_OK;
}
STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)
{ return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }
void CMatchFinderBinTree::BeforeMoveBlock()
{
if (m_Callback)
m_Callback->BeforeChangingBufferPos();
CLZInWindow::BeforeMoveBlock();
}
STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()
{ CLZInWindow::MoveBlock();}
void CMatchFinderBinTree::AfterMoveBlock()
{
if (m_Callback)
m_Callback->AfterChangingBufferPos();
CLZInWindow::AfterMoveBlock();
}
#undef HASH_CALC
#undef kNumHashDirectBytes
}

View File

@@ -1,55 +0,0 @@
// HC.h
#include "../LZInWindow.h"
#include "../IMatchFinder.h"
namespace HC_NAMESPACE {
typedef UInt32 CIndex;
const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
class CMatchFinderHC:
public IMatchFinder,
public IMatchFinderSetCallback,
public CLZInWindow,
public CMyUnknownImp
{
UInt32 _cyclicBufferPos;
UInt32 _cyclicBufferSize; // it must be historySize + 1
UInt32 _matchMaxLen;
CIndex *_hash;
UInt32 _cutValue;
CMyComPtr<IMatchFinderCallback> m_Callback;
void Normalize();
void FreeThisClassMemory();
void FreeMemory();
MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
STDMETHOD(Init)(ISequentialInStream *inStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(MovePos)();
STDMETHOD_(Byte, GetIndexByte)(Int32 index);
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
STDMETHOD_(UInt32, GetNumAvailableBytes)();
STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
STDMETHOD_(void, DummyLongestMatch)();
// IMatchFinderSetCallback
STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
virtual void BeforeMoveBlock();
virtual void AfterMoveBlock();
public:
CMatchFinderHC();
virtual ~CMatchFinderHC();
void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
};
}

View File

@@ -3,11 +3,11 @@
#ifndef __HC2_H
#define __HC2_H
#undef HC_NAMESPACE
#define HC_NAMESPACE NHC2
#define BT_NAMESPACE NHC2
#include "HCMF.h"
#include "HCMFMain.h"
#include "HCMain.h"
#undef BT_NAMESPACE
#endif

View File

@@ -3,15 +3,14 @@
#ifndef __HC3_H
#define __HC3_H
#undef HC_NAMESPACE
#define HC_NAMESPACE NHC3
#define BT_NAMESPACE NHC3
#define HASH_ARRAY_2
#include "HC.h"
#include "HCMain.h"
#undef HASH_ARRAY_2
#undef BT_NAMESPACE
#endif

View File

@@ -3,17 +3,17 @@
#ifndef __HC4_H
#define __HC4_H
#undef HC_NAMESPACE
#define HC_NAMESPACE NHC4
#define BT_NAMESPACE NHC4
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#include "HC.h"
#include "HCMain.h"
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#undef BT_NAMESPACE
#endif

View File

@@ -1,21 +0,0 @@
// HC4b.h
#ifndef __HC4B__H
#define __HC4B__H
#undef HC_NAMESPACE
#define HC_NAMESPACE NHC4b
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#define HASH_BIG
#include "HC.h"
#include "HCMain.h"
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#undef HASH_BIG
#endif

View File

@@ -1,350 +1,6 @@
// HC.h
// HCMain.h
#include "../../../../Common/Defs.h"
#include "../../../../Common/CRC.h"
#include "../../../../Common/Alloc.h"
#define _HASH_CHAIN
#include "../BinTree/BinTreeMain.h"
#undef _HASH_CHAIN
namespace HC_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 = 0;
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << (16);
#endif
#else
#ifdef HASH_ZIP
static const UInt32 kNumHashDirectBytes = 0;
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << 16;
#else
#define THERE_ARE_DIRECT_HASH_BYTES
static const UInt32 kNumHashDirectBytes = 2;
static const UInt32 kNumHashBytes = 2;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
#endif
#endif
static const UInt32 kHashSizeSum = kHashSize
#ifdef HASH_ARRAY_2
+ kHash2Size
#ifdef HASH_ARRAY_3
+ kHash3Size
#endif
#endif
;
#ifdef HASH_ARRAY_2
static const UInt32 kHash2Offset = kHashSize;
#ifdef HASH_ARRAY_3
static const UInt32 kHash3Offset = kHashSize + kHash2Size;
#endif
#endif
CMatchFinderHC::CMatchFinderHC():
_hash(0),
_cutValue(16)
{
}
void CMatchFinderHC::FreeThisClassMemory()
{
BigFree(_hash);
_hash = 0;
}
void CMatchFinderHC::FreeMemory()
{
FreeThisClassMemory();
CLZInWindow::Free();
}
CMatchFinderHC::~CMatchFinderHC()
{
FreeMemory();
}
STDMETHODIMP CMatchFinderHC::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
UInt32 sizeReserv = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
if (CLZInWindow::Create(historySize + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter, sizeReserv))
{
if (historySize + 256 > kMaxValForNormalize)
{
FreeMemory();
return E_INVALIDARG;
}
_matchMaxLen = matchMaxLen;
UInt32 newCyclicBufferSize = historySize + 1;
if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
return S_OK;
FreeThisClassMemory();
_cyclicBufferSize = newCyclicBufferSize; // don't change it
_hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize) * sizeof(CIndex));
if (_hash != 0)
return S_OK;
}
FreeMemory();
return E_OUTOFMEMORY;
}
static const UInt32 kEmptyHashValue = 0;
STDMETHODIMP CMatchFinderHC::Init(ISequentialInStream *stream)
{
RINOK(CLZInWindow::Init(stream));
for(UInt32 i = 0; i < kHashSizeSum; i++)
_hash[i] = kEmptyHashValue;
_cyclicBufferPos = 0;
ReduceOffsets(-1);
return S_OK;
}
STDMETHODIMP_(void) CMatchFinderHC::ReleaseStream()
{
// ReleaseStream();
}
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
{
UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
hash2Value = temp & (kHash2Size - 1);
hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
(kHashSize - 1);
}
#else // no HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
{
UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
hash2Value = temp & (kHash2Size - 1);
return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);;
}
#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
STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances)
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if(lenLimit < kNumHashBytes)
return 0;
}
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
Byte *cur = _buffer + _pos;
UInt32 maxLen = 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
#ifdef HASH_ARRAY_2
UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
_hash[kHash2Offset + hash2Value] = _pos;
distances[2] = 0xFFFFFFFF;
if(curMatch2 > matchMinPos)
if (_buffer[curMatch2] == cur[0])
{
distances[2] = _pos - curMatch2 - 1;
maxLen = 2;
}
#ifdef HASH_ARRAY_3
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
_hash[kHash3Offset + hash3Value] = _pos;
distances[3] = 0xFFFFFFFF;
if(curMatch3 > matchMinPos)
if (_buffer[curMatch3] == cur[0])
{
distances[3] = _pos - curMatch3 - 1;
maxLen = 3;
}
#endif
#endif
UInt32 curMatch = _hash[hashValue];
_hash[hashValue] = _pos;
CIndex *chain = _hash + kHashSizeSum;
chain[_cyclicBufferPos] = curMatch;
distances[kNumHashBytes] = 0xFFFFFFFF;
#ifdef THERE_ARE_DIRECT_HASH_BYTES
if (lenLimit == kNumHashDirectBytes)
{
if(curMatch > matchMinPos)
while (maxLen < kNumHashDirectBytes)
distances[++maxLen] = _pos - curMatch - 1;
}
else
#endif
{
UInt32 count = _cutValue;
do
{
if(curMatch <= matchMinPos)
break;
Byte *pby1 = _buffer + curMatch;
UInt32 currentLen = kNumHashDirectBytes;
do
{
if (pby1[currentLen] != cur[currentLen])
break;
}
while(++currentLen != lenLimit);
UInt32 delta = _pos - curMatch;
while (maxLen < currentLen)
distances[++maxLen] = delta - 1;
if(currentLen == lenLimit)
break;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
curMatch = chain[cyclicPos];
}
while(--count != 0);
}
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
if (distances[4] < distances[3])
distances[3] = distances[4];
#endif
if (distances[3] < distances[2])
distances[2] = distances[3];
#endif
return maxLen;
}
STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch()
{
if (_streamPos - _pos < kNumHashBytes)
return;
Byte *cur = _buffer + _pos;
#ifdef HASH_ARRAY_2
UInt32 hash2Value;
#ifdef HASH_ARRAY_3
UInt32 hash3Value;
UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
_hash[kHash3Offset + hash3Value] = _pos;
#else
UInt32 hashValue = Hash(cur, hash2Value);
#endif
_hash[kHash2Offset + hash2Value] = _pos;
#else
UInt32 hashValue = Hash(cur);
#endif
_hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue];
_hash[hashValue] = _pos;
}
void CMatchFinderHC::Normalize()
{
UInt32 subValue = _pos - _cyclicBufferSize;
CIndex *items = _hash;
UInt32 numItems = kHashSizeSum + _cyclicBufferSize;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
ReduceOffsets(subValue);
}
STDMETHODIMP CMatchFinderHC::MovePos()
{
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
return S_OK;
}
STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index)
{ return CLZInWindow::GetIndexByte(index); }
STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index,
UInt32 back, UInt32 limit)
{ return CLZInWindow::GetMatchLen(index, back, limit); }
STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes()
{ return CLZInWindow::GetNumAvailableBytes(); }
STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos()
{ return CLZInWindow::GetPointerToCurrentPos(); }
// IMatchFinderSetCallback
STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback)
{
m_Callback = callback;
return S_OK;
}
void CMatchFinderHC::BeforeMoveBlock()
{
if (m_Callback)
m_Callback->BeforeChangingBufferPos();
CLZInWindow::BeforeMoveBlock();
}
void CMatchFinderHC::AfterMoveBlock()
{
if (m_Callback)
m_Callback->AfterChangingBufferPos();
CLZInWindow::AfterMoveBlock();
}
}

View File

@@ -3,61 +3,25 @@
#ifndef __IMATCHFINDER_H
#define __IMATCHFINDER_H
// {23170F69-40C1-278A-0000-000200010000}
DEFINE_GUID(IID_IInWindowStream,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000")
IInWindowStream: public IUnknown
struct IInWindowStream: public IUnknown
{
STDMETHOD(Init)(ISequentialInStream *inStream) PURE;
STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE;
STDMETHOD_(void, ReleaseStream)() PURE;
STDMETHOD(MovePos)() PURE;
STDMETHOD(Init)() PURE;
STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE;
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE;
STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE;
STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE;
STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE;
STDMETHOD_(void, ChangeBufferPos)() PURE;
};
// {23170F69-40C1-278A-0000-000200020000}
DEFINE_GUID(IID_IMatchFinder,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000")
IMatchFinder: public IInWindowStream
struct IMatchFinder: public IInWindowStream
{
STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE;
STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE;
STDMETHOD_(void, DummyLongestMatch)() PURE;
STDMETHOD(GetMatches)(UInt32 *distances) PURE;
STDMETHOD(Skip)(UInt32 num) PURE;
};
// {23170F69-40C1-278A-0000-000200020100}
DEFINE_GUID(IID_IMatchFinderCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100")
IMatchFinderCallback: public IUnknown
{
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

@@ -16,7 +16,6 @@ bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 kee
{
_keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter;
_keepSizeReserv = keepSizeReserv;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == 0 || _blockSize != blockSize)
{
@@ -31,10 +30,13 @@ bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 kee
return (_bufferBase != 0);
}
HRESULT CLZInWindow::Init(ISequentialInStream *stream)
void CLZInWindow::SetStream(ISequentialInStream *stream)
{
_stream = stream;
}
HRESULT CLZInWindow::Init()
{
_buffer = _bufferBase;
_pos = 0;
_streamPos = 0;
@@ -68,7 +70,7 @@ HRESULT CLZInWindow::ReadBlock()
return S_OK;
while(true)
{
UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos;
UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos;
if(size == 0)
return S_OK;
UInt32 numReadBytes;
@@ -93,10 +95,11 @@ HRESULT CLZInWindow::ReadBlock()
void CLZInWindow::MoveBlock()
{
BeforeMoveBlock();
UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore;
UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset;
UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0)
offset--;
UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset;
memmove(_bufferBase, _bufferBase + offset, numBytes);
_buffer -= offset;
AfterMoveBlock();
}

View File

@@ -9,7 +9,7 @@ class CLZInWindow
{
Byte *_bufferBase; // pointer to buffer with data
ISequentialInStream *_stream;
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
UInt32 _posLimit; // offset (from _buffer) when new block reading must be done
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
const Byte *_pointerToLastSafePosition;
protected:
@@ -18,22 +18,20 @@ protected:
UInt32 _pos; // offset (from _buffer) of curent byte
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv
UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
virtual void BeforeMoveBlock() {};
virtual void AfterMoveBlock() {};
void MoveBlock();
virtual HRESULT ReadBlock();
HRESULT ReadBlock();
void Free();
public:
CLZInWindow(): _bufferBase(0) {}
virtual ~CLZInWindow() { Free(); }
bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter,
UInt32 keepSizeReserv = (1<<17));
// keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G)
bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17));
HRESULT Init(ISequentialInStream *stream);
void SetStream(ISequentialInStream *stream);
HRESULT Init();
// void ReleaseStream();
Byte *GetBuffer() const { return _buffer; }
@@ -53,17 +51,17 @@ public:
else
return S_OK;
}
Byte GetIndexByte(Int32 index)const
{ return _buffer[(size_t)_pos + index]; }
Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; }
// index + limit have not to exceed _keepSizeAfter;
// -2G <= index < 2G
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const
{
if(_streamEndWasReached)
if ((_pos + index) + limit > _streamPos)
limit = _streamPos - (_pos + index);
distance++;
Byte *pby = _buffer + (size_t)_pos + index;
const Byte *pby = _buffer + (size_t)_pos + index;
UInt32 i;
for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);
return i;
@@ -79,6 +77,11 @@ public:
_streamPos -= subValue;
}
bool NeedMove(UInt32 numCheckBytes)
{
UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos);
return (reserv <= numCheckBytes);
}
};
#endif

View File

@@ -6,87 +6,96 @@
#include "MT.h"
class CMatchFinderCallback:
public IMatchFinderCallback,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
static const UInt32 kBlockSize = (1 << 14);
STDMETHOD(BeforeChangingBufferPos)();
STDMETHOD(AfterChangingBufferPos)();
public:
CMatchFinderMT *m_MatchFinderMT;
const Byte *m_BufferPosBefore;
};
STDMETHODIMP CMatchFinderCallback::BeforeChangingBufferPos()
static DWORD WINAPI MFThread(void *threadCoderInfo)
{
m_MatchFinderMT->m_AskChangeBufferPos.Set();
m_MatchFinderMT->m_CanChangeBufferPos.Lock();
m_BufferPosBefore = m_MatchFinderMT->m_MatchFinder->GetPointerToCurrentPos();
return S_OK;
return ((CMatchFinderMT *)threadCoderInfo)->ThreadFunc();
}
STDMETHODIMP CMatchFinderCallback::AfterChangingBufferPos()
CMatchFinderMT::CMatchFinderMT():
m_Buffer(0),
m_NeedStart(true)
{
m_MatchFinderMT->m_DataCurrentPos +=
m_MatchFinderMT->m_MatchFinder->GetPointerToCurrentPos() - m_BufferPosBefore;
m_MatchFinderMT->m_BufferPosWasChanged.Set();
return S_OK;
m_BlockIndex = kNumMTBlocks - 1;
m_CS[m_BlockIndex].Enter();
if (!m_Thread.Create(MFThread, this))
throw 271826;
}
HRESULT CMatchFinderMT::SetMatchFinder(IMatchFinder *matchFinder,
UInt32 multiThreadMult)
CMatchFinderMT::~CMatchFinderMT()
{
m_Exit = true;
m_CS[m_BlockIndex].Leave();
m_CanChangeBufferPos.Set();
if (m_NeedStart)
m_MtCanStart.Set();
m_Thread.Wait();
FreeMem();
}
void CMatchFinderMT::FreeMem()
{
::MyFree(m_Buffer);
m_Buffer = 0;
}
STDMETHODIMP CMatchFinderMT::Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
FreeMem();
m_MatchMaxLen = matchMaxLen;
if (kBlockSize <= matchMaxLen * 4)
return E_INVALIDARG;
UInt32 bufferSize = kBlockSize * kNumMTBlocks;
m_Buffer = (UInt32 *)::MyAlloc(bufferSize * sizeof(UInt32));
if (m_Buffer == 0)
return E_OUTOFMEMORY;
keepAddBufferBefore += bufferSize;
keepAddBufferAfter += (kBlockSize + 1);
return m_MatchFinder->Create(sizeHistory, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter);
}
// UInt32 blockSizeMult = 800
HRESULT CMatchFinderMT::SetMatchFinder(IMatchFinder *matchFinder)
{
_multiThreadMult = multiThreadMult;
m_MatchFinder = matchFinder;
CMyComPtr<IMatchFinderSetCallback> matchFinderSetCallback;
if (m_MatchFinder.QueryInterface(IID_IMatchFinderSetCallback,
&matchFinderSetCallback) == S_OK)
{
CMatchFinderCallback *matchFinderCallbackSpec =
new CMatchFinderCallback;
CMyComPtr<IMatchFinderCallback> matchFinderCallback = matchFinderCallbackSpec;
matchFinderCallbackSpec->m_MatchFinderMT = this;
matchFinderSetCallback->SetCallback(matchFinderCallback);
return S_OK;
}
else
return E_FAIL;
STDMETHODIMP CMatchFinderMT::SetStream(ISequentialInStream *s)
{
return m_MatchFinder->SetStream(s);
}
STDMETHODIMP CMatchFinderMT::Init(ISequentialInStream *s)
// Call it after ReleaseStream / SetStream
STDMETHODIMP CMatchFinderMT::Init()
{
m_AskChangeBufferPos.Reset();
m_CanChangeBufferPos.Reset();
m_BufferPosWasChanged.Reset();
m_StopWriting.Reset();
m_WritingWasStopped.Reset();
m_NeedStart = true;
m_CurrentPos = 0;
m_CurrentLimitPos = 0;
m_Pos = 0;
m_PosLimit = 0;
HRESULT result = m_MatchFinder->Init(s);
HRESULT result = m_MatchFinder->Init();
if (result == S_OK)
m_DataCurrentPos = m_MatchFinder->GetPointerToCurrentPos();
m_NumAvailableBytes = m_MatchFinder->GetNumAvailableBytes();
return result;
}
// ReleaseStream is required to finish multithreading
STDMETHODIMP_(void) CMatchFinderMT::ReleaseStream()
{
m_StopWriting.Set();
m_WritingWasStopped.Lock();
m_MatchFinder->ReleaseStream();
}
STDMETHODIMP CMatchFinderMT::MovePos()
m_StopWriting = true;
m_CS[m_BlockIndex].Leave();
if (!m_NeedStart)
{
if (m_Result != S_OK)
return m_Result;
m_NumAvailableBytesCurrent--;
m_DataCurrentPos++;
return S_OK;
m_CanChangeBufferPos.Set();
m_MtWasStopped.Lock();
m_NeedStart = true;
}
m_MatchFinder->ReleaseStream();
m_BlockIndex = kNumMTBlocks - 1;
m_CS[m_BlockIndex].Enter();
}
STDMETHODIMP_(Byte) CMatchFinderMT::GetIndexByte(Int32 index)
@@ -94,11 +103,10 @@ STDMETHODIMP_(Byte) CMatchFinderMT::GetIndexByte(Int32 index)
return m_DataCurrentPos[index];
}
STDMETHODIMP_(UInt32) CMatchFinderMT::GetMatchLen(Int32 index,
UInt32 distance, UInt32 limit)
STDMETHODIMP_(UInt32) CMatchFinderMT::GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{
if (int(index + limit) > m_NumAvailableBytesCurrent)
limit = m_NumAvailableBytesCurrent - (index);
if ((Int32)(index + limit) > m_NumAvailableBytes)
limit = m_NumAvailableBytes - (index);
distance++;
const Byte *pby = m_DataCurrentPos + index;
UInt32 i;
@@ -111,202 +119,177 @@ STDMETHODIMP_(const Byte *) CMatchFinderMT::GetPointerToCurrentPos()
return m_DataCurrentPos;
}
STDMETHODIMP_(UInt32) CMatchFinderMT::GetNumAvailableBytes()
{
return m_NumAvailableBytes;
}
void CMatchFinderMT::GetNextBlock()
{
if (m_NeedStart)
return m_MatchFinder->GetNumAvailableBytes();
else
return m_NumAvailableBytesCurrent;
}
void CMatchFinderMT::FreeMem()
{
MyFree(m_Buffer);
MyFree(m_DummyBuffer);
m_NeedStart = false;
for (UInt32 i = 0; i < kNumMTBlocks; i++)
m_StopReading[i] = false;
m_StopWriting = false;
m_Exit = false;
m_MtWasStarted.Reset();
m_MtWasStopped.Reset();
m_CanChangeBufferPos.Reset();
m_BufferPosWasChanged.Reset();
m_MtCanStart.Set();
m_MtWasStarted.Lock();
m_Result = S_OK;
}
STDMETHODIMP CMatchFinderMT::Create(UInt32 sizeHistory,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
UInt32 keepAddBufferAfter)
while (true)
{
FreeMem();
m_MatchMaxLen = matchMaxLen;
m_BlockSize = (matchMaxLen + 1) * _multiThreadMult;
UInt32 bufferSize = m_BlockSize * kNumMTBlocks;
m_DummyBuffer = (UInt32 *)MyAlloc((matchMaxLen + 1) * sizeof(UInt32));
if (m_DummyBuffer == 0)
return E_OUTOFMEMORY;
m_Buffer = (UInt32 *)MyAlloc(bufferSize * sizeof(UInt32));
if (m_Buffer == 0)
return E_OUTOFMEMORY;
for (int i = 0; i < kNumMTBlocks; i++)
m_Buffers[i] = &m_Buffer[i * m_BlockSize];
m_NeedStart = true;
m_CurrentPos = 0;
m_CurrentLimitPos = 0;
keepAddBufferBefore += bufferSize;
return m_MatchFinder->Create(sizeHistory, keepAddBufferBefore, matchMaxLen,
keepAddBufferAfter);
}
static DWORD WINAPI MFThread(void *threadCoderInfo)
UInt32 nextIndex = (m_BlockIndex == kNumMTBlocks - 1) ? 0 : m_BlockIndex + 1;
m_CS[nextIndex].Enter();
if (!m_StopReading[nextIndex])
{
CMatchFinderMT &mt = *(CMatchFinderMT *)threadCoderInfo;
return mt.ThreadFunc();
m_CS[m_BlockIndex].Leave();
m_BlockIndex = nextIndex;
break;
}
m_StopReading[nextIndex] = false;
m_CS[nextIndex].Leave();
m_CanChangeBufferPos.Set();
m_BufferPosWasChanged.Lock();
m_CS[nextIndex].Enter();
m_CS[m_BlockIndex].Leave();
m_BlockIndex = nextIndex;
}
m_Pos = m_BlockIndex * kBlockSize;
m_PosLimit = m_Buffer[m_Pos++];
m_NumAvailableBytes = m_Buffer[m_Pos++];
m_Result = m_Results[m_BlockIndex];
}
STDMETHODIMP CMatchFinderMT::GetMatches(UInt32 *distances)
{
if (m_Pos == m_PosLimit)
GetNextBlock();
if (m_Result != S_OK)
return m_Result;
m_NumAvailableBytes--;
m_DataCurrentPos++;
const UInt32 *buffer = m_Buffer + m_Pos;
UInt32 len = *buffer++;
*distances++ = len;
m_Pos += 1 + len;
for (UInt32 i = 0; i != len; i += 2)
{
distances[i] = buffer[i];
distances[i + 1] = buffer[i + 1];
}
return S_OK;
}
STDMETHODIMP CMatchFinderMT::Skip(UInt32 num)
{
do
{
if (m_Pos == m_PosLimit)
GetNextBlock();
if (m_Result != S_OK)
return m_Result;
m_NumAvailableBytes--;
m_DataCurrentPos++;
UInt32 len = m_Buffer[m_Pos++];
m_Pos += len;
}
while(--num != 0);
return S_OK;
}
STDMETHODIMP_(Int32) CMatchFinderMT::NeedChangeBufferPos(UInt32 numCheckBytes)
{
throw 1;
}
STDMETHODIMP_(void) CMatchFinderMT::ChangeBufferPos()
{
throw 1;
}
DWORD CMatchFinderMT::ThreadFunc()
{
bool errorMode = false;
while(true)
{
HANDLE events[3] = { m_ExitEvent, m_StopWriting, m_CanWriteEvents[m_WriteBufferIndex] } ;
DWORD waitResult = ::WaitForMultipleObjects((errorMode ? 2: 3), events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
bool needStartEvent = true;
m_MtCanStart.Lock();
HRESULT result = S_OK;
UInt32 blockIndex = 0;
while (true)
{
m_CS[blockIndex].Enter();
if (needStartEvent)
{
m_MtWasStarted.Set();
needStartEvent = false;
}
else
m_CS[(blockIndex == 0) ? kNumMTBlocks - 1 : blockIndex - 1].Leave();
if (m_Exit)
return 0;
if (waitResult == WAIT_OBJECT_0 + 1)
if (m_StopWriting)
{
m_WriteBufferIndex = 0;
for (int i = 0; i < kNumMTBlocks; i++)
m_CanWriteEvents[i].Reset();
m_WritingWasStopped.Set();
errorMode = false;
continue;
}
if (errorMode)
{
// this case means bug_in_program. So just exit;
return 1;
}
m_Results[m_WriteBufferIndex] = S_OK;
UInt32 *buffer = m_Buffers[m_WriteBufferIndex];
UInt32 curPos = 0;
UInt32 numBytes = 0;
UInt32 limit = m_BlockSize - m_MatchMaxLen;
IMatchFinder *mf = m_MatchFinder;
do
{
if (mf->GetNumAvailableBytes() == 0)
m_MtWasStopped.Set();
m_CS[blockIndex].Leave();
break;
UInt32 len = mf->GetLongestMatch(buffer + curPos);
/*
if (len == 1)
len = 0;
*/
buffer[curPos] = len;
curPos += len + 1;
numBytes++;
HRESULT result = mf->MovePos();
}
if (result == S_OK)
{
IMatchFinder *mf = m_MatchFinder;
if (mf->NeedChangeBufferPos(kBlockSize) != 0)
{
// m_AskChangeBufferPos.Set();
m_StopReading[blockIndex] = true;
m_CS[blockIndex].Leave();
m_CanChangeBufferPos.Lock();
m_CS[blockIndex].Enter();
const Byte *bufferPosBefore = mf->GetPointerToCurrentPos();
mf->ChangeBufferPos();
m_DataCurrentPos += mf->GetPointerToCurrentPos() - bufferPosBefore;
m_BufferPosWasChanged.Set();
}
else
{
UInt32 curPos = blockIndex * kBlockSize;
UInt32 limit = curPos + kBlockSize - m_MatchMaxLen - m_MatchMaxLen - 1;
UInt32 *buffer = m_Buffer;
m_Results[blockIndex] = S_OK;
curPos++;
UInt32 numAvailableBytes = mf->GetNumAvailableBytes();
buffer[curPos++] = numAvailableBytes;
while (numAvailableBytes-- != 0 && curPos < limit)
{
result = mf->GetMatches(buffer + curPos);
if (result != S_OK)
{
m_Results[m_WriteBufferIndex] = result;
errorMode = true;
m_Results[blockIndex] = result;
break;
}
curPos += buffer[curPos] + 1;
}
buffer[blockIndex * kBlockSize] = curPos;
}
}
while (curPos < limit);
m_LimitPos[m_WriteBufferIndex] = curPos;
if (errorMode)
m_NumAvailableBytes[m_WriteBufferIndex] = numBytes;
else
m_NumAvailableBytes[m_WriteBufferIndex] = numBytes +
mf->GetNumAvailableBytes();
m_CanReadEvents[m_WriteBufferIndex].Set();
if (++m_WriteBufferIndex == kNumMTBlocks)
m_WriteBufferIndex = 0;
}
}
CMatchFinderMT::CMatchFinderMT():
m_Buffer(0),
m_DummyBuffer(0),
_multiThreadMult(100)
{
for (int i = 0; i < kNumMTBlocks; i++)
{
m_CanReadEvents[i].Reset();
m_CanWriteEvents[i].Reset();
UInt32 curPos = blockIndex * kBlockSize;
m_Buffer[curPos] = curPos + 2; // size of buffer
m_Buffer[curPos + 1] = 0; // NumAvailableBytes
m_Results[blockIndex] = result; // error
}
m_ReadBufferIndex = 0;
m_WriteBufferIndex = 0;
m_ExitEvent.Reset();
if (!m_Thread.Create(MFThread, this))
throw 271826;
if (++blockIndex == kNumMTBlocks)
blockIndex = 0;
}
CMatchFinderMT::~CMatchFinderMT()
{
m_ExitEvent.Set();
m_Thread.Wait();
FreeMem();
}
void CMatchFinderMT::Start()
{
m_AskChangeBufferPos.Reset();
m_CanChangeBufferPos.Reset();
m_BufferPosWasChanged.Reset();
m_WriteBufferIndex = 0;
m_ReadBufferIndex = 0;
m_NeedStart = false;
m_CurrentPos = 0;
m_CurrentLimitPos = 0;
m_Result = S_OK;
int i;
for (i = 0; i < kNumMTBlocks; i++)
m_CanReadEvents[i].Reset();
for (i = kNumMTBlocks - 1; i >= 0; i--)
m_CanWriteEvents[i].Set();
}
STDMETHODIMP_(UInt32) CMatchFinderMT::GetLongestMatch(UInt32 *distances)
{
if (m_CurrentPos == m_CurrentLimitPos)
{
if (m_NeedStart)
Start();
while (true)
{
HANDLE events[2] = { m_AskChangeBufferPos, m_CanReadEvents[m_ReadBufferIndex] } ;
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 1)
break;
m_BufferPosWasChanged.Reset();
m_CanChangeBufferPos.Set();
m_BufferPosWasChanged.Lock();
}
m_CurrentLimitPos = m_LimitPos[m_ReadBufferIndex];
m_NumAvailableBytesCurrent = m_NumAvailableBytes[m_ReadBufferIndex];
m_CurrentPos = 0;
m_Result = m_Results[m_ReadBufferIndex];
}
/*
if (m_CurrentPos >= m_CurrentLimitPos)
throw 1123324;
*/
const UInt32 *buffer = m_Buffers[m_ReadBufferIndex];
UInt32 len = buffer[m_CurrentPos++];
for (UInt32 i = 1; i <= len; i++)
distances[i] = buffer[m_CurrentPos++];
if (m_CurrentPos == m_CurrentLimitPos)
{
m_CanWriteEvents[m_ReadBufferIndex].Set();
if (++m_ReadBufferIndex == kNumMTBlocks)
m_ReadBufferIndex = 0;
}
return len;
}
STDMETHODIMP_(void) CMatchFinderMT::DummyLongestMatch()
{
GetLongestMatch(m_DummyBuffer);
}

View File

@@ -11,7 +11,7 @@
#include "../../../ICoder.h"
#include "../IMatchFinder.h"
const int kNumMTBlocks = 3;
const UInt32 kNumMTBlocks = (1 << 6);
class CMatchFinderMT:
public IMatchFinder,
@@ -19,65 +19,61 @@ class CMatchFinderMT:
{
MY_UNKNOWN_IMP
STDMETHOD(Init)(ISequentialInStream *s);
STDMETHOD(SetStream)(ISequentialInStream *inStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(MovePos)();
STDMETHOD(Init)();
STDMETHOD_(Byte, GetIndexByte)(Int32 index);
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, 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)();
STDMETHOD(Create)(UInt32 sizeHistory, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
STDMETHOD(GetMatches)(UInt32 *distances);
STDMETHOD(Skip)(UInt32 num);
UInt32 m_CurrentPos;
UInt32 m_CurrentLimitPos;
STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes);
STDMETHOD_(void, ChangeBufferPos)();
UInt32 m_Pos;
UInt32 m_PosLimit;
UInt32 m_MatchMaxLen;
UInt32 m_BlockSize;
UInt32 *m_Buffer;
UInt32 *m_Buffers[kNumMTBlocks];
UInt32 *m_DummyBuffer;
bool m_NeedStart;
UInt32 m_WriteBufferIndex;
UInt32 m_ReadBufferIndex;
NWindows::NSynchronization::CAutoResetEvent m_StopWriting;
NWindows::NSynchronization::CAutoResetEvent m_WritingWasStopped;
NWindows::NSynchronization::CManualResetEvent m_ExitEvent;
NWindows::NSynchronization::CAutoResetEvent m_CanReadEvents[kNumMTBlocks];
NWindows::NSynchronization::CAutoResetEvent m_CanWriteEvents[kNumMTBlocks];
HRESULT m_Results[kNumMTBlocks];
UInt32 m_LimitPos[kNumMTBlocks];
UInt32 m_NumAvailableBytes[kNumMTBlocks];
UInt32 m_NumAvailableBytesCurrent;
NWindows::CThread m_Thread;
UInt32 _multiThreadMult;
UInt32 m_BlockIndex;
HRESULT m_Result;
UInt32 m_NumAvailableBytes;
const Byte *m_DataCurrentPos;
void Start();
void FreeMem();
// Common variables
public:
NWindows::NSynchronization::CAutoResetEvent m_AskChangeBufferPos;
CMyComPtr<IMatchFinder> m_MatchFinder;
NWindows::CThread m_Thread;
NWindows::NSynchronization::CAutoResetEvent m_MtCanStart;
NWindows::NSynchronization::CAutoResetEvent m_MtWasStarted;
NWindows::NSynchronization::CAutoResetEvent m_MtWasStopped;
NWindows::NSynchronization::CAutoResetEvent m_CanChangeBufferPos;
NWindows::NSynchronization::CAutoResetEvent m_BufferPosWasChanged;
CMyComPtr<IMatchFinder> m_MatchFinder;
const Byte *m_DataCurrentPos;
NWindows::NSynchronization::CCriticalSection m_CS[kNumMTBlocks];
HRESULT m_Results[kNumMTBlocks];
bool m_StopReading[kNumMTBlocks];
bool m_Exit;
bool m_StopWriting;
////////////////////////////
void FreeMem();
void GetNextBlock();
public:
DWORD ThreadFunc();
CMatchFinderMT();
~CMatchFinderMT();
HRESULT SetMatchFinder(IMatchFinder *matchFinder, UInt32 multiThreadMult = 200);
HRESULT SetMatchFinder(IMatchFinder *matchFinder);
};
#endif

View File

@@ -1,318 +0,0 @@
// Pat.h
// #ifndef __PATRICIA__H
// #define __PATRICIA__H
#include "../../../../Common/MyCom.h"
#include "../../../../Common/Types.h"
#include "../LZInWindow.h"
namespace PAT_NAMESPACE {
struct CNode;
typedef CNode *CNodePointer;
// #define __AUTO_REMOVE
// #define __NODE_4_BITS
// #define __NODE_3_BITS
// #define __NODE_2_BITS
// #define __NODE_2_BITS_PADDING
// #define __HASH_3
typedef UInt32 CIndex;
#ifdef __NODE_4_BITS
typedef UInt32 CIndex2;
typedef UInt32 CSameBitsType;
#else
#ifdef __NODE_3_BITS
typedef UInt32 CIndex2;
typedef UInt32 CSameBitsType;
#else
typedef UInt32 CIndex;
typedef UInt32 CSameBitsType;
typedef CIndex CIndex2;
#endif
#endif
const UInt32 kNumBitsInIndex = sizeof(CIndex) * 8;
const UInt32 kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1);
// don't change kMatchStartValue definition, since it is used in
// PatMain.h:
typedef CIndex CMatchPointer;
const UInt32 kDescendantEmptyValue = kMatchStartValue - 1;
union CDescendant
{
CIndex NodePointer;
CMatchPointer MatchPointer;
bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; }
bool IsNode() const { return NodePointer < kDescendantEmptyValue; }
bool IsMatch() const { return NodePointer > kDescendantEmptyValue; }
void MakeEmpty() { NodePointer = kDescendantEmptyValue; }
};
#undef MY_BYTE_SIZE
#ifdef __NODE_4_BITS
#define MY_BYTE_SIZE 8
const UInt32 kNumSubBits = 4;
#else
#ifdef __NODE_3_BITS
#define MY_BYTE_SIZE 9
const UInt32 kNumSubBits = 3;
#else
#define MY_BYTE_SIZE 8
#ifdef __NODE_2_BITS
const UInt32 kNumSubBits = 2;
#else
const UInt32 kNumSubBits = 1;
#endif
#endif
#endif
const UInt32 kNumSubNodes = 1 << kNumSubBits;
const UInt32 kSubNodesMask = kNumSubNodes - 1;
struct CNode
{
CIndex2 LastMatch;
CSameBitsType NumSameBits;
union
{
CDescendant Descendants[kNumSubNodes];
UInt32 NextFreeNode;
};
#ifdef __NODE_2_BITS
#ifdef __NODE_2_BITS_PADDING
UInt32 Padding[2];
#endif
#endif
};
#undef kIDNumBitsByte
#undef kIDNumBitsString
#ifdef __NODE_4_BITS
#define kIDNumBitsByte 0x30
#define kIDNumBitsString TEXT("4")
#else
#ifdef __NODE_3_BITS
#define kIDNumBitsByte 0x20
#define kIDNumBitsString TEXT("3")
#else
#ifdef __NODE_2_BITS
#define kIDNumBitsByte 0x10
#define kIDNumBitsString TEXT("2")
#else
#define kIDNumBitsByte 0x00
#define kIDNumBitsString TEXT("1")
#endif
#endif
#endif
#undef kIDManualRemoveByte
#undef kIDManualRemoveString
#ifdef __AUTO_REMOVE
#define kIDManualRemoveByte 0x00
#define kIDManualRemoveString TEXT("")
#else
#define kIDManualRemoveByte 0x08
#define kIDManualRemoveString TEXT("R")
#endif
#undef kIDHash3Byte
#undef kIDHash3String
#ifdef __HASH_3
#define kIDHash3Byte 0x04
#define kIDHash3String TEXT("H")
#else
#define kIDHash3Byte 0x00
#define kIDHash3String TEXT("")
#endif
#undef kIDUse3BytesByte
#undef kIDUse3BytesString
#define kIDUse3BytesByte 0x00
#define kIDUse3BytesString TEXT("")
#undef kIDPaddingByte
#undef kIDPaddingString
#ifdef __NODE_2_BITS_PADDING
#define kIDPaddingByte 0x01
#define kIDPaddingString TEXT("P")
#else
#define kIDPaddingByte 0x00
#define kIDPaddingString TEXT("")
#endif
// #undef kIDString
// #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String
// {23170F69-40C1-278C-01XX-0000000000}
DEFINE_GUID(PAT_CLSID,
0x23170F69, 0x40C1, 0x278C, 0x01,
kIDNumBitsByte |
kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
// III(PAT_NAMESPACE)
class CPatricia:
public IMatchFinder,
public IMatchFinderSetCallback,
public CMyUnknownImp,
CLZInWindow
{
MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
STDMETHOD(Init)(ISequentialInStream *aStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(MovePos)();
STDMETHOD_(Byte, GetIndexByte)(Int32 index);
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
STDMETHOD_(UInt32, GetNumAvailableBytes)();
STDMETHOD(Create)(UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
UInt32 keepAddBufferAfter);
STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
STDMETHOD_(void, DummyLongestMatch)();
STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
void FreeMemory();
public:
CPatricia();
~CPatricia();
UInt32 _sizeHistory;
UInt32 _matchMaxLen;
CDescendant *m_HashDescendants;
#ifdef __HASH_3
CDescendant *m_Hash2Descendants;
#endif
CNode *m_Nodes;
UInt32 m_FreeNode;
UInt32 m_FreeNodeMax;
#ifdef __AUTO_REMOVE
UInt32 m_NumUsedNodes;
UInt32 m_NumNodes;
#else
bool m_SpecialRemoveMode;
#endif
bool m_SpecialMode;
UInt32 m_NumNotChangedCycles;
UInt32 *m_TmpBacks;
CMyComPtr<IMatchFinderCallback> m_Callback;
virtual void BeforeMoveBlock();
virtual void AfterMoveBlock();
// IMatchFinderSetCallback
STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
void ChangeLastMatch(UInt32 hashValue);
#ifdef __AUTO_REMOVE
void TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos);
void TestRemoveNodes();
void RemoveNode(UInt32 index);
void TestRemoveAndNormalizeDescendant(CDescendant &descendant,
UInt32 limitPos, UInt32 subValue);
void TestRemoveNodesAndNormalize();
#else
void NormalizeDescendant(CDescendant &descendant, UInt32 subValue);
void Normalize();
void RemoveMatch();
#endif
private:
void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer,
Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos)
{
while((aByteXOR & kSubNodesMask) == 0)
{
aByteXOR >>= kNumSubBits;
aByte >>= kNumSubBits;
aNumSameBits -= kNumSubBits;
}
// Insert New Node
CNodePointer aNewNode = &m_Nodes[m_FreeNode];
UInt32 aNodeIndex = *aNodePointerPointer;
*aNodePointerPointer = m_FreeNode;
m_FreeNode = aNewNode->NextFreeNode;
#ifdef __AUTO_REMOVE
m_NumUsedNodes++;
#endif
if (m_FreeNode > m_FreeNodeMax)
{
m_FreeNodeMax = m_FreeNode;
m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
}
UInt32 aBitsNew = aByte & kSubNodesMask;
UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
for (UInt32 i = 0; i < kNumSubNodes; i++)
aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex;
aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits);
aNewNode->LastMatch = aPos;
aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits);
}
void AddLeafNode(CNodePointer aNode, Byte aByte, Byte aByteXOR,
UInt32 aNumSameBits, UInt32 aPos, UInt32 aDescendantIndex)
{
for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits)
{
aByte >>= kNumSubBits;
aByteXOR >>= kNumSubBits;
}
UInt32 aNewNodeIndex = m_FreeNode;
CNodePointer aNewNode = &m_Nodes[m_FreeNode];
m_FreeNode = aNewNode->NextFreeNode;
#ifdef __AUTO_REMOVE
m_NumUsedNodes++;
#endif
if (m_FreeNode > m_FreeNodeMax)
{
m_FreeNodeMax = m_FreeNode;
m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
}
UInt32 aBitsNew = (aByte & kSubNodesMask);
UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
for (UInt32 i = 0; i < kNumSubNodes; i++)
aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
aNewNode->Descendants[aBitsOld].MatchPointer =
aNode->Descendants[aDescendantIndex].MatchPointer;
aNewNode->NumSameBits = CSameBitsType(aNumSameBits);
aNewNode->LastMatch = aPos;
aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex;
}
};
}
// #endif

View File

@@ -1,22 +0,0 @@
// Pat2.h
#ifndef __PAT2__H
#define __PAT2__H
#undef PAT_CLSID
#define PAT_CLSID CLSID_CMatchFinderPat2
#undef PAT_NAMESPACE
#define PAT_NAMESPACE NPat2
#define __AUTO_REMOVE
#define __NODE_2_BITS
#include "Pat.h"
#include "PatMain.h"
#undef __AUTO_REMOVE
#undef __NODE_2_BITS
#endif

View File

@@ -1,24 +0,0 @@
// Pat2H.h
#ifndef __PAT2H__H
#define __PAT2H__H
#undef PAT_CLSID
#define PAT_CLSID CLSID_CMatchFinderPat2H
#undef PAT_NAMESPACE
#define PAT_NAMESPACE NPat2H
#define __AUTO_REMOVE
#define __NODE_2_BITS
#define __HASH_3
#include "Pat.h"
#include "PatMain.h"
#undef __AUTO_REMOVE
#undef __NODE_2_BITS
#undef __HASH_3
#endif

View File

@@ -1,20 +0,0 @@
// Pat2R.h
#ifndef __PAT2R__H
#define __PAT2R__H
#undef PAT_CLSID
#define PAT_CLSID CLSID_CMatchFinderPat2R
#undef PAT_NAMESPACE
#define PAT_NAMESPACE NPat2R
#define __NODE_2_BITS
#include "Pat.h"
#include "PatMain.h"
#undef __NODE_2_BITS
#endif

View File

@@ -1,24 +0,0 @@
// Pat3H.h
#ifndef __PAT3H__H
#define __PAT3H__H
#undef PAT_CLSID
#define PAT_CLSID CLSID_CMatchFinderPat3H
#undef PAT_NAMESPACE
#define PAT_NAMESPACE NPat3H
#define __AUTO_REMOVE
#define __NODE_3_BITS
#define __HASH_3
#include "Pat.h"
#include "PatMain.h"
#undef __AUTO_REMOVE
#undef __NODE_3_BITS
#undef __HASH_3
#endif

View File

@@ -1,24 +0,0 @@
// Pat4H.h
#ifndef __PAT4H__H
#define __PAT4H__H
#undef PAT_CLSID
#define PAT_CLSID CLSID_CMatchFinderPat4H
#undef PAT_NAMESPACE
#define PAT_NAMESPACE NPat4H
#define __AUTO_REMOVE
#define __NODE_4_BITS
#define __HASH_3
#include "Pat.h"
#include "PatMain.h"
#undef __AUTO_REMOVE
#undef __NODE_4_BITS
#undef __HASH_3
#endif

View File

@@ -1,989 +0,0 @@
// PatMain.h
#include "../../../../Common/Defs.h"
#include "../../../../Common/Alloc.h"
namespace PAT_NAMESPACE {
STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback)
{
m_Callback = callback;
return S_OK;
}
void CPatricia::BeforeMoveBlock()
{
if (m_Callback)
m_Callback->BeforeChangingBufferPos();
CLZInWindow::BeforeMoveBlock();
}
void CPatricia::AfterMoveBlock()
{
if (m_Callback)
m_Callback->AfterChangingBufferPos();
CLZInWindow::AfterMoveBlock();
}
const UInt32 kMatchStartValue2 = 2;
const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1;
const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1;
#ifdef __HASH_3
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
static const UInt32 kNumHash2Bytes = 2;
static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes);
static const UInt32 kPrevHashSize = kNumHash2Bytes;
#else
static const UInt32 kNumHashBytes = 2;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
static const UInt32 kPrevHashSize = 0;
#endif
CPatricia::CPatricia():
m_HashDescendants(0),
#ifdef __HASH_3
m_Hash2Descendants(0),
#endif
m_Nodes(0),
m_TmpBacks(0)
{
}
CPatricia::~CPatricia()
{
FreeMemory();
}
void CPatricia::FreeMemory()
{
MyFree(m_TmpBacks);
m_TmpBacks = 0;
::BigFree(m_Nodes);
m_Nodes = 0;
::BigFree(m_HashDescendants);
m_HashDescendants = 0;
#ifdef __HASH_3
::BigFree(m_Hash2Descendants);
m_Hash2Descendants = 0;
CLZInWindow::Free();
#endif
}
STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
FreeMemory();
int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8;
if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits)))
return E_INVALIDARG;
const UInt32 kAlignMask = (1 << 16) - 1;
UInt32 windowReservSize = historySize;
windowReservSize += kAlignMask;
windowReservSize &= ~(kAlignMask);
const UInt32 kMinReservSize = (1 << 19);
if (windowReservSize < kMinReservSize)
windowReservSize = kMinReservSize;
windowReservSize += 256;
if (!CLZInWindow::Create(historySize + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter, windowReservSize))
return E_OUTOFMEMORY;
_sizeHistory = historySize;
_matchMaxLen = matchMaxLen;
m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant));
if (m_HashDescendants == 0)
{
FreeMemory();
return E_OUTOFMEMORY;
}
#ifdef __HASH_3
m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant));
if (m_Hash2Descendants == 0)
{
FreeMemory();
return E_OUTOFMEMORY;
}
#endif
#ifdef __AUTO_REMOVE
#ifdef __HASH_3
m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19);
#else
m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10);
#endif
#else
UInt32 m_NumNodes = historySize;
#endif
const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1);
if (m_NumNodes + 32 > kMaxNumNodes)
return E_INVALIDARG;
// m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode));
m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode));
if (m_Nodes == 0)
{
FreeMemory();
return E_OUTOFMEMORY;
}
m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32));
if (m_TmpBacks == 0)
{
FreeMemory();
return E_OUTOFMEMORY;
}
return S_OK;
}
STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream)
{
RINOK(CLZInWindow::Init(aStream));
// memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0]));
#ifdef __HASH_3
for (UInt32 i = 0; i < kHash2Size; i++)
m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2;
#else
for (UInt32 i = 0; i < kHashSize; i++)
m_HashDescendants[i].MakeEmpty();
#endif
m_Nodes[0].NextFreeNode = 1;
m_FreeNode = 0;
m_FreeNodeMax = 0;
#ifdef __AUTO_REMOVE
m_NumUsedNodes = 0;
#else
m_SpecialRemoveMode = false;
#endif
m_SpecialMode = false;
return S_OK;
}
STDMETHODIMP_(void) CPatricia::ReleaseStream()
{
// CLZInWindow::ReleaseStream();
}
// pos = _pos + kNumHashBytes
// fullCurrentLimit = currentLimit + kNumHashBytes
// fullMatchLen = matchLen + kNumHashBytes
void CPatricia::ChangeLastMatch(UInt32 hashValue)
{
UInt32 pos = _pos + kNumHashBytes - 1;
UInt32 descendantIndex;
const Byte *currentBytePointer = _buffer + pos;
UInt32 numLoadedBits = 0;
Byte curByte = 0; // = 0 to disable warning of GCC
CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer];
while(true)
{
UInt32 numSameBits = node->NumSameBits;
if(numSameBits > 0)
{
if (numLoadedBits < numSameBits)
{
numSameBits -= numLoadedBits;
currentBytePointer += (numSameBits / MY_BYTE_SIZE);
numSameBits %= MY_BYTE_SIZE;
curByte = *currentBytePointer++;
numLoadedBits = MY_BYTE_SIZE;
}
curByte >>= numSameBits;
numLoadedBits -= numSameBits;
}
if(numLoadedBits == 0)
{
curByte = *currentBytePointer++;
numLoadedBits = MY_BYTE_SIZE;
}
descendantIndex = (curByte & kSubNodesMask);
node->LastMatch = pos;
numLoadedBits -= kNumSubBits;
curByte >>= kNumSubBits;
if(node->Descendants[descendantIndex].IsNode())
node = &m_Nodes[node->Descendants[descendantIndex].NodePointer];
else
break;
}
node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
}
UInt32 CPatricia::GetLongestMatch(UInt32 *distances)
{
UInt32 fullCurrentLimit;
if (_pos + _matchMaxLen <= _streamPos)
fullCurrentLimit = _matchMaxLen;
else
{
fullCurrentLimit = _streamPos - _pos;
if(fullCurrentLimit < kNumHashBytes)
return 0;
}
UInt32 pos = _pos + kNumHashBytes;
#ifdef __HASH_3
UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1];
UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2];
CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
CDescendant &hashDescendant = m_HashDescendants[hashValue];
if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2)
{
if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2)
{
UInt32 base = hashValue & 0xFFFF00;
for (UInt32 i = 0; i < 0x100; i++)
m_HashDescendants[base + i].MakeEmpty();
}
hash2Descendant.MatchPointer = pos + kMatchStartValue2;
hashDescendant.MatchPointer = pos + kMatchStartValue;
return 0;
}
distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1;
hash2Descendant.MatchPointer = pos + kMatchStartValue2;
#ifdef __AUTO_REMOVE
if (distances[kNumHash2Bytes] >= _sizeHistory)
{
if (hashDescendant.IsNode())
RemoveNode(hashDescendant.NodePointer);
hashDescendant.MatchPointer = pos + kMatchStartValue;
return 0;
}
#endif
if (fullCurrentLimit == kNumHash2Bytes)
return kNumHash2Bytes;
#else
UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8);
CDescendant &hashDescendant = m_HashDescendants[hashValue];
#endif
if(m_SpecialMode)
{
if(hashDescendant.IsMatch())
m_NumNotChangedCycles = 0;
if(m_NumNotChangedCycles >= _sizeHistory - 1)
{
ChangeLastMatch(hashValue);
m_NumNotChangedCycles = 0;
}
if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2))
{
if(hashDescendant.IsMatch())
hashDescendant.MatchPointer = pos + kMatchStartValue;
else
m_NumNotChangedCycles++;
for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++)
distances[i] = 0;
return fullCurrentLimit;
}
else if(m_NumNotChangedCycles > 0)
ChangeLastMatch(hashValue);
m_SpecialMode = false;
}
if(hashDescendant.IsEmpty())
{
hashDescendant.MatchPointer = pos + kMatchStartValue;
return kPrevHashSize;
}
UInt32 currentLimit = fullCurrentLimit - kNumHashBytes;
if(hashDescendant.IsMatch())
{
CMatchPointer matchPointer = hashDescendant.MatchPointer;
UInt32 backReal = pos - (matchPointer - kMatchStartValue);
UInt32 back = backReal - 1;
#ifdef __AUTO_REMOVE
if (back >= _sizeHistory)
{
hashDescendant.MatchPointer = pos + kMatchStartValue;
return kPrevHashSize;
}
#endif
UInt32 matchLen;
distances += kNumHashBytes;
Byte *buffer = _buffer + pos;
for(matchLen = 0; true; matchLen++)
{
*distances++ = back;
if (matchLen == currentLimit)
{
hashDescendant.MatchPointer = pos + kMatchStartValue;
return kNumHashBytes + matchLen;
}
if (buffer[matchLen] != buffer[(size_t)matchLen - backReal])
break;
}
// UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit);
UInt32 fullMatchLen = matchLen + kNumHashBytes;
hashDescendant.NodePointer = m_FreeNode;
CNodePointer node = &m_Nodes[m_FreeNode];
m_FreeNode = node->NextFreeNode;
#ifdef __AUTO_REMOVE
m_NumUsedNodes++;
#endif
if (m_FreeNode > m_FreeNodeMax)
{
m_FreeNodeMax = m_FreeNode;
m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
}
for (UInt32 i = 0; i < kNumSubNodes; i++)
node->Descendants[i].NodePointer = kDescendantEmptyValue;
node->LastMatch = pos;
Byte byteNew = GetIndexByte(fullMatchLen);
Byte byteOld = GetIndexByte(fullMatchLen - backReal);
Byte bitsNew, bitsOld;
UInt32 numSameBits = matchLen * MY_BYTE_SIZE;
while (true)
{
bitsNew = (byteNew & kSubNodesMask);
bitsOld = (byteOld & kSubNodesMask);
if(bitsNew != bitsOld)
break;
byteNew >>= kNumSubBits;
byteOld >>= kNumSubBits;
numSameBits += kNumSubBits;
}
node->NumSameBits = CSameBitsType(numSameBits);
node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue;
node->Descendants[bitsOld].MatchPointer = matchPointer;
return fullMatchLen;
}
const Byte *baseCurrentBytePointer = _buffer + pos;
const Byte *currentBytePointer = baseCurrentBytePointer;
UInt32 numLoadedBits = 0;
Byte curByte = 0;
CIndex *nodePointerPointer = &hashDescendant.NodePointer;
CNodePointer node = &m_Nodes[*nodePointerPointer];
distances += kNumHashBytes;
const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit;
const Byte *currentAddingOffset = _buffer;
#ifdef __AUTO_REMOVE
UInt32 lowPos;
if (pos > _sizeHistory)
lowPos = pos - _sizeHistory;
else
lowPos = 0;
#endif
while(true)
{
#ifdef __AUTO_REMOVE
if (node->LastMatch < lowPos)
{
RemoveNode(*nodePointerPointer);
*nodePointerPointer = pos + kMatchStartValue;
if (currentBytePointer == baseCurrentBytePointer)
return kPrevHashSize;
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
#endif
if(numLoadedBits == 0)
{
*distances++ = pos - node->LastMatch - 1;
if(currentBytePointer >= bytePointerLimit)
{
for (UInt32 i = 0; i < kNumSubNodes; i++)
node->Descendants[i].MatchPointer = pos + kMatchStartValue;
node->LastMatch = pos;
node->NumSameBits = 0;
return fullCurrentLimit;
}
curByte = (*currentBytePointer++);
currentAddingOffset++;
numLoadedBits = MY_BYTE_SIZE;
}
UInt32 numSameBits = node->NumSameBits;
if(numSameBits > 0)
{
Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >>
(MY_BYTE_SIZE - numLoadedBits)) ^ curByte;
while(numLoadedBits <= numSameBits)
{
if(byteXOR != 0)
{
AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
numSameBits, pos);
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
*distances++ = pos - node->LastMatch - 1;
numSameBits -= numLoadedBits;
if(currentBytePointer >= bytePointerLimit)
{
for (UInt32 i = 0; i < kNumSubNodes; i++)
node->Descendants[i].MatchPointer = pos + kMatchStartValue;
node->LastMatch = pos;
node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits);
return fullCurrentLimit;
}
numLoadedBits = MY_BYTE_SIZE;
curByte = (*currentBytePointer++);
byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch));
currentAddingOffset++;
}
if((byteXOR & ((1 << numSameBits) - 1)) != 0)
{
AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
numSameBits, pos);
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
curByte >>= numSameBits;
numLoadedBits -= numSameBits;
}
UInt32 descendantIndex = (curByte & kSubNodesMask);
numLoadedBits -= kNumSubBits;
nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
UInt32 nextNodeIndex = *nodePointerPointer;
node->LastMatch = pos;
if (nextNodeIndex < kDescendantEmptyValue)
{
curByte >>= kNumSubBits;
node = &m_Nodes[nextNodeIndex];
}
else if (nextNodeIndex == kDescendantEmptyValue)
{
node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
else
break;
}
UInt32 descendantIndex = (curByte & kSubNodesMask);
curByte >>= kNumSubBits;
CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer;
CMatchPointer realMatchPointer;
realMatchPointer = matchPointer - kMatchStartValue;
#ifdef __AUTO_REMOVE
if (realMatchPointer < lowPos)
{
node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
#endif
Byte byteXOR;
UInt32 numSameBits = 0;
if(numLoadedBits != 0)
{
Byte matchByte = *(currentAddingOffset + realMatchPointer -1);
matchByte >>= (MY_BYTE_SIZE - numLoadedBits);
byteXOR = matchByte ^ curByte;
if(byteXOR != 0)
{
AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
numSameBits += numLoadedBits;
}
const Byte *matchBytePointer = _buffer + realMatchPointer +
(currentBytePointer - baseCurrentBytePointer);
for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE)
{
curByte = (*currentBytePointer++);
*distances++ = pos - realMatchPointer - 1;
byteXOR = curByte ^ (*matchBytePointer++);
if(byteXOR != 0)
{
AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
}
}
*distances = pos - realMatchPointer - 1;
node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
if(*distances == 0)
{
m_SpecialMode = true;
m_NumNotChangedCycles = 0;
}
return fullCurrentLimit;
}
STDMETHODIMP_(void) CPatricia::DummyLongestMatch()
{
GetLongestMatch(m_TmpBacks);
}
// ------------------------------------
// Remove Match
typedef Byte CRemoveDataWord;
static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord);
#ifndef __AUTO_REMOVE
void CPatricia::RemoveMatch()
{
if(m_SpecialRemoveMode)
{
if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) ==
GetIndexByte(_matchMaxLen - _sizeHistory))
return;
m_SpecialRemoveMode = false;
}
UInt32 pos = _pos + kNumHashBytes - _sizeHistory;
#ifdef __HASH_3
const Byte *pp = _buffer + _pos - _sizeHistory;
UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1];
UInt32 hashValue = (hash2Value << 8) | pp[2];
CDescendant &hashDescendant = m_HashDescendants[hashValue];
CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
if (hash2Descendant >= kMatchStartValue2)
if(hash2Descendant.MatchPointer == pos + kMatchStartValue2)
hash2Descendant.MatchPointer = kDescendantEmptyValue2;
#else
UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) |
(UInt32(GetIndexByte(0 - _sizeHistory)) << 8);
CDescendant &hashDescendant = m_HashDescendants[hashValue];
#endif
if(hashDescendant.IsEmpty())
return;
if(hashDescendant.IsMatch())
{
if(hashDescendant.MatchPointer == pos + kMatchStartValue)
hashDescendant.MakeEmpty();
return;
}
UInt32 descendantIndex;
const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos);
UInt32 numLoadedBits = 0;
CRemoveDataWord curWord = 0; // = 0 to disable GCC warning
CIndex *nodePointerPointer = &hashDescendant.NodePointer;
CNodePointer node = &m_Nodes[hashDescendant.NodePointer];
while(true)
{
if(numLoadedBits == 0)
{
curWord = *currentPointer++;
numLoadedBits = kSizeRemoveDataWordInBits;
}
UInt32 numSameBits = node->NumSameBits;
if(numSameBits > 0)
{
if (numLoadedBits <= numSameBits)
{
numSameBits -= numLoadedBits;
currentPointer += (numSameBits / kSizeRemoveDataWordInBits);
numSameBits %= kSizeRemoveDataWordInBits;
curWord = *currentPointer++;
numLoadedBits = kSizeRemoveDataWordInBits;
}
curWord >>= numSameBits;
numLoadedBits -= numSameBits;
}
descendantIndex = (curWord & kSubNodesMask);
numLoadedBits -= kNumSubBits;
curWord >>= kNumSubBits;
UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer;
if (nextNodeIndex < kDescendantEmptyValue)
{
nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
node = &m_Nodes[nextNodeIndex];
}
else
break;
}
if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue)
{
const Byte *currentBytePointer = _buffer + _pos - _sizeHistory;
const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen;
for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++)
if(*currentBytePointer != *(currentBytePointer+1))
return;
m_SpecialRemoveMode = true;
return;
}
UInt32 numNodes = 0, numMatches = 0;
UInt32 i;
for (i = 0; i < kNumSubNodes; i++)
{
UInt32 nodeIndex = node->Descendants[i].NodePointer;
if (nodeIndex < kDescendantEmptyValue)
numNodes++;
else if (nodeIndex > kDescendantEmptyValue)
numMatches++;
}
numMatches -= 1;
if (numNodes + numMatches > 1)
{
node->Descendants[descendantIndex].MakeEmpty();
return;
}
if(numNodes == 1)
{
UInt32 i;
for (i = 0; i < kNumSubNodes; i++)
if (node->Descendants[i].IsNode())
break;
UInt32 nextNodeIndex = node->Descendants[i].NodePointer;
CNodePointer nextNode = &m_Nodes[nextNodeIndex];
nextNode->NumSameBits += node->NumSameBits + kNumSubBits;
*node = *nextNode;
nextNode->NextFreeNode = m_FreeNode;
m_FreeNode = nextNodeIndex;
return;
}
UInt32 matchPointer = 0; // = 0 to disable GCC warning
for (i = 0; i < kNumSubNodes; i++)
if (node->Descendants[i].IsMatch() && i != descendantIndex)
{
matchPointer = node->Descendants[i].MatchPointer;
break;
}
node->NextFreeNode = m_FreeNode;
m_FreeNode = *nodePointerPointer;
*nodePointerPointer = matchPointer;
}
#endif
// Commented code is more correct, but it gives warning
// on GCC: (1 << 32)
// So we use kMatchStartValue twice:
// kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1);
// must be defined in Pat.h
/*
const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) -
kMatchStartValue - kNumHashBytes - 1;
*/
const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1;
STDMETHODIMP CPatricia::MovePos()
{
#ifndef __AUTO_REMOVE
if(_pos >= _sizeHistory)
RemoveMatch();
#endif
RINOK(CLZInWindow::MovePos());
#ifdef __AUTO_REMOVE
if (m_NumUsedNodes >= m_NumNodes)
TestRemoveNodes();
#endif
if (_pos >= kNormalizeStartPos)
{
#ifdef __AUTO_REMOVE
TestRemoveNodesAndNormalize();
#else
Normalize();
#endif
}
return S_OK;
}
#ifndef __AUTO_REMOVE
void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue)
{
if (descendant.IsEmpty())
return;
if (descendant.IsMatch())
descendant.MatchPointer = descendant.MatchPointer - subValue;
else
{
CNode &node = m_Nodes[descendant.NodePointer];
node.LastMatch = node.LastMatch - subValue;
for (UInt32 i = 0; i < kNumSubNodes; i++)
NormalizeDescendant(node.Descendants[i], subValue);
}
}
void CPatricia::Normalize()
{
UInt32 subValue = _pos - _sizeHistory;
CLZInWindow::ReduceOffsets(subValue);
#ifdef __HASH_3
for(UInt32 hash = 0; hash < kHash2Size; hash++)
{
CDescendant &descendant = m_Hash2Descendants[hash];
if (descendant.MatchPointer != kDescendantsNotInitilized2)
{
UInt32 base = hash << 8;
for (UInt32 i = 0; i < 0x100; i++)
NormalizeDescendant(m_HashDescendants[base + i], subValue);
}
if (descendant.MatchPointer < kMatchStartValue2)
continue;
descendant.MatchPointer = descendant.MatchPointer - subValue;
}
#else
for(UInt32 hash = 0; hash < kHashSize; hash++)
NormalizeDescendant(m_HashDescendants[hash], subValue);
#endif
}
#else
void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos)
{
CNode &node = m_Nodes[descendant.NodePointer];
UInt32 numChilds = 0;
UInt32 childIndex = 0; // = 0 to disable GCC warning
for (UInt32 i = 0; i < kNumSubNodes; i++)
{
CDescendant &descendant2 = node.Descendants[i];
if (descendant2.IsEmpty())
continue;
if (descendant2.IsMatch())
{
if (descendant2.MatchPointer < limitPos)
descendant2.MakeEmpty();
else
{
numChilds++;
childIndex = i;
}
}
else
{
TestRemoveDescendant(descendant2, limitPos);
if (!descendant2.IsEmpty())
{
numChilds++;
childIndex = i;
}
}
}
if (numChilds > 1)
return;
CIndex nodePointerTemp = descendant.NodePointer;
if (numChilds == 1)
{
const CDescendant &descendant2 = node.Descendants[childIndex];
if (descendant2.IsNode())
m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
descendant = descendant2;
}
else
descendant.MakeEmpty();
node.NextFreeNode = m_FreeNode;
m_FreeNode = nodePointerTemp;
m_NumUsedNodes--;
}
void CPatricia::RemoveNode(UInt32 index)
{
CNode &node = m_Nodes[index];
for (UInt32 i = 0; i < kNumSubNodes; i++)
{
CDescendant &descendant2 = node.Descendants[i];
if (descendant2.IsNode())
RemoveNode(descendant2.NodePointer);
}
node.NextFreeNode = m_FreeNode;
m_FreeNode = index;
m_NumUsedNodes--;
}
void CPatricia::TestRemoveNodes()
{
UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
#ifdef __HASH_3
UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
for(UInt32 hash = 0; hash < kHash2Size; hash++)
{
CDescendant &descendant = m_Hash2Descendants[hash];
if (descendant.MatchPointer != kDescendantsNotInitilized2)
{
UInt32 base = hash << 8;
for (UInt32 i = 0; i < 0x100; i++)
{
CDescendant &descendant = m_HashDescendants[base + i];
if (descendant.IsEmpty())
continue;
if (descendant.IsMatch())
{
if (descendant.MatchPointer < limitPos)
descendant.MakeEmpty();
}
else
TestRemoveDescendant(descendant, limitPos);
}
}
if (descendant.MatchPointer < kMatchStartValue2)
continue;
if (descendant.MatchPointer < limitPos2)
descendant.MatchPointer = kDescendantEmptyValue2;
}
#else
for(UInt32 hash = 0; hash < kHashSize; hash++)
{
CDescendant &descendant = m_HashDescendants[hash];
if (descendant.IsEmpty())
continue;
if (descendant.IsMatch())
{
if (descendant.MatchPointer < limitPos)
descendant.MakeEmpty();
}
else
TestRemoveDescendant(descendant, limitPos);
}
#endif
}
void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant,
UInt32 limitPos, UInt32 subValue)
{
if (descendant.IsEmpty())
return;
if (descendant.IsMatch())
{
if (descendant.MatchPointer < limitPos)
descendant.MakeEmpty();
else
descendant.MatchPointer = descendant.MatchPointer - subValue;
return;
}
CNode &node = m_Nodes[descendant.NodePointer];
UInt32 numChilds = 0;
UInt32 childIndex = 0; // = 0 to disable GCC warning
for (UInt32 i = 0; i < kNumSubNodes; i++)
{
CDescendant &descendant2 = node.Descendants[i];
TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue);
if (!descendant2.IsEmpty())
{
numChilds++;
childIndex = i;
}
}
if (numChilds > 1)
{
node.LastMatch = node.LastMatch - subValue;
return;
}
CIndex nodePointerTemp = descendant.NodePointer;
if (numChilds == 1)
{
const CDescendant &descendant2 = node.Descendants[childIndex];
if (descendant2.IsNode())
m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
descendant = descendant2;
}
else
descendant.MakeEmpty();
node.NextFreeNode = m_FreeNode;
m_FreeNode = nodePointerTemp;
m_NumUsedNodes--;
}
void CPatricia::TestRemoveNodesAndNormalize()
{
UInt32 subValue = _pos - _sizeHistory;
UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
CLZInWindow::ReduceOffsets(subValue);
#ifdef __HASH_3
UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
for(UInt32 hash = 0; hash < kHash2Size; hash++)
{
CDescendant &descendant = m_Hash2Descendants[hash];
if (descendant.MatchPointer != kDescendantsNotInitilized2)
{
UInt32 base = hash << 8;
for (UInt32 i = 0; i < 0x100; i++)
TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue);
}
if (descendant.MatchPointer < kMatchStartValue2)
continue;
if (descendant.MatchPointer < limitPos2)
descendant.MatchPointer = kDescendantEmptyValue2;
else
descendant.MatchPointer = descendant.MatchPointer - subValue;
}
#else
for(UInt32 hash = 0; hash < kHashSize; hash++)
TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue);
#endif
}
#endif
STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index)
{
return CLZInWindow::GetIndexByte(index);
}
STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit)
{
return CLZInWindow::GetMatchLen(index, back, limit);
}
STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes()
{
return CLZInWindow::GetNumAvailableBytes();
}
STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos()
{
return CLZInWindow::GetPointerToCurrentPos();
}
}

View File

@@ -206,38 +206,6 @@ SOURCE=..\LZ\MT\MT.cpp
SOURCE=..\LZ\MT\MT.h
# End Source File
# End Group
# Begin Group "Pat"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\Patricia\Pat.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2R.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat3H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat4H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\PatMain.h
# End Source File
# End Group
# Begin Group "BT"
# PROP Default_Filter ""
@@ -259,10 +227,6 @@ SOURCE=..\LZ\BinTree\BinTree4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree4b.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeMain.h
# End Source File
# End Group
@@ -271,26 +235,10 @@ SOURCE=..\LZ\BinTree\BinTreeMain.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\HashChain\HC.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC2.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC3.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC4b.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HCMain.h
# End Source File
# End Group

View File

File diff suppressed because it is too large Load Diff

View File

@@ -51,23 +51,23 @@ struct COptimal
};
extern Byte g_FastPos[1024];
extern Byte g_FastPos[1 << 11];
inline UInt32 GetPosSlot(UInt32 pos)
{
if (pos < (1 << 10))
if (pos < (1 << 11))
return g_FastPos[pos];
if (pos < (1 << 19))
return g_FastPos[pos >> 9] + 18;
return g_FastPos[pos >> 18] + 36;
if (pos < (1 << 21))
return g_FastPos[pos >> 10] + 20;
return g_FastPos[pos >> 20] + 40;
}
inline UInt32 GetPosSlot2(UInt32 pos)
{
if (pos < (1 << 16))
if (pos < (1 << 17))
return g_FastPos[pos >> 6] + 12;
if (pos < (1 << 25))
return g_FastPos[pos >> 15] + 30;
return g_FastPos[pos >> 24] + 48;
if (pos < (1 << 27))
return g_FastPos[pos >> 16] + 32;
return g_FastPos[pos >> 26] + 52;
}
const UInt32 kIfinityPrice = 0xFFFFFFF;
@@ -105,8 +105,7 @@ public:
}
bool Create(int numPosBits, int numPrevBits)
{
if (_coders == 0 || (numPosBits + numPrevBits) !=
(_numPrevBits + _numPosBits) )
if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))
{
Free();
UInt32 numStates = 1 << (numPosBits + numPrevBits);
@@ -123,21 +122,8 @@ public:
for (UInt32 i = 0; i < numStates; i++)
_coders[i].Init();
}
UInt32 GetState(UInt32 pos, Byte prevByte) const
{ return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
{ return &_coders[GetState(pos, prevByte)]; }
/*
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
Byte symbol)
{ _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); }
void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
Byte matchByte, Byte symbol)
{ _coders[GetState(pos, prevByte)].Encode(rangeEncoder,
matchByte, symbol); }
*/
UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const
{ return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); }
{ return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }
};
namespace NLength {
@@ -152,24 +138,22 @@ class CEncoder
public:
void Init(UInt32 numPosStates);
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const;
void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;
};
const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
class CPriceTableEncoder: public CEncoder
{
UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax];
UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];
UInt32 _tableSize;
UInt32 _counters[kNumPosStatesEncodingMax];
public:
void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const
{ return _prices[symbol][posState]; }
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }
void UpdateTable(UInt32 posState)
{
for (UInt32 len = 0; len < _tableSize; len++)
_prices[len][posState] = CEncoder::GetPrice(len, posState);
SetPrices(posState, _tableSize, _prices[posState]);
_counters[posState] = _tableSize;
}
void UpdateTables(UInt32 numPosStates)
@@ -177,9 +161,10 @@ public:
for (UInt32 posState = 0; posState < numPosStates; posState++)
UpdateTable(posState);
}
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)
{
CEncoder::Encode(rangeEncoder, symbol, posState);
if (updatePrice)
if (--_counters[posState] == 0)
UpdateTable(posState);
}
@@ -216,12 +201,13 @@ class CEncoder :
CLiteralEncoder _literalEncoder;
UInt32 _matchDistances[kMatchMaxLen + 1];
UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];
bool _fastMode;
bool _maxMode;
// bool _maxMode;
UInt32 _numFastBytes;
UInt32 _longestMatchLength;
UInt32 _numDistancePairs;
UInt32 _additionalOffset;
@@ -249,7 +235,7 @@ class CEncoder :
UInt32 _dictionarySizePrev;
UInt32 _numFastBytesPrev;
UInt64 lastPosSlotFillingPos;
UInt32 _matchPriceCount;
UInt64 nowPos64;
bool _finished;
ISequentialInStream *_inStream;
@@ -263,7 +249,7 @@ class CEncoder :
bool _needReleaseMFStream;
HRESULT ReadMatchDistances(UInt32 &len);
HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);
HRESULT MovePos(UInt32 num);
UInt32 GetRepLen1Price(CState state, UInt32 posState) const
@@ -271,17 +257,18 @@ class CEncoder :
return _isRepG0[state.Index].GetPrice0() +
_isRep0Long[state.Index][posState].GetPrice0();
}
UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const
{
UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState);
UInt32 price;
if(repIndex == 0)
{
price += _isRepG0[state.Index].GetPrice0();
price = _isRepG0[state.Index].GetPrice0();
price += _isRep0Long[state.Index][posState].GetPrice1();
}
else
{
price += _isRepG0[state.Index].GetPrice1();
price = _isRepG0[state.Index].GetPrice1();
if (repIndex == 1)
price += _isRepG1[state.Index].GetPrice0();
else
@@ -292,6 +279,11 @@ class CEncoder :
}
return price;
}
UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
{
return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +
GetPureRepPrice(repIndex, state, posState);
}
/*
UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
{
@@ -313,8 +305,6 @@ class CEncoder :
*/
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)
@@ -329,7 +319,6 @@ class CEncoder :
HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
void FillPosSlotPrices();
void FillDistancesPrices();
void FillAlignPrices();

View File

@@ -206,38 +206,6 @@ SOURCE=..\RangeCoder\RangeCoderOpt.h
# Begin Group "LZ"
# PROP Default_Filter ""
# Begin Group "Pat"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\Patricia\Pat.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat2R.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat3H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\Pat4H.h
# End Source File
# Begin Source File
SOURCE=..\LZ\Patricia\PatMain.h
# End Source File
# End Group
# Begin Group "BT"
# PROP Default_Filter ""
@@ -259,18 +227,10 @@ SOURCE=..\LZ\BinTree\BinTree3Z.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree3ZMain.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree4b.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeMain.h
# End Source File
# End Group
@@ -279,26 +239,10 @@ SOURCE=..\LZ\BinTree\BinTreeMain.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\HashChain\HC.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC2.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC3.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HC4b.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HCMain.h
# End Source File
# End Group

View File

@@ -96,14 +96,13 @@ static void PrintHelp()
" d: decode file\n"
" b: Benchmark\n"
"<Switches>\n"
" -a{N}: set compression mode - [0, 2], default: 2 (max)\n"
" -d{N}: set dictionary - [0,28], default: 23 (8MB)\n"
" -a{N}: set compression mode - [0, 1], default: 1 (max)\n"
" -d{N}: set dictionary - [0,30], default: 23 (8MB)\n"
" -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
" -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
" -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
" -pb{N}: set number of pos bits - [0, 4], default: 2\n"
" -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n"
" pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n"
" -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"
" -eos: write End Of Stream marker\n"
" -si: read data from stdin\n"
" -so: write data to stdout\n"
@@ -150,7 +149,7 @@ int main2(int n, const char *args[])
g_IsNT = IsItWindowsNT();
#endif
fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n");
fprintf(stderr, "\nLZMA 4.33 Copyright (c) 1999-2006 Igor Pavlov 2006-02-05\n");
if (n == 1)
{
@@ -211,8 +210,7 @@ int main2(int n, const char *args[])
if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
numIterations = kNumDefaultItereations;
}
return LzmaBenchmark(stderr, numIterations, dictionary,
mf.CompareNoCase(L"BT4") == 0);
return LzmaBenchmark(stderr, numIterations, dictionary);
}
bool encodeMode = false;

View File

@@ -71,19 +71,31 @@ class CBenchRandomGenerator
{
CBitRandomGenerator RG;
UInt32 Pos;
UInt32 Rep0;
public:
UInt32 BufferSize;
Byte *Buffer;
CBenchRandomGenerator(): Buffer(0) {}
~CBenchRandomGenerator() { delete []Buffer; }
void Init() { RG.Init(); }
void Set(UInt32 bufferSize)
~CBenchRandomGenerator() { Free(); }
void Free()
{
delete []Buffer;
::MidFree(Buffer);
Buffer = 0;
Buffer = new Byte[bufferSize];
}
void Init()
{
RG.Init();
Rep0 = 1;
}
bool Alloc(UInt32 bufferSize)
{
if (Buffer != 0 && BufferSize == bufferSize)
return true;
Free();
Buffer = (Byte *)::MidAlloc(bufferSize);
Pos = 0;
BufferSize = bufferSize;
return (Buffer != 0);
}
UInt32 GetRndBit() { return RG.GetRnd(1); }
/*
@@ -104,29 +116,29 @@ public:
return GetLogRandBits(4);
return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
}
UInt32 GetLen()
{
if (GetRndBit() == 0)
return RG.GetRnd(2);
if (GetRndBit() == 0)
return 4 + RG.GetRnd(3);
return 12 + RG.GetRnd(4);
}
UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }
UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }
void Generate()
{
while(Pos < BufferSize)
{
if (GetRndBit() == 0 || Pos < 1)
Buffer[Pos++] = Byte(RG.GetRnd(8));
Buffer[Pos++] = (Byte)RG.GetRnd(8);
else
{
UInt32 offset = GetOffset();
while (offset >= Pos)
offset >>= 1;
offset += 1;
UInt32 len = 2 + GetLen();
UInt32 len;
if (RG.GetRnd(3) == 0)
len = 1 + GetLen1();
else
{
do
Rep0 = GetOffset();
while (Rep0 >= Pos);
Rep0++;
len = 2 + GetLen2();
}
for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
Buffer[Pos] = Buffer[Pos - offset];
Buffer[Pos] = Buffer[Pos - Rep0];
}
}
}
@@ -296,20 +308,10 @@ static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
return value * freq / elTime;
}
static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4,
UInt64 elapsedTime, UInt64 size)
static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size)
{
UInt64 numCommandsForOne;
if (isBT4)
{
UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
}
else
{
UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits);
numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits));
}
UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);
UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
return MyMultDiv64(numCommands, elapsedTime);
}
@@ -317,7 +319,7 @@ static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4,
static UInt64 GetDecompressRating(UInt64 elapsedTime,
UInt64 outSize, UInt64 inSize)
{
UInt64 numCommands = inSize * 250 + outSize * 21;
UInt64 numCommands = inSize * 220 + outSize * 20;
return MyMultDiv64(numCommands, elapsedTime);
}
@@ -342,7 +344,6 @@ static void PrintRating(FILE *f, UInt64 rating)
static void PrintResults(
FILE *f,
UInt32 dictionarySize,
bool isBT4,
UInt64 elapsedTime,
UInt64 size,
bool decompressMode, UInt64 secondSize)
@@ -353,7 +354,7 @@ static void PrintResults(
if (decompressMode)
rating = GetDecompressRating(elapsedTime, size, secondSize);
else
rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size);
rating = GetCompressRating(dictionarySize, elapsedTime, size);
PrintRating(f, rating);
}
@@ -372,11 +373,11 @@ static void ThrowError(FILE *f, HRESULT result, const char *s)
const wchar_t *bt2 = L"BT2";
const wchar_t *bt4 = L"BT4";
int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4)
int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize)
{
if (numIterations == 0)
return 0;
if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15))
if (dictionarySize < (1 << 18))
{
fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n");
return 1;
@@ -394,17 +395,13 @@ int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isB
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kMatchFinder
NCoderPropID::kDictionarySize
};
const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
PROPVARIANT properties[kNumProps];
properties[0].vt = VT_UI4;
properties[0].ulVal = UInt32(dictionarySize);
properties[1].vt = VT_BSTR;
properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2;
const UInt32 kBufferSize = dictionarySize + kAdditionalSize;
const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
@@ -417,7 +414,12 @@ int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isB
CBenchRandomGenerator rg;
rg.Init();
rg.Set(kBufferSize);
if (!rg.Alloc(kBufferSize))
{
fprintf(f, "\nError: Can't allocate memory\n");
return 1;
}
rg.Generate();
CCRC crc;
crc.Update(rg.Buffer, rg.BufferSize);
@@ -488,9 +490,9 @@ int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isB
}
}
UInt64 benchSize = kBufferSize - progressInfoSpec->InSize;
PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0);
PrintResults(f, dictionarySize, encodeTime, benchSize, false, 0);
fprintf(f, " ");
PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize);
PrintResults(f, dictionarySize, decodeTime, kBufferSize, true, compressedSize);
fprintf(f, "\n");
totalBenchSize += benchSize;
@@ -499,9 +501,9 @@ int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isB
totalCompressedSize += compressedSize;
}
fprintf(f, "---------------------------------------------------\n");
PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0);
PrintResults(f, dictionarySize, totalEncodeTime, totalBenchSize, false, 0);
fprintf(f, " ");
PrintResults(f, dictionarySize, isBT4, totalDecodeTime,
PrintResults(f, dictionarySize, totalDecodeTime,
kBufferSize * numIterations, true, totalCompressedSize);
fprintf(f, " Average\n");
return 0;

View File

@@ -6,6 +6,6 @@
#include <stdio.h>
#include "../../../Common/Types.h"
int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4);
int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize);
#endif

View File

@@ -53,7 +53,7 @@ class CCoder :
CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;
CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder;
void CCoder::ReleaseStreams()
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();

View File

@@ -209,7 +209,7 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize)
if (m_UnCompressedBlockSize == 0)
{
m_InBitStream.Align(m_AlignPos);
m_AlignPos = 0;
// m_AlignPos = 0;
}
}
else while(next > 0)

View File

@@ -49,7 +49,7 @@ public:
HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)
{
const startSize = size;
const UInt32 startSize = size;
if (_outSizeDefined)
{
const UInt64 rem = _outSize - _processedSize;

View File

@@ -682,6 +682,7 @@ void CApp::OnSetSubFolder(int srcPanelIndex)
if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)
return;
}
destPanel.CloseOpenFolders();
destPanel._folder = newFolder;
destPanel.RefreshListCtrl();
}

View File

@@ -137,6 +137,7 @@ class CBenchRandomGenerator
{
CBitRandomGenerator RG;
UInt32 Pos;
UInt32 Rep0;
public:
UInt32 BufferSize;
Byte *Buffer;
@@ -147,7 +148,11 @@ public:
::MidFree(Buffer);
Buffer = 0;
}
void Init() { RG.Init(); }
void Init()
{
RG.Init();
Rep0 = 1;
}
bool Alloc(UInt32 bufferSize)
{
if (Buffer != 0 && BufferSize == bufferSize)
@@ -177,14 +182,8 @@ public:
return GetLogRandBits(4);
return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
}
UInt32 GetLen()
{
if (GetRndBit() == 0)
return RG.GetRnd(2);
if (GetRndBit() == 0)
return 4 + RG.GetRnd(3);
return 12 + RG.GetRnd(4);
}
UInt32 GetLen1() { return RG.GetRnd(1 + RG.GetRnd(2)); }
UInt32 GetLen2() { return RG.GetRnd(2 + RG.GetRnd(2)); }
void Generate()
{
while(Pos < BufferSize)
@@ -193,13 +192,19 @@ public:
Buffer[Pos++] = Byte(RG.GetRnd(8));
else
{
UInt32 offset = GetOffset();
while (offset >= Pos)
offset >>= 1;
offset += 1;
UInt32 len = 2 + GetLen();
UInt32 len;
if (RG.GetRnd(3) == 0)
len = 1 + GetLen1();
else
{
do
Rep0 = GetOffset();
while (Rep0 >= Pos);
Rep0++;
len = 2 + GetLen2();
}
for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
Buffer[Pos] = Buffer[Pos - offset];
Buffer[Pos] = Buffer[Pos - Rep0];
}
}
}
@@ -218,10 +223,18 @@ bool CBenchmarkDialog::OnInit()
#endif
m_Dictionary.Attach(GetItem(IDC_BENCHMARK_COMBO_DICTIONARY));
for (int i = kNumBenchDictionaryBitsStart; i < 28; i++)
for (int i = kNumBenchDictionaryBitsStart; i <= 30; i++)
for (int j = 0; j < 2; j++)
{
UInt32 dictionary = (1 << i) + (j << (i - 1));
if(dictionary >
#ifdef _WIN64
(1 << 30)
#else
(1 << 27)
#endif
)
continue;
TCHAR s[40];
ConvertUInt64ToString((dictionary >> 20), s);
lstrcat(s, kMB);
@@ -240,20 +253,32 @@ bool CBenchmarkDialog::OnInit()
}
static UInt64 GetLZMAUsage(UInt32 dictionary)
{ return ((UInt64)dictionary * 19 / 2) + (8 << 20); }
{
UInt32 hs = dictionary - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
hs >>= 1;
hs++;
return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20);
}
static UInt64 GetMemoryUsage(UInt32 dictionary)
static UInt64 GetMemoryUsage(UInt32 dictionary, bool mtMode)
{
const UInt32 kBufferSize = dictionary + kAdditionalSize;
const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
return kBufferSize + kCompressedBufferSize +
GetLZMAUsage(dictionary) + dictionary + (1 << 20);
return (mtMode ? (6 << 20) : 0 )+ kBufferSize + kCompressedBufferSize +
GetLZMAUsage(dictionary) + dictionary + (2 << 20);
}
UInt32 CBenchmarkDialog::OnChangeDictionary()
{
UInt32 dictionary = (UInt32)m_Dictionary.GetItemData(m_Dictionary.GetCurSel());
UInt64 memUsage = GetMemoryUsage(dictionary);
UInt64 memUsage = GetMemoryUsage(dictionary, IsButtonCheckedBool(IDC_BENCHMARK_MULTITHREADING));
memUsage = (memUsage + (1 << 20) - 1) >> 20;
TCHAR s[40];
ConvertUInt64ToString(memUsage, s);
@@ -339,8 +364,8 @@ static UInt64 GetCompressRating(UInt32 dictionarySize,
{
if (elapsedTime == 0)
elapsedTime = 1;
UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
UInt64 numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);
UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
return numCommands * GetFreq() / elapsedTime;
}
@@ -350,7 +375,7 @@ static UInt64 GetDecompressRating(UInt64 elapsedTime,
{
if (elapsedTime == 0)
elapsedTime = 1;
UInt64 numCommands = inSize * 250 + outSize * 21;
UInt64 numCommands = inSize * 220 + outSize * 20;
return numCommands * GetFreq() / elapsedTime;
}

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 4
#define MY_VER_MINOR 32
#define MY_VERSION "4.32"
#define MY_7ZIP_VERSION "7-Zip 4.32"
#define MY_DATE "2005-12-09"
#define MY_COPYRIGHT "Copyright (c) 1999-2005 Igor Pavlov"
#define MY_VER_MINOR 33
#define MY_VERSION "4.33 beta"
#define MY_7ZIP_VERSION "7-Zip 4.33 beta"
#define MY_DATE "2006-02-05"
#define MY_COPYRIGHT "Copyright (c) 1999-2006 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE

View File

@@ -258,7 +258,7 @@ HRESULT OpenArchive(
if (result != S_OK)
continue;
}
#endif EXCLUDE_COM
#endif
if (!archive)
return E_FAIL;

View File

@@ -52,7 +52,7 @@ public:
CStdOutStream *OutStream;
void CExtractCallbackConsole::Init()
void Init()
{
NumArchives = 0;
NumArchiveErrors = 0;

View File

@@ -172,7 +172,7 @@ static const CFormatInfo g_Formats[] =
},
{
k7zFormat,
(1 << 0) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
g_7zMethods, MY_SIZE_OF_ARRAY(g_7zMethods),
true, true, true, true, true, true
},
@@ -184,7 +184,7 @@ static const CFormatInfo g_Formats[] =
},
{
L"GZip",
(1 << 5) | (1 << 9),
(1 << 5) | (1 << 7) | (1 << 9),
g_GZipMethods, MY_SIZE_OF_ARRAY(g_GZipMethods),
false, false, false, false, false, false
},
@@ -315,6 +315,11 @@ bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
UpdatePasswordControl();
return true;
}
case IDC_COMPRESS_MULTI_THREAD:
{
SetMemoryUsage();
return true;
}
}
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
@@ -460,7 +465,7 @@ void CCompressDialog::OnOK()
Info.SFXMode = IsSFX();
m_RegistryInfo.Solid = Info.Solid = IsButtonCheckedBool(IDC_COMPRESS_SOLID);
m_RegistryInfo.MultiThread = Info.MultiThread = IsButtonCheckedBool(IDC_COMPRESS_MULTI_THREAD);
m_RegistryInfo.MultiThread = Info.MultiThread = IsMultiThread();
m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES);
m_Params.GetText(Info.Options);
@@ -715,6 +720,17 @@ int CCompressDialog::GetLevel2()
return level;
}
bool CCompressDialog::IsMultiThread()
{
/*
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
bool multiThreadEnable = fi.MultiThread & IsMultiProcessor();
if (!multiThreadEnable)
return false;
*/
return IsButtonCheckedBool(IDC_COMPRESS_MULTI_THREAD);
}
void CCompressDialog::SetMethod()
{
m_Method.ResetContent();
@@ -825,32 +841,35 @@ void CCompressDialog::SetDictionary()
{
case kLZMA:
{
static const kMinDicSize = (1 << 16);
if (defaultDictionary == UInt32(-1))
{
if (level >= 9)
defaultDictionary = (32 << 20);
defaultDictionary = (1 << 26);
else if (level >= 7)
defaultDictionary = (8 << 20);
defaultDictionary = (1 << 24);
else if (level >= 5)
defaultDictionary = (2 << 20);
defaultDictionary = (1 << 22);
else if (level >= 3)
defaultDictionary = (1 << 20);
else
defaultDictionary = (32 << 10);
defaultDictionary = (kMinDicSize);
}
int i;
AddDictionarySize(32 << 10);
for (i = 20; i <= 28; i++)
AddDictionarySize(kMinDicSize);
for (i = 20; i <= 30; i++)
for (int j = 0; j < 2; j++)
{
if (i == 20 && j > 0)
continue;
UInt32 dictionary = (1 << i) + (j << (i - 1));
if (dictionary <=
#ifdef _WIN64
if (dictionary > (1 << 28))
continue;
(1 << 30)
#else
if (dictionary >= (1 << 28))
continue;
(1 << 27)
#endif
)
AddDictionarySize(dictionary);
}
SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
@@ -997,7 +1016,9 @@ void CCompressDialog::SetOrder()
{
if (defaultOrder == UInt32(-1))
{
if (level >= 7)
if (level >= 9)
defaultOrder = 128;
else if (level >= 7)
defaultOrder = 64;
else
defaultOrder = 32;
@@ -1061,20 +1082,29 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
if (fi.Filter && level >= 9)
size += (12 << 20) * 2 + (5 << 20);
bool isMultiThread = IsMultiThread();
switch (GetMethodID())
{
case kLZMA:
{
UInt32 hs = dictionary - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
hs >>= 1;
hs++;
size += hs * 4;
size += (UInt64)dictionary * 11 / 2;
if (level >= 5)
{
size += ((UInt64)dictionary * 19 / 2) + (2 << 20);
if (level >= 9)
size += (34 << 20);
else
size += (6 << 20);
}
else
size += ((UInt64)dictionary * 11 / 2) + (2 << 20);
size += dictionary * 4;
size += (2 << 20);
if (isMultiThread && level >= 5)
size += (2 << 20) + (4 << 20);
decompressMemory = dictionary + (2 << 20);
return size;
}
@@ -1090,7 +1120,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)
if (order == UInt32(-1))
order = 32;
if (level >= 7)
size += (order * 2 + 4) * (64 << 10);
size += (1 << 20);
size += 3 << 20;
decompressMemory = (2 << 20);
return size;

View File

@@ -104,6 +104,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
int GetLevel();
int GetLevelSpec();
int GetLevel2();
bool IsMultiThread();
void SetMethod();
int GetMethodID();

View File

@@ -2,8 +2,8 @@
;Defines
!define VERSION_MAJOR 4
!define VERSION_MINOR 32
!define VERSION_POSTFIX_FULL ""
!define VERSION_MINOR 33
!define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64
!ifdef IA64
!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64"

View File

@@ -1,7 +1,7 @@
LZMA SDK 4.32
LZMA SDK 4.33
-------------
LZMA SDK 4.32 Copyright (C) 1999-2005 Igor Pavlov
LZMA SDK 4.33 Copyright (C) 1999-2006 Igor Pavlov
LZMA SDK provides the documentation, samples, header files, libraries,
and tools you need to develop applications that use LZMA compression.
@@ -185,10 +185,10 @@ other directories of SDK for compiling.
http://sourceforge.net/projects/sevenzip/
LZMA Decompression features
---------------------------
- Variable dictionary size (up to 256 MB)
- Estimated compressing speed: about 500 KB/s on 1 GHz CPU
LZMA features
-------------
- Variable dictionary size (up to 1 GB)
- Estimated compressing speed: about 1 MB/s on 1 GHz CPU
- Estimated decompressing speed:
- 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon
- 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC
@@ -224,7 +224,7 @@ Usage: LZMA <e|d> inputFile outputFile [<switches>...]
b: Benchmark. There are two tests: compressing and decompressing
with LZMA method. Benchmark shows rating in MIPS (million
instructions per second). Rating value is calculated from
measured speed and it is normalized with AMD Athlon XP CPU
measured speed and it is normalized with AMD Athlon 64 X2 CPU
results. Also Benchmark checks possible hardware errors (RAM
errors in most cases). Benchmark uses these settings:
(-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you
@@ -235,11 +235,11 @@ Usage: LZMA <e|d> inputFile outputFile [<switches>...]
<Switches>
-a{N}: set compression mode 0 = fast, 1 = normal, 2 = max
default: 2 (max)
-a{N}: set compression mode 0 = fast, 1 = normal
default: 1 (normal)
d{N}: Sets Dictionary size - [0, 28], default: 23 (8MB)
The maximum value for dictionary size is 256 MB = 2^28 bytes.
d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB)
The maximum value for dictionary size is 1 GB = 2^30 bytes.
Dictionary size is calculated as DictionarySize = 2^N bytes.
For decompressing file compressed by LZMA method with dictionary
size D = 2^N you need about D bytes of memory (RAM).
@@ -262,29 +262,19 @@ Usage: LZMA <e|d> inputFile outputFile [<switches>...]
when period is equal 2^N.
-mf{MF_ID}: set Match Finder. Default: bt4.
Compression ratio for all bt* and pat* almost the same.
Algorithms from hc* group doesn't provide good compression
ratio, but they often works pretty fast in combination with
fast mode (-a0). Methods from bt* group require less memory
than methods from pat* group. Usually bt4 works faster than
any pat*, but for some types of files pat* can work faster.
fast mode (-a0).
Memory requirements depend from dictionary size
(parameter "d" in table below).
MF_ID Memory Description
bt2 d*9.5 + 1MB Binary Tree with 2 bytes hashing.
bt3 d*9.5 + 65MB Binary Tree with 2-3(full) bytes hashing.
bt4 d*9.5 + 6MB Binary Tree with 2-3-4 bytes hashing.
bt4b d*9.5 + 34MB Binary Tree with 2-3-4(big) bytes hashing.
pat2r d*26 + 1MB Patricia Tree with 2-bits nodes, removing.
pat2 d*38 + 1MB Patricia Tree with 2-bits nodes.
pat2h d*38 + 77MB Patricia Tree with 2-bits nodes, 2-3 bytes hashing.
pat3h d*62 + 85MB Patricia Tree with 3-bits nodes, 2-3 bytes hashing.
pat4h d*110 +101MB Patricia Tree with 4-bits nodes, 2-3 bytes hashing.
hc3 d*5.5 + 1MB Hash Chain with 2-3 bytes hashing.
hc4 d*5.5 + 6MB Hash Chain with 2-3-4 bytes hashing.
bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing.
bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing.
bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing.
hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing.
-eos: write End Of Stream marker. By default LZMA doesn't write
eos marker, since LZMA decoder knows uncompressed size

View File

@@ -1,9 +1,9 @@
7-Zip 4.32 Sources
7-Zip 4.33 Sources
------------------
7-Zip is a file archiver for Windows 95/98/ME/NT/2000/2003/XP.
7-Zip Copyright (C) 1999-2005 Igor Pavlov.
7-Zip Copyright (C) 1999-2006 Igor Pavlov.
License Info