This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions

View File

@@ -10,20 +10,17 @@ namespace NCompress{
namespace NArj {
namespace NDecoder1 {
static const UINT32 kHistorySize = 26624;
static const UINT32 kMatchMaxLen = 256;
static const UINT32 kMatchMinLen = 3;
static const UInt32 kHistorySize = 26624;
static const UInt32 kMatchMaxLen = 256;
static const UInt32 kMatchMinLen = 3;
static const UINT32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;
static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;
CCoder::CCoder()
{}
void CCoder::make_table(int nchar, BYTE *bitlen, int tablebits,
UINT32 *table, int tablesize)
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;
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;
@@ -33,7 +30,7 @@ void CCoder::make_table(int nchar, BYTE *bitlen, int tablebits,
start[1] = 0;
for (i = 1; i <= 16; i++)
start[i + 1] = start[i] + (count[i] << (16 - i));
if (start[17] != (UINT32) (1 << 16))
if (start[17] != (UInt32) (1 << 16))
throw "Data error";
jutbits = 16 - tablebits;
@@ -49,7 +46,7 @@ void CCoder::make_table(int nchar, BYTE *bitlen, int tablebits,
}
i = start[tablebits + 1] >> jutbits;
if (i != (UINT32) (1 << 16))
if (i != (UInt32) (1 << 16))
{
k = 1 << tablebits;
while (i != k)
@@ -66,7 +63,7 @@ void CCoder::make_table(int nchar, BYTE *bitlen, int tablebits,
nextcode = k + weight[len];
if ((int)len <= tablebits)
{
if (nextcode > (UINT32)tablesize)
if (nextcode > (UInt32)tablesize)
throw "Data error";
for (i = start[len]; i < nextcode; i++)
table[i] = ch;
@@ -97,10 +94,10 @@ void CCoder::make_table(int nchar, BYTE *bitlen, int tablebits,
void CCoder::read_pt_len(int nn, int nbit, int i_special)
{
UINT32 n = m_InBitStream.ReadBits(nbit);
UInt32 n = m_InBitStream.ReadBits(nbit);
if (n == 0)
{
UINT32 c = m_InBitStream.ReadBits(nbit);
UInt32 c = m_InBitStream.ReadBits(nbit);
int i;
for (i = 0; i < nn; i++)
pt_len[i] = 0;
@@ -109,14 +106,14 @@ void CCoder::read_pt_len(int nn, int nbit, int i_special)
}
else
{
UINT32 i = 0;
UInt32 i = 0;
while (i < n)
{
UINT32 bitBuf = m_InBitStream.GetValue(16);
UInt32 bitBuf = m_InBitStream.GetValue(16);
int c = bitBuf >> 13;
if (c == 7)
{
UINT32 mask = 1 << (12);
UInt32 mask = 1 << (12);
while (mask & bitBuf)
{
mask >>= 1;
@@ -124,24 +121,24 @@ void CCoder::read_pt_len(int nn, int nbit, int i_special)
}
}
m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3));
pt_len[i++] = (BYTE)c;
if (i == (UINT32)i_special)
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)
while (i < (UInt32)nn)
pt_len[i++] = 0;
make_table(nn, pt_len, 8, pt_table, PTABLESIZE);
MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE);
}
}
void CCoder::read_c_len()
{
int i, c, n;
UINT32 mask;
UInt32 mask;
n = m_InBitStream.ReadBits(CBIT);
if (n == 0)
@@ -157,7 +154,7 @@ void CCoder::read_c_len()
i = 0;
while (i < n)
{
UINT32 bitBuf = m_InBitStream.GetValue(16);
UInt32 bitBuf = m_InBitStream.GetValue(16);
c = pt_table[bitBuf >> (8)];
if (c >= NT)
{
@@ -184,18 +181,18 @@ void CCoder::read_c_len()
c_len[i++] = 0;
}
else
c_len[i++] = (BYTE)(c - 2);
c_len[i++] = (Byte)(c - 2);
}
while (i < NC)
c_len[i++] = 0;
make_table(NC, c_len, 12, c_table, CTABLESIZE);
MakeTable(NC, c_len, 12, c_table, CTABLESIZE);
}
}
UINT32 CCoder::decode_c()
UInt32 CCoder::decode_c()
{
UINT32 j, mask;
UINT32 bitbuf = m_InBitStream.GetValue(16);
UInt32 j, mask;
UInt32 bitbuf = m_InBitStream.GetValue(16);
j = c_table[bitbuf >> 4];
if (j >= NC)
{
@@ -213,10 +210,10 @@ UINT32 CCoder::decode_c()
return j;
}
UINT32 CCoder::decode_p()
UInt32 CCoder::decode_p()
{
UINT32 j, mask;
UINT32 bitbuf = m_InBitStream.GetValue(16);
UInt32 j, mask;
UInt32 bitbuf = m_InBitStream.GetValue(16);
j = pt_table[bitbuf >> (8)];
if (j >= NP)
{
@@ -241,9 +238,17 @@ UINT32 CCoder::decode_p()
STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
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++)
{
@@ -253,20 +258,16 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
c_table[i] = 0;
}
if (outSize == NULL)
return E_INVALIDARG;
if (!m_OutWindowStream.IsCreated())
{
try { m_OutWindowStream.Create(kHistorySize); }
catch(...) { return E_OUTOFMEMORY; }
}
UINT64 pos = 0;
m_OutWindowStream.Init(outStream, false);
m_InBitStream.Init(inStream);
UInt64 pos = 0;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(false);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
UINT32 blockSize = 0;
UInt32 blockSize = 0;
while(pos < *outSize)
{
@@ -274,7 +275,7 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
{
if (progress != NULL)
{
UINT64 packSize = m_InBitStream.GetProcessedSize();
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
blockSize = m_InBitStream.ReadBits(16);
@@ -284,28 +285,29 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
}
blockSize--;
UINT32 number = decode_c();
UInt32 number = decode_c();
if (number < 256)
{
m_OutWindowStream.PutOneByte(number);
m_OutWindowStream.PutByte(number);
pos++;
continue;
}
else
{
UINT32 len = number - 256 + kMatchMinLen;
UINT32 distance = decode_p();
UInt32 len = number - 256 + kMatchMinLen;
UInt32 distance = decode_p();
if (distance >= pos)
throw "data error";
m_OutWindowStream.CopyBackBlock(distance, len);
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,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress);}

View File

@@ -1,11 +1,9 @@
// Arj/Decoder1.h
#pragma once
#ifndef __COMPRESS_ARJ_DECODER1_H
#define __COMPRESS_ARJ_DECODER1_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
@@ -28,7 +26,7 @@ namespace NDecoder1 {
#define MAXDICBIT 16
#define MATCHBIT 8
#define MAXMATCH 256
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
#define NC (0xFF + MAXMATCH + 2 - THRESHOLD)
#define NP (MAXDICBIT + 1)
#define CBIT 9
#define NT (CODE_BIT + 3)
@@ -52,55 +50,53 @@ class CCoder :
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 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];
UInt32 c_table[CTABLESIZE];
UInt32 pt_table[PTABLESIZE];
/*
void CCoder::ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
}
*/
class CCoderReleaser
{
CCoder *m_Coder;
public:
CCoderReleaser(CCoder *aCoder): m_Coder(aCoder) {}
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
m_Coder->m_OutWindowStream.Flush();
// m_Coder->ReleaseStreams();
if (NeedFlush)
m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
void make_table(int nchar, BYTE *bitlen, int tablebits,
UINT32 *table, int tablesize);
void MakeTable(int nchar, Byte *bitlen, int tablebits,
UInt32 *table, int tablesize);
void read_c_len();
void read_pt_len(int nn, int nbit, int i_special);
UINT32 decode_c();
UINT32 decode_p();
UInt32 decode_c();
UInt32 decode_p();
public:
CCoder();
MY_UNKNOWN_IMP
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
};

View File

@@ -4,43 +4,40 @@
#include "Decoder2.h"
#include "Windows/Defs.h"
namespace NCompress{
namespace NArj {
namespace NDecoder2 {
static const UINT32 kHistorySize = 26624;
static const UINT32 kMatchMaxLen = 256;
static const UINT32 kMatchMinLen = 3;
CCoder::CCoder()
{}
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,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (outSize == NULL)
return E_INVALIDARG;
if (!m_OutWindowStream.IsCreated())
{
try { m_OutWindowStream.Create(kHistorySize); }
catch(...) { return E_OUTOFMEMORY; }
}
UINT64 pos = 0;
m_OutWindowStream.Init(outStream, false);
m_InBitStream.Init(inStream);
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;
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)
@@ -52,18 +49,18 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
len += m_InBitStream.ReadBits(width);
if (len == 0)
{
m_OutWindowStream.PutOneByte(m_InBitStream.ReadBits(8));
m_OutWindowStream.PutByte(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;
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)
@@ -75,15 +72,16 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
distance += m_InBitStream.ReadBits(width);
if (distance >= pos)
throw "data error";
m_OutWindowStream.CopyBackBlock(distance, len);
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,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress);}

View File

@@ -1,11 +1,9 @@
// Arj/Decoder2.h
#pragma once
#ifndef __COMPRESS_ARJ_DECODER2_H
#define __COMPRESS_ARJ_DECODER2_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
@@ -28,38 +26,36 @@ class CCoder :
CLZOutWindow m_OutWindowStream;
NStream::NMSBF::CDecoder<CInBuffer> m_InBitStream;
/*
void CCoder::ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
m_InBitStream.ReleaseStream();
}
*/
class CCoderReleaser
{
CCoder *m_Coder;
public:
CCoderReleaser(CCoder *aCoder): m_Coder(aCoder) {}
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
m_Coder->m_OutWindowStream.Flush();
// m_Coder->ReleaseStreams();
if (NeedFlush)
m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
public:
CCoder();
MY_UNKNOWN_IMP
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
};

8
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

289
7zip/Compress/BWT/BlockSort.cpp Executable file
View File

@@ -0,0 +1,289 @@
// BlockSort.cpp
#include "StdAfx.h"
#include "BlockSort.h"
#include "Common/Alloc.h"
namespace NCompress {
static const int kNumHashBytes = 2;
static const UInt32 kNumHashValues = 1 << (kNumHashBytes * 8);
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;
bool CBlockSorter::Create(UInt32 blockSizeMax)
{
if (Indices != 0 && blockSizeMax == BlockSizeMax)
return true;
Free();
BlockSizeMax = blockSizeMax;
Indices = (UInt32 *)::BigAlloc((blockSizeMax * 2 +
((blockSizeMax + kFlagsMask) >> kNumFlagsBits) + kNumHashValues) * sizeof(UInt32));
return (Indices != 0);
}
void CBlockSorter::Free()
{
::BigFree(Indices);
Indices = 0;
}
// SortGroup - is recursive Radix-Range-Sort function with Bubble-Sort optimization
// It uses both mask & maskSize (Range-Sort), since it can change values (Groups)
// during sorting
// returns: 0 - if there are groups, 1 - no more groups
UInt32 CBlockSorter::SortGroup(UInt32 groupOffset, UInt32 groupSize, UInt32 mask, UInt32 maskSize)
{
if (groupSize <= 2)
{
if (groupSize <= 1)
return 0;
UInt32 *ind2 = Indices + groupOffset;
UInt32 stringPos = ind2[0] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
UInt32 group = Groups[stringPos];
stringPos = ind2[1] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (group == Groups[stringPos])
return 1;
if (group > Groups[stringPos])
{
UInt32 temp = ind2[0];
ind2[0] = ind2[1];
ind2[1] = temp;
}
Flags[groupOffset >> kNumFlagsBits] &= ~(1 << (groupOffset & kFlagsMask));
Groups[ind2[1]] = groupOffset + 1;
return 0;
}
// Check that all strings are in one group (cannot sort)
UInt32 *ind2 = Indices + groupOffset;
{
UInt32 stringPos = ind2[0] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
UInt32 group = Groups[stringPos];
UInt32 j;
for (j = 1; j < groupSize; j++)
{
stringPos = ind2[j] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (Groups[stringPos] != group)
break;
}
if (j == groupSize)
return 1;
}
if (groupSize <= 15)
{
// Bubble-Sort
UInt32 lastChange = groupSize;
do
{
UInt32 stringPos = ind2[0] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
UInt32 group = Groups[stringPos];
UInt32 sortSize = lastChange;
lastChange = 0;
for (UInt32 j = 1; j < sortSize; j++)
{
stringPos = ind2[j] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (Groups[stringPos] < group)
{
UInt32 temp = ind2[j];
ind2[j] = ind2[j - 1];
ind2[j - 1] = temp;
lastChange = j;
}
else
group = Groups[stringPos];
}
}
while(lastChange > 1);
// Write Flags
UInt32 stringPos = ind2[0] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
UInt32 group = Groups[stringPos];
UInt32 j;
for (j = 1; j < groupSize; j++)
{
stringPos = ind2[j] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (Groups[stringPos] != group)
{
group = Groups[stringPos];
UInt32 t = groupOffset + j - 1;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
}
}
// Write new Groups values and Check that there are groups
UInt32 thereAreGroups = 0;
for (j = 0; j < groupSize; j++)
{
UInt32 group = groupOffset + j;
while (true)
{
Groups[ind2[j]] = group;
if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0)
break;
j++;
thereAreGroups = 1;
}
}
return thereAreGroups;
}
// Radix-Range Sort
UInt32 i;
do
{
if (maskSize == 0)
return 1;
UInt32 j = groupSize;
i = 0;
do
{
UInt32 stringPos = ind2[i] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (Groups[stringPos] >= mask)
{
for (j--; j > i; j--)
{
stringPos = ind2[j] + NumSortedBytes;
if (stringPos >= BlockSize)
stringPos -= BlockSize;
if (Groups[stringPos] < mask)
{
UInt32 temp = ind2[i];
ind2[i] = ind2[j];
ind2[j] = temp;
break;
}
}
if (i >= j)
break;
}
}
while(++i < j);
maskSize >>= 1;
if (i == 0)
mask += maskSize;
else if (i == groupSize)
mask -= maskSize;
else
break;
}
while(true);
UInt32 t = (groupOffset + i - 1);
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
for (UInt32 j = i; j < groupSize; j++)
Groups[ind2[j]] = groupOffset + i;
UInt32 res = SortGroup(groupOffset, i, mask - maskSize, maskSize);
return res | SortGroup(groupOffset + i, groupSize - i, mask + maskSize, maskSize);
}
UInt32 CBlockSorter::Sort(const Byte *data, UInt32 blockSize)
{
BlockSize = blockSize;
UInt32 *counters = Indices + blockSize;
Groups = counters + kNumHashValues;
Flags = Groups + 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 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;
for (i = 0; i < numWords; i++)
Flags[i] = kAllFlags;
}
UInt32 sum = 0;
for (i = 0; i < kNumHashValues; i++)
{
UInt32 groupSize = counters[i];
if (groupSize > 0)
{
UInt32 t = sum + groupSize - 1;
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
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;
}
UInt32 mask;
for (mask = 2; mask < blockSize; mask <<= 1);
mask >>= 1;
for (NumSortedBytes = kNumHashBytes; true; NumSortedBytes <<= 1)
{
UInt32 newLimit = 0;
for (i = 0; i < blockSize;)
{
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++;
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(i, groupSize, mask, mask) != 0)
newLimit = i + groupSize;
i += groupSize;
}
if (newLimit == 0)
break;
}
return Groups[0];
}
}

29
7zip/Compress/BWT/BlockSort.h Executable file
View File

@@ -0,0 +1,29 @@
// BlockSort.h
#ifndef __BLOCKSORT_H
#define __BLOCKSORT_H
#include "Common/Types.h"
namespace NCompress {
class CBlockSorter
{
UInt32 *Groups;
UInt32 *Flags;
UInt32 BlockSize;
UInt32 NumSortedBytes;
UInt32 BlockSizeMax;
UInt32 SortGroup(UInt32 groupOffset, UInt32 groupSize, UInt32 mask, UInt32 maskSize);
public:
UInt32 *Indices;
CBlockSorter(): Indices(0) {}
~CBlockSorter() { Free(); }
bool Create(UInt32 blockSizeMax);
void Free();
UInt32 Sort(const Byte *data, UInt32 blockSize);
};
}
#endif

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

@@ -0,0 +1,140 @@
// 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 size) {};
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;
}
};
/*
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
7zip/Compress/BWT/StdAfx.h Executable file
View File

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

View File

@@ -115,130 +115,6 @@ SOURCE=.\StdAfx.cpp
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Origianl"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Original\blocksort.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=.\Original\bzlib.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=.\Original\bzlib.h
# End Source File
# Begin Source File
SOURCE=.\Original\bzlib_private.h
# End Source File
# Begin Source File
SOURCE=.\Original\compress.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=.\Original\crctable.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=.\Original\decompress.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=.\Original\huffman.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=.\Original\randtable.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
# End Group
# Begin Group "Common"
@@ -246,6 +122,14 @@ SOURCE=.\Original\randtable.c
# 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
@@ -253,6 +137,94 @@ SOURCE=..\..\..\Common\NewHandler.cpp
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=..\Huffman\HuffmanEncoder.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=..\Huffman\HuffmanEncoder.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 Source File
SOURCE=.\BZip2CRC.cpp
# End Source File
# Begin Source File
SOURCE=.\BZip2CRC.h
# End Source File
# Begin Source File
SOURCE=.\BZip2Decoder.cpp
@@ -289,9 +261,5 @@ SOURCE=.\BZip2Encoder.cpp
SOURCE=.\BZip2Encoder.h
# End Source File
# Begin Source File
SOURCE=.\BZip2Error.cpp
# End Source File
# End Target
# End Project

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_CRCTableInit;

30
7zip/Compress/BZip2/BZip2CRC.h Executable file
View File

@@ -0,0 +1,30 @@
// 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); }
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

@@ -4,122 +4,402 @@
#include "BZip2Decoder.h"
#include "Windows/Defs.h"
#include "Original/bzlib.h"
#include "../../../Common/Alloc.h"
#include "../../../Common/Defs.h"
#include "../BWT/Mtf8.h"
#include "BZip2CRC.h"
namespace NCompress {
namespace NBZip2 {
static const UINT32 kBufferSize = (1 << 20);
static const UInt32 kBufferSize = (1 << 17);
CDecoder::CDecoder()
{
m_InBuffer = new BYTE[kBufferSize];
m_OutBuffer = new BYTE[kBufferSize];
}
CDecoder::~CDecoder()
{
delete []m_OutBuffer;
delete []m_InBuffer;
}
struct CBZip2Decompressor: public bz_stream
{
// bz_stream m_Object;
public:
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; }
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
};
class CBZip2DecompressorReleaser
CState::~CState()
{
CBZip2Decompressor *m_Decompressor;
public:
CBZip2DecompressorReleaser(CBZip2Decompressor *aDecompressor): m_Decompressor(aDecompressor) {}
void Diable() { m_Decompressor = NULL; }
~CBZip2DecompressorReleaser() { if (m_Decompressor != NULL) m_Decompressor->End(); }
};
::BigFree(tt);
}
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress)
bool CState::Alloc()
{
CBZip2Decompressor bzStream;
bzStream.bzalloc = NULL;
bzStream.bzfree = NULL;
bzStream.opaque = NULL;
if (tt == 0)
tt = (UInt32 *)BigAlloc(kBlockSizeMax * sizeof(UInt32));
return (tt != 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; }
int result = bzStream.Init(0, 0);
switch(result)
UInt32 CDecoder::ReadCRC()
{
UInt32 crc = 0;
for (int i = 0; i < 4; i++)
{
case BZ_OK:
break;
case BZ_MEM_ERROR:
return E_OUTOFMEMORY;
default:
return E_FAIL;
crc <<= 8;
crc |= ReadByte();
}
CBZip2DecompressorReleaser releaser(&bzStream);
bzStream.avail_in = 0;
while (true)
return crc;
}
HRESULT CDecoder::ReadBlock(UInt32 blockSizeMax, CState &state)
{
state.BlockRandomised = ReadBit();
state.OrigPtr = ReadBits(kNumOrigBits);
// in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?
if (state.OrigPtr >= blockSizeMax)
return S_FALSE;
CMtf8Decoder mtf;
int numInUse = 0;
{
if (bzStream.avail_in == 0)
{
bzStream.next_in = (char *)m_InBuffer;
UINT32 processedSize;
RINOK(inStream->Read(m_InBuffer, kBufferSize, &processedSize));
bzStream.avail_in = processedSize;
}
bool inUse16[16];
int i;
for (i = 0; i < 16; i++)
inUse16[i] = ReadBit();
for (i = 0; i < 256; i++)
if (inUse16[i >> 4])
if (ReadBit())
mtf.Buffer[numInUse++] = (Byte)i;
if (numInUse == 0)
return S_FALSE;
mtf.Init(numInUse);
}
int alphaSize = numInUse + 2;
bzStream.next_out = (char *)m_OutBuffer;
bzStream.avail_out = kBufferSize;
result = bzStream.Decompress();
UINT32 numBytesToWrite = kBufferSize - bzStream.avail_out;
if (numBytesToWrite > 0)
{
UINT32 processedSize;
RINOK(outStream->Write(m_OutBuffer, numBytesToWrite, &processedSize));
if (numBytesToWrite != processedSize)
return E_FAIL;
}
int numTables = ReadBits(kNumTablesBits);
if (numTables < kNumTablesMin || numTables > kNumTablesMax)
return S_FALSE;
UInt32 numSelectors = ReadBits(kNumSelectorsBits);
if (numSelectors < 1 || numSelectors > kNumSelectorsMax)
return S_FALSE;
if (result == BZ_STREAM_END)
break;
switch(result)
{
Byte mtfPos[kNumTablesMax];
int t = 0;
do
mtfPos[t] = (Byte)t;
while(++t < numTables);
UInt32 i = 0;
do
{
case BZ_DATA_ERROR:
case BZ_DATA_ERROR_MAGIC:
return S_FALSE;
case BZ_OK:
int j = 0;
while (ReadBit())
if (++j >= numTables)
return S_FALSE;
Byte tmp = mtfPos[j];
for (;j > 0; j--)
mtfPos[j] = mtfPos[j - 1];
state.m_Selectors[i] = mtfPos[0] = tmp;
}
while(++i < numSelectors);
}
int t = 0;
do
{
Byte lens[kMaxAlphaSize];
int len = (int)ReadBits(kNumLevelsBits);
int i;
for (i = 0; i < alphaSize; i++)
{
while (true)
{
if (len < 1 || len > kMaxHuffmanLen)
return S_FALSE;
if (!ReadBit())
break;
if (ReadBit())
len--;
else
len++;
}
lens[i] = (Byte)len;
}
for (; i < kMaxAlphaSize; i++)
lens[i] = 0;
m_HuffmanDecoders[t].SetCodeLengths(lens);
}
while(++t < numTables);
{
for (int i = 0; i < 256; i++)
state.CharCounters[i] = 0;
}
UInt32 blockSize = 0;
{
UInt32 groupIndex = 0;
UInt32 groupSize = 0;
CHuffmanDecoder *huffmanDecoder = 0;
int runPower = 0;
UInt32 runCounter = 0;
while (true)
{
if (groupSize == 0)
{
if (groupIndex >= numSelectors)
return S_FALSE;
groupSize = kGroupSize;
huffmanDecoder = &m_HuffmanDecoders[state.m_Selectors[groupIndex++]];
}
groupSize--; \
int nextSym = (int)huffmanDecoder->DecodeSymbol(&m_InStream);
if (nextSym < 2)
{
runCounter += ((UInt32)(nextSym + 1) << runPower++);
if (blockSizeMax - blockSize < runCounter)
return S_FALSE;
continue;
}
if (runCounter != 0)
{
Byte b = mtf.GetHead();
state.CharCounters[b] += runCounter;
do
state.tt[blockSize++] = (UInt32)b;
while(--runCounter != 0);
runPower = 0;
}
if (nextSym > numInUse)
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));
Byte b = mtf.GetAndMove(nextSym - 1);
if (blockSize >= blockSizeMax)
return S_FALSE;
state.CharCounters[b]++;
state.tt[blockSize++] = (UInt32)b;
}
}
// result = bzStream.End();
if (state.OrigPtr >= blockSize)
return S_FALSE;
state.BlockSize = blockSize;
return S_OK;
}
HRESULT CState::DecodeBlock(COutBuffer &m_OutStream)
{
UInt32 *charCounters = this->CharCounters;
{
UInt32 sum = 0;
for (UInt32 i = 0; i < 256; i++)
{
sum += charCounters[i];
charCounters[i] = sum - charCounters[i];
}
}
// Compute the T^(-1) vector
UInt32 blockSize = this->BlockSize;
UInt32 i = 0;
do
tt[charCounters[tt[i] & 0xFF]++] |= (i << 8);
while(++i < blockSize);
// Decode
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];
Byte prevByte = (Byte)(tPos & 0xFF);
do
{
Byte b = (Byte)(tPos & 0xFF);
tPos = tt[tPos >> 8];
if (BlockRandomised)
{
if (randToGo == 0)
{
b ^= 1;
randToGo = kRandNums[randIndex++];
randIndex &= 0x1FF;
}
randToGo--;
}
if (numReps == kRleModeRepSize)
{
for (; b > 0; b--)
{
crc.UpdateByte(prevByte);
m_OutStream.WriteByte(prevByte);
}
numReps = 0;
continue;
}
if (prevByte == b)
numReps++;
else
{
numReps = 1;
prevByte = b;
}
crc.UpdateByte(b);
m_OutStream.WriteByte(b);
}
while(--blockSize != 0);
return (StoredCRC == crc.GetDigest()) ? S_OK : S_FALSE;
}
HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress)
{
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;
if (!m_State.Alloc())
return E_OUTOFMEMORY;
CBZip2CombinedCRC computedCombinedCRC;
while (true)
{
if (progress)
{
UInt64 packSize = m_InStream.GetProcessedSize();
UInt64 unpackSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
}
for (i = 0; i < 6; i++)
s[i] = ReadByte();
UInt32 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;
return (crc == computedCombinedCRC.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;
m_State.StoredCRC = crc;
computedCombinedCRC.Update(crc);
RINOK(ReadBlock(dicSize, m_State));
RINOK(m_State.DecodeBlock(m_OutStream));
}
}
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,
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_InStream.GetProcessedSize();
return S_OK;
}
}}

View File

@@ -1,39 +1,88 @@
// Compress/BZip2/Decoder.h
#pragma once
#ifndef __COMPRESS_BZIP2_DECODER_H
#define __COMPRESS_BZIP2_DECODER_H
#include "../../ICoder.h"
// #include "../../Interface/CompressInterface.h"
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../Common/MSBFDecoder.h"
#include "../../Common/InBuffer.h"
#include "../../Common/OutBuffer.h"
#include "../Huffman/HuffmanDecoder.h"
#include "BZip2Const.h"
namespace NCompress {
namespace NBZip2 {
typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder;
struct CState
{
UInt32 *tt;
bool BlockRandomised;
UInt32 OrigPtr;
UInt32 BlockSize;
UInt32 CharCounters[256];
Byte m_Selectors[kNumSelectorsMax];
UInt32 StoredCRC;
CState(): tt(0) {}
~CState();
bool Alloc();
HRESULT DecodeBlock(COutBuffer &m_OutStream);
};
class CDecoder :
public ICompressCoder,
public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
BYTE *m_InBuffer;
BYTE *m_OutBuffer;
NStream::NMSBF::CDecoder<CInBuffer> m_InStream;
COutBuffer m_OutStream;
CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];
CState m_State;
UInt32 ReadBits(int numBits);
Byte ReadByte();
bool ReadBit();
UInt32 ReadCRC();
HRESULT ReadBlock(UInt32 blockSizeMax, CState &state);
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:
CDecoder();
~CDecoder();
MY_UNKNOWN_IMP
HRESULT Flush();
// void (ReleaseStreams)();
STDMETHOD(CodeReal)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress);
HRESULT Flush() { return m_OutStream.Flush(); }
void ReleaseStreams()
{
m_InStream.ReleaseStream();
m_OutStream.ReleaseStream();
}
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};
}}

View File

@@ -2,119 +2,632 @@
#include "StdAfx.h"
#include "Windows/Defs.h"
#include "BZip2Encoder.h"
#include "Original/bzlib.h"
#include "../../../Common/Alloc.h"
#include "../BWT/Mtf8.h"
#include "BZip2CRC.h"
namespace NCompress {
namespace NBZip2 {
static const UINT32 kBufferSize = (1 << 20);
static const UInt32 kBufferSize = (1 << 17);
static const int kNumHuffPasses = 4;
CEncoder::CEncoder()
{
m_InBuffer = new BYTE[kBufferSize];
m_OutBuffer = new BYTE[kBufferSize];
}
CEncoder::CEncoder():
m_Block(0),
m_NeedHuffmanCreate(true),
m_NumPasses(1),
m_OptimizeNumTables(false),
m_BlockSizeMult(kBlockSizeMultMax)
{}
CEncoder::~CEncoder()
{
delete []m_OutBuffer;
delete []m_InBuffer;
::BigFree(m_Block);
}
struct CBZip2Compressor: public bz_stream
UInt32 CEncoder::ReadRleBlock(Byte *buffer)
{
public:
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; }
};
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++] = numReps - kRleModeRepSize;
buffer[i++] = b;
numReps = 1;
prevByte = b;
continue;
}
numReps++;
if (numReps <= kRleModeRepSize)
buffer[i++] = b;
else if (numReps == kRleModeRepSize + 255)
{
buffer[i++] = numReps - kRleModeRepSize;
numReps = 0;
}
}
// it's to support original BZip2 decoder
if (numReps >= kRleModeRepSize)
buffer[i++] = numReps - kRleModeRepSize;
}
return i;
}
class CBZip2CompressorReleaser
void CEncoder::WriteBits2(UInt32 value, UInt32 numBits)
{ m_OutStreamCurrent->WriteBits(value, numBits); }
void CEncoder::WriteByte2(Byte b) { WriteBits2(b , 8); }
void CEncoder::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); }
void CEncoder::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 CEncoder::EncodeBlock(Byte *block, UInt32 blockSize)
{
CBZip2Compressor *m_Compressor;
public:
CBZip2CompressorReleaser(CBZip2Compressor *compressor): m_Compressor(compressor) {}
void Disable() { m_Compressor = NULL; }
~CBZip2CompressorReleaser() { if (m_Compressor != NULL) m_Compressor->End(); }
};
WriteBit2(false); // Randomised = false
{
UInt32 origPtr = m_BlockSorter.Sort(block, 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;
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
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;
do
{
UInt32 index = m_BlockSorter.Indices[i];
if (index == 0)
index = blockSize - 1;
else
index--;
int pos = mtf.FindAndMove(block[index]);
if (pos == 0)
rleSize++;
else
{
while (rleSize != 0)
{
rleSize--;
mtfs[mtfArraySize++] = (rleSize & 1);
symbolCounts[rleSize & 1]++;
rleSize >>= 1;
}
if (pos >= 0xFE)
{
mtfs[mtfArraySize++] = 0xFF;
mtfs[mtfArraySize++] = pos - 0xFE;
}
else
mtfs[mtfArraySize++] = pos + 1;
symbolCounts[pos + 1]++;
}
}
while (++i < blockSize);
while (rleSize != 0)
{
rleSize--;
mtfs[mtfArraySize++] = (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();
UInt32 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];
NCompression::NHuffman::CEncoder &huffEncoder = m_HuffEncoders[t - 1];
int i = 0;
do
huffEncoder.m_Items[i].Len = (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
m_HuffEncoders[t].StartNewBlock();
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
{
NCompression::NHuffman::CItem *items = m_HuffEncoders[t].m_Items;
UInt32 price = 0;
int j = 0;
do
price += items[symbols[j]].Len;
while (++j < i);
if (price < bestPrice)
{
m_Selectors[g] = (Byte)t;
bestPrice = price;
}
}
while(++t < numTables);
NCompression::NHuffman::CEncoder &huffEncoder = m_HuffEncoders[m_Selectors[g++]];
int j = 0;
do
huffEncoder.AddSymbol(symbols[j]);
while (++j < i);
}
while (mtfPos < mtfArraySize);
}
int t = 0;
do
{
NCompression::NHuffman::CEncoder &huffEncoder = m_HuffEncoders[t];
int i = 0;
do
if (huffEncoder.m_Items[i].Freq == 0)
huffEncoder.m_Items[i].Freq = 1;
while(++i < alphaSize);
Byte levels[kMaxAlphaSize];
huffEncoder.BuildTree(levels);
}
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
{
NCompression::NHuffman::CItem *items = m_HuffEncoders[t].m_Items;
UInt32 len = items[0].Len;
WriteBits2(len, kNumLevelsBits);
int i = 0;
do
{
UInt32 level = items[i].Len;
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;
NCompression::NHuffman::CEncoder *huffEncoder = 0;
UInt32 mtfPos = 0;
do
{
UInt32 symbol = mtfs[mtfPos++];
if (symbol >= 0xFF)
symbol += mtfs[mtfPos++];
if (groupSize == 0)
{
groupSize = kGroupSize;
huffEncoder = &m_HuffEncoders[m_Selectors[groupIndex++]];
}
groupSize--; \
huffEncoder->CodeOneValue(m_OutStreamCurrent, 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 CEncoder::EncodeBlockWithHeaders(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 CEncoder::EncodeBlock2(CBZip2CombinedCRC &combinedCRC,
Byte *block, UInt32 blockSize, UInt32 numPasses)
{
bool needCompare = false;
CBZip2CombinedCRC specCombinedCRC = combinedCRC;
UInt32 startBytePos = m_OutStreamCurrent->GetBytePos();
UInt32 startPos = m_OutStreamCurrent->GetPos();
UInt32 startCurByte = m_OutStreamCurrent->GetCurByte();
UInt32 endCurByte;
UInt32 endPos;
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(specCombinedCRC, block, blockSize0, numPasses - 1);
EncodeBlock2(specCombinedCRC, 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();
combinedCRC.Update(crcVal);
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);
}
else
{
m_OutStreamCurrent->SetPos(endPos);
m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte);
combinedCRC = specCombinedCRC;
}
}
}
void CEncoder::EncodeBlock3(CBZip2CombinedCRC &combinedCRC, UInt32 blockSize)
{
CMsbfEncoderTemp outStreamTemp;
outStreamTemp.SetStream(m_TempArray);
outStreamTemp.Init();
m_OutStreamCurrent = &outStreamTemp;
EncodeBlock2(combinedCRC, m_Block, blockSize, m_NumPasses);
UInt32 size = outStreamTemp.GetPos();
UInt32 bytesSize = (size / 8);
for (UInt32 i = 0; i < bytesSize; i++)
m_OutStream.WriteBits(m_TempArray[i], 8);
WriteBits(outStreamTemp.GetCurByte(), (size & 7));
}
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
CBZip2Compressor bzStream;
bzStream.bzalloc = NULL;
bzStream.bzfree = NULL;
bzStream.opaque = NULL;
int result = bzStream.Init(9, 0, 0);
switch(result)
if (!m_BlockSorter.Create(kBlockSizeMax))
return E_OUTOFMEMORY;
if (m_Block == 0)
{
case BZ_OK:
break;
case BZ_MEM_ERROR:
m_Block = (Byte *)BigAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10));
if (m_Block == 0)
return E_OUTOFMEMORY;
default:
return E_FAIL;
m_MtfArray = m_Block + kBlockSizeMax;
m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2;
}
CBZip2CompressorReleaser releaser(&bzStream);
bzStream.avail_in = 0;
if (!m_InStream.Create(kBufferSize))
return E_OUTOFMEMORY;
if (!m_OutStream.Create(kBufferSize))
return E_OUTOFMEMORY;
if (m_NeedHuffmanCreate)
{
for (int i = 0; i < kNumTablesMax; i++)
if (!m_HuffEncoders[i].Create(kMaxAlphaSize, 0, 0, kMaxHuffmanLen))
return E_OUTOFMEMORY;
m_NeedHuffmanCreate = false;
}
m_InStream.SetStream(inStream);
m_InStream.Init();
m_OutStream.SetStream(outStream);
m_OutStream.Init();
CFlusher flusher(this);
CBZip2CombinedCRC combinedCRC;
WriteByte(kArSig0);
WriteByte(kArSig1);
WriteByte(kArSig2);
WriteByte((Byte)(kArSig3 + m_BlockSizeMult));
while (true)
{
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 *)m_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(m_OutBuffer, numBytesToWrite, &processedSize));
if (numBytesToWrite != processedSize)
return E_FAIL;
}
if (result == BZ_STREAM_END)
UInt32 blockSize = ReadRleBlock(m_Block);
if (blockSize == 0)
break;
switch(result)
EncodeBlock3(combinedCRC, blockSize);
if (progress)
{
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));
UInt64 packSize = m_InStream.GetProcessedSize();
UInt64 unpackSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
}
}
// result = bzStream.End();
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(...) { 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 > 10)
return E_INVALIDARG;
m_NumPasses = numPasses;
m_OptimizeNumTables = (m_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;
}
default:
return E_INVALIDARG;
}
}
return S_OK;
}
}}

View File

@@ -1,34 +1,158 @@
// Compress/BZip2/Encoder.h
#pragma once
#ifndef __COMPRESS_BZIP2_ENCODER_H
#define __COMPRESS_BZIP2_ENCODER_H
#include "Common/MyCom.h"
#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
#include "../../Common/MSBFEncoder.h"
#include "../../Common/InBuffer.h"
#include "../../Common/OutBuffer.h"
#include "../Huffman/HuffmanEncoder.h"
#include "../BWT/BlockSort.h"
#include "BZip2Const.h"
#include "BZip2CRC.h"
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 :
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp
{
BYTE *m_InBuffer;
BYTE *m_OutBuffer;
Byte *m_Block;
CInBuffer m_InStream;
NStream::NMSBF::CEncoder<COutBuffer> m_OutStream;
CMsbfEncoderTemp *m_OutStreamCurrent;
CBlockSorter m_BlockSorter;
bool m_NeedHuffmanCreate;
NCompression::NHuffman::CEncoder m_HuffEncoders[kNumTablesMax];
Byte *m_MtfArray;
Byte *m_TempArray;
Byte m_Selectors[kNumSelectorsMax];
UInt32 m_BlockSizeMult;
UInt32 m_NumPasses;
bool m_OptimizeNumTables;
UInt32 ReadRleBlock(Byte *buffer);
void WriteBits2(UInt32 value, UInt32 numBits);
void WriteByte2(Byte b);
void WriteBit2(bool v);
void WriteCRC2(UInt32 v);
void WriteBits(UInt32 value, UInt32 numBits);
void WriteByte(Byte b);
void WriteBit(bool v);
void WriteCRC(UInt32 v);
void EncodeBlock(Byte *block, UInt32 blockSize);
UInt32 EncodeBlockWithHeaders(Byte *block, UInt32 blockSize);
void EncodeBlock2(CBZip2CombinedCRC &combinedCRC, Byte *block, UInt32 blockSize, UInt32 numPasses);
void EncodeBlock3(CBZip2CombinedCRC &combinedCRC, UInt32 blockSize);
public:
CEncoder();
~CEncoder();
MY_UNKNOWN_IMP
HRESULT Flush() { return m_OutStream.Flush(); }
void ReleaseStreams()
{
m_InStream.ReleaseStream();
m_OutStream.ReleaseStream();
}
// STDMETHOD(ReleaseStreams)();
class CFlusher
{
CEncoder *_coder;
public:
bool NeedFlush;
CFlusher(CEncoder *coder): _coder(coder), NeedFlush(true) {}
~CFlusher()
{
if (NeedFlush)
_coder->Flush();
_coder->ReleaseStreams();
}
};
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
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,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
};
}}

View File

@@ -2,11 +2,11 @@
#include "StdAfx.h"
#define INITGUID
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "BZip2Encoder.h"
#include "BZip2Decoder.h"
#include "Common/ComTry.h"
// {23170F69-40C1-278B-0402-020000000000}
DEFINE_GUID(CLSID_CCompressBZip2Decoder,

View File

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,8,1,0
PRODUCTVERSION 3,8,1,0
FILEVERSION 4,19,0,0
PRODUCTVERSION 4,19,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -85,14 +85,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", " \0"
VALUE "FileDescription", "BZip2 Coder\0"
VALUE "FileVersion", "3, 8, 1, 0\0"
VALUE "FileVersion", "4, 19, 0, 0\0"
VALUE "InternalName", "BZip2\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "BZip2.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 8, 1, 0\0"
VALUE "ProductVersion", "4, 19, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -0,0 +1,9 @@
; BZip2.def
LIBRARY BZip2.dll
EXPORTS
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE

View File

@@ -0,0 +1,305 @@
# 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 "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_EXPORTS" /D "BZ_NO_STDIO" /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 "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_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\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=.\BZip2.def
# End Source File
# Begin Source File
SOURCE=.\DllExports.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.h
# 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 "Origianl"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Original\blocksort.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=.\Original\bzlib.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=.\Original\bzlib.h
# End Source File
# Begin Source File
SOURCE=.\Original\bzlib_private.h
# End Source File
# Begin Source File
SOURCE=.\Original\compress.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=.\Original\crctable.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=.\Original\decompress.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=.\Original\huffman.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=.\Original\randtable.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
# 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 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
# Begin Source File
SOURCE=.\BZip2Error.cpp
# 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,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;
while (true)
{
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;
while (true)
{
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,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,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,121 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Russian resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Russian resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,16,0,0
PRODUCTVERSION 4,16,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", " \0"
VALUE "FileDescription", "BZip2 Coder\0"
VALUE "FileVersion", "4, 16, 0, 0\0"
VALUE "InternalName", "BZip2\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "BZip2.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "4, 16, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -3,67 +3,14 @@
#include "StdAfx.h"
#include "ARM.h"
#include "Windows/Defs.h"
#include "BranchARM.c"
static HRESULT BC_ARM_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 4)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 4; bufferPos += 4)
{
if (buffer[bufferPos + 3] == 0xeb)
{
UINT32 src =
(buffer[bufferPos + 2] << 16) |
(buffer[bufferPos + 1] << 8) |
(buffer[bufferPos + 0]);
src <<= 2;
UINT32 dest;
if (encoding)
dest = nowPos + bufferPos + 8 + src;
else
dest = src - (nowPos + bufferPos + 8);
dest >>= 2;
buffer[bufferPos + 2] = (dest >> 16);
buffer[bufferPos + 1] = (dest >> 8);
buffer[bufferPos + 0] = dest;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
return ::ARM_Convert(data, size, _bufferPos, 1);
}
MyClassImp(BC_ARM)
UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARM_Convert(data, size, _bufferPos, 0);
}

View File

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

View File

@@ -3,74 +3,14 @@
#include "StdAfx.h"
#include "ARMThumb.h"
#include "Windows/Defs.h"
#include "BranchARMThumb.c"
static HRESULT BC_ARMThumb_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 4)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 4; bufferPos += 2)
{
if ((buffer[bufferPos + 1] & 0xF8) == 0xF0 &&
(buffer[bufferPos + 3] & 0xF8) == 0xF8)
{
UINT32 src =
((buffer[bufferPos + 1] & 0x7) << 19) |
(buffer[bufferPos + 0] << 11) |
((buffer[bufferPos + 3] & 0x7) << 8) |
(buffer[bufferPos + 2]);
src <<= 1;
UINT32 dest;
if (encoding)
dest = nowPos + bufferPos + 4 + src;
else
dest = src - (nowPos + bufferPos + 4);
dest >>= 1;
buffer[bufferPos + 1] = 0xF0 | ((dest >> 19) & 0x7);
buffer[bufferPos + 0] = (dest >> 11);
buffer[bufferPos + 3] = 0xF8 | ((dest >> 8) & 0x7);
buffer[bufferPos + 2] = (dest);
bufferPos += 2;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
return ::ARMThumb_Convert(data, size, _bufferPos, 1);
}
MyClassImp(BC_ARMThumb)
UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::ARMThumb_Convert(data, size, _bufferPos, 0);
}

View File

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

View File

@@ -1,75 +0,0 @@
// Alpha.cpp
#include "StdAfx.h"
#include "Alpha.h"
#include "Windows/Defs.h"
static HRESULT BC_Alpha_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 4)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 4; bufferPos += 4)
{
// if (buffer[bufferPos + 3] == 0xc3 && (buffer[bufferPos + 2] >> 5) == 7) // its jump
// if (buffer[bufferPos + 3] == 0xd3 && (buffer[bufferPos + 2] >> 5) == 2)
// if (buffer[bufferPos + 3] == 0xd3)
if ((buffer[bufferPos + 3] >> 2) == 0x34)
{
UINT32 src =
((buffer[bufferPos + 2] & 0x1F) << 16) |
(buffer[bufferPos + 1] << 8) |
(buffer[bufferPos + 0]);
src <<= 2;
UINT32 dest;
if (encoding)
dest = (nowPos + bufferPos + 4) + src;
else
dest = src - (nowPos + bufferPos + 4);
dest >>= 2;
dest &= 0x1FFFFF;
buffer[bufferPos + 2] &= (~0x1F);
buffer[bufferPos + 2] |= (dest >> 16);
buffer[bufferPos + 1] = (dest >> 8);
buffer[bufferPos + 0] = dest;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
}
MyClassImp(BC_Alpha)

View File

@@ -1,12 +0,0 @@
// Alpha.h
#pragma once
#ifndef __ALPHA_H
#define __ALPHA_H
#include "Coder.h"
MyClass(BC_Alpha, 0x03, 1)
#endif

View File

@@ -123,24 +123,6 @@ SOURCE=.\StdAfx.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Alpha.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=.\Alpha.h
# End Source File
# Begin Source File
SOURCE=.\ARM.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
@@ -177,7 +159,15 @@ SOURCE=.\ARMThumb.h
# End Source File
# Begin Source File
SOURCE=.\Coder.h
SOURCE=.\BranchCoder.cpp
# End Source File
# Begin Source File
SOURCE=.\BranchCoder.h
# End Source File
# Begin Source File
SOURCE=.\BranchX86.h
# End Source File
# Begin Source File
@@ -199,24 +189,6 @@ SOURCE=.\IA64.h
# End Source File
# Begin Source File
SOURCE=.\M68.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=.\M68.h
# End Source File
# Begin Source File
SOURCE=.\PPC.cpp
!IF "$(CFG)" == "Branch - Win32 Release"
@@ -235,6 +207,14 @@ 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"
@@ -305,6 +285,14 @@ SOURCE=..\RangeCoder\RangeCoderBit.h
# 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,26 @@
// BranchARM.c
#include "BranchARM.h"
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
{
UInt32 i;
for (i = 0; i + 4 <= size; i += 4)
{
if (data[i + 3] == 0xEB)
{
UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
src <<= 2;
UInt32 dest;
if (encoding)
dest = nowPos + i + 8 + src;
else
dest = src - (nowPos + i + 8);
dest >>= 2;
data[i + 2] = (dest >> 16);
data[i + 1] = (dest >> 8);
data[i + 0] = dest;
}
}
return i;
}

View File

@@ -0,0 +1,10 @@
// BranchARM.h
#ifndef __BRANCH_ARM_H
#define __BRANCH_ARM_H
#include "Common/Types.h"
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
#endif

View File

@@ -0,0 +1,35 @@
// BranchARMThumb.c
#include "BranchARMThumb.h"
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
{
UInt32 i;
for (i = 0; i + 4 <= size; i += 2)
{
if ((data[i + 1] & 0xF8) == 0xF0 &&
(data[i + 3] & 0xF8) == 0xF8)
{
UInt32 src =
((data[i + 1] & 0x7) << 19) |
(data[i + 0] << 11) |
((data[i + 3] & 0x7) << 8) |
(data[i + 2]);
src <<= 1;
UInt32 dest;
if (encoding)
dest = nowPos + i + 4 + src;
else
dest = src - (nowPos + i + 4);
dest >>= 1;
data[i + 1] = 0xF0 | ((dest >> 19) & 0x7);
data[i + 0] = (dest >> 11);
data[i + 3] = 0xF8 | ((dest >> 8) & 0x7);
data[i + 2] = (dest);
i += 2;
}
}
return i;
}

View File

@@ -0,0 +1,10 @@
// BranchARMThumb.h
#ifndef __BRANCH_ARM_THUMB_H
#define __BRANCH_ARM_THUMB_H
#include "Common/Types.h"
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
#endif

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,65 @@
// BranchIA64.c
#include "BranchIA64.h"
const Byte kBranchTable[32] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 6, 0, 0, 7, 7,
4, 4, 0, 0, 4, 4, 0, 0
};
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
{
UInt32 i;
for (i = 0; i + 16 <= size; i += 16)
{
UInt32 instrTemplate = data[i] & 0x1F;
UInt32 mask = kBranchTable[instrTemplate];
UInt32 bitPos = 5;
for (int slot = 0; slot < 3; slot++, bitPos += 41)
{
if (((mask >> slot) & 1) == 0)
continue;
UInt32 bytePos = (bitPos >> 3);
UInt32 bitRes = bitPos & 0x7;
// UInt64 instruction = *(UInt64 *)(data + i + bytePos);
UInt64 instruction = 0;
int j;
for (j = 0; j < 6; j++)
instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
UInt64 instNorm = instruction >> bitRes;
if (((instNorm >> 37) & 0xF) == 0x5
&& ((instNorm >> 9) & 0x7) == 0
// && (instNorm & 0x3F)== 0
)
{
UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF);
src |= ((instNorm >> 36) & 1) << 20;
src <<= 4;
UInt32 dest;
if (encoding)
dest = nowPos + i + src;
else
dest = src - (nowPos + i);
dest >>= 4;
instNorm &= ~(UInt64(0x8FFFFF) << 13);
instNorm |= (UInt64(dest & 0xFFFFF) << 13);
instNorm |= (UInt64(dest & 0x100000) << (36 - 20));
instruction &= (1 << bitRes) - 1;
instruction |= (instNorm << bitRes);
// *(UInt64 *)(data + i + bytePos) = instruction;
for (j = 0; j < 6; j++)
data[i + j + bytePos] = Byte(instruction >> (8 * j));
}
}
}
return i;
}

View File

@@ -0,0 +1,10 @@
// BranchIA64.h
#ifndef __BRANCH_IA64_H
#define __BRANCH_IA64_H
#include "Common/Types.h"
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
#endif

View File

@@ -0,0 +1,36 @@
// BranchPPC.c
#include "BranchPPC.h"
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
{
UInt32 i;
for (i = 0; i + 4 <= size; i += 4)
{
// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
if ((data[i] >> 2) == 0x12 &&
(
(data[i + 3] & 3) == 1
// || (data[i+3] & 3) == 3
)
)
{
UInt32 src = ((data[i + 0] & 3) << 24) |
(data[i + 1] << 16) |
(data[i + 2] << 8) |
(data[i + 3] & (~3));
UInt32 dest;
if (encoding)
dest = nowPos + i + src;
else
dest = src - (nowPos + i);
data[i + 0] = 0x48 | ((dest >> 24) & 0x3);
data[i + 1] = (dest >> 16);
data[i + 2] = (dest >> 8);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
}
}
return i;
}

View File

@@ -0,0 +1,10 @@
// BranchPPC.h
#ifndef __BRANCH_PPC_H
#define __BRANCH_PPC_H
#include "Common/Types.h"
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
#endif

View File

@@ -0,0 +1,36 @@
// BranchSPARC.c
#include "BranchSPARC.h"
UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
{
UInt32 i;
for (i = 0; i + 4 <= size; i += 4)
{
if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
{
UInt32 src =
((UInt32)data[i + 0] << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3]);
src <<= 2;
UInt32 dest;
if (encoding)
dest = nowPos + i + src;
else
dest = src - (nowPos + i);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
data[i + 0] = (Byte)(dest >> 24);
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] = (Byte)dest;
}
}
return i;
}

View File

@@ -0,0 +1,10 @@
// BranchSPARC.h
#ifndef __BRANCH_SPARC_H
#define __BRANCH_SPARC_H
#include "Common/Types.h"
UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
#endif

101
7zip/Compress/Branch/BranchX86.c Executable file
View File

@@ -0,0 +1,101 @@
/* BranchX86.c */
#include "BranchX86.h"
/*
static int inline Test86MSByte(Byte b)
{
return (b == 0 || b == 0xFF);
}
*/
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
/*
void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos)
{
*prevMask = 0;
*prevPos = (UInt32)(-5);
}
*/
UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
UInt32 *prevMask, UInt32 *prevPos, int encoding)
{
UInt32 bufferPos = 0;
UInt32 limit;
if (endPos < 5)
return 0;
if (nowPos - *prevPos > 5)
*prevPos = nowPos - 5;
limit = endPos - 5;
while(bufferPos <= limit)
{
Byte b = buffer[bufferPos];
UInt32 offset;
if (b != 0xE8 && b != 0xE9)
{
bufferPos++;
continue;
}
offset = (nowPos + bufferPos - *prevPos);
*prevPos = (nowPos + bufferPos);
if (offset > 5)
*prevMask = 0;
else
{
UInt32 i;
for (i = 0; i < offset; i++)
{
*prevMask &= 0x77;
*prevMask <<= 1;
}
}
b = buffer[bufferPos + 4];
if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] &&
(*prevMask >> 1) < 0x10)
{
UInt32 src =
((UInt32)(b) << 24) |
((UInt32)(buffer[bufferPos + 3]) << 16) |
((UInt32)(buffer[bufferPos + 2]) << 8) |
(buffer[bufferPos + 1]);
UInt32 dest;
while(1)
{
UInt32 index;
if (encoding)
dest = (nowPos + bufferPos + 5) + src;
else
dest = src - (nowPos + bufferPos + 5);
if (*prevMask == 0)
break;
index = kMaskToBitNumber[*prevMask >> 1];
b = (Byte)(dest >> (24 - index * 8));
if (!Test86MSByte(b))
break;
src = dest ^ ((1 << (32 - index * 8)) - 1);
}
buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1));
buffer[bufferPos + 3] = (Byte)(dest >> 16);
buffer[bufferPos + 2] = (Byte)(dest >> 8);
buffer[bufferPos + 1] = (Byte)dest;
bufferPos += 5;
*prevMask = 0;
}
else
{
bufferPos++;
*prevMask |= 1;
if (Test86MSByte(b))
*prevMask |= 0x10;
}
}
return bufferPos;
}

