4.44 beta

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

View File

@@ -0,0 +1,341 @@
# Microsoft Developer Studio Project File - Name="Deflate" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Deflate - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Deflate.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Deflate.mak" CFG="Deflate - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Deflate - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Deflate - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "Deflate - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEFLATE_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEFLATE_EXPORTS" /D "_ST_MODE" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\Deflate.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEFLATE_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEFLATE_EXPORTS" /D "_ST_MODE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\Deflate.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Deflate - Win32 Release"
# Name "Deflate - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Codec.def
# End Source File
# Begin Source File
SOURCE=.\DllExports.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"StdAfx.h"
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Huffman"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Huffman\HuffmanDecoder.h
# End Source File
# End Group
# Begin Group "Interface"
# PROP Default_Filter ""
# End Group
# Begin Group "7zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\InBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\LSBFDecoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\LSBFDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\LSBFEncoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\LSBFEncoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Alloc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Alloc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# End Group
# Begin Group "LZ"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\LZOutWindow.cpp
# End Source File
# Begin Source File
SOURCE=..\LZ\LZOutWindow.h
# End Source File
# End Group
# Begin Group "LZ_C"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\..\C\7zCrc.c
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\7zCrc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h
# End Source File
# End Group
# Begin Group "C Huffman"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Huffman\HuffmanEncode.c
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Huffman\HuffmanEncode.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sort.c
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sort.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\DeflateConst.h
# End Source File
# Begin Source File
SOURCE=.\DeflateDecoder.cpp
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\DeflateDecoder.h
# End Source File
# Begin Source File
SOURCE=.\DeflateEncoder.cpp
!IF "$(CFG)" == "Deflate - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Deflate - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\DeflateEncoder.h
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Deflate"=.\Deflate.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,134 @@
// DeflateConst.h
#ifndef __DEFLATE_CONST_H
#define __DEFLATE_CONST_H
namespace NCompress {
namespace NDeflate {
const int kNumHuffmanBits = 15;
const UInt32 kHistorySize32 = (1 << 15);
const UInt32 kHistorySize64 = (1 << 16);
const UInt32 kDistTableSize32 = 30;
const UInt32 kDistTableSize64 = 32;
const UInt32 kNumLenSymbols32 = 256;
const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255.
const UInt32 kNumLenSymbolsMax = kNumLenSymbols32;
const UInt32 kNumLenSlots = 29;
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 kTableDirectLevels = 16;
const UInt32 kTableLevelRepNumber = kTableDirectLevels;
const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
const UInt32 kLevelMask = 0xF;
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[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,
1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152};
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[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 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2
const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2
const UInt32 kMatchMaxLen = kMatchMaxLen32;
const int kFinalBlockFieldSize = 1;
namespace NFinalBlockField
{
enum
{
kNotFinalBlock = 0,
kFinalBlock = 1
};
}
const int kBlockTypeFieldSize = 2;
namespace NBlockType
{
enum
{
kStored = 0,
kFixedHuffman = 1,
kDynamicHuffman = 2
};
}
const int kNumLenCodesFieldSize = 5;
const int kNumDistCodesFieldSize = 5;
const int kNumLevelCodesFieldSize = 4;
const UInt32 kNumLitLenCodesMin = 257;
const UInt32 kNumDistCodesMin = 1;
const UInt32 kNumLevelCodesMin = 4;
const int kLevelFieldSize = 3;
const int kStoredBlockLengthFieldSize = 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;
}
};
}}
#endif

View File

