frame content size support
This commit is contained in:
parent
7d87d43e61
commit
7ee725645b
1
NEWS
1
NEWS
@ -1,6 +1,7 @@
|
||||
r128:
|
||||
New : lz4 cli sparse file support
|
||||
New : command -m, to compress multiple files in a single command
|
||||
New : lz4frame supports frame content size
|
||||
Fixed : Restored lz4hc compression ratio (was slightly lower since r124)
|
||||
New : lz4frame supports skippable frames
|
||||
Changed:Default "make install" directory is /usr/local
|
||||
|
203
lib/lz4frame.c
203
lib/lz4frame.c
@ -33,7 +33,7 @@ You can contact the author at :
|
||||
*/
|
||||
|
||||
/* LZ4F is a stand-alone API to create LZ4-compressed Frames
|
||||
* in full conformance with specification v1.4.1.
|
||||
* in full conformance with specification v1.5.0
|
||||
* All related operations, including memory management, are handled by the library.
|
||||
* */
|
||||
|
||||
@ -100,9 +100,10 @@ typedef unsigned long long U64;
|
||||
#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
|
||||
#define LZ4F_MAGICNUMBER 0x184D2204U
|
||||
#define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
|
||||
#define LZ4F_MAXHEADERFRAME_SIZE 7
|
||||
#define LZ4F_MAXHEADERFRAME_SIZE 15
|
||||
#define LZ4F_BLOCKSIZEID_DEFAULT max64KB
|
||||
|
||||
static const size_t minFHSize = 5;
|
||||
static const U32 minHClevel = 3;
|
||||
|
||||
/**************************************
|
||||
@ -111,23 +112,24 @@ static const U32 minHClevel = 3;
|
||||
typedef struct
|
||||
{
|
||||
LZ4F_preferences_t prefs;
|
||||
U32 version;
|
||||
U32 cStage;
|
||||
U32 version;
|
||||
U32 cStage;
|
||||
size_t maxBlockSize;
|
||||
size_t maxBufferSize;
|
||||
BYTE* tmpBuff;
|
||||
BYTE* tmpIn;
|
||||
size_t tmpInSize;
|
||||
U64 totalInSize;
|
||||
XXH32_state_t xxh;
|
||||
void* lz4CtxPtr;
|
||||
U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
|
||||
void* lz4CtxPtr;
|
||||
U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
|
||||
} LZ4F_cctx_internal_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LZ4F_frameInfo_t frameInfo;
|
||||
unsigned version;
|
||||
unsigned dStage;
|
||||
U32 version;
|
||||
U32 dStage;
|
||||
size_t maxBlockSize;
|
||||
size_t maxBufferSize;
|
||||
const BYTE* srcExpect;
|
||||
@ -141,7 +143,7 @@ typedef struct
|
||||
size_t tmpOutSize;
|
||||
size_t tmpOutStart;
|
||||
XXH32_state_t xxh;
|
||||
BYTE header[8];
|
||||
BYTE header[16];
|
||||
} LZ4F_dctx_internal_t;
|
||||
|
||||
|
||||
@ -152,7 +154,7 @@ typedef struct
|
||||
static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };
|
||||
|
||||
|
||||
U32 LZ4F_isError(LZ4F_errorCode_t code)
|
||||
unsigned LZ4F_isError(LZ4F_errorCode_t code)
|
||||
{
|
||||
return (code > (LZ4F_errorCode_t)(-ERROR_maxCode));
|
||||
}
|
||||
@ -180,14 +182,6 @@ static size_t LZ4F_getBlockSize(unsigned blockSizeID)
|
||||
|
||||
|
||||
/* unoptimized version; solves endianess & alignment issues */
|
||||
static void LZ4F_writeLE32 (BYTE* dstPtr, U32 value32)
|
||||
{
|
||||
dstPtr[0] = (BYTE)value32;
|
||||
dstPtr[1] = (BYTE)(value32 >> 8);
|
||||
dstPtr[2] = (BYTE)(value32 >> 16);
|
||||
dstPtr[3] = (BYTE)(value32 >> 24);
|
||||
}
|
||||
|
||||
static U32 LZ4F_readLE32 (const BYTE* srcPtr)
|
||||
{
|
||||
U32 value32 = srcPtr[0];
|
||||
@ -197,10 +191,43 @@ static U32 LZ4F_readLE32 (const BYTE* srcPtr)
|
||||
return value32;
|
||||
}
|
||||
|
||||
|
||||
static BYTE LZ4F_headerChecksum (const BYTE* header, size_t length)
|
||||
static void LZ4F_writeLE32 (BYTE* dstPtr, U32 value32)
|
||||
{
|
||||
U32 xxh = XXH32(header, (U32)length, 0);
|
||||
dstPtr[0] = (BYTE)value32;
|
||||
dstPtr[1] = (BYTE)(value32 >> 8);
|
||||
dstPtr[2] = (BYTE)(value32 >> 16);
|
||||
dstPtr[3] = (BYTE)(value32 >> 24);
|
||||
}
|
||||
|
||||
static U64 LZ4F_readLE64 (const BYTE* srcPtr)
|
||||
{
|
||||
U64 value64 = srcPtr[0];
|
||||
value64 += (srcPtr[1]<<8);
|
||||
value64 += (srcPtr[2]<<16);
|
||||
value64 += (srcPtr[3]<<24);
|
||||
value64 += ((U64)srcPtr[4]<<32);
|
||||
value64 += ((U64)srcPtr[5]<<40);
|
||||
value64 += ((U64)srcPtr[6]<<48);
|
||||
value64 += ((U64)srcPtr[7]<<56);
|
||||
return value64;
|
||||
}
|
||||
|
||||
static void LZ4F_writeLE64 (BYTE* dstPtr, U64 value64)
|
||||
{
|
||||
dstPtr[0] = (BYTE)value64;
|
||||
dstPtr[1] = (BYTE)(value64 >> 8);
|
||||
dstPtr[2] = (BYTE)(value64 >> 16);
|
||||
dstPtr[3] = (BYTE)(value64 >> 24);
|
||||
dstPtr[4] = (BYTE)(value64 >> 32);
|
||||
dstPtr[5] = (BYTE)(value64 >> 40);
|
||||
dstPtr[6] = (BYTE)(value64 >> 48);
|
||||
dstPtr[7] = (BYTE)(value64 >> 56);
|
||||
}
|
||||
|
||||
|
||||
static BYTE LZ4F_headerChecksum (const void* header, size_t length)
|
||||
{
|
||||
U32 xxh = XXH32(header, length, 0);
|
||||
return (BYTE)(xxh >> 8);
|
||||
}
|
||||
|
||||
@ -235,7 +262,7 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
|
||||
prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
|
||||
prefs.autoFlush = 1;
|
||||
|
||||
headerSize = 7; /* basic header size (no option) including magic number */
|
||||
headerSize = 15; /* header size, including magic number and frame content size*/
|
||||
streamSize = LZ4F_compressBound(srcSize, &prefs);
|
||||
|
||||
return headerSize + streamSize;
|
||||
@ -269,7 +296,13 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuf
|
||||
cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent allocation; works because autoflush==1 & stableSrc==1 */
|
||||
|
||||
if (preferencesPtr!=NULL) prefs = *preferencesPtr;
|
||||
else memset(&prefs, 0, sizeof(prefs));
|
||||
else
|
||||
{
|
||||
memset(&prefs, 0, sizeof(prefs));
|
||||
prefs.frameInfo.frameOSize = (U64)srcSize;
|
||||
}
|
||||
if (prefs.frameInfo.frameOSize != 0)
|
||||
prefs.frameInfo.frameOSize = (U64)srcSize; /* correct frame size if selected (!=0) */
|
||||
|
||||
if (prefs.compressionLevel < minHClevel)
|
||||
{
|
||||
@ -412,13 +445,22 @@ size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* ds
|
||||
/* FLG Byte */
|
||||
*dstPtr++ = ((1 & _2BITS) << 6) /* Version('01') */
|
||||
+ ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5) /* Block mode */
|
||||
+ (char)((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2); /* Stream checksum */
|
||||
+ (BYTE)((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2) /* Frame checksum */
|
||||
+ (BYTE)((cctxPtr->prefs.frameInfo.frameOSize > 0) << 3); /* Frame content size */
|
||||
/* BD Byte */
|
||||
*dstPtr++ = (char)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
|
||||
*dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
|
||||
/* Optional Frame content size field */
|
||||
if (cctxPtr->prefs.frameInfo.frameOSize)
|
||||
{
|
||||
LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.frameOSize);
|
||||
dstPtr += 8;
|
||||
cctxPtr->totalInSize = 0;
|
||||
}
|
||||
/* CRC Byte */
|
||||
*dstPtr++ = LZ4F_headerChecksum(headerStart, 2);
|
||||
*dstPtr = LZ4F_headerChecksum(headerStart, dstPtr - headerStart);
|
||||
dstPtr++;
|
||||
|
||||
cctxPtr->cStage = 1; /* header written, wait for data block */
|
||||
cctxPtr->cStage = 1; /* header written, now request input data block */
|
||||
|
||||
return (dstPtr - dstStart);
|
||||
}
|
||||
@ -608,8 +650,9 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
|
||||
}
|
||||
|
||||
if (cctxPtr->prefs.frameInfo.contentChecksumFlag == contentChecksumEnabled)
|
||||
XXH32_update(&(cctxPtr->xxh), srcBuffer, (unsigned)srcSize);
|
||||
XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
|
||||
|
||||
cctxPtr->totalInSize += srcSize;
|
||||
return dstPtr - dstStart;
|
||||
}
|
||||
|
||||
@ -686,6 +729,12 @@ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstB
|
||||
|
||||
cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
|
||||
|
||||
if (cctxPtr->prefs.frameInfo.frameOSize)
|
||||
{
|
||||
if (cctxPtr->prefs.frameInfo.frameOSize != cctxPtr->totalInSize)
|
||||
return (size_t)-ERROR_frameSize_wrong;
|
||||
}
|
||||
|
||||
return dstPtr - dstStart;
|
||||
}
|
||||
|
||||
@ -735,7 +784,7 @@ typedef enum { dstage_getHeader=0, dstage_storeHeader,
|
||||
dstage_getCBlock, dstage_storeCBlock, dstage_decodeCBlock,
|
||||
dstage_decodeCBlock_intoDst, dstage_decodeCBlock_intoTmp, dstage_flushOut,
|
||||
dstage_getSuffix, dstage_storeSuffix,
|
||||
dstage_getSBlockSize, dstage_storeSBlockSize,
|
||||
dstage_getSFrameSize, dstage_storeSFrameSize,
|
||||
dstage_skipSkippable
|
||||
} dStage_t;
|
||||
|
||||
@ -745,72 +794,84 @@ typedef enum { dstage_getHeader=0, dstage_storeHeader,
|
||||
or an error code (testable with LZ4F_isError())
|
||||
output : set internal values of dctx, such as
|
||||
dctxPtr->frameInfo and dctxPtr->dStage.
|
||||
|
||||
*/
|
||||
static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)
|
||||
{
|
||||
BYTE FLG, BD, HC;
|
||||
unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictFlag, blockSizeID;
|
||||
unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;
|
||||
size_t bufferNeeded;
|
||||
size_t frameHeaderSize;
|
||||
const BYTE* srcPtr = (const BYTE*)srcVoidPtr;
|
||||
|
||||
/* need to decode header to get frameInfo */
|
||||
if (srcSize < 7) return (size_t)-ERROR_GENERIC; /* minimal header size */
|
||||
if (srcSize < minFHSize) return (size_t)-ERROR_GENERIC; /* minimal header size */
|
||||
memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));
|
||||
|
||||
/* skippable frames */
|
||||
if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
|
||||
{
|
||||
memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));
|
||||
dctxPtr->frameInfo.frameType = skippableFrame;
|
||||
if (srcVoidPtr == (void*)(dctxPtr->header))
|
||||
{
|
||||
memcpy(dctxPtr->header, dctxPtr->header + 4, srcSize-4);
|
||||
dctxPtr->tmpInSize = srcSize-4;
|
||||
dctxPtr->dStage = dstage_storeSBlockSize;
|
||||
dctxPtr->tmpInSize = srcSize;
|
||||
dctxPtr->tmpInTarget = 8;
|
||||
dctxPtr->dStage = dstage_storeSFrameSize;
|
||||
return srcSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
dctxPtr->dStage = dstage_getSBlockSize;
|
||||
dctxPtr->dStage = dstage_getSFrameSize;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* control magic number */
|
||||
if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return (size_t)-ERROR_GENERIC;
|
||||
srcPtr += 4;
|
||||
if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return (size_t)-ERROR_frameType_unknown;
|
||||
dctxPtr->frameInfo.frameType = LZ4F_frame;
|
||||
|
||||
/* Flags */
|
||||
FLG = srcPtr[0];
|
||||
FLG = srcPtr[4];
|
||||
version = (FLG>>6) & _2BITS;
|
||||
blockMode = (FLG>>5) & _1BIT;
|
||||
blockChecksumFlag = (FLG>>4) & _1BIT;
|
||||
contentSizeFlag = (FLG>>3) & _1BIT;
|
||||
contentChecksumFlag = (FLG>>2) & _1BIT;
|
||||
dictFlag = (FLG>>0) & _1BIT;
|
||||
BD = srcPtr[1];
|
||||
blockSizeID = (BD>>4) & _3BITS;
|
||||
|
||||
/* check */
|
||||
HC = LZ4F_headerChecksum(srcPtr, 2);
|
||||
if (HC != srcPtr[2]) return (size_t)-ERROR_GENERIC; /* Bad header checksum error */
|
||||
/* Frame Header Size */
|
||||
frameHeaderSize = contentSizeFlag ? 15 : 7;
|
||||
|
||||
if (srcSize < frameHeaderSize)
|
||||
{
|
||||
if (srcPtr != dctxPtr->header)
|
||||
memcpy(dctxPtr->header, srcPtr, srcSize);
|
||||
dctxPtr->tmpInSize = srcSize;
|
||||
dctxPtr->tmpInTarget = frameHeaderSize;
|
||||
dctxPtr->dStage = dstage_storeHeader;
|
||||
return srcSize;
|
||||
}
|
||||
|
||||
BD = srcPtr[5];
|
||||
blockSizeID = (BD>>4) & _3BITS;
|
||||
|
||||
/* validate */
|
||||
if (version != 1) return (size_t)-ERROR_GENERIC; /* Version Number, only supported value */
|
||||
if (blockChecksumFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
|
||||
if (contentSizeFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
|
||||
if (((FLG>>1)&_1BIT) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bit */
|
||||
if (dictFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
|
||||
if (((FLG>>0)&_2BITS) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bits */
|
||||
if (((BD>>7)&_1BIT) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bit */
|
||||
if (blockSizeID < 4) return (size_t)-ERROR_GENERIC; /* 4-7 only supported values for the time being */
|
||||
if (((BD>>0)&_4BITS) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bits */
|
||||
|
||||
/* check */
|
||||
HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
|
||||
if (HC != srcPtr[frameHeaderSize-1]) return (size_t)-ERROR_GENERIC; /* Bad header checksum error */
|
||||
|
||||
/* save */
|
||||
dctxPtr->frameInfo.blockMode = (blockMode_t)blockMode;
|
||||
dctxPtr->frameInfo.contentChecksumFlag = (contentChecksum_t)contentChecksumFlag;
|
||||
dctxPtr->frameInfo.blockSizeID = (blockSizeID_t)blockSizeID;
|
||||
dctxPtr->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
|
||||
if (contentSizeFlag)
|
||||
dctxPtr->frameInfo.frameOSize = LZ4F_readLE64(srcPtr+6);
|
||||
|
||||
/* init */
|
||||
if (contentChecksumFlag) XXH32_reset(&(dctxPtr->xxh), 0);
|
||||
@ -837,7 +898,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVo
|
||||
|
||||
dctxPtr->dStage = dstage_getCBlockSize;
|
||||
|
||||
return 7;
|
||||
return frameHeaderSize;
|
||||
}
|
||||
|
||||
|
||||
@ -872,15 +933,14 @@ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t decompressionCont
|
||||
}
|
||||
|
||||
|
||||
/* redirector, with common prototype */
|
||||
static int LZ4F_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
(void)dictStart;
|
||||
(void)dictSize;
|
||||
(void)dictStart; (void)dictSize;
|
||||
return LZ4_decompress_safe (source, dest, compressedSize, maxDecompressedSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void LZ4F_updateDict(LZ4F_dctx_internal_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
|
||||
{
|
||||
if (dctxPtr->dictSize==0)
|
||||
@ -1011,23 +1071,24 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
|
||||
break;
|
||||
}
|
||||
dctxPtr->tmpInSize = 0;
|
||||
dctxPtr->tmpInTarget = 7;
|
||||
dctxPtr->dStage = dstage_storeHeader;
|
||||
}
|
||||
|
||||
case dstage_storeHeader:
|
||||
{
|
||||
size_t sizeToCopy = 7 - dctxPtr->tmpInSize;
|
||||
size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
|
||||
if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
|
||||
memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
|
||||
dctxPtr->tmpInSize += sizeToCopy;
|
||||
srcPtr += sizeToCopy;
|
||||
if (dctxPtr->tmpInSize < 7)
|
||||
if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget)
|
||||
{
|
||||
nextSrcSizeHint = (7 - dctxPtr->tmpInSize) + 4;
|
||||
doAnotherStage = 0; /* not enough src data, wait to get some more */
|
||||
nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + 4;
|
||||
doAnotherStage = 0; /* not enough src data, ask for some more */
|
||||
break;
|
||||
}
|
||||
LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, dctxPtr->header, 7);
|
||||
LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, dctxPtr->header, dctxPtr->tmpInTarget);
|
||||
if (LZ4F_isError(errorCode)) return errorCode;
|
||||
break;
|
||||
}
|
||||
@ -1292,7 +1353,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
|
||||
break;
|
||||
}
|
||||
|
||||
case dstage_getSBlockSize:
|
||||
case dstage_getSFrameSize:
|
||||
{
|
||||
if ((srcEnd - srcPtr) >= 4)
|
||||
{
|
||||
@ -1302,32 +1363,34 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
|
||||
else
|
||||
{
|
||||
/* not enough input to read cBlockSize field */
|
||||
dctxPtr->tmpInSize = 0;
|
||||
dctxPtr->dStage = dstage_storeSBlockSize;
|
||||
dctxPtr->tmpInSize = 4;
|
||||
dctxPtr->tmpInTarget = 8;
|
||||
dctxPtr->dStage = dstage_storeSFrameSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (dctxPtr->dStage == dstage_storeSBlockSize)
|
||||
case dstage_storeSBlockSize:
|
||||
if (dctxPtr->dStage == dstage_storeSFrameSize)
|
||||
case dstage_storeSFrameSize:
|
||||
{
|
||||
size_t sizeToCopy = 4 - dctxPtr->tmpInSize;
|
||||
size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
|
||||
if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
|
||||
memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
|
||||
srcPtr += sizeToCopy;
|
||||
dctxPtr->tmpInSize += sizeToCopy;
|
||||
if (dctxPtr->tmpInSize < 4) /* not enough input to get full sBlockSize; wait for more */
|
||||
if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* not enough input to get full sBlockSize; wait for more */
|
||||
{
|
||||
nextSrcSizeHint = 4 - dctxPtr->tmpInSize;
|
||||
doAnotherStage=0;
|
||||
nextSrcSizeHint = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
|
||||
doAnotherStage = 0;
|
||||
break;
|
||||
}
|
||||
selectedIn = dctxPtr->header;
|
||||
selectedIn = dctxPtr->header + 4;
|
||||
}
|
||||
|
||||
/* case dstage_decodeSBlockSize: */ /* no direct access */
|
||||
{
|
||||
size_t nextSBlockSize = LZ4F_readLE32(selectedIn);
|
||||
dctxPtr->tmpInTarget = nextSBlockSize;
|
||||
size_t SFrameSize = LZ4F_readLE32(selectedIn);
|
||||
dctxPtr->frameInfo.frameOSize = SFrameSize;
|
||||
dctxPtr->tmpInTarget = SFrameSize;
|
||||
dctxPtr->dStage = dstage_skipSkippable;
|
||||
break;
|
||||
}
|
||||
|
@ -68,18 +68,19 @@ typedef enum { noContentChecksum=0, contentChecksumEnabled } contentChecksum_t;
|
||||
typedef enum { LZ4F_frame=0, skippableFrame } frameType_t;
|
||||
|
||||
typedef struct {
|
||||
blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
frameType_t frameType; /* LZ4F_frame, skippableFrame : 0 == default */
|
||||
unsigned reserved[4];
|
||||
blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
frameType_t frameType; /* LZ4F_frame, skippableFrame ; 0 == default */
|
||||
unsigned long long frameOSize; /* Size of uncompressed (original) content ; 0 == unknown */
|
||||
unsigned reserved[2]; /* must be zero for forward compatibility */
|
||||
} LZ4F_frameInfo_t;
|
||||
|
||||
typedef struct {
|
||||
LZ4F_frameInfo_t frameInfo;
|
||||
unsigned compressionLevel; /* 0 == default (fast mode); values above 16 count as 16 */
|
||||
unsigned autoFlush; /* 1 == always flush : reduce need for tmp buffer */
|
||||
unsigned reserved[4];
|
||||
unsigned autoFlush; /* 1 == always flush (reduce need for tmp buffer) */
|
||||
unsigned reserved[4]; /* must be zero for forward compatibility */
|
||||
} LZ4F_preferences_t;
|
||||
|
||||
|
||||
@ -131,7 +132,7 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp
|
||||
size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
/* LZ4F_compressBegin() :
|
||||
* will write the frame header into dstBuffer.
|
||||
* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 19 bytes.
|
||||
* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
|
||||
* The LZ4F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.
|
||||
* The result of the function is the number of bytes written into dstBuffer for the header
|
||||
* or an error code (can be tested using LZ4F_isError())
|
||||
|
@ -52,6 +52,8 @@ extern "C" {
|
||||
ITEM(ERROR_compressionLevel_invalid) \
|
||||
ITEM(ERROR_allocation_failed) \
|
||||
ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \
|
||||
ITEM(ERROR_frameSize_wrong) \
|
||||
ITEM(ERROR_frameType_unknown) \
|
||||
ITEM(ERROR_wrongSrcPtr) \
|
||||
ITEM(ERROR_decompressionFailed) \
|
||||
ITEM(ERROR_checksum_invalid) \
|
||||
|
@ -381,6 +381,57 @@ int basicTests(U32 seed, double compressibility)
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
{
|
||||
size_t errorCode;
|
||||
BYTE* const ostart = (BYTE*)compressedBuffer;
|
||||
BYTE* op = ostart;
|
||||
LZ4F_compressionContext_t cctx;
|
||||
errorCode = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
|
||||
DISPLAYLEVEL(3, "compress without frameSize : \n");
|
||||
memset(&(prefs.frameInfo), 0, sizeof(prefs.frameInfo));
|
||||
errorCode = LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
|
||||
|
||||
DISPLAYLEVEL(3, "compress with frameSize : \n");
|
||||
prefs.frameInfo.frameOSize = testSize;
|
||||
op = ostart;
|
||||
errorCode = LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
|
||||
|
||||
DISPLAYLEVEL(3, "compress with wrong frameSize : \n");
|
||||
prefs.frameInfo.frameOSize = testSize+1;
|
||||
op = ostart;
|
||||
errorCode = LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += errorCode;
|
||||
errorCode = LZ4F_compressEnd(cctx, op, testSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) { DISPLAYLEVEL(3, "Error correctly detected : %s \n", LZ4F_getErrorName(errorCode)); }
|
||||
else
|
||||
goto _output_error;
|
||||
|
||||
errorCode = LZ4F_freeCompressionContext(cctx);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "Skippable frame test : \n");
|
||||
{
|
||||
size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
@ -412,11 +463,13 @@ int basicTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)decodedBufferSize);
|
||||
|
||||
/* generate zero-size skippable frame */
|
||||
DISPLAYLEVEL(3, "zero-size skippable frame\n");
|
||||
ip = (BYTE*)compressedBuffer;
|
||||
op = (BYTE*)decodedBuffer;
|
||||
FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+1);
|
||||
FUZ_writeLE32(ip+4, 0);
|
||||
iend = ip+8;
|
||||
|
||||
DISPLAYLEVEL(3, "random segment sizes : \n");
|
||||
while (ip < iend)
|
||||
{
|
||||
unsigned nbBits = FUZ_rand(&randState) % maxBits;
|
||||
@ -428,8 +481,27 @@ int basicTests(U32 seed, double compressibility)
|
||||
op += oSize;
|
||||
ip += iSize;
|
||||
}
|
||||
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)decodedBufferSize);
|
||||
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
|
||||
|
||||
DISPLAYLEVEL(3, "Skippable frame header complete in first call \n");
|
||||
ip = (BYTE*)compressedBuffer;
|
||||
op = (BYTE*)decodedBuffer;
|
||||
FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+2);
|
||||
FUZ_writeLE32(ip+4, 10);
|
||||
iend = ip+18;
|
||||
while (ip < iend)
|
||||
{
|
||||
size_t iSize = 10;
|
||||
size_t oSize = 10;
|
||||
if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
|
||||
errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += oSize;
|
||||
ip += iSize;
|
||||
}
|
||||
DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
|
||||
|
||||
/* release memory */
|
||||
errorCode = LZ4F_freeDecompressionContext(dCtx);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
}
|
||||
|
@ -625,7 +625,7 @@ static unsigned long long decodeLZ4S(FILE* finput, FILE* foutput)
|
||||
if (seekResult != 0) EXM_THROW(68, "1 GB skip error (sparse file)");
|
||||
storedSkips -= 1 GB;
|
||||
}
|
||||
if (nb0T != seg0SizeT)
|
||||
if (nb0T != seg0SizeT) /* not all 0s */
|
||||
{
|
||||
seekResult = fseek(foutput, storedSkips, SEEK_CUR);
|
||||
if (seekResult) EXM_THROW(68, "Skip error (sparse file)");
|
||||
|
Loading…
Reference in New Issue
Block a user