moved implementation of CLZMA into clzma.cpp
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3704 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
38b693f19a
commit
85b2ea48a3
8 changed files with 474 additions and 426 deletions
|
@ -5,8 +5,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# -- Objects and source files --
|
# -- Objects and source files --
|
||||||
SRCS = zlib/deflate.c zlib/trees.c bzip2/blocksort.c bzip2/bzlib.c bzip2/compress.c bzip2/huffman.c 7zip/7zGuids.cpp 7zip/Common/CRC.cpp 7zip/7zip/Compress/LZ/LZInWindow.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp 7zip/7zip/Common/OutBuffer.cpp 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp 7zip/Common/Alloc.cpp build.cpp crc32.c DialogTemplate.cpp exedata.cpp lang.cpp makenssi.cpp Plugins.cpp ResourceEditor.cpp ResourceVersionInfo.cpp script.cpp tokens.cpp util.cpp strlist.cpp growbuf.cpp mmap.cpp
|
SRCS = zlib/deflate.c zlib/trees.c bzip2/blocksort.c bzip2/bzlib.c bzip2/compress.c bzip2/huffman.c 7zip/7zGuids.cpp 7zip/Common/CRC.cpp 7zip/7zip/Compress/LZ/LZInWindow.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp 7zip/7zip/Common/OutBuffer.cpp 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp 7zip/Common/Alloc.cpp build.cpp crc32.c DialogTemplate.cpp exedata.cpp lang.cpp makenssi.cpp Plugins.cpp ResourceEditor.cpp ResourceVersionInfo.cpp script.cpp tokens.cpp util.cpp strlist.cpp growbuf.cpp mmap.cpp clzma.cpp
|
||||||
OBJS = 7zGuids.o blocksort.o build.o bzlib.o compress.o CRC.o crc32.o deflate.o DialogTemplate.o exedata.o huffman.o lang.o LZInWindow.o LZMAEncoder.o Alloc.o makenssi.o OutBuffer.o Plugins.o RangeCoderBit.o ResourceEditor.o ResourceVersionInfo.o script.o tokens.o trees.o util.o strlist.o growbuf.o mmap.o
|
OBJS = 7zGuids.o blocksort.o build.o bzlib.o compress.o CRC.o crc32.o deflate.o DialogTemplate.o exedata.o huffman.o lang.o LZInWindow.o LZMAEncoder.o Alloc.o makenssi.o OutBuffer.o Plugins.o RangeCoderBit.o ResourceEditor.o ResourceVersionInfo.o script.o tokens.o trees.o util.o strlist.o growbuf.o mmap.o clzma.o
|
||||||
ifeq "$(strip $(findstring i386pe,$(shell ld -V)))" ""
|
ifeq "$(strip $(findstring i386pe,$(shell ld -V)))" ""
|
||||||
LIBS = -lstdc++ -lpthread
|
LIBS = -lstdc++ -lpthread
|
||||||
EXESUFF =
|
EXESUFF =
|
||||||
|
|
|
@ -33,22 +33,6 @@ using namespace std;
|
||||||
return rc; \
|
return rc; \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
|
|
||||||
#ifdef _WIN32
|
|
||||||
DWORD WINAPI lzmaCompressThread(LPVOID lpParameter)
|
|
||||||
#else
|
|
||||||
void *lzmaCompressThread(void *lpParameter)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
CLZMA *Compressor = (CLZMA *) lpParameter;
|
|
||||||
if (!Compressor)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Compressor->CompressReal();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace { // begin anonymous namespace
|
namespace { // begin anonymous namespace
|
||||||
|
|
||||||
bool isSimpleChar(char ch)
|
bool isSimpleChar(char ch)
|
||||||
|
@ -2768,7 +2752,7 @@ int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush
|
||||||
build_compressor_set=true;
|
build_compressor_set=true;
|
||||||
|
|
||||||
char obuf[65536];
|
char obuf[65536];
|
||||||
int flush=0;
|
bool flush=false;
|
||||||
compressor->SetNextIn(buf,len);
|
compressor->SetNextIn(buf,len);
|
||||||
if (!buf||!len)
|
if (!buf||!len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ class CBzip2 : public ICompressor {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Compress(BOOL finish) {
|
int Compress(bool finish) {
|
||||||
// act like zlib when it comes to stream ending
|
// act like zlib when it comes to stream ending
|
||||||
if (last_ret == BZ_STREAM_END && finish)
|
if (last_ret == BZ_STREAM_END && finish)
|
||||||
return BZ_STREAM_END;
|
return BZ_STREAM_END;
|
||||||
|
|
437
Source/clzma.cpp
Normal file
437
Source/clzma.cpp
Normal file
|
@ -0,0 +1,437 @@
|
||||||
|
#include "clzma.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct evnet_t
|
||||||
|
{
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
bool signaled;
|
||||||
|
};
|
||||||
|
|
||||||
|
HANDLE CreateEvent(void *, BOOL, BOOL, char *)
|
||||||
|
{
|
||||||
|
evnet_t *event = (evnet_t *) malloc(sizeof(evnet_t));
|
||||||
|
if (!event)
|
||||||
|
return 0;
|
||||||
|
if (pthread_cond_init(&event->cond, NULL))
|
||||||
|
{
|
||||||
|
free(event);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (pthread_mutex_init(&event->mutex, NULL))
|
||||||
|
{
|
||||||
|
free(event);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
event->signaled = false;
|
||||||
|
return (HANDLE) event;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SetEvent(HANDLE _event)
|
||||||
|
{
|
||||||
|
evnet_t *event = (evnet_t *) _event;
|
||||||
|
if (pthread_mutex_lock(&event->mutex))
|
||||||
|
return FALSE;
|
||||||
|
event->signaled = true;
|
||||||
|
pthread_cond_signal(&event->cond);
|
||||||
|
if (pthread_mutex_unlock(&event->mutex))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ResetEvent(HANDLE _event)
|
||||||
|
{
|
||||||
|
evnet_t *event = (evnet_t *) _event;
|
||||||
|
event->signaled = false;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CloseHandle(HANDLE _event)
|
||||||
|
{
|
||||||
|
BOOL ret = TRUE;
|
||||||
|
evnet_t *event = (evnet_t *) _event;
|
||||||
|
if (event)
|
||||||
|
return FALSE;
|
||||||
|
if (pthread_cond_destroy(&event->cond))
|
||||||
|
ret = FALSE;
|
||||||
|
if (pthread_mutex_destroy(&event->mutex))
|
||||||
|
ret = FALSE;
|
||||||
|
free(event);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WAIT_OBJECT_0 0
|
||||||
|
#define INFINITE 0
|
||||||
|
DWORD WaitForSingleObject(HANDLE _event, DWORD) {
|
||||||
|
DWORD ret = WAIT_OBJECT_0;
|
||||||
|
evnet_t *event = (evnet_t *) _event;
|
||||||
|
if (!event->signaled)
|
||||||
|
{
|
||||||
|
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
if (pthread_mutex_lock(&m) || pthread_cond_wait(&event->cond, &m))
|
||||||
|
{
|
||||||
|
ret = !WAIT_OBJECT_0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&m);
|
||||||
|
pthread_mutex_destroy(&m);
|
||||||
|
}
|
||||||
|
if (pthread_mutex_lock(&event->mutex))
|
||||||
|
return !WAIT_OBJECT_0;
|
||||||
|
event->signaled = false;
|
||||||
|
if (pthread_mutex_unlock(&event->mutex))
|
||||||
|
return !WAIT_OBJECT_0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WaitForMultipleObjects(x, list, y, t) WaitForSingleObject(list[0], t)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD CLZMA::lzmaCompressThread(LPVOID lpParameter)
|
||||||
|
#else
|
||||||
|
void* CLZMA::lzmaCompressThread(void *lpParameter)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CLZMA *Compressor = (CLZMA *) lpParameter;
|
||||||
|
if (!Compressor)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Compressor->CompressReal();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::ConvertError(HRESULT result)
|
||||||
|
{
|
||||||
|
if (result != S_OK)
|
||||||
|
{
|
||||||
|
if (result == E_OUTOFMEMORY)
|
||||||
|
return LZMA_MEM_ERROR;
|
||||||
|
else
|
||||||
|
return LZMA_IO_ERROR;
|
||||||
|
}
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLZMA::CLZMA(): _encoder(NULL)
|
||||||
|
{
|
||||||
|
_encoder = new NCompress::NLZMA::CEncoder();
|
||||||
|
_encoder->SetWriteEndMarkerMode(true);
|
||||||
|
#ifdef _WIN32
|
||||||
|
hCompressionThread = NULL;
|
||||||
|
#else
|
||||||
|
hCompressionThread = 0;
|
||||||
|
#endif
|
||||||
|
hNeedIOEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
hIOReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
finish = FALSE;
|
||||||
|
compressor_finished = TRUE;
|
||||||
|
hCompressionThread = 0;
|
||||||
|
SetNextOut(NULL, 0);
|
||||||
|
SetNextIn(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLZMA::~CLZMA()
|
||||||
|
{
|
||||||
|
End();
|
||||||
|
if (hNeedIOEvent)
|
||||||
|
CloseHandle(hNeedIOEvent);
|
||||||
|
if (hIOReadyEvent)
|
||||||
|
CloseHandle(hIOReadyEvent);
|
||||||
|
if (_encoder)
|
||||||
|
{
|
||||||
|
delete _encoder;
|
||||||
|
_encoder = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::Init(int level, UINT32 dicSize)
|
||||||
|
{
|
||||||
|
End();
|
||||||
|
|
||||||
|
compressor_finished = FALSE;
|
||||||
|
finish = FALSE;
|
||||||
|
res = C_OK;
|
||||||
|
|
||||||
|
if (!hNeedIOEvent || !hIOReadyEvent)
|
||||||
|
{
|
||||||
|
return LZMA_INIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetEvent(hNeedIOEvent);
|
||||||
|
ResetEvent(hIOReadyEvent);
|
||||||
|
|
||||||
|
res = C_OK;
|
||||||
|
|
||||||
|
PROPID propdIDs [] =
|
||||||
|
{
|
||||||
|
NCoderPropID::kAlgorithm,
|
||||||
|
NCoderPropID::kDictionarySize,
|
||||||
|
NCoderPropID::kNumFastBytes
|
||||||
|
};
|
||||||
|
const int kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]);
|
||||||
|
PROPVARIANT props[kNumProps];
|
||||||
|
// NCoderPropID::kAlgorithm
|
||||||
|
props[0].vt = VT_UI4;
|
||||||
|
props[0].ulVal = 2;
|
||||||
|
// NCoderPropID::kDictionarySize
|
||||||
|
props[1].vt = VT_UI4;
|
||||||
|
props[1].ulVal = dicSize;
|
||||||
|
// NCoderPropID::kNumFastBytes
|
||||||
|
props[2].vt = VT_UI4;
|
||||||
|
props[2].ulVal = 64;
|
||||||
|
if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0)
|
||||||
|
return LZMA_INIT_ERROR;
|
||||||
|
return _encoder->SetStreams(this, this, 0, 0) == S_OK ? C_OK : LZMA_INIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::Init(int level)
|
||||||
|
{
|
||||||
|
// default dictionary size is 8MB
|
||||||
|
return Init(level, 8 << 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::End()
|
||||||
|
{
|
||||||
|
// has compressor not finished?
|
||||||
|
if (hCompressionThread && !compressor_finished)
|
||||||
|
{
|
||||||
|
// kill compression thread
|
||||||
|
avail_in = 0;
|
||||||
|
avail_out = 0;
|
||||||
|
compressor_finished = TRUE;
|
||||||
|
|
||||||
|
SetEvent(hIOReadyEvent);
|
||||||
|
#ifdef _WIN32
|
||||||
|
WaitForSingleObject(hCompressionThread, INFINITE);
|
||||||
|
#else
|
||||||
|
pthread_join(hCompressionThread, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (hCompressionThread)
|
||||||
|
{
|
||||||
|
CloseHandle(hCompressionThread);
|
||||||
|
hCompressionThread = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
hCompressionThread = 0;
|
||||||
|
#endif
|
||||||
|
SetNextOut(NULL, 0);
|
||||||
|
SetNextIn(NULL, 0);
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::CompressReal()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HRESULT hResult = _encoder->WriteCoderProperties(this);
|
||||||
|
if (res == S_OK)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
UINT64 inSize, outSize;
|
||||||
|
INT32 finished;
|
||||||
|
res = ConvertError(_encoder->CodeOneBlock(&inSize, &outSize, &finished));
|
||||||
|
if (res != C_OK)
|
||||||
|
break;
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
res = C_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = ConvertError(hResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
res = LZMA_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
compressor_finished = TRUE;
|
||||||
|
SetEvent(hNeedIOEvent);
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLZMA::Compress(bool flush)
|
||||||
|
{
|
||||||
|
if (compressor_finished)
|
||||||
|
{
|
||||||
|
// act like zlib when it comes to stream ending
|
||||||
|
if (flush)
|
||||||
|
return C_OK;
|
||||||
|
else
|
||||||
|
return LZMA_BAD_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
finish = flush;
|
||||||
|
|
||||||
|
if (!hCompressionThread)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD dwThreadId;
|
||||||
|
|
||||||
|
hCompressionThread = CreateThread(0, 0, lzmaCompressThread, (LPVOID) this, 0, &dwThreadId);
|
||||||
|
if (!hCompressionThread)
|
||||||
|
#else
|
||||||
|
if (pthread_create(&hCompressionThread, NULL, lzmaCompressThread, (LPVOID) this))
|
||||||
|
#endif
|
||||||
|
return LZMA_INIT_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetEvent(hIOReadyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE waitList[2] = {hNeedIOEvent, (HANDLE) hCompressionThread};
|
||||||
|
if (WaitForMultipleObjects(2, waitList, FALSE, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
// thread ended or WaitForMultipleObjects failed
|
||||||
|
compressor_finished = TRUE;
|
||||||
|
SetEvent(hIOReadyEvent);
|
||||||
|
return LZMA_THREAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compressor_finished)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLZMA::GetMoreIO()
|
||||||
|
{
|
||||||
|
SetEvent(hNeedIOEvent);
|
||||||
|
if (WaitForSingleObject(hIOReadyEvent, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
compressor_finished = TRUE;
|
||||||
|
res = LZMA_THREAD_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CLZMA::Read(void *data, UINT32 size, UINT32 *processedSize)
|
||||||
|
{
|
||||||
|
return ReadPart(data, size, processedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CLZMA::ReadPart(void *data, UINT32 size, UINT32 *processedSize)
|
||||||
|
{
|
||||||
|
if (processedSize)
|
||||||
|
*processedSize = 0;
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
if (!avail_in)
|
||||||
|
{
|
||||||
|
if (finish)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
GetMoreIO();
|
||||||
|
if (!avail_in)
|
||||||
|
{
|
||||||
|
if (finish)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
if (compressor_finished)
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
UINT32 l = min(size, avail_in);
|
||||||
|
memcpy(data, next_in, l);
|
||||||
|
avail_in -= l;
|
||||||
|
size -= l;
|
||||||
|
next_in += l;
|
||||||
|
data = LPBYTE(data) + l;
|
||||||
|
if (processedSize)
|
||||||
|
*processedSize += l;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CLZMA::Write(const void *data, UINT32 size, UINT32 *processedSize)
|
||||||
|
{
|
||||||
|
return WritePart(data, size, processedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CLZMA::WritePart(const void *data, UINT32 size, UINT32 *processedSize)
|
||||||
|
{
|
||||||
|
if (processedSize)
|
||||||
|
*processedSize = 0;
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
if (!avail_out)
|
||||||
|
{
|
||||||
|
GetMoreIO();
|
||||||
|
if (!avail_out)
|
||||||
|
return E_ABORT;
|
||||||
|
}
|
||||||
|
UINT32 l = min(size, avail_out);
|
||||||
|
memcpy(next_out, data, l);
|
||||||
|
avail_out -= l;
|
||||||
|
size -= l;
|
||||||
|
next_out += l;
|
||||||
|
data = LPBYTE(data) + l;
|
||||||
|
if (processedSize)
|
||||||
|
*processedSize += l;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLZMA::SetNextIn(char *in, unsigned int size)
|
||||||
|
{
|
||||||
|
next_in = (LPBYTE) in;
|
||||||
|
avail_in = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLZMA::SetNextOut(char *out, unsigned int size)
|
||||||
|
{
|
||||||
|
next_out = (LPBYTE) out;
|
||||||
|
avail_out = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* CLZMA::GetNextOut()
|
||||||
|
{
|
||||||
|
return (char *) next_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CLZMA::GetAvailIn()
|
||||||
|
{
|
||||||
|
return avail_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CLZMA::GetAvailOut()
|
||||||
|
{
|
||||||
|
return avail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CLZMA::GetName()
|
||||||
|
{
|
||||||
|
return "lzma";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CLZMA::GetErrStr(int err)
|
||||||
|
{
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case LZMA_BAD_CALL:
|
||||||
|
return "bad call";
|
||||||
|
case LZMA_INIT_ERROR:
|
||||||
|
return "initialization failed";
|
||||||
|
case LZMA_THREAD_ERROR:
|
||||||
|
return "thread synchronization error";
|
||||||
|
case LZMA_IO_ERROR:
|
||||||
|
return "input/output error";
|
||||||
|
case LZMA_MEM_ERROR:
|
||||||
|
return "not enough memory";
|
||||||
|
default:
|
||||||
|
return "unknown error";
|
||||||
|
}
|
||||||
|
}
|
429
Source/clzma.h
429
Source/clzma.h
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __CLZMA_H__
|
#ifndef __CLZMA_H__
|
||||||
#define __CLZMA_H__
|
#define __CLZMA_H__
|
||||||
|
|
||||||
|
#include "Platform.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,13 +13,6 @@
|
||||||
#include "7zip/Common/MyCom.h"
|
#include "7zip/Common/MyCom.h"
|
||||||
#include "7zip/Common/Defs.h"
|
#include "7zip/Common/Defs.h"
|
||||||
|
|
||||||
// implemented in build.cpp - simply calls CompressReal
|
|
||||||
#ifdef _WIN32
|
|
||||||
DWORD WINAPI lzmaCompressThread(LPVOID lpParameter);
|
|
||||||
#else
|
|
||||||
void *lzmaCompressThread(void *arg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_BAD_CALL -1
|
#define LZMA_BAD_CALL -1
|
||||||
#define LZMA_INIT_ERROR -2
|
#define LZMA_INIT_ERROR -2
|
||||||
#define LZMA_THREAD_ERROR -3
|
#define LZMA_THREAD_ERROR -3
|
||||||
|
@ -52,414 +47,42 @@ private:
|
||||||
BOOL finish;
|
BOOL finish;
|
||||||
BOOL compressor_finished;
|
BOOL compressor_finished;
|
||||||
|
|
||||||
#ifndef _WIN32
|
int ConvertError(HRESULT result);
|
||||||
struct evnet_t
|
|
||||||
{
|
|
||||||
pthread_cond_t cond;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
bool signaled;
|
|
||||||
};
|
|
||||||
|
|
||||||
HANDLE CreateEvent(void *, BOOL, BOOL, char *)
|
void GetMoreIO();
|
||||||
{
|
int CompressReal();
|
||||||
evnet_t *event = (evnet_t *) malloc(sizeof(evnet_t));
|
|
||||||
if (!event)
|
|
||||||
return 0;
|
|
||||||
if (pthread_cond_init(&event->cond, NULL))
|
|
||||||
{
|
|
||||||
free(event);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (pthread_mutex_init(&event->mutex, NULL))
|
|
||||||
{
|
|
||||||
free(event);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
event->signaled = false;
|
|
||||||
return (HANDLE) event;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL SetEvent(HANDLE _event)
|
|
||||||
{
|
|
||||||
evnet_t *event = (evnet_t *) _event;
|
|
||||||
if (pthread_mutex_lock(&event->mutex))
|
|
||||||
return FALSE;
|
|
||||||
event->signaled = true;
|
|
||||||
pthread_cond_signal(&event->cond);
|
|
||||||
if (pthread_mutex_unlock(&event->mutex))
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ResetEvent(HANDLE _event)
|
|
||||||
{
|
|
||||||
evnet_t *event = (evnet_t *) _event;
|
|
||||||
event->signaled = false;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CloseHandle(HANDLE _event)
|
|
||||||
{
|
|
||||||
BOOL ret = TRUE;
|
|
||||||
evnet_t *event = (evnet_t *) _event;
|
|
||||||
if (event)
|
|
||||||
return FALSE;
|
|
||||||
if (pthread_cond_destroy(&event->cond))
|
|
||||||
ret = FALSE;
|
|
||||||
if (pthread_mutex_destroy(&event->mutex))
|
|
||||||
ret = FALSE;
|
|
||||||
free(event);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WAIT_OBJECT_0 0
|
|
||||||
#define INFINITE 0
|
|
||||||
DWORD WaitForSingleObject(HANDLE _event, DWORD) {
|
|
||||||
DWORD ret = WAIT_OBJECT_0;
|
|
||||||
evnet_t *event = (evnet_t *) _event;
|
|
||||||
if (!event->signaled)
|
|
||||||
{
|
|
||||||
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
if (pthread_mutex_lock(&m) || pthread_cond_wait(&event->cond, &m))
|
|
||||||
{
|
|
||||||
ret = !WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&m);
|
|
||||||
pthread_mutex_destroy(&m);
|
|
||||||
}
|
|
||||||
if (pthread_mutex_lock(&event->mutex))
|
|
||||||
return !WAIT_OBJECT_0;
|
|
||||||
event->signaled = false;
|
|
||||||
if (pthread_mutex_unlock(&event->mutex))
|
|
||||||
return !WAIT_OBJECT_0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WaitForMultipleObjects(x, list, y, t) WaitForSingleObject(list[0], t)
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static DWORD WINAPI lzmaCompressThread(LPVOID lpParameter);
|
||||||
|
#else
|
||||||
|
static void* lzmaCompressThread(void *lpParameter);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ConvertError(HRESULT result)
|
|
||||||
{
|
|
||||||
if (result != S_OK)
|
|
||||||
{
|
|
||||||
if (result == E_OUTOFMEMORY)
|
|
||||||
return LZMA_MEM_ERROR;
|
|
||||||
else
|
|
||||||
return LZMA_IO_ERROR;
|
|
||||||
}
|
|
||||||
return C_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MY_UNKNOWN_IMP
|
MY_UNKNOWN_IMP
|
||||||
|
|
||||||
CLZMA(): _encoder(NULL)
|
CLZMA();
|
||||||
{
|
virtual ~CLZMA();
|
||||||
_encoder = new NCompress::NLZMA::CEncoder();
|
|
||||||
_encoder->SetWriteEndMarkerMode(true);
|
|
||||||
#ifdef _WIN32
|
|
||||||
hCompressionThread = NULL;
|
|
||||||
#else
|
|
||||||
hCompressionThread = 0;
|
|
||||||
#endif
|
|
||||||
hNeedIOEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
||||||
hIOReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
||||||
finish = FALSE;
|
|
||||||
compressor_finished = TRUE;
|
|
||||||
hCompressionThread = 0;
|
|
||||||
SetNextOut(NULL, 0);
|
|
||||||
SetNextIn(NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~CLZMA()
|
virtual int Init(int level);
|
||||||
{
|
virtual int Init(int level, UINT32 dicSize);
|
||||||
End();
|
virtual int End();
|
||||||
if (hNeedIOEvent)
|
virtual int Compress(bool flush);
|
||||||
CloseHandle(hNeedIOEvent);
|
|
||||||
if (hIOReadyEvent)
|
|
||||||
CloseHandle(hIOReadyEvent);
|
|
||||||
if (_encoder)
|
|
||||||
{
|
|
||||||
delete _encoder;
|
|
||||||
_encoder = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Init(int level, UINT32 dicSize)
|
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
|
||||||
{
|
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
|
||||||
End();
|
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||||
|
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||||
|
|
||||||
compressor_finished = FALSE;
|
virtual void SetNextIn(char *in, unsigned int size);
|
||||||
finish = FALSE;
|
virtual void SetNextOut(char *out, unsigned int size);
|
||||||
res = C_OK;
|
|
||||||
|
|
||||||
if (!hNeedIOEvent || !hIOReadyEvent)
|
virtual char *GetNextOut();
|
||||||
{
|
virtual unsigned int GetAvailIn();
|
||||||
return LZMA_INIT_ERROR;
|
virtual unsigned int GetAvailOut();
|
||||||
}
|
virtual const char *GetName();
|
||||||
|
|
||||||
ResetEvent(hNeedIOEvent);
|
virtual const char* GetErrStr(int err);
|
||||||
ResetEvent(hIOReadyEvent);
|
|
||||||
|
|
||||||
res = C_OK;
|
|
||||||
|
|
||||||
PROPID propdIDs [] =
|
|
||||||
{
|
|
||||||
NCoderPropID::kAlgorithm,
|
|
||||||
NCoderPropID::kDictionarySize,
|
|
||||||
NCoderPropID::kNumFastBytes
|
|
||||||
};
|
|
||||||
const int kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]);
|
|
||||||
PROPVARIANT props[kNumProps];
|
|
||||||
// NCoderPropID::kAlgorithm
|
|
||||||
props[0].vt = VT_UI4;
|
|
||||||
props[0].ulVal = 2;
|
|
||||||
// NCoderPropID::kDictionarySize
|
|
||||||
props[1].vt = VT_UI4;
|
|
||||||
props[1].ulVal = dicSize;
|
|
||||||
// NCoderPropID::kNumFastBytes
|
|
||||||
props[2].vt = VT_UI4;
|
|
||||||
props[2].ulVal = 64;
|
|
||||||
if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0)
|
|
||||||
return LZMA_INIT_ERROR;
|
|
||||||
return _encoder->SetStreams(this, this, 0, 0) == S_OK ? C_OK : LZMA_INIT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Init(int level)
|
|
||||||
{
|
|
||||||
// default dictionary size is 8MB
|
|
||||||
return Init(level, 8 << 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
int End()
|
|
||||||
{
|
|
||||||
// has compressor not finished?
|
|
||||||
if (hCompressionThread && !compressor_finished)
|
|
||||||
{
|
|
||||||
// kill compression thread
|
|
||||||
avail_in = 0;
|
|
||||||
avail_out = 0;
|
|
||||||
compressor_finished = TRUE;
|
|
||||||
|
|
||||||
SetEvent(hIOReadyEvent);
|
|
||||||
#ifdef _WIN32
|
|
||||||
WaitForSingleObject(hCompressionThread, INFINITE);
|
|
||||||
#else
|
|
||||||
pthread_join(hCompressionThread, NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (hCompressionThread)
|
|
||||||
{
|
|
||||||
CloseHandle(hCompressionThread);
|
|
||||||
hCompressionThread = NULL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
hCompressionThread = 0;
|
|
||||||
#endif
|
|
||||||
SetNextOut(NULL, 0);
|
|
||||||
SetNextIn(NULL, 0);
|
|
||||||
return C_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CompressReal()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HRESULT hResult = _encoder->WriteCoderProperties(this);
|
|
||||||
if (res == S_OK)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
UINT64 inSize, outSize;
|
|
||||||
INT32 finished;
|
|
||||||
res = ConvertError(_encoder->CodeOneBlock(&inSize, &outSize, &finished));
|
|
||||||
if (res != C_OK)
|
|
||||||
break;
|
|
||||||
if (finished)
|
|
||||||
{
|
|
||||||
res = C_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = ConvertError(hResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
res = LZMA_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
compressor_finished = TRUE;
|
|
||||||
SetEvent(hNeedIOEvent);
|
|
||||||
return C_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Compress(BOOL flush)
|
|
||||||
{
|
|
||||||
if (compressor_finished)
|
|
||||||
{
|
|
||||||
// act like zlib when it comes to stream ending
|
|
||||||
if (flush)
|
|
||||||
return C_OK;
|
|
||||||
else
|
|
||||||
return LZMA_BAD_CALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
finish = flush;
|
|
||||||
|
|
||||||
if (!hCompressionThread)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
DWORD dwThreadId;
|
|
||||||
|
|
||||||
hCompressionThread = CreateThread(0, 0, lzmaCompressThread, (LPVOID) this, 0, &dwThreadId);
|
|
||||||
if (!hCompressionThread)
|
|
||||||
#else
|
|
||||||
if (pthread_create(&hCompressionThread, NULL, lzmaCompressThread, (LPVOID) this))
|
|
||||||
#endif
|
|
||||||
return LZMA_INIT_ERROR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetEvent(hIOReadyEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE waitList[2] = {hNeedIOEvent, (HANDLE) hCompressionThread};
|
|
||||||
if (WaitForMultipleObjects(2, waitList, FALSE, INFINITE) != WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
// thread ended or WaitForMultipleObjects failed
|
|
||||||
compressor_finished = TRUE;
|
|
||||||
SetEvent(hIOReadyEvent);
|
|
||||||
return LZMA_THREAD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compressor_finished)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return C_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetMoreIO()
|
|
||||||
{
|
|
||||||
SetEvent(hNeedIOEvent);
|
|
||||||
if (WaitForSingleObject(hIOReadyEvent, INFINITE) != WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
compressor_finished = TRUE;
|
|
||||||
res = LZMA_THREAD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize)
|
|
||||||
{
|
|
||||||
return ReadPart(data, size, processedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize)
|
|
||||||
{
|
|
||||||
if (processedSize)
|
|
||||||
*processedSize = 0;
|
|
||||||
while (size)
|
|
||||||
{
|
|
||||||
if (!avail_in)
|
|
||||||
{
|
|
||||||
if (finish)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
GetMoreIO();
|
|
||||||
if (!avail_in)
|
|
||||||
{
|
|
||||||
if (finish)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return E_ABORT;
|
|
||||||
}
|
|
||||||
if (compressor_finished)
|
|
||||||
return E_ABORT;
|
|
||||||
}
|
|
||||||
UINT32 l = min(size, avail_in);
|
|
||||||
memcpy(data, next_in, l);
|
|
||||||
avail_in -= l;
|
|
||||||
size -= l;
|
|
||||||
next_in += l;
|
|
||||||
data = LPBYTE(data) + l;
|
|
||||||
if (processedSize)
|
|
||||||
*processedSize += l;
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize)
|
|
||||||
{
|
|
||||||
return WritePart(data, size, processedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize)
|
|
||||||
{
|
|
||||||
if (processedSize)
|
|
||||||
*processedSize = 0;
|
|
||||||
while (size)
|
|
||||||
{
|
|
||||||
if (!avail_out)
|
|
||||||
{
|
|
||||||
GetMoreIO();
|
|
||||||
if (!avail_out)
|
|
||||||
return E_ABORT;
|
|
||||||
}
|
|
||||||
UINT32 l = min(size, avail_out);
|
|
||||||
memcpy(next_out, data, l);
|
|
||||||
avail_out -= l;
|
|
||||||
size -= l;
|
|
||||||
next_out += l;
|
|
||||||
data = LPBYTE(data) + l;
|
|
||||||
if (processedSize)
|
|
||||||
*processedSize += l;
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNextIn(char *in, unsigned int size)
|
|
||||||
{
|
|
||||||
next_in = (LPBYTE) in;
|
|
||||||
avail_in = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNextOut(char *out, unsigned int size)
|
|
||||||
{
|
|
||||||
next_out = (LPBYTE) out;
|
|
||||||
avail_out = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual char *GetNextOut() { return (char *) next_out; }
|
|
||||||
virtual unsigned int GetAvailIn() { return avail_in; }
|
|
||||||
virtual unsigned int GetAvailOut() { return avail_out; }
|
|
||||||
const char *GetName() { return "lzma"; }
|
|
||||||
|
|
||||||
const char* GetErrStr(int err) {
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case LZMA_BAD_CALL:
|
|
||||||
return "bad call";
|
|
||||||
case LZMA_INIT_ERROR:
|
|
||||||
return "initialization failed";
|
|
||||||
case LZMA_THREAD_ERROR:
|
|
||||||
return "thread synchronization error";
|
|
||||||
case LZMA_IO_ERROR:
|
|
||||||
return "input/output error";
|
|
||||||
case LZMA_MEM_ERROR:
|
|
||||||
return "not enough memory";
|
|
||||||
default:
|
|
||||||
return "unknown error";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
#define __COMPRESSOR_H__
|
#define __COMPRESSOR_H__
|
||||||
|
|
||||||
#define C_OK 0
|
#define C_OK 0
|
||||||
#define C_FINISH TRUE
|
#define C_FINISH true
|
||||||
|
|
||||||
class ICompressor {
|
class ICompressor {
|
||||||
public:
|
public:
|
||||||
virtual int Init(int level) = 0;
|
virtual int Init(int level) = 0;
|
||||||
virtual int End() = 0;
|
virtual int End() = 0;
|
||||||
virtual int Compress(BOOL finish) = 0;
|
virtual int Compress(bool finish) = 0;
|
||||||
|
|
||||||
virtual void SetNextIn(char *in, unsigned int size) = 0;
|
virtual void SetNextIn(char *in, unsigned int size) = 0;
|
||||||
virtual void SetNextOut(char *out, unsigned int size) = 0;
|
virtual void SetNextOut(char *out, unsigned int size) = 0;
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CZlib : public ICompressor {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Compress(BOOL finish) {
|
int Compress(bool finish) {
|
||||||
return deflate(stream, finish?Z_FINISH:0);
|
return deflate(stream, finish?Z_FINISH:0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,6 +192,10 @@ SOURCE=.\build.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\clzma.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\crc32.c
|
SOURCE=.\crc32.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue