summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Mohr <alexander.m.mohr@mercedes-benz.com>2022-07-05 09:35:58 (GMT)
committerAlexander Mohr <alexander.m.mohr@mercedes-benz.com>2022-07-05 09:56:23 (GMT)
commit42eb47d42f041054140b8e08ffc6ba85e9f092f2 (patch)
treede71755c5a79fdc34631f1e31f2d763c105df5a7
parente595150bafff318f6f66e4b364193b32701449e3 (diff)
downloadlz4-42eb47d42f041054140b8e08ffc6ba85e9f092f2.zip
lz4-42eb47d42f041054140b8e08ffc6ba85e9f092f2.tar.gz
lz4-42eb47d42f041054140b8e08ffc6ba85e9f092f2.tar.bz2
uncompressed-api: allow uncompressed_update only for independent blocks
Signed-off-by: Alexander Mohr <alexander.m.mohr@mercedes-benz.com>
-rw-r--r--doc/lz4_manual.html12
-rw-r--r--lib/lz4.c24
-rw-r--r--lib/lz4.h11
-rw-r--r--lib/lz4frame.c172
-rw-r--r--lib/lz4frame.h1
-rw-r--r--lib/lz4hc.c27
6 files changed, 84 insertions, 163 deletions
diff --git a/doc/lz4_manual.html b/doc/lz4_manual.html
index 700cb84..037cfc0 100644
--- a/doc/lz4_manual.html
+++ b/doc/lz4_manual.html
@@ -391,18 +391,6 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
</p></pre><BR>
-<pre><b>LZ4LIB_STATIC_API int LZ4_getDictSize (const LZ4_stream_t* LZ4_dict, int dictSize);
-</b><p> Get the size of the dictionary. This can be used for adding data without
- compression to the LZ4 archive. If linked blocked mode is used the memory
- of the dictionary is kept free.
- This way uncompressed data does not influence the effectiveness of the
- dictionary.
- @param LZ4_dict Pointer to the dictionary to get the size of.
- @param dictSize The maximum dictionary size. (Normally 64 KB).
- @return The size of the dictionary.
-
-</p></pre><BR>
-
<pre><b></b><p>
It's possible to have input and output sharing the same buffer,
for highly constrained memory environments.
diff --git a/lib/lz4.c b/lib/lz4.c
index 289162d..a2272cf 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -1679,25 +1679,6 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char*
return result;
}
-/*! LZ4_getDictSize():
- * Get the size of the dictionary. This can be used for adding data without
- * compression to the LZ4 archive. If linked blocked mode is used the memory
- * of the dictionary is kept free.
- * This way uncompressed data does not influence the effectiveness of the
- * dictionary.
- * @param LZ4_dict Pointer to the dictionary to get the size of.
- * @param dictSize The maximum dictionary size. (Normally 64 KB).
- * @return The size of the dictionary.
- */
-int LZ4_getDictSize (const LZ4_stream_t* LZ4_dict, int dictSize)
-{
- const LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
-
- if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
- if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
-
- return dictSize;
-}
/*! LZ4_saveDict() :
* If previously compressed data block is not guaranteed to remain available at its memory location,
@@ -1709,9 +1690,12 @@ int LZ4_getDictSize (const LZ4_stream_t* LZ4_dict, int dictSize)
int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
{
LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
- dictSize = LZ4_getDictSize(LZ4_dict, dictSize);
+
DEBUGLOG(5, "LZ4_saveDict : dictSize=%i, safeBuffer=%p", dictSize, safeBuffer);
+ if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */
+ if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }
+
if (safeBuffer == NULL) assert(dictSize == 0);
if (dictSize > 0) {
const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
diff --git a/lib/lz4.h b/lib/lz4.h
index ce2288e..6c068c6 100644
--- a/lib/lz4.h
+++ b/lib/lz4.h
@@ -509,17 +509,6 @@ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const c
*/
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
-/*! LZ4_getDictSize():
- * Get the size of the dictionary. This can be used for adding data without
- * compression to the LZ4 archive. If linked blocked mode is used the memory
- * of the dictionary is kept free.
- * This way uncompressed data does not influence the effectiveness of the
- * dictionary.
- * @param LZ4_dict Pointer to the dictionary to get the size of.
- * @param dictSize The maximum dictionary size. (Normally 64 KB).
- * @return The size of the dictionary.
- */
-LZ4LIB_STATIC_API int LZ4_getDictSize (const LZ4_stream_t* LZ4_dict, int dictSize);
/*! In-place compression and decompression
*
diff --git a/lib/lz4frame.c b/lib/lz4frame.c
index f32ed1d..3042d6f 100644
--- a/lib/lz4frame.c
+++ b/lib/lz4frame.c
@@ -841,23 +841,12 @@ static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int lev
return LZ4F_compressBlockHC_continue;
}
-static int LZ4F_maxDictSize(void) {
- return 64 KB;
-}
-
/* Save history (up to 64KB) into @tmpBuff */
static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)
{
if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
- return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), LZ4F_maxDictSize());
- return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), LZ4F_maxDictSize());
-}
-
-static int LZ4F_localDictSize(LZ4F_cctx_t* cctxPtr)
-{
- if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
- return LZ4_getDictSize ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), LZ4F_maxDictSize());
- return LZ4_getDictHCSize ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), LZ4F_maxDictSize());
+ return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
+ return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
}
typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
@@ -886,69 +875,64 @@ static size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr,
size_t const blockSize = cctxPtr->maxBlockSize;
const BYTE* srcPtr = (const BYTE*)srcBuffer;
const BYTE* const srcEnd = srcPtr + srcSize;
- BYTE* dstStart = (BYTE*)dstBuffer;
+ BYTE* const dstStart = (BYTE*)dstBuffer;
BYTE* dstPtr = dstStart;
LZ4F_lastBlockStatus lastBlockCompressed = notDone;
compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
- size_t bytesWritten = 0;
+ size_t bytesWritten;
DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize);
- /* flush currently written block, to continue with new block compression */
- if (cctxPtr->blockCompression != blockCompression) {
- bytesWritten = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
- dstStart = (BYTE*)dstBuffer + bytesWritten;
- dstPtr = dstStart;
- dstCapacity -= bytesWritten;
- cctxPtr->blockCompression = blockCompression;
- }
-
RETURN_ERROR_IF(cctxPtr->cStage != 1, compressionState_uninitialized); /* state must be initialized and waiting for next block */
-
- if (blockCompression == LZ4B_COMPRESSED &&
- dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
- RETURN_ERROR(dstMaxSize_tooSmall);
+ if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
+ RETURN_ERROR(dstMaxSize_tooSmall);
if (blockCompression == LZ4B_UNCOMPRESSED && dstCapacity < srcSize)
- RETURN_ERROR(dstMaxSize_tooSmall);
+ RETURN_ERROR(dstMaxSize_tooSmall);
+
+ /* flush currently written block, to continue with new block compression */
+ if (cctxPtr->blockCompression != blockCompression) {
+ bytesWritten = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
+ dstPtr += bytesWritten;
+ cctxPtr->blockCompression = blockCompression;
+ }
if (compressOptionsPtr == NULL) compressOptionsPtr = &k_cOptionsNull;
/* complete tmp buffer */
if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
- size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
- assert(blockSize > cctxPtr->tmpInSize);
- if (sizeToCopy > srcSize) {
- /* add src to tmpIn buffer */
- memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
- srcPtr = srcEnd;
- cctxPtr->tmpInSize += srcSize;
- /* still needs some CRC */
- } else {
- /* complete tmpIn block and then compress it */
- lastBlockCompressed = fromTmpBuffer;
- memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
- srcPtr += sizeToCopy;
+ size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
+ assert(blockSize > cctxPtr->tmpInSize);
+ if (sizeToCopy > srcSize) {
+ /* add src to tmpIn buffer */
+ memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
+ srcPtr = srcEnd;
+ cctxPtr->tmpInSize += srcSize;
+ /* still needs some CRC */
+ } else {
+ /* complete tmpIn block and then compress it */
+ lastBlockCompressed = fromTmpBuffer;
+ memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
+ srcPtr += sizeToCopy;
+
+ dstPtr += LZ4F_makeBlock(dstPtr,
+ cctxPtr->tmpIn, blockSize,
+ compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
+ cctxPtr->cdict,
+ cctxPtr->prefs.frameInfo.blockChecksumFlag, blockCompression);
+ if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
+ cctxPtr->tmpInSize = 0;
+ } }
+ while ((size_t)(srcEnd - srcPtr) >= blockSize) {
+ /* compress full blocks */
+ lastBlockCompressed = fromSrcBuffer;
dstPtr += LZ4F_makeBlock(dstPtr,
- cctxPtr->tmpIn, blockSize,
+ srcPtr, blockSize,
compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
cctxPtr->cdict,
- cctxPtr->prefs.frameInfo.blockChecksumFlag, blockCompression);
-
- if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
- cctxPtr->tmpInSize = 0;
- }
- }
-
- while ((size_t)(srcEnd - srcPtr) >= blockSize) {
- /* compress full blocks */
- lastBlockCompressed = fromSrcBuffer;
- dstPtr += LZ4F_makeBlock(dstPtr,
- srcPtr, blockSize,
- compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
- cctxPtr->cdict,
- cctxPtr->prefs.frameInfo.blockChecksumFlag, blockCompression);
- srcPtr += blockSize;
+ cctxPtr->prefs.frameInfo.blockChecksumFlag,
+ blockCompression);
+ srcPtr += blockSize;
}
if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
@@ -960,27 +944,20 @@ static size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr,
cctxPtr->cdict,
cctxPtr->prefs.frameInfo.blockChecksumFlag,
blockCompression);
- srcPtr = srcEnd;
+ srcPtr = srcEnd;
}
/* preserve dictionary within @tmpBuff whenever necessary */
if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {
- if (compressOptionsPtr->stableSrc) {
- cctxPtr->tmpIn = cctxPtr->tmpBuff; /* src is stable : dictionary remains in src across invocations */
- } else {
- int realDictSize;
- if (blockCompression == LZ4B_COMPRESSED) {
- realDictSize = LZ4F_localSaveDict(cctxPtr);
+ /* linked blocks are only supported in compressed mode, see LZ4F_uncompressedUpdate */
+ assert(blockCompression == LZ4B_COMPRESSED);
+ if (compressOptionsPtr->stableSrc) {
+ cctxPtr->tmpIn = cctxPtr->tmpBuff; /* src is stable : dictionary remains in src across invocations */
} else {
- /* only keep the space of the dictionary, so dict data is kept for the next compressedUpdate
- * this is only relevant if linked block mode
- * */
- realDictSize = LZ4F_localDictSize(cctxPtr);
+ int const realDictSize = LZ4F_localSaveDict(cctxPtr);
+ assert(0 <= realDictSize && realDictSize <= 64 KB);
+ cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
}
-
- assert(0 <= realDictSize && realDictSize <= 64 KB);
- cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
- }
}
/* keep tmpIn within limits */
@@ -989,30 +966,24 @@ static size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr,
{
/* only preserve 64KB within internal buffer. Ensures there is enough room for next block.
* note: this situation necessarily implies lastBlockCompressed==fromTmpBuffer */
- int realDictSize;
- if (blockCompression == LZ4B_COMPRESSED) {
- realDictSize = LZ4F_localSaveDict(cctxPtr);
- } else {
- /* only keep the space of the dictionary, so dict data is kept for the next compressedUpdate*/
- realDictSize = LZ4F_maxDictSize();
- }
+ int const realDictSize = LZ4F_localSaveDict(cctxPtr);
cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
assert((cctxPtr->tmpIn + blockSize) <= (cctxPtr->tmpBuff + cctxPtr->maxBufferSize));
}
/* some input data left, necessarily < blockSize */
if (srcPtr < srcEnd) {
- /* fill tmp buffer */
- size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
- memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
- cctxPtr->tmpInSize = sizeToCopy;
+ /* fill tmp buffer */
+ size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
+ memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
+ cctxPtr->tmpInSize = sizeToCopy;
}
if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
- (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
+ (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
cctxPtr->totalInSize += srcSize;
- return bytesWritten + (size_t)(dstPtr - dstStart);
+ return (size_t)(dstPtr - dstStart);
}
/*! LZ4F_compressUpdate() :
@@ -1032,10 +1003,10 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
const void* srcBuffer, size_t srcSize,
const LZ4F_compressOptions_t* compressOptionsPtr)
{
- return LZ4F_compressUpdateImpl(cctxPtr,
- dstBuffer, dstCapacity,
- srcBuffer, srcSize,
- compressOptionsPtr, LZ4B_COMPRESSED);
+ return LZ4F_compressUpdateImpl(cctxPtr,
+ dstBuffer, dstCapacity,
+ srcBuffer, srcSize,
+ compressOptionsPtr, LZ4B_COMPRESSED);
}
/*! LZ4F_compressUpdate() :
@@ -1044,6 +1015,7 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
* src data is either buffered or compressed into @dstBuffer.
* If previously an uncompressed block was written, buffered data is flushed
* before appending compressed data is continued.
+ * This is only supported when LZ4F_blockIndependent is used
* @dstCapacity MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).
* @compressOptionsPtr is optional : provide NULL to mean "default".
* @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.
@@ -1051,13 +1023,14 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
* After an error, the state is left in a UB state, and must be re-initialized.
*/
size_t LZ4F_uncompressedUpdate(LZ4F_cctx* cctxPtr,
- void* dstBuffer, size_t dstCapacity,
- const void* srcBuffer, size_t srcSize,
- const LZ4F_compressOptions_t* compressOptionsPtr) {
- return LZ4F_compressUpdateImpl(cctxPtr,
- dstBuffer, dstCapacity,
- srcBuffer, srcSize,
- compressOptionsPtr, LZ4B_UNCOMPRESSED);
+ void* dstBuffer, size_t dstCapacity,
+ const void* srcBuffer, size_t srcSize,
+ const LZ4F_compressOptions_t* compressOptionsPtr) {
+ assert(cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockIndependent);
+ return LZ4F_compressUpdateImpl(cctxPtr,
+ dstBuffer, dstCapacity,
+ srcBuffer, srcSize,
+ compressOptionsPtr, LZ4B_UNCOMPRESSED);
}
@@ -1090,7 +1063,8 @@ size_t LZ4F_flush(LZ4F_cctx* cctxPtr,
cctxPtr->tmpIn, cctxPtr->tmpInSize,
compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
cctxPtr->cdict,
- cctxPtr->prefs.frameInfo.blockChecksumFlag, cctxPtr->blockCompression);
+ cctxPtr->prefs.frameInfo.blockChecksumFlag,
+ cctxPtr->blockCompression);
assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity));
if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)
diff --git a/lib/lz4frame.h b/lib/lz4frame.h
index 7d81fa0..691ad50 100644
--- a/lib/lz4frame.h
+++ b/lib/lz4frame.h
@@ -552,6 +552,7 @@ LZ4FLIB_STATIC_API size_t LZ4F_getBlockSize(unsigned);
* After an error, the state is left in a UB state, and must be re-initialized or freed.
* If previously a compressed block was written, buffered data is flushed
* before appending uncompressed data is continued.
+ * This is only supported when LZ4F_blockIndependent is used
* `cOptPtr` is optional : NULL can be provided, in which case all options are set to default.
* @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).
* or an error code if it fails (which can be tested using LZ4F_isError())
diff --git a/lib/lz4hc.c b/lib/lz4hc.c
index b5bc880..99650a6 100644
--- a/lib/lz4hc.c
+++ b/lib/lz4hc.c
@@ -1154,26 +1154,6 @@ int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const ch
return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, fillOutput);
}
-/*! LZ4_getDictHCSize():
- * Get the size of the dictionary. This can be used for adding data without
- * compression to the LZ4 archive. If linked blocked mode is used the memory
- * of the dictionary is kept free.
- * This way uncompressed data does not influence the effectiveness of the
- * dictionary.
- * @param LZ4_dict Pointer to the dictionary to get the size of.
- * @param dictSize The maximum dictionary size. (Normally 64 KB).
- * @return The size of the dictionary.
- */
-int LZ4_getDictHCSize(const LZ4_streamHC_t* LZ4_streamHCPtr, int dictSize) {
- const LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
- int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
- DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);
- assert(prefixSize >= 0);
- if (dictSize > 64 KB) dictSize = 64 KB;
- if (dictSize < 4) dictSize = 0;
- if (dictSize > prefixSize) dictSize = prefixSize;
- return dictSize;
-}
/* LZ4_saveDictHC :
@@ -1184,7 +1164,12 @@ int LZ4_getDictHCSize(const LZ4_streamHC_t* LZ4_streamHCPtr, int dictSize) {
int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
{
LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
- dictSize = LZ4_getDictHCSize(LZ4_streamHCPtr, dictSize);
+ int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
+ DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);
+ assert(prefixSize >= 0);
+ if (dictSize > 64 KB) dictSize = 64 KB;
+ if (dictSize < 4) dictSize = 0;
+ if (dictSize > prefixSize) dictSize = prefixSize;
if (safeBuffer == NULL) assert(dictSize == 0);
if (dictSize > 0)
memmove(safeBuffer, streamPtr->end - dictSize, dictSize);