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,319 @@
// Arj/Decoder.cpp
#include "StdAfx.h"
#include "ArjDecoder1.h"
#include "Windows/Defs.h"
namespace NCompress{
namespace NArj {
namespace NDecoder1 {
static const UInt32 kHistorySize = 26624;
static const UInt32 kMatchMaxLen = 256;
static const UInt32 kMatchMinLen = 3;
static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;
void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits,
UInt32 *table, int tablesize)
{
UInt32 count[17], weight[17], start[18], *p;
UInt32 i, k, len, ch, jutbits, avail, nextcode, mask;
for (i = 1; i <= 16; i++)
count[i] = 0;
for (i = 0; (int)i < nchar; i++)
count[bitlen[i]]++;
start[1] = 0;
for (i = 1; i <= 16; i++)
start[i + 1] = start[i] + (count[i] << (16 - i));
if (start[17] != (UInt32) (1 << 16))
throw "Data error";
jutbits = 16 - tablebits;
for (i = 1; (int)i <= tablebits; i++)
{
start[i] >>= jutbits;
weight[i] = 1 << (tablebits - i);
}
while (i <= 16)
{
weight[i] = 1 << (16 - i);
i++;
}
i = start[tablebits + 1] >> jutbits;
if (i != (UInt32) (1 << 16))
{
k = 1 << tablebits;
while (i != k)
table[i++] = 0;
}
avail = nchar;
mask = 1 << (15 - tablebits);
for (ch = 0; (int)ch < nchar; ch++)
{
if ((len = bitlen[ch]) == 0)
continue;
k = start[len];
nextcode = k + weight[len];
if ((int)len <= tablebits)
{
if (nextcode > (UInt32)tablesize)
throw "Data error";
for (i = start[len]; i < nextcode; i++)
table[i] = ch;
}
else
{
p = &table[k >> jutbits];
i = len - tablebits;
while (i != 0)
{
if (*p == 0)
{
right[avail] = left[avail] = 0;
*p = avail++;
}
if (k & mask)
p = &right[*p];
else
p = &left[*p];
k <<= 1;
i--;
}
*p = ch;
}
start[len] = nextcode;
}
}
void CCoder::read_pt_len(int nn, int nbit, int i_special)
{
UInt32 n = m_InBitStream.ReadBits(nbit);
if (n == 0)
{
UInt32 c = m_InBitStream.ReadBits(nbit);
int i;
for (i = 0; i < nn; i++)
pt_len[i] = 0;
for (i = 0; i < 256; i++)
pt_table[i] = c;
}
else
{
UInt32 i = 0;
while (i < n)
{
UInt32 bitBuf = m_InBitStream.GetValue(16);
int c = bitBuf >> 13;
if (c == 7)
{
UInt32 mask = 1 << (12);
while (mask & bitBuf)
{
mask >>= 1;
c++;
}
}
m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3));
pt_len[i++] = (Byte)c;
if (i == (UInt32)i_special)
{
c = m_InBitStream.ReadBits(2);
while (--c >= 0)
pt_len[i++] = 0;
}
}
while (i < (UInt32)nn)
pt_len[i++] = 0;
MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE);
}
}
void CCoder::read_c_len()
{
int i, c, n;
UInt32 mask;
n = m_InBitStream.ReadBits(CBIT);
if (n == 0)
{
c = m_InBitStream.ReadBits(CBIT);
for (i = 0; i < NC; i++)
c_len[i] = 0;
for (i = 0; i < CTABLESIZE; i++)
c_table[i] = c;
}
else
{
i = 0;
while (i < n)
{
UInt32 bitBuf = m_InBitStream.GetValue(16);
c = pt_table[bitBuf >> (8)];
if (c >= NT)
{
mask = 1 << (7);
do
{
if (bitBuf & mask)
c = right[c];
else
c = left[c];
mask >>= 1;
} while (c >= NT);
}
m_InBitStream.MovePos((int)(pt_len[c]));
if (c <= 2)
{
if (c == 0)
c = 1;
else if (c == 1)
c = m_InBitStream.ReadBits(4) + 3;
else
c = m_InBitStream.ReadBits(CBIT) + 20;
while (--c >= 0)
c_len[i++] = 0;
}
else
c_len[i++] = (Byte)(c - 2);
}
while (i < NC)
c_len[i++] = 0;
MakeTable(NC, c_len, 12, c_table, CTABLESIZE);
}
}
UInt32 CCoder::decode_c()
{
UInt32 j, mask;
UInt32 bitbuf = m_InBitStream.GetValue(16);
j = c_table[bitbuf >> 4];
if (j >= NC)
{
mask = 1 << (3);
do
{
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= NC);
}
m_InBitStream.MovePos((int)(c_len[j]));
return j;
}
UInt32 CCoder::decode_p()
{
UInt32 j, mask;
UInt32 bitbuf = m_InBitStream.GetValue(16);
j = pt_table[bitbuf >> (8)];
if (j >= NP)
{
mask = 1 << (7);
do
{
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= NP);
}
m_InBitStream.MovePos((int)(pt_len[j]));
if (j != 0)
{
j--;
j = (1 << j) + m_InBitStream.ReadBits((int)j);
}
return j;
}
STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (outSize == NULL)
return E_INVALIDARG;
if (!m_OutWindowStream.Create(kHistorySize))
return E_OUTOFMEMORY;
if (!m_InBitStream.Create(1 << 20))
return E_OUTOFMEMORY;
int size1 = sizeof(c_table) / sizeof(c_table[0]);
for (int i = 0; i < size1; i++)
{
if (i % 100 == 0)
c_table[i] = 0;
c_table[i] = 0;
}
UInt64 pos = 0;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(false);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
UInt32 blockSize = 0;
while(pos < *outSize)
{
if (blockSize == 0)
{
if (progress != NULL)
{
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
blockSize = m_InBitStream.ReadBits(16);
read_pt_len(NT, TBIT, 3);
read_c_len();
read_pt_len(NP, PBIT, -1);
}
blockSize--;
UInt32 number = decode_c();
if (number < 256)
{
m_OutWindowStream.PutByte((Byte)number);
pos++;
continue;
}
else
{
UInt32 len = number - 256 + kMatchMinLen;
UInt32 distance = decode_p();
if (distance >= pos)
throw "data error";
m_OutWindowStream.CopyBlock(distance, len);
pos += len;
}
}
coderReleaser.NeedFlush = false;
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 CInBufferException &e) { return e.ErrorCode; }
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
}}}

View File

@@ -0,0 +1,105 @@
// Arj/Decoder1.h
#ifndef __COMPRESS_ARJ_DECODER1_H
#define __COMPRESS_ARJ_DECODER1_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../LZ/LZOutWindow.h"
/*
// {23170F69-40C1-278B-0404-010000000000}
DEFINE_GUID(CLSID_CCompressArjDecoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
*/
namespace NCompress {
namespace NArj {
namespace NDecoder1 {
#define CODE_BIT 16
#define THRESHOLD 3
#define DDICSIZ 26624
#define MAXDICBIT 16
#define MATCHBIT 8
#define MAXMATCH 256
#define NC (0xFF + MAXMATCH + 2 - THRESHOLD)
#define NP (MAXDICBIT + 1)
#define CBIT 9
#define NT (CODE_BIT + 3)
#define PBIT 5
#define TBIT 5
#if NT > NP
#define NPT NT
#else
#define NPT NP
#endif
#define CTABLESIZE 4096
#define PTABLESIZE 256
class CCoder :
public ICompressCoder,
public CMyUnknownImp
{
CLZOutWindow m_OutWindowStream;
NStream::NMSBF::CDecoder<CInBuffer> m_InBitStream;
UInt32 left[2 * NC - 1];
UInt32 right[2 * NC - 1];
Byte c_len[NC];
Byte pt_len[NPT];
UInt32 c_table[CTABLESIZE];
UInt32 pt_table[PTABLESIZE];
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
}
class CCoderReleaser
{
CCoder *m_Coder;
public:
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
if (NeedFlush)
m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
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);
UInt32 decode_c();
UInt32 decode_p();
public:
MY_UNKNOWN_IMP
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);
};
}}}
#endif

View File

@@ -0,0 +1,93 @@
// Arj/Decoder2.cpp
#include "StdAfx.h"
#include "ArjDecoder2.h"
namespace NCompress{
namespace NArj {
namespace NDecoder2 {
static const UInt32 kHistorySize = 26624;
static const UInt32 kMatchMaxLen = 256;
static const UInt32 kMatchMinLen = 3;
STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo * /* progress */)
{
if (outSize == NULL)
return E_INVALIDARG;
if (!m_OutWindowStream.Create(kHistorySize))
return E_OUTOFMEMORY;
if (!m_InBitStream.Create(1 << 20))
return E_OUTOFMEMORY;
UInt64 pos = 0;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(false);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
while(pos < *outSize)
{
const UInt32 kStartWidth = 0;
const UInt32 kStopWidth = 7;
UInt32 power = 1 << kStartWidth;
UInt32 width;
UInt32 len = 0;
for (width = kStartWidth; width < kStopWidth; width++)
{
if (m_InBitStream.ReadBits(1) == 0)
break;
len += power;
power <<= 1;
}
if (width != 0)
len += m_InBitStream.ReadBits(width);
if (len == 0)
{
m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
pos++;
continue;
}
else
{
len = len - 1 + kMatchMinLen;
const UInt32 kStartWidth = 9;
const UInt32 kStopWidth = 13;
UInt32 power = 1 << kStartWidth;
UInt32 width;
UInt32 distance = 0;
for (width = kStartWidth; width < kStopWidth; width++)
{
if (m_InBitStream.ReadBits(1) == 0)
break;
distance += power;
power <<= 1;
}
if (width != 0)
distance += m_InBitStream.ReadBits(width);
if (distance >= pos)
throw "data error";
m_OutWindowStream.CopyBlock(distance, len);
pos += len;
}
}
coderReleaser.NeedFlush = false;
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 CInBufferException &e) { return e.ErrorCode; }
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
}}}

View File

@@ -0,0 +1,65 @@
// Arj/Decoder2.h
#ifndef __COMPRESS_ARJ_DECODER2_H
#define __COMPRESS_ARJ_DECODER2_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../LZ/LZOutWindow.h"
/*
// {23170F69-40C1-278B-0404-020000000000}
DEFINE_GUID(CLSID_CCompressArj2Decoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
*/
namespace NCompress {
namespace NArj {
namespace NDecoder2 {
class CCoder :
public ICompressCoder,
public CMyUnknownImp
{
CLZOutWindow m_OutWindowStream;
NStream::NMSBF::CDecoder<CInBuffer> m_InBitStream;
void ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
}
class CCoderReleaser
{
CCoder *m_Coder;
public:
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
if (NeedFlush)
m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
public:
MY_UNKNOWN_IMP
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);
};
}}}
#endif

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

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

View File

@@ -0,0 +1,487 @@
// BlockSort.cpp
#include "StdAfx.h"
#include "BlockSort.h"
extern "C"
{
#include "../../../../C/Sort.h"
}
// use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M
// #define BLOCK_SORT_USE_HEAP_SORT
#if _MSC_VER >= 1300
#define NO_INLINE __declspec(noinline) __fastcall
#else
#ifdef _MSC_VER
#define NO_INLINE __fastcall
#else
#define NO_INLINE
#endif
#endif
// Don't change it !!
static const int kNumHashBytes = 2;
static const UInt32 kNumHashValues = 1 << (kNumHashBytes * 8);
static const int kNumRefBitsMax = 12; // must be < (kNumHashBytes * 8) = 16
static const UInt32 kNumRefsMax = (1 << kNumRefBitsMax);
#define BS_TEMP_SIZE kNumHashValues
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
static const int kNumFlagsBits = 5; // 32 Flags in UInt32 word
static const UInt32 kNumFlagsInWord = (1 << kNumFlagsBits);
static const UInt32 kFlagsMask = kNumFlagsInWord - 1;
static const UInt32 kAllFlags = 0xFFFFFFFF;
#else
const int kNumBitsMax = 20;
const UInt32 kIndexMask = (1 << kNumBitsMax) - 1;
const int kNumExtraBits = 32 - kNumBitsMax;
const int kNumExtra0Bits = kNumExtraBits - 2;
const UInt32 kNumExtra0Mask = (1 << kNumExtra0Bits) - 1;
#define SetFinishedGroupSize(p, size) \
{ *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \
if ((size) > (1 << kNumExtra0Bits)) { \
*(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \
inline void SetGroupSize(UInt32 *p, UInt32 size)
{
if (--size == 0)
return;
*p |= 0x80000000 | ((size & kNumExtra0Mask) << kNumBitsMax);
if (size >= (1 << kNumExtra0Bits))
{
*p |= 0x40000000;
p[1] |= ((size >> kNumExtra0Bits) << kNumBitsMax);
}
}
#endif
// SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks
// "range" is not real range. It's only for optimization.
// returns: 1 - if there are groups, 0 - no more groups
UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices
#ifndef BLOCK_SORT_USE_HEAP_SORT
, UInt32 left, UInt32 range
#endif
)
{
UInt32 *ind2 = Indices + groupOffset;
if (groupSize <= 1)
{
/*
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetFinishedGroupSize(ind2, 1);
#endif
*/
return 0;
}
UInt32 *Groups = Indices + BlockSize + BS_TEMP_SIZE;
if (groupSize <= ((UInt32)1 << NumRefBits)
#ifndef BLOCK_SORT_USE_HEAP_SORT
&& groupSize <= range
#endif
)
{
UInt32 *temp = Indices + BlockSize;
UInt32 j;
{
UInt32 gPrev;
UInt32 gRes = 0;
{
UInt32 sp = ind2[0] + NumSortedBytes;
if (sp >= BlockSize) sp -= BlockSize;
gPrev = Groups[sp];
temp[0] = (gPrev << NumRefBits);
}
for (j = 1; j < groupSize; j++)
{
UInt32 sp = ind2[j] + NumSortedBytes;
if (sp >= BlockSize) sp -= BlockSize;
UInt32 g = Groups[sp];
temp[j] = (g << NumRefBits) | j;
gRes |= (gPrev ^ g);
}
if (gRes == 0)
{
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetGroupSize(ind2, groupSize);
#endif
return 1;
}
}
HeapSort(temp, groupSize);
const UInt32 mask = ((1 << NumRefBits) - 1);
UInt32 thereAreGroups = 0;
UInt32 group = groupOffset;
UInt32 cg = (temp[0] >> NumRefBits);
temp[0] = ind2[temp[0] & mask];
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 *Flags = Groups + BlockSize;
#else
UInt32 prevGroupStart = 0;
#endif
for (j = 1; j < groupSize; j++)
{
UInt32 val = temp[j];
UInt32 cgCur = (val >> NumRefBits);
if (cgCur != cg)
{
cg = cgCur;
group = groupOffset + j;
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 t = group - 1;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
#else
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
prevGroupStart = j;
#endif
}
else
thereAreGroups = 1;
UInt32 ind = ind2[val & mask];
temp[j] = ind;
Groups[ind] = group;
}
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
#endif
for (j = 0; j < groupSize; j++)
ind2[j] = temp[j];
return thereAreGroups;
}
// Check that all strings are in one group (cannot sort)
{
UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
UInt32 group = Groups[sp];
UInt32 j;
for (j = 1; j < groupSize; j++)
{
sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
if (Groups[sp] != group)
break;
}
if (j == groupSize)
{
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetGroupSize(ind2, groupSize);
#endif
return 1;
}
}
#ifndef BLOCK_SORT_USE_HEAP_SORT
//--------------------------------------
// Range Sort
UInt32 i;
UInt32 mid;
for (;;)
{
if (range <= 1)
{
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetGroupSize(ind2, groupSize);
#endif
return 1;
}
mid = left + ((range + 1) >> 1);
UInt32 j = groupSize;
i = 0;
do
{
UInt32 sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
if (Groups[sp] >= mid)
{
for (j--; j > i; j--)
{
sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
if (Groups[sp] < mid)
{
UInt32 temp = ind2[i]; ind2[i] = ind2[j]; ind2[j] = temp;
break;
}
}
if (i >= j)
break;
}
}
while(++i < j);
if (i == 0)
{
range = range - (mid - left);
left = mid;
}
else if (i == groupSize)
range = (mid - left);
else
break;
}
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
{
UInt32 t = (groupOffset + i - 1);
UInt32 *Flags = Groups + BlockSize;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
}
#endif
for (UInt32 j = i; j < groupSize; j++)
Groups[ind2[j]] = groupOffset + i;
UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);
return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));
#else
//--------------------------------------
// Heap Sort
{
UInt32 j;
for (j = 0; j < groupSize; j++)
{
UInt32 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
ind2[j] = sp;
}
HeapSortRef(ind2, Groups, groupSize);
// Write Flags
UInt32 sp = ind2[0];
UInt32 group = Groups[sp];
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 *Flags = Groups + BlockSize;
#else
UInt32 prevGroupStart = 0;
#endif
for (j = 1; j < groupSize; j++)
{
sp = ind2[j];
if (Groups[sp] != group)
{
group = Groups[sp];
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 t = groupOffset + j - 1;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
#else
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
prevGroupStart = j;
#endif
}
}
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
#endif
// Write new Groups values and Check that there are groups
UInt32 thereAreGroups = 0;
for (j = 0; j < groupSize; j++)
{
UInt32 group = groupOffset + j;
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);
if ((ind2[j] & 0x40000000) != 0)
subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits);
subGroupSize++;
for (;;)
{
UInt32 original = ind2[j];
UInt32 sp = original & kIndexMask;
if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
ind2[j] = sp | (original & ~kIndexMask);
Groups[sp] = group;
if (--subGroupSize == 0)
break;
j++;
thereAreGroups = 1;
}
#else
for (;;)
{
UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
ind2[j] = sp;
Groups[sp] = group;
if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0)
break;
j++;
thereAreGroups = 1;
}
#endif
}
return thereAreGroups;
}
#endif
}
// conditions: blockSize > 0
UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
{
UInt32 *counters = Indices + blockSize;
UInt32 i;
// Radix-Sort for 2 bytes
for (i = 0; i < kNumHashValues; i++)
counters[i] = 0;
for (i = 0; i < blockSize - 1; i++)
counters[((UInt32)data[i] << 8) | data[i + 1]]++;
counters[((UInt32)data[i] << 8) | data[0]]++;
UInt32 *Groups = counters + BS_TEMP_SIZE;
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 *Flags = Groups + blockSize;
{
UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;
for (i = 0; i < numWords; i++)
Flags[i] = kAllFlags;
}
#endif
{
UInt32 sum = 0;
for (i = 0; i < kNumHashValues; i++)
{
UInt32 groupSize = counters[i];
if (groupSize > 0)
{
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 t = sum + groupSize - 1;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
#endif
sum += groupSize;
}
counters[i] = sum - groupSize;
}
for (i = 0; i < blockSize - 1; i++)
Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]];
Groups[i] = counters[((UInt32)data[i] << 8) | data[0]];
for (i = 0; i < blockSize - 1; i++)
Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i;
Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i;
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 prev = 0;
for (i = 0; i < kNumHashValues; i++)
{
UInt32 prevGroupSize = counters[i] - prev;
if (prevGroupSize == 0)
continue;
SetGroupSize(Indices + prev, prevGroupSize);
prev = counters[i];
}
#endif
}
int NumRefBits;
for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++);
NumRefBits = 32 - NumRefBits;
if (NumRefBits > kNumRefBitsMax)
NumRefBits = kNumRefBitsMax;
for (UInt32 NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)
{
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 finishedGroupSize = 0;
#endif
UInt32 newLimit = 0;
for (i = 0; i < blockSize;)
{
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)
{
i++;
continue;
}
UInt32 groupSize;
for(groupSize = 1;
(Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;
groupSize++);
groupSize++;
#else
UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
bool finishedGroup = ((Indices[i] & 0x80000000) == 0);
if ((Indices[i] & 0x40000000) != 0)
{
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
Indices[i + 1] &= kIndexMask;
}
Indices[i] &= kIndexMask;
groupSize++;
if (finishedGroup || groupSize == 1)
{
Indices[i - finishedGroupSize] &= kIndexMask;
if (finishedGroupSize > 1)
Indices[i - finishedGroupSize + 1] &= kIndexMask;
UInt32 newGroupSize = groupSize + finishedGroupSize;
SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
finishedGroupSize = newGroupSize;
i += groupSize;
continue;
}
finishedGroupSize = 0;
#endif
if (NumSortedBytes >= blockSize)
for (UInt32 j = 0; j < groupSize; j++)
{
UInt32 t = (i + j);
// Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
Groups[Indices[t]] = t;
}
else
if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices
#ifndef BLOCK_SORT_USE_HEAP_SORT
, 0, blockSize
#endif
) != 0)
newLimit = i + groupSize;
i += groupSize;
}
if (newLimit == 0)
break;
}
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
for (i = 0; i < blockSize;)
{
UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
if ((Indices[i] & 0x40000000) != 0)
{
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
Indices[i + 1] &= kIndexMask;
}
Indices[i] &= kIndexMask;
groupSize++;
i += groupSize;
}
#endif
return Groups[0];
}

