mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 20:11:35 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
65
CPP/7zip/Compress/Implode/DllExports.cpp
Executable file
65
CPP/7zip/Compress/Implode/DllExports.cpp
Executable file
@@ -0,0 +1,65 @@
|
||||
// DLLExports.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/MyInitGuid.h"
|
||||
#include "Common/ComTry.h"
|
||||
#include "ImplodeDecoder.h"
|
||||
|
||||
// {23170F69-40C1-278B-0401-060000000000}
|
||||
DEFINE_GUID(CLSID_CCompressImplodeDecoder,
|
||||
0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*outObject = 0;
|
||||
if (*clsid != CLSID_CCompressImplodeDecoder)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
if (*iid != IID_ICompressCoder)
|
||||
return E_NOINTERFACE;
|
||||
CMyComPtr<ICompressCoder> coder = (ICompressCoder *)new
|
||||
NCompress::NImplode::NDecoder::CCoder;
|
||||
*outObject = coder.Detach();
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetNumberOfMethods(UINT32 *numMethods)
|
||||
{
|
||||
*numMethods = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
if (index != 0)
|
||||
return E_INVALIDARG;
|
||||
::VariantClear((tagVARIANT *)value);
|
||||
switch(propID)
|
||||
{
|
||||
case NMethodPropID::kID:
|
||||
{
|
||||
const char id[] = { 0x04, 0x01, 0x06 };
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
case NMethodPropID::kName:
|
||||
if ((value->bstrVal = ::SysAllocString(L"Implode")) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
case NMethodPropID::kDecoder:
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(
|
||||
(const char *)&CLSID_CCompressImplodeDecoder, sizeof(GUID))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
222
CPP/7zip/Compress/Implode/ImplodeDecoder.cpp
Executable file
222
CPP/7zip/Compress/Implode/ImplodeDecoder.cpp
Executable file
@@ -0,0 +1,222 @@
|
||||
// Implode/Decoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ImplodeDecoder.h"
|
||||
#include "Common/Defs.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NDecoder {
|
||||
|
||||
class CException
|
||||
{
|
||||
public:
|
||||
enum ECauseType
|
||||
{
|
||||
kData
|
||||
} m_Cause;
|
||||
CException(ECauseType cause): m_Cause(cause) {}
|
||||
};
|
||||
|
||||
static const int kNumDistanceLowDirectBitsForBigDict = 7;
|
||||
static const int kNumDistanceLowDirectBitsForSmallDict = 6;
|
||||
|
||||
static const int kNumBitsInByte = 8;
|
||||
|
||||
static const int kLevelStructuresNumberFieldSize = kNumBitsInByte;
|
||||
static const int kLevelStructuresNumberAdditionalValue = 1;
|
||||
|
||||
static const int kNumLevelStructureLevelBits = 4;
|
||||
static const int kLevelStructureLevelAdditionalValue = 1;
|
||||
|
||||
static const int kNumLevelStructureRepNumberBits = 4;
|
||||
static const int kLevelStructureRepNumberAdditionalValue = 1;
|
||||
|
||||
|
||||
static const int kLiteralTableSize = (1 << kNumBitsInByte);
|
||||
static const int kDistanceTableSize = 64;
|
||||
static const int kLengthTableSize = 64;
|
||||
|
||||
static const UInt32 kHistorySize =
|
||||
(1 << MyMax(kNumDistanceLowDirectBitsForBigDict,
|
||||
kNumDistanceLowDirectBitsForSmallDict)) *
|
||||
kDistanceTableSize; // = 8 KB;
|
||||
|
||||
static const int kNumAdditionalLengthBits = 8;
|
||||
|
||||
static const UInt32 kMatchMinLenWhenLiteralsOn = 3;
|
||||
static const UInt32 kMatchMinLenWhenLiteralsOff = 2;
|
||||
|
||||
static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn,
|
||||
kMatchMinLenWhenLiteralsOff); // 3
|
||||
|
||||
static const UInt32 kMatchMaxLenMax = kMatchMinLenMax +
|
||||
(kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 2
|
||||
|
||||
enum
|
||||
{
|
||||
kMatchId = 0,
|
||||
kLiteralId = 1
|
||||
};
|
||||
|
||||
|
||||
CCoder::CCoder():
|
||||
m_LiteralDecoder(kLiteralTableSize),
|
||||
m_LengthDecoder(kLengthTableSize),
|
||||
m_DistanceDecoder(kDistanceTableSize)
|
||||
{
|
||||
}
|
||||
|
||||
void CCoder::ReleaseStreams()
|
||||
{
|
||||
m_OutWindowStream.ReleaseStream();
|
||||
m_InBitStream.ReleaseStream();
|
||||
}
|
||||
|
||||
bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder,
|
||||
Byte *levels, int numLevelItems)
|
||||
{
|
||||
int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) +
|
||||
kLevelStructuresNumberAdditionalValue;
|
||||
int currentIndex = 0;
|
||||
for(int i = 0; i < numCodedStructures; i++)
|
||||
{
|
||||
int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) +
|
||||
kLevelStructureLevelAdditionalValue;
|
||||
int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) +
|
||||
kLevelStructureRepNumberAdditionalValue;
|
||||
if (currentIndex + rep > numLevelItems)
|
||||
throw CException(CException::kData);
|
||||
for(int j = 0; j < rep; j++)
|
||||
levels[currentIndex++] = (Byte)level;
|
||||
}
|
||||
if (currentIndex != numLevelItems)
|
||||
return false;
|
||||
return decoder.SetCodeLengths(levels);
|
||||
}
|
||||
|
||||
|
||||
bool CCoder::ReadTables(void)
|
||||
{
|
||||
if (m_LiteralsOn)
|
||||
{
|
||||
Byte literalLevels[kLiteralTableSize];
|
||||
if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize))
|
||||
return false;
|
||||
}
|
||||
|
||||
Byte lengthLevels[kLengthTableSize];
|
||||
if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize))
|
||||
return false;
|
||||
|
||||
Byte distanceLevels[kDistanceTableSize];
|
||||
return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize);
|
||||
}
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CCoder *m_Coder;
|
||||
public:
|
||||
CCoderReleaser(CCoder *coder): m_Coder(coder) {}
|
||||
~CCoderReleaser() { m_Coder->ReleaseStreams(); }
|
||||
};
|
||||
|
||||
STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_OutWindowStream.Create(kHistorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
UInt64 pos = 0, unPackSize = *outSize;
|
||||
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
m_OutWindowStream.Init(false);
|
||||
m_InBitStream.SetStream(inStream);
|
||||
m_InBitStream.Init();
|
||||
CCoderReleaser coderReleaser(this);
|
||||
|
||||
if (!ReadTables())
|
||||
return S_FALSE;
|
||||
|
||||
while(pos < unPackSize)
|
||||
{
|
||||
if (progress != NULL && pos % (1 << 16) == 0)
|
||||
{
|
||||
UInt64 packSize = m_InBitStream.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos));
|
||||
}
|
||||
if(m_InBitStream.ReadBits(1) == kMatchId) // match
|
||||
{
|
||||
UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);
|
||||
UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (distance >= kDistanceTableSize)
|
||||
return S_FALSE;
|
||||
distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;
|
||||
UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (lengthSymbol >= kLengthTableSize)
|
||||
return S_FALSE;
|
||||
UInt32 length = lengthSymbol + m_MinMatchLength;
|
||||
if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63
|
||||
length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);
|
||||
while(distance >= pos && length > 0)
|
||||
{
|
||||
m_OutWindowStream.PutByte(0);
|
||||
pos++;
|
||||
length--;
|
||||
}
|
||||
if (length > 0)
|
||||
m_OutWindowStream.CopyBlock(distance, length);
|
||||
pos += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte b;
|
||||
if (m_LiteralsOn)
|
||||
{
|
||||
UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (temp >= kLiteralTableSize)
|
||||
return S_FALSE;
|
||||
b = (Byte)temp;
|
||||
}
|
||||
else
|
||||
b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);
|
||||
m_OutWindowStream.PutByte(b);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
if (pos > unPackSize)
|
||||
throw CException(CException::kData);
|
||||
return m_OutWindowStream.Flush();
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
|
||||
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size < 1)
|
||||
return E_INVALIDARG;
|
||||
Byte flag = data[0];
|
||||
m_BigDictionaryOn = ((flag & 2) != 0);
|
||||
m_NumDistanceLowDirectBits = m_BigDictionaryOn ?
|
||||
kNumDistanceLowDirectBitsForBigDict:
|
||||
kNumDistanceLowDirectBitsForSmallDict;
|
||||
m_LiteralsOn = ((flag & 4) != 0);
|
||||
m_MinMatchLength = m_LiteralsOn ?
|
||||
kMatchMinLenWhenLiteralsOn :
|
||||
kMatchMinLenWhenLiteralsOff;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}}
|
||||
60
CPP/7zip/Compress/Implode/ImplodeDecoder.h
Executable file
60
CPP/7zip/Compress/Implode/ImplodeDecoder.h
Executable file
@@ -0,0 +1,60 @@
|
||||
// ImplodeDecoder.h
|
||||
|
||||
#ifndef __IMPLODE_DECODER_H
|
||||
#define __IMPLODE_DECODER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../LZ/LZOutWindow.h"
|
||||
|
||||
#include "ImplodeHuffmanDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NDecoder {
|
||||
|
||||
class CCoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetDecoderProperties2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
NStream::NLSBF::CDecoder<CInBuffer> m_InBitStream;
|
||||
|
||||
NImplode::NHuffman::CDecoder m_LiteralDecoder;
|
||||
NImplode::NHuffman::CDecoder m_LengthDecoder;
|
||||
NImplode::NHuffman::CDecoder m_DistanceDecoder;
|
||||
|
||||
bool m_BigDictionaryOn;
|
||||
bool m_LiteralsOn;
|
||||
|
||||
int m_NumDistanceLowDirectBits;
|
||||
UInt32 m_MinMatchLength;
|
||||
|
||||
bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems);
|
||||
bool ReadTables();
|
||||
void DeCodeLevelTable(Byte *newLevels, int numLevels);
|
||||
public:
|
||||
CCoder();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
|
||||
|
||||
void ReleaseStreams();
|
||||
HRESULT (Flush)() { return m_OutWindowStream.Flush(); }
|
||||
|
||||
STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
// ICompressSetDecoderProperties
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
89
CPP/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp
Executable file
89
CPP/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp
Executable file
@@ -0,0 +1,89 @@
|
||||
// ImplodeHuffmanDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ImplodeHuffmanDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NHuffman {
|
||||
|
||||
CDecoder::CDecoder(UInt32 numSymbols):
|
||||
m_NumSymbols(numSymbols)
|
||||
{
|
||||
m_Symbols = new UInt32[m_NumSymbols];
|
||||
}
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
delete []m_Symbols;
|
||||
}
|
||||
|
||||
bool CDecoder::SetCodeLengths(const Byte *codeLengths)
|
||||
{
|
||||
// int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
|
||||
int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1];
|
||||
int i;
|
||||
for(i = 0; i <= kNumBitsInLongestCode; i++)
|
||||
lenCounts[i] = 0;
|
||||
UInt32 symbolIndex;
|
||||
for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)
|
||||
lenCounts[codeLengths[symbolIndex]]++;
|
||||
// lenCounts[0] = 0;
|
||||
|
||||
// tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;
|
||||
m_Limitits[kNumBitsInLongestCode + 1] = 0;
|
||||
m_Positions[kNumBitsInLongestCode + 1] = 0;
|
||||
lenCounts[kNumBitsInLongestCode + 1] = 0;
|
||||
|
||||
|
||||
UInt32 startPos = 0;
|
||||
static const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);
|
||||
|
||||
for (i = kNumBitsInLongestCode; i > 0; i--)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsInLongestCode - i);
|
||||
if (startPos > kMaxValue)
|
||||
return false;
|
||||
m_Limitits[i] = startPos;
|
||||
m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1];
|
||||
tmpPositions[i] = m_Positions[i] + lenCounts[i];
|
||||
|
||||
}
|
||||
|
||||
// if _ZIP_MODE do not throw exception for trees containing only one node
|
||||
// #ifndef _ZIP_MODE
|
||||
if (startPos != kMaxValue)
|
||||
return false;
|
||||
// #endif
|
||||
|
||||
for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)
|
||||
if (codeLengths[symbolIndex] != 0)
|
||||
m_Symbols[--tmpPositions[codeLengths[symbolIndex]]] = symbolIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt32 CDecoder::DecodeSymbol(CInBit *inStream)
|
||||
{
|
||||
UInt32 numBits = 0;
|
||||
UInt32 value = inStream->GetValue(kNumBitsInLongestCode);
|
||||
int i;
|
||||
for(i = kNumBitsInLongestCode; i > 0; i--)
|
||||
{
|
||||
if (value < m_Limitits[i])
|
||||
{
|
||||
numBits = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 0)
|
||||
return 0xFFFFFFFF;
|
||||
inStream->MovePos(numBits);
|
||||
UInt32 index = m_Positions[numBits] +
|
||||
((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits));
|
||||
if (index >= m_NumSymbols)
|
||||
return 0xFFFFFFFF;
|
||||
return m_Symbols[index];
|
||||
}
|
||||
|
||||
}}}
|
||||
33
CPP/7zip/Compress/Implode/ImplodeHuffmanDecoder.h
Executable file
33
CPP/7zip/Compress/Implode/ImplodeHuffmanDecoder.h
Executable file
@@ -0,0 +1,33 @@
|
||||
// ImplodeHuffmanDecoder.h
|
||||
|
||||
#ifndef __IMPLODE_HUFFMAN_DECODER_H
|
||||
#define __IMPLODE_HUFFMAN_DECODER_H
|
||||
|
||||
#include "../../Common/LSBFDecoder.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NHuffman {
|
||||
|
||||
const int kNumBitsInLongestCode = 16;
|
||||
|
||||
typedef NStream::NLSBF::CDecoder<CInBuffer> CInBit;
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
UInt32 m_Limitits[kNumBitsInLongestCode + 2]; // m_Limitits[i] = value limit for symbols with length = i
|
||||
UInt32 m_Positions[kNumBitsInLongestCode + 2]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
|
||||
UInt32 m_NumSymbols; // number of symbols in m_Symbols
|
||||
UInt32 *m_Symbols; // symbols: at first with len=1 then 2, ... 15.
|
||||
public:
|
||||
CDecoder(UInt32 numSymbols);
|
||||
~CDecoder();
|
||||
|
||||
bool SetCodeLengths(const Byte *codeLengths);
|
||||
UInt32 DecodeSymbol(CInBit *inStream);
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
3
CPP/7zip/Compress/Implode/StdAfx.cpp
Executable file
3
CPP/7zip/Compress/Implode/StdAfx.cpp
Executable file
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
8
CPP/7zip/Compress/Implode/StdAfx.h
Executable file
8
CPP/7zip/Compress/Implode/StdAfx.h
Executable file
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user