@@ -0,0 +1,339 @@
// DeflateDecoder.cpp
#include "StdAfx.h"
#include "DeflateDecoder.h"
namespace NCompress {
namespace NDeflate {
namespace NDecoder {
static const int kLenIdFinished = -1;
static const int kLenIdNeedInit = -2;
CCoder::CCoder(bool deflate64Mode, bool deflateNSIS):
_deflate64Mode(deflate64Mode),
_deflateNSIS(deflateNSIS),
_keepHistory(false) {}
UInt32 CCoder::ReadBits(int numBits)
{
return m_InBitStream.ReadBits(numBits);
}
bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)
{
int i = 0;
do
{
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number < kTableDirectLevels)
values[i++] = (Byte)number;
else if (number < kLevelTableSize)
{
if (number == kTableLevelRepNumber)
{
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 = ReadBits(3) + 3;
else
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 = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
UInt32 blockType = ReadBits(kBlockTypeFieldSize);
if (blockType > NBlockType::kDynamicHuffman)
return false;
if (blockType == NBlockType::kStored)
{
m_StoredMode = true;
UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
ReadBits(numBitsForAlign);
m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);
if (_deflateNSIS)
return true;
return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));
}
m_StoredMode = false;
CLevels levels;
if (blockType == NBlockType::kFixedHuffman)
{
levels.SetFixedLevels();
_numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
}
else
{
int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
_numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
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)ReadBits(kLevelFieldSize);
else
levelLevels[position] = 0;
}
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))
return false;
levels.SubClear();
memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
}
RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));
return m_DistDecoder.SetCodeLengths(levels.distLevels);
}
HRESULT CCoder::CodeSpec(UInt32 curSize)
{
if (_remainLen == kLenIdFinished)
return S_OK;
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);
m_InBitStream.Init();
m_FinalBlock = false;
_remainLen = 0;
_needReadTable = true;
}
if (curSize == 0)
return S_OK;
while(_remainLen > 0 && curSize > 0)
{
_remainLen--;
Byte b = m_OutWindowStream.GetByte(_rep0);
m_OutWindowStream.PutByte(b);
curSize--;
}
while(curSize > 0)
{
if (_needReadTable)
{
if (m_FinalBlock)
{
_remainLen = kLenIdFinished;
break;
}
if (!ReadTables())
return S_FALSE;
_needReadTable = false;
}
if(m_StoredMode)
{
for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
_needReadTable = (m_StoredBlockSize == 0);
continue;
}
while(curSize > 0)
{
if (m_InBitStream.NumExtraBytes > 4)
return S_FALSE;
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number < 0x100)
{
m_OutWindowStream.PutByte((Byte)number);
curSize--;
continue;
}
else if (number == kSymbolEndOfBlock)
{
_needReadTable = true;
break;
}
else if (number < kMainTableSize)
{
number -= kSymbolMatch;
UInt32 len;
{
int numBits;
if (_deflate64Mode)
{
len = kLenStart64[number];
numBits = kLenDirectBits64[number];
}
else
{
len = kLenStart32[number];
numBits = kLenDirectBits32[number];
}
len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
}
UInt32 locLen = len;
if (locLen > curSize)
locLen = (UInt32)curSize;
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
if (number >= _numDistLevels)
return S_FALSE;
UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
if (!m_OutWindowStream.CopyBlock(distance, locLen))
return S_FALSE;
curSize -= locLen;
len -= locLen;
if (len != 0)
{
_remainLen = (Int32)len;
_rep0 = distance;
break;
}
}
else
return S_FALSE;
}
}
return S_OK;
}
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
SetInStream(inStream);
m_OutWindowStream.SetStream(outStream);
SetOutStreamSize(outSize);
CCoderReleaser flusher(this);
const UInt64 start = m_OutWindowStream.GetProcessedSize();
for (;;)
{
UInt32 curSize = 1 << 18;
if (outSize != 0)
{
const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);
if (curSize > rem)
curSize = (UInt32)rem;
}
if (curSize == 0)
break;
RINOK(CodeSpec(curSize));
if (_remainLen == kLenIdFinished)
break;
if (progress != NULL)
{
const UInt64 inSize = m_InBitStream.GetProcessedSize();
const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
}
}
flusher.NeedFlush = false;
return Flush();
}
#ifdef _NO_EXCEPTIONS
#define DEFLATE_TRY_BEGIN
#define DEFLATE_TRY_END
#else
#define DEFLATE_TRY_BEGIN try {
#define DEFLATE_TRY_END } \
catch(const CInBufferException &e) { return e.ErrorCode; } \
catch(const CLZOutWindowException &e) { return e.ErrorCode; } \
catch(...) { return S_FALSE; }
#endif
HRESULT CCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
DEFLATE_TRY_BEGIN
return CodeReal(inStream, outStream, inSize, outSize, progress);
DEFLATE_TRY_END
}
STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
{
if (value == NULL)
return E_INVALIDARG;
*value = m_InBitStream.GetProcessedSize();
return S_OK;
}
STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
{
m_InBitStream.SetStream(inStream);
return S_OK;
}
STDMETHODIMP CCoder::ReleaseInStream()
{
m_InBitStream.ReleaseStream();
return S_OK;
}
STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)
{
_remainLen = kLenIdNeedInit;
m_OutWindowStream.Init(_keepHistory);
return S_OK;
}
#ifdef _ST_MODE
STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
DEFLATE_TRY_BEGIN
if (processedSize)
*processedSize = 0;
const UInt64 startPos = m_OutWindowStream.GetProcessedSize();
m_OutWindowStream.SetMemStream((Byte *)data);
RINOK(CodeSpec(size));
if (processedSize)
*processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);
return Flush();
DEFLATE_TRY_END
}
#endif
}}}

View File

@@ -0,0 +1,134 @@
// DeflateDecoder.h
#ifndef __DEFLATE_DECODER_H
#define __DEFLATE_DECODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/LSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../LZ/LZOutWindow.h"
#include "../Huffman/HuffmanDecoder.h"
#include "DeflateConst.h"
namespace NCompress {
namespace NDeflate {
namespace NDecoder {
class CCoder:
public ICompressCoder,
public ICompressGetInStreamProcessedSize,
#ifdef _ST_MODE
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
public CMyUnknownImp
{
CLZOutWindow m_OutWindowStream;
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 _deflateNSIS;
bool _deflate64Mode;
bool _keepHistory;
Int32 _remainLen;
UInt32 _rep0;
bool _needReadTable;
UInt32 ReadBits(int numBits);
bool DeCodeLevelTable(Byte *values, int numSymbols);
bool ReadTables();
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
ReleaseInStream();
}
HRESULT Flush() { return m_OutWindowStream.Flush(); }
class CCoderReleaser
{
CCoder *m_Coder;
public:
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
if (NeedFlush)
m_Coder->Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
HRESULT CodeSpec(UInt32 curSize);
public:
CCoder(bool deflate64Mode, bool deflateNSIS = false);
void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
#ifdef _ST_MODE
MY_UNKNOWN_IMP4(
ICompressGetInStreamProcessedSize,
ICompressSetInStream,
ICompressSetOutStreamSize,
ISequentialInStream
)
#else
MY_UNKNOWN_IMP1(
ICompressGetInStreamProcessedSize)
#endif
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifdef _ST_MODE
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif
// IGetInStreamProcessedSize
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};
class CCOMCoder : public CCoder
{
public:
CCOMCoder(): CCoder(false) {}
};
class CNsisCOMCoder : public CCoder
{
public:
CNsisCOMCoder(): CCoder(false, true) {}
};
class CCOMCoder64 : public CCoder
{
public:
CCOMCoder64(): CCoder(true) {}
};
}}}
#endif

View File