View File

@@ -0,0 +1,21 @@
// BlockSort.h
#ifndef __BLOCKSORT_H
#define __BLOCKSORT_H
#include "Common/Types.h"
// use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M
// #define BLOCK_SORT_EXTERNAL_FLAGS
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5))
#else
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0
#endif
#define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16))
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
#endif

195
CPP/7zip/Compress/BWT/Mtf8.h Executable file
View File

@@ -0,0 +1,195 @@
// Mtf8.h
#ifndef __MTF8_H
#define __MTF8_H
#include "Common/Types.h"
namespace NCompress {
class CMtf8Encoder
{
public:
Byte Buffer[256];
int FindAndMove(Byte v)
{
int pos;
for (pos = 0; Buffer[pos] != v; pos++);
int resPos = pos;
for (; pos >= 8; pos -= 8)
{
Buffer[pos] = Buffer[pos - 1];
Buffer[pos - 1] = Buffer[pos - 2];
Buffer[pos - 2] = Buffer[pos - 3];
Buffer[pos - 3] = Buffer[pos - 4];
Buffer[pos - 4] = Buffer[pos - 5];
Buffer[pos - 5] = Buffer[pos - 6];
Buffer[pos - 6] = Buffer[pos - 7];
Buffer[pos - 7] = Buffer[pos - 8];
}
for (; pos > 0; pos--)
Buffer[pos] = Buffer[pos - 1];
Buffer[0] = v;
return resPos;
}
};
/*
class CMtf8Decoder
{
public:
Byte Buffer[256];
void Init(int) {};
Byte GetHead() const { return Buffer[0]; }
Byte GetAndMove(int pos)
{
Byte res = Buffer[pos];
for (; pos >= 8; pos -= 8)
{
Buffer[pos] = Buffer[pos - 1];
Buffer[pos - 1] = Buffer[pos - 2];
Buffer[pos - 2] = Buffer[pos - 3];
Buffer[pos - 3] = Buffer[pos - 4];
Buffer[pos - 4] = Buffer[pos - 5];
Buffer[pos - 5] = Buffer[pos - 6];
Buffer[pos - 6] = Buffer[pos - 7];
Buffer[pos - 7] = Buffer[pos - 8];
}
for (; pos > 0; pos--)
Buffer[pos] = Buffer[pos - 1];
Buffer[0] = res;
return res;
}
};
*/
#ifdef _WIN64
#define MODE_64BIT
#endif
#ifdef MODE_64BIT
typedef UInt64 CMtfVar;
#define MTF_MOVS 3
#else
typedef UInt32 CMtfVar;
#define MTF_MOVS 2
#endif
#define MTF_MASK ((1 << MTF_MOVS) - 1)
class CMtf8Decoder
{
public:
CMtfVar Buffer[256 >> MTF_MOVS];
void StartInit() { memset(Buffer, 0, sizeof(Buffer)); }
void Add(unsigned int pos, Byte val) { Buffer[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3)); }
Byte GetHead() const { return (Byte)Buffer[0]; }
Byte GetAndMove(unsigned int pos)
{
UInt32 lim = ((UInt32)pos >> MTF_MOVS);
pos = (pos & MTF_MASK) << 3;
CMtfVar prev = (Buffer[lim] >> pos) & 0xFF;
UInt32 i = 0;
if ((lim & 1) != 0)
{
CMtfVar next = Buffer[0];
Buffer[0] = (next << 8) | prev;
prev = (next >> (MTF_MASK << 3));
i = 1;
lim -= 1;
}
for (; i < lim; i += 2)
{
CMtfVar next = Buffer[i];
Buffer[i] = (next << 8) | prev;
prev = (next >> (MTF_MASK << 3));
next = Buffer[i + 1];
Buffer[i + 1] = (next << 8) | prev;
prev = (next >> (MTF_MASK << 3));
}
CMtfVar next = Buffer[i];
CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);
Buffer[i] = (next & ~mask) | (((next << 8) | prev) & mask);
return (Byte)Buffer[0];
}
};
/*
const int kSmallSize = 64;
class CMtf8Decoder
{
Byte SmallBuffer[kSmallSize];
int SmallSize;
Byte Counts[16];
int Size;
public:
Byte Buffer[256];
Byte GetHead() const
{
if (SmallSize > 0)
return SmallBuffer[kSmallSize - SmallSize];
return Buffer[0];
}
void Init(int size)
{
Size = size;
SmallSize = 0;
for (int i = 0; i < 16; i++)
{
Counts[i] = ((size >= 16) ? 16 : size);
size -= Counts[i];
}
}
Byte GetAndMove(int pos)
{
if (pos < SmallSize)
{
Byte *p = SmallBuffer + kSmallSize - SmallSize;
Byte res = p[pos];
for (; pos > 0; pos--)
p[pos] = p[pos - 1];
SmallBuffer[kSmallSize - SmallSize] = res;
return res;
}
if (SmallSize == kSmallSize)
{
int i = Size - 1;
int g = 16;
do
{
g--;
int offset = (g << 4);
for (int t = Counts[g] - 1; t >= 0; t--, i--)
Buffer[i] = Buffer[offset + t];
}
while(g != 0);
for (i = kSmallSize - 1; i >= 0; i--)
Buffer[i] = SmallBuffer[i];
Init(Size);
}
pos -= SmallSize;
int g;
for (g = 0; pos >= Counts[g]; g++)
pos -= Counts[g];
int offset = (g << 4);
Byte res = Buffer[offset + pos];
for (pos; pos < 16 - 1; pos++)
Buffer[offset + pos] = Buffer[offset + pos + 1];
SmallSize++;
SmallBuffer[kSmallSize - SmallSize] = res;
Counts[g]--;
return res;
}
};
*/
}
#endif

6
CPP/7zip/Compress/BWT/StdAfx.h Executable file
View File

@@ -0,0 +1,6 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#endif

303
CPP/7zip/Compress/BZip2/BZip2.dsp Executable file
View File

@@ -0,0 +1,303 @@
# Microsoft Developer Studio Project File - Name="BZip2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=BZip2 - 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 "BZip2.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 "BZip2.mak" CFG="BZip2 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "BZip2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "BZip2 - 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)" == "BZip2 - 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 "BZIP2_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "BZ_NO_STDIO" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_EXPORTS" /D "COMPRESS_BZIP2_MT" /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 0x419 /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\BZip2.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "BZip2 - 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 "BZIP2_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 "BZIP2_EXPORTS" /D "COMPRESS_BZIP2_MT" /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 0x419 /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\BZip2.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "BZip2 - Win32 Release"
# Name "BZip2 - 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 "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\NewHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# End Group
# Begin Group "Huffman"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Huffman\HuffmanDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Huffman\HuffmanEncode.c
!IF "$(CFG)" == "BZip2 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "BZip2 - 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)" == "BZip2 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "BZip2 - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sort.h
# End Source File
# End Group
# Begin Group "7-Zip 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\MSBFDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MSBFEncoder.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 "BWT"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\BWT\BlockSort.cpp
!IF "$(CFG)" == "BZip2 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "BZip2 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\BWT\BlockSort.h
# End Source File
# Begin Source File
SOURCE=..\BWT\Mtf8.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Thread.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\BZip2Const.h
# End Source File
# Begin Source File
SOURCE=.\BZip2CRC.cpp
# End Source File
# Begin Source File
SOURCE=.\BZip2CRC.h
# End Source File
# Begin Source File
SOURCE=.\BZip2Decoder.cpp
!IF "$(CFG)" == "BZip2 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "BZip2 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\BZip2Decoder.h
# End Source File
# Begin Source File
SOURCE=.\BZip2Encoder.cpp
!IF "$(CFG)" == "BZip2 - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "BZip2 - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\BZip2Encoder.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: "BZip2"=.\BZip2.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,26 @@
// BZip2CRC.cpp
#include "StdAfx.h"
#include "BZip2CRC.h"
UInt32 CBZip2CRC::Table[256];
static const UInt32 kBZip2CRCPoly = 0x04c11db7; /* AUTODIN II, Ethernet, & FDDI */
void CBZip2CRC::InitTable()
{
for (UInt32 i = 0; i < 256; i++)
{
UInt32 r = (i << 24);
for (int j = 8; j > 0; j--)
r = (r & 0x80000000) ? ((r << 1) ^ kBZip2CRCPoly) : (r << 1);
Table[i] = r;
}
}
class CBZip2CRCTableInit
{
public:
CBZip2CRCTableInit() { CBZip2CRC::InitTable(); }
} g_BZip2CRCTableInit;

View File

@@ -0,0 +1,31 @@
// BZip2CRC.h
#ifndef __BZIP2_CRC_H
#define __BZIP2_CRC_H
#include "Common/Types.h"
class CBZip2CRC
{
UInt32 _value;
static UInt32 Table[256];
public:
static void InitTable();
CBZip2CRC(): _value(0xFFFFFFFF) {};
void Init() { _value = 0xFFFFFFFF; }
void UpdateByte(Byte b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }
void UpdateByte(unsigned int b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }
UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }
};
class CBZip2CombinedCRC
{
UInt32 _value;
public:
CBZip2CombinedCRC(): _value(0){};
void Init() { _value = 0; }
void Update(UInt32 v) { _value = ((_value << 1) | (_value >> 31)) ^ v; }
UInt32 GetDigest() const { return _value ; }
};
#endif

View File

@@ -0,0 +1,54 @@
// Compress/BZip2Const.h
#ifndef __COMPRESS_BZIP2_CONST_H
#define __COMPRESS_BZIP2_CONST_H
namespace NCompress {
namespace NBZip2 {
const Byte kArSig0 = 'B';
const Byte kArSig1 = 'Z';
const Byte kArSig2 = 'h';
const Byte kArSig3 = '0';
const Byte kFinSig0 = 0x17;
const Byte kFinSig1 = 0x72;
const Byte kFinSig2 = 0x45;
const Byte kFinSig3 = 0x38;
const Byte kFinSig4 = 0x50;
const Byte kFinSig5 = 0x90;
const Byte kBlockSig0 = 0x31;
const Byte kBlockSig1 = 0x41;
const Byte kBlockSig2 = 0x59;
const Byte kBlockSig3 = 0x26;
const Byte kBlockSig4 = 0x53;
const Byte kBlockSig5 = 0x59;
const int kNumOrigBits = 24;
const int kNumTablesBits = 3;
const int kNumTablesMin = 2;
const int kNumTablesMax = 6;
const int kNumLevelsBits = 5;
const int kMaxHuffmanLen = 20; // Check it
const int kMaxAlphaSize = 258;
const int kGroupSize = 50;
const int kBlockSizeMultMin = 1;
const int kBlockSizeMultMax = 9;
const UInt32 kBlockSizeStep = 100000;
const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep;
const int kNumSelectorsBits = 15;
const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize));
const int kRleModeRepSize = 4;
}}
#endif

View File