View File

@@ -0,0 +1,19 @@
/* BranchX86.h */
#ifndef __BRANCHX86_H
#define __BRANCHX86_H
#ifndef UInt32
#define UInt32 unsigned int
#endif
#ifndef Byte
#define Byte unsigned char
#endif
#define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); }
UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
UInt32 *prevMask, UInt32 *prevPos, int encoding);
#endif

View File

@@ -1,66 +0,0 @@
// Branch/Coder.h
#pragma once
#ifndef __CallPowerPC_CODER_H
#define __CallPowerPC_CODER_H
#include "Common/MyCom.h"
#include "Common/Types.h"
#include "../../ICoder.h"
const int kBufferSize = 1 << 17;
class CDataBuffer
{
protected:
BYTE *_buffer;
public:
CDataBuffer()
{ _buffer = new BYTE[kBufferSize]; }
~CDataBuffer()
{ delete []_buffer; }
};
#define MyClass3(Name) \
class C ## Name: \
public ICompressCoder, \
public CDataBuffer, \
public CMyUnknownImp \
{ \
public: \
MY_UNKNOWN_IMP \
STDMETHOD(Code)(ISequentialInStream *inStream, \
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, \
ICompressProgressInfo *progress); \
};
// {23170F69-40C1-278B-0303-010100000100}
#define MyClass2(Name, id, subId, encodingId) \
DEFINE_GUID(CLSID_CCompressConvert ## Name, \
0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); \
MyClass3(Name) \
#define MyClass(Name, id, subId) \
MyClass2(Name ## _Encoder, id, subId, 0x01) \
MyClass2(Name ## _Decoder, id, subId, 0x00)
#define MyClassImp(Name) \
STDMETHODIMP C ## Name ## _Encoder::Code(ISequentialInStream *inStream, \
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, \
ICompressProgressInfo *progress) \
{ \
return Name ## _Code(inStream, outStream, inSize, outSize, \
progress, _buffer, true); \
} \
STDMETHODIMP C ## Name ## _Decoder::Code(ISequentialInStream *inStream, \
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize, \
ICompressProgressInfo *progress) \
{ \
return Name ## _Code(inStream, outStream, inSize, outSize, \
progress, _buffer, false); \
}
#endif

