45 # pragma warning(disable : 4127)
53 #define ALLOCATOR(s) calloc(1,s)
56 #define MEM_INIT memset
71 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
79 typedef unsigned char BYTE;
80 typedef unsigned short U16;
81 typedef unsigned int U32;
82 typedef signed int S32;
83 typedef unsigned long long U64;
100 #define MLZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
101 #define MLZ4F_MAGICNUMBER 0x184D2204U
102 #define MLZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
103 #define MLZ4F_BLOCKSIZEID_DEFAULT MLZ4F_max64KB
156 #define MLZ4F_GENERATE_STRING(STRING) #STRING,
167 static const char* codeError =
"Unspecified error code";
178 static const size_t blockSizes[4] = { 64
KB, 256
KB, 1
MB, 4
MB };
182 if (blockSizeID > 3)
return (
size_t)-MLZ4F_ERROR_maxBlockSize_invalid;
183 return blockSizes[blockSizeID];
190 U32 value32 = srcPtr[0];
191 value32 += (srcPtr[1]<<8);
192 value32 += (srcPtr[2]<<16);
193 value32 += ((
U32)srcPtr[3])<<24;
199 dstPtr[0] = (
BYTE)value32;
200 dstPtr[1] = (
BYTE)(value32 >> 8);
201 dstPtr[2] = (
BYTE)(value32 >> 16);
202 dstPtr[3] = (
BYTE)(value32 >> 24);
207 U64 value64 = srcPtr[0];
208 value64 += ((
U64)srcPtr[1]<<8);
209 value64 += ((
U64)srcPtr[2]<<16);
210 value64 += ((
U64)srcPtr[3]<<24);
211 value64 += ((
U64)srcPtr[4]<<32);
212 value64 += ((
U64)srcPtr[5]<<40);
213 value64 += ((
U64)srcPtr[6]<<48);
214 value64 += ((
U64)srcPtr[7]<<56);
220 dstPtr[0] = (
BYTE)value64;
221 dstPtr[1] = (
BYTE)(value64 >> 8);
222 dstPtr[2] = (
BYTE)(value64 >> 16);
223 dstPtr[3] = (
BYTE)(value64 >> 24);
224 dstPtr[4] = (
BYTE)(value64 >> 32);
225 dstPtr[5] = (
BYTE)(value64 >> 40);
226 dstPtr[6] = (
BYTE)(value64 >> 48);
227 dstPtr[7] = (
BYTE)(value64 >> 56);
234 return (
BYTE)(xxh >> 8);
244 size_t maxBlockSize = 64
KB;
245 while (requestedBSID > proposedBSID)
247 if (srcSize <= maxBlockSize)
252 return requestedBSID;
262 if (preferencesPtr!=NULL) prefs = *preferencesPtr;
263 else memset(&prefs, 0,
sizeof(prefs));
271 return headerSize + streamSize;
291 BYTE*
const dstStart = (
BYTE*) dstBuffer;
292 BYTE* dstPtr = dstStart;
293 BYTE*
const dstEnd = dstStart + dstMaxSize;
295 memset(&cctxI, 0,
sizeof(cctxI));
296 memset(&options, 0,
sizeof(options));
301 if (preferencesPtr!=NULL)
302 prefs = *preferencesPtr;
304 memset(&prefs, 0,
sizeof(prefs));
322 return (
size_t)-MLZ4F_ERROR_dstMaxSize_tooSmall;
339 return (dstPtr - dstStart);
367 return MLZ4F_OK_NoError;
379 FREEMEM(MLZ4F_compressionContext);
382 return MLZ4F_OK_NoError;
396 BYTE*
const dstStart = (
BYTE*)dstBuffer;
397 BYTE* dstPtr = dstStart;
399 size_t requiredBuffSize;
401 if (dstMaxSize <
maxFHSize)
return (
size_t)-MLZ4F_ERROR_dstMaxSize_tooSmall;
402 if (cctxPtr->
cStage != 0)
return (
size_t)-MLZ4F_ERROR_GENERIC;
403 memset(&prefNull, 0,
sizeof(prefNull));
404 if (preferencesPtr == NULL) preferencesPtr = &prefNull;
405 cctxPtr->
prefs = *preferencesPtr;
434 if (cctxPtr->
tmpBuff == NULL)
return (
size_t)-MLZ4F_ERROR_allocation_failed;
447 headerStart = dstPtr;
469 return (dstPtr - dstStart);
480 memset(&prefsNull, 0,
sizeof(prefsNull));
483 const MLZ4F_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
486 unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;
487 size_t lastBlockSize = prefsPtr->
autoFlush ? srcSize % blockSize : blockSize;
488 size_t blockInfo = 4;
491 return (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;;
496 typedef int (*
compressFunc_t)(
void* ctx,
const char* src,
char*
dst,
int srcSize,
int dstSize,
int level);
503 cSize = (
U32)compress(lz4ctx, (
const char*)src, (
char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);
507 cSize = (
U32)srcSize;
509 memcpy(cSizePtr+4, src, srcSize);
567 const BYTE* srcPtr = (
const BYTE*)srcBuffer;
568 const BYTE*
const srcEnd = srcPtr + srcSize;
569 BYTE*
const dstStart = (
BYTE*)dstBuffer;
570 BYTE* dstPtr = dstStart;
575 if (cctxPtr->
cStage != 1)
return (
size_t)-MLZ4F_ERROR_GENERIC;
577 memset(&cOptionsNull, 0,
sizeof(cOptionsNull));
578 if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
586 size_t sizeToCopy = blockSize - cctxPtr->
tmpInSize;
587 if (sizeToCopy > srcSize)
599 memcpy(cctxPtr->
tmpIn + cctxPtr->
tmpInSize, srcBuffer, sizeToCopy);
600 srcPtr += sizeToCopy;
609 while ((
size_t)(srcEnd - srcPtr) >= blockSize)
635 if (realDictSize==0)
return (
size_t)-MLZ4F_ERROR_GENERIC;
652 size_t sizeToCopy = srcEnd - srcPtr;
653 memcpy(cctxPtr->
tmpIn, srcPtr, sizeToCopy);
661 return dstPtr - dstStart;
676 BYTE*
const dstStart = (
BYTE*)dstBuffer;
677 BYTE* dstPtr = dstStart;
682 if (cctxPtr->
cStage != 1)
return (
size_t)-MLZ4F_ERROR_GENERIC;
683 if (dstMaxSize < (cctxPtr->
tmpInSize + 8))
return (
size_t)-MLZ4F_ERROR_dstMaxSize_tooSmall;
684 (void)compressOptionsPtr;
701 return dstPtr - dstStart;
717 BYTE*
const dstStart = (
BYTE*)dstBuffer;
718 BYTE* dstPtr = dstStart;
721 errorCode =
MLZ4F_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);
740 return (
size_t)-MLZ4F_ERROR_frameSize_wrong;
743 return dstPtr - dstStart;
767 dctxPtr->
version = versionNumber;
769 return MLZ4F_OK_NoError;
813 unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;
815 size_t frameHeaderSize;
816 const BYTE* srcPtr = (
const BYTE*)srcVoidPtr;
819 if (srcSize <
minFHSize)
return (
size_t)-MLZ4F_ERROR_frameHeader_incomplete;
826 if (srcVoidPtr == (
void*)(dctxPtr->
header))
846 version = (FLG>>6) &
_2BITS;
847 blockMode = (FLG>>5) &
_1BIT;
848 blockChecksumFlag = (FLG>>4) &
_1BIT;
849 contentSizeFlag = (FLG>>3) &
_1BIT;
850 contentChecksumFlag = (FLG>>2) &
_1BIT;
855 if (srcSize < frameHeaderSize)
858 if (srcPtr != dctxPtr->
header)
859 memcpy(dctxPtr->
header, srcPtr, srcSize);
867 blockSizeID = (BD>>4) &
_3BITS;
870 if (version != 1)
return (
size_t)-MLZ4F_ERROR_headerVersion_wrong;
871 if (blockChecksumFlag != 0)
return (
size_t)-MLZ4F_ERROR_blockChecksum_unsupported;
872 if (((FLG>>0)&
_2BITS) != 0)
return (
size_t)-MLZ4F_ERROR_reservedFlag_set;
873 if (((BD>>7)&
_1BIT) != 0)
return (
size_t)-MLZ4F_ERROR_reservedFlag_set;
874 if (blockSizeID < 4)
return (
size_t)-MLZ4F_ERROR_maxBlockSize_invalid;
875 if (((BD>>0)&
_4BITS) != 0)
return (
size_t)-MLZ4F_ERROR_reservedFlag_set;
879 if (HC != srcPtr[frameHeaderSize-1])
return (
size_t)-MLZ4F_ERROR_headerChecksum_invalid;
900 if (dctxPtr->
tmpIn == NULL)
return (
size_t)-MLZ4F_ERROR_GENERIC;
902 if (dctxPtr->
tmpOutBuffer== NULL)
return (
size_t)-MLZ4F_ERROR_GENERIC;
914 return frameHeaderSize;
929 const void* srcBuffer,
size_t* srcSizePtr)
944 size_t nextSrcSize =
MLZ4F_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);
946 return (
size_t)-MLZ4F_ERROR_frameHeader_incomplete;
956 (void)dictStart; (void)dictSize;
964 dctxPtr->
dict = (
const BYTE*)dstPtr;
972 if (dstPtr - dstPtr0 + dstSize >= 64
KB)
974 dctxPtr->
dict = (
const BYTE*)dstPtr0;
975 dctxPtr->
dictSize = dstPtr - dstPtr0 + dstSize;
992 if (copySize > preserveSize) copySize = preserveSize;
994 memcpy(dctxPtr->
tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1005 size_t preserveSize = 64
KB - dstSize;
1016 size_t preserveSize = 64
KB - dstSize;
1019 memcpy(dctxPtr->
tmpOutBuffer + preserveSize, dstPtr, dstSize);
1021 dctxPtr->
dictSize = preserveSize + dstSize;
1045 void* dstBuffer,
size_t* dstSizePtr,
1046 const void* srcBuffer,
size_t* srcSizePtr,
1051 const BYTE*
const srcStart = (
const BYTE*)srcBuffer;
1052 const BYTE*
const srcEnd = srcStart + *srcSizePtr;
1053 const BYTE* srcPtr = srcStart;
1054 BYTE*
const dstStart = (
BYTE*)dstBuffer;
1055 BYTE*
const dstEnd = dstStart + *dstSizePtr;
1056 BYTE* dstPtr = dstStart;
1057 const BYTE* selectedIn = NULL;
1058 unsigned doAnotherStage = 1;
1059 size_t nextSrcSizeHint = 1;
1062 memset(&optionsNull, 0,
sizeof(optionsNull));
1063 if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1070 if (srcStart != dctxPtr->
srcExpect)
return (
size_t)-MLZ4F_ERROR_srcPtr_wrong;
1075 while (doAnotherStage)
1083 if ((
size_t)(srcEnd-srcPtr) >=
maxFHSize)
1087 srcPtr += errorCode;
1098 if (sizeToCopy > (
size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1101 srcPtr += sizeToCopy;
1117 if ((
size_t)(srcEnd - srcPtr) >=
BHSize)
1119 selectedIn = srcPtr;
1134 if (sizeToCopy > (
size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1136 srcPtr += sizeToCopy;
1144 selectedIn = dctxPtr->
tmpIn;
1149 size_t nextCBlockSize =
MLZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1150 if (nextCBlockSize==0)
1155 if (nextCBlockSize > dctxPtr->
maxBlockSize)
return (
size_t)-MLZ4F_ERROR_GENERIC;
1165 nextSrcSizeHint = nextCBlockSize +
BHSize;
1174 if ((
size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr;
1175 if ((
size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;
1176 memcpy(dstPtr, srcPtr, sizeToCopy);
1184 srcPtr += sizeToCopy;
1185 dstPtr += sizeToCopy;
1199 if ((
size_t)(srcEnd-srcPtr) < dctxPtr->
tmpInTarget)
1205 selectedIn = srcPtr;
1214 if (sizeToCopy > (
size_t)(srcEnd-srcPtr)) sizeToCopy = srcEnd-srcPtr;
1217 srcPtr += sizeToCopy;
1224 selectedIn = dctxPtr->
tmpIn;
1240 int (*decoder)(
const char*,
char*, int, int,
const char*, int);
1249 if (decodedSize < 0)
return (
size_t)-MLZ4F_ERROR_GENERIC;
1257 dstPtr += decodedSize;
1265 int (*decoder)(
const char*,
char*, int, int,
const char*, int);
1287 size_t reservedDictSpace = dctxPtr->
dictSize;
1288 if (reservedDictSpace > 64
KB) reservedDictSpace = 64
KB;
1295 if (decodedSize < 0)
return (
size_t)-MLZ4F_ERROR_decompressionFailed;
1307 if (sizeToCopy > (
size_t)(dstEnd-dstPtr)) sizeToCopy = dstEnd-dstPtr;
1315 dstPtr += sizeToCopy;
1323 nextSrcSizeHint =
BHSize;
1332 if (suffixSize == 0)
1334 nextSrcSizeHint = 0;
1339 if ((srcEnd - srcPtr) < 4)
1346 selectedIn = srcPtr;
1354 size_t sizeToCopy = 4 - dctxPtr->
tmpInSize;
1355 if (sizeToCopy > (
size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1357 srcPtr += sizeToCopy;
1361 nextSrcSizeHint = 4 - dctxPtr->
tmpInSize;
1365 selectedIn = dctxPtr->
tmpIn;
1372 if (readCRC != resultCRC)
return (
size_t)-MLZ4F_ERROR_contentChecksum_invalid;
1373 nextSrcSizeHint = 0;
1381 if ((srcEnd - srcPtr) >= 4)
1383 selectedIn = srcPtr;
1399 if (sizeToCopy > (
size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1401 srcPtr += sizeToCopy;
1409 selectedIn = dctxPtr->
header + 4;
1424 if (skipSize > (
size_t)(srcEnd-srcPtr)) skipSize = srcEnd-srcPtr;
1429 if (nextSrcSizeHint)
break;
1449 if (copySize > preserveSize) copySize = preserveSize;
1451 memcpy(dctxPtr->
tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1458 size_t newDictSize = dctxPtr->
dictSize;
1460 if ((newDictSize) > 64
KB) newDictSize = 64
KB;
1462 memcpy(dctxPtr->
tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1476 *srcSizePtr = (srcPtr - srcStart);
1477 *dstSizePtr = (dstPtr - dstStart);
1478 return nextSrcSizeHint;
int MLZ4_saveDict(MLZ4_stream_t *streamPtr, char *safeBuffer, int dictSize)
MLZ4_stream_t * MLZ4_createStream(void)
int MLZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
void MLZ4_resetStream(MLZ4_stream_t *streamPtr)
int MLZ4_compress_limitedOutput_continue(MLZ4_stream_t *MLZ4_streamPtr, const char *source, char *dest, int inputSize, int maxOutputSize)
int MLZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxDecompressedSize, const char *dictStart, int dictSize)
int MLZ4_compress_limitedOutput_withState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize)
struct MLZ4F_cctx_s * MLZ4F_compressionContext_t
struct MLZ4F_dctx_s * MLZ4F_decompressionContext_t
@ MLZ4F_contentChecksumEnabled
#define MLZ4F_LIST_ERRORS(ITEM)
int MLZ4_saveDictHC(MLZ4_streamHC_t *streamHCPtr, char *safeBuffer, int maxDictSize)
int MLZ4_compress_HC_extStateHC(void *state, const char *src, char *dst, int srcSize, int maxDstSize, int compressionLevel)
void MLZ4_resetStreamHC(MLZ4_streamHC_t *streamHCPtr, int compressionLevel)
MLZ4_streamHC_t * MLZ4_createStreamHC(void)
int MLZ4_compress_HC_continue(MLZ4_streamHC_t *streamHCPtr, const char *src, char *dst, int srcSize, int maxDstSize)
static void MLZ4F_writeLE32(BYTE *dstPtr, U32 value32)
static size_t MLZ4F_compressBlock(void *dst, const void *src, size_t srcSize, compressFunc_t compress, void *lz4ctx, int level)
#define MLZ4F_BLOCKUNCOMPRESSED_FLAG
#define MLZ4F_MAGICNUMBER
#define MLZ4F_BLOCKSIZEID_DEFAULT
static int MLZ4F_localMLZ4_compress_limitedOutput_withState(void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
static compressFunc_t MLZ4F_selectCompression(MLZ4F_blockMode_t blockMode, int level)
static size_t MLZ4F_decodeHeader(MLZ4F_dctx_t *dctxPtr, const void *srcVoidPtr, size_t srcSize)
size_t MLZ4F_compressBegin(MLZ4F_compressionContext_t compressionContext, void *dstBuffer, size_t dstMaxSize, const MLZ4F_preferences_t *preferencesPtr)
static int MLZ4F_localSaveDict(MLZ4F_cctx_t *cctxPtr)
@ dstage_decodeCBlock_intoDst
@ dstage_decodeCBlock_intoTmp
static BYTE MLZ4F_headerChecksum(const void *header, size_t length)
size_t MLZ4F_compressBound(size_t srcSize, const MLZ4F_preferences_t *preferencesPtr)
#define MLZ4F_GENERATE_STRING(STRING)
static U32 MLZ4F_readLE32(const BYTE *srcPtr)
MLZ4F_errorCode_t MLZ4F_getFrameInfo(MLZ4F_decompressionContext_t dCtx, MLZ4F_frameInfo_t *frameInfoPtr, const void *srcBuffer, size_t *srcSizePtr)
size_t MLZ4F_flush(MLZ4F_compressionContext_t compressionContext, void *dstBuffer, size_t dstMaxSize, const MLZ4F_compressOptions_t *compressOptionsPtr)
unsigned MLZ4F_isError(MLZ4F_errorCode_t code)
static const size_t minFHSize
size_t MLZ4F_compressFrame(void *dstBuffer, size_t dstMaxSize, const void *srcBuffer, size_t srcSize, const MLZ4F_preferences_t *preferencesPtr)
static size_t MLZ4F_getBlockSize(unsigned blockSizeID)
static const size_t BHSize
static const size_t maxFHSize
#define MLZ4F_MAGIC_SKIPPABLE_START
static void MLZ4F_updateDict(MLZ4F_dctx_t *dctxPtr, const BYTE *dstPtr, size_t dstSize, const BYTE *dstPtr0, unsigned withinTmp)
MLZ4F_errorCode_t MLZ4F_freeDecompressionContext(MLZ4F_decompressionContext_t MLZ4F_decompressionContext)
MLZ4F_errorCode_t MLZ4F_createCompressionContext(MLZ4F_compressionContext_t *MLZ4F_compressionContextPtr, unsigned version)
MLZ4F_errorCode_t MLZ4F_createDecompressionContext(MLZ4F_decompressionContext_t *MLZ4F_decompressionContextPtr, unsigned versionNumber)
static U64 MLZ4F_readLE64(const BYTE *srcPtr)
static MLZ4F_blockSizeID_t MLZ4F_optimalBSID(const MLZ4F_blockSizeID_t requestedBSID, const size_t srcSize)
struct MLZ4F_dctx_s MLZ4F_dctx_t
static int MLZ4F_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize, const char *dictStart, int dictSize)
MLZ4F_errorCode_t MLZ4F_freeCompressionContext(MLZ4F_compressionContext_t MLZ4F_compressionContext)
const char * MLZ4F_getErrorName(MLZ4F_errorCode_t code)
static void MLZ4F_writeLE64(BYTE *dstPtr, U64 value64)
size_t MLZ4F_decompress(MLZ4F_decompressionContext_t decompressionContext, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, const MLZ4F_decompressOptions_t *decompressOptionsPtr)
int(* compressFunc_t)(void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
size_t MLZ4F_compressFrameBound(size_t srcSize, const MLZ4F_preferences_t *preferencesPtr)
static int MLZ4F_localMLZ4_compressHC_limitedOutput_continue(void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
struct MLZ4F_cctx_s MLZ4F_cctx_t
static const int minHClevel
static const char * MLZ4F_errorStrings[]
static int MLZ4F_localMLZ4_compress_limitedOutput_continue(void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
size_t MLZ4F_compressEnd(MLZ4F_compressionContext_t compressionContext, void *dstBuffer, size_t dstMaxSize, const MLZ4F_compressOptions_t *compressOptionsPtr)
size_t MLZ4F_compressUpdate(MLZ4F_compressionContext_t compressionContext, void *dstBuffer, size_t dstMaxSize, const void *srcBuffer, size_t srcSize, const MLZ4F_compressOptions_t *compressOptionsPtr)
MLZ4F_preferences_t prefs
MLZ4F_frameInfo_t frameInfo
MLZ4F_blockMode_t blockMode
MLZ4F_blockSizeID_t blockSizeID
unsigned long long contentSize
MLZ4F_frameType_t frameType
MLZ4F_contentChecksum_t contentChecksumFlag
MLZ4F_frameInfo_t frameInfo