@@ -0,0 +1,770 @@
// BZip2Decoder.cpp
#include "StdAfx.h"
#include "BZip2Decoder.h"
#include "../../../Common/Alloc.h"
#include "../../../Common/Defs.h"
#include "../BWT/Mtf8.h"
#include "BZip2CRC.h"
namespace NCompress {
namespace NBZip2 {
const UInt32 kNumThreadsMax = 4;
static const UInt32 kBufferSize = (1 << 17);
static Int16 kRandNums[512] = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
936, 638
};
bool CState::Alloc()
{
if (Counters == 0)
Counters = (UInt32 *)BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));
return (Counters != 0);
}
void CState::Free()
{
::BigFree(Counters);
Counters = 0;
}
UInt32 CDecoder::ReadBits(int numBits) { return m_InStream.ReadBits(numBits); }
Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); }
bool CDecoder::ReadBit() { return ReadBits(1) != 0; }
UInt32 CDecoder::ReadCRC()
{
UInt32 crc = 0;
for (int i = 0; i < 4; i++)
{
crc <<= 8;
crc |= ReadByte();
}
return crc;
}
UInt32 NO_INLINE ReadBits(NStream::NMSBF::CDecoder<CInBuffer> *m_InStream, int num)
{
return m_InStream->ReadBits(num);
}
UInt32 NO_INLINE ReadBit(NStream::NMSBF::CDecoder<CInBuffer> *m_InStream)
{
return m_InStream->ReadBits(1);
}
static HRESULT NO_INLINE ReadBlock(NStream::NMSBF::CDecoder<CInBuffer> *m_InStream,
UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,
UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes)
{
*randRes = ReadBit(m_InStream) ? true : false;
*origPtrRes = ReadBits(m_InStream, kNumOrigBits);
// in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?
if (*origPtrRes >= blockSizeMax)
return S_FALSE;
CMtf8Decoder mtf;
mtf.StartInit();
int numInUse = 0;
{
Byte inUse16[16];
int i;
for (i = 0; i < 16; i++)
inUse16[i] = (Byte)ReadBit(m_InStream);
for (i = 0; i < 256; i++)
if (inUse16[i >> 4])
{
if (ReadBit(m_InStream))
mtf.Add(numInUse++, (Byte)i);
}
if (numInUse == 0)
return S_FALSE;
// mtf.Init(numInUse);
}
int alphaSize = numInUse + 2;
int numTables = ReadBits(m_InStream, kNumTablesBits);
if (numTables < kNumTablesMin || numTables > kNumTablesMax)
return S_FALSE;
UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits);
if (numSelectors < 1 || numSelectors > kNumSelectorsMax)
return S_FALSE;
{
Byte mtfPos[kNumTablesMax];
int t = 0;
do
mtfPos[t] = (Byte)t;
while(++t < numTables);
UInt32 i = 0;
do
{
int j = 0;
while (ReadBit(m_InStream))
if (++j >= numTables)
return S_FALSE;
Byte tmp = mtfPos[j];
for (;j > 0; j--)
mtfPos[j] = mtfPos[j - 1];
m_Selectors[i] = mtfPos[0] = tmp;
}
while(++i < numSelectors);
}
int t = 0;
do
{
Byte lens[kMaxAlphaSize];
int len = (int)ReadBits(m_InStream, kNumLevelsBits);
int i;
for (i = 0; i < alphaSize; i++)
{
for (;;)
{
if (len < 1 || len > kMaxHuffmanLen)
return S_FALSE;
if (!ReadBit(m_InStream))
break;
len += 1 - (int)(ReadBit(m_InStream) << 1);
}
lens[i] = (Byte)len;
}
for (; i < kMaxAlphaSize; i++)
lens[i] = 0;
if(!m_HuffmanDecoders[t].SetCodeLengths(lens))
return S_FALSE;
}
while(++t < numTables);
{
for (int i = 0; i < 256; i++)
CharCounters[i] = 0;
}
UInt32 blockSize = 0;
{
UInt32 groupIndex = 0;
UInt32 groupSize = 0;
CHuffmanDecoder *huffmanDecoder = 0;
int runPower = 0;
UInt32 runCounter = 0;
for (;;)
{
if (groupSize == 0)
{
if (groupIndex >= numSelectors)
return S_FALSE;
groupSize = kGroupSize;
huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]];
}
groupSize--;
UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream);
if (nextSym < 2)
{
runCounter += ((UInt32)(nextSym + 1) << runPower++);
if (blockSizeMax - blockSize < runCounter)
return S_FALSE;
continue;
}
if (runCounter != 0)
{
UInt32 b = (UInt32)mtf.GetHead();
CharCounters[b] += runCounter;
do
CharCounters[256 + blockSize++] = b;
while(--runCounter != 0);
runPower = 0;
}
if (nextSym <= (UInt32)numInUse)
{
UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1);
if (blockSize >= blockSizeMax)
return S_FALSE;
CharCounters[b]++;
CharCounters[256 + blockSize++] = b;
}
else if (nextSym == (UInt32)numInUse + 1)
break;
else
return S_FALSE;
}
}
*blockSizeRes = blockSize;
return (*origPtrRes < blockSize) ? S_OK : S_FALSE;
}
void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize)
{
{
UInt32 sum = 0;
for (UInt32 i = 0; i < 256; i++)
{
sum += charCounters[i];
charCounters[i] = sum - charCounters[i];
}
}
UInt32 *tt = charCounters + 256;
// Compute the T^(-1) vector
UInt32 i = 0;
do
tt[charCounters[tt[i] & 0xFF]++] |= (i << 8);
while(++i < blockSize);
}
static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)
{
CBZip2CRC crc;
// it's for speed optimization: prefetch & prevByte_init;
UInt32 tPos = tt[tt[OrigPtr] >> 8];
unsigned int prevByte = (unsigned int)(tPos & 0xFF);
int numReps = 0;
do
{
unsigned int b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
if (numReps == kRleModeRepSize)
{
for (; b > 0; b--)
{
crc.UpdateByte(prevByte);
m_OutStream.WriteByte((Byte)prevByte);
}
numReps = 0;
continue;
}
if (b != prevByte)
numReps = 0;
numReps++;
prevByte = b;
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
/*
prevByte = b;
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
for (; --blockSize != 0;)
{
b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
if (b != prevByte)
{
prevByte = b;
continue;
}
if (--blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
if (b != prevByte)
{
prevByte = b;
continue;
}
if (--blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
if (b != prevByte)
{
prevByte = b;
continue;
}
--blockSize;
break;
}
if (blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
for (; b > 0; b--)
{
crc.UpdateByte(prevByte);
m_OutStream.WriteByte((Byte)prevByte);
}
*/
}
while(--blockSize != 0);
return crc.GetDigest();
}
static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)
{
CBZip2CRC crc;
UInt32 randIndex = 1;
UInt32 randToGo = kRandNums[0] - 2;
int numReps = 0;
// it's for speed optimization: prefetch & prevByte_init;
UInt32 tPos = tt[tt[OrigPtr] >> 8];
unsigned int prevByte = (unsigned int)(tPos & 0xFF);
do
{
unsigned int b = (unsigned int)(tPos & 0xFF);
tPos = tt[tPos >> 8];
{
if (randToGo == 0)
{
b ^= 1;
randToGo = kRandNums[randIndex++];
randIndex &= 0x1FF;
}
randToGo--;
}
if (numReps == kRleModeRepSize)
{
for (; b > 0; b--)
{
crc.UpdateByte(prevByte);
m_OutStream.WriteByte((Byte)prevByte);
}
numReps = 0;
continue;
}
if (b != prevByte)
numReps = 0;
numReps++;
prevByte = b;
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
}
while(--blockSize != 0);
return crc.GetDigest();
}
#ifdef COMPRESS_BZIP2_MT
static DWORD WINAPI MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; }
CDecoder::CDecoder():
m_States(0)
{
m_NumThreadsPrev = 0;
NumThreads = 1;
CS.Enter();
}
CDecoder::~CDecoder()
{
Free();
}
bool CDecoder::Create()
{
try
{
if (m_States != 0 && m_NumThreadsPrev == NumThreads)
return true;
Free();
MtMode = (NumThreads > 1);
m_NumThreadsPrev = NumThreads;
m_States = new CState[NumThreads];
if (m_States == 0)
return false;
#ifdef COMPRESS_BZIP2_MT
for (UInt32 t = 0; t < NumThreads; t++)
{
CState &ti = m_States[t];
ti.Decoder = this;
if (MtMode)
if (!ti.Thread.Create(MFThread, &ti))
{
NumThreads = t;
Free();
return false;
}
}
#endif
}
catch(...) { return false; }
return true;
}
void CDecoder::Free()
{
if (!m_States)
return;
CloseThreads = true;
CS.Leave();
for (UInt32 t = 0; t < NumThreads; t++)
{
CState &s = m_States[t];
if (MtMode)
s.Thread.Wait();
s.Free();
}
delete []m_States;
m_States = 0;
}
#endif
HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc)
{
wasFinished = false;
Byte s[6];
for (int i = 0; i < 6; i++)
s[i] = ReadByte();
crc = ReadCRC();
if (s[0] == kFinSig0)
{
if (s[1] != kFinSig1 ||
s[2] != kFinSig2 ||
s[3] != kFinSig3 ||
s[4] != kFinSig4 ||
s[5] != kFinSig5)
return S_FALSE;
wasFinished = true;
return (crc == CombinedCRC.GetDigest()) ? S_OK : S_FALSE;
}
if (s[0] != kBlockSig0 ||
s[1] != kBlockSig1 ||
s[2] != kBlockSig2 ||
s[3] != kBlockSig3 ||
s[4] != kBlockSig4 ||
s[5] != kBlockSig5)
return S_FALSE;
CombinedCRC.Update(crc);
return S_OK;
}
HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress)
{
#ifdef COMPRESS_BZIP2_MT
Progress = progress;
if (!Create())
return E_FAIL;
for (UInt32 t = 0; t < NumThreads; t++)
{
CState &s = m_States[t];
if (!s.Alloc())
return E_OUTOFMEMORY;
s.StreamWasFinishedEvent.Reset();
s.WaitingWasStartedEvent.Reset();
s.CanWriteEvent.Reset();
}
#else
if (!m_States[0].Alloc())
return E_OUTOFMEMORY;
#endif
isBZ = false;
Byte s[6];
int i;
for (i = 0; i < 4; i++)
s[i] = ReadByte();
if (s[0] != kArSig0 ||
s[1] != kArSig1 ||
s[2] != kArSig2 ||
s[3] <= kArSig3 ||
s[3] > kArSig3 + kBlockSizeMultMax)
return S_OK;
isBZ = true;
UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep;
CombinedCRC.Init();
#ifdef COMPRESS_BZIP2_MT
if (MtMode)
{
NextBlockIndex = 0;
StreamWasFinished1 = StreamWasFinished2 = false;
CloseThreads = false;
CanStartWaitingEvent.Reset();
m_States[0].CanWriteEvent.Set();
BlockSizeMax = dicSize;
Result1 = Result2 = S_OK;
CS.Leave();
UInt32 t;
for (t = 0; t < NumThreads; t++)
m_States[t].StreamWasFinishedEvent.Lock();
CS.Enter();
CanStartWaitingEvent.Set();
for (t = 0; t < NumThreads; t++)
m_States[t].WaitingWasStartedEvent.Lock();
CanStartWaitingEvent.Reset();
RINOK(Result2);
RINOK(Result1);
}
else
#endif
{
CState &state = m_States[0];
for (;;)
{
if (progress)
{
UInt64 packSize = m_InStream.GetProcessedSize();
UInt64 unpackSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
}
bool wasFinished;
UInt32 crc;
RINOK(ReadSignatures(wasFinished, crc));
if (wasFinished)
return S_OK;
UInt32 blockSize, origPtr;
bool randMode;
RINOK(ReadBlock(&m_InStream, state.Counters, dicSize,
m_Selectors, m_HuffmanDecoders,
&blockSize, &origPtr, &randMode));
DecodeBlock1(state.Counters, blockSize);
if ((randMode ?
DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) :
DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc)
return S_FALSE;
}
}
return S_OK;
}
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
ICompressProgressInfo *progress)
{
if (!m_InStream.Create(kBufferSize))
return E_OUTOFMEMORY;
if (!m_OutStream.Create(kBufferSize))
return E_OUTOFMEMORY;
m_InStream.SetStream(inStream);
m_InStream.Init();
m_OutStream.SetStream(outStream);
m_OutStream.Init();
CDecoderFlusher flusher(this);
bool isBZ;
RINOK(DecodeFile(isBZ, progress));
return isBZ ? S_OK: S_FALSE;
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return E_FAIL; }
}
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
{
if (value == NULL)
return E_INVALIDARG;
*value = m_InStream.GetProcessedSize();
return S_OK;
}
#ifdef COMPRESS_BZIP2_MT
void CState::FinishStream()
{
Decoder->StreamWasFinished1 = true;
StreamWasFinishedEvent.Set();
Decoder->CS.Leave();
Decoder->CanStartWaitingEvent.Lock();
WaitingWasStartedEvent.Set();
}
void CState::ThreadFunc()
{
for (;;)
{
Decoder->CS.Enter();
if (Decoder->CloseThreads)
{
Decoder->CS.Leave();
return;
}
if (Decoder->StreamWasFinished1)
{
FinishStream();
continue;
}
HRESULT res = S_OK;
UInt32 blockIndex = Decoder->NextBlockIndex;
UInt32 nextBlockIndex = blockIndex + 1;
if (nextBlockIndex == Decoder->NumThreads)
nextBlockIndex = 0;
Decoder->NextBlockIndex = nextBlockIndex;
UInt32 crc;
UInt64 packSize;
UInt32 blockSize = 0, origPtr = 0;
bool randMode = false;
try
{
bool wasFinished;
res = Decoder->ReadSignatures(wasFinished, crc);
if (res != S_OK)
{
Decoder->Result1 = res;
FinishStream();
continue;
}
if (wasFinished)
{
Decoder->Result1 = res;
FinishStream();
continue;
}
res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax,
Decoder->m_Selectors, Decoder->m_HuffmanDecoders,
&blockSize, &origPtr, &randMode);
if (res != S_OK)
{
Decoder->Result1 = res;
FinishStream();
continue;
}
packSize = Decoder->m_InStream.GetProcessedSize();
}
catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }
catch(...) { res = E_FAIL; }
if (res != S_OK)
{
Decoder->Result1 = res;
FinishStream();
continue;
}
Decoder->CS.Leave();
DecodeBlock1(Counters, blockSize);
bool needFinish = true;
try
{
Decoder->m_States[blockIndex].CanWriteEvent.Lock();
needFinish = Decoder->StreamWasFinished2;
if (!needFinish)
{
if ((randMode ?
DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) :
DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc)
{
if (Decoder->Progress)
{
UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize();
res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize);
}
}
else
res = S_FALSE;
}
}
catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }
catch(...) { res = E_FAIL; }
if (res != S_OK)
{
Decoder->Result2 = res;
Decoder->StreamWasFinished2 = true;
}
Decoder->m_States[nextBlockIndex].CanWriteEvent.Set();
if (res != S_OK || needFinish)
{
StreamWasFinishedEvent.Set();
Decoder->CanStartWaitingEvent.Lock();
WaitingWasStartedEvent.Set();
}
}
}
STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
{
NumThreads = numThreads;
if (NumThreads < 1)
NumThreads = 1;
if (NumThreads > kNumThreadsMax)
NumThreads = kNumThreadsMax;
return S_OK;
}
#endif
}}

View File