View File

@@ -2,52 +2,28 @@
#include "StdAfx.h"
#define INITGUID
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "Coder.h"
#include "x86.h"
#include "PPC.h"
#include "Alpha.h"
#include "IA64.h"
#include "ARM.h"
#include "ARMThumb.h"
#include "M68.h"
#include "x86_2.h"
#include "SPARC.h"
#include "../../ICoder.h"
#define MY_CreateClass(n) \
#define MY_CreateClass0(n) \
if (*clsid == CLSID_CCompressConvert ## n ## _Encoder) { \
if (!correctInterface) \
return E_NOINTERFACE; \
coder = (ICompressCoder *)new C ## n ## _Encoder(); \
filter = (ICompressFilter *)new C ## n ## _Encoder(); \
} else if (*clsid == CLSID_CCompressConvert ## n ## _Decoder){ \
if (!correctInterface) \
return E_NOINTERFACE; \
coder = (ICompressCoder *)new C ## n ## _Decoder(); \
filter = (ICompressFilter *)new C ## n ## _Decoder(); \
}
/*
#define MyOBJECT_ENTRY(Name) \
OBJECT_ENTRY(CLSID_CCompressConvert ## Name ## _Encoder, C ## Name ## _Encoder) \
OBJECT_ENTRY(CLSID_CCompressConvert ## Name ## _Decoder, C ## Name ## _Decoder) \
BEGIN_OBJECT_MAP(ObjectMap)
MyOBJECT_ENTRY(BCJ_x86)
MyOBJECT_ENTRY(BCJ2_x86)
MyOBJECT_ENTRY(BC_PPC_B)
MyOBJECT_ENTRY(BC_Alpha)
MyOBJECT_ENTRY(BC_IA64)
MyOBJECT_ENTRY(BC_ARM)
MyOBJECT_ENTRY(BC_ARMThumb)
MyOBJECT_ENTRY(BC_M68_B)
END_OBJECT_MAP()
*/
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
@@ -61,22 +37,19 @@ STDAPI CreateObject(
{
COM_TRY_BEGIN
*outObject = 0;
int correctInterface = (*interfaceID == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
MY_CreateClass(BCJ_x86)
int correctInterface = (*interfaceID == IID_ICompressFilter);
CMyComPtr<ICompressFilter> filter;
MY_CreateClass0(BCJ_x86)
else
MY_CreateClass(BC_PPC_B)
MY_CreateClass0(BC_ARM)
else
MY_CreateClass(BC_Alpha)
MY_CreateClass0(BC_PPC_B)
else
MY_CreateClass(BC_IA64)
MY_CreateClass0(BC_IA64)
else
MY_CreateClass(BC_ARM)
MY_CreateClass0(BC_ARMThumb)
else
MY_CreateClass(BC_ARMThumb)
else
MY_CreateClass(BC_M68_B)
MY_CreateClass0(BC_SPARC)
else
{
CMyComPtr<ICompressCoder2> coder2;
@@ -98,8 +71,9 @@ STDAPI CreateObject(
*outObject = coder2.Detach();
return S_OK;
}
*outObject = coder.Detach();
*outObject = filter.Detach();
return S_OK;
COM_TRY_END
}
@@ -123,11 +97,12 @@ 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_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_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)
@@ -175,4 +150,3 @@ STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
}
return S_OK;
}

