Update fast-lzma2

This commit is contained in:
conor42
2019-03-22 20:14:34 +10:00
parent ed1f022688
commit 4b0103cebd
5 changed files with 34 additions and 29 deletions

View File

@@ -249,7 +249,7 @@ typedef struct {
* The radix match finder allows compressed data to be stored in its match table during encoding.
* Applications may call streaming compression functions with output == NULL. In this case,
* when the function returns 1, the compressed data must be read from the internal buffers.
* Call FL2_getNextCStreamBuffer() repeatedly until it returns 0.
* Call FL2_getNextCompressedBuffer() repeatedly until it returns 0.
* Each call returns buffer information in the FL2_inBuffer parameter. Applications typically will
* passed this to an I/O write function or downstream filter.
* Alternately, applications may pass an FL2_outBuffer object pointer to receive the output. In this
@@ -279,11 +279,12 @@ FL2LIB_API size_t FL2LIB_CALL FL2_initCStream(FL2_CStream* fcs, int compressionL
/*! FL2_setCStreamTimeout() :
* Sets a timeout in milliseconds. Zero disables the timeout (default). If a nonzero timout is set, functions
* FL2_compressStream(), FL2_updateDictionary(), FL2_getNextCStreamBuffer(), FL2_flushStream(), and
* FL2_endStream() may return a timeout code before compression of the current dictionary of data
* completes. FL2_isError() returns true for the timeout code, so check the code with FL2_isTimedOut() before
* testing for errors. With the exception of FL2_updateDictionary(), the above functions may be called again
* to wait for completion. A typical application for timeouts is to update the user on compression progress. */
* FL2_compressStream(), FL2_getDictionaryBuffer(), FL2_updateDictionary(), FL2_getNextCompressedBuffer(),
* FL2_flushStream(), and FL2_endStream() may return a timeout code before compression of the current
* dictionary of data completes. FL2_isError() returns true for the timeout code, so check the code with
* FL2_isTimedOut() before testing for errors. With the exception of FL2_updateDictionary(), the above
* functions may be called again to wait for completion. A typical application for timeouts is to update the
* user on compression progress. */
FL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned timeout);
/*! FL2_compressStream() :
@@ -295,6 +296,12 @@ FL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned
* Returns 1 to indicate compressed data must be read (or output is full), or 0 otherwise. */
FL2LIB_API size_t FL2LIB_CALL FL2_compressStream(FL2_CStream* fcs, FL2_outBuffer *output, FL2_inBuffer* input);
/*! FL2_copyCStreamOutput() :
* Copies compressed data to the output buffer until the buffer is full or all available data is copied.
* If asynchronous compression is in progress, the function returns 0 without waiting.
* Returns 1 to indicate some compressed data remains, or 0 otherwise. */
FL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output);
/*** Push/pull functions ***/
/*! FL2_getDictionaryBuffer() :
@@ -308,12 +315,12 @@ FL2LIB_API size_t FL2LIB_CALL FL2_getDictionaryBuffer(FL2_CStream* fcs, FL2_dict
* was filled. Returns 1 to indicate compressed data must be read, 0 if not, or an error code. */
FL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream* fcs, size_t addedSize);
/*! FL2_getNextCStreamBuffer() :
/*! FL2_getNextCompressedBuffer() :
* Returns a buffer containing a slice of the compressed data. Call this function and process the data
* until the function returns zero. In most cases it will return a buffer for each compression thread
* used. It is sometimes less but never more than nbThreads. If asynchronous compression is in progress,
* this function will wait for completion before returning, or it will return the timeout code. */
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCStreamBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf);
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf);
/******/
@@ -368,17 +375,12 @@ FL2LIB_API size_t FL2LIB_CALL FL2_endStream(FL2_CStream* fcs, FL2_outBuffer *out
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again the remaining data.
* More data must be loaded if `input.pos + LZMA_REQUIRED_INPUT_MAX >= input.size`. In this case,
* move the remaining input (<= LZMA_REQUIRED_INPUT_MAX bytes) to the start of the buffer and
* load new data after it.
* If `output.pos < output.size`, decoder has flushed everything it could.
* @return : 0 when a stream is completely decoded and fully flushed,
* 1, which means there is still some decoding to do to complete the stream,
* or an error code, which can be tested using FL2_isError().
* *******************************************************************************/
#define LZMA_REQUIRED_INPUT_MAX 20
typedef struct FL2_DStream_s FL2_DStream;
/*===== FL2_DStream management functions =====*/
@@ -434,9 +436,7 @@ FL2LIB_API size_t FL2LIB_CALL FL2_initDStream_withProp(FL2_DStream* fds, unsigne
* Reads data from input and decompresses to output.
* Returns 1 if the stream is unfinished, 0 if the terminator was encountered (he'll be back)
* and all data was written to output, or an error code. Call this function repeatedly if
* necessary, removing data from output and/or loading data into input before each call.
* Note the requirement for LZMA_REQUIRED_INPUT_MAX bytes of input if the input data is
* incomplete (see intro above). */
* necessary, removing data from output and/or loading data into input before each call. */
FL2LIB_API size_t FL2LIB_CALL FL2_decompressStream(FL2_DStream* fds, FL2_outBuffer* output, FL2_inBuffer* input);
/*-***************************************************************************

View File

@@ -446,7 +446,7 @@ static size_t FL2_beginFrame(FL2_CCtx* const cctx, size_t const dictReduce)
if (FL2_initEncoders(cctx) != 0) /* Create hash objects together, leaving the (large) match table last */
return FL2_ERROR(memory_allocation);
if (!cctx->matchTable) {
if (cctx->matchTable == NULL) {
cctx->matchTable = RMF_createMatchTable(&cctx->params.rParams, dictReduce, cctx->jobCount);
if (cctx->matchTable == NULL)
return FL2_ERROR(memory_allocation);
@@ -938,7 +938,7 @@ static size_t FL2_compressStream_internal(FL2_CStream* const fcs, int const endi
/* Copy the compressed output stored in the match table buffer.
* One slice exists per thread.
*/
static void FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output)
FL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output)
{
for (; fcs->outThread < fcs->threadCount; ++fcs->outThread) {
const BYTE* const outBuf = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[fcs->outThread].block.start) + fcs->outPos;
@@ -956,10 +956,11 @@ static void FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output)
/* If the slice is not flushed, the output is full */
if (fcs->outPos < fcs->jobs[fcs->outThread].cSize)
break;
return 1;
fcs->outPos = 0;
}
return 0;
}
static size_t FL2_compressStream_input(FL2_CStream* fcs, FL2_inBuffer* input)
@@ -999,8 +1000,10 @@ static size_t FL2_loopCheck(FL2_CStream* fcs, int unchanged)
{
if (unchanged) {
++fcs->loopCount;
if (fcs->loopCount > FL2_MAX_LOOPS)
if (fcs->loopCount > FL2_MAX_LOOPS) {
FL2_cancelCStream(fcs);
return FL2_ERROR(buffer);
}
}
else {
fcs->loopCount = 0;
@@ -1057,14 +1060,13 @@ FL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream * fcs, size_t add
return fcs->outThread < fcs->threadCount;
}
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCStreamBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf)
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf)
{
cbuf->src = NULL;
cbuf->size = 0;
#ifndef FL2_SINGLETHREAD
FL2POOL_waitAll(fcs->compressThread, 0);
CHECK_F(fcs->asyncRes);
CHECK_F(FL2_waitCStream(fcs));
#endif
if (fcs->outThread < fcs->threadCount) {

View File

@@ -78,7 +78,8 @@ Public domain
#define kChunkSize ((1UL << 16U) - 8192U)
#define kSqrtChunkSize 239U
#define kTempMinOutput (LZMA_REQUIRED_INPUT_MAX * 4U)
#define kMaxMatchEncodeSize 20
#define kTempMinOutput (kMaxMatchEncodeSize * 4U)
#define kTempBufferSize (kTempMinOutput + kOptimizerBufferSize + kOptimizerBufferSize / 16U)
#define kMaxChunkUncompressedSize ((1UL << 21U) - kMatchLenMax)
#define kMaxChunkCompressedSize (1UL << 16U)

View File

@@ -197,7 +197,8 @@ FL2_matchTable* RMF_createMatchTable(const RMF_parameters* const p, size_t const
size_t const table_bytes = is_struct ? ((dictionary_size + 3U) / 4U) * sizeof(RMF_unit)
: dictionary_size * sizeof(U32);
FL2_matchTable* const tbl = malloc(sizeof(FL2_matchTable) + table_bytes - sizeof(U32));
if (!tbl) return NULL;
if (tbl == NULL)
return NULL;
tbl->is_struct = is_struct;
tbl->alloc_struct = is_struct;
@@ -707,7 +708,7 @@ BYTE* RMF_getTableAsOutputBuffer(FL2_matchTable* const tbl, size_t const index)
size_t RMF_memoryUsage(size_t const dict_size, unsigned const buffer_log, unsigned const thread_count)
{
size_t size = (size_t)(4U + RMF_isStruct(dict_size)) * dict_size;
size_t const buf_size = dict_size >> buffer_log;
size_t const buf_size = dict_size >> (RMF_BUFFER_LOG_BASE - buffer_log);
size += ((buf_size - 1) * sizeof(RMF_buildMatch) + sizeof(RMF_builder)) * thread_count;
return size;
}

View File

@@ -272,9 +272,10 @@ HRESULT CFastEncoder::FastLzma2::WriteBuffers(ISequentialOutStream *outStream)
size_t csize;
for (;;) {
FL2_cBuffer cbuf;
// Waits if compression in progress
csize = FL2_getNextCStreamBuffer(fcs, &cbuf);
CHECK_S(csize);
do {
csize = FL2_getNextCompressedBuffer(fcs, &cbuf);
} while (FL2_isTimedOut(csize));
CHECK_S(csize);
if (csize == 0)
break;
HRESULT err = WriteStream(outStream, cbuf.src, cbuf.size);