@@ -0,0 +1,164 @@
// Compress/BZip2/Decoder.h
#ifndef __COMPRESS_BZIP2_DECODER_H
#define __COMPRESS_BZIP2_DECODER_H
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../../Common/OutBuffer.h"
#include "../Huffman/HuffmanDecoder.h"
#include "BZip2Const.h"
#include "BZip2CRC.h"
#ifdef COMPRESS_BZIP2_MT
#include "../../../Windows/Thread.h"
#include "../../../Windows/Synchronization.h"
#endif
#if _MSC_VER >= 1300
#define NO_INLINE __declspec(noinline) __fastcall
#else
#ifdef _MSC_VER
#define NO_INLINE __fastcall
#endif
#endif
namespace NCompress {
namespace NBZip2 {
typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder;
class CDecoder;
struct CState
{
UInt32 *Counters;
#ifdef COMPRESS_BZIP2_MT
CDecoder *Decoder;
NWindows::CThread Thread;
bool m_OptimizeNumTables;
NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;
NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;
// it's not member of this thread. We just need one event per thread
NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
void FinishStream();
void ThreadFunc();
#endif
CState(): Counters(0) {}
~CState() { Free(); }
bool Alloc();
void Free();
};
class CDecoder :
public ICompressCoder,
#ifdef COMPRESS_BZIP2_MT
public ICompressSetCoderMt,
#endif
public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
public:
COutBuffer m_OutStream;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
NStream::NMSBF::CDecoder<CInBuffer> m_InStream;
Byte m_Selectors[kNumSelectorsMax];
CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];
private:
UInt32 m_NumThreadsPrev;
UInt32 ReadBits(int numBits);
Byte ReadByte();
bool ReadBit();
UInt32 ReadCRC();
HRESULT PrepareBlock(CState &state);
HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress);
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
class CDecoderFlusher
{
CDecoder *_decoder;
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
~CDecoderFlusher()
{
if (NeedFlush)
_decoder->Flush();
_decoder->ReleaseStreams();
}
};
public:
CBZip2CombinedCRC CombinedCRC;
#ifdef COMPRESS_BZIP2_MT
ICompressProgressInfo *Progress;
CState *m_States;
NWindows::NSynchronization::CCriticalSection CS;
UInt32 NumThreads;
bool MtMode;
UInt32 NextBlockIndex;
bool CloseThreads;
bool StreamWasFinished1;
bool StreamWasFinished2;
NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;
HRESULT Result1;
HRESULT Result2;
UInt32 BlockSizeMax;
CDecoder();
~CDecoder();
bool Create();
void Free();
#else
CState m_States[1];
#endif
HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc);
HRESULT Flush() { return m_OutStream.Flush(); }
void ReleaseStreams()
{
m_InStream.ReleaseStream();
m_OutStream.ReleaseStream();
}
#ifdef COMPRESS_BZIP2_MT
MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressGetInStreamProcessedSize)
#else
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
#endif
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
#ifdef COMPRESS_BZIP2_MT
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
#endif
};
}}
#endif

View File

@@ -0,0 +1,883 @@
// BZip2Encoder.cpp
#include "StdAfx.h"
#include "../../../Common/Alloc.h"
#include "BZip2Encoder.h"
#include "../BWT/BlockSort.h"
#include "../BWT/Mtf8.h"
#include "BZip2CRC.h"
extern "C"
{
#include "../../../../C/Compress/Huffman/HuffmanEncode.h"
}
namespace NCompress {
namespace NBZip2 {
const int kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20
static const UInt32 kBufferSize = (1 << 17);
static const int kNumHuffPasses = 4;
bool CThreadInfo::Create()
{
if (m_BlockSorterIndex != 0)
return true;
m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32));
if (m_BlockSorterIndex == 0)
return false;
if (m_Block == 0)
{
m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10));
if (m_Block == 0)
return false;
m_MtfArray = m_Block + kBlockSizeMax;
m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2;
}
return true;
}
void CThreadInfo::Free()
{
::BigFree(m_BlockSorterIndex);
m_BlockSorterIndex = 0;
::MidFree(m_Block);
m_Block = 0;
}
#ifdef COMPRESS_BZIP2_MT
void CThreadInfo::FinishStream(bool needLeave)
{
Encoder->StreamWasFinished = true;
StreamWasFinishedEvent.Set();
if (needLeave)
Encoder->CS.Leave();
Encoder->CanStartWaitingEvent.Lock();
WaitingWasStartedEvent.Set();
}
DWORD CThreadInfo::ThreadFunc()
{
for (;;)
{
Encoder->CS.Enter();
if (Encoder->CloseThreads)
{
Encoder->CS.Leave();
return 0;
}
if (Encoder->StreamWasFinished)
{
FinishStream(true);
continue;
}
HRESULT res = S_OK;
bool needLeave = true;
try
{
UInt32 blockSize = Encoder->ReadRleBlock(m_Block);
m_PackSize = Encoder->m_InStream.GetProcessedSize();
m_BlockIndex = Encoder->NextBlockIndex;
if (++Encoder->NextBlockIndex == Encoder->NumThreads)
Encoder->NextBlockIndex = 0;
if (blockSize == 0)
{
FinishStream(true);
continue;
}
Encoder->CS.Leave();
needLeave = false;
res = EncodeBlock3(blockSize);
}
catch(const CInBufferException &e) { res = e.ErrorCode; }
catch(const COutBufferException &e) { res = e.ErrorCode; }
catch(...) { res = E_FAIL; }
if (res != S_OK)
{
Encoder->Result = res;
FinishStream(needLeave);
continue;
}
}
}
static DWORD WINAPI MFThread(void *threadCoderInfo)
{
return ((CThreadInfo *)threadCoderInfo)->ThreadFunc();
}
#endif
CEncoder::CEncoder():
NumPasses(1),
m_OptimizeNumTables(false),
m_BlockSizeMult(kBlockSizeMultMax)
{
#ifdef COMPRESS_BZIP2_MT
ThreadsInfo = 0;
m_NumThreadsPrev = 0;
NumThreads = 1;
CS.Enter();
#endif
}
#ifdef COMPRESS_BZIP2_MT
CEncoder::~CEncoder()
{
Free();
}
bool CEncoder::Create()
{
try
{
if (ThreadsInfo != 0 && m_NumThreadsPrev == NumThreads)
return true;
Free();
MtMode = (NumThreads > 1);
m_NumThreadsPrev = NumThreads;
ThreadsInfo = new CThreadInfo[NumThreads];
if (ThreadsInfo == 0)
return false;
for (UInt32 t = 0; t < NumThreads; t++)
{
CThreadInfo &ti = ThreadsInfo[t];
ti.Encoder = this;
if (MtMode)
if (!ti.Thread.Create(MFThread, &ti))
{
NumThreads = t;
Free();
return false;
}
}
}
catch(...) { return false; }
return true;
}
void CEncoder::Free()
{
if (!ThreadsInfo)
return;
CloseThreads = true;
CS.Leave();
for (UInt32 t = 0; t < NumThreads; t++)
{
CThreadInfo &ti = ThreadsInfo[t];
if (MtMode)
ti.Thread.Wait();
ti.Free();
}
delete []ThreadsInfo;
ThreadsInfo = 0;
}
#endif
UInt32 CEncoder::ReadRleBlock(Byte *buffer)
{
UInt32 i = 0;
Byte prevByte;
if (m_InStream.ReadByte(prevByte))
{
UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1;
int numReps = 1;
buffer[i++] = prevByte;
while (i < blockSize) // "- 1" to support RLE
{
Byte b;
if (!m_InStream.ReadByte(b))
break;
if (b != prevByte)
{
if (numReps >= kRleModeRepSize)
buffer[i++] = (Byte)(numReps - kRleModeRepSize);
buffer[i++] = b;
numReps = 1;
prevByte = b;
continue;
}
numReps++;
if (numReps <= kRleModeRepSize)
buffer[i++] = b;
else if (numReps == kRleModeRepSize + 255)
{
buffer[i++] = (Byte)(numReps - kRleModeRepSize);
numReps = 0;
}
}
// it's to support original BZip2 decoder
if (numReps >= kRleModeRepSize)
buffer[i++] = (Byte)(numReps - kRleModeRepSize);
}
return i;
}
void CThreadInfo::WriteBits2(UInt32 value, UInt32 numBits)
{ m_OutStreamCurrent->WriteBits(value, numBits); }
void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b , 8); }
void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); }
void CThreadInfo::WriteCRC2(UInt32 v)
{
for (int i = 0; i < 4; i++)
WriteByte2(((Byte)(v >> (24 - i * 8))));
}
void CEncoder::WriteBits(UInt32 value, UInt32 numBits)
{ m_OutStream.WriteBits(value, numBits); }
void CEncoder::WriteByte(Byte b) { WriteBits(b , 8); }
void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); }
void CEncoder::WriteCRC(UInt32 v)
{
for (int i = 0; i < 4; i++)
WriteByte(((Byte)(v >> (24 - i * 8))));
}
// blockSize > 0
void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
{
WriteBit2(false); // Randomised = false
{
UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize);
// if (m_BlockSorterIndex[origPtr] != 0) throw 1;
m_BlockSorterIndex[origPtr] = blockSize;
WriteBits2(origPtr, kNumOrigBits);
}
CMtf8Encoder mtf;
int numInUse = 0;
{
bool inUse[256];
bool inUse16[16];
UInt32 i;
for (i = 0; i < 256; i++)
inUse[i] = false;
for (i = 0; i < 16; i++)
inUse16[i] = false;
for (i = 0; i < blockSize; i++)
inUse[block[i]] = true;
for (i = 0; i < 256; i++)
if (inUse[i])
{
inUse16[i >> 4] = true;
mtf.Buffer[numInUse++] = (Byte)i;
}
for (i = 0; i < 16; i++)
WriteBit2(inUse16[i]);
for (i = 0; i < 256; i++)
if (inUse16[i >> 4])
WriteBit2(inUse[i]);
}
int alphaSize = numInUse + 2;
Byte *mtfs = m_MtfArray;
UInt32 mtfArraySize = 0;
UInt32 symbolCounts[kMaxAlphaSize];
{
for (int i = 0; i < kMaxAlphaSize; i++)
symbolCounts[i] = 0;
}
{
UInt32 rleSize = 0;
UInt32 i = 0;
const UInt32 *bsIndex = m_BlockSorterIndex;
block--;
do
{
int pos = mtf.FindAndMove(block[bsIndex[i]]);
if (pos == 0)
rleSize++;
else
{
while (rleSize != 0)
{
rleSize--;
mtfs[mtfArraySize++] = (Byte)(rleSize & 1);
symbolCounts[rleSize & 1]++;
rleSize >>= 1;
}
if (pos >= 0xFE)
{
mtfs[mtfArraySize++] = 0xFF;
mtfs[mtfArraySize++] = (Byte)(pos - 0xFE);
}
else
mtfs[mtfArraySize++] = (Byte)(pos + 1);
symbolCounts[pos + 1]++;
}
}
while (++i < blockSize);
while (rleSize != 0)
{
rleSize--;
mtfs[mtfArraySize++] = (Byte)(rleSize & 1);
symbolCounts[rleSize & 1]++;
rleSize >>= 1;
}
if (alphaSize < 256)
mtfs[mtfArraySize++] = (Byte)(alphaSize - 1);
else
{
mtfs[mtfArraySize++] = 0xFF;
mtfs[mtfArraySize++] = (Byte)(alphaSize - 256);
}
symbolCounts[alphaSize - 1]++;
}
UInt32 numSymbols = 0;
{
for (int i = 0; i < kMaxAlphaSize; i++)
numSymbols += symbolCounts[i];
}
int bestNumTables = kNumTablesMin;
UInt32 bestPrice = 0xFFFFFFFF;
UInt32 startPos = m_OutStreamCurrent->GetPos();
Byte startCurByte = m_OutStreamCurrent->GetCurByte();
for (int nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)
{
int numTables;
if(m_OptimizeNumTables)
{
m_OutStreamCurrent->SetPos(startPos);
m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);
if (nt <= kNumTablesMax)
numTables = nt;
else
numTables = bestNumTables;
}
else
{
if (numSymbols < 200) numTables = 2;
else if (numSymbols < 600) numTables = 3;
else if (numSymbols < 1200) numTables = 4;
else if (numSymbols < 2400) numTables = 5;
else numTables = 6;
}
WriteBits2(numTables, kNumTablesBits);
UInt32 numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize;
WriteBits2(numSelectors, kNumSelectorsBits);
{
UInt32 remFreq = numSymbols;
int gs = 0;
int t = numTables;
do
{
UInt32 tFreq = remFreq / t;
int ge = gs;
UInt32 aFreq = 0;
while (aFreq < tFreq) // && ge < alphaSize)
aFreq += symbolCounts[ge++];
if (ge - 1 > gs && t != numTables && t != 1 && (((numTables - t) & 1) == 1))
aFreq -= symbolCounts[--ge];
Byte *lens = Lens[t - 1];
int i = 0;
do
lens[i] = (i >= gs && i < ge) ? 0 : 1;
while (++i < alphaSize);
gs = ge;
remFreq -= aFreq;
}
while(--t != 0);
}
for (int pass = 0; pass < kNumHuffPasses; pass++)
{
{
int t = 0;
do
memset(Freqs[t], 0, sizeof(Freqs[t]));
while(++t < numTables);
}
{
UInt32 mtfPos = 0;
UInt32 g = 0;
do
{
UInt32 symbols[kGroupSize];
int i = 0;
do
{
UInt32 symbol = mtfs[mtfPos++];
if (symbol >= 0xFF)
symbol += mtfs[mtfPos++];
symbols[i] = symbol;
}
while (++i < kGroupSize && mtfPos < mtfArraySize);
UInt32 bestPrice = 0xFFFFFFFF;
int t = 0;
do
{
const Byte *lens = Lens[t];
UInt32 price = 0;
int j = 0;
do
price += lens[symbols[j]];
while (++j < i);
if (price < bestPrice)
{
m_Selectors[g] = (Byte)t;
bestPrice = price;
}
}
while(++t < numTables);
UInt32 *freqs = Freqs[m_Selectors[g++]];
int j = 0;
do
freqs[symbols[j]]++;
while (++j < i);
}
while (mtfPos < mtfArraySize);
}
int t = 0;
do
{
UInt32 *freqs = Freqs[t];
int i = 0;
do
if (freqs[i] == 0)
freqs[i] = 1;
while(++i < alphaSize);
Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding);
}
while(++t < numTables);
}
{
Byte mtfSel[kNumTablesMax];
{
int t = 0;
do
mtfSel[t] = (Byte)t;
while(++t < numTables);
}
UInt32 i = 0;
do
{
Byte sel = m_Selectors[i];
int pos;
for (pos = 0; mtfSel[pos] != sel; pos++)
WriteBit2(true);
WriteBit2(false);
for (; pos > 0; pos--)
mtfSel[pos] = mtfSel[pos - 1];
mtfSel[0] = sel;
}
while(++i < numSelectors);
}
{
int t = 0;
do
{
const Byte *lens = Lens[t];
UInt32 len = lens[0];
WriteBits2(len, kNumLevelsBits);
int i = 0;
do
{
UInt32 level = lens[i];
while (len != level)
{
WriteBit2(true);
if (len < level)
{
WriteBit2(false);
len++;
}
else
{
WriteBit2(true);
len--;
}
}
WriteBit2(false);
}
while (++i < alphaSize);
}
while(++t < numTables);
}
{
UInt32 groupSize = 0;
UInt32 groupIndex = 0;
const Byte *lens = 0;
const UInt32 *codes = 0;
UInt32 mtfPos = 0;
do
{
UInt32 symbol = mtfs[mtfPos++];
if (symbol >= 0xFF)
symbol += mtfs[mtfPos++];
if (groupSize == 0)
{
groupSize = kGroupSize;
int t = m_Selectors[groupIndex++];
lens = Lens[t];
codes = Codes[t];
}
groupSize--;
m_OutStreamCurrent->WriteBits(codes[symbol], lens[symbol]);
}
while (mtfPos < mtfArraySize);
}
if (!m_OptimizeNumTables)
break;
UInt32 price = m_OutStreamCurrent->GetPos() - startPos;
if (price <= bestPrice)
{
if (nt == kNumTablesMax)
break;
bestPrice = price;
bestNumTables = nt;
}
}
}
// blockSize > 0
UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize)
{
WriteByte2(kBlockSig0);
WriteByte2(kBlockSig1);
WriteByte2(kBlockSig2);
WriteByte2(kBlockSig3);
WriteByte2(kBlockSig4);
WriteByte2(kBlockSig5);
CBZip2CRC crc;
int numReps = 0;
Byte prevByte = block[0];
UInt32 i = 0;
do
{
Byte b = block[i];
if (numReps == kRleModeRepSize)
{
for (; b > 0; b--)
crc.UpdateByte(prevByte);
numReps = 0;
continue;
}
if (prevByte == b)
numReps++;
else
{
numReps = 1;
prevByte = b;
}
crc.UpdateByte(b);
}
while (++i < blockSize);
UInt32 crcRes = crc.GetDigest();
WriteCRC2(crcRes);
EncodeBlock(block, blockSize);
return crcRes;
}
void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses)
{
UInt32 numCrcs = m_NumCrcs;
bool needCompare = false;
UInt32 startBytePos = m_OutStreamCurrent->GetBytePos();
UInt32 startPos = m_OutStreamCurrent->GetPos();
Byte startCurByte = m_OutStreamCurrent->GetCurByte();
Byte endCurByte = 0;
UInt32 endPos = 0;
if (numPasses > 1 && blockSize >= (1 << 10))
{
UInt32 blockSize0 = blockSize / 2;
for (;(block[blockSize0] == block[blockSize0 - 1] ||
block[blockSize0 - 1] == block[blockSize0 - 2]) &&
blockSize0 < blockSize; blockSize0++);
if (blockSize0 < blockSize)
{
EncodeBlock2(block, blockSize0, numPasses - 1);
EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1);
endPos = m_OutStreamCurrent->GetPos();
endCurByte = m_OutStreamCurrent->GetCurByte();
if ((endPos & 7) > 0)
WriteBits2(0, 8 - (endPos & 7));
m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);
needCompare = true;
}
}
UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos();
UInt32 startPos2 = m_OutStreamCurrent->GetPos();
UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize);
UInt32 endPos2 = m_OutStreamCurrent->GetPos();
if (needCompare)
{
UInt32 size2 = endPos2 - startPos2;
if (size2 < endPos - startPos)
{
UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2;
Byte *buffer = m_OutStreamCurrent->GetStream();
for (UInt32 i = 0; i < numBytes; i++)
buffer[startBytePos + i] = buffer[startBytePos2 + i];
m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2);
m_NumCrcs = numCrcs;
m_CRCs[m_NumCrcs++] = crcVal;
}
else
{
m_OutStreamCurrent->SetPos(endPos);
m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte);
}
}
else
{
m_NumCrcs = numCrcs;
m_CRCs[m_NumCrcs++] = crcVal;
}
}
HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)
{
CMsbfEncoderTemp outStreamTemp;
outStreamTemp.SetStream(m_TempArray);
outStreamTemp.Init();
m_OutStreamCurrent = &outStreamTemp;
m_NumCrcs = 0;
EncodeBlock2(m_Block, blockSize, Encoder->NumPasses);
#ifdef COMPRESS_BZIP2_MT
if (Encoder->MtMode)
Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock();
#endif
for (UInt32 i = 0; i < m_NumCrcs; i++)
Encoder->CombinedCRC.Update(m_CRCs[i]);
Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte());
HRESULT res = S_OK;
#ifdef COMPRESS_BZIP2_MT
if (Encoder->MtMode)
{
UInt32 blockIndex = m_BlockIndex + 1;
if (blockIndex == Encoder->NumThreads)
blockIndex = 0;
if (Encoder->Progress)
{
UInt64 unpackSize = Encoder->m_OutStream.GetProcessedSize();
res = Encoder->Progress->SetRatioInfo(&m_PackSize, &unpackSize);
}
Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set();
}
#endif
return res;
}
void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte)
{
UInt32 bytesSize = (sizeInBits / 8);
for (UInt32 i = 0; i < bytesSize; i++)
m_OutStream.WriteBits(data[i], 8);
WriteBits(lastByte, (sizeInBits & 7));
}
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
ICompressProgressInfo *progress)
{
#ifdef COMPRESS_BZIP2_MT
Progress = progress;
if (!Create())
return E_FAIL;
for (UInt32 t = 0; t < NumThreads; t++)
#endif
{
#ifdef COMPRESS_BZIP2_MT
CThreadInfo &ti = ThreadsInfo[t];
ti.StreamWasFinishedEvent.Reset();
ti.WaitingWasStartedEvent.Reset();
ti.CanWriteEvent.Reset();
#else
CThreadInfo &ti = ThreadsInfo;
ti.Encoder = this;
#endif
ti.m_OptimizeNumTables = m_OptimizeNumTables;
if (!ti.Create())
return E_OUTOFMEMORY;
}
if (!m_InStream.Create(kBufferSize))
return E_OUTOFMEMORY;
if (!m_OutStream.Create(kBufferSize))
return E_OUTOFMEMORY;
m_InStream.SetStream(inStream);
m_InStream.Init();
m_OutStream.SetStream(outStream);
m_OutStream.Init();
CFlusher flusher(this);
CombinedCRC.Init();
#ifdef COMPRESS_BZIP2_MT
NextBlockIndex = 0;
StreamWasFinished = false;
CloseThreads = false;
CanStartWaitingEvent.Reset();
#endif
WriteByte(kArSig0);
WriteByte(kArSig1);
WriteByte(kArSig2);
WriteByte((Byte)(kArSig3 + m_BlockSizeMult));
#ifdef COMPRESS_BZIP2_MT
if (MtMode)
{
ThreadsInfo[0].CanWriteEvent.Set();
Result = S_OK;
CS.Leave();
UInt32 t;
for (t = 0; t < NumThreads; t++)
ThreadsInfo[t].StreamWasFinishedEvent.Lock();
CS.Enter();
CanStartWaitingEvent.Set();
for (t = 0; t < NumThreads; t++)
ThreadsInfo[t].WaitingWasStartedEvent.Lock();
CanStartWaitingEvent.Reset();
RINOK(Result);
}
else
#endif
{
for (;;)
{
CThreadInfo &ti =
#ifdef COMPRESS_BZIP2_MT
ThreadsInfo[0];
#else
ThreadsInfo;
#endif
UInt32 blockSize = ReadRleBlock(ti.m_Block);
if (blockSize == 0)
break;
RINOK(ti.EncodeBlock3(blockSize));
if (progress)
{
UInt64 packSize = m_InStream.GetProcessedSize();
UInt64 unpackSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
}
}
}
WriteByte(kFinSig0);
WriteByte(kFinSig1);
WriteByte(kFinSig2);
WriteByte(kFinSig3);
WriteByte(kFinSig4);
WriteByte(kFinSig5);
WriteCRC(CombinedCRC.GetDigest());
return S_OK;
}
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{
for(UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &property = properties[i];
switch(propIDs[i])
{
case NCoderPropID::kNumPasses:
{
if (property.vt != VT_UI4)
return E_INVALIDARG;
UInt32 numPasses = property.ulVal;
if (numPasses == 0)
numPasses = 1;
if (numPasses > kNumPassesMax)
numPasses = kNumPassesMax;
NumPasses = numPasses;
m_OptimizeNumTables = (NumPasses > 1);
break;
}
case NCoderPropID::kDictionarySize:
{
if (property.vt != VT_UI4)
return E_INVALIDARG;
UInt32 dictionary = property.ulVal / kBlockSizeStep;
if (dictionary < kBlockSizeMultMin)
dictionary = kBlockSizeMultMin;
else if (dictionary > kBlockSizeMultMax)
dictionary = kBlockSizeMultMax;
m_BlockSizeMult = dictionary;
break;
}
case NCoderPropID::kNumThreads:
{
#ifdef COMPRESS_BZIP2_MT
if (property.vt != VT_UI4)
return E_INVALIDARG;
NumThreads = property.ulVal;
if (NumThreads < 1)
NumThreads = 1;
#endif
break;
}
default:
return E_INVALIDARG;
}
}
return S_OK;
}
#ifdef COMPRESS_BZIP2_MT
STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)
{
NumThreads = numThreads;
if (NumThreads < 1)
NumThreads = 1;
return S_OK;
}
#endif
}}