View File

@@ -3,101 +3,14 @@
#include "StdAfx.h"
#include "IA64.h"
#include "Windows/Defs.h"
#include "BranchIA64.c"
const BYTE kBranchTable[32] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 6, 0, 0, 7, 7,
4, 4, 0, 0, 4, 4, 0, 0
};
static HRESULT BC_IA64_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 16)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 16; bufferPos += 16)
{
UINT32 instrTemplate = buffer[bufferPos] & 0x1F;
// ofs << hex << setw(4) << instrTemplate << endl;
UINT32 mask = kBranchTable[instrTemplate];
UINT32 bitPos = 5;
for (int slot = 0; slot < 3; slot++, bitPos += 41)
{
if (((mask >> slot) & 1) == 0)
continue;
UINT32 bytePos = (bitPos >> 3);
UINT32 bitRes = bitPos & 0x7;
UINT64 instruction = *(UINT64 *)(buffer + bufferPos + bytePos);
UINT64 instNorm = instruction >> bitRes;
if (((instNorm >> 37) & 0xF) == 0x5
&& ((instNorm >> 9) & 0x7) == 0
// && (instNorm & 0x3F)== 0
)
{
UINT32 src = UINT32((instNorm >> 13) & 0xFFFFF);
src |= ((instNorm >> 36) & 1) << 20;
src <<= 4;
UINT32 dest;
if (encoding)
dest = nowPos + bufferPos + src;
else
dest = src - (nowPos + bufferPos);
dest >>= 4;
UINT64 instNorm2 = instNorm;
instNorm &= ~(UINT64(0x8FFFFF) << 13);
instNorm |= (UINT64(dest & 0xFFFFF) << 13);
instNorm |= (UINT64(dest & 0x100000) << (36 - 20));
instruction &= (1 << bitRes) - 1;
instruction |= (instNorm << bitRes);
*(UINT64 *)(buffer + bufferPos + bytePos) = instruction;
}
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
return ::IA64_Convert(data, size, _bufferPos, 1);
}
MyClassImp(BC_IA64)
UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::IA64_Convert(data, size, _bufferPos, 0);
}

View File

@@ -1,14 +1,10 @@
// IA64.h
#pragma once
#ifndef __IA64_H
#define __IA64_H
#include "Coder.h"
#include "BranchCoder.h"
MyClass(BC_IA64, 0x04, 1)
// MyClass(IA64_Parse, 0x08, 1)
MyClassA(BC_IA64, 0x04, 1)
#endif

View File

@@ -1,69 +0,0 @@
// M68.cpp
#include "StdAfx.h"
#include "M68.h"
#include "Windows/Defs.h"
static HRESULT BC_M68_B_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 4)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 4;)
{
if (buffer[bufferPos] == 0x61 && buffer[bufferPos + 1] == 0x00)
{
UINT32 src =
(buffer[bufferPos + 2] << 8) |
(buffer[bufferPos + 3]);
UINT32 dest;
if (encoding)
dest = nowPos + bufferPos + 2 + src;
else
dest = src - (nowPos + bufferPos + 2);
buffer[bufferPos + 2] = (dest >> 8);
buffer[bufferPos + 3] = dest;
bufferPos += 4;
}
else
bufferPos += 2;
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
}
MyClassImp(BC_M68_B)

View File

@@ -1,12 +0,0 @@
// M68.h
#pragma once
#ifndef __M68_H
#define __M68_H
#include "Coder.h"
MyClass(BC_M68_B, 0x06, 5)
#endif

View File

@@ -4,73 +4,14 @@
#include "PPC.h"
#include "Windows/Defs.h"
#include "BranchPPC.c"
static HRESULT BC_PPC_B_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size)
{
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 4)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
for (bufferPos = 0; bufferPos <= endPos - 4; bufferPos += 4)
{
// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
if ((buffer[bufferPos] >> 2) == 0x12 &&
(
(buffer[bufferPos + 3] & 3) == 1
// || (buffer[bufferPos+3] & 3) == 3
)
)
{
UINT32 src = ((buffer[bufferPos + 0] & 3) << 24) |
(buffer[bufferPos + 1] << 16) |
(buffer[bufferPos + 2] << 8) |
(buffer[bufferPos + 3] & (~3));
UINT32 dest;
if (encoding)
dest = nowPos + bufferPos + src;
else
dest = src - (nowPos + bufferPos);
buffer[bufferPos + 0] = 0x48 | ((dest >> 24) & 0x3);
buffer[bufferPos + 1] = (dest >> 16);
buffer[bufferPos + 2] = (dest >> 8);
buffer[bufferPos + 3] &= 0x3;
buffer[bufferPos + 3] |= dest;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
return ::PPC_B_Convert(data, size, _bufferPos, 1);
}
MyClassImp(BC_PPC_B)
UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size)
{
return ::PPC_B_Convert(data, size, _bufferPos, 0);
}

View File

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

17
7zip/Compress/Branch/SPARC.cpp Executable file
View File

@@ -0,0 +1,17 @@
// SPARC.cpp
#include "StdAfx.h"
#include "SPARC.h"
#include "Windows/Defs.h"
#include "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);
}

10
7zip/Compress/Branch/SPARC.h Executable file
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

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,9,2,0
PRODUCTVERSION 3,9,2,0
FILEVERSION 4,17,0,0
PRODUCTVERSION 4,17,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -84,15 +84,15 @@ BEGIN
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "Branch converter\0"
VALUE "FileVersion", "3, 9, 2, 0\0"
VALUE "FileDescription", "Branch filter\0"
VALUE "FileVersion", "4, 17, 0, 0\0"
VALUE "InternalName", "Branch\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "Branch.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 9, 2, 0\0"
VALUE "ProductVersion", "4, 17, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -1,124 +1,18 @@
// x86.h
// x86.cpp
#include "StdAfx.h"
#include "x86.h"
#include "Windows/Defs.h"
static bool inline Test86MSByte(BYTE b)
#include "BranchX86.c"
UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)
{
return (b == 0 || b == 0xFF);
return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1);
}
const bool kMaskToAllowedStatus[8] = {true, true, true, false, true, false, false, false};
const BYTE kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
static HRESULT BCJ_x86_Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress, BYTE *buffer, bool encoding)
UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)
{
UINT64 nowPos64 = 0;
UINT32 nowPos = 0;
UINT32 bufferPos = 0;
UINT32 prevMask = 0;
UINT32 prevPos = (- 5);
while(true)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
if (endPos < 5)
{
if (endPos > 0)
{
RINOK(outStream->Write(buffer, endPos, &processedSize));
if (endPos != processedSize)
return E_FAIL;
}
return S_OK;
}
bufferPos = 0;
if (nowPos - prevPos > 5)
prevPos = nowPos - 5;
UINT32 limit = endPos - 5;
while(bufferPos <= limit)
{
if (buffer[bufferPos] != 0xE8 && buffer[bufferPos] != 0xE9)
{
bufferPos++;
continue;
}
UINT32 offset = (nowPos + bufferPos - prevPos);
prevPos = (nowPos + bufferPos);
if (offset > 5)
prevMask = 0;
else
{
for (UINT32 i = 0; i < offset; i++)
{
prevMask &= 0x77;
prevMask <<= 1;
}
}
BYTE &nextByte = buffer[bufferPos + 4];
if (Test86MSByte(nextByte) && kMaskToAllowedStatus[(prevMask >> 1) & 0x7] &&
(prevMask >> 1) < 0x10)
{
UINT32 src =
(UINT32(nextByte) << 24) |
(UINT32(buffer[bufferPos + 3]) << 16) |
(UINT32(buffer[bufferPos + 2]) << 8) |
(buffer[bufferPos + 1]);
UINT32 dest;
while(true)
{
if (encoding)
dest = (nowPos + bufferPos + 5) + src;
else
dest = src - (nowPos + bufferPos + 5);
if (prevMask == 0)
break;
UINT32 index = kMaskToBitNumber[prevMask >> 1];
if (!Test86MSByte(dest >> (24 - index * 8)))
break;
src = dest ^ ((1 << (32 - index * 8)) - 1);
// src = dest;
}
nextByte = ~(((dest >> 24) & 1) - 1);
buffer[bufferPos + 3] = (dest >> 16);
buffer[bufferPos + 2] = (dest >> 8);
buffer[bufferPos + 1] = dest;
bufferPos += 5;
prevMask = 0;
}
else
{
bufferPos++;
prevMask |= 1;
if (Test86MSByte(nextByte))
prevMask |= 0x10;
}
}
nowPos += bufferPos;
nowPos64 += bufferPos;
RINOK(outStream->Write(buffer, bufferPos, &processedSize));
if (bufferPos != processedSize)
return E_FAIL;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
UINT32 i = 0;
while(bufferPos < endPos)
buffer[i++] = buffer[bufferPos++];
bufferPos = i;
}
return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0);
}
MyClassImp(BCJ_x86)

View File

@@ -1,13 +1,19 @@
// x86.h
#pragma once
#ifndef __X86_H
#define __X86_H
#include "Coder.h"
#include "BranchCoder.h"
#include "BranchX86.h"
MyClass(BCJ_x86, 0x01, 3)
// MyClass(x86_J, 0x01, 2)
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

@@ -3,27 +3,46 @@
#include "StdAfx.h"
#include "x86_2.h"
#include "Windows/Defs.h"
#include "../../ICoder.h"
#include "../../../Common/Alloc.h"
inline UINT32 Swap4(UINT32 value)
{
return (value << 24) | (value >> 24) |
( (value >> 8) & 0xFF00) | ( (value << 8) & 0xFF0000);
}
static const int kBufferSize = 1 << 17;
inline bool IsJcc(BYTE b0, BYTE b1)
inline bool IsJcc(Byte b0, Byte b1)
{
return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
}
#ifndef EXTRACT_ONLY
static bool inline Test86MSByte(BYTE b)
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 *)BigAlloc(kBufferSize);
if (_buffer == 0)
return false;
}
return true;
}
CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
{
BigFree(_buffer);
}
HRESULT CBCJ2_x86_Encoder::Flush()
{
RINOK(_mainStream.Flush());
@@ -33,21 +52,24 @@ HRESULT CBCJ2_x86_Encoder::Flush()
return _rangeEncoder.FlushStream();
}
const UINT32 kDefaultLimit = (1 << 24);
const UInt32 kDefaultLimit = (1 << 24);
HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
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;
UInt64 inSize;
if (inSizes != NULL)
if (inSizes[0] != NULL)
{
@@ -56,48 +78,50 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
sizeIsDefined = true;
}
ISequentialInStream *inStream = inStreams[0];
_mainStream.Init(outStreams[0]);
_callStream.Init(outStreams[1]);
_jumpStream.Init(outStreams[2]);
_rangeEncoder.Init(outStreams[3]);
_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);
CCoderReleaser releaser(this);
CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
{
inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
}
UInt32 nowPos = 0;
UInt64 nowPos64 = 0;
UInt32 bufferPos = 0;
UInt32 processedSize;
UINT32 nowPos = 0;
UINT64 nowPos64 = 0;
UINT32 bufferPos = 0;
UINT32 processedSize;
Byte prevByte = 0;
BYTE prevByte = 0;
UINT64 subStreamIndex = 0;
UINT64 subStreamStartPos = 0;
UINT64 subStreamEndPos = 0;
UInt64 subStreamIndex = 0;
UInt64 subStreamStartPos = 0;
UInt64 subStreamEndPos = 0;
while(true)
{
UINT32 size = kBufferSize - bufferPos;
UInt32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
UINT32 endPos = bufferPos + processedSize;
UInt32 endPos = bufferPos + processedSize;
if (endPos < 5)
{
// change it
for (bufferPos = 0; bufferPos < endPos; bufferPos++)
{
BYTE b = _buffer[bufferPos];
Byte b = _buffer[bufferPos];
_mainStream.WriteByte(b);
if (b == 0xE8)
_statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
@@ -112,10 +136,10 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
bufferPos = 0;
UINT32 limit = endPos - 5;
UInt32 limit = endPos - 5;
while(bufferPos <= limit)
{
BYTE b = _buffer[bufferPos];
Byte b = _buffer[bufferPos];
_mainStream.WriteByte(b);
if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
{
@@ -123,21 +147,21 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
prevByte = b;
continue;
}
BYTE nextByte = _buffer[bufferPos + 4];
UINT32 src =
(UINT32(nextByte) << 24) |
(UINT32(_buffer[bufferPos + 3]) << 16) |
(UINT32(_buffer[bufferPos + 2]) << 8) |
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;
UInt32 dest = (nowPos + bufferPos + 5) + src;
// if (Test86MSByte(nextByte))
bool convert;
if (getSubStreamSize != NULL)
{
UINT64 currentPos = (nowPos64 + bufferPos);
UInt64 currentPos = (nowPos64 + bufferPos);
while (subStreamEndPos < currentPos)
{
UINT64 subStreamSize;
UInt64 subStreamSize;
HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
if (result == S_OK)
{
@@ -165,7 +189,7 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
convert = Test86MSByte(nextByte);
else
{
UINT64 dest64 = (currentPos + 5) + INT64(INT32(src));
UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
}
}
@@ -182,13 +206,21 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
else
_statusJccEncoder.Encode(&_rangeEncoder, 1);
dest = Swap4(dest);
bufferPos += 5;
if (b == 0xE8)
_callStream.WriteBytes(&dest, sizeof(dest));
{
_callStream.WriteByte((Byte)(dest >> 24));
_callStream.WriteByte((Byte)(dest >> 16));
_callStream.WriteByte((Byte)(dest >> 8));
_callStream.WriteByte((Byte)(dest));
}
else
_jumpStream.WriteBytes(&dest, sizeof(dest));
{
_jumpStream.WriteByte((Byte)(dest >> 24));
_jumpStream.WriteByte((Byte)(dest >> 16));
_jumpStream.WriteByte((Byte)(dest >> 8));
_jumpStream.WriteByte((Byte)(dest));
}
prevByte = nextByte;
}
else
@@ -211,8 +243,7 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
RINOK(progress->SetRatioInfo(&nowPos64, NULL));
}
UINT32 i = 0;
UInt32 i = 0;
while(bufferPos < endPos)
_buffer[i++] = _buffer[bufferPos++];
bufferPos = i;
@@ -220,11 +251,11 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
}
STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
@@ -239,41 +270,58 @@ STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
#endif
HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != 4 || numOutStreams != 1)
return E_INVALIDARG;
_mainInStream.Init(inStreams[0]);
_callStream.Init(inStreams[1]);
_jumpStream.Init(inStreams[2]);
_rangeDecoder.Init(inStreams[3]);
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();
_outStream.Init(outStreams[0]);
CCoderReleaser releaser(this);
// CCoderReleaser releaser(this);
BYTE prevByte = 0;
UINT32 processedBytes = 0;
Byte prevByte = 0;
UInt32 processedBytes = 0;
while(true)
{
if (processedBytes > (1 << 20) && progress != NULL)
{
UINT64 nowPos64 = _outStream.GetProcessedSize();
UInt64 nowPos64 = _outStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(NULL, &nowPos64));
processedBytes = 0;
}
processedBytes++;
BYTE b;
Byte b;
if (!_mainInStream.ReadByte(b))
return Flush();
_outStream.WriteByte(b);
@@ -291,20 +339,44 @@ HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
if (status)
{
UINT32 src;
UInt32 src;
if (b == 0xE8)
{
if (!_callStream.ReadBytes(&src, sizeof(src)))
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
{
if (!_jumpStream.ReadBytes(&src, sizeof(src)))
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);
}
src = Swap4(src);
UINT32 dest = src - (UINT32(_outStream.GetProcessedSize()) + 4) ;
_outStream.WriteBytes(&dest, sizeof(dest));
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 = (dest >> 24);
processedBytes += 4;
}
@@ -314,11 +386,11 @@ HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
}
STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try

View File

@@ -1,14 +1,11 @@
// x86_2.h
#pragma once
#ifndef __BRANCH_X86_2_H
#define __BRANCH_X86_2_H
#ifndef __X86_2_H
#define __X86_2_H
#include "Common/MyCom.h"
#include "Coder.h"
#include "../../../Common/MyCom.h"
#include "../RangeCoder/RangeCoderBit.h"
// #include "../../Common/InBuffer.h"
#include "../../ICoder.h"
// {23170F69-40C1-278B-0303-010100000100}
#define MyClass2_a(Name, id, subId, encodingId) \
@@ -27,11 +24,13 @@ const int kNumMoveBits = 5;
class CBCJ2_x86_Encoder:
public ICompressCoder2,
public CDataBuffer,
public CMyUnknownImp
{
Byte *_buffer;
public:
CBCJ2_x86_Encoder(): _mainStream(1 << 16) {}
CBCJ2_x86_Encoder(): _buffer(0) {};
~CBCJ2_x86_Encoder();
bool Create();
COutBuffer _mainStream;
COutBuffer _callStream;
@@ -42,7 +41,6 @@ public:
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusJccEncoder;
HRESULT Flush();
/*
void ReleaseStreams()
{
_mainStream.ReleaseStream();
@@ -55,32 +53,27 @@ public:
{
CBCJ2_x86_Encoder *_coder;
public:
CCoderReleaser(CBCJ2_x86_Encoder *aCoder): _coder(aCoder) {}
~CCoderReleaser()
{
_coder->ReleaseStreams();
}
CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {}
~CCoderReleaser() { _coder->ReleaseStreams(); }
};
friend class CCoderReleaser;
*/
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
};
@@ -91,8 +84,6 @@ class CBCJ2_x86_Decoder:
public CMyUnknownImp
{
public:
CBCJ2_x86_Decoder(): _outStream(1 << 16), _mainInStream(1 << 16) {}
CInBuffer _mainInStream;
CInBuffer _callStream;
CInBuffer _jumpStream;
@@ -103,7 +94,6 @@ public:
COutBuffer _outStream;
/*
void ReleaseStreams()
{
_mainInStream.ReleaseStream();
@@ -112,35 +102,31 @@ public:
_rangeDecoder.ReleaseStream();
_outStream.ReleaseStream();
}
*/
HRESULT Flush() { return _outStream.Flush(); }
/*
class CCoderReleaser
{
CBCJ2_x86_Decoder *_coder;
public:
CCoderReleaser(CBCJ2_x86_Decoder *aCoder): _coder(aCoder) {}
CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {}
~CCoderReleaser() { _coder->ReleaseStreams(); }
};
friend class CCoderReleaser;
*/
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
};

View File

@@ -1,100 +1,38 @@
// Coder.cpp
// ByteSwap.cpp
#include "StdAfx.h"
#include "ByteSwap.h"
#include "Windows/Defs.h"
const int kBufferSize = 1 << 17;
STDMETHODIMP CByteSwap2::Init() { return S_OK; }
CBuffer::CBuffer():
_buffer(0)
STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)
{
_buffer = new BYTE[kBufferSize];
}
CBuffer::~CBuffer()
{
delete []_buffer;
}
STDMETHODIMP CByteSwap2::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress)
{
const UINT32 kStep = 2;
UINT32 bufferPos = 0;
UINT64 nowPos64 = 0;
while(true)
const UInt32 kStep = 2;
UInt32 i;
for (i = 0; i + kStep <= size; i += kStep)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
if (processedSize == 0)
return outStream->Write(_buffer, bufferPos, NULL);
UINT32 endPos = bufferPos + processedSize;
for (UINT32 curPos = 0; curPos + kStep <= endPos; curPos += kStep)
{
BYTE data[kStep];
data[0] = _buffer[curPos + 0];
data[1] = _buffer[curPos + 1];
_buffer[curPos + 0] = data[1];
_buffer[curPos + 1] = data[0];
}
RINOK(outStream->Write(_buffer, curPos, &processedSize));
if (curPos != processedSize)
return E_FAIL;
nowPos64 += curPos;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
bufferPos = 0;
while(curPos < endPos)
_buffer[bufferPos++] = _buffer[curPos++];
Byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
return i;
}
STDMETHODIMP CByteSwap4::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress)
STDMETHODIMP CByteSwap4::Init() { return S_OK; }
STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)
{
const UINT32 kStep = 4;
UINT32 bufferPos = 0;
UINT64 nowPos64 = 0;
while(true)
const UInt32 kStep = 4;
UInt32 i;
for (i = 0; i + kStep <= size; i += kStep)
{
UINT32 processedSize;
UINT32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
if (processedSize == 0)
return outStream->Write(_buffer, bufferPos, NULL);
UINT32 endPos = bufferPos + processedSize;
for (UINT32 curPos = 0; curPos + kStep <= endPos; curPos += kStep)
{
BYTE data[kStep];
data[0] = _buffer[curPos + 0];
data[1] = _buffer[curPos + 1];
data[2] = _buffer[curPos + 2];
data[3] = _buffer[curPos + 3];
_buffer[curPos + 0] = data[3];
_buffer[curPos + 1] = data[2];
_buffer[curPos + 2] = data[1];
_buffer[curPos + 3] = data[0];
}
RINOK(outStream->Write(_buffer, curPos, &processedSize));
if (curPos != processedSize)
return E_FAIL;
nowPos64 += curPos;
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
}
bufferPos = 0;
while(curPos < endPos)
_buffer[bufferPos++] = _buffer[curPos++];
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

@@ -14,38 +14,24 @@ DEFINE_GUID(CLSID_CCompressConvertByteSwap2,
DEFINE_GUID(CLSID_CCompressConvertByteSwap4,
0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00);
class CBuffer
{
protected:
BYTE *_buffer;
public:
CBuffer();
~CBuffer();
};
class CByteSwap2 :
public ICompressCoder,
public CBuffer,
class CByteSwap2:
public ICompressFilter,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
};
class CByteSwap4 :
public ICompressCoder,
public CBuffer,
class CByteSwap4:
public ICompressFilter,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress);
STDMETHOD(Init)();
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
};
#endif
#endif

