commit
3f80a22819
2
Makefile
2
Makefile
@ -31,7 +31,7 @@
|
||||
# ################################################################
|
||||
|
||||
# Version numbers
|
||||
VERSION=122
|
||||
VERSION=123
|
||||
export RELEASE=r$(VERSION)
|
||||
LIBVER_MAJOR=`sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < lz4.h`
|
||||
LIBVER_MINOR=`sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < lz4.h`
|
||||
|
27
lz4.c
27
lz4.c
@ -855,12 +855,12 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
||||
if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
|
||||
if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
|
||||
|
||||
memcpy(safeBuffer, previousDictEnd - dictSize, dictSize);
|
||||
memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
|
||||
|
||||
dict->dictionary = (const BYTE*)safeBuffer;
|
||||
dict->dictSize = (U32)dictSize;
|
||||
|
||||
return 1;
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
@ -870,9 +870,9 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
|
||||
****************************/
|
||||
/*
|
||||
* This generic decompression function cover all use cases.
|
||||
* It shall be instanciated several times, using different sets of directives
|
||||
* It shall be instantiated several times, using different sets of directives
|
||||
* Note that it is essential this generic function is really inlined,
|
||||
* in order to remove useless branches during compilation optimisation.
|
||||
* in order to remove useless branches during compilation optimization.
|
||||
*/
|
||||
FORCE_INLINE int LZ4_decompress_generic(
|
||||
const char* source,
|
||||
@ -1153,14 +1153,29 @@ Advanced decoding functions :
|
||||
the dictionary must be explicitly provided within parameters
|
||||
*/
|
||||
|
||||
FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
|
||||
{
|
||||
if ((dictStart+dictSize == source) && (dictSize >= (int)(64 KB - 1)))
|
||||
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, NULL, 64 KB);
|
||||
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, dictStart, dictSize);
|
||||
}
|
||||
|
||||
int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, dictStart, dictSize);
|
||||
//return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, dictStart, dictSize);
|
||||
return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
|
||||
}
|
||||
|
||||
int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, dictStart, dictSize);
|
||||
//return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, dictStart, dictSize);
|
||||
return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
|
||||
}
|
||||
|
||||
/* debug function */
|
||||
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, dictStart, dictSize);
|
||||
}
|
||||
|
||||
|
||||
|
27
lz4.h
27
lz4.h
@ -37,13 +37,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lz4.h provides raw compression format functions, for optimal performance and integration into programs.
|
||||
* If you need to generate data using an inter-operable format (respecting the framing specification),
|
||||
* please use lz4frame.h instead.
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
Version
|
||||
**************************************/
|
||||
#define LZ4_VERSION_MAJOR 1 /* for major interface/format changes */
|
||||
#define LZ4_VERSION_MINOR 3 /* for minor interface/format changes */
|
||||
#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||
int LZ4_versionNumber (void);
|
||||
|
||||
@ -142,7 +147,7 @@ LZ4_decompress_fast() :
|
||||
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
|
||||
note : This function fully respect memory boundaries for properly formed compressed data.
|
||||
It is a bit faster than LZ4_decompress_safe().
|
||||
However, it does not provide any protection against intentionnally modified data stream (malicious input).
|
||||
However, it does not provide any protection against intentionally modified data stream (malicious input).
|
||||
Use this function in trusted environment only (data to decode comes from a trusted source).
|
||||
*/
|
||||
int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
|
||||
@ -178,10 +183,9 @@ typedef struct { unsigned int table[LZ4_STREAMSIZE_U32]; } LZ4_stream_t;
|
||||
|
||||
/*
|
||||
* LZ4_resetStream
|
||||
* Use this function to init a newly allocated LZ4_stream_t structure
|
||||
* You can also reset an existing LZ4_stream_t structure
|
||||
* Use this function to init an allocated LZ4_stream_t structure
|
||||
*/
|
||||
void LZ4_resetStream (LZ4_stream_t* LZ4_stream);
|
||||
void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
|
||||
|
||||
/*
|
||||
* If you prefer dynamic allocation methods,
|
||||
@ -217,10 +221,10 @@ int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* s
|
||||
/*
|
||||
* LZ4_saveDict
|
||||
* If previously compressed data block is not guaranteed to remain available at its memory location
|
||||
* save it into a safe place (char* safeBuffer)
|
||||
* save it into a safer place (char* safeBuffer)
|
||||
* Note : you don't need to call LZ4_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call again LZ4_compress_continue()
|
||||
* Return : 1 if OK, 0 if error
|
||||
* Return : dictionary size in bytes, or 0 if error
|
||||
* Note : any dictSize > 64 KB will be interpreted as 64KB.
|
||||
*/
|
||||
int LZ4_saveDict (LZ4_stream_t* LZ4_stream, char* safeBuffer, int dictSize);
|
||||
@ -262,9 +266,9 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks must still be available at the memory position where they were decoded.
|
||||
If it's not possible, save the relevant part of decoded data into a safe buffer,
|
||||
and indicate where its new address using LZ4_setDictDecode()
|
||||
and indicate where its new address using LZ4_setStreamDecode()
|
||||
*/
|
||||
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize);
|
||||
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
|
||||
|
||||
|
||||
@ -273,10 +277,9 @@ Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as
|
||||
a combination of LZ4_setDictDecode() followed by LZ4_decompress_x_continue()
|
||||
all together into a single function call.
|
||||
It doesn't use nor update an LZ4_streamDecode_t structure.
|
||||
They don't use nor update an LZ4_streamDecode_t structure.
|
||||
*/
|
||||
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize);
|
||||
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
|
1127
lz4frame.c
Normal file
1127
lz4frame.c
Normal file
File diff suppressed because it is too large
Load Diff
258
lz4frame.h
Normal file
258
lz4frame.h
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
LZ4 auto-framing library
|
||||
Header File
|
||||
Copyright (C) 2011-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : http://code.google.com/p/lz4/
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
/* LZ4F is a stand-alone API to create LZ4-compressed frames
|
||||
* fully conformant to specification v1.4.1.
|
||||
* All related operations, including memory management, are handled by the library.
|
||||
* You don't need lz4.h when using lz4frame.h.
|
||||
* */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************
|
||||
Note : experimental API.
|
||||
Not yet integrated within lz4 library.
|
||||
****************************************/
|
||||
|
||||
/**************************************
|
||||
Includes
|
||||
**************************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**************************************
|
||||
Error management
|
||||
**************************************/
|
||||
typedef size_t LZ4F_errorCode_t;
|
||||
typedef enum { OK_FrameEnd = 1 } LZ4F_successCodes;
|
||||
typedef enum { OK_NoError = 0, ERROR_GENERIC = 1,
|
||||
ERROR_maxBlockSize_invalid, ERROR_blockMode_invalid, ERROR_contentChecksumFlag_invalid,
|
||||
ERROR_compressionLevel_invalid,
|
||||
ERROR_allocation_failed,
|
||||
ERROR_srcSize_tooLarge, ERROR_dstMaxSize_tooSmall,
|
||||
ERROR_checksum_invalid,
|
||||
ERROR_maxCode
|
||||
} LZ4F_errorCodes; /* error codes are negative unsigned values.
|
||||
Compare function result to (-specificCode) */
|
||||
|
||||
int LZ4F_isError(LZ4F_errorCode_t code); /* Basically : code > -ERROR_maxCode */
|
||||
|
||||
|
||||
/**************************************
|
||||
Framing compression functions
|
||||
**************************************/
|
||||
|
||||
typedef enum { LZ4F_default=0, max64KB=4, max256KB=5, max1MB=6, max4MB=7} blockSizeID_t;
|
||||
typedef enum { blockLinked=0, blockIndependent} blockMode_t;
|
||||
typedef enum { noContentChecksum=0, contentChecksumEnabled } contentChecksum_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 */
|
||||
unsigned reserved[5];
|
||||
} LZ4F_frameInfo_t;
|
||||
|
||||
typedef struct {
|
||||
LZ4F_frameInfo_t frameInfo;
|
||||
unsigned compressionLevel; /* from 0 to 16 */
|
||||
unsigned autoFlush; /* 1 == always flush; reduce need for tmp buffer */
|
||||
unsigned reserved[4];
|
||||
} LZ4F_preferences_t;
|
||||
|
||||
|
||||
|
||||
/***********************************
|
||||
* Simple compression function
|
||||
* *********************************/
|
||||
size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
|
||||
size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
/* LZ4F_compressFrame()
|
||||
* Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.4.1, in a single step.
|
||||
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
|
||||
* You can get the minimum value of dstMaxSize by using LZ4F_compressFrameBound()
|
||||
* If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode)
|
||||
* The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
|
||||
* The result of the function is the number of bytes written into dstBuffer.
|
||||
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* Advanced compression functions
|
||||
* *********************************/
|
||||
|
||||
typedef void* LZ4F_compressionContext_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned stableSrc; /* 1 == src content will remain available on future calls to LZ4F_compress(); avoid saving src content within tmp buffer as future dictionary */
|
||||
unsigned reserved[3];
|
||||
} LZ4F_compressOptions_t;
|
||||
|
||||
/* Resource Management */
|
||||
|
||||
#define LZ4F_VERSION 100
|
||||
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 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();
|
||||
*/
|
||||
|
||||
|
||||
/* Compression */
|
||||
|
||||
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.
|
||||
* 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())
|
||||
*/
|
||||
|
||||
size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
/* LZ4F_compressBound() :
|
||||
* Provides the minimum size of Dst buffer given srcSize to handle worst case situations.
|
||||
* preferencesPtr is optional : you can provide NULL as argument, all preferences will then be set to default.
|
||||
*/
|
||||
|
||||
size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr);
|
||||
/* LZ4F_compressUpdate()
|
||||
* LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
|
||||
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
|
||||
* If this condition is not respected, LZ4F_compress() will fail (result is an errorCode)
|
||||
* You can get the minimum value of dstMaxSize by using LZ4F_compressBound()
|
||||
* 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 was just buffered.
|
||||
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr);
|
||||
/* 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 buffered 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())
|
||||
*/
|
||||
|
||||
size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr);
|
||||
/* LZ4F_compressEnd()
|
||||
* When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
|
||||
* It will flush whatever data remained within compressionContext (like LZ4_flush())
|
||||
* but also properly finalize the frame, with an endMark and a checksum.
|
||||
* The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
|
||||
* 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.
|
||||
* compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
|
||||
*/
|
||||
|
||||
|
||||
/***********************************
|
||||
* Decompression functions
|
||||
* *********************************/
|
||||
|
||||
typedef void* LZ4F_decompressionContext_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned stableDst; /* unused for the time being, must be 0 */
|
||||
unsigned reserved[3];
|
||||
} LZ4F_decompressOptions_t;
|
||||
|
||||
/* Resource management */
|
||||
|
||||
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.
|
||||
* This is achieved using LZ4F_createDecompressionContext().
|
||||
* The function will provide a pointer to a fully allocated and initialized LZ4F_decompressionContext 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_freeDecompressionContext();
|
||||
*/
|
||||
|
||||
/* Decompression */
|
||||
|
||||
size_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t decompressionContext, LZ4F_frameInfo_t* frameInfoPtr, const void* srcBuffer, size_t* srcSizePtr);
|
||||
/* LZ4F_getFrameInfo()
|
||||
* This function decodes frame header information, such as blockSize.
|
||||
* It is optional : you could start by calling directly LZ4F_decompress() instead.
|
||||
* The objective is to extract header information without starting decompression, typically for allocation purposes.
|
||||
* LZ4F_getFrameInfo() can also be used *after* starting decompression, on a valid LZ4F_decompressionContext_t.
|
||||
* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)
|
||||
* The function result is an hint of the better srcSize to use for next call to LZ4F_decompress,
|
||||
* or an error code which can be tested using LZ4F_isError().
|
||||
*/
|
||||
|
||||
size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext, void* dstBuffer, size_t* dstSizePtr, const void* srcBuffer, size_t* srcSizePtr, const LZ4F_decompressOptions_t* decompressOptionsPtr);
|
||||
/* LZ4F_decompress()
|
||||
* Call this function repetitively to regenerate data compressed within srcBuffer.
|
||||
* The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
|
||||
*
|
||||
* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
|
||||
*
|
||||
* The number of bytes effectively used from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.
|
||||
* This typically happens when dstBuffer is not large enough to contain all decoded data.
|
||||
* LZ4F_decompress() will have to be called again, starting from where it stopped (srcBuffer + *srcSizePtr)
|
||||
* The function will check this condition, and refuse to continue if it is not respected.
|
||||
* dstBuffer is supposed to be flushed between calls to the function, since its content will be rewritten.
|
||||
* Different dst arguments can be used between each calls.
|
||||
*
|
||||
* The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
|
||||
* Basically, it's the size of the current (or remaining) compressed block + header of next block.
|
||||
* Respecting the hint provides some boost to performance, since it allows less buffer shuffling.
|
||||
* Note that this is just a hint, you can always provide any srcSize you want.
|
||||
* When a frame is fully decoded, the function result will be 0.
|
||||
* If decompression failed, function result is an error code which can be tested using LZ4F_isError().
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
@ -30,7 +30,7 @@
|
||||
# fullbench32: Same as fullbench, but forced to compile in 32-bits mode
|
||||
# ##########################################################################
|
||||
|
||||
RELEASE=r122
|
||||
RELEASE=r123
|
||||
|
||||
DESTDIR?=
|
||||
PREFIX ?= /usr
|
||||
@ -68,7 +68,7 @@ endif
|
||||
|
||||
default: lz4 lz4c
|
||||
|
||||
all: lz4 lz4c lz4c32 fullbench fullbench32 fuzzer fuzzer32 datagen
|
||||
all: lz4 lz4c lz4c32 fullbench fullbench32 fuzzer fuzzer32 frametest datagen
|
||||
|
||||
lz4: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
|
||||
$(CC) $(FLAGS) -DDISABLE_LZ4C_LEGACY_OPTIONS $^ -o $@$(EXT)
|
||||
@ -79,10 +79,10 @@ lz4c : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
|
||||
lz4c32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c bench.c xxhash.c lz4io.c lz4cli.c
|
||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fullbench : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fullbench.c
|
||||
fullbench : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/lz4frame.c xxhash.c fullbench.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fullbench32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fullbench.c
|
||||
fullbench32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/lz4frame.c xxhash.c fullbench.c
|
||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fuzzer : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
|
||||
@ -91,6 +91,9 @@ fuzzer : $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
|
||||
fuzzer32: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c fuzzer.c
|
||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
frametest: $(LZ4DIR)/lz4frame.c $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c xxhash.c frametest.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
datagen : datagen.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
@ -99,7 +102,8 @@ clean:
|
||||
@rm -f core *.o \
|
||||
lz4$(EXT) lz4c$(EXT) lz4c32$(EXT) \
|
||||
fullbench$(EXT) fullbench32$(EXT) \
|
||||
fuzzer$(EXT) fuzzer32$(EXT) datagen$(EXT)
|
||||
fuzzer$(EXT) fuzzer32$(EXT) \
|
||||
frametest$(EXT) datagen$(EXT)
|
||||
@echo Cleaning completed
|
||||
|
||||
|
||||
@ -128,7 +132,7 @@ uninstall:
|
||||
[ -f $(DESTDIR)$(MANDIR)/lz4cat.1 ] && rm -f $(DESTDIR)$(MANDIR)/lz4cat.1
|
||||
@echo lz4 successfully uninstalled
|
||||
|
||||
test-native: test-lz4 test-lz4c test-fullbench test-fuzzer test-mem
|
||||
test-native: test-lz4 test-lz4c test-frame test-fullbench test-fuzzer test-mem
|
||||
|
||||
test-force32: test-lz4c32 test-fullbench32 test-fuzzer32 test-mem32
|
||||
|
||||
@ -165,7 +169,10 @@ test-fuzzer: fuzzer
|
||||
test-fuzzer32: fuzzer32
|
||||
./fuzzer32 --no-prompt
|
||||
|
||||
test-mem: lz4 datagen
|
||||
test-frame: frametest
|
||||
./frametest
|
||||
|
||||
test-mem: lz4 datagen frametest
|
||||
./datagen -g16KB > tmp
|
||||
valgrind ./lz4 -9 -BD -f tmp /dev/null
|
||||
./datagen -g16MB > tmp
|
||||
@ -173,6 +180,7 @@ test-mem: lz4 datagen
|
||||
./datagen -g256MB > tmp
|
||||
valgrind ./lz4 -B4D -f tmp /dev/null
|
||||
rm tmp
|
||||
valgrind ./frametest -i100
|
||||
|
||||
test-mem32: lz4c32 datagen
|
||||
# unfortunately, valgrind doesn't seem to work with non-native binary. If someone knows how to do a valgrind-test on a 32-bits exe with a 64-bits system...
|
||||
|
619
programs/frametest.c
Normal file
619
programs/frametest.c
Normal file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
frameTest - test tool for lz4frame
|
||||
Copyright (C) Yann Collet 2014
|
||||
GPL v2 License
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : http://code.google.com/p/lz4/
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
Compiler specific
|
||||
**************************************/
|
||||
#define _CRT_SECURE_NO_WARNINGS // fgets
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
|
||||
#endif
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
Includes
|
||||
**************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h> // fgets, sscanf
|
||||
#include <sys/timeb.h> // timeb
|
||||
#include <string.h> // strcmp
|
||||
#include "lz4frame.h"
|
||||
#include "xxhash.h" // XXH64
|
||||
|
||||
|
||||
/**************************************
|
||||
Basic Types
|
||||
**************************************/
|
||||
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
Constants
|
||||
**************************************/
|
||||
#ifndef LZ4_VERSION
|
||||
# define LZ4_VERSION ""
|
||||
#endif
|
||||
|
||||
#define KB *(1U<<10)
|
||||
#define MB *(1U<<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
static const U32 nbTestsDefault = 128 KB;
|
||||
#define COMPRESSIBLE_NOISE_LENGTH (2 MB)
|
||||
#define FUZ_COMPRESSIBILITY_DEFAULT 50
|
||||
static const U32 prime1 = 2654435761U;
|
||||
static const U32 prime2 = 2246822519U;
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
Macros
|
||||
**************************************/
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
|
||||
#define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
|
||||
if ((FUZ_GetMilliSpan(g_time) > refreshRate) || (displayLevel>=4)) \
|
||||
{ g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
|
||||
if (displayLevel>=4) fflush(stdout); } }
|
||||
static const U32 refreshRate = 150;
|
||||
static U32 g_time = 0;
|
||||
|
||||
|
||||
/*****************************************
|
||||
Local Parameters
|
||||
*****************************************/
|
||||
static U32 no_prompt = 0;
|
||||
static char* programName;
|
||||
static U32 displayLevel = 2;
|
||||
|
||||
|
||||
/*********************************************************
|
||||
Fuzzer functions
|
||||
*********************************************************/
|
||||
static U32 FUZ_GetMilliStart(void)
|
||||
{
|
||||
struct timeb tb;
|
||||
U32 nCount;
|
||||
ftime( &tb );
|
||||
nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
|
||||
return nCount;
|
||||
}
|
||||
|
||||
|
||||
static U32 FUZ_GetMilliSpan(U32 nTimeStart)
|
||||
{
|
||||
U32 nCurrent = FUZ_GetMilliStart();
|
||||
U32 nSpan = nCurrent - nTimeStart;
|
||||
if (nTimeStart > nCurrent)
|
||||
nSpan += 0x100000 * 1000;
|
||||
return nSpan;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
unsigned int FUZ_rand(unsigned int* src)
|
||||
{
|
||||
U32 rand32 = *src;
|
||||
rand32 *= prime1;
|
||||
rand32 += prime2;
|
||||
rand32 = FUZ_rotl32(rand32, 13);
|
||||
*src = rand32;
|
||||
return rand32 >> 5;
|
||||
}
|
||||
|
||||
|
||||
#define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
|
||||
#define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
|
||||
static void FUZ_fillCompressibleNoiseBuffer(void* buffer, unsigned bufferSize, double proba, U32* seed)
|
||||
{
|
||||
BYTE* BBuffer = (BYTE*)buffer;
|
||||
unsigned pos = 0;
|
||||
U32 P32 = (U32)(32768 * proba);
|
||||
|
||||
// First Byte
|
||||
BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
|
||||
|
||||
while (pos < bufferSize)
|
||||
{
|
||||
// Select : Literal (noise) or copy (within 64K)
|
||||
if (FUZ_RAND15BITS < P32)
|
||||
{
|
||||
// Copy (within 64K)
|
||||
unsigned match, end;
|
||||
unsigned length = FUZ_RANDLENGTH + 4;
|
||||
unsigned offset = FUZ_RAND15BITS + 1;
|
||||
if (offset > pos) offset = pos;
|
||||
if (pos + length > bufferSize) length = bufferSize - pos;
|
||||
match = pos - offset;
|
||||
end = pos + length;
|
||||
while (pos < end) BBuffer[pos++] = BBuffer[match++];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Literal (noise)
|
||||
unsigned end;
|
||||
unsigned length = FUZ_RANDLENGTH;
|
||||
if (pos + length > bufferSize) length = bufferSize - pos;
|
||||
end = pos + length;
|
||||
while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned FUZ_highbit(U32 v32)
|
||||
{
|
||||
unsigned nbBits = 0;
|
||||
if (v32==0) return 0;
|
||||
while (v32) { v32 >>= 1; nbBits ++; }
|
||||
return nbBits;
|
||||
}
|
||||
|
||||
|
||||
int basicTests(U32 seed, double compressibility)
|
||||
{
|
||||
int testResult = 0;
|
||||
void* CNBuffer;
|
||||
void* compressedBuffer;
|
||||
void* decodedBuffer;
|
||||
U32 randState = seed;
|
||||
size_t cSize, testSize;
|
||||
LZ4F_preferences_t prefs = { 0 };
|
||||
LZ4F_decompressionContext_t dCtx;
|
||||
U64 crcOrig;
|
||||
|
||||
// Create compressible test buffer
|
||||
CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
|
||||
compressedBuffer = malloc(LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL));
|
||||
decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
|
||||
FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
|
||||
crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
|
||||
|
||||
// Trivial tests : one-step frame
|
||||
testSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
DISPLAYLEVEL(3, "Using NULL preferences : \n");
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Decompression test : \n");
|
||||
{
|
||||
size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
size_t compressedBufferSize = cSize;
|
||||
BYTE* op = (BYTE*)decodedBuffer;
|
||||
BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
|
||||
BYTE* ip = (BYTE*)compressedBuffer;
|
||||
BYTE* const iend = (BYTE*)compressedBuffer + cSize;
|
||||
U64 crcDest;
|
||||
|
||||
LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
|
||||
DISPLAYLEVEL(3, "Single Block : \n");
|
||||
errorCode = LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL);
|
||||
crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
|
||||
if (crcDest != crcOrig) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Byte after byte : \n");
|
||||
while (ip < iend)
|
||||
{
|
||||
size_t oSize = oend-op;
|
||||
size_t iSize = 1;
|
||||
//DISPLAY("%7i \n", (int)(ip-(BYTE*)compressedBuffer));
|
||||
errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += oSize;
|
||||
ip += iSize;
|
||||
}
|
||||
crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
|
||||
if (crcDest != crcOrig) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
|
||||
|
||||
errorCode = LZ4F_freeDecompressionContext(dCtx);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "Using 64 KB block : \n");
|
||||
prefs.frameInfo.blockSizeID = max64KB;
|
||||
prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "without checksum : \n");
|
||||
prefs.frameInfo.contentChecksumFlag = noContentChecksum;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Using 256 KB block : \n");
|
||||
prefs.frameInfo.blockSizeID = max256KB;
|
||||
prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Decompression test : \n");
|
||||
{
|
||||
size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
unsigned maxBits = FUZ_highbit(decodedBufferSize);
|
||||
BYTE* op = (BYTE*)decodedBuffer;
|
||||
BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
|
||||
BYTE* ip = (BYTE*)compressedBuffer;
|
||||
BYTE* const iend = (BYTE*)compressedBuffer + cSize;
|
||||
U64 crcDest;
|
||||
|
||||
LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
|
||||
DISPLAYLEVEL(3, "random segment sizes : \n");
|
||||
while (ip < iend)
|
||||
{
|
||||
unsigned nbBits = FUZ_rand(&randState) % maxBits;
|
||||
size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
|
||||
size_t oSize = oend-op;
|
||||
if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
|
||||
//DISPLAY("%7i : + %6i\n", (int)(ip-(BYTE*)compressedBuffer), (int)iSize);
|
||||
errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
op += oSize;
|
||||
ip += iSize;
|
||||
}
|
||||
crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
|
||||
if (crcDest != crcOrig) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
|
||||
|
||||
errorCode = LZ4F_freeDecompressionContext(dCtx);
|
||||
if (LZ4F_isError(errorCode)) goto _output_error;
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "without checksum : \n");
|
||||
prefs.frameInfo.contentChecksumFlag = noContentChecksum;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Using 1 MB block : \n");
|
||||
prefs.frameInfo.blockSizeID = max1MB;
|
||||
prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "without checksum : \n");
|
||||
prefs.frameInfo.contentChecksumFlag = noContentChecksum;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "Using 4 MB block : \n");
|
||||
prefs.frameInfo.blockSizeID = max4MB;
|
||||
prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAYLEVEL(3, "without checksum : \n");
|
||||
prefs.frameInfo.contentChecksumFlag = noContentChecksum;
|
||||
cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs);
|
||||
if (LZ4F_isError(cSize)) goto _output_error;
|
||||
DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
|
||||
|
||||
DISPLAY("Basic tests completed \n");
|
||||
_end:
|
||||
free(CNBuffer);
|
||||
free(compressedBuffer);
|
||||
free(decodedBuffer);
|
||||
return testResult;
|
||||
|
||||
_output_error:
|
||||
testResult = 1;
|
||||
DISPLAY("Error detected ! \n");
|
||||
goto _end;
|
||||
}
|
||||
|
||||
|
||||
static void locateBuffDiff(const void* buff1, const void* buff2, size_t size)
|
||||
{
|
||||
int p=0;
|
||||
BYTE* b1=(BYTE*)buff1;
|
||||
BYTE* b2=(BYTE*)buff2;
|
||||
while (b1[p]==b2[p]) p++;
|
||||
printf("Error at pos %i/%i : %02X != %02X \n", p, (int)size, b1[p], b2[p]);
|
||||
}
|
||||
|
||||
|
||||
static const U32 srcDataLength = 9 MB; /* needs to be > 2x4MB to test large blocks */
|
||||
|
||||
int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility)
|
||||
{
|
||||
unsigned testResult = 0;
|
||||
unsigned testNb = 0;
|
||||
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; }
|
||||
|
||||
// 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
|
||||
for (testNb =0; testNb < startTest; testNb++) (void)FUZ_rand(&coreRand); // sync randomizer
|
||||
|
||||
// main fuzzer loop
|
||||
for ( ; testNb < nbTests; testNb++)
|
||||
{
|
||||
U32 randState = coreRand ^ prime1;
|
||||
unsigned BSId = 4 + (FUZ_rand(&randState) & 3);
|
||||
unsigned BMId = FUZ_rand(&randState) & 1;
|
||||
unsigned CCflag = FUZ_rand(&randState) & 1;
|
||||
unsigned autoflush = (FUZ_rand(&randState) & 3) == 2;
|
||||
LZ4F_preferences_t prefs = { 0 };
|
||||
LZ4F_compressOptions_t options = { 0 };
|
||||
unsigned nbBits = (FUZ_rand(&randState) % (FUZ_highbit(srcDataLength-1) - 1)) + 1;
|
||||
size_t srcSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
|
||||
size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize);
|
||||
size_t cSize;
|
||||
U64 crcOrig, crcDecoded;
|
||||
|
||||
prefs.frameInfo.blockMode = BMId;
|
||||
prefs.frameInfo.blockSizeID = BSId;
|
||||
prefs.frameInfo.contentChecksumFlag = CCflag;
|
||||
prefs.autoFlush = autoflush;
|
||||
|
||||
DISPLAYUPDATE(2, "\r%5i ", testNb);
|
||||
crcOrig = XXH64((BYTE*)srcBuffer+srcStart, srcSize, 1);
|
||||
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)srcBuffer + srcStart;
|
||||
const BYTE* const iend = ip + srcSize;
|
||||
BYTE* op = compressedBuffer;
|
||||
BYTE* const oend = op + LZ4F_compressFrameBound(srcDataLength, NULL);
|
||||
unsigned maxBits = FUZ_highbit(srcSize);
|
||||
result = LZ4F_compressBegin(cCtx, op, oend-op, &prefs);
|
||||
CHECK(LZ4F_isError(result), "Compression header failed (error %i)", (int)result);
|
||||
op += result;
|
||||
while (ip < iend)
|
||||
{
|
||||
unsigned nbBitsSeg = FUZ_rand(&randState) % maxBits;
|
||||
size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
|
||||
size_t oSize = oend-op;
|
||||
unsigned forceFlush = ((FUZ_rand(&randState) & 3) == 1);
|
||||
if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
|
||||
options.stableSrc = ((FUZ_rand(&randState) && 3) == 2);
|
||||
|
||||
result = LZ4F_compressUpdate(cCtx, op, oSize, ip, iSize, &options);
|
||||
CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
|
||||
op += result;
|
||||
ip += iSize;
|
||||
|
||||
if (forceFlush)
|
||||
{
|
||||
result = LZ4F_flush(cCtx, op, oend-op, &options);
|
||||
CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
|
||||
op += result;
|
||||
}
|
||||
}
|
||||
result = LZ4F_compressEnd(cCtx, op, oend-op, &options);
|
||||
CHECK(LZ4F_isError(result), "Compression completion failed (error %i)", (int)result);
|
||||
op += result;
|
||||
cSize = op-(BYTE*)compressedBuffer;
|
||||
}
|
||||
|
||||
{
|
||||
const BYTE* ip = compressedBuffer;
|
||||
const BYTE* const iend = ip + cSize;
|
||||
BYTE* op = decodedBuffer;
|
||||
BYTE* const oend = op + srcDataLength;
|
||||
unsigned maxBits = FUZ_highbit(cSize);
|
||||
while (ip < iend)
|
||||
{
|
||||
unsigned nbBitsI = (FUZ_rand(&randState) % (maxBits-1)) + 1;
|
||||
unsigned nbBitsO = (FUZ_rand(&randState) % (maxBits)) + 1;
|
||||
size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsI)-1)) + 1;
|
||||
size_t oSize = (FUZ_rand(&randState) & ((1<<nbBitsO)-1)) + 2;
|
||||
if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
|
||||
if (oSize > (size_t)(oend-op)) oSize = oend-op;
|
||||
result = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
|
||||
if (result == (size_t)-ERROR_checksum_invalid) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize);
|
||||
CHECK(LZ4F_isError(result), "Decompression failed (error %i)", (int)result);
|
||||
op += oSize;
|
||||
ip += iSize;
|
||||
}
|
||||
CHECK(result != 0, "Frame decompression failed (error %i)", (int)result);
|
||||
crcDecoded = XXH64(decodedBuffer, op-(BYTE*)decodedBuffer, 1);
|
||||
if (crcDecoded != crcOrig) locateBuffDiff((BYTE*)srcBuffer+srcStart, decodedBuffer, srcSize);
|
||||
CHECK(crcDecoded != crcOrig, "Decompression corruption");
|
||||
}
|
||||
|
||||
(void)FUZ_rand(&coreRand); // update rand seed
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(2, "\rAll tests completed \n");
|
||||
|
||||
_end:
|
||||
LZ4F_freeDecompressionContext(dCtx);
|
||||
LZ4F_freeCompressionContext(cCtx);
|
||||
free(srcBuffer);
|
||||
free(compressedBuffer);
|
||||
free(decodedBuffer);
|
||||
return testResult;
|
||||
|
||||
_output_error:
|
||||
testResult = 1;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
|
||||
int FUZ_usage(void)
|
||||
{
|
||||
DISPLAY( "Usage :\n");
|
||||
DISPLAY( " %s [args]\n", programName);
|
||||
DISPLAY( "\n");
|
||||
DISPLAY( "Arguments :\n");
|
||||
DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault);
|
||||
DISPLAY( " -s# : Select seed (default:prompt user)\n");
|
||||
DISPLAY( " -t# : Select starting test number (default:0)\n");
|
||||
DISPLAY( " -p# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
|
||||
DISPLAY( " -v : verbose\n");
|
||||
DISPLAY( " -h : display help and exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
U32 seed=0;
|
||||
int seedset=0;
|
||||
int argNb;
|
||||
int nbTests = nbTestsDefault;
|
||||
int testNb = 0;
|
||||
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
|
||||
int result=0;
|
||||
|
||||
// Check command line
|
||||
programName = argv[0];
|
||||
for(argNb=1; argNb<argc; argNb++)
|
||||
{
|
||||
char* argument = argv[argNb];
|
||||
|
||||
if(!argument) continue; // Protection if argument empty
|
||||
|
||||
// Decode command (note : aggregated commands are allowed)
|
||||
if (argument[0]=='-')
|
||||
{
|
||||
if (!strcmp(argument, "--no-prompt")) { no_prompt=1; seedset=1; displayLevel=1; continue; }
|
||||
|
||||
while (argument[1]!=0)
|
||||
{
|
||||
argument++;
|
||||
switch(*argument)
|
||||
{
|
||||
case 'h':
|
||||
return FUZ_usage();
|
||||
case 'v':
|
||||
argument++;
|
||||
displayLevel=4;
|
||||
break;
|
||||
case 'q':
|
||||
argument++;
|
||||
displayLevel--;
|
||||
break;
|
||||
case 'i':
|
||||
argument++;
|
||||
nbTests=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
nbTests *= 10;
|
||||
nbTests += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
argument++;
|
||||
seed=0; seedset=1;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
seed *= 10;
|
||||
seed += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
argument++;
|
||||
testNb=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
testNb *= 10;
|
||||
testNb += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
argument++;
|
||||
proba=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
proba *= 10;
|
||||
proba += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
if (proba<0) proba=0;
|
||||
if (proba>100) proba=100;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Seed
|
||||
printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
|
||||
|
||||
if (!seedset) seed = FUZ_GetMilliStart() % 10000;
|
||||
printf("Seed = %u\n", seed);
|
||||
if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
|
||||
|
||||
if (nbTests<=0) nbTests=1;
|
||||
|
||||
//if (testNb==0) result = basicTests(seed, ((double)proba) / 100);
|
||||
if (result) return 1;
|
||||
return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
|
||||
}
|
@ -60,10 +60,8 @@
|
||||
#endif
|
||||
|
||||
#include "lz4.h"
|
||||
#define COMPRESSOR0 LZ4_compress
|
||||
#include "lz4hc.h"
|
||||
#define COMPRESSOR1 LZ4_compressHC
|
||||
#define DEFAULTCOMPRESSOR COMPRESSOR0
|
||||
#include "lz4frame.h"
|
||||
|
||||
#include "xxhash.h"
|
||||
|
||||
@ -323,6 +321,11 @@ static int local_LZ4_compressHC_limitedOutput_continue(const char* in, char* out
|
||||
return LZ4_compressHC_limitedOutput_continue(ctx, in, out, inSize, LZ4_compressBound(inSize));
|
||||
}
|
||||
|
||||
static int local_LZ4F_compressFrame(const char* in, char* out, int inSize)
|
||||
{
|
||||
return LZ4F_compressFrame(out, 2*inSize + 16, in, inSize, NULL);
|
||||
}
|
||||
|
||||
static int local_LZ4_decompress_fast(const char* in, char* out, int inSize, int outSize)
|
||||
{
|
||||
(void)inSize;
|
||||
@ -351,26 +354,51 @@ static int local_LZ4_decompress_safe_usingDict(const char* in, char* out, int in
|
||||
return outSize;
|
||||
}
|
||||
|
||||
extern int LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize, const char* dict, int dictSize);
|
||||
|
||||
static int local_LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize)
|
||||
{
|
||||
(void)inSize;
|
||||
LZ4_decompress_safe_forceExtDict(in, out, inSize, outSize, in - 65536, 65536);
|
||||
return outSize;
|
||||
}
|
||||
|
||||
static int local_LZ4_decompress_safe_partial(const char* in, char* out, int inSize, int outSize)
|
||||
{
|
||||
return LZ4_decompress_safe_partial(in, out, inSize, outSize - 5, outSize);
|
||||
}
|
||||
|
||||
static LZ4F_decompressionContext_t g_dCtx;
|
||||
|
||||
static int local_LZ4F_decompress(const char* in, char* out, int inSize, int outSize)
|
||||
{
|
||||
size_t srcSize = inSize;
|
||||
size_t dstSize = outSize;
|
||||
size_t result;
|
||||
result = LZ4F_decompress(g_dCtx, out, &dstSize, in, &srcSize, NULL);
|
||||
if (result!=0) { DISPLAY("Error decompressing frame : unfinished frame\n"); exit(8); }
|
||||
if (srcSize != (size_t)inSize) { DISPLAY("Error decompressing frame : read size incorrect\n"); exit(9); }
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
|
||||
int fullSpeedBench(char** fileNamesTable, int nbFiles)
|
||||
{
|
||||
int fileIdx=0;
|
||||
char* orig_buff;
|
||||
# define NB_COMPRESSION_ALGORITHMS 13
|
||||
# define MINCOMPRESSIONCHAR '0'
|
||||
# define NB_COMPRESSION_ALGORITHMS 14
|
||||
double totalCTime[NB_COMPRESSION_ALGORITHMS+1] = {0};
|
||||
double totalCSize[NB_COMPRESSION_ALGORITHMS+1] = {0};
|
||||
# define NB_DECOMPRESSION_ALGORITHMS 7
|
||||
# define MINDECOMPRESSIONCHAR '0'
|
||||
# define MAXDECOMPRESSIONCHAR (MINDECOMPRESSIONCHAR + NB_DECOMPRESSION_ALGORITHMS)
|
||||
static char* decompressionNames[] = { "LZ4_decompress_fast", "LZ4_decompress_fast_withPrefix64k", "LZ4_decompress_fast_usingDict",
|
||||
"LZ4_decompress_safe", "LZ4_decompress_safe_withPrefix64k", "LZ4_decompress_safe_usingDict", "LZ4_decompress_safe_partial" };
|
||||
# define NB_DECOMPRESSION_ALGORITHMS 9
|
||||
double totalDTime[NB_DECOMPRESSION_ALGORITHMS+1] = {0};
|
||||
size_t errorCode;
|
||||
|
||||
errorCode = LZ4F_createDecompressionContext(&g_dCtx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(errorCode))
|
||||
{
|
||||
DISPLAY("dctx allocation issue \n");
|
||||
return 10;
|
||||
}
|
||||
|
||||
// Loop for each file
|
||||
while (fileIdx<nbFiles)
|
||||
@ -428,22 +456,6 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
|
||||
return 12;
|
||||
}
|
||||
|
||||
// Init chunks data
|
||||
{
|
||||
int i;
|
||||
size_t remaining = benchedSize;
|
||||
char* in = orig_buff;
|
||||
char* out = compressed_buff;
|
||||
for (i=0; i<nbChunks; i++)
|
||||
{
|
||||
chunkP[i].id = i;
|
||||
chunkP[i].origBuffer = in; in += chunkSize;
|
||||
if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }
|
||||
chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize;
|
||||
chunkP[i].compressedSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill input buffer
|
||||
DISPLAY("Loading %s... \r", inFileName);
|
||||
readSize = fread(orig_buff, 1, benchedSize, inFile);
|
||||
@ -471,10 +483,27 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
|
||||
DISPLAY("\r%79s\r", "");
|
||||
DISPLAY(" %s : \n", inFileName);
|
||||
|
||||
// Init chunks data
|
||||
{
|
||||
int i;
|
||||
size_t remaining = benchedSize;
|
||||
char* in = orig_buff;
|
||||
char* out = compressed_buff;
|
||||
nbChunks = (int) ((int)benchedSize / chunkSize) + 1;
|
||||
for (i=0; i<nbChunks; i++)
|
||||
{
|
||||
chunkP[i].id = i;
|
||||
chunkP[i].origBuffer = in; in += chunkSize;
|
||||
if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }
|
||||
chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize;
|
||||
chunkP[i].compressedSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Compression Algorithms
|
||||
for (cAlgNb=1; (cAlgNb <= NB_COMPRESSION_ALGORITHMS) && (compressionTest); cAlgNb++)
|
||||
{
|
||||
char* compressorName;
|
||||
const char* compressorName;
|
||||
int (*compressionFunction)(const char*, char*, int);
|
||||
void* (*initFunction)(const char*) = NULL;
|
||||
double bestTime = 100000000.;
|
||||
@ -496,6 +525,9 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
|
||||
case 11: compressionFunction = local_LZ4_compressHC_continue; initFunction = LZ4_createHC; compressorName = "LZ4_compressHC_continue"; break;
|
||||
case 12: compressionFunction = local_LZ4_compressHC_limitedOutput_continue; initFunction = LZ4_createHC; compressorName = "LZ4_compressHC_limitedOutput_continue"; break;
|
||||
case 13: compressionFunction = local_LZ4_compress_forceDict; initFunction = local_LZ4_resetDictT; compressorName = "LZ4_compress_forceDict"; break;
|
||||
case 14: compressionFunction = local_LZ4F_compressFrame; compressorName = "LZ4F_compressFrame";
|
||||
chunkP[0].origSize = benchedSize; nbChunks=1;
|
||||
break;
|
||||
default : DISPLAY("ERROR ! Bad algorithm Id !! \n"); free(chunkP); return 1;
|
||||
}
|
||||
|
||||
@ -546,29 +578,39 @@ int fullSpeedBench(char** fileNamesTable, int nbFiles)
|
||||
chunkP[chunkNb].compressedSize = LZ4_compress(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);
|
||||
if (chunkP[chunkNb].compressedSize==0) DISPLAY("ERROR ! %s() = 0 !! \n", "LZ4_compress"), exit(1);
|
||||
}
|
||||
{ size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing source area, for CRC checking
|
||||
|
||||
// Decompression Algorithms
|
||||
for (dAlgNb=0; (dAlgNb < NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); dAlgNb++)
|
||||
for (dAlgNb=1; (dAlgNb <= NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); dAlgNb++)
|
||||
{
|
||||
char* dName = decompressionNames[dAlgNb];
|
||||
//const char* dName = decompressionNames[dAlgNb];
|
||||
const char* dName;
|
||||
int (*decompressionFunction)(const char*, char*, int, int);
|
||||
double bestTime = 100000000.;
|
||||
|
||||
if ((decompressionAlgo != ALL_DECOMPRESSORS) && (decompressionAlgo != dAlgNb+1)) continue;
|
||||
if ((decompressionAlgo != ALL_DECOMPRESSORS) && (decompressionAlgo != dAlgNb)) continue;
|
||||
|
||||
switch(dAlgNb)
|
||||
{
|
||||
case 0: decompressionFunction = local_LZ4_decompress_fast; break;
|
||||
case 1: decompressionFunction = local_LZ4_decompress_fast_withPrefix64k; break;
|
||||
case 2: decompressionFunction = local_LZ4_decompress_fast_usingDict; break;
|
||||
case 3: decompressionFunction = LZ4_decompress_safe; break;
|
||||
case 4: decompressionFunction = LZ4_decompress_safe_withPrefix64k; break;
|
||||
case 5: decompressionFunction = local_LZ4_decompress_safe_usingDict; break;
|
||||
case 6: decompressionFunction = local_LZ4_decompress_safe_partial; break;
|
||||
case 1: decompressionFunction = local_LZ4_decompress_fast; dName = "LZ4_decompress_fast"; break;
|
||||
case 2: decompressionFunction = local_LZ4_decompress_fast_withPrefix64k; dName = "LZ4_decompress_fast_withPrefix64k"; break;
|
||||
case 3: decompressionFunction = local_LZ4_decompress_fast_usingDict; dName = "LZ4_decompress_fast_usingDict"; break;
|
||||
case 4: decompressionFunction = LZ4_decompress_safe; dName = "LZ4_decompress_safe"; break;
|
||||
case 5: decompressionFunction = LZ4_decompress_safe_withPrefix64k; dName = "LZ4_decompress_safe_withPrefix64k"; break;
|
||||
case 6: decompressionFunction = local_LZ4_decompress_safe_usingDict; dName = "LZ4_decompress_safe_usingDict"; break;
|
||||
case 7: decompressionFunction = local_LZ4_decompress_safe_partial; dName = "LZ4_decompress_safe_partial"; break;
|
||||
case 8: decompressionFunction = local_LZ4_decompress_safe_forceExtDict; dName = "LZ4_decompress_safe_forceExtDict"; break;
|
||||
case 9: decompressionFunction = local_LZ4F_decompress; dName = "LZ4F_decompress";
|
||||
errorCode = LZ4F_compressFrame(compressed_buff, compressedBuffSize, orig_buff, benchedSize, NULL);
|
||||
if (LZ4F_isError(errorCode)) { DISPLAY("Preparation error compressing frame\n"); return 1; }
|
||||
chunkP[0].origSize = benchedSize;
|
||||
chunkP[0].compressedSize = errorCode;
|
||||
nbChunks = 1;
|
||||
break;
|
||||
default : DISPLAY("ERROR ! Bad decompression algorithm Id !! \n"); free(chunkP); return 1;
|
||||
}
|
||||
|
||||
{ size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing source area, for CRC checking
|
||||
|
||||
for (loopNb = 1; loopNb <= nbIterations; loopNb++)
|
||||
{
|
||||
double averageTime;
|
||||
|
168
xxhash.h
Normal file
168
xxhash.h
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
*/
|
||||
|
||||
/* Notice extracted from xxHash homepage :
|
||||
|
||||
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
|
||||
It also successfully passes all tests from the SMHasher suite.
|
||||
|
||||
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
|
||||
|
||||
Name Speed Q.Score Author
|
||||
xxHash 5.4 GB/s 10
|
||||
CrapWow 3.2 GB/s 2 Andrew
|
||||
MumurHash 3a 2.7 GB/s 10 Austin Appleby
|
||||
SpookyHash 2.0 GB/s 10 Bob Jenkins
|
||||
SBox 1.4 GB/s 9 Bret Mulvey
|
||||
Lookup3 1.2 GB/s 9 Bob Jenkins
|
||||
SuperFastHash 1.2 GB/s 1 Paul Hsieh
|
||||
CityHash64 1.05 GB/s 10 Pike & Alakuijala
|
||||
FNV 0.55 GB/s 5 Fowler, Noll, Vo
|
||||
CRC32 0.43 GB/s 9
|
||||
MD5-32 0.33 GB/s 10 Ronald L. Rivest
|
||||
SHA1-32 0.28 GB/s 10
|
||||
|
||||
Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
Type
|
||||
*****************************/
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
unsigned int XXH32 (const void* input, unsigned int len, unsigned int seed);
|
||||
unsigned long long XXH64 (const void* input, unsigned int len, unsigned long long seed);
|
||||
|
||||
/*
|
||||
XXH32() :
|
||||
Calculate the 32-bits hash of sequence of length "len" stored at memory address "input".
|
||||
The memory between input & input+len must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function successfully passes all SMHasher tests.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, use the advanced functions below.
|
||||
XXH64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
Advanced Hash Functions
|
||||
*****************************/
|
||||
|
||||
void* XXH32_init (unsigned int seed);
|
||||
XXH_errorcode XXH32_update (void* state, const void* input, unsigned int len);
|
||||
unsigned int XXH32_digest (void* state);
|
||||
|
||||
void* XXH64_init (unsigned long long seed);
|
||||
XXH_errorcode XXH64_update (void* state, const void* input, unsigned int len);
|
||||
unsigned long long XXH64_digest (void* state);
|
||||
|
||||
/*
|
||||
These functions calculate the xxhash of an input provided in several small packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
It must be started with :
|
||||
void* XXHnn_init()
|
||||
The function returns a pointer which holds the state of calculation.
|
||||
If the pointer is NULL, allocation has failed, so no state can be tracked.
|
||||
|
||||
The state pointer must be provided as "void* state" parameter for XXHnn_update().
|
||||
XXHnn_update() can be called as many times as necessary.
|
||||
The user must provide a valid (allocated) input.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
Note that "len" is type "int", which means it is limited to 2^31-1.
|
||||
If your data is larger, it is recommended to chunk your data into blocks
|
||||
of size for example 2^30 (1GB) to avoid any "int" overflow issue.
|
||||
|
||||
Finally, you can end the calculation anytime, by using XXHnn_digest().
|
||||
This function returns the final nn-bits hash.
|
||||
You must provide the same "void* state" parameter created by XXHnn_init().
|
||||
Memory will be freed by XXHnn_digest().
|
||||
*/
|
||||
|
||||
|
||||
int XXH32_sizeofState(void);
|
||||
XXH_errorcode XXH32_resetState(void* state, unsigned int seed);
|
||||
|
||||
#define XXH32_SIZEOFSTATE 48
|
||||
typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
|
||||
|
||||
int XXH64_sizeofState(void);
|
||||
XXH_errorcode XXH64_resetState(void* state, unsigned long long seed);
|
||||
|
||||
#define XXH64_SIZEOFSTATE 88
|
||||
typedef struct { long long ll[(XXH64_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH64_stateSpace_t;
|
||||
|
||||
/*
|
||||
These functions allow user application to make its own allocation for state.
|
||||
|
||||
XXHnn_sizeofState() is used to know how much space must be allocated for the xxHash nn-bits state.
|
||||
Note that the state must be aligned to access 'long long' fields. Memory must be allocated and referenced by a pointer.
|
||||
This pointer must then be provided as 'state' into XXHnn_resetState(), which initializes the state.
|
||||
|
||||
For static allocation purposes (such as allocation on stack, or freestanding systems without malloc()),
|
||||
use the structure XXHnn_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields.
|
||||
*/
|
||||
|
||||
|
||||
unsigned int XXH32_intermediateDigest (void* state);
|
||||
unsigned long long XXH64_intermediateDigest (void* state);
|
||||
/*
|
||||
These functions do the same as XXHnn_digest(), generating a nn-bit hash,
|
||||
but preserve memory context.
|
||||
This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXHnn_update().
|
||||
To free memory context, use XXHnn_digest(), or free().
|
||||
*/
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user