View File

@@ -0,0 +1,246 @@
// Compress/BZip2/Encoder.h
#ifndef __COMPRESS_BZIP2_ENCODER_H
#define __COMPRESS_BZIP2_ENCODER_H
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
#include "../../Common/MSBFEncoder.h"
#include "../../Common/InBuffer.h"
#include "../../Common/OutBuffer.h"
#include "BZip2Const.h"
#include "BZip2CRC.h"
#ifdef COMPRESS_BZIP2_MT
#include "../../../Windows/Thread.h"
#include "../../../Windows/Synchronization.h"
#endif
namespace NCompress {
namespace NBZip2 {
class CMsbfEncoderTemp
{
UInt32 m_Pos;
int m_BitPos;
Byte m_CurByte;
Byte *Buffer;
public:
void SetStream(Byte *buffer) { Buffer = buffer; }
Byte *GetStream() const { return Buffer; }
void Init()
{
m_Pos = 0;
m_BitPos = 8;
m_CurByte = 0;
}
void Flush()
{
if(m_BitPos < 8)
WriteBits(0, m_BitPos);
}
void WriteBits(UInt32 value, int numBits)
{
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)
{
Buffer[m_Pos++] = m_CurByte;
m_BitPos = 8;
}
}
}
UInt32 GetBytePos() const { return m_Pos ; }
UInt32 GetPos() const { return m_Pos * 8 + (8 - m_BitPos); }
Byte GetCurByte() const { return m_CurByte; }
void SetPos(UInt32 bitPos)
{
m_Pos = bitPos / 8;
m_BitPos = 8 - (bitPos & 7);
}
void SetCurState(UInt32 bitPos, Byte curByte)
{
m_BitPos = 8 - bitPos;
m_CurByte = curByte;
}
};
class CEncoder;
const int kNumPassesMax = 10;
class CThreadInfo
{
public:
Byte *m_Block;
private:
Byte *m_MtfArray;
Byte *m_TempArray;
UInt32 *m_BlockSorterIndex;
CMsbfEncoderTemp *m_OutStreamCurrent;
Byte Lens[kNumTablesMax][kMaxAlphaSize];
UInt32 Freqs[kNumTablesMax][kMaxAlphaSize];
UInt32 Codes[kNumTablesMax][kMaxAlphaSize];
Byte m_Selectors[kNumSelectorsMax];
UInt32 m_CRCs[1 << kNumPassesMax];
UInt32 m_NumCrcs;
int m_BlockIndex;
void FinishStream(bool needLeave);
void WriteBits2(UInt32 value, UInt32 numBits);
void WriteByte2(Byte b);
void WriteBit2(bool v);
void WriteCRC2(UInt32 v);
void EncodeBlock(const Byte *block, UInt32 blockSize);
UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize);
void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses);
public:
bool m_OptimizeNumTables;
CEncoder *Encoder;
#ifdef COMPRESS_BZIP2_MT
NWindows::CThread Thread;
NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;
NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;
// it's not member of this thread. We just need one event per thread
NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;
UInt64 m_PackSize;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
#endif
CThreadInfo(): m_BlockSorterIndex(0), m_Block(0) {}
~CThreadInfo() { Free(); }
bool Create();
void Free();
HRESULT EncodeBlock3(UInt32 blockSize);
DWORD ThreadFunc();
};
class CEncoder :
public ICompressCoder,
public ICompressSetCoderProperties,
#ifdef COMPRESS_BZIP2_MT
public ICompressSetCoderMt,
#endif
public CMyUnknownImp
{
UInt32 m_BlockSizeMult;
bool m_OptimizeNumTables;
UInt32 m_NumPassesPrev;
UInt32 m_NumThreadsPrev;
public:
CInBuffer m_InStream;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
NStream::NMSBF::CEncoder<COutBuffer> m_OutStream;
UInt32 NumPasses;
CBZip2CombinedCRC CombinedCRC;
#ifdef COMPRESS_BZIP2_MT
CThreadInfo *ThreadsInfo;
NWindows::NSynchronization::CCriticalSection CS;
UInt32 NumThreads;
bool MtMode;
UInt32 NextBlockIndex;
bool CloseThreads;
bool StreamWasFinished;
NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;
HRESULT Result;
ICompressProgressInfo *Progress;
#else
CThreadInfo ThreadsInfo;
#endif
UInt32 ReadRleBlock(Byte *buffer);
void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte);
void WriteBits(UInt32 value, UInt32 numBits);
void WriteByte(Byte b);
void WriteBit(bool v);
void WriteCRC(UInt32 v);
#ifdef COMPRESS_BZIP2_MT
bool Create();
void Free();
#endif
public:
CEncoder();
#ifdef COMPRESS_BZIP2_MT
~CEncoder();
#endif
HRESULT Flush() { return m_OutStream.Flush(); }
void ReleaseStreams()
{
m_InStream.ReleaseStream();
m_OutStream.ReleaseStream();
}
class CFlusher
{
CEncoder *_coder;
public:
bool NeedFlush;
CFlusher(CEncoder *coder): _coder(coder), NeedFlush(true) {}
~CFlusher()
{
if (NeedFlush)
_coder->Flush();
_coder->ReleaseStreams();
}
};
#ifdef COMPRESS_BZIP2_MT
MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties)
#else
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
#endif
HRESULT 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);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
#ifdef COMPRESS_BZIP2_MT
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
#endif
};
}}
#endif

View File

@@ -0,0 +1,93 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#ifdef _WIN32
#include "Common/Alloc.h"
#endif
#include "BZip2Encoder.h"
#include "BZip2Decoder.h"
// {23170F69-40C1-278B-0402-020000000000}
DEFINE_GUID(CLSID_CCompressBZip2Decoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0402-020000000100}
DEFINE_GUID(CLSID_CCompressBZip2Encoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00);
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID /*lpReserved*/)
{
#ifdef _WIN32
if (dwReason == DLL_PROCESS_ATTACH)
SetLargePageSize();
#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_CCompressBZip2Decoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NBZip2::CDecoder;
}
else if (*clsid == CLSID_CCompressBZip2Encoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NBZip2::CEncoder;
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*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, 0x02, 0x02 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(L"BZip2")) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressBZip2Decoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kEncoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressBZip2Encoder, 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,56 @@
PROG = BZip2.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_BZIP2_MT
LIBS = $(LIBS) oleaut32.lib
BZIP2_OBJS = \
$O\DllExports.obj \
$O\BZip2CRC.obj \
BZIP2_OPT_OBJS = \
$O\BZip2Decoder.obj \
$O\BZip2Encoder.obj \
COMMON_OBJS = \
$O\Alloc.obj \
WIN_OBJS = \
$O\Synchronization.obj
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
C_OBJS = \
$O\Sort.obj \
OBJS = \
$O\StdAfx.obj \
$(BZIP2_OBJS) \
$(BZIP2_OPT_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(7ZIP_COMMON_OBJS) \
$O\BlockSort.obj \
$(C_OBJS) \
$O\HuffmanEncode.obj \
$O\resource.res
!include "../../../Build.mak"
$(BZIP2_OBJS): $(*B).cpp
$(COMPL)
$(BZIP2_OPT_OBJS): $(*B).cpp
$(COMPL_O2)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(WIN_OBJS): ../../../Windows/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$O\BlockSort.obj: ../BWT/$(*B).cpp
$(COMPL_O2)
$(C_OBJS): ../../../../C/$(*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("BZip2 Codec", "BZip2")

View File

@@ -0,0 +1,131 @@
// BZip2Decoder.cpp
#include "StdAfx.h"
#include "BZip2Decoder.h"
#include "../../../Common/Alloc.h"
#include "Original/bzlib.h"
namespace NCompress {
namespace NBZip2 {
static const UInt32 kBufferSize = (1 << 20);
CDecoder::~CDecoder()
{
BigFree(m_InBuffer);
}
struct CBZip2Decompressor: public bz_stream
{
int Init(int verbosity, int small) { return BZ2_bzDecompressInit(this, verbosity, small); }
int Decompress() { return BZ2_bzDecompress(this); }
int End() { return BZ2_bzDecompressEnd(this); }
UInt64 GetTotalIn() const { return (UInt64(total_in_hi32) << 32) + total_in_lo32; }
UInt64 GetTotalOut() const { return (UInt64(total_out_hi32) << 32) + total_out_lo32; }
};
class CBZip2DecompressorReleaser
{
CBZip2Decompressor *m_Decompressor;
public:
CBZip2DecompressorReleaser(CBZip2Decompressor *decompressor): m_Decompressor(decompressor) {}
void Diable() { m_Decompressor = NULL; }
~CBZip2DecompressorReleaser() { if (m_Decompressor != NULL) m_Decompressor->End(); }
};
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
m_InSize = 0;
if (m_InBuffer == 0)
{
m_InBuffer = (Byte *)BigAlloc(kBufferSize * 2);
if (m_InBuffer == 0)
return E_OUTOFMEMORY;
}
Byte *outBuffer = m_InBuffer + kBufferSize;
CBZip2Decompressor bzStream;
bzStream.bzalloc = NULL;
bzStream.bzfree = NULL;
bzStream.opaque = NULL;
int result = bzStream.Init(0, 0);
switch(result)
{
case BZ_OK:
break;
case BZ_MEM_ERROR:
return E_OUTOFMEMORY;
default:
return E_FAIL;
}
CBZip2DecompressorReleaser releaser(&bzStream);
bzStream.avail_in = 0;
for (;;)
{
if (bzStream.avail_in == 0)
{
bzStream.next_in = (char *)m_InBuffer;
UInt32 processedSize;
RINOK(inStream->Read(m_InBuffer, kBufferSize, &processedSize));
bzStream.avail_in = processedSize;
}
bzStream.next_out = (char *)outBuffer;
bzStream.avail_out = kBufferSize;
result = bzStream.Decompress();
UInt32 numBytesToWrite = kBufferSize - bzStream.avail_out;
if (numBytesToWrite > 0)
{
UInt32 processedSize;
RINOK(outStream->Write(outBuffer, numBytesToWrite, &processedSize));
if (numBytesToWrite != processedSize)
return E_FAIL;
}
if (result == BZ_STREAM_END)
break;
switch(result)
{
case BZ_DATA_ERROR:
case BZ_DATA_ERROR_MAGIC:
return S_FALSE;
case BZ_OK:
break;
case BZ_MEM_ERROR:
return E_OUTOFMEMORY;
default:
return E_FAIL;
}
if (progress != NULL)
{
UInt64 totalIn = bzStream.GetTotalIn();
UInt64 totalOut = bzStream.GetTotalOut();
RINOK(progress->SetRatioInfo(&totalIn, &totalOut));
}
}
m_InSize = bzStream.GetTotalIn();
return S_OK;
}
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(...) { return S_FALSE; }
}
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
{
if (value == NULL)
return E_INVALIDARG;
*value = m_InSize;
return S_OK;
}
}}