View File

@@ -2,8 +2,7 @@
#include "StdAfx.h"
#define INITGUID
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "ByteSwap.h"
#include "../../ICoder.h"
@@ -18,19 +17,19 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
COM_TRY_BEGIN
*outObject = 0;
int correctInterface = (*iid == IID_ICompressCoder);
CMyComPtr<ICompressCoder> coder;
int correctInterface = (*iid == IID_ICompressFilter);
CMyComPtr<ICompressFilter> coder;
if (*clsid == CLSID_CCompressConvertByteSwap2)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new CByteSwap2();
coder = (ICompressFilter *)new CByteSwap2();
}
else if (*clsid == CLSID_CCompressConvertByteSwap4)
{
if (!correctInterface)
return E_NOINTERFACE;
coder = (ICompressCoder *)new CByteSwap4();
coder = (ICompressFilter *)new CByteSwap4();
}
else
return CLASS_E_CLASSNOTAVAILABLE;

View File

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,9,2,0
PRODUCTVERSION 3,9,2,0
FILEVERSION 4,7,0,0
PRODUCTVERSION 4,7,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -84,15 +84,15 @@ BEGIN
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "Byte Swap converter \0"
VALUE "FileVersion", "3, 9, 2, 0\0"
VALUE "FileDescription", "Byte Swap filter\0"
VALUE "FileVersion", "4, 7, 0, 0\0"
VALUE "InternalName", "Swap\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2004 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "Swap.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 9, 2, 0\0"
VALUE "ProductVersion", "4, 7, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -113,6 +113,18 @@ SOURCE=.\StdAfx.cpp
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 Source File
SOURCE=.\CopyCoder.cpp

View File

@@ -3,32 +3,38 @@
#include "StdAfx.h"
#include "CopyCoder.h"
#include "../../../Common/Alloc.h"
namespace NCompress {
static const UINT32 kBufferSize = 1 << 17;
CCopyCoder::CCopyCoder():
TotalSize(0)
{
_buffer = new BYTE[kBufferSize];
}
static const UInt32 kBufferSize = 1 << 17;
CCopyCoder::~CCopyCoder()
{
delete []_buffer;
BigFree(_buffer);
}
STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (_buffer == 0)
{
_buffer = (Byte *)BigAlloc(kBufferSize);
if (_buffer == 0)
return E_OUTOFMEMORY;
}
TotalSize = 0;
while(true)
{
UINT32 realProcessedSize;
RINOK(inStream->ReadPart(_buffer, kBufferSize, &realProcessedSize));
UInt32 realProcessedSize;
UInt32 size = kBufferSize;
if (outSize != 0)
if (size > *outSize - TotalSize)
size = (UInt32)(*outSize - TotalSize);
RINOK(inStream->ReadPart(_buffer, size, &realProcessedSize));
if(realProcessedSize == 0)
break;
RINOK(outStream->Write(_buffer, realProcessedSize, NULL));

View File

@@ -1,31 +1,28 @@
// Compress/CopyCoder.h
// #pragma once
#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;
Byte *_buffer;
public:
UINT64 TotalSize;
CCopyCoder();
UInt64 TotalSize;
CCopyCoder(): TotalSize(0) , _buffer(0) {};
~CCopyCoder();
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
};

View File

@@ -2,10 +2,10 @@
#include "StdAfx.h"
#include <initguid.h>
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/ComTry.h"
#include "CopyCoder.h"
#include "../../../Common/ComTry.h"
// {23170F69-40C1-278B-0000-000000000000}
DEFINE_GUID(CLSID_CCompressCopyCoder,

View File

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,8,1,0
PRODUCTVERSION 3,8,1,0
FILEVERSION 4,7,0,0
PRODUCTVERSION 4,7,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -85,14 +85,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "Copy Coder\0"
VALUE "FileVersion", "3, 8, 1, 0\0"
VALUE "FileVersion", "4, 7, 0, 0\0"
VALUE "InternalName", "Copy\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2004 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "Copy.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 8, 1, 0\0"
VALUE "ProductVersion", "4, 7, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -188,6 +188,14 @@ SOURCE=..\..\Common\OutBuffer.h
# 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
@@ -210,6 +218,26 @@ SOURCE=..\..\..\Common\NewHandler.h
# Begin Group "LZ"
# PROP Default_Filter ""
# Begin Group "BinTree"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTree3Z.h
# End Source File
# Begin Source File
SOURCE=..\LZ\BinTree\BinTreeMain.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\LZ\IMatchFinder.h
# End Source File
# Begin Source File
SOURCE=..\LZ\LZInWindow.cpp

View File

@@ -1,7 +1,5 @@
// DeflateConst.h
#pragma once
#ifndef __DEFLATE_CONST_H
#define __DEFLATE_CONST_H
@@ -10,59 +8,59 @@
namespace NCompress {
namespace NDeflate {
const UINT32 kLenTableSize = 29;
const UInt32 kLenTableSize = 29;
const UINT32 kStaticDistTableSize = 32;
const UINT32 kStaticLenTableSize = 31;
const UInt32 kStaticDistTableSize = 32;
const UInt32 kStaticLenTableSize = 31;
const UINT32 kReadTableNumber = 0x100;
const UINT32 kMatchNumber = kReadTableNumber + 1;
const UInt32 kReadTableNumber = 0x100;
const UInt32 kMatchNumber = kReadTableNumber + 1;
const UINT32 kMainTableSize = kMatchNumber + kLenTableSize; //298;
const UINT32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298;
const UInt32 kMainTableSize = kMatchNumber + kLenTableSize; //298;
const UInt32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298;
const UINT32 kDistTableStart = kMainTableSize;
const UInt32 kDistTableStart = kMainTableSize;
const UINT32 kHeapTablesSizesSum32 = kMainTableSize + kDistTableSize32;
const UINT32 kHeapTablesSizesSum64 = kMainTableSize + kDistTableSize64;
const UInt32 kHeapTablesSizesSum32 = kMainTableSize + kDistTableSize32;
const UInt32 kHeapTablesSizesSum64 = kMainTableSize + kDistTableSize64;
const UINT32 kLevelTableSize = 19;
const UInt32 kLevelTableSize = 19;
const UINT32 kMaxTableSize32 = kHeapTablesSizesSum32; // test it
const UINT32 kMaxTableSize64 = kHeapTablesSizesSum64; // test it
const UInt32 kMaxTableSize32 = kHeapTablesSizesSum32; // test it
const UInt32 kMaxTableSize64 = kHeapTablesSizesSum64; // test it
const UINT32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize;
const UInt32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize;
const UINT32 kTableDirectLevels = 16;
const UINT32 kTableLevelRepNumber = kTableDirectLevels;
const UINT32 kTableLevel0Number = kTableLevelRepNumber + 1;
const UINT32 kTableLevel0Number2 = kTableLevel0Number + 1;
const UInt32 kTableDirectLevels = 16;
const UInt32 kTableLevelRepNumber = kTableDirectLevels;
const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
const UINT32 kLevelMask = 0xF;
const UInt32 kLevelMask = 0xF;
const BYTE kLenStart32[kLenTableSize] =
const Byte kLenStart32[kLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255};
const BYTE kLenStart64[kLenTableSize] =
const Byte kLenStart64[kLenTableSize] =
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0};
const BYTE kLenDirectBits32[kLenTableSize] =
const Byte kLenDirectBits32[kLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
const BYTE kLenDirectBits64[kLenTableSize] =
const Byte kLenDirectBits64[kLenTableSize] =
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16};
const UINT32 kDistStart[kDistTableSize64] =
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] =
const Byte kDistDirectBits[kDistTableSize64] =
{0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14};
const BYTE kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
const UINT32 kMatchMinLen = 3;
const UINT32 kMatchMaxLen32 = kNumLenCombinations32 + kMatchMinLen - 1; //256 + 2; test it
const UINT32 kMatchMaxLen64 = kNumLenCombinations64 + kMatchMinLen - 1; //255 + 2; test it
const UInt32 kMatchMinLen = 3;
const UInt32 kMatchMaxLen32 = kNumLenCombinations32 + kMatchMinLen - 1; //256 + 2; test it
const UInt32 kMatchMaxLen64 = kNumLenCombinations64 + kMatchMinLen - 1; //255 + 2; test it
const int kFinalBlockFieldSize = 1;
@@ -88,18 +86,18 @@ namespace NBlockType
};
}
const UINT32 kDeflateNumberOfLengthCodesFieldSize = 5;
const UINT32 kDeflateNumberOfDistanceCodesFieldSize = 5;
const UINT32 kDeflateNumberOfLevelCodesFieldSize = 4;
const UInt32 kDeflateNumberOfLengthCodesFieldSize = 5;
const UInt32 kDeflateNumberOfDistanceCodesFieldSize = 5;
const UInt32 kDeflateNumberOfLevelCodesFieldSize = 4;
const UINT32 kDeflateNumberOfLitLenCodesMin = 257;
const UInt32 kDeflateNumberOfLitLenCodesMin = 257;
const UINT32 kDeflateNumberOfDistanceCodesMin = 1;
const UINT32 kDeflateNumberOfLevelCodesMin = 4;
const UInt32 kDeflateNumberOfDistanceCodesMin = 1;
const UInt32 kDeflateNumberOfLevelCodesMin = 4;
const UINT32 kDeflateLevelCodeFieldSize = 3;
const UInt32 kDeflateLevelCodeFieldSize = 3;
const UINT32 kDeflateStoredBlockLengthFieldSizeSize = 16;
const UInt32 kDeflateStoredBlockLengthFieldSizeSize = 16;
}}

View File

@@ -3,29 +3,21 @@
#include "StdAfx.h"
#include "DeflateDecoder.h"
#include "DeflateConst.h"
#include "Windows/Defs.h"
namespace NCompress {
namespace NDeflate {
namespace NDecoder {
CCoder::CCoder(bool deflate64Mode):
m_MainDecoder(kStaticMainTableSize),
m_DistDecoder(kStaticDistTableSize),
m_LevelDecoder(kLevelTableSize),
_deflate64Mode(deflate64Mode)
{}
CCoder::CCoder(bool deflate64Mode): _deflate64Mode(deflate64Mode) {}
void CCoder::DeCodeLevelTable(BYTE *newLevels, int numLevels)
void CCoder::DeCodeLevelTable(Byte *newLevels, int numLevels)
{
int i = 0;
while (i < numLevels)
{
UINT32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
if (number < kTableDirectLevels)
newLevels[i++] = BYTE(number);
newLevels[i++] = Byte(number);
else
{
if (number == kTableLevelRepNumber)
@@ -62,12 +54,12 @@ void CCoder::ReadTables(void)
case NBlockType::kStored:
{
m_StoredMode = true;
UINT32 currentBitPosition = m_InBitStream.GetBitPosition();
UINT32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0;
UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
UInt32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0;
if (numBitsForAlign > 0)
m_InBitStream.ReadBits(numBitsForAlign);
m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize);
WORD onesComplementReverse = ~WORD(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize));
UInt16 onesComplementReverse = ~(UInt16)(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize));
if (m_StoredBlockSize != onesComplementReverse)
throw CException(CException::kData);
break;
@@ -76,8 +68,8 @@ void CCoder::ReadTables(void)
case NBlockType::kDynamicHuffman:
{
m_StoredMode = false;
BYTE litLenLevels[kStaticMainTableSize];
BYTE distLevels[kStaticDistTableSize];
Byte litLenLevels[kStaticMainTableSize];
Byte distLevels[kStaticDistTableSize];
if (blockType == NBlockType::kFixedHuffman)
{
int i;
@@ -108,13 +100,13 @@ void CCoder::ReadTables(void)
int numLevels = _deflate64Mode ? kHeapTablesSizesSum64 :
kHeapTablesSizesSum32;
BYTE levelLevels[kLevelTableSize];
Byte levelLevels[kLevelTableSize];
int i;
for (i = 0; i < kLevelTableSize; i++)
{
int position = kCodeLengthAlphabetOrder[i];
if(i < numLevelCodes)
levelLevels[position] = BYTE(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize));
levelLevels[position] = Byte(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize));
else
levelLevels[position] = 0;
}
@@ -128,7 +120,7 @@ void CCoder::ReadTables(void)
throw CException(CException::kData);
}
BYTE tmpLevels[kStaticMaxTableSize];
Byte tmpLevels[kStaticMaxTableSize];
DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels);
memmove(litLenLevels, tmpLevels, numLitLenLevels);
@@ -155,23 +147,19 @@ void CCoder::ReadTables(void)
}
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
{
try
{
m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32 /* , kMatchMaxLen */);
}
catch(...)
{
return E_OUTOFMEMORY;
}
}
UINT64 pos = 0;
m_OutWindowStream.Init(outStream, false);
m_InBitStream.Init(inStream);
// CCoderReleaser coderReleaser(this);
if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
return E_OUTOFMEMORY;
if (!m_InBitStream.Create(1 << 17))
return E_OUTOFMEMORY;
UInt64 pos = 0;
m_OutWindowStream.SetStream(outStream);
m_OutWindowStream.Init(false);
m_InBitStream.SetStream(inStream);
m_InBitStream.Init();
CCoderReleaser coderReleaser(this);
m_FinalBlock = false;
@@ -179,14 +167,14 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
{
if (progress != NULL)
{
UINT64 packSize = m_InBitStream.GetProcessedSize();
UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
ReadTables();
if(m_StoredMode)
{
for (UINT32 i = 0; i < m_StoredBlockSize; i++)
m_OutWindowStream.PutOneByte(BYTE(m_InBitStream.ReadBits(8)));
for (UInt32 i = 0; i < m_StoredBlockSize; i++)
m_OutWindowStream.PutByte(Byte(m_InBitStream.ReadBits(8)));
pos += m_StoredBlockSize;
continue;
}
@@ -195,13 +183,13 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
if (m_InBitStream.NumExtraBytes > 4)
throw CException(CException::kData);
UINT32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
if (number < 256)
{
if (outSize != NULL)
if (pos >= *outSize)
throw CException(CException::kData);
m_OutWindowStream.PutOneByte(BYTE(number));
m_OutWindowStream.PutByte(Byte(number));
pos++;
continue;
}
@@ -212,28 +200,28 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
throw CException(CException::kData);
number -= kMatchNumber;
UINT32 length;
UInt32 length;
if (_deflate64Mode)
{
length = UINT32(kLenStart64[number]) + kMatchMinLen;
UINT32 numBits = kLenDirectBits64[number];
length = UInt32(kLenStart64[number]) + kMatchMinLen;
UInt32 numBits = kLenDirectBits64[number];
if (numBits > 0)
length += m_InBitStream.ReadBits(numBits);
}
else
{
length = UINT32(kLenStart32[number]) + kMatchMinLen;
UINT32 numBits = kLenDirectBits32[number];
length = UInt32(kLenStart32[number]) + kMatchMinLen;
UInt32 numBits = kLenDirectBits32[number];
if (numBits > 0)
length += m_InBitStream.ReadBits(numBits);
}
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
UINT32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
if (distance >= pos)
throw "data error";
m_OutWindowStream.CopyBackBlock(distance, length);
m_OutWindowStream.CopyBlock(distance, length);
pos += length;
}
else if (number == kReadTableNumber)
@@ -242,11 +230,12 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
throw CException(CException::kData);
}
}
coderReleaser.NeedFlush = false;
return m_OutWindowStream.Flush();
}
HRESULT CCoder::BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
@@ -255,7 +244,7 @@ HRESULT CCoder::BaseCode(ISequentialInStream *inStream,
catch(...) { return S_FALSE; }
}
HRESULT CCoder::BaseGetInStreamProcessedSize(UINT64 *value)
HRESULT CCoder::BaseGetInStreamProcessedSize(UInt64 *value)
{
if (value == NULL)
return E_INVALIDARG;
@@ -263,25 +252,25 @@ HRESULT CCoder::BaseGetInStreamProcessedSize(UINT64 *value)
return S_OK;
}
STDMETHODIMP CCOMCoder::GetInStreamProcessedSize(UINT64 *value)
STDMETHODIMP CCOMCoder::GetInStreamProcessedSize(UInt64 *value)
{
return BaseGetInStreamProcessedSize(value);
}
HRESULT CCOMCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
return BaseCode(inStream, outStream, inSize, outSize, progress);
}
STDMETHODIMP CCOMCoder64::GetInStreamProcessedSize(UINT64 *value)
STDMETHODIMP CCOMCoder64::GetInStreamProcessedSize(UInt64 *value)
{
return BaseGetInStreamProcessedSize(value);
}
HRESULT CCOMCoder64::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
return BaseCode(inStream, outStream, inSize, outSize, progress);