@@ -0,0 +1,963 @@
// DeflateEncoder.cpp
#include "StdAfx.h"
#include "DeflateEncoder.h"
#include "Windows/Defs.h"
#include "Common/ComTry.h"
#include "../../../Common/Alloc.h"
// #include "../LZ/BinTree/BinTree3Z.h"
#if _MSC_VER >= 1300
#define NO_INLINE __declspec(noinline)
#else
#define NO_INLINE
#endif
extern "C"
{
#include "../../../../C/Compress/Huffman/HuffmanEncode.h"
}
namespace NCompress {
namespace NDeflate {
namespace NEncoder {
const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
const UInt32 kNumTables = (1 << kNumDivPassesMax);
static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
static UInt32 kDivideCodeBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))
static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))
static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * sizeof(UInt16);
static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize -
kMatchMaxLen - kNumOpts;
static const int kMaxCodeBitLength = 15;
static const int kMaxLevelBitLength = 7;
static Byte kNoLiteralStatPrice = 13;
static Byte kNoLenStatPrice = 13;
static Byte kNoPosStatPrice = 6;
static Byte g_LenSlots[kNumLenSymbolsMax];
static Byte g_FastPos[1 << 9];
class CFastPosInit
{
public:
CFastPosInit()
{
int i;
for(i = 0; i < kNumLenSlots; i++)
{
int c = kLenStart32[i];
int j = 1 << kLenDirectBits32[i];
for(int k = 0; k < j; k++, c++)
g_LenSlots[c] = (Byte)i;
}
const int kFastSlots = 18;
int c = 0;
for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)
{
UInt32 k = (1 << kDistDirectBits[slotFast]);
for (UInt32 j = 0; j < k; j++, c++)
g_FastPos[c] = slotFast;
}
}
};
static CFastPosInit g_FastPosInit;
inline UInt32 GetPosSlot(UInt32 pos)
{
if (pos < 0x200)
return g_FastPos[pos];
return g_FastPos[pos >> 8] + 16;
}
void *SzAlloc(size_t size)
{
if (size == 0)
return 0;
return malloc(size);
}
void SzFree(void *address)
{
free(address);
}
ISzAlloc g_Alloc = { SzAlloc, SzFree };
CCoder::CCoder(bool deflate64Mode):
m_Deflate64Mode(deflate64Mode),
m_NumPasses(1),
m_NumDivPasses(1),
m_NumFastBytes(32),
m_OnePosMatchesMemory(0),
m_DistanceMemory(0),
m_Created(false),
m_Values(0),
m_Tables(0),
m_MatchFinderCycles(0)
// m_SetMfPasses(0)
{
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
MatchFinder_Construct(&_lzInWindow);
}
HRESULT CCoder::Create()
{
COM_TRY_BEGIN
if (m_Values == 0)
{
m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue));
if (m_Values == 0)
return E_OUTOFMEMORY;
}
if (m_Tables == 0)
{
m_Tables = (CTables *)MyAlloc((kNumTables) * sizeof(CTables));
if (m_Tables == 0)
return E_OUTOFMEMORY;
}
if (m_IsMultiPass)
{
if (m_OnePosMatchesMemory == 0)
{
m_OnePosMatchesMemory = (UInt16 *)::MidAlloc(kMatchArraySize * sizeof(UInt16));
if (m_OnePosMatchesMemory == 0)
return E_OUTOFMEMORY;
}
}
else
{
if (m_DistanceMemory == 0)
{
m_DistanceMemory = (UInt16 *)MyAlloc((kMatchMaxLen + 2) * 2 * sizeof(UInt16));
if (m_DistanceMemory == 0)
return E_OUTOFMEMORY;
m_MatchDistances = m_DistanceMemory;
}
}
if (!m_Created)
{
_lzInWindow.btMode = 1;
_lzInWindow.numHashBytes = 3;
if (!MatchFinder_Create(&_lzInWindow,
m_Deflate64Mode ? kHistorySize64 : kHistorySize32,
kNumOpts + kMaxUncompressedBlockSize,
m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes, &g_Alloc))
return E_OUTOFMEMORY;
if (!m_OutStream.Create(1 << 20))
return E_OUTOFMEMORY;
}
if (m_MatchFinderCycles != 0)
_lzInWindow.cutValue = m_MatchFinderCycles;
m_Created = true;
return S_OK;
COM_TRY_END
}
// ICompressSetEncoderProperties2
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{
for(UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &prop = properties[i];
switch(propIDs[i])
{
case NCoderPropID::kNumPasses:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_NumDivPasses = prop.ulVal;
if (m_NumDivPasses == 0)
m_NumDivPasses = 1;
if (m_NumDivPasses == 1)
m_NumPasses = 1;
else if (m_NumDivPasses <= kNumDivPassesMax)
m_NumPasses = 2;
else
{
m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
m_NumDivPasses = kNumDivPassesMax;
}
break;
case NCoderPropID::kNumFastBytes:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_NumFastBytes = prop.ulVal;
if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen)
return E_INVALIDARG;
break;
case NCoderPropID::kMatchFinderCycles:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_MatchFinderCycles = prop.ulVal;
break;
}
default:
return E_INVALIDARG;
}
}
return S_OK;
}
void CCoder::Free()
{
::MidFree(m_OnePosMatchesMemory);
m_OnePosMatchesMemory = 0;
::MyFree(m_DistanceMemory);
m_DistanceMemory = 0;
::MyFree(m_Values);
m_Values = 0;
::MyFree(m_Tables);
m_Tables = 0;
}
CCoder::~CCoder()
{
Free();
MatchFinder_Free(&_lzInWindow, &g_Alloc);
}
void CCoder::GetMatches()
{
if (m_IsMultiPass)
{
m_MatchDistances = m_OnePosMatchesMemory + m_Pos;
if (m_SecondPass)
{
m_Pos += *m_MatchDistances + 1;
return;
}
}
UInt32 distanceTmp[kMatchMaxLen * 2 + 3];
UInt32 numPairs = Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp);
*m_MatchDistances = (UInt16)numPairs;
if (numPairs > 0)
{
UInt32 i;
for(i = 0; i < numPairs; i += 2)
{
m_MatchDistances[i + 1] = (UInt16)distanceTmp[i];
m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1];
}
UInt32 len = distanceTmp[numPairs - 2];
if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)
{
UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1;
const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1;
UInt32 distance = distanceTmp[numPairs - 1] + 1;
if (numAvail > m_MatchMaxLen)
numAvail = m_MatchMaxLen;
for (; len < numAvail && pby[len] == pby[(size_t)len - distance]; len++);
m_MatchDistances[i - 1] = (UInt16)len;
}
}
if (m_IsMultiPass)
m_Pos += numPairs + 1;
if (!m_SecondPass)
m_AdditionalOffset++;
}
void CCoder::MovePos(UInt32 num)
{
if (!m_SecondPass && num > 0)
{
Bt3Zip_MatchFinder_Skip(&_lzInWindow, num);
m_AdditionalOffset += num;
}
}
static const UInt32 kIfinityPrice = 0xFFFFFFF;
NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur)
{
m_OptimumEndIndex = cur;
UInt32 posMem = m_Optimum[cur].PosPrev;
UInt16 backMem = m_Optimum[cur].BackPrev;
do
{
UInt32 posPrev = posMem;
UInt16 backCur = backMem;
backMem = m_Optimum[posPrev].BackPrev;
posMem = m_Optimum[posPrev].PosPrev;
m_Optimum[posPrev].BackPrev = backCur;
m_Optimum[posPrev].PosPrev = (UInt16)cur;
cur = posPrev;
}
while(cur > 0);
backRes = m_Optimum[0].BackPrev;
m_OptimumCurrentIndex = m_Optimum[0].PosPrev;
return m_OptimumCurrentIndex;
}
NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
{
if(m_OptimumEndIndex != m_OptimumCurrentIndex)
{
UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex;
backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev;
m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev;
return len;
}
m_OptimumCurrentIndex = m_OptimumEndIndex = 0;
GetMatches();
UInt32 numDistancePairs = m_MatchDistances[0];
if(numDistancePairs == 0)
return 1;
const UInt16 *matchDistances = m_MatchDistances + 1;
UInt32 lenMain = matchDistances[numDistancePairs - 2];
if(lenMain > m_NumFastBytes)
{
backRes = matchDistances[numDistancePairs - 1];
MovePos(lenMain - 1);
return lenMain;
}
m_Optimum[1].Price = m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset)];
m_Optimum[1].PosPrev = 0;
m_Optimum[2].Price = kIfinityPrice;
m_Optimum[2].PosPrev = 1;
UInt32 offs = 0;
for(UInt32 i = kMatchMinLen; i <= lenMain; i++)
{
UInt32 distance = matchDistances[offs + 1];
m_Optimum[i].PosPrev = 0;
m_Optimum[i].BackPrev = (UInt16)distance;
m_Optimum[i].Price = m_LenPrices[i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];
if (i == matchDistances[offs])
offs += 2;
}
UInt32 cur = 0;
UInt32 lenEnd = lenMain;
for (;;)
{
++cur;
if(cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit)
return Backward(backRes, cur);
GetMatches();
matchDistances = m_MatchDistances + 1;
UInt32 numDistancePairs = m_MatchDistances[0];
UInt32 newLen = 0;
if(numDistancePairs != 0)
{
newLen = matchDistances[numDistancePairs - 2];
if(newLen > m_NumFastBytes)
{
UInt32 len = Backward(backRes, cur);
m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1];
m_OptimumEndIndex = cur + newLen;
m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex;
MovePos(newLen - 1);
return len;
}
}
UInt32 curPrice = m_Optimum[cur].Price;
UInt32 curAnd1Price = curPrice + m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, cur - m_AdditionalOffset)];
COptimal &optimum = m_Optimum[cur + 1];
if (curAnd1Price < optimum.Price)
{
optimum.Price = curAnd1Price;
optimum.PosPrev = (UInt16)cur;
}
if(numDistancePairs == 0)
continue;
while(lenEnd < cur + newLen)
m_Optimum[++lenEnd].Price = kIfinityPrice;
offs = 0;
UInt32 distance = matchDistances[offs + 1];
curPrice += m_PosPrices[GetPosSlot(distance)];
for(UInt32 lenTest = kMatchMinLen; ; lenTest++)
{
UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen];
COptimal &optimum = m_Optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
optimum.PosPrev = (UInt16)cur;
optimum.BackPrev = (UInt16)distance;
}
if (lenTest == matchDistances[offs])
{
offs += 2;
if (offs == numDistancePairs)
break;
curPrice -= m_PosPrices[GetPosSlot(distance)];
distance = matchDistances[offs + 1];
curPrice += m_PosPrices[GetPosSlot(distance)];
}
}
}
}
void CTables::InitStructures()
{
UInt32 i;
for(i = 0; i < 256; i++)
litLenLevels[i] = 8;
litLenLevels[i++] = 13;
for(;i < kFixedMainTableSize; i++)
litLenLevels[i] = 5;
for(i = 0; i < kFixedDistTableSize; i++)
distLevels[i] = 5;
}
NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs)
{
int prevLen = 0xFF;
int nextLen = levels[0];
int count = 0;
int maxCount = 7;
int minCount = 4;
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
for (int n = 0; n < numLevels; n++)
{
int curLen = nextLen;
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
count++;
if (count < maxCount && curLen == nextLen)
continue;
if (count < minCount)
freqs[curLen] += (UInt32)count;
else if (curLen != 0)
{
if (curLen != prevLen)
{
freqs[curLen]++;
count--;
}
freqs[kTableLevelRepNumber]++;
}
else if (count <= 10)
freqs[kTableLevel0Number]++;
else
freqs[kTableLevel0Number2]++;
count = 0;
prevLen = curLen;
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
else if (curLen == nextLen)
{
maxCount = 6;
minCount = 3;
}
else
{
maxCount = 7;
minCount = 4;
}
}
}
#define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i])
#define WRITE_HF(i) m_OutStream.WriteBits(codes[i], lens[i])
NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes)
{
int prevLen = 0xFF;
int nextLen = levels[0];
int count = 0;
int maxCount = 7;
int minCount = 4;
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
for (int n = 0; n < numLevels; n++)
{
int curLen = nextLen;
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
count++;
if (count < maxCount && curLen == nextLen)
continue;
if (count < minCount)
for(int i = 0; i < count; i++)
WRITE_HF(curLen);
else if (curLen != 0)
{
if (curLen != prevLen)
{
WRITE_HF(curLen);
count--;
}
WRITE_HF(kTableLevelRepNumber);
m_OutStream.WriteBits(count - 3, 2);
}
else if (count <= 10)
{
WRITE_HF(kTableLevel0Number);
m_OutStream.WriteBits(count - 3, 3);
}
else
{
WRITE_HF(kTableLevel0Number2);
m_OutStream.WriteBits(count - 11, 7);
}
count = 0;
prevLen = curLen;
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
else if (curLen == nextLen)
{
maxCount = 6;
minCount = 3;
}
else
{
maxCount = 7;
minCount = 4;
}
}
}
NO_INLINE void CCoder::MakeTables()
{
Huffman_Generate(mainFreqs, mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize, kMaxCodeBitLength);
Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, kMaxCodeBitLength);
}
NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num)
{
UInt32 price = 0;
UInt32 i;
for (i = 0; i < num; i++)
price += lens[i] * freqs[i];
return price;
};
NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase)
{
return Huffman_GetPrice(freqs, lens, num) +
Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase);
}
NO_INLINE UInt32 CCoder::GetLzBlockPrice() const
{
return
Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) +
Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, kDistTableSize64, kDistDirectBits, 0);
}
NO_INLINE void CCoder::TryBlock()
{
memset(mainFreqs, 0, sizeof(mainFreqs));
memset(distFreqs, 0, sizeof(distFreqs));
m_ValueIndex = 0;
UInt32 blockSize = BlockSizeRes;
BlockSizeRes = 0;
for (;;)
{
if (m_OptimumCurrentIndex == m_OptimumEndIndex)
{
if (m_Pos >= kMatchArrayLimit || BlockSizeRes >= blockSize || !m_SecondPass &&
((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize))
break;
}
UInt32 pos;
UInt32 len = GetOptimal(pos);
CCodeValue &codeValue = m_Values[m_ValueIndex++];
if (len >= kMatchMinLen)
{
UInt32 newLen = len - kMatchMinLen;
codeValue.Len = (UInt16)newLen;
mainFreqs[kSymbolMatch + g_LenSlots[newLen]]++;
codeValue.Pos = (UInt16)pos;
distFreqs[GetPosSlot(pos)]++;
}
else
{
Byte b = Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset);
mainFreqs[b]++;
codeValue.SetAsLiteral();
codeValue.Pos = b;
}
m_AdditionalOffset -= len;
BlockSizeRes += len;
}
mainFreqs[kSymbolEndOfBlock]++;
m_AdditionalOffset += BlockSizeRes;
m_SecondPass = true;
}
NO_INLINE void CCoder::SetPrices(const CLevels &levels)
{
UInt32 i;
for(i = 0; i < 256; i++)
{
Byte price = levels.litLenLevels[i];
m_LiteralPrices[i] = ((price != 0) ? price : kNoLiteralStatPrice);
}
for(i = 0; i < m_NumLenCombinations; i++)
{
UInt32 slot = g_LenSlots[i];
Byte price = levels.litLenLevels[kSymbolMatch + slot];
m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]);
}
for(i = 0; i < kDistTableSize64; i++)
{
Byte price = levels.distLevels[i];
m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]);
}
}
NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num)
{
for (UInt32 i = 0; i < num; i++)
{
UInt32 x = codes[i];
x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1);
x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2);
x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4);
codes[i] = (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - lens[i]);
}
}
NO_INLINE void CCoder::WriteBlock()
{
Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize);
Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64);
for (UInt32 i = 0; i < m_ValueIndex; i++)
{
const CCodeValue &codeValue = m_Values[i];
if (codeValue.IsLiteral())
WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, codeValue.Pos);
else
{
UInt32 len = codeValue.Len;
UInt32 lenSlot = g_LenSlots[len];
WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot);
m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]);
UInt32 dist = codeValue.Pos;
UInt32 posSlot = GetPosSlot(dist);
WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot);
m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]);
}
}
WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock);
}
static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition)
{
UInt32 price = 0;
do
{
UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7;
int numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;
price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8;
bitPosition = 0;
blockSize -= curBlockSize;
}
while(blockSize != 0);
return price;
}
void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock)
{
do
{
UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;
blockSize -= curBlockSize;
m_OutStream.WriteBits((finalBlock && (blockSize == 0) ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);
m_OutStream.WriteBits(NBlockType::kStored, kBlockTypeFieldSize);
m_OutStream.FlushByte();
m_OutStream.WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize);
m_OutStream.WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize);
const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset;
for(UInt32 i = 0; i < curBlockSize; i++)
m_OutStream.WriteByte(data[i]);
additionalOffset -= curBlockSize;
}
while(blockSize != 0);
}
NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses)
{
CTables &t = m_Tables[tableIndex];
BlockSizeRes = t.BlockSizeRes;
UInt32 posTemp = t.m_Pos;
SetPrices(t);
for (UInt32 p = 0; p < numPasses; p++)
{
m_Pos = posTemp;
TryBlock();
MakeTables();
SetPrices(m_NewLevels);
}
(CLevels &)t = m_NewLevels;
m_NumLitLenLevels = kMainTableSize;
while(m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0)
m_NumLitLenLevels--;
m_NumDistLevels = kDistTableSize64;
while(m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0)
m_NumDistLevels--;
UInt32 levelFreqs[kLevelTableSize];
memset(levelFreqs, 0, sizeof(levelFreqs));
LevelTableDummy(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelFreqs);
LevelTableDummy(m_NewLevels.distLevels, m_NumDistLevels, levelFreqs);
Huffman_Generate(levelFreqs, levelCodes, levelLens, kLevelTableSize, kMaxLevelBitLength);
m_NumLevelCodes = kNumLevelCodesMin;
for (UInt32 i = 0; i < kLevelTableSize; i++)
{
Byte level = levelLens[kCodeLengthAlphabetOrder[i]];
if (level > 0 && i >= m_NumLevelCodes)
m_NumLevelCodes = i + 1;
m_LevelLevels[i] = level;
}
return GetLzBlockPrice() +
Huffman_GetPrice_Spec(levelFreqs, levelLens, kLevelTableSize, kLevelDirectBits, kTableDirectLevels) +
kNumLenCodesFieldSize + kNumDistCodesFieldSize + kNumLevelCodesFieldSize +
m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize;
}
NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex)
{
CTables &t = m_Tables[tableIndex];
BlockSizeRes = t.BlockSizeRes;
m_Pos = t.m_Pos;
m_NewLevels.SetFixedLevels();
SetPrices(m_NewLevels);
TryBlock();
return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice();
}
NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses)
{
CTables &t = m_Tables[tableIndex];
t.StaticMode = false;
UInt32 price = TryDynBlock(tableIndex, m_NumPasses);
t.BlockSizeRes = BlockSizeRes;
UInt32 numValues = m_ValueIndex;
UInt32 posTemp = m_Pos;
UInt32 additionalOffsetEnd = m_AdditionalOffset;
if (m_CheckStatic && m_ValueIndex <= kFixedHuffmanCodeBlockSizeMax)
{
const UInt32 fixedPrice = TryFixedBlock(tableIndex);
t.StaticMode = (fixedPrice < price);
if (t.StaticMode)
price = fixedPrice;
}
const UInt32 storePrice = GetStorePrice(BlockSizeRes, 0); // bitPosition
t.StoreMode = (storePrice <= price);
if (t.StoreMode)
price = storePrice;
t.UseSubBlocks = false;
if (numDivPasses > 1 && numValues >= kDivideCodeBlockSizeMin)
{
CTables &t0 = m_Tables[(tableIndex << 1)];
(CLevels &)t0 = t;
t0.BlockSizeRes = t.BlockSizeRes >> 1;
t0.m_Pos = t.m_Pos;
UInt32 subPrice = GetBlockPrice((tableIndex << 1), numDivPasses - 1);
UInt32 blockSize2 = t.BlockSizeRes - t0.BlockSizeRes;
if (t0.BlockSizeRes >= kDivideBlockSizeMin && blockSize2 >= kDivideBlockSizeMin)
{
CTables &t1 = m_Tables[(tableIndex << 1) + 1];
(CLevels &)t1 = t;
t1.BlockSizeRes = blockSize2;
t1.m_Pos = m_Pos;
m_AdditionalOffset -= t0.BlockSizeRes;
subPrice += GetBlockPrice((tableIndex << 1) + 1, numDivPasses - 1);
t.UseSubBlocks = (subPrice < price);
if (t.UseSubBlocks)
price = subPrice;
}
}
m_AdditionalOffset = additionalOffsetEnd;
m_Pos = posTemp;
return price;
}
void CCoder::CodeBlock(int tableIndex, bool finalBlock)
{
CTables &t = m_Tables[tableIndex];
if (t.UseSubBlocks)
{
CodeBlock((tableIndex << 1), false);
CodeBlock((tableIndex << 1) + 1, finalBlock);
}
else
{
if (t.StoreMode)
WriteStoreBlock(t.BlockSizeRes, m_AdditionalOffset, finalBlock);
else
{
m_OutStream.WriteBits((finalBlock ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);
if (t.StaticMode)
{
m_OutStream.WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize);
TryFixedBlock(tableIndex);
int i;
for (i = 0; i < kFixedMainTableSize; i++)
mainFreqs[i] = (UInt32)1 << (kNumHuffmanBits - m_NewLevels.litLenLevels[i]);
for (i = 0; i < kFixedDistTableSize; i++)
distFreqs[i] = (UInt32)1 << (kNumHuffmanBits - m_NewLevels.distLevels[i]);
MakeTables();
}
else
{
if (m_NumDivPasses > 1 || m_CheckStatic)
TryDynBlock(tableIndex, 1);
m_OutStream.WriteBits(NBlockType::kDynamicHuffman, kBlockTypeFieldSize);
m_OutStream.WriteBits(m_NumLitLenLevels - kNumLitLenCodesMin, kNumLenCodesFieldSize);
m_OutStream.WriteBits(m_NumDistLevels - kNumDistCodesMin, kNumDistCodesFieldSize);
m_OutStream.WriteBits(m_NumLevelCodes - kNumLevelCodesMin, kNumLevelCodesFieldSize);
for (UInt32 i = 0; i < m_NumLevelCodes; i++)
m_OutStream.WriteBits(m_LevelLevels[i], kLevelFieldSize);
Huffman_ReverseBits(levelCodes, levelLens, kLevelTableSize);
LevelTableCode(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelLens, levelCodes);
LevelTableCode(m_NewLevels.distLevels, m_NumDistLevels, levelLens, levelCodes);
}
WriteBlock();
}
m_AdditionalOffset -= t.BlockSizeRes;
}
}
HRes Read(void *object, void *data, UInt32 size, UInt32 *processedSize)
{
return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize);
}
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */ , const UInt64 * /* outSize */ ,
ICompressProgressInfo *progress)
{
m_CheckStatic = (m_NumPasses != 1 || m_NumDivPasses != 1);
m_IsMultiPass = (m_CheckStatic || (m_NumPasses != 1 || m_NumDivPasses != 1));
RINOK(Create());
m_ValueBlockSize = (1 << 13) + (1 << 12) * m_NumDivPasses;
UInt64 nowPos = 0;
_seqInStream.RealStream = inStream;
_seqInStream.SeqInStream.Read = Read;
_lzInWindow.stream = &_seqInStream.SeqInStream;
MatchFinder_Init(&_lzInWindow);
m_OutStream.SetStream(outStream);
m_OutStream.Init();
CCoderReleaser coderReleaser(this);
m_OptimumEndIndex = m_OptimumCurrentIndex = 0;
CTables &t = m_Tables[1];
t.m_Pos = 0;
t.InitStructures();
m_AdditionalOffset = 0;
do
{
t.BlockSizeRes = kBlockUncompressedSizeThreshold;
m_SecondPass = false;
GetBlockPrice(1, m_NumDivPasses);
CodeBlock(1, Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0);
nowPos += m_Tables[1].BlockSizeRes;
if (progress != NULL)
{
UInt64 packSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&nowPos, &packSize));
}
}
while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);
if (_lzInWindow.result != SZ_OK)
return _lzInWindow.result;
return m_OutStream.Flush();
}
HRESULT CCoder::BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return E_FAIL; }
}
STDMETHODIMP CCOMCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{ return BaseCode(inStream, outStream, inSize, outSize, progress); }
STDMETHODIMP CCOMCoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{ return BaseSetEncoderProperties2(propIDs, properties, numProperties); }
STDMETHODIMP CCOMCoder64::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{ return BaseCode(inStream, outStream, inSize, outSize, progress); }
STDMETHODIMP CCOMCoder64::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{ return BaseSetEncoderProperties2(propIDs, properties, numProperties); }
}}}