View File

@@ -0,0 +1,38 @@
// Compress/BZip2/Decoder.h
#ifndef __COMPRESS_BZIP2_DECODER_H
#define __COMPRESS_BZIP2_DECODER_H
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
namespace NCompress {
namespace NBZip2 {
class CDecoder :
public ICompressCoder,
public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
Byte *m_InBuffer;
UInt64 m_InSize;
public:
CDecoder(): m_InBuffer(0), m_InSize(0) {};
~CDecoder();
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
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);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};
}}
#endif

View File

@@ -0,0 +1,120 @@
// BZip2Encoder.cpp
#include "StdAfx.h"
#include "BZip2Encoder.h"
#include "../../../Common/Alloc.h"
#include "Original/bzlib.h"
namespace NCompress {
namespace NBZip2 {
static const UInt32 kBufferSize = (1 << 20);
CEncoder::~CEncoder()
{
BigFree(m_InBuffer);
}
struct CBZip2Compressor: public bz_stream
{
int Init(int blockSize100k, int verbosity, int small)
{ return BZ2_bzCompressInit(this, blockSize100k, verbosity, small); }
int Compress(int action ) { return BZ2_bzCompress(this, action ); }
int End() { return BZ2_bzCompressEnd(this); }
UInt64 GetTotalIn() const { return (UInt64(total_in_hi32) << 32) + total_in_lo32; }
UInt64 GetTotalOut() const { return (UInt64(total_out_hi32) << 32) + total_out_lo32; }
};
class CBZip2CompressorReleaser
{
CBZip2Compressor *m_Compressor;
public:
CBZip2CompressorReleaser(CBZip2Compressor *compressor): m_Compressor(compressor) {}
void Disable() { m_Compressor = NULL; }
~CBZip2CompressorReleaser() { if (m_Compressor != NULL) m_Compressor->End(); }
};
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (m_InBuffer == 0)
{
m_InBuffer = (Byte *)BigAlloc(kBufferSize * 2);
if (m_InBuffer == 0)
return E_OUTOFMEMORY;
}
Byte *outBuffer = m_InBuffer + kBufferSize;
CBZip2Compressor bzStream;
bzStream.bzalloc = NULL;
bzStream.bzfree = NULL;
bzStream.opaque = NULL;
int result = bzStream.Init(9, 0, 0);
switch(result)
{
case BZ_OK:
break;
case BZ_MEM_ERROR:
return E_OUTOFMEMORY;
default:
return E_FAIL;
}
CBZip2CompressorReleaser releaser(&bzStream);
bzStream.avail_in = 0;
for (;;)
{
if (bzStream.avail_in == 0)
{
bzStream.next_in = (char *)m_InBuffer;
UInt32 processedSize;
RINOK(inStream->Read(m_InBuffer, kBufferSize, &processedSize));
bzStream.avail_in = processedSize;
}
bzStream.next_out = (char *)outBuffer;
bzStream.avail_out = kBufferSize;
bool askFinish = (bzStream.avail_in == 0);
result = bzStream.Compress(askFinish ? BZ_FINISH : BZ_RUN);
UInt32 numBytesToWrite = kBufferSize - bzStream.avail_out;
if (numBytesToWrite > 0)
{
UInt32 processedSize;
RINOK(outStream->Write(outBuffer, numBytesToWrite, &processedSize));
if (numBytesToWrite != processedSize)
return E_FAIL;
}
if (result == BZ_STREAM_END)
break;
switch(result)
{
case BZ_RUN_OK:
if (!askFinish)
break;
return E_FAIL;
case BZ_FINISH_OK:
if (askFinish)
break;
return E_FAIL;
case BZ_MEM_ERROR:
return E_OUTOFMEMORY;
default:
return E_FAIL;
}
if (progress != NULL)
{
UInt64 totalIn = bzStream.GetTotalIn();
UInt64 totalOut = bzStream.GetTotalOut();
RINOK(progress->SetRatioInfo(&totalIn, &totalOut));
}
}
// result = bzStream.End();
return S_OK;
}
}}

View File

@@ -0,0 +1,30 @@
// Compress/BZip2/Encoder.h
#ifndef __COMPRESS_BZIP2_ENCODER_H
#define __COMPRESS_BZIP2_ENCODER_H
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
namespace NCompress {
namespace NBZip2 {
class CEncoder :
public ICompressCoder,
public CMyUnknownImp
{
Byte *m_InBuffer;
public:
CEncoder(): m_InBuffer(0) {};
~CEncoder();
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
};
}}
#endif

View File

@@ -0,0 +1,10 @@
#include "StdAfx.h"
#include "Original/bzlib.h"
extern "C"
void bz_internal_error (int errcode)
{
throw "error";
}

View File

@@ -0,0 +1,86 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "BZip2Encoder.h"
#include "BZip2Decoder.h"
// {23170F69-40C1-278B-0402-020000000000}
DEFINE_GUID(CLSID_CCompressBZip2Decoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0402-020000000100}
DEFINE_GUID(CLSID_CCompressBZip2Encoder,
0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 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;
int correctInterface = (*iid == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
if (*clsid == CLSID_CCompressBZip2Decoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NBZip2::CDecoder;
}
else if (*clsid == CLSID_CCompressBZip2Encoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NBZip2::CEncoder;
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*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, 0x02, 0x02 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(L"BZip2")) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressBZip2Decoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kEncoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressBZip2Encoder, 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,16 @@
// ARM.cpp
#include "StdAfx.h"
#include "ARM.h"
#include "../../../../C/Compress/Branch/BranchARM.c"
UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARM_Convert(data, size, _bufferPos, 1);
}
UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARM_Convert(data, size, _bufferPos, 0);
}

10
CPP/7zip/Compress/Branch/ARM.h Executable file
View File

@@ -0,0 +1,10 @@
// ARM.h
#ifndef __ARM_H
#define __ARM_H
#include "BranchCoder.h"
MyClassA(BC_ARM, 0x05, 1)
#endif

View File

@@ -0,0 +1,16 @@
// ARMThumb.cpp
#include "StdAfx.h"
#include "ARMThumb.h"
#include "../../../../C/Compress/Branch/BranchARMThumb.c"
UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARMThumb_Convert(data, size, _bufferPos, 1);
}
UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARMThumb_Convert(data, size, _bufferPos, 0);
}

View File

@@ -0,0 +1,10 @@
// ARMThumb.h
#ifndef __ARMTHUMB_H
#define __ARMTHUMB_H
#include "BranchCoder.h"
MyClassA(BC_ARMThumb, 0x07, 1)
#endif

View File

@@ -0,0 +1,298 @@
# Microsoft Developer Studio Project File - Name="Branch" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Branch - 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 "Branch.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 "Branch.mak" CFG="Branch - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Branch - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Branch - 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)" == "Branch - 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 "BRANCH_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BRANCH_EXPORTS" /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# 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 0x419 /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\Branch.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Branch - 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 "BRANCH_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BRANCH_EXPORTS" /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 0x419 /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\Branch.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Branch - Win32 Release"
# Name "Branch - 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 "Methods"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\ARM.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\ARM.h
# End Source File
# Begin Source File
SOURCE=.\ARMThumb.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\ARMThumb.h
# End Source File
# Begin Source File
SOURCE=.\BranchCoder.cpp
# End Source File
# Begin Source File
SOURCE=.\BranchCoder.h
# End Source File
# Begin Source File
SOURCE=.\BranchTypes.h
# End Source File
# Begin Source File
SOURCE=.\BranchX86.h
# End Source File
# Begin Source File
SOURCE=.\IA64.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\IA64.h
# End Source File
# Begin Source File
SOURCE=.\PPC.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\PPC.h
# End Source File
# Begin Source File
SOURCE=.\SPARC.cpp
# End Source File
# Begin Source File
SOURCE=.\SPARC.h
# End Source File
# Begin Source File
SOURCE=.\x86.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\x86.h
# End Source File
# Begin Source File
SOURCE=.\x86_2.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "Branch - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\x86_2.h
# End Source File
# End Group
# Begin Group "Stream"
# 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\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# End Group
# Begin Group "RangeCoder"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\RangeCoder\RangeCoder.h
# End Source File
# Begin Source File
SOURCE=..\RangeCoder\RangeCoderBit.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
# End Group
# 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: "Branch"=.\Branch.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,18 @@
// BranchCoder.cpp
#include "StdAfx.h"
#include "BranchCoder.h"
STDMETHODIMP CBranchConverter::Init()
{
_bufferPos = 0;
SubInit();
return S_OK;
}
STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)
{
UInt32 processedSize = SubFilter(data, size);
_bufferPos += processedSize;
return processedSize;
}

View File

@@ -0,0 +1,54 @@
// BranchCoder.h
#ifndef __BRANCH_CODER_H
#define __BRANCH_CODER_H
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "Common/Alloc.h"
#include "../../ICoder.h"
class CBranchConverter:
public ICompressFilter,
public CMyUnknownImp
{
protected:
UInt32 _bufferPos;
virtual void SubInit() {}
virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;
public:
MY_UNKNOWN_IMP;
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
};
#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \
{ public: UInt32 SubFilter(Byte *data, UInt32 size); };
#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \
{ public: UInt32 SubFilter(Byte *data, UInt32 size); };
#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
{ public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
{ public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
#define MyClass2b(Name, id, subId, encodingId) \
DEFINE_GUID(CLSID_CCompressConvert ## Name, \
0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00);
#define MyClassA(Name, id, subId) \
MyClass2b(Name ## _Encoder, id, subId, 0x01) \
MyClassEncoderA(Name ## _Encoder) \
MyClass2b(Name ## _Decoder, id, subId, 0x00) \
MyClassDecoderA(Name ## _Decoder)
#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \
MyClass2b(Name ## _Encoder, id, subId, 0x01) \
MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \
MyClass2b(Name ## _Decoder, id, subId, 0x00) \
MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)
#endif

View File

@@ -0,0 +1,152 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "x86.h"
#include "PPC.h"
#include "IA64.h"
#include "ARM.h"
#include "ARMThumb.h"
#include "x86_2.h"
#include "SPARC.h"
#define MY_CreateClass0(n) \
if (*clsid == CLSID_CCompressConvert ## n ## _Encoder) { \
if (!correctInterface) \
return E_NOINTERFACE; \
filter = (ICompressFilter *)new C ## n ## _Encoder(); \
} else if (*clsid == CLSID_CCompressConvert ## n ## _Decoder){ \
if (!correctInterface) \
return E_NOINTERFACE; \
filter = (ICompressFilter *)new C ## n ## _Decoder(); \
}
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
{
return TRUE;
}
STDAPI CreateObject(
const GUID *clsid,
const GUID *interfaceID,
void **outObject)
{
COM_TRY_BEGIN
*outObject = 0;
int correctInterface = (*interfaceID == IID_ICompressFilter);
CMyComPtr<ICompressFilter> filter;
MY_CreateClass0(BCJ_x86)
else
MY_CreateClass0(BC_ARM)
else
MY_CreateClass0(BC_PPC_B)
else
MY_CreateClass0(BC_IA64)
else
MY_CreateClass0(BC_ARMThumb)
else
MY_CreateClass0(BC_SPARC)
else
{
CMyComPtr<ICompressCoder2> coder2;
correctInterface = (*interfaceID == IID_ICompressCoder2);
if (*clsid == CLSID_CCompressConvertBCJ2_x86_Encoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder2 = (ICompressCoder2 *)new CBCJ2_x86_Encoder();
}
else if (*clsid == CLSID_CCompressConvertBCJ2_x86_Decoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder2 = (ICompressCoder2 *)new CBCJ2_x86_Decoder();
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = coder2.Detach();
return S_OK;
}
*outObject = filter.Detach();
return S_OK;
COM_TRY_END
}
struct CBranchMethodItem
{
char ID[4];
const wchar_t *UserName;
const GUID *Decoder;
const GUID *Encoder;
UINT32 NumInStreams;
};
#define METHOD_ITEM(Name, id, subId, UserName, NumInStreams) \
{ { 0x03, 0x03, id, subId }, UserName, \
&CLSID_CCompressConvert ## Name ## _Decoder, \
&CLSID_CCompressConvert ## Name ## _Encoder, NumInStreams }
static CBranchMethodItem g_Methods[] =
{
METHOD_ITEM(BCJ_x86, 0x01, 0x03, L"BCJ", 1),
METHOD_ITEM(BCJ2_x86, 0x01, 0x1B, L"BCJ2", 4),
METHOD_ITEM(BC_PPC_B, 0x02, 0x05, L"BC_PPC_B", 1),
// METHOD_ITEM(BC_Alpha, 0x03, 1, L"BC_Alpha", 1),
METHOD_ITEM(BC_IA64, 0x04, 1, L"BC_IA64", 1),
METHOD_ITEM(BC_ARM, 0x05, 1, L"BC_ARM", 1),
// METHOD_ITEM(BC_M68_B, 0x06, 5, L"BC_M68_B", 1),
METHOD_ITEM(BC_ARMThumb, 0x07, 1, L"BC_ARMThumb", 1),
METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"BC_SPARC", 1)
};
STDAPI GetNumberOfMethods(UINT32 *numMethods)
{
*numMethods = sizeof(g_Methods) / sizeof(g_Methods[1]);
return S_OK;
}
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
if (index > sizeof(g_Methods) / sizeof(g_Methods[1]))
return E_INVALIDARG;
VariantClear((tagVARIANT *)value);
const CBranchMethodItem &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 ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)method.Encoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kInStreams:
{
if (method.NumInStreams != 1)
{
value->vt = VT_UI4;
value->ulVal = method.NumInStreams;
}
return S_OK;
}
}
return S_OK;
}

View File

@@ -0,0 +1,16 @@
// IA64.cpp
#include "StdAfx.h"
#include "IA64.h"
#include "../../../../C/Compress/Branch/BranchIA64.c"
UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::IA64_Convert(data, size, _bufferPos, 1);
}
UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::IA64_Convert(data, size, _bufferPos, 0);
}

10
CPP/7zip/Compress/Branch/IA64.h Executable file
View File

@@ -0,0 +1,10 @@
// IA64.h
#ifndef __IA64_H
#define __IA64_H
#include "BranchCoder.h"
MyClassA(BC_IA64, 0x04, 1)
#endif

View File

@@ -0,0 +1,17 @@
// PPC.cpp
#include "StdAfx.h"
#include "PPC.h"
#include "Windows/Defs.h"
#include "../../../../C/Compress/Branch/BranchPPC.c"
UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::PPC_B_Convert(data, size, _bufferPos, 1);
}
UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::PPC_B_Convert(data, size, _bufferPos, 0);
}

10
CPP/7zip/Compress/Branch/PPC.h Executable file
View File

@@ -0,0 +1,10 @@
// PPC.h
#ifndef __PPC_H
#define __PPC_H
#include "BranchCoder.h"
MyClassA(BC_PPC_B, 0x02, 5)
#endif

View File

@@ -0,0 +1,17 @@
// SPARC.cpp
#include "StdAfx.h"
#include "SPARC.h"
#include "Windows/Defs.h"
#include "../../../../C/Compress/Branch/BranchSPARC.c"
UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::SPARC_Convert(data, size, _bufferPos, 1);
}
UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::SPARC_Convert(data, size, _bufferPos, 0);
}