View File

@@ -1,11 +1,9 @@
// DeflateDecoder.h
#pragma once
#ifndef __DEFLATE_DECODER_H
#define __DEFLATE_DECODER_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/LSBFDecoder.h"
@@ -14,6 +12,7 @@
#include "../Huffman/HuffmanDecoder.h"
#include "DeflateExtConst.h"
#include "DeflateConst.h"
namespace NCompress {
namespace NDeflate {
@@ -30,26 +29,24 @@ public:
};
typedef NStream::NLSBF::CDecoder<CInBuffer> CInBit;
typedef NCompress::NHuffman::CDecoder<kNumHuffmanBits> CHuffmanDecoder;
class CCoder
{
CLZOutWindow m_OutWindowStream;
CInBit m_InBitStream;
CHuffmanDecoder m_MainDecoder;
CHuffmanDecoder m_DistDecoder;
CHuffmanDecoder m_LevelDecoder; // table for decoding other tables;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticMainTableSize> m_MainDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticDistTableSize> m_DistDecoder;
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
bool m_FinalBlock;
bool m_StoredMode;
UINT32 m_StoredBlockSize;
UInt32 m_StoredBlockSize;
bool _deflate64Mode;
void DeCodeLevelTable(BYTE *newLevels, int numLevels);
void DeCodeLevelTable(Byte *newLevels, int numLevels);
void ReadTables();
/*
void CCoder::ReleaseStreams()
{
m_OutWindowStream.ReleaseStream();
@@ -59,29 +56,30 @@ class CCoder
{
CCoder *m_Coder;
public:
CCoderReleaser(CCoder *coder): m_Coder(coder) {}
bool NeedFlush;
CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
~CCoderReleaser()
{
m_Coder->m_OutWindowStream.Flush();
if (NeedFlush)
m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams();
}
};
friend class CCoderReleaser;
*/
public:
CCoder(bool deflate64Mode = false);
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
HRESULT BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// IGetInStreamProcessedSize
HRESULT BaseGetInStreamProcessedSize(UINT64 *aValue);
HRESULT BaseGetInStreamProcessedSize(UInt64 *aValue);
};
class CCOMCoder :
@@ -95,11 +93,11 @@ public:
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// IGetInStreamProcessedSize
STDMETHOD(GetInStreamProcessedSize)(UINT64 *aValue);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *aValue);
CCOMCoder(): CCoder(false) {}
};
@@ -114,11 +112,11 @@ public:
MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// IGetInStreamProcessedSize
STDMETHOD(GetInStreamProcessedSize)(UINT64 *aValue);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *aValue);
CCOMCoder64(): CCoder(true) {}
};

View File

@@ -7,7 +7,8 @@
#include "Windows/Defs.h"
#include "Common/ComTry.h"
#include "../LZ/BinTree/BinTree3ZMain.h"
#include "../../../Common/Alloc.h"
#include "../LZ/BinTree/BinTree3Z.h"
namespace NCompress {
namespace NDeflate {
@@ -25,22 +26,22 @@ static const int kValueBlockSize = 0x2000;
static const int kMaxCodeBitLength = 15;
static const int kMaxLevelBitLength = 7;
static const BYTE kFlagImm = 0;
static const BYTE kFlagLenPos = 4;
static const Byte kFlagImm = 0;
static const Byte kFlagLenPos = 4;
static const UINT32 kMaxUncompressedBlockSize = 0xFFFF; // test it !!!
static const UInt32 kMaxUncompressedBlockSize = 0xFFFF; // test it !!!
static const UINT32 kBlockUncompressedSizeThreshold =
static const UInt32 kBlockUncompressedSizeThreshold =
kMaxUncompressedBlockSize - kMatchMaxLen32 - kNumOpts;
static const int kNumGoodBacks = 0x10000;
static BYTE kNoLiteralDummy = 13;
static BYTE kNoLenDummy = 13;
static BYTE kNoPosDummy = 6;
static Byte kNoLiteralDummy = 13;
static Byte kNoLenDummy = 13;
static Byte kNoPosDummy = 6;
static BYTE g_LenSlots[kNumLenCombinations32];
static BYTE g_FastPos[1 << 9];
static Byte g_LenSlots[kNumLenCombinations32];
static Byte g_FastPos[1 << 9];
class CFastPosInit
{
@@ -53,15 +54,15 @@ public:
int c = kLenStart32[i];
int j = 1 << kLenDirectBits32[i];
for(int k = 0; k < j; k++, c++)
g_LenSlots[c] = i;
g_LenSlots[c] = (Byte)i;
}
const int kFastSlots = 18;
int c = 0;
for (BYTE slotFast = 0; slotFast < kFastSlots; slotFast++)
for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)
{
UINT32 k = (1 << kDistDirectBits[slotFast]);
for (UINT32 j = 0; j < k; j++, c++)
UInt32 k = (1 << kDistDirectBits[slotFast]);
for (UInt32 j = 0; j < k; j++, c++)
g_FastPos[c] = slotFast;
}
}
@@ -70,9 +71,9 @@ public:
static CFastPosInit g_FastPosInit;
inline UINT32 GetPosSlot(UINT32 pos)
inline UInt32 GetPosSlot(UInt32 pos)
{
// for (UINT32 i = 1; pos >= kDistStart[i]; i++);
// for (UInt32 i = 1; pos >= kDistStart[i]; i++);
// return i - 1;
if (pos < 0x200)
return g_FastPos[pos];
@@ -81,11 +82,6 @@ inline UINT32 GetPosSlot(UINT32 pos)
CCoder::CCoder(bool deflate64Mode):
_deflate64Mode(deflate64Mode),
m_MainCoder(kMainTableSize,
deflate64Mode ? kLenDirectBits64 : kLenDirectBits32,
kMatchNumber, kMaxCodeBitLength),
m_DistCoder(deflate64Mode ? kDistTableSize64 : kDistTableSize32, kDistDirectBits, 0, kMaxCodeBitLength),
m_LevelCoder(kLevelTableSize, kLevelDirectBits, 0, kMaxLevelBitLength),
m_NumPasses(1),
m_NumFastBytes(32),
m_OnePosMatchesMemory(0),
@@ -99,47 +95,57 @@ CCoder::CCoder(bool deflate64Mode):
kNumLenCombinations32;
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
m_Values = new CCodeValue[kValueBlockSize + kNumOpts];
}
HRESULT CCoder::Create()
{
COM_TRY_BEGIN
m_MatchFinder.Create(
_deflate64Mode ? kHistorySize64 : kHistorySize32,
kNumOpts + kNumGoodBacks, m_NumFastBytes,
m_MatchMaxLen - m_NumFastBytes);
if (!m_MatchFinder)
{
m_MatchFinder = new NBT3Z::CMatchFinderBinTree;
if (m_MatchFinder == 0)
return E_OUTOFMEMORY;
}
if (m_Values == 0)
{
m_Values = (CCodeValue *)MyAlloc((kValueBlockSize + kNumOpts) * sizeof(CCodeValue));
if (m_Values == 0)
return E_OUTOFMEMORY;
}
RINOK(m_MatchFinder->Create(_deflate64Mode ? kHistorySize64 : kHistorySize32,
kNumOpts + kNumGoodBacks, m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes));
if (!m_OutStream.Create(1 << 20))
return E_OUTOFMEMORY;
m_MatchLengthEdge = m_NumFastBytes + 1;
Free();
if (m_NumPasses > 1)
{
m_OnePosMatchesMemory = new UINT16[kNumGoodBacks * (m_NumFastBytes + 1)];
try
{
m_OnePosMatchesArray = new COnePosMatches[kNumGoodBacks];
}
catch(...)
{
delete []m_OnePosMatchesMemory;
m_OnePosMatchesMemory = 0;
throw;
}
UINT16 *goodBacksWordsCurrent = m_OnePosMatchesMemory;
m_OnePosMatchesMemory = (UInt16 *)BigAlloc(kNumGoodBacks * (m_NumFastBytes + 1) * sizeof(UInt16));
if (m_OnePosMatchesMemory == 0)
return E_OUTOFMEMORY;
m_OnePosMatchesArray = (COnePosMatches *)MyAlloc(kNumGoodBacks * sizeof(COnePosMatches));
if (m_OnePosMatchesArray == 0)
return E_OUTOFMEMORY;
UInt16 *goodBacksWordsCurrent = m_OnePosMatchesMemory;
for(int i = 0; i < kNumGoodBacks; i++, goodBacksWordsCurrent += (m_NumFastBytes + 1))
m_OnePosMatchesArray[i].Init(goodBacksWordsCurrent);
}
else
m_MatchDistances = new UINT16[m_NumFastBytes + 1];
{
m_MatchDistances = (UInt16 *)MyAlloc((m_NumFastBytes + 1) * sizeof(UInt16));
if (m_MatchDistances == 0)
return E_OUTOFMEMORY;
}
return S_OK;
COM_TRY_END
}
// ICompressSetEncoderProperties2
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties)
const PROPVARIANT *properties, UInt32 numProperties)
{
for(UINT32 i = 0; i < numProperties; i++)
for(UInt32 i = 0; i < numProperties; i++)
{
const PROPVARIANT &property = properties[i];
switch(propIDs[i])
@@ -171,52 +177,52 @@ void CCoder::Free()
{
if (m_NumPasses > 1)
{
delete []m_OnePosMatchesMemory;
delete []m_OnePosMatchesArray;
BigFree(m_OnePosMatchesMemory);
MyFree(m_OnePosMatchesArray);
}
else
delete []m_MatchDistances;
MyFree(m_MatchDistances);
}
}
CCoder::~CCoder()
{
Free();
delete []m_Values;
MyFree(m_Values);
}
void CCoder::ReadGoodBacks()
{
UINT32 goodIndex;
UInt32 goodIndex;
if (m_NumPasses > 1)
{
goodIndex = m_FinderPos % kNumGoodBacks;
m_MatchDistances = m_OnePosMatchesArray[goodIndex].MatchDistances;
}
UINT32 distanceTmp[kMatchMaxLen32 + 1];
UINT32 len = m_MatchFinder.GetLongestMatch(distanceTmp);
for(UINT32 i = kMatchMinLen; i <= len; i++)
m_MatchDistances[i] = distanceTmp[i];
UInt32 distanceTmp[kMatchMaxLen32 + 1];
UInt32 len = m_MatchFinder->GetLongestMatch(distanceTmp);
for(UInt32 i = kMatchMinLen; i <= len; i++)
m_MatchDistances[i] = (UInt16)distanceTmp[i];
m_LongestMatchDistance = m_MatchDistances[len];
if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)
m_LongestMatchLength = len + m_MatchFinder.GetMatchLen(len,
m_LongestMatchLength = len + m_MatchFinder->GetMatchLen(len,
m_LongestMatchDistance, m_MatchMaxLen - len);
else
m_LongestMatchLength = len;
if (m_NumPasses > 1)
{
m_OnePosMatchesArray[goodIndex].LongestMatchDistance = UINT16(m_LongestMatchDistance);
m_OnePosMatchesArray[goodIndex].LongestMatchLength = UINT16(m_LongestMatchLength);
m_OnePosMatchesArray[goodIndex].LongestMatchDistance = UInt16(m_LongestMatchDistance);
m_OnePosMatchesArray[goodIndex].LongestMatchLength = UInt16(m_LongestMatchLength);
}
HRESULT result = m_MatchFinder.MovePos();
HRESULT result = m_MatchFinder->MovePos();
if (result != S_OK)
throw CMatchFinderException(result);
m_FinderPos++;
m_AdditionalOffset++;
}
void CCoder::GetBacks(UINT32 pos)
void CCoder::GetBacks(UInt32 pos)
{
if(pos == m_FinderPos)
ReadGoodBacks();
@@ -230,7 +236,7 @@ void CCoder::GetBacks(UINT32 pos)
}
else
{
UINT32 goodIndex = pos % kNumGoodBacks;
UInt32 goodIndex = pos % kNumGoodBacks;
m_MatchDistances = m_OnePosMatchesArray[goodIndex].MatchDistances;
m_LongestMatchDistance = m_OnePosMatchesArray[goodIndex].LongestMatchDistance;
m_LongestMatchLength = m_OnePosMatchesArray[goodIndex].LongestMatchLength;
@@ -239,19 +245,19 @@ void CCoder::GetBacks(UINT32 pos)
}
void CCoder::MovePos(UINT32 num)
void CCoder::MovePos(UInt32 num)
{
if (m_NumPasses > 1)
{
for(UINT32 i = 0; i < num; i++)
GetBacks(UINT32(m_BlockStartPostion + m_CurrentBlockUncompressedSize + i + 1));
for(UInt32 i = 0; i < num; i++)
GetBacks(UInt32(m_BlockStartPostion + m_CurrentBlockUncompressedSize + i + 1));
}
else
{
for (;num > 0; num--)
{
m_MatchFinder.DummyLongestMatch();
HRESULT result = m_MatchFinder.MovePos();
m_MatchFinder->DummyLongestMatch();
HRESULT result = m_MatchFinder->MovePos();
if (result != S_OK)
throw CMatchFinderException(result);
m_FinderPos++;
@@ -260,21 +266,21 @@ void CCoder::MovePos(UINT32 num)
}
}
static const UINT32 kIfinityPrice = 0xFFFFFFF;
static const UInt32 kIfinityPrice = 0xFFFFFFF;
UINT32 CCoder::Backward(UINT32 &backRes, UINT32 cur)
UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur)
{
m_OptimumEndIndex = cur;
UINT32 posMem = m_Optimum[cur].PosPrev;
UINT16 backMem = m_Optimum[cur].BackPrev;
UInt32 posMem = m_Optimum[cur].PosPrev;
UInt16 backMem = m_Optimum[cur].BackPrev;
do
{
UINT32 posPrev = posMem;
UINT16 backCur = backMem;
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 = cur;
m_Optimum[posPrev].PosPrev = (UInt16)cur;
cur = posPrev;
}
while(cur > 0);
@@ -283,11 +289,11 @@ UINT32 CCoder::Backward(UINT32 &backRes, UINT32 cur)
return m_OptimumCurrentIndex;
}
UINT32 CCoder::GetOptimal(UINT32 &backRes)
UInt32 CCoder::GetOptimal(UInt32 &backRes)
{
if(m_OptimumEndIndex != m_OptimumCurrentIndex)
{
UINT32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - 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;
@@ -295,10 +301,10 @@ UINT32 CCoder::GetOptimal(UINT32 &backRes)
m_OptimumCurrentIndex = 0;
m_OptimumEndIndex = 0;
GetBacks(UINT32(m_BlockStartPostion + m_CurrentBlockUncompressedSize));
GetBacks(UInt32(m_BlockStartPostion + m_CurrentBlockUncompressedSize));
UINT32 lenMain = m_LongestMatchLength;
UINT32 backMain = m_LongestMatchDistance;
UInt32 lenMain = m_LongestMatchLength;
UInt32 backMain = m_LongestMatchDistance;
if(lenMain < kMatchMinLen)
return 1;
@@ -308,13 +314,13 @@ UINT32 CCoder::GetOptimal(UINT32 &backRes)
MovePos(lenMain - 1);
return lenMain;
}
m_Optimum[1].Price = m_LiteralPrices[m_MatchFinder.GetIndexByte(0 - m_AdditionalOffset)];
m_Optimum[1].Price = m_LiteralPrices[m_MatchFinder->GetIndexByte(0 - m_AdditionalOffset)];
m_Optimum[1].PosPrev = 0;
m_Optimum[2].Price = kIfinityPrice;
m_Optimum[2].PosPrev = 1;
for(UINT32 i = kMatchMinLen; i <= lenMain; i++)
for(UInt32 i = kMatchMinLen; i <= lenMain; i++)
{
m_Optimum[i].PosPrev = 0;
m_Optimum[i].BackPrev = m_MatchDistances[i];
@@ -322,26 +328,26 @@ UINT32 CCoder::GetOptimal(UINT32 &backRes)
}
UINT32 cur = 0;
UINT32 lenEnd = lenMain;
UInt32 cur = 0;
UInt32 lenEnd = lenMain;
while(true)
{
cur++;
if(cur == lenEnd)
return Backward(backRes, cur);
GetBacks(UINT32(m_BlockStartPostion + m_CurrentBlockUncompressedSize + cur));
UINT32 newLen = m_LongestMatchLength;
GetBacks(UInt32(m_BlockStartPostion + m_CurrentBlockUncompressedSize + cur));
UInt32 newLen = m_LongestMatchLength;
if(newLen >= m_MatchLengthEdge)
return Backward(backRes, cur);
UINT32 curPrice = m_Optimum[cur].Price;
UINT32 curAnd1Price = curPrice +
m_LiteralPrices[m_MatchFinder.GetIndexByte(cur - m_AdditionalOffset)];
UInt32 curPrice = m_Optimum[cur].Price;
UInt32 curAnd1Price = curPrice +
m_LiteralPrices[m_MatchFinder->GetIndexByte(cur - m_AdditionalOffset)];
COptimal &optimum = m_Optimum[cur + 1];
if (curAnd1Price < optimum.Price)
{
optimum.Price = curAnd1Price;
optimum.PosPrev = cur;
optimum.PosPrev = (UInt16)cur;
}
if (newLen < kMatchMinLen)
continue;
@@ -349,24 +355,24 @@ UINT32 CCoder::GetOptimal(UINT32 &backRes)
{
if (cur + newLen > kNumOpts - 1)
newLen = kNumOpts - 1 - cur;
UINT32 lenEndNew = cur + newLen;
UInt32 lenEndNew = cur + newLen;
if (lenEnd < lenEndNew)
{
for(UINT32 i = lenEnd + 1; i <= lenEndNew; i++)
for(UInt32 i = lenEnd + 1; i <= lenEndNew; i++)
m_Optimum[i].Price = kIfinityPrice;
lenEnd = lenEndNew;
}
}
for(UINT32 lenTest = kMatchMinLen; lenTest <= newLen; lenTest++)
for(UInt32 lenTest = kMatchMinLen; lenTest <= newLen; lenTest++)
{
UINT16 curBack = m_MatchDistances[lenTest];
UINT32 curAndLenPrice = curPrice +
UInt16 curBack = m_MatchDistances[lenTest];
UInt32 curAndLenPrice = curPrice +
m_LenPrices[lenTest - kMatchMinLen] + m_PosPrices[GetPosSlot(curBack)];
COptimal &optimum = m_Optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
optimum.PosPrev = cur;
optimum.PosPrev = (UInt16)cur;
optimum.BackPrev = curBack;
}
}
@@ -389,13 +395,13 @@ void CCoder::InitStructures()
m_MainCoder.StartNewBlock();
m_DistCoder.StartNewBlock();
UINT32 i;
UInt32 i;
for(i = 0; i < 256; i++)
m_LiteralPrices[i] = 8;
for(i = 0; i < m_NumLenCombinations; i++)
m_LenPrices[i] = 5 + m_LenDirectBits[g_LenSlots[i]]; // test it
m_LenPrices[i] = (Byte)(5 + m_LenDirectBits[g_LenSlots[i]]); // test it
for(i = 0; i < kDistTableSize64; i++)
m_PosPrices[i] = 5 + kDistDirectBits[i];
m_PosPrices[i] = (Byte)(5 + kDistDirectBits[i]);
}
void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
@@ -407,27 +413,27 @@ void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
{
if(method == NBlockType::kStored)
{
for(UINT32 i = 0; i < m_CurrentBlockUncompressedSize; i++)
for(UInt32 i = 0; i < m_CurrentBlockUncompressedSize; i++)
{
BYTE b = m_MatchFinder.GetIndexByte(i - m_AdditionalOffset -
Byte b = m_MatchFinder->GetIndexByte(i - m_AdditionalOffset -
m_CurrentBlockUncompressedSize);
m_OutStream.WriteBits(b, 8);
}
}
else
{
for (UINT32 i = 0; i < m_ValueIndex; i++)
for (UInt32 i = 0; i < m_ValueIndex; i++)
{
if (m_Values[i].Flag == kFlagImm)
m_MainCoder.CodeOneValue(&m_ReverseOutStream, m_Values[i].Imm);
else if (m_Values[i].Flag == kFlagLenPos)
{
UINT32 len = m_Values[i].Len;
UINT32 lenSlot = g_LenSlots[len];
UInt32 len = m_Values[i].Len;
UInt32 lenSlot = g_LenSlots[len];
m_MainCoder.CodeOneValue(&m_ReverseOutStream, kMatchNumber + lenSlot);
m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]);
UINT32 dist = m_Values[i].Pos;
UINT32 posSlot = GetPosSlot(dist);
UInt32 dist = m_Values[i].Pos;
UInt32 posSlot = GetPosSlot(dist);
m_DistCoder.CodeOneValue(&m_ReverseOutStream, posSlot);
m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]);
}
@@ -438,7 +444,7 @@ void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
m_MainCoder.StartNewBlock();
m_DistCoder.StartNewBlock();
m_ValueIndex = 0;
UINT32 i;
UInt32 i;
for(i = 0; i < 256; i++)
if(m_LastLevels[i] != 0)
m_LiteralPrices[i] = m_LastLevels[i];
@@ -449,8 +455,8 @@ void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
for(i = 0; i < m_NumLenCombinations; i++)
{
UINT32 slot = g_LenSlots[i];
BYTE dummy = m_LastLevels[kMatchNumber + slot];
UInt32 slot = g_LenSlots[i];
Byte dummy = m_LastLevels[kMatchNumber + slot];
if (dummy != 0)
m_LenPrices[i] = dummy;
else
@@ -459,7 +465,7 @@ void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
}
for(i = 0; i < kDistTableSize64; i++)
{
BYTE dummy = m_LastLevels[kDistTableStart + i];
Byte dummy = m_LastLevels[kDistTableStart + i];
if (dummy != 0)
m_PosPrices[i] = dummy;
else
@@ -468,7 +474,7 @@ void CCoder::WriteBlockData(bool writeMode, bool finalBlock)
}
}
void CCoder::CodeLevelTable(BYTE *newLevels, int numLevels, bool codeMode)
void CCoder::CodeLevelTable(Byte *newLevels, int numLevels, bool codeMode)
{
int prevLen = 0xFF; // last emitted length
int nextLen = newLevels[0]; // length of next code
@@ -480,7 +486,7 @@ void CCoder::CodeLevelTable(BYTE *newLevels, int numLevels, bool codeMode)
maxCount = 138;
minCount = 3;
}
BYTE oldValueInGuardElement = newLevels[numLevels]; // push guard value
Byte oldValueInGuardElement = newLevels[numLevels]; // push guard value
try
{
newLevels[numLevels] = 0xFF; // guard already set
@@ -568,7 +574,7 @@ void CCoder::CodeLevelTable(BYTE *newLevels, int numLevels, bool codeMode)
int CCoder::WriteTables(bool writeMode, bool finalBlock)
{
BYTE newLevels[kMaxTableSize64 + 1]; // (+ 1) for guard
Byte newLevels[kMaxTableSize64 + 1]; // (+ 1) for guard
m_MainCoder.BuildTree(&newLevels[0]);
m_DistCoder.BuildTree(&newLevels[kDistTableStart]);
@@ -604,22 +610,22 @@ int CCoder::WriteTables(bool writeMode, bool finalBlock)
memcpy(m_LastLevels, newLevels, kMaxTableSize64);
BYTE levelLevels[kLevelTableSize];
Byte levelLevels[kLevelTableSize];
m_LevelCoder.BuildTree(levelLevels);
BYTE levelLevelsStream[kLevelTableSize];
Byte levelLevelsStream[kLevelTableSize];
int numLevelCodes = kDeflateNumberOfLevelCodesMin;
int i;
for (i = 0; i < kLevelTableSize; i++)
{
int streamPos = kCodeLengthAlphabetOrder[i];
int level = levelLevels[streamPos];
Byte level = levelLevels[streamPos];
if (level > 0 && i >= numLevelCodes)
numLevelCodes = i + 1;
levelLevelsStream[i] = level;
}
UINT32 numLZHuffmanBits = m_MainCoder.GetBlockBitLength();
UInt32 numLZHuffmanBits = m_MainCoder.GetBlockBitLength();
numLZHuffmanBits += m_DistCoder.GetBlockBitLength();
numLZHuffmanBits += m_LevelCoder.GetBlockBitLength();
numLZHuffmanBits += kDeflateNumberOfLengthCodesFieldSize +
@@ -627,18 +633,18 @@ int CCoder::WriteTables(bool writeMode, bool finalBlock)
kDeflateNumberOfLevelCodesFieldSize;
numLZHuffmanBits += numLevelCodes * kDeflateLevelCodeFieldSize;
UINT32 nextBitPosition =
UInt32 nextBitPosition =
(m_OutStream.GetBitPosition() + kBlockTypeFieldSize) % 8;
UINT32 numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
UInt32 numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
UINT32 numStoreBits = numBitsForAlign + (2 * sizeof(UINT16)) * 8;
UInt32 numStoreBits = numBitsForAlign + (2 * 2) * 8;
numStoreBits += m_CurrentBlockUncompressedSize * 8;
if(numStoreBits < numLZHuffmanBits)
{
m_OutStream.WriteBits(NBlockType::kStored, kBlockTypeFieldSize); // test it
m_OutStream.WriteBits(0, numBitsForAlign); // test it
UINT16 currentBlockUncompressedSize = UINT16(m_CurrentBlockUncompressedSize);
UINT16 currentBlockUncompressedSizeNot = ~currentBlockUncompressedSize;
UInt16 currentBlockUncompressedSize = UInt16(m_CurrentBlockUncompressedSize);
UInt16 currentBlockUncompressedSizeNot = ~currentBlockUncompressedSize;
m_OutStream.WriteBits(currentBlockUncompressedSize, kDeflateStoredBlockLengthFieldSizeSize);
m_OutStream.WriteBits(currentBlockUncompressedSizeNot, kDeflateStoredBlockLengthFieldSizeSize);
return NBlockType::kStored;
@@ -669,23 +675,33 @@ int CCoder::WriteTables(bool writeMode, bool finalBlock)
}
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
if (!m_Created)
{
RINOK(Create());
if (!m_MainCoder.Create(kMainTableSize, _deflate64Mode ? kLenDirectBits64 : kLenDirectBits32,
kMatchNumber, kMaxCodeBitLength))
return E_OUTOFMEMORY;
if (!m_DistCoder.Create(_deflate64Mode ? kDistTableSize64 : kDistTableSize32,
kDistDirectBits, 0, kMaxCodeBitLength))
return E_OUTOFMEMORY;
if (!m_LevelCoder.Create(kLevelTableSize, kLevelDirectBits, 0, kMaxLevelBitLength))
return E_OUTOFMEMORY;
m_Created = true;
}
UINT64 nowPos = 0;
UInt64 nowPos = 0;
m_FinderPos = 0;
RINOK(m_MatchFinder.Init(inStream));
m_OutStream.Init(outStream);
RINOK(m_MatchFinder->Init(inStream));
m_OutStream.SetStream(outStream);
m_OutStream.Init();
m_ReverseOutStream.Init(&m_OutStream);
// CCoderReleaser coderReleaser(this);
CCoderReleaser coderReleaser(this);
InitStructures();
while(true)
@@ -696,29 +712,29 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
{
while(true)
{
noMoreBytes = (m_AdditionalOffset == 0 && m_MatchFinder.GetNumAvailableBytes() == 0);
noMoreBytes = (m_AdditionalOffset == 0 && m_MatchFinder->GetNumAvailableBytes() == 0);
if (((m_CurrentBlockUncompressedSize >= kBlockUncompressedSizeThreshold ||
m_ValueIndex >= kValueBlockSize) &&
(m_OptimumEndIndex == m_OptimumCurrentIndex))
|| noMoreBytes)
break;
UINT32 pos;
UINT32 len = GetOptimal(pos);
UInt32 pos;
UInt32 len = GetOptimal(pos);
if (len >= kMatchMinLen)
{
UINT32 newLen = len - kMatchMinLen;
UInt32 newLen = len - kMatchMinLen;
m_Values[m_ValueIndex].Flag = kFlagLenPos;
m_Values[m_ValueIndex].Len = BYTE(newLen);
UINT32 lenSlot = g_LenSlots[newLen];
m_Values[m_ValueIndex].Len = Byte(newLen);
UInt32 lenSlot = g_LenSlots[newLen];
m_MainCoder.AddSymbol(kMatchNumber + lenSlot);
m_Values[m_ValueIndex].Pos = UINT16(pos);
UINT32 posSlot = GetPosSlot(pos);
m_Values[m_ValueIndex].Pos = UInt16(pos);
UInt32 posSlot = GetPosSlot(pos);
m_DistCoder.AddSymbol(posSlot);
}
else if (len == 1)
{
BYTE b = m_MatchFinder.GetIndexByte(0 - m_AdditionalOffset);
Byte b = m_MatchFinder->GetIndexByte(0 - m_AdditionalOffset);
len = 1;
m_MainCoder.AddSymbol(b);
m_Values[m_ValueIndex].Flag = kFlagImm;
@@ -738,14 +754,14 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
if (writeMode)
break;
nowPos = m_BlockStartPostion;
m_AdditionalOffset = UINT32(m_FinderPos - m_BlockStartPostion);
m_AdditionalOffset = UInt32(m_FinderPos - m_BlockStartPostion);
m_CurrentBlockUncompressedSize = 0;
}
m_BlockStartPostion += m_CurrentBlockUncompressedSize;
m_CurrentBlockUncompressedSize = 0;
if (progress != NULL)
{
UINT64 packSize = m_OutStream.GetProcessedSize();
UInt64 packSize = m_OutStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&nowPos, &packSize));
}
if (noMoreBytes)
@@ -755,7 +771,7 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
}
HRESULT CCoder::BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
@@ -765,21 +781,21 @@ HRESULT CCoder::BaseCode(ISequentialInStream *inStream,
}
STDMETHODIMP CCOMCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
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)
const PROPVARIANT *properties, UInt32 numProperties)
{ return BaseSetEncoderProperties2(propIDs, properties, numProperties); }
STDMETHODIMP CCOMCoder64::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
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)
const PROPVARIANT *properties, UInt32 numProperties)
{ return BaseSetEncoderProperties2(propIDs, properties, numProperties); }
}}}