View File

@@ -0,0 +1,221 @@
// DeflateEncoder.h
#ifndef __DEFLATE_ENCODER_H
#define __DEFLATE_ENCODER_H
#include "Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/LSBFEncoder.h"
#include "DeflateConst.h"
extern "C"
{
#include "../../../../C/Compress/Lz/MatchFinder.h"
}
namespace NCompress {
namespace NDeflate {
namespace NEncoder {
struct CCodeValue
{
UInt16 Len;
UInt16 Pos;
void SetAsLiteral() { Len = (1 << 15); }
bool IsLiteral() const { return ((Len & (1 << 15)) != 0); }
};
struct COptimal
{
UInt32 Price;
UInt16 PosPrev;
UInt16 BackPrev;
};
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();
};
typedef struct _CSeqInStream
{
ISeqInStream SeqInStream;
CMyComPtr<ISequentialInStream> RealStream;
} CSeqInStream;
class CCoder
{
CMatchFinder _lzInWindow;
NStream::NLSBF::CEncoder m_OutStream;
CSeqInStream _seqInStream;
public:
CCodeValue *m_Values;
UInt16 *m_MatchDistances;
UInt32 m_NumFastBytes;
UInt16 *m_OnePosMatchesMemory;
UInt16 *m_DistanceMemory;
UInt32 m_Pos;
int m_NumPasses;
int m_NumDivPasses;
bool m_CheckStatic;
bool m_IsMultiPass;
UInt32 m_ValueBlockSize;
UInt32 m_NumLenCombinations;
UInt32 m_MatchMaxLen;
const Byte *m_LenStart;
const Byte *m_LenDirectBits;
bool m_Created;
bool m_Deflate64Mode;
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 mainFreqs[kFixedMainTableSize];
UInt32 distFreqs[kDistTableSize64];
UInt32 mainCodes[kFixedMainTableSize];
UInt32 distCodes[kDistTableSize64];
UInt32 levelCodes[kLevelTableSize];
Byte levelLens[kLevelTableSize];
UInt32 BlockSizeRes;
CTables *m_Tables;
COptimal m_Optimum[kNumOpts];
UInt32 m_MatchFinderCycles;
// IMatchFinderSetNumPasses *m_SetMfPasses;
void GetMatches();
void MovePos(UInt32 num);
UInt32 Backward(UInt32 &backRes, UInt32 cur);
UInt32 GetOptimal(UInt32 &backRes);
void LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs);
void LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes);
void MakeTables();
UInt32 GetLzBlockPrice() const;
void TryBlock();
UInt32 TryDynBlock(int tableIndex, UInt32 numPasses);
UInt32 TryFixedBlock(int tableIndex);
void SetPrices(const CLevels &levels);
void WriteBlock();
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 ReleaseStreams()
{
_seqInStream.RealStream.Release();
m_OutStream.ReleaseStream();
}
class CCoderReleaser
{
CCoder *m_Coder;
public:
CCoderReleaser(CCoder *coder): m_Coder(coder) {}
~CCoderReleaser() { m_Coder->ReleaseStreams(); }
};
friend class CCoderReleaser;
UInt32 GetBlockPrice(int tableIndex, int numDivPasses);
void CodeBlock(int tableIndex, bool finalBlock);
public:
CCoder(bool deflate64Mode = false);
~CCoder();
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
HRESULT BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
HRESULT BaseSetEncoderProperties2(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
};
///////////////////////////////////////////////////////////////
class CCOMCoder :
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp,
public CCoder
{
public:
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
CCOMCoder(): CCoder(false) {};
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
};
class CCOMCoder64 :
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp,
public CCoder
{
public:
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
CCOMCoder64(): CCoder(true) {};
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
};
}}}
#endif