View File

@@ -0,0 +1,10 @@
// SPARC.h
#ifndef __SPARC_H
#define __SPARC_H
#include "BranchCoder.h"
MyClassA(BC_SPARC, 0x08, 5)
#endif

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,48 @@
PROG = Branch.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../
LIBS = $(LIBS) oleaut32.lib
BRANCH_OBJS = \
$O\DllExports.obj \
BRANCH_OPT_OBJS = \
$O\ARM.obj \
$O\ARMThumb.obj \
$O\BranchCoder.obj \
$O\IA64.obj \
$O\PPC.obj \
$O\SPARC.obj \
$O\x86.obj \
$O\x86_2.obj \
COMMON_OBJS = \
$O\Alloc.obj \
7ZIP_COMMON_OBJS = \
$O\InBuffer.obj \
$O\OutBuffer.obj \
OBJS = \
$O\StdAfx.obj \
$(BRANCH_OBJS) \
$(BRANCH_OPT_OBJS) \
$(COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$O\RangeCoderBit.obj \
$O\resource.res
!include "../../../Build.mak"
$(BRANCH_OBJS): $(*B).cpp
$(COMPL)
$(BRANCH_OPT_OBJS): $(*B).cpp
$(COMPL_O2)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp
$(COMPL)

View File

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

View File

@@ -0,0 +1,18 @@
// x86.cpp
#include "StdAfx.h"
#include "x86.h"
#include "Windows/Defs.h"
#include "../../../../C/Compress/Branch/BranchX86.c"
UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)
{
return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1);
}
UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0);
}

19
CPP/7zip/Compress/Branch/x86.h Executable file
View File

@@ -0,0 +1,19 @@
// x86.h
#ifndef __X86_H
#define __X86_H
#include "BranchCoder.h"
#include "../../../../C/Compress/Branch/BranchX86.h"
struct CBranch86
{
UInt32 _prevMask;
UInt32 _prevPos;
void x86Init() { x86_Convert_Init(_prevMask, _prevPos); }
};
MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,
virtual void SubInit() { x86Init(); })
#endif

View File

@@ -0,0 +1,412 @@
// x86_2.cpp
#include "StdAfx.h"
#include "x86_2.h"
#include "../../../Common/Alloc.h"
static const int kBufferSize = 1 << 17;
inline bool IsJcc(Byte b0, Byte b1)
{
return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
}
#ifndef EXTRACT_ONLY
static bool inline Test86MSByte(Byte b)
{
return (b == 0 || b == 0xFF);
}
bool CBCJ2_x86_Encoder::Create()
{
if (!_mainStream.Create(1 << 16))
return false;
if (!_callStream.Create(1 << 20))
return false;
if (!_jumpStream.Create(1 << 20))
return false;
if (!_rangeEncoder.Create(1 << 20))
return false;
if (_buffer == 0)
{
_buffer = (Byte *)MidAlloc(kBufferSize);
if (_buffer == 0)
return false;
}
return true;
}
CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
{
::MidFree(_buffer);
}
HRESULT CBCJ2_x86_Encoder::Flush()
{
RINOK(_mainStream.Flush());
RINOK(_callStream.Flush());
RINOK(_jumpStream.Flush());
_rangeEncoder.FlushData();
return _rangeEncoder.FlushStream();
}
const UInt32 kDefaultLimit = (1 << 24);
HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 ** /* outSizes */,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != 1 || numOutStreams != 4)
return E_INVALIDARG;
if (!Create())
return E_OUTOFMEMORY;
bool sizeIsDefined = false;
UInt64 inSize = 0;
if (inSizes != NULL)
if (inSizes[0] != NULL)
{
inSize = *inSizes[0];
if (inSize <= kDefaultLimit)
sizeIsDefined = true;
}
ISequentialInStream *inStream = inStreams[0];
_mainStream.SetStream(outStreams[0]);
_mainStream.Init();
_callStream.SetStream(outStreams[1]);
_callStream.Init();
_jumpStream.SetStream(outStreams[2]);
_jumpStream.Init();
_rangeEncoder.SetStream(outStreams[3]);
_rangeEncoder.Init();
for (int i = 0; i < 256; i++)
_statusE8Encoder[i].Init();
_statusE9Encoder.Init();
_statusJccEncoder.Init();
CCoderReleaser releaser(this);
CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
{
inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
}
UInt32 nowPos = 0;
UInt64 nowPos64 = 0;
UInt32 bufferPos = 0;
Byte prevByte = 0;
UInt64 subStreamIndex = 0;
UInt64 subStreamStartPos = 0;
UInt64 subStreamEndPos = 0;
for (;;)
{
UInt32 processedSize = 0;
for (;;)
{
UInt32 size = kBufferSize - (bufferPos + processedSize);
UInt32 processedSizeLoc;
if (size == 0)
break;
RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
if (processedSizeLoc == 0)
break;
processedSize += processedSizeLoc;
}
UInt32 endPos = bufferPos + processedSize;
if (endPos < 5)
{
// change it
for (bufferPos = 0; bufferPos < endPos; bufferPos++)
{
Byte b = _buffer[bufferPos];
_mainStream.WriteByte(b);
if (b == 0xE8)
_statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
else if (b == 0xE9)
_statusE9Encoder.Encode(&_rangeEncoder, 0);
else if (IsJcc(prevByte, b))
_statusJccEncoder.Encode(&_rangeEncoder, 0);
prevByte = b;
}
return Flush();
}
bufferPos = 0;
UInt32 limit = endPos - 5;
while(bufferPos <= limit)
{
Byte b = _buffer[bufferPos];
_mainStream.WriteByte(b);
if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
{
bufferPos++;
prevByte = b;
continue;
}
Byte nextByte = _buffer[bufferPos + 4];
UInt32 src =
(UInt32(nextByte) << 24) |
(UInt32(_buffer[bufferPos + 3]) << 16) |
(UInt32(_buffer[bufferPos + 2]) << 8) |
(_buffer[bufferPos + 1]);
UInt32 dest = (nowPos + bufferPos + 5) + src;
// if (Test86MSByte(nextByte))
bool convert;
if (getSubStreamSize != NULL)
{
UInt64 currentPos = (nowPos64 + bufferPos);
while (subStreamEndPos < currentPos)
{
UInt64 subStreamSize;
HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
if (result == S_OK)
{
subStreamStartPos = subStreamEndPos;
subStreamEndPos += subStreamSize;
subStreamIndex++;
}
else if (result == S_FALSE || result == E_NOTIMPL)
{
getSubStreamSize.Release();
subStreamStartPos = 0;
subStreamEndPos = subStreamStartPos - 1;
}
else
return result;
}
if (getSubStreamSize == NULL)
{
if (sizeIsDefined)
convert = (dest < inSize);
else
convert = Test86MSByte(nextByte);
}
else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
convert = Test86MSByte(nextByte);
else
{
UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
}
}
else if (sizeIsDefined)
convert = (dest < inSize);
else
convert = Test86MSByte(nextByte);
if (convert)
{
if (b == 0xE8)
_statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
else if (b == 0xE9)
_statusE9Encoder.Encode(&_rangeEncoder, 1);
else
_statusJccEncoder.Encode(&_rangeEncoder, 1);
bufferPos += 5;
if (b == 0xE8)
{
_callStream.WriteByte((Byte)(dest >> 24));
_callStream.WriteByte((Byte)(dest >> 16));
_callStream.WriteByte((Byte)(dest >> 8));
_callStream.WriteByte((Byte)(dest));
}
else
{
_jumpStream.WriteByte((Byte)(dest >> 24));
_jumpStream.WriteByte((Byte)(dest >> 16));
_jumpStream.WriteByte((Byte)(dest >> 8));
_jumpStream.WriteByte((Byte)(dest));
}
prevByte = nextByte;
}
else
{
if (b == 0xE8)
_statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
else if (b == 0xE9)
_statusE9Encoder.Encode(&_rangeEncoder, 0);
else
_statusJccEncoder.Encode(&_rangeEncoder, 0);
bufferPos++;
prevByte = b;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, NULL));
}
UInt32 i = 0;
while(bufferPos < endPos)
_buffer[i++] = _buffer[bufferPos++];
bufferPos = i;
}
}
STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
{
return CodeReal(inStreams, inSizes, numInStreams,
outStreams, outSizes,numOutStreams, progress);
}
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
#endif
HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
const UInt64 ** /* inSizes */,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 ** /* outSizes */,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != 4 || numOutStreams != 1)
return E_INVALIDARG;
if (!_mainInStream.Create(1 << 16))
return E_OUTOFMEMORY;
if (!_callStream.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_jumpStream.Create(1 << 16))
return E_OUTOFMEMORY;
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
if (!_outStream.Create(1 << 16))
return E_OUTOFMEMORY;
_mainInStream.SetStream(inStreams[0]);
_callStream.SetStream(inStreams[1]);
_jumpStream.SetStream(inStreams[2]);
_rangeDecoder.SetStream(inStreams[3]);
_outStream.SetStream(outStreams[0]);
_mainInStream.Init();
_callStream.Init();
_jumpStream.Init();
_rangeDecoder.Init();
_outStream.Init();
for (int i = 0; i < 256; i++)
_statusE8Decoder[i].Init();
_statusE9Decoder.Init();
_statusJccDecoder.Init();
CCoderReleaser releaser(this);
Byte prevByte = 0;
UInt32 processedBytes = 0;
for (;;)
{
if (processedBytes > (1 << 20) && progress != NULL)
{
UInt64 nowPos64 = _outStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(NULL, &nowPos64));
processedBytes = 0;
}
processedBytes++;
Byte b;
if (!_mainInStream.ReadByte(b))
return Flush();
_outStream.WriteByte(b);
if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
{
prevByte = b;
continue;
}
bool status;
if (b == 0xE8)
status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
else if (b == 0xE9)
status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
else
status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
if (status)
{
UInt32 src;
if (b == 0xE8)
{
Byte b0;
if(!_callStream.ReadByte(b0))
return S_FALSE;
src = ((UInt32)b0) << 24;
if(!_callStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0) << 16;
if(!_callStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0) << 8;
if(!_callStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0);
}
else
{
Byte b0;
if(!_jumpStream.ReadByte(b0))
return S_FALSE;
src = ((UInt32)b0) << 24;
if(!_jumpStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0) << 16;
if(!_jumpStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0) << 8;
if(!_jumpStream.ReadByte(b0))
return S_FALSE;
src |= ((UInt32)b0);
}
UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
_outStream.WriteByte((Byte)(dest));
_outStream.WriteByte((Byte)(dest >> 8));
_outStream.WriteByte((Byte)(dest >> 16));
_outStream.WriteByte((Byte)(dest >> 24));
prevByte = (Byte)(dest >> 24);
processedBytes += 4;
}
else
prevByte = b;
}
}
STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
{
return CodeReal(inStreams, inSizes, numInStreams,
outStreams, outSizes,numOutStreams, progress);
}
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}

133
CPP/7zip/Compress/Branch/x86_2.h Executable file
View File

@@ -0,0 +1,133 @@
// x86_2.h
#ifndef __BRANCH_X86_2_H
#define __BRANCH_X86_2_H
#include "../../../Common/MyCom.h"
#include "../RangeCoder/RangeCoderBit.h"
#include "../../ICoder.h"
// {23170F69-40C1-278B-0303-010100000100}
#define MyClass2_a(Name, id, subId, encodingId) \
DEFINE_GUID(CLSID_CCompressConvert ## Name, \
0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00);
#define MyClass_a(Name, id, subId) \
MyClass2_a(Name ## _Encoder, id, subId, 0x01) \
MyClass2_a(Name ## _Decoder, id, subId, 0x00)
MyClass_a(BCJ2_x86, 0x01, 0x1B)
const int kNumMoveBits = 5;
#ifndef EXTRACT_ONLY
class CBCJ2_x86_Encoder:
public ICompressCoder2,
public CMyUnknownImp
{
Byte *_buffer;
public:
CBCJ2_x86_Encoder(): _buffer(0) {};
~CBCJ2_x86_Encoder();
bool Create();
COutBuffer _mainStream;
COutBuffer _callStream;
COutBuffer _jumpStream;
NCompress::NRangeCoder::CEncoder _rangeEncoder;
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE8Encoder[256];
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE9Encoder;
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusJccEncoder;
HRESULT Flush();
void ReleaseStreams()
{
_mainStream.ReleaseStream();
_callStream.ReleaseStream();
_jumpStream.ReleaseStream();
_rangeEncoder.ReleaseStream();
}
class CCoderReleaser
{
CBCJ2_x86_Encoder *_coder;
public:
CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {}
~CCoderReleaser() { _coder->ReleaseStreams(); }
};
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
};
#endif
class CBCJ2_x86_Decoder:
public ICompressCoder2,
public CMyUnknownImp
{
public:
CInBuffer _mainInStream;
CInBuffer _callStream;
CInBuffer _jumpStream;
NCompress::NRangeCoder::CDecoder _rangeDecoder;
NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE8Decoder[256];
NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE9Decoder;
NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusJccDecoder;
COutBuffer _outStream;
void ReleaseStreams()
{
_mainInStream.ReleaseStream();
_callStream.ReleaseStream();
_jumpStream.ReleaseStream();
_rangeDecoder.ReleaseStream();
_outStream.ReleaseStream();
}
HRESULT Flush() { return _outStream.Flush(); }
class CCoderReleaser
{
CBCJ2_x86_Decoder *_coder;
public:
CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {}
~CCoderReleaser() { _coder->ReleaseStreams(); }
};
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
};
#endif

View File

@@ -0,0 +1,38 @@
// ByteSwap.cpp
#include "StdAfx.h"
#include "ByteSwap.h"
STDMETHODIMP CByteSwap2::Init() { return S_OK; }
STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)
{
const UInt32 kStep = 2;
UInt32 i;
for (i = 0; i + kStep <= size; i += kStep)
{
Byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
return i;
}
STDMETHODIMP CByteSwap4::Init() { return S_OK; }
STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)
{
const UInt32 kStep = 4;
UInt32 i;
for (i = 0; i + kStep <= size; i += kStep)
{
Byte b0 = data[i];
Byte b1 = data[i + 1];
data[i] = data[i + 3];
data[i + 1] = data[i + 2];
data[i + 2] = b1;
data[i + 3] = b0;
}
return i;
}

View File

@@ -0,0 +1,125 @@
# Microsoft Developer Studio Project File - Name="ByteSwap" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=ByteSwap - 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 "ByteSwap.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 "ByteSwap.mak" CFG="ByteSwap - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ByteSwap - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ByteSwap - 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)" == "ByteSwap - 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 "BYTESWAP_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BYTESWAP_EXPORTS" /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 0x419 /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\Swap.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "ByteSwap - 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 "BYTESWAP_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BYTESWAP_EXPORTS" /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 0x419 /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\Swap.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "ByteSwap - Win32 Release"
# Name "ByteSwap - 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 Source File
SOURCE=.\ByteSwap.cpp
# End Source File
# Begin Source File
SOURCE=.\ByteSwap.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: "ByteSwap"=.\ByteSwap.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,37 @@
// ByteSwap.h
#ifndef __BYTESWAP_H
#define __BYTESWAP_H
#include "../../ICoder.h"
#include "Common/MyCom.h"
// {23170F69-40C1-278B-0203-020000000000}
DEFINE_GUID(CLSID_CCompressConvertByteSwap2,
0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0203-040000000000}
DEFINE_GUID(CLSID_CCompressConvertByteSwap4,
0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00);
class CByteSwap2:
public ICompressFilter,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
};
class CByteSwap4:
public ICompressFilter,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
};
#endif