View File

@@ -1,7 +1,5 @@
// DeflateEncoder.h
#pragma once
#ifndef __DEFLATE_ENCODER_H
#define __DEFLATE_ENCODER_H
@@ -9,7 +7,7 @@
#include "../../ICoder.h"
#include "../../Common/LSBFEncoder.h"
#include "../LZ/BinTree/BinTree3Z.h"
#include "../LZ/IMatchFinder.h"
#include "../Huffman/HuffmanEncoder.h"
#include "DeflateConst.h"
@@ -20,22 +18,22 @@ namespace NEncoder {
struct CCodeValue
{
BYTE Flag;
Byte Flag;
union
{
BYTE Imm;
BYTE Len;
Byte Imm;
Byte Len;
};
UINT16 Pos;
UInt16 Pos;
};
class COnePosMatches
{
public:
UINT16 *MatchDistances;
UINT16 LongestMatchLength;
UINT16 LongestMatchDistance;
void Init(UINT16 *matchDistances)
UInt16 *MatchDistances;
UInt16 LongestMatchLength;
UInt16 LongestMatchDistance;
void Init(UInt16 *matchDistances)
{
MatchDistances = matchDistances;
};
@@ -43,21 +41,20 @@ public:
struct COptimal
{
UINT32 Price;
UINT16 PosPrev;
UINT16 BackPrev;
UInt32 Price;
UInt16 PosPrev;
UInt16 BackPrev;
};
const int kNumOpts = 0x1000;
class CCoder
{
UINT32 m_FinderPos;
UInt32 m_FinderPos;
COptimal m_Optimum[kNumOpts];
// CComPtr<IInWindowStreamMatch> m_MatchFinder;
NBT3Z::CInTree m_MatchFinder;
CMyComPtr<IMatchFinder> m_MatchFinder;
NStream::NLSBF::CEncoder m_OutStream;
NStream::NLSBF::CReverseEncoder m_ReverseOutStream;
@@ -66,93 +63,88 @@ class CCoder
NCompression::NHuffman::CEncoder m_DistCoder;
NCompression::NHuffman::CEncoder m_LevelCoder;
BYTE m_LastLevels[kMaxTableSize64];
Byte m_LastLevels[kMaxTableSize64];
UINT32 m_ValueIndex;
UInt32 m_ValueIndex;
CCodeValue *m_Values;
UINT32 m_OptimumEndIndex;
UINT32 m_OptimumCurrentIndex;
UINT32 m_AdditionalOffset;
UInt32 m_OptimumEndIndex;
UInt32 m_OptimumCurrentIndex;
UInt32 m_AdditionalOffset;
UINT32 m_LongestMatchLength;
UINT32 m_LongestMatchDistance;
UINT16 *m_MatchDistances;
UInt32 m_LongestMatchLength;
UInt32 m_LongestMatchDistance;
UInt16 *m_MatchDistances;
UINT32 m_NumFastBytes;
UINT32 m_MatchLengthEdge;
UInt32 m_NumFastBytes;
UInt32 m_MatchLengthEdge;
BYTE m_LiteralPrices[256];
Byte m_LiteralPrices[256];
BYTE m_LenPrices[kNumLenCombinations32];
BYTE m_PosPrices[kDistTableSize64];
Byte m_LenPrices[kNumLenCombinations32];
Byte m_PosPrices[kDistTableSize64];
UINT32 m_CurrentBlockUncompressedSize;
UInt32 m_CurrentBlockUncompressedSize;
COnePosMatches *m_OnePosMatchesArray;
UINT16 *m_OnePosMatchesMemory;
UInt16 *m_OnePosMatchesMemory;
UINT64 m_BlockStartPostion;
UInt64 m_BlockStartPostion;
int m_NumPasses;
bool m_Created;
bool _deflate64Mode;
UINT32 m_NumLenCombinations;
UINT32 m_MatchMaxLen;
const BYTE *m_LenStart;
const BYTE *m_LenDirectBits;
UInt32 m_NumLenCombinations;
UInt32 m_MatchMaxLen;
const Byte *m_LenStart;
const Byte *m_LenDirectBits;
HRESULT Create();
void Free();
void GetBacks(UINT32 aPos);
void GetBacks(UInt32 aPos);
void ReadGoodBacks();
void MovePos(UINT32 num);
UINT32 Backward(UINT32 &backRes, UINT32 cur);
UINT32 GetOptimal(UINT32 &backRes);
void MovePos(UInt32 num);
UInt32 Backward(UInt32 &backRes, UInt32 cur);
UInt32 GetOptimal(UInt32 &backRes);
void InitStructures();
void CodeLevelTable(BYTE *newLevels, int numLevels, bool codeMode);
void CodeLevelTable(Byte *newLevels, int numLevels, bool codeMode);
int WriteTables(bool writeMode, bool finalBlock);
void CopyBackBlockOp(UINT32 distance, UINT32 length);
void CopyBackBlockOp(UInt32 distance, UInt32 length);
void WriteBlockData(bool writeMode, bool finalBlock);
/*
void CCoder::ReleaseStreams()
{
m_MatchFinder.ReleaseStream();
// m_MatchFinder.ReleaseStream();
m_OutStream.ReleaseStream();
}
class CCoderReleaser
{
CCoder *m_Coder;
public:
CCoderReleaser(CCoder *aCoder): m_Coder(aCoder) {}
~CCoderReleaser()
{
m_Coder->ReleaseStreams();
}
CCoderReleaser(CCoder *coder): m_Coder(coder) {}
~CCoderReleaser() { m_Coder->ReleaseStreams(); }
};
friend class CCoderReleaser;
*/
public:
CCoder(bool deflate64Mode = false);
~CCoder();
HRESULT CodeReal(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
HRESULT BaseCode(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
HRESULT BaseSetEncoderProperties2(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties);
const PROPVARIANT *properties, UInt32 numProperties);
};
///////////////////////////////////////////////////////////////
@@ -167,11 +159,11 @@ public:
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
CCOMCoder(): CCoder(false) {};
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties);
const PROPVARIANT *properties, UInt32 numProperties);
};
class CCOMCoder64 :
@@ -184,11 +176,11 @@ public:
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
CCOMCoder64(): CCoder(true) {};
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// ICompressSetCoderProperties
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UINT32 numProperties);
const PROPVARIANT *properties, UInt32 numProperties);
};

