From d1d1f8835de315ce401c8d1309ba648539878a64 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 7 Sep 2014 12:57:09 +0100 Subject: [PATCH] API change : compressionContext more easily reusable --- lz4frame.c | 39 ++++++++++++++++++++++----------------- lz4frame.h | 14 +++++++------- programs/frametest.c | 32 +++++++++++++++++--------------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/lz4frame.c b/lz4frame.c index 19b228c..eaa8408 100644 --- a/lz4frame.c +++ b/lz4frame.c @@ -117,6 +117,7 @@ typedef struct { unsigned version; unsigned cStage; size_t maxBlockSize; + size_t maxBufferSize; XXH32_stateSpace_t xxh; BYTE* tmpIn; size_t tmpInSize; @@ -254,10 +255,10 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuf if (dstMaxSize < LZ4F_compressFrameBound(srcSize, frameInfoPtr)) return -ERROR_dstMaxSize_tooSmall; - errorCode = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION, preferencesPtr); + errorCode = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION); if (LZ4F_isError(errorCode)) return errorCode; - errorCode = LZ4F_compressBegin(cctx, dstBuffer, dstMaxSize); /* write header */ + errorCode = LZ4F_compressBegin(cctx, dstBuffer, dstMaxSize, preferencesPtr); /* write header */ if (LZ4F_isError(errorCode)) return errorCode; dstPtr += errorCode; /* header size */ @@ -297,30 +298,19 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuf * The first thing to do is to create a compressionContext object, which will be used in all compression operations. * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure. * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries. - * The LZ4F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default. - * The function will provide a pointer to a fully allocated LZ4F_compressionContext_t object. - * If the result LZ4F_errorCode_t is not zero, there was an error during context creation. + * The function will provide a pointer to an allocated LZ4F_compressionContext_t object. + * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation. * Object can release its memory using LZ4F_freeCompressionContext(); */ -LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, int version, const LZ4F_preferences_t* preferencesPtr) +LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version) { - const LZ4F_preferences_t prefNull = { 0 }; LZ4F_cctx_internal_t* cctxPtr; - if (preferencesPtr == NULL) preferencesPtr = &prefNull; - cctxPtr = ALLOCATOR(sizeof(LZ4F_cctx_internal_t)); if (cctxPtr==NULL) return -ERROR_allocation_failed; - cctxPtr->prefs = *preferencesPtr; /* equivalent to memcpy() */ cctxPtr->version = version; cctxPtr->cStage = 0; /* Next stage : write header */ - if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; - cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID); - cctxPtr->tmpIn = ALLOCATOR(cctxPtr->maxBlockSize); - if (cctxPtr->tmpIn == NULL) return -ERROR_allocation_failed; - cctxPtr->tmpInSize = 0; - XXH32_resetState(&(cctxPtr->xxh), 0); *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr; @@ -345,8 +335,9 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp * 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()) */ -size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize) +size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr) { + LZ4F_preferences_t prefNull = { 0 }; LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)compressionContext; BYTE* const dstStart = (BYTE*)dstBuffer; BYTE* dstPtr = dstStart; @@ -354,6 +345,20 @@ size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* ds if (dstMaxSize < LZ4F_MAXHEADERFRAME_SIZE) return -ERROR_dstMaxSize_tooSmall; if (cctxPtr->cStage != 0) return -ERROR_GENERIC; + if (preferencesPtr == NULL) preferencesPtr = &prefNull; + + /* Buffer Management */ + cctxPtr->prefs = *preferencesPtr; + if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; + cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID); + if (cctxPtr->maxBufferSize < cctxPtr->maxBlockSize) + { + cctxPtr->maxBufferSize = cctxPtr->maxBlockSize; + cctxPtr->tmpIn = ALLOCATOR(cctxPtr->maxBlockSize); + if (cctxPtr->tmpIn == NULL) return -ERROR_allocation_failed; + } + cctxPtr->tmpInSize = 0; + XXH32_resetState(&(cctxPtr->xxh), 0); /* Magic Number */ LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER); diff --git a/lz4frame.h b/lz4frame.h index b4a067e..179271a 100644 --- a/lz4frame.h +++ b/lz4frame.h @@ -124,13 +124,12 @@ typedef struct { /* Resource Management */ #define LZ4F_VERSION 100 -LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, int version, const LZ4F_preferences_t* preferencesPtr); +LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version); LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext); /* LZ4F_createCompressionContext() : * The first thing to do is to create a compressionContext object, which will be used in all compression operations. * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure. * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries. - * The LZ4F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default. * The function will provide a pointer to a fully allocated LZ4F_compressionContext_t object. * If the result LZ4F_errorCode_t is not zero, there was an error during context creation. * Object can release its memory using LZ4F_freeCompressionContext(); @@ -139,10 +138,11 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp /* Compression */ -size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize); +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 accomodate a header (dstMaxSize). Maximum header size is 19 bytes. + * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 19 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()) */ @@ -163,7 +163,7 @@ size_t LZ4F_compress(LZ4F_compressionContext_t compressionContext, void* dstBuff * Conversely, given a fixed dstMaxSize value, you can know the maximum srcSize authorized using LZ4F_getMaxSrcSize() * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode) * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. - * The result of the function is the number of bytes written into dstBuffer (it can be zero, meaning input data is just stored within compressionContext for a future block to complete) + * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just stored within compressionContext * The function outputs an error code if it fails (can be tested using LZ4F_isError()) */ @@ -171,10 +171,10 @@ size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, /* LZ4F_flush() * Should you need to create compressed data immediately, without waiting for a block to be filled, * you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext. + * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. * The result of the function is the number of bytes written into dstBuffer * (it can be zero, this means there was no data left within compressionContext) * The function outputs an error code if it fails (can be tested using LZ4F_isError()) - * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. */ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr); @@ -202,7 +202,7 @@ typedef struct { /* Resource management */ -LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_compressionContext_t* LZ4F_decompressionContextPtr, unsigned versionNumber); +LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_compressionContext_t* LZ4F_decompressionContextPtr, unsigned version); LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_compressionContext_t LZ4F_decompressionContext); /* LZ4F_createDecompressionContext() : * The first thing to do is to create a decompressionContext object, which will be used in all decompression operations. diff --git a/programs/frametest.c b/programs/frametest.c index 6807f4c..c33e1ac 100644 --- a/programs/frametest.c +++ b/programs/frametest.c @@ -363,20 +363,27 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi { unsigned testResult = 0; unsigned testNb = 0; - void* srcBuffer; - void* compressedBuffer; - void* decodedBuffer; + void* srcBuffer = NULL; + void* compressedBuffer = NULL; + void* decodedBuffer = NULL; U32 coreRand = seed; LZ4F_decompressionContext_t dCtx; + LZ4F_compressionContext_t cCtx; + size_t result; # define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \ DISPLAY(" (seed %u, test nb %i) \n", seed, testNb); goto _output_error; } - (void)startTest; - // Create compressible test buffer - LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION); + // Create buffers + result = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION); + CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result); + result = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION); + CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result); srcBuffer = malloc(srcDataLength); + CHECK(srcBuffer==NULL, "srcBuffer Allocation failed"); compressedBuffer = malloc(LZ4F_compressFrameBound(srcDataLength, NULL)); + CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed"); decodedBuffer = malloc(srcDataLength); + CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed"); FUZ_fillCompressibleNoiseBuffer(srcBuffer, srcDataLength, compressibility, &coreRand); // jump to requested testNb @@ -394,7 +401,6 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize); size_t cSize; U64 crcOrig, crcDecoded; - size_t result; DISPLAYUPDATE(2, "\r%5i ", testNb); crcOrig = XXH64(srcBuffer+srcStart, srcSize, 1); @@ -405,10 +411,7 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi BYTE* op = compressedBuffer; BYTE* const oend = op + LZ4F_compressFrameBound(srcDataLength, NULL); unsigned maxBits = FUZ_highbit(srcSize); - LZ4F_compressionContext_t cctx; - result = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION, &prefs); - CHECK(LZ4F_isError(result), "Allocation for compression failed (error %i)", (int)result); - result = LZ4F_compressBegin(cctx, op, oend-op); + result = LZ4F_compressBegin(cCtx, op, oend-op, &prefs); CHECK(LZ4F_isError(result), "Compression header failed (error %i)", (int)result); op += result; while (ip < iend) @@ -417,16 +420,14 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi size_t iSize = (FUZ_rand(&randState) & ((1< (size_t)(iend-ip)) iSize = iend-ip; - result = LZ4F_compress(cctx, op, oSize, ip, iSize, NULL); + result = LZ4F_compress(cCtx, op, oSize, ip, iSize, NULL); CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result); op += result; ip += iSize; } - result = LZ4F_compressEnd(cctx, op, oend-op, NULL); + result = LZ4F_compressEnd(cCtx, op, oend-op, NULL); CHECK(LZ4F_isError(result), "Compression completion failed (error %i)", (int)result); op += result; - result = LZ4F_freeCompressionContext(cctx); - CHECK(LZ4F_isError(result), "deallocation failed (error %i)", (int)result); cSize = op-(BYTE*)compressedBuffer; } @@ -461,6 +462,7 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi _end: LZ4F_freeDecompressionContext(dCtx); + LZ4F_freeCompressionContext(cCtx); free(srcBuffer); free(compressedBuffer); free(decodedBuffer); -- 2.7.4