View File

@@ -0,0 +1,91 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "ByteSwap.h"
#include "../../ICoder.h"
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;
int correctInterface = (*iid == IID_ICompressFilter);
CMyComPtr<ICompressFilter> coder;
if (*clsid == CLSID_CCompressConvertByteSwap2)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressFilter *)new CByteSwap2();
}
else if (*clsid == CLSID_CCompressConvertByteSwap4)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressFilter *)new CByteSwap4();
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = coder.Detach();
COM_TRY_END
return S_OK;
}
struct CSwapMethodInfo
{
char ID[3];
const wchar_t *Name;
const GUID *clsid;
};
static CSwapMethodInfo g_Methods[] =
{
{ { 0x2, 0x03, 0x02 }, L"Swap2", &CLSID_CCompressConvertByteSwap2 },
{ { 0x2, 0x03, 0x04 }, L"Swap4", &CLSID_CCompressConvertByteSwap4 }
};
STDAPI GetNumberOfMethods(UINT32 *numMethods)
{
*numMethods = sizeof(g_Methods) / sizeof(g_Methods[1]);
return S_OK;
}
STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
if (index > sizeof(g_Methods) / sizeof(g_Methods[1]))
return E_INVALIDARG;
::VariantClear((tagVARIANT *)value);
const CSwapMethodInfo &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.Name)) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kDecoder:
case NMethodPropID::kEncoder:
{
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)method.clsid, 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,23 @@
PROG = Swap.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../
LIBS = $(LIBS) oleaut32.lib
SWAP_OBJS = \
$O\DllExports.obj \
SWAP_OPT_OBJS = \
$O\ByteSwap.obj \
OBJS = \
$O\StdAfx.obj \
$(SWAP_OBJS) \
$(SWAP_OPT_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(SWAP_OBJS): $(*B).cpp
$(COMPL)
$(SWAP_OPT_OBJS): $(*B).cpp
$(COMPL_O2)

View File

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

4
CPP/7zip/Compress/Codec.def Executable file
View File

@@ -0,0 +1,4 @@
EXPORTS
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE

149
CPP/7zip/Compress/Copy/Copy.dsp Executable file
View File

@@ -0,0 +1,149 @@
# Microsoft Developer Studio Project File - Name="Copy" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Copy - 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 "Copy.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 "Copy.mak" CFG="Copy - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Copy - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Copy - 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)" == "Copy - 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 "COPY_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COPY_EXPORTS" /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\Copy.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Copy - 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 "COPY_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COPY_EXPORTS" /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\Copy.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Copy - Win32 Release"
# Name "Copy - 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 "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Alloc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Alloc.h
# End Source File
# End Group
# Begin Group "7-Zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\CopyCoder.cpp
# End Source File
# Begin Source File
SOURCE=.\CopyCoder.h
# End Source File
# End Target
# End Project

29
CPP/7zip/Compress/Copy/Copy.dsw Executable file
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: "Copy"=".\Copy.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,52 @@
// Compress/CopyCoder.cpp
#include "StdAfx.h"
#include "CopyCoder.h"
#include "../../../Common/Alloc.h"
#include "../../Common/StreamUtils.h"
namespace NCompress {
static const UInt32 kBufferSize = 1 << 17;
CCopyCoder::~CCopyCoder()
{
::MidFree(_buffer);
}
STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (_buffer == 0)
{
_buffer = (Byte *)::MidAlloc(kBufferSize);
if (_buffer == 0)
return E_OUTOFMEMORY;
}
TotalSize = 0;
for (;;)
{
UInt32 realProcessedSize;
UInt32 size = kBufferSize;
if (outSize != 0)
if (size > *outSize - TotalSize)
size = (UInt32)(*outSize - TotalSize);
RINOK(inStream->Read(_buffer, size, &realProcessedSize));
if(realProcessedSize == 0)
break;
RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL));
TotalSize += realProcessedSize;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
}
}
return S_OK;
}
}

View File

@@ -0,0 +1,31 @@
// Compress/CopyCoder.h
#ifndef __COMPRESS_COPYCODER_H
#define __COMPRESS_COPYCODER_H
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
namespace NCompress {
class CCopyCoder:
public ICompressCoder,
public CMyUnknownImp
{
Byte *_buffer;
public:
UInt64 TotalSize;
CCopyCoder(): TotalSize(0) , _buffer(0) {};
~CCopyCoder();
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
};
}
#endif

View File

@@ -0,0 +1,70 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/ComTry.h"
#include "CopyCoder.h"
// {23170F69-40C1-278B-0000-000000000000}
DEFINE_GUID(CLSID_CCompressCopyCoder,
0x23170F69, 0x40C1, 0x278B, 0x00, 0x00, 0x00, 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_CCompressCopyCoder)
return CLASS_E_CLASSNOTAVAILABLE;
if (*iid != IID_ICompressCoder)
return E_NOINTERFACE;
CMyComPtr<ICompressCoder> coder = (ICompressCoder *)new NCompress::CCopyCoder();
*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[] = { 0x0 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
{
if ((value->bstrVal = ::SysAllocString(L"Copy")) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kDecoder:
case NMethodPropID::kEncoder:
{
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CCompressCopyCoder, 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

30
CPP/7zip/Compress/Copy/makefile Executable file
View File

@@ -0,0 +1,30 @@
PROG = Copy.dll
DEF_FILE = ../Codec.def
CFLAGS = $(CFLAGS) -I ../../../
LIBS = $(LIBS) oleaut32.lib
COPY_OBJS = \
$O\DllExports.obj \
$O\CopyCoder.obj \
COMMON_OBJS = \
$O\Alloc.obj \
7ZIP_COMMON_OBJS = \
$O\StreamUtils.obj \
OBJS = \
$O\StdAfx.obj \
$(COPY_OBJS) \
$(COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(COPY_OBJS): $(*B).cpp
$(COMPL)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)

View File

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

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")

View File

@@ -0,0 +1,88 @@
// Compress/HuffmanDecoder.h
#ifndef __COMPRESS_HUFFMANDECODER_H
#define __COMPRESS_HUFFMANDECODER_H
#include "../../../Common/Types.h"
namespace NCompress {
namespace NHuffman {
const int kNumTableBits = 9;
template <int kNumBitsMax, UInt32 m_NumSymbols>
class CDecoder
{
UInt32 m_Limits[kNumBitsMax + 1]; // m_Limits[i] = value limit for symbols with length = i
UInt32 m_Positions[kNumBitsMax + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UInt32 m_Symbols[m_NumSymbols];
Byte m_Lengths[1 << kNumTableBits]; // Table oh length for short codes.
public:
bool SetCodeLengths(const Byte *codeLengths)
{
int lenCounts[kNumBitsMax + 1], tmpPositions[kNumBitsMax + 1];
int i;
for(i = 1; i <= kNumBitsMax; i++)
lenCounts[i] = 0;
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
int len = codeLengths[symbol];
if (len > kNumBitsMax)
return false;
lenCounts[len]++;
m_Symbols[symbol] = 0xFFFFFFFF;
}
lenCounts[0] = 0;
m_Positions[0] = m_Limits[0] = 0;
UInt32 startPos = 0;
UInt32 index = 0;
const UInt32 kMaxValue = (1 << kNumBitsMax);
for (i = 1; i <= kNumBitsMax; i++)
{
startPos += lenCounts[i] << (kNumBitsMax - i);
if (startPos > kMaxValue)
return false;
m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos;
m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1];
tmpPositions[i] = m_Positions[i];
if(i <= kNumTableBits)
{
UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits));
for (; index < limit; index++)
m_Lengths[index] = (Byte)i;
}
}
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
int len = codeLengths[symbol];
if (len != 0)
m_Symbols[tmpPositions[len]++] = symbol;
}
return true;
}
template <class TBitDecoder>
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
int numBits;
UInt32 value = bitStream->GetValue(kNumBitsMax);
if (value < m_Limits[kNumTableBits])
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
else
for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
bitStream->MovePos(numBits);
UInt32 index = m_Positions[numBits] +
((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
if (index >= m_NumSymbols)
// throw CDecoderException(); // test it
return 0xFFFFFFFF;
return m_Symbols[index];
}
};
}}
#endif

View File

@@ -0,0 +1,6 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#endif

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

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

View 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

View 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];
}
}}}

View 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

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,17 @@
// LZOutWindow.cpp
#include "StdAfx.h"
#include "../../../Common/Alloc.h"
#include "LZOutWindow.h"
void CLZOutWindow::Init(bool solid)
{
if(!solid)
COutBuffer::Init();
#ifdef _NO_EXCEPTIONS
ErrorCode = S_OK;
#endif
}

View File

@@ -0,0 +1,56 @@
// LZOutWindow.h
#ifndef __LZ_OUT_WINDOW_H
#define __LZ_OUT_WINDOW_H
#include "../../IStream.h"
#include "../../Common/OutBuffer.h"
#ifndef _NO_EXCEPTIONS
typedef COutBufferException CLZOutWindowException;
#endif
class CLZOutWindow: public COutBuffer
{
public:
void Init(bool solid = false);
// distance >= 0, len > 0,
bool CopyBlock(UInt32 distance, UInt32 len)
{
UInt32 pos = _pos - distance - 1;
if (distance >= _pos)
{
if (!_overDict || distance >= _bufferSize)
return false;
pos += _bufferSize;
}
do
{
if (pos == _bufferSize)
pos = 0;
_buffer[_pos++] = _buffer[pos++];
if (_pos == _limitPos)
FlushWithCheck();
}
while(--len != 0);
return true;
}
void PutByte(Byte b)
{
_buffer[_pos++] = b;
if (_pos == _limitPos)
FlushWithCheck();
}
Byte GetByte(UInt32 distance) const
{
UInt32 pos = _pos - distance - 1;
if (pos >= _bufferSize)
pos += _bufferSize;
return _buffer[pos];
}
};
#endif

6
CPP/7zip/Compress/LZ/StdAfx.h Executable file
View File

@@ -0,0 +1,6 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#endif

View File

@@ -0,0 +1,109 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/ComTry.h"
#ifdef _WIN32
#include "../../../Common/Alloc.h"
#endif
#include "LZMAEncoder.h"
#include "LZMADecoder.h"
#ifdef CRC_GENERATE_TABLE
extern "C"
{
#include "../../../../C/7zCrc.h"
}
#endif
// {23170F69-40C1-278B-0301-010000000000}
DEFINE_GUID(CLSID_CLZMADecoder,
0x23170F69, 0x40C1, 0x278B, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
// {23170F69-40C1-278B-0301-010000000100}
DEFINE_GUID(CLSID_CLZMAEncoder,
0x23170F69, 0x40C1, 0x278B, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00);
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// NCompress::NRangeCoder::g_PriceTables.Init();
#ifdef CRC_GENERATE_TABLE
CrcGenerateTable();
#endif
#ifdef _WIN32
SetLargePageSize();
#endif
}
return TRUE;
}
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
// NCompress::NRangeCoder::g_PriceTables.Init();
// CCRC::InitTable();
COM_TRY_BEGIN
*outObject = 0;
int correctInterface = (*iid == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
if (*clsid == CLSID_CLZMADecoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NLZMA::CDecoder();
}
else if (*clsid == CLSID_CLZMAEncoder)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new NCompress::NLZMA::CEncoder();
}
else
return CLASS_E_CLASSNOTAVAILABLE;
*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[] = { 0x03, 0x01, 0x01 };
if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
case NMethodPropID::kName:
if ((value->bstrVal = ::SysAllocString(L"LZMA")) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kDecoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CLZMADecoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
case NMethodPropID::kEncoder:
if ((value->bstrVal = ::SysAllocStringByteLen(
(const char *)&CLSID_CLZMAEncoder, sizeof(GUID))) != 0)
value->vt = VT_BSTR;
return S_OK;
}
return S_OK;
}

478
CPP/7zip/Compress/LZMA/LZMA.dsp Executable file
View File

@@ -0,0 +1,478 @@
# Microsoft Developer Studio Project File - Name="LZMA" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=LZMA - 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 "LZMA.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 "LZMA.mak" CFG="LZMA - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "LZMA - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "LZMA - 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)" == "LZMA - 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 "LZMA_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMA_EXPORTS" /D "COMPRESS_MF_MT" /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 0x419 /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\LZMA.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none /debug
!ELSEIF "$(CFG)" == "LZMA - 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 "LZMA_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMA_EXPORTS" /D "COMPRESS_MF_MT" /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 0x419 /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\LZMA.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "LZMA - Win32 Release"
# Name "LZMA - 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 "7-zip 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\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.h
# End Source File
# End Group
# Begin Group "RangeCoder"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\RangeCoder\RangeCoder.h
# End Source File
# Begin Source File
SOURCE=..\RangeCoder\RangeCoderBit.cpp
# End Source File
# Begin Source File
SOURCE=..\RangeCoder\RangeCoderBit.h
# End Source File
# Begin Source File
SOURCE=..\RangeCoder\RangeCoderBitTree.h
# End Source File
# Begin Source File
SOURCE=..\RangeCoder\RangeCoderOpt.h
# End Source File
# End Group
# Begin Group "Interface"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\ICoder.h
# End Source File
# Begin Source File
SOURCE=..\MatchFinders\IMatchFinder.h
# End Source File
# Begin Source File
SOURCE=..\..\IStream.h
# End Source File
# End Group
# Begin Group "LZ"
# PROP Default_Filter ""
# Begin Group "BT"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree2.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree3.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeBase.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeD.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeD4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeDMain.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeMain.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeR.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeR4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeRMain.h
# End Source File
# End Group
# Begin Group "HC"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\HashChain\HC4.h
# End Source File
# Begin Source File
SOURCE=..\LZ\HashChain\HCMain.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\LZ\IMatchFinder.h
# End Source File
# Begin Source File
SOURCE=..\LZ\LZInWindow.h
# End Source File
# Begin Source File
SOURCE=..\LZ\LZOutWindow.cpp
# End Source File
# Begin Source File
SOURCE=..\LZ\LZOutWindow.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\AlignedBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\AlignedBuffer.h
# End Source File
# 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\ComTry.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\Defs.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Exception.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyCom.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyUnknown.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyWindows.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 ""
# Begin Source File
SOURCE=..\..\..\Windows\Handle.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Thread.h
# End Source File
# End Group
# Begin Group "C"
# PROP Default_Filter ""
# Begin Group "C_Lz"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c
!IF "$(CFG)" == "LZMA - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "LZMA - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c
!IF "$(CFG)" == "LZMA - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "LZMA - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\..\..\..\C\7zCrc.c
!IF "$(CFG)" == "LZMA - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "LZMA - 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\IStream.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Types.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\LZMA.h
# End Source File
# Begin Source File
SOURCE=.\LZMADecoder.cpp
!IF "$(CFG)" == "LZMA - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "LZMA - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\LZMADecoder.h
# End Source File
# Begin Source File
SOURCE=.\LZMAEncoder.cpp
!IF "$(CFG)" == "LZMA - Win32 Release"
# ADD CPP /O2 /FAs
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "LZMA - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\LZMAEncoder.h
# End Source File
# End Target
# End Project

29
CPP/7zip/Compress/LZMA/LZMA.dsw Executable file
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: "LZMA"=".\LZMA.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Some files were not shown because too many files have changed in this diff Show More