View File

@@ -1,7 +1,5 @@
// DeflateExtConst.h
#pragma once
#ifndef __DEFLATE_EXTCONST_H
#define __DEFLATE_EXTCONST_H
@@ -10,17 +8,17 @@
namespace NCompress {
namespace NDeflate {
// const UINT32 kDistTableSize = 30;
const UINT32 kDistTableSize32 = 30;
const UINT32 kDistTableSize64 = 32;
// const UInt32 kDistTableSize = 30;
const UInt32 kDistTableSize32 = 30;
const UInt32 kDistTableSize64 = 32;
const UINT32 kHistorySize32 = 0x8000;
const UINT32 kHistorySize64 = 0x10000;
const UINT32 kNumLenCombinations32 = 256;
const UINT32 kNumLenCombinations64 = 255;
const UInt32 kHistorySize32 = 0x8000;
const UInt32 kHistorySize64 = 0x10000;
const UInt32 kNumLenCombinations32 = 256;
const UInt32 kNumLenCombinations64 = 255;
// don't change kNumLenCombinations64. It must be less than 255.
const UINT32 kNumHuffmanBits = 15;
const UInt32 kNumHuffmanBits = 15;
}}

View File

@@ -2,11 +2,11 @@
#include "StdAfx.h"
#define INITGUID
#include "Common/MyInitGuid.h"
#include "Common/ComTry.h"
#include "DeflateEncoder.h"
#include "DeflateDecoder.h"
#include "Common/ComTry.h"
// {23170F69-40C1-278B-0401-080000000000}

View File

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

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,9,2,0
PRODUCTVERSION 3,9,2,0
FILEVERSION 4,19,0,0
PRODUCTVERSION 4,19,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -85,14 +85,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", " \0"
VALUE "FileDescription", "Deflate Coder\0"
VALUE "FileVersion", "3, 9, 2, 0\0"
VALUE "FileVersion", "4, 19, 0, 0\0"
VALUE "InternalName", "Deflate\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "Deflate.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 9, 2, 0\0"
VALUE "ProductVersion", "4, 19, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -1,60 +1,42 @@
// Compress/HuffmanDecoder.h
#pragma once
#ifndef __COMPRESS_HUFFMANDECODER_H
#define __COMPRESS_HUFFMANDECODER_H
#include "../../../Common/Types.h"
namespace NCompress {
namespace NHuffman {
class CDecoderException{};
const UINT32 kValueTableBits = 8;
const UInt32 kValueTableBits = 9;
template <int kNumBitsInLongestCode>
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
class CDecoder
{
UINT32 m_Limitits[kNumBitsInLongestCode + 1]; // m_Limitits[i] = value limit for symbols with length = i
UINT32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UINT32 m_NumSymbols;
UINT32 *m_Symbols; // symbols: at first with len = 1 then 2, ... 15.
BYTE m_Lengths[1 << kValueTableBits];
UInt32 m_Limitits[kNumBitsInLongestCode + 1]; // m_Limitits[i] = value limit for symbols with length = i
UInt32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UInt32 m_Symbols[m_NumSymbols]; // symbols: at first with len = 1 then 2, ... 15.
Byte m_Lengths[1 << kValueTableBits];
public:
CDecoder(UINT32 numSymbols):
m_NumSymbols(numSymbols)
{ m_Symbols = new UINT32[m_NumSymbols]; }
~CDecoder()
{ delete []m_Symbols; }
void SetNumSymbols(UINT32 numSymbols)
{ m_NumSymbols = numSymbols; }
void SetCodeLengths(const BYTE *codeLengths);
void SetNumSymbols(UInt32 numSymbols) { m_NumSymbols = numSymbols; }
void SetCodeLengths(const Byte *codeLengths);
template <class TBitDecoder>
UINT32 DecodeSymbol(TBitDecoder *bitStream)
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
UINT32 numBits;
UInt32 numBits;
UINT32 value = bitStream->GetValue(kNumBitsInLongestCode);
UInt32 value = bitStream->GetValue(kNumBitsInLongestCode);
if (value < m_Limitits[kValueTableBits])
numBits = m_Lengths[value >> (kNumBitsInLongestCode - kValueTableBits)];
else if (value < m_Limitits[10])
if (value < m_Limitits[9])
numBits = 9;
else
numBits = 10;
else if (value < m_Limitits[11])
numBits = 11;
else if (value < m_Limitits[12])
numBits = 12;
else
for (numBits = 13; numBits < kNumBitsInLongestCode; numBits++)
for (numBits = kValueTableBits + 1; numBits < kNumBitsInLongestCode; numBits++)
if (value < m_Limitits[numBits])
break;
bitStream->MovePos(numBits);
UINT32 index = m_Positions[numBits] +
UInt32 index = m_Positions[numBits] +
((value - m_Limitits[numBits - 1]) >> (kNumBitsInLongestCode - numBits));
if (index >= m_NumSymbols)
throw CDecoderException(); // test it
@@ -62,27 +44,26 @@ public:
}
};
template <int kNumBitsInLongestCode>
void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
void CDecoder<kNumBitsInLongestCode, m_NumSymbols>::SetCodeLengths(const Byte *codeLengths)
{
int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
int i;
for(i = 1; i <= kNumBitsInLongestCode; i++)
lenCounts[i] = 0;
UINT32 symbol;
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
BYTE codeLength = codeLengths[symbol];
Byte codeLength = codeLengths[symbol];
if (codeLength > kNumBitsInLongestCode)
throw CDecoderException();
lenCounts[codeLength]++;
}
lenCounts[0] = 0;
tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;
UINT32 startPos = 0;
UINT32 index = 0;
const UINT32 kMaxValue = (1 << kNumBitsInLongestCode);
UInt32 startPos = 0;
UInt32 index = 0;
const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);
for (i = 1; i <= kNumBitsInLongestCode; i++)
{
startPos += lenCounts[i] << (kNumBitsInLongestCode - i);
@@ -94,8 +75,8 @@ void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
if(i <= kValueTableBits)
{
UINT32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
memset(m_Lengths + index, BYTE(i), limit - index);
UInt32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
memset(m_Lengths + index, Byte(i), limit - index);
index = limit;
}
}

View File

@@ -4,41 +4,63 @@
#include "HuffmanEncoder.h"
#include "Common/Defs.h"
#include "Common/Alloc.h"
namespace NCompression {
namespace NHuffman {
static const char *kIncorrectBitLenCountsMessage = "Incorrect bit len counts";
CEncoder::CEncoder(UINT32 numSymbols,
const BYTE *extraBits, UINT32 extraBase, UINT32 maxLength):
m_NumSymbols(numSymbols),
m_ExtraBits(extraBits),
m_ExtraBase(extraBase),
m_MaxLength(maxLength),
m_HeapSize(numSymbols * 2+ 1)
CEncoder::CEncoder():
m_Items(0),
m_Heap(0),
m_Depth(0)
{}
void CEncoder::Free()
{
m_Items = new CItem[m_HeapSize];
m_Heap = new UINT32[m_HeapSize];
m_Depth = new BYTE[m_HeapSize];
MyFree(m_Items);
MyFree(m_Heap);
MyFree(m_Depth);
m_Items = 0;
m_Heap = 0;
m_Depth = 0;
}
bool CEncoder::Create(UInt32 numSymbols,
const Byte *extraBits, UInt32 extraBase, UInt32 maxLength)
{
m_NumSymbols = numSymbols;
m_ExtraBits = extraBits;
m_ExtraBase = extraBase;
m_MaxLength = maxLength;
m_HeapSize = numSymbols * 2 + 1;
Free();
m_Items = (CItem *)MyAlloc(m_HeapSize * sizeof(CItem));
m_Heap = (UInt32 *)MyAlloc(m_HeapSize * sizeof(UInt32));
m_Depth = (Byte *)MyAlloc(m_HeapSize * sizeof(Byte));
if (m_Items == 0 || m_Heap == 0 || m_Depth == 0)
{
Free();
return false;
}
return true;
}
CEncoder::~CEncoder()
{
delete []m_Depth;
delete []m_Heap;
delete []m_Items;
Free();
}
void CEncoder::StartNewBlock()
{
for (UINT32 i = 0; i < m_NumSymbols; i++)
for (UInt32 i = 0; i < m_NumSymbols; i++)
m_Items[i].Freq = 0;
}
void CEncoder::SetFreqs(const UINT32 *freqs)
void CEncoder::SetFreqs(const UInt32 *freqs)
{
for (UINT32 i = 0; i < m_NumSymbols; i++)
for (UInt32 i = 0; i < m_NumSymbols; i++)
m_Items[i].Freq = freqs[i];
}
@@ -48,9 +70,9 @@ static const int kSmallest = 1;
// Remove the smallest element from the heap and recreate the heap with
// one less element. Updates heap and m_HeapLength.
UINT32 CEncoder::RemoveSmallest()
UInt32 CEncoder::RemoveSmallest()
{
UINT32 top = m_Heap[kSmallest];
UInt32 top = m_Heap[kSmallest];
m_Heap[kSmallest] = m_Heap[m_HeapLength--];
DownHeap(kSmallest);
return top;
@@ -72,15 +94,15 @@ bool CEncoder::Smaller(int n, int m)
// when the m_Heap property is re-established (each father CompareFreqs than its
// two sons).
void CEncoder::DownHeap(UINT32 k)
void CEncoder::DownHeap(UInt32 k)
{
UINT32 symbol = m_Heap[k];
for (UINT32 j = k << 1; j <= m_HeapLength;) // j: left son of k
UInt32 symbol = m_Heap[k];
for (UInt32 j = k << 1; j <= m_HeapLength;) // j: left son of k
{
// Set j to the smallest of the two sons:
if (j < m_HeapLength && Smaller(m_Heap[j+1], m_Heap[j]))
j++;
UINT32 htemp = m_Heap[j]; // htemp required because of bug in SASC compiler
UInt32 htemp = m_Heap[j]; // htemp required because of bug in SASC compiler
if (Smaller(symbol, htemp)) // Exit if v is smaller than both sons
break;
m_Heap[k] = htemp; // Exchange v with the smallest son
@@ -100,22 +122,22 @@ void CEncoder::DownHeap(UINT32 k)
// The length m_BlockBitLength is updated; static_len is also updated if stree is
// not null.
void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
void CEncoder::GenerateBitLen(UInt32 maxCode, UInt32 heapMax)
{
int overflow = 0; // number of elements with bit length too large
for (UINT32 i = 0; i <= kNumBitsInLongestCode; i++)
for (UInt32 i = 0; i <= kNumBitsInLongestCode; i++)
m_BitLenCounters[i] = 0;
/* In a first pass, compute the optimal bit lengths (which may
* overflow in the case of the bit length tree).
*/
m_Items[m_Heap[heapMax]].Len = 0; /* root of the heap */
UINT32 h; /* heap index */
UInt32 h; /* heap index */
for (h = heapMax+1; h < m_HeapSize; h++)
{
UINT32 symbol = m_Heap[h];
UINT32 len = m_Items[m_Items[symbol].Dad].Len + 1;
UInt32 symbol = m_Heap[h];
UInt32 len = m_Items[m_Items[symbol].Dad].Len + 1;
if (len > m_MaxLength)
{
len = m_MaxLength;
@@ -125,7 +147,7 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
if (symbol > maxCode)
continue; // not a leaf node
m_BitLenCounters[len]++;
UINT32 extraBits;
UInt32 extraBits;
if (m_ExtraBits != 0 && symbol >= m_ExtraBase)
extraBits = m_ExtraBits[symbol - m_ExtraBase];
else
@@ -139,7 +161,7 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// Find the first bit length which could increase:
do
{
UINT32 bits = m_MaxLength-1;
UInt32 bits = m_MaxLength-1;
while (m_BitLenCounters[bits] == 0)
bits--;
m_BitLenCounters[bits]--; // move one leaf down the m_Items
@@ -155,12 +177,12 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
// lengths instead of fixing only the wrong ones. This idea is taken
// from 'ar' written by Haruhiko Okumura.)
for (UINT32 bits = m_MaxLength; bits != 0; bits--)
for (UInt32 bits = m_MaxLength; bits != 0; bits--)
{
UINT32 numNodes = m_BitLenCounters[bits];
UInt32 numNodes = m_BitLenCounters[bits];
while (numNodes != 0)
{
UINT32 m = m_Heap[--h];
UInt32 m = m_Heap[--h];
if (m > maxCode)
continue;
if (m_Items[m].Len != (unsigned) bits)
@@ -182,22 +204,22 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// OUT assertion: the field code is set for all tree elements of non
// zero code length.
// UINT32 maxCode = largest code with non zero frequency
// UInt32 maxCode = largest code with non zero frequency
void CEncoder::GenerateCodes(UINT32 maxCode)
void CEncoder::GenerateCodes(UInt32 maxCode)
{
UINT32 nextCodes[kNumBitsInLongestCode + 1]; // next code value for each bit length
UINT32 code = 0; // running code value
UInt32 nextCodes[kNumBitsInLongestCode + 1]; // next code value for each bit length
UInt32 code = 0; // running code value
// The distribution counts are first used to generate the code values
// without bit reversal.
for (UINT32 bits = 1; bits <= kNumBitsInLongestCode; bits++)
for (UInt32 bits = 1; bits <= kNumBitsInLongestCode; bits++)
nextCodes[bits] = code = (code + m_BitLenCounters[bits - 1]) << 1;
// Check that the bit counts in m_BitLenCounters are consistent. The last code
// must be all ones.
if (code + m_BitLenCounters[kNumBitsInLongestCode] - 1 != (1 << kNumBitsInLongestCode) - 1)
throw kIncorrectBitLenCountsMessage;
for (UINT32 n = 0; n <= maxCode; n++)
for (UInt32 n = 0; n <= maxCode; n++)
{
int len = m_Items[n].Len;
if (len == 0)
@@ -215,7 +237,7 @@ void CEncoder::GenerateCodes(UINT32 maxCode)
// and corresponding code. The length m_BlockBitLength is updated; static_len is
// also updated if stree is not null. The field max_code is set.
void CEncoder::BuildTree(BYTE *levels)
void CEncoder::BuildTree(Byte *levels)
{
m_BlockBitLength = 0;
int maxCode = -1; // WAS = -1; largest code with non zero frequency */
@@ -226,7 +248,7 @@ void CEncoder::BuildTree(BYTE *levels)
//
m_HeapLength = 0;
UINT32 n; // iterate over m_Heap elements
UInt32 n; // iterate over m_Heap elements
for (n = 0; n < m_NumSymbols; n++)
{
if (m_Items[n].Freq != 0)
@@ -260,18 +282,18 @@ void CEncoder::BuildTree(BYTE *levels)
// Construct the Huffman tree by repeatedly combining the least two
// frequent nodes.
int node = m_NumSymbols; // next internal node of the tree
UINT32 heapMax = m_NumSymbols * 2+ 1;
UInt32 heapMax = m_NumSymbols * 2+ 1;
do
{
n = RemoveSmallest(); /* n = node of least frequency */
UINT32 m = m_Heap[kSmallest]; /* m = node of next least frequency */
UInt32 m = m_Heap[kSmallest]; /* m = node of next least frequency */
m_Heap[--heapMax] = n; /* keep the nodes sorted by frequency */
m_Heap[--heapMax] = m;
// Create a new node father of n and m
m_Items[node].Freq = m_Items[n].Freq + m_Items[m].Freq;
m_Depth[node] = (BYTE) (MyMax(m_Depth[n], m_Depth[m]) + 1);
m_Depth[node] = (Byte) (MyMax(m_Depth[n], m_Depth[m]) + 1);
m_Items[n].Dad = m_Items[m].Dad = node;
// and insert the new node in the m_Heap
m_Heap[kSmallest] = node++;
@@ -290,7 +312,7 @@ void CEncoder::BuildTree(BYTE *levels)
GenerateCodes (maxCode);
for (n = 0; n < m_NumSymbols; n++)
levels[n] = BYTE(m_Items[n].Len);
levels[n] = Byte(m_Items[n].Len);
}
}}

View File

@@ -1,7 +1,5 @@
// Compression/HuffmanEncoder.h
#pragma once
#ifndef __COMPRESSION_HUFFMANENCODER_H
#define __COMPRESSION_HUFFMANENCODER_H
@@ -10,54 +8,58 @@
namespace NCompression {
namespace NHuffman {
const int kNumBitsInLongestCode = 15;
const int kNumBitsInLongestCode = 20;
struct CItem
{
UINT32 Freq;
UINT32 Code;
UINT32 Dad;
UINT32 Len;
UInt32 Freq;
UInt32 Code;
UInt32 Dad;
UInt32 Len;
};
class CEncoder
{
UINT32 m_NumSymbols; // number of symbols in adwSymbol
public:
UInt32 m_NumSymbols; // number of symbols in adwSymbol
CItem *m_Items;
UINT32 *m_Heap;
UINT32 m_HeapSize;
BYTE *m_Depth;
const BYTE *m_ExtraBits;
UINT32 m_ExtraBase;
UINT32 m_MaxLength;
UInt32 *m_Heap;
UInt32 m_HeapSize;
Byte *m_Depth;
const Byte *m_ExtraBits;
UInt32 m_ExtraBase;
UInt32 m_MaxLength;
UINT32 m_HeapLength;
UINT32 m_BitLenCounters[kNumBitsInLongestCode + 1];
UInt32 m_HeapLength;
UInt32 m_BitLenCounters[kNumBitsInLongestCode + 1];
UINT32 RemoveSmallest();
UInt32 RemoveSmallest();
bool Smaller(int n, int m);
void DownHeap(UINT32 k);
void GenerateBitLen(UINT32 maxCode, UINT32 heapMax);
void GenerateCodes(UINT32 maxCode);
void DownHeap(UInt32 k);
void GenerateBitLen(UInt32 maxCode, UInt32 heapMax);
void GenerateCodes(UInt32 maxCode);
UINT32 m_BlockBitLength;
UInt32 m_BlockBitLength;
void Free();
public:
CEncoder(UINT32 numSymbols, const BYTE *extraBits,
UINT32 extraBase, UINT32 maxLength);
CEncoder();
~CEncoder();
bool Create(UInt32 numSymbols, const Byte *extraBits,
UInt32 extraBase, UInt32 maxLength);
void StartNewBlock();
void AddSymbol(UINT32 symbol)
{ m_Items[symbol].Freq++; }
void AddSymbol(UInt32 symbol) { m_Items[symbol].Freq++; }
void SetFreqs(const UINT32 *freqs);
void BuildTree(BYTE *levels);
UINT32 GetBlockBitLength() const { return m_BlockBitLength; }
void SetFreqs(const UInt32 *freqs);
void BuildTree(Byte *levels);
UInt32 GetBlockBitLength() const { return m_BlockBitLength; }
template <class TBitEncoder>
void CodeOneValue(TBitEncoder *bitEncoder, UINT32 symbol)
void CodeOneValue(TBitEncoder *bitEncoder, UInt32 symbol)
{ bitEncoder->WriteBits(m_Items[symbol].Code, m_Items[symbol].Len); }
};

View File

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

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