View File

@@ -0,0 +1,157 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "DeflateEncoder.h"
#include "DeflateDecoder.h"
#ifdef CRC_GENERATE_TABLE
extern "C"
{
#include "../../../../C/7zCrc.h"
}
#endif
// {23170F69-40C1-278B-0401-080000000000}
DEFINE_GUID(CLSID_CCompressDeflateDecoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0401-090000000000}
DEFINE_GUID(CLSID_CCompressDeflate64Decoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0401-080000000100}
DEFINE_GUID(CLSID_CCompressDeflateEncoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00);
// {23170F69-40C1-278B-0401-090000000100}
DEFINE_GUID(CLSID_CCompressDeflate64Encoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00);
// {23170F69-40C1-278B-0409-010000000000}
DEFINE_GUID(CLSID_CCompressDeflateNsisDecoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
#ifdef CRC_GENERATE_TABLE
CrcGenerateTable();
#endif
}
return TRUE;
}
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
COM_TRY_BEGIN
*outObject = 0;
int correctInterface = (*iid == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
if (*clsid == CLSID_CCompressDeflateDecoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NDeflate::NDecoder::CCOMCoder();
}
else if (*clsid == CLSID_CCompressDeflateNsisDecoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NDeflate::NDecoder::CNsisCOMCoder();
}
else if (*clsid == CLSID_CCompressDeflateEncoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NDeflate::NEncoder::CCOMCoder();
}
else if (*clsid == CLSID_CCompressDeflate64Decoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NDeflate::NDecoder::CCOMCoder64();
}
else if (*clsid == CLSID_CCompressDeflate64Encoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NDeflate::NEncoder::CCOMCoder64();
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = coder.Detach();
COM_TRY_END
return S_OK;
}
struct CDeflateMethodItem
{
char ID[3];
const wchar_t *UserName;
const GUID *Decoder;
const GUID *Encoder;
};
#define METHOD_ITEM(Name, id, UserName) \
{ { 0x04, 0x01, id }, UserName, \
&CLSID_CCompress ## Name ## Decoder, \
&CLSID_CCompress ## Name ## Encoder }
#define METHOD_ITEM_DE(Name, id1, id2, UserName) \
{ { 0x04, id1, id2 }, UserName, \
&CLSID_CCompress ## Name ## Decoder, NULL }
static CDeflateMethodItem g_Methods[] =
{
METHOD_ITEM(Deflate, 0x08, L"Deflate"),
METHOD_ITEM(Deflate64, 0x09, L"Deflate64"),
METHOD_ITEM_DE(DeflateNsis, 0x09, 0x01, L"DeflateNSIS")
};
STDAPI GetNumberOfMethods(UINT32 *numMethods)
{
*numMethods = sizeof(g_Methods) / sizeof(g_Methods[0]);
return S_OK;
}
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
if (index > sizeof(g_Methods) / sizeof(g_Methods[0]))
return E_INVALIDARG;
VariantClear((tagVARIANT *)value);
const CDeflateMethodItem &method = g_Methods[index];
switch(propID)
{
case NMethodPropID::kID:
if ((value->bstrVal = ::SysAllocStringByteLen(method.ID,
sizeof(method.ID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(method.UserName)) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)method.Decoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kEncoder:
if (method.Encoder)
{
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)method.Encoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
}
return S_OK;
}
return S_OK;
}

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

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

View File

@@ -0,0 +1,63 @@
PROG = Deflate.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../ -D_ST_MODE
LIBS = $(LIBS) oleaut32.lib
DEFLATE_OBJS = \
$O\DllExports.obj \
DEFLATE_OPT_OBJS = \
$O\DeflateDecoder.obj \
$O\DeflateEncoder.obj \
COMMON_OBJS = \
$O\Alloc.obj \
$O\CRC.obj \
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
$O\LSBFDecoder.obj \
$O\LSBFEncoder.obj \
LZ_OBJS = \
$O\LZOutWindow.obj \
C_OBJS = \
$O\7zCrc.obj \
$O\Sort.obj \
C_LZ_OBJS = \
$O\MatchFinder.obj \
OBJS = \
$O\StdAfx.obj \
$(DEFLATE_OBJS) \
$(DEFLATE_OPT_OBJS) \
$(COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(LZ_OBJS) \
$(C_OBJS) \
$(C_LZ_OBJS) \
$O\HuffmanEncode.obj \
$O\resource.res
!include "../../../Build.mak"
$(DEFLATE_OBJS): $(*B).cpp
$(COMPL)
$(DEFLATE_OPT_OBJS): $(*B).cpp
$(COMPL_O2)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$(LZ_OBJS): ../LZ/$(*B).cpp
$(COMPL)
$(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2)
$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
$(COMPL_O2)
$O\HuffmanEncode.obj: ../../../../C/Compress/Huffman/$(*B).c
$(COMPL_O2)

View File

@@ -0,0 +1,3 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_DLL("Deflate Codec", "Deflate")