mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 04:07:12 -06:00
merge multi threading to master branch
- updated zstd to latest devel release - lz4, lz5 and zstd is included now - all three support threading
This commit is contained in:
1355
C/lz5/lz5.c
Normal file
1355
C/lz5/lz5.c
Normal file
File diff suppressed because it is too large
Load Diff
363
C/lz5/lz5.h
Normal file
363
C/lz5/lz5.h
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2015, 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 :
|
||||
- LZ5 source repository : https://github.com/inikep/lz5
|
||||
- LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lz5.h provides block compression functions, and gives full buffer control to programmer.
|
||||
* If you need to generate inter-operable compressed data (respecting LZ5 frame specification),
|
||||
* and can let the library handle its own memory, please use lz5frame.h instead.
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
* Version
|
||||
**************************************/
|
||||
#define LZ5_VERSION "v1.5.0"
|
||||
#define LZ5_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LZ5_VERSION_MINOR 5 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ5_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ5_VERSION_NUMBER (LZ5_VERSION_MAJOR *100*100 + LZ5_VERSION_MINOR *100 + LZ5_VERSION_RELEASE)
|
||||
int LZ5_versionNumber (void);
|
||||
|
||||
#define LZ5HC_MAX_CLEVEL 15
|
||||
|
||||
|
||||
/**************************************
|
||||
* Tuning parameter
|
||||
**************************************/
|
||||
/*
|
||||
* LZ5_MEMORY_USAGE :
|
||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||
* Increasing memory usage improves compression ratio
|
||||
* Reduced memory usage can improve speed, due to cache effect
|
||||
*/
|
||||
#define LZ5_MEMORY_USAGE 20
|
||||
|
||||
|
||||
/**************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
|
||||
int LZ5_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
int LZ5_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
/*
|
||||
LZ5_compress_default() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= LZ5_compressBound(sourceSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'source' into a more limited 'dest' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
As a consequence, 'dest' content is not valid.
|
||||
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
|
||||
sourceSize : Max supported value is LZ5_MAX_INPUT_VALUE
|
||||
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
|
||||
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
|
||||
or 0 if compression fails
|
||||
|
||||
LZ5_decompress_safe() :
|
||||
compressedSize : is the precise full size of the compressed block.
|
||||
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (<0).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function is protected against buffer overflow exploits, including malicious data packets.
|
||||
It never writes outside output buffer, nor reads outside input buffer.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LZ5_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LZ5_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ5_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/128) + 16)
|
||||
|
||||
/*
|
||||
LZ5_compressBound() :
|
||||
Provides the maximum size that LZ5 compression may output in a "worst case" scenario (input data not compressible)
|
||||
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||
Macro LZ5_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that LZ5_compress_default() compress faster when dest buffer size is >= LZ5_compressBound(srcSize)
|
||||
inputSize : max supported value is LZ5_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LZ5_MAX_INPUT_SIZE)
|
||||
*/
|
||||
int LZ5_compressBound(int inputSize);
|
||||
|
||||
/*
|
||||
LZ5_compress_fast() :
|
||||
Same as LZ5_compress_default(), but allows to select an "acceleration" factor.
|
||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
An acceleration value of "1" is the same as regular LZ5_compress_default()
|
||||
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz5.c), which is 1.
|
||||
*/
|
||||
int LZ5_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ5_compress_fast_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LZ5_sizeofState() to know how much memory must be allocated,
|
||||
and allocate it on 8-bytes boundaries (using malloc() typically).
|
||||
Then, provide it as 'void* state' to compression function.
|
||||
*/
|
||||
int LZ5_sizeofState(void);
|
||||
int LZ5_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ5_compress_destSize() :
|
||||
Reverse the logic, by compressing as much data as possible from 'source' buffer
|
||||
into already allocated buffer 'dest' of size 'targetDestSize'.
|
||||
This function either compresses the entire 'source' content into 'dest' if it's large enough,
|
||||
or fill 'dest' buffer completely with as much data as possible from 'source'.
|
||||
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
|
||||
New value is necessarily <= old value.
|
||||
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
|
||||
or 0 if compression fails
|
||||
*/
|
||||
int LZ5_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
|
||||
|
||||
|
||||
/*
|
||||
LZ5_decompress_fast() :
|
||||
originalSize : is the original and therefore uncompressed size
|
||||
return : the number of bytes read from the source buffer (in other words, the compressed size)
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
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 LZ5_decompress_safe().
|
||||
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 LZ5_decompress_fast (const char* source, char* dest, int originalSize);
|
||||
|
||||
/*
|
||||
LZ5_decompress_safe_partial() :
|
||||
This function decompress a compressed block of size 'compressedSize' at position 'source'
|
||||
into destination buffer 'dest' of size 'maxDecompressedSize'.
|
||||
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
|
||||
reducing decompression time.
|
||||
return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
|
||||
Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
|
||||
Always control how many bytes were decoded.
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
|
||||
*/
|
||||
int LZ5_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
/***********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
#define LZ5_STREAMSIZE_U64 ((1 << (LZ5_MEMORY_USAGE-3)) + 4)
|
||||
#define LZ5_STREAMSIZE (LZ5_STREAMSIZE_U64 * sizeof(long long))
|
||||
/*
|
||||
* LZ5_stream_t
|
||||
* information structure to track an LZ5 stream.
|
||||
* important : init this structure content before first use !
|
||||
* note : only allocated directly the structure if you are statically linking LZ5
|
||||
* If you are using liblz5 as a DLL, please use below construction methods instead.
|
||||
*/
|
||||
typedef struct { long long table[LZ5_STREAMSIZE_U64]; } LZ5_stream_t;
|
||||
|
||||
/*
|
||||
* LZ5_resetStream
|
||||
* Use this function to init an allocated LZ5_stream_t structure
|
||||
*/
|
||||
void LZ5_resetStream (LZ5_stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ5_createStream will allocate and initialize an LZ5_stream_t structure
|
||||
* LZ5_freeStream releases its memory.
|
||||
* In the context of a DLL (liblz5), please use these methods rather than the static struct.
|
||||
* They are more future proof, in case of a change of LZ5_stream_t size.
|
||||
*/
|
||||
LZ5_stream_t* LZ5_createStream(void);
|
||||
int LZ5_freeStream (LZ5_stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ5_loadDict
|
||||
* Use this function to load a static dictionary into LZ5_stream.
|
||||
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
|
||||
* Loading a size of 0 is allowed.
|
||||
* Return : dictionary size, in bytes (necessarily <= 64 KB)
|
||||
*/
|
||||
int LZ5_loadDict (LZ5_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
/*
|
||||
* LZ5_compress_fast_continue
|
||||
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
|
||||
* Important : Previous data blocks are assumed to still be present and unmodified !
|
||||
* 'dst' buffer must be already allocated.
|
||||
* If maxDstSize >= LZ5_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
|
||||
*/
|
||||
int LZ5_compress_fast_continue (LZ5_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
|
||||
|
||||
/*
|
||||
* LZ5_saveDict
|
||||
* If previously compressed data block is not guaranteed to remain available at its memory location
|
||||
* save it into a safer place (char* safeBuffer)
|
||||
* Note : you don't need to call LZ5_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call LZ5_compress_fast_continue()
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
|
||||
*/
|
||||
int LZ5_saveDict (LZ5_stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Streaming Decompression Functions
|
||||
************************************************/
|
||||
|
||||
#define LZ5_STREAMDECODESIZE_U64 4
|
||||
#define LZ5_STREAMDECODESIZE (LZ5_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||
typedef struct { unsigned long long table[LZ5_STREAMDECODESIZE_U64]; } LZ5_streamDecode_t;
|
||||
/*
|
||||
* LZ5_streamDecode_t
|
||||
* information structure to track an LZ5 stream.
|
||||
* init this structure content using LZ5_setStreamDecode or memset() before first use !
|
||||
*
|
||||
* In the context of a DLL (liblz5) please prefer usage of construction methods below.
|
||||
* They are more future proof, in case of a change of LZ5_streamDecode_t size in the future.
|
||||
* LZ5_createStreamDecode will allocate and initialize an LZ5_streamDecode_t structure
|
||||
* LZ5_freeStreamDecode releases its memory.
|
||||
*/
|
||||
LZ5_streamDecode_t* LZ5_createStreamDecode(void);
|
||||
int LZ5_freeStreamDecode (LZ5_streamDecode_t* LZ5_stream);
|
||||
|
||||
/*
|
||||
* LZ5_setStreamDecode
|
||||
* Use this function to instruct where to find the dictionary.
|
||||
* Setting a size of 0 is allowed (same effect as reset).
|
||||
* Return : 1 if OK, 0 if error
|
||||
*/
|
||||
int LZ5_setStreamDecode (LZ5_streamDecode_t* LZ5_streamDecode, const char* dictionary, int dictSize);
|
||||
|
||||
/*
|
||||
*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
|
||||
In the case of a ring buffers, decoding buffer must be either :
|
||||
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
|
||||
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
|
||||
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
- _At least_ 64 KB + 8 bytes + maxBlockSize.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including larger than decoding buffer.
|
||||
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
|
||||
and indicate where it is saved using LZ5_setStreamDecode()
|
||||
*/
|
||||
int LZ5_decompress_safe_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
int LZ5_decompress_fast_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int originalSize);
|
||||
|
||||
|
||||
/*
|
||||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as
|
||||
a combination of LZ5_setStreamDecode() followed by LZ5_decompress_x_continue()
|
||||
They are stand-alone. They don't need nor update an LZ5_streamDecode_t structure.
|
||||
*/
|
||||
int LZ5_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
int LZ5_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
/**************************************
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
/* Deprecate Warnings */
|
||||
/* Should these warnings messages be a problem,
|
||||
it is generally possible to disable them,
|
||||
with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual for example.
|
||||
Otherwise, you can also define LZ5_DISABLE_DEPRECATE_WARNINGS */
|
||||
#define LZ5_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#ifdef LZ5_DISABLE_DEPRECATE_WARNINGS
|
||||
# define LZ5_DEPRECATED() /* disable deprecation warnings */
|
||||
#else
|
||||
# if (LZ5_GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ5_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ5_GCC_VERSION >= 301)
|
||||
# define LZ5_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ5_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ5_DEPRECATED for this compiler")
|
||||
# define LZ5_DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* LZ5_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
/* These functions will generate warnings in a future release */
|
||||
int LZ5_compress (const char* source, char* dest, int sourceSize);
|
||||
int LZ5_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
int LZ5_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ5_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ5_compress_continue (LZ5_stream_t* LZ5_streamPtr, const char* source, char* dest, int inputSize);
|
||||
int LZ5_compress_limitedOutput_continue (LZ5_stream_t* LZ5_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Obsolete decompression functions */
|
||||
/* These function names are completely deprecated and must no longer be used.
|
||||
They are only provided in lz5.c for compatibility with older programs.
|
||||
- LZ5_uncompress is the same as LZ5_decompress_fast
|
||||
- LZ5_uncompress_unknownOutputSize is the same as LZ5_decompress_safe
|
||||
These function prototypes are now disabled; uncomment them only if you really need them.
|
||||
It is highly recommended to stop using these prototypes and migrate to maintained ones */
|
||||
/* int LZ5_uncompress (const char* source, char* dest, int outputSize); */
|
||||
/* int LZ5_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
|
||||
|
||||
/* Obsolete streaming functions; use new streaming interface whenever possible */
|
||||
LZ5_DEPRECATED("use LZ5_createStream() instead") void* LZ5_create (char* inputBuffer);
|
||||
LZ5_DEPRECATED("use LZ5_createStream() instead") int LZ5_sizeofStreamState(void);
|
||||
LZ5_DEPRECATED("use LZ5_resetStream() instead") int LZ5_resetStreamState(void* state, char* inputBuffer);
|
||||
LZ5_DEPRECATED("use LZ5_saveDict() instead") char* LZ5_slideInputBuffer (void* state);
|
||||
|
||||
/* Obsolete streaming decoding functions */
|
||||
LZ5_DEPRECATED("use LZ5_decompress_safe_usingDict() instead") int LZ5_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||
LZ5_DEPRECATED("use LZ5_decompress_fast_usingDict() instead") int LZ5_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
330
C/lz5/lz5common.h
Normal file
330
C/lz5/lz5common.h
Normal file
@@ -0,0 +1,330 @@
|
||||
#ifndef LZ5COMMON_H
|
||||
#define LZ5COMMON_H
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Tuning parameters
|
||||
**************************************/
|
||||
/*
|
||||
* HEAPMODE :
|
||||
* Select how default compression functions will allocate memory for their hash table,
|
||||
* in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define HEAPMODE 1 /* Default stack size for VC++ is 1 MB and size of LZ5_stream_t exceeds that limit */
|
||||
#else
|
||||
#define HEAPMODE 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* ACCELERATION_DEFAULT :
|
||||
* Select "acceleration" for LZ5_compress_fast() when parameter value <= 0
|
||||
*/
|
||||
#define ACCELERATION_DEFAULT 1
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Compiler Options
|
||||
**************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h>
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
|
||||
#else
|
||||
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define LZ5_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
#if (LZ5_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
|
||||
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
|
||||
#else
|
||||
# define expect(expr,value) (expr)
|
||||
#endif
|
||||
|
||||
#define likely(expr) expect((expr) != 0, 1)
|
||||
#define unlikely(expr) expect((expr) != 0, 0)
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Memory routines
|
||||
**************************************/
|
||||
#include <stdlib.h> /* malloc, calloc, free */
|
||||
#define ALLOCATOR(n,s) calloc(n,s)
|
||||
#define FREEMEM free
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#define MEM_INIT memset
|
||||
|
||||
|
||||
/**************************************
|
||||
* Common Constants
|
||||
**************************************/
|
||||
#define MINMATCH 3 // should be 3 or 4
|
||||
|
||||
#define WILDCOPYLENGTH 8
|
||||
#define LASTLITERALS 5
|
||||
#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
|
||||
static const int LZ5_minLength = (MFLIMIT+1);
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define MAXD_LOG 22
|
||||
#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
|
||||
#define LZ5_DICT_SIZE (1 << MAXD_LOG)
|
||||
|
||||
#define ML_BITS 3
|
||||
#define ML_MASK ((1U<<ML_BITS)-1)
|
||||
#define RUN_BITS 3
|
||||
#define RUN_MASK ((1U<<RUN_BITS)-1)
|
||||
#define RUN_BITS2 2
|
||||
#define RUN_MASK2 ((1U<<RUN_BITS2)-1)
|
||||
#define ML_RUN_BITS (ML_BITS + RUN_BITS)
|
||||
#define ML_RUN_BITS2 (ML_BITS + RUN_BITS2)
|
||||
|
||||
#define LZ5_SHORT_OFFSET_BITS 10
|
||||
#define LZ5_SHORT_OFFSET_DISTANCE (1<<LZ5_SHORT_OFFSET_BITS)
|
||||
#define LZ5_MID_OFFSET_BITS 16
|
||||
#define LZ5_MID_OFFSET_DISTANCE (1<<LZ5_MID_OFFSET_BITS)
|
||||
|
||||
|
||||
/**************************************
|
||||
* Common Utils
|
||||
**************************************/
|
||||
#define LZ5_STATIC_ASSERT(c) { enum { LZ5_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Basic Types
|
||||
*****************************************************************/
|
||||
#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef int16_t S16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
typedef int64_t S64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef signed short S16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
typedef signed long long S64;
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* HC Inline functions and Macros
|
||||
***************************************/
|
||||
#include "mem.h" // MEM_read
|
||||
#include "lz5.h" // LZ5HC_MAX_CLEVEL
|
||||
|
||||
|
||||
static const U32 prime4bytes = 2654435761U;
|
||||
static const U64 prime5bytes = 889523592379ULL;
|
||||
|
||||
#ifdef LZ5HC_INCLUDES
|
||||
static const U32 prime3bytes = 506832829U;
|
||||
static const U64 prime6bytes = 227718039650203ULL;
|
||||
static const U64 prime7bytes = 58295818150454627ULL;
|
||||
|
||||
static U32 LZ5HC_hash3(U32 u, U32 h) { return (u * prime3bytes) << (32-24) >> (32-h) ; }
|
||||
static size_t LZ5HC_hash3Ptr(const void* ptr, U32 h) { return LZ5HC_hash3(MEM_read32(ptr), h); }
|
||||
|
||||
static U32 LZ5HC_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
|
||||
static size_t LZ5HC_hash4Ptr(const void* ptr, U32 h) { return LZ5HC_hash4(MEM_read32(ptr), h); }
|
||||
|
||||
static size_t LZ5HC_hash5(U64 u, U32 h) { return (size_t)((u * prime5bytes) << (64-40) >> (64-h)) ; }
|
||||
static size_t LZ5HC_hash5Ptr(const void* p, U32 h) { return LZ5HC_hash5(MEM_read64(p), h); }
|
||||
|
||||
static size_t LZ5HC_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; }
|
||||
static size_t LZ5HC_hash6Ptr(const void* p, U32 h) { return LZ5HC_hash6(MEM_read64(p), h); }
|
||||
|
||||
static size_t LZ5HC_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }
|
||||
static size_t LZ5HC_hash7Ptr(const void* p, U32 h) { return LZ5HC_hash7(MEM_read64(p), h); }
|
||||
|
||||
static size_t LZ5HC_hashPtr(const void* p, U32 hBits, U32 mls)
|
||||
{
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
case 4: return LZ5HC_hash4Ptr(p, hBits);
|
||||
case 5: return LZ5HC_hash5Ptr(p, hBits);
|
||||
case 6: return LZ5HC_hash6Ptr(p, hBits);
|
||||
case 7: return LZ5HC_hash7Ptr(p, hBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* HC Local Macros
|
||||
**************************************/
|
||||
#define LZ5HC_DEBUG(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LZ5_LOG_PARSER(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LZ5_LOG_PRICE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LZ5_LOG_ENCODE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
|
||||
#define MAX(a,b) ((a)>(b))?(a):(b)
|
||||
#define LZ5_OPT_NUM (1<<12)
|
||||
|
||||
#define LZ5_SHORT_LITERALS ((1<<RUN_BITS2)-1)
|
||||
#define LZ5_LITERALS ((1<<RUN_BITS)-1)
|
||||
|
||||
#define LZ5_SHORT_LITLEN_COST(len) (len<LZ5_SHORT_LITERALS ? 0 : (len-LZ5_SHORT_LITERALS < 255 ? 1 : (len-LZ5_SHORT_LITERALS-255 < (1<<7) ? 2 : 3)))
|
||||
#define LZ5_LEN_COST(len) (len<LZ5_LITERALS ? 0 : (len-LZ5_LITERALS < 255 ? 1 : (len-LZ5_LITERALS-255 < (1<<7) ? 2 : 3)))
|
||||
|
||||
static size_t LZ5_LIT_COST(size_t len, size_t offset){ return (len)+(((offset > LZ5_MID_OFFSET_DISTANCE) || (offset<LZ5_SHORT_OFFSET_DISTANCE)) ? LZ5_SHORT_LITLEN_COST(len) : LZ5_LEN_COST(len)); }
|
||||
static size_t LZ5_MATCH_COST(size_t mlen, size_t offset) { return LZ5_LEN_COST(mlen) + ((offset == 0) ? 1 : (offset<LZ5_SHORT_OFFSET_DISTANCE ? 2 : (offset<LZ5_MID_OFFSET_DISTANCE ? 3 : 4))); }
|
||||
|
||||
#define LZ5_CODEWORD_COST(litlen,offset,mlen) (LZ5_MATCH_COST(mlen,offset) + LZ5_LIT_COST(litlen,offset))
|
||||
#define LZ5_LIT_ONLY_COST(len) ((len)+(LZ5_LEN_COST(len))+1)
|
||||
|
||||
#define LZ5_NORMAL_MATCH_COST(mlen,offset) (LZ5_MATCH_COST(mlen,offset))
|
||||
#define LZ5_NORMAL_LIT_COST(len) (len)
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE size_t LZ5HC_get_price(size_t litlen, size_t offset, size_t mlen)
|
||||
{
|
||||
return LZ5_CODEWORD_COST(litlen, offset, mlen);
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t LZ5HC_better_price(size_t best_off, size_t best_common, size_t off, size_t common, size_t last_off)
|
||||
{
|
||||
return LZ5_NORMAL_MATCH_COST(common - MINMATCH, (off == last_off) ? 0 : off) < LZ5_NORMAL_MATCH_COST(best_common - MINMATCH, (best_off == last_off) ? 0 : best_off) + (LZ5_NORMAL_LIT_COST(common - best_common) );
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE size_t LZ5HC_more_profitable(size_t best_off, size_t best_common, size_t off, size_t common, size_t literals, size_t last_off)
|
||||
{
|
||||
size_t sum;
|
||||
|
||||
if (literals > 0)
|
||||
sum = MAX(common + literals, best_common);
|
||||
else
|
||||
sum = MAX(common, best_common - literals);
|
||||
|
||||
// return LZ5_CODEWORD_COST(sum - common, (off == last_off) ? 0 : (off), common - MINMATCH) <= LZ5_CODEWORD_COST(sum - best_common, (best_off == last_off) ? 0 : (best_off), best_common - MINMATCH);
|
||||
return LZ5_NORMAL_MATCH_COST(common - MINMATCH, (off == last_off) ? 0 : off) + LZ5_NORMAL_LIT_COST(sum - common) <= LZ5_NORMAL_MATCH_COST(best_common - MINMATCH, (best_off == last_off) ? 0 : (best_off)) + LZ5_NORMAL_LIT_COST(sum - best_common);
|
||||
}
|
||||
|
||||
#endif // LZ5HC_INCLUDES
|
||||
|
||||
|
||||
|
||||
/* *************************************
|
||||
* HC Types
|
||||
***************************************/
|
||||
/** from faster to stronger */
|
||||
typedef enum { LZ5HC_fast, LZ5HC_price_fast, LZ5HC_lowest_price, LZ5HC_optimal_price, LZ5HC_optimal_price_bt } LZ5HC_strategy;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U32 windowLog; /* largest match distance : impact decompression buffer size */
|
||||
U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */
|
||||
U32 hashLog; /* dispatch table : larger == more memory, faster*/
|
||||
U32 hashLog3; /* dispatch table : larger == more memory, faster*/
|
||||
U32 searchNum; /* nb of searches : larger == more compression, slower*/
|
||||
U32 searchLength; /* size of matches : larger == faster decompression */
|
||||
U32 sufficientLength; /* used only by optimal parser: size of matches which is acceptable: larger == more compression, slower */
|
||||
U32 fullSearch; /* used only by optimal parser: perform full search of matches: 1 == more compression, slower */
|
||||
LZ5HC_strategy strategy;
|
||||
} LZ5HC_parameters;
|
||||
|
||||
|
||||
struct LZ5HC_Data_s
|
||||
{
|
||||
U32* hashTable;
|
||||
U32* hashTable3;
|
||||
U32* chainTable;
|
||||
const BYTE* end; /* next block here to continue on current prefix */
|
||||
const BYTE* base; /* All index relative to this position */
|
||||
const BYTE* dictBase; /* alternate base for extDict */
|
||||
const BYTE* inputBuffer; /* for debugging */
|
||||
const BYTE* outputBuffer; /* for debugging */
|
||||
U32 dictLimit; /* below that point, need extDict */
|
||||
U32 lowLimit; /* below that point, no more dict */
|
||||
U32 nextToUpdate; /* index from which to continue dictionary update */
|
||||
U32 compressionLevel;
|
||||
U32 last_off;
|
||||
LZ5HC_parameters params;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int off;
|
||||
int len;
|
||||
int back;
|
||||
} LZ5HC_match_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int price;
|
||||
int off;
|
||||
int mlen;
|
||||
int litlen;
|
||||
int rep;
|
||||
} LZ5HC_optimal_t;
|
||||
|
||||
|
||||
|
||||
/* *************************************
|
||||
* HC Pre-defined compression levels
|
||||
***************************************/
|
||||
|
||||
static const int g_maxCompressionLevel = LZ5HC_MAX_CLEVEL;
|
||||
static const int LZ5HC_compressionLevel_default = 6;
|
||||
|
||||
static const LZ5HC_parameters LZ5HC_defaultParameters[LZ5HC_MAX_CLEVEL+1] =
|
||||
{
|
||||
/* windLog, contentLog, H, H3, Snum, SL, SuffL, FS, Strategy */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, LZ5HC_fast }, // level 0 - never used
|
||||
{ MAXD_LOG, MAXD_LOG, 13, 0, 4, 6, 0, 0, LZ5HC_fast }, // level 1
|
||||
{ MAXD_LOG, MAXD_LOG, 13, 0, 2, 6, 0, 0, LZ5HC_fast }, // level 2
|
||||
{ MAXD_LOG, MAXD_LOG, 13, 0, 1, 5, 0, 0, LZ5HC_fast }, // level 3
|
||||
{ MAXD_LOG, MAXD_LOG, 14, 13, 1, 4, 0, 0, LZ5HC_price_fast }, // level 4
|
||||
{ MAXD_LOG, MAXD_LOG, 17, 13, 1, 4, 0, 0, LZ5HC_price_fast }, // level 5
|
||||
{ MAXD_LOG, MAXD_LOG, 15, 13, 1, 4, 0, 0, LZ5HC_lowest_price }, // level 6
|
||||
{ MAXD_LOG, MAXD_LOG, 17, 13, 1, 4, 0, 0, LZ5HC_lowest_price }, // level 7
|
||||
{ MAXD_LOG, MAXD_LOG, 19, 16, 1, 4, 0, 0, LZ5HC_lowest_price }, // level 8
|
||||
{ MAXD_LOG, MAXD_LOG, 23, 16, 3, 4, 0, 0, LZ5HC_lowest_price }, // level 9
|
||||
{ MAXD_LOG, MAXD_LOG, 23, 16, 8, 4, 0, 0, LZ5HC_lowest_price }, // level 10
|
||||
{ MAXD_LOG, MAXD_LOG, 23, 16, 8, 4, 12, 0, LZ5HC_optimal_price }, // level 11
|
||||
{ MAXD_LOG, MAXD_LOG, 23, 16, 8, 4, 64, 0, LZ5HC_optimal_price }, // level 12
|
||||
{ MAXD_LOG, MAXD_LOG+1, 23, 16, 8, 4, 64, 1, LZ5HC_optimal_price_bt }, // level 13
|
||||
{ MAXD_LOG, MAXD_LOG+1, 23, 16, 128, 4, 64, 1, LZ5HC_optimal_price_bt }, // level 14
|
||||
{ MAXD_LOG, MAXD_LOG+1, 28, 24, 1<<10, 4, 1<<10, 1, LZ5HC_optimal_price_bt }, // level 15
|
||||
// { 10, 10, 10, 0, 0, 4, 0, 0, LZ5HC_fast }, // min values
|
||||
// { 24, 24, 28, 24, 1<<24, 7, 1<<24, 2, LZ5HC_optimal_price }, // max values
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LZ5COMMON_H */
|
||||
1485
C/lz5/lz5frame.c
Normal file
1485
C/lz5/lz5frame.c
Normal file
File diff suppressed because it is too large
Load Diff
306
C/lz5/lz5frame.h
Normal file
306
C/lz5/lz5frame.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
LZ5 auto-framing library
|
||||
Header File
|
||||
Copyright (C) 2011-2015, 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 :
|
||||
- LZ5 source repository : https://github.com/inikep/lz5
|
||||
- LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c
|
||||
*/
|
||||
|
||||
/* LZ5F is a stand-alone API to create LZ5-compressed frames
|
||||
* conformant with specification v1.5.1.
|
||||
* All related operations, including memory management, are handled internally by the library.
|
||||
* You don't need lz5.h when using lz5frame.h.
|
||||
* */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Error management
|
||||
**************************************/
|
||||
typedef size_t LZ5F_errorCode_t;
|
||||
|
||||
unsigned LZ5F_isError(LZ5F_errorCode_t code);
|
||||
const char* LZ5F_getErrorName(LZ5F_errorCode_t code); /* return error code string; useful for debugging */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Frame compression types
|
||||
**************************************/
|
||||
//#define LZ5F_DISABLE_OBSOLETE_ENUMS
|
||||
#ifndef LZ5F_DISABLE_OBSOLETE_ENUMS
|
||||
# define LZ5F_OBSOLETE_ENUM(x) ,x
|
||||
#else
|
||||
# define LZ5F_OBSOLETE_ENUM(x)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LZ5F_default=0,
|
||||
LZ5F_max64KB=1,
|
||||
LZ5F_max256KB=2,
|
||||
LZ5F_max1MB=3,
|
||||
LZ5F_max4MB=4,
|
||||
LZ5F_max16MB=5,
|
||||
LZ5F_max64MB=6,
|
||||
LZ5F_max256MB=7
|
||||
LZ5F_OBSOLETE_ENUM(max64KB = LZ5F_max64KB)
|
||||
LZ5F_OBSOLETE_ENUM(max256KB = LZ5F_max256KB)
|
||||
LZ5F_OBSOLETE_ENUM(max1MB = LZ5F_max1MB)
|
||||
LZ5F_OBSOLETE_ENUM(max4MB = LZ5F_max4MB)
|
||||
} LZ5F_blockSizeID_t;
|
||||
|
||||
typedef enum {
|
||||
LZ5F_blockLinked=0,
|
||||
LZ5F_blockIndependent
|
||||
LZ5F_OBSOLETE_ENUM(blockLinked = LZ5F_blockLinked)
|
||||
LZ5F_OBSOLETE_ENUM(blockIndependent = LZ5F_blockIndependent)
|
||||
} LZ5F_blockMode_t;
|
||||
|
||||
typedef enum {
|
||||
LZ5F_noContentChecksum=0,
|
||||
LZ5F_contentChecksumEnabled
|
||||
LZ5F_OBSOLETE_ENUM(noContentChecksum = LZ5F_noContentChecksum)
|
||||
LZ5F_OBSOLETE_ENUM(contentChecksumEnabled = LZ5F_contentChecksumEnabled)
|
||||
} LZ5F_contentChecksum_t;
|
||||
|
||||
typedef enum {
|
||||
LZ5F_frame=0,
|
||||
LZ5F_skippableFrame
|
||||
LZ5F_OBSOLETE_ENUM(skippableFrame = LZ5F_skippableFrame)
|
||||
} LZ5F_frameType_t;
|
||||
|
||||
#ifndef LZ5F_DISABLE_OBSOLETE_ENUMS
|
||||
typedef LZ5F_blockSizeID_t blockSizeID_t;
|
||||
typedef LZ5F_blockMode_t blockMode_t;
|
||||
typedef LZ5F_frameType_t frameType_t;
|
||||
typedef LZ5F_contentChecksum_t contentChecksum_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
LZ5F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
LZ5F_blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
LZ5F_contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
LZ5F_frameType_t frameType; /* LZ5F_frame, skippableFrame ; 0 == default */
|
||||
unsigned long long contentSize; /* Size of uncompressed (original) content ; 0 == unknown */
|
||||
unsigned reserved[2]; /* must be zero for forward compatibility */
|
||||
} LZ5F_frameInfo_t;
|
||||
|
||||
typedef struct {
|
||||
LZ5F_frameInfo_t frameInfo;
|
||||
int compressionLevel; /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */
|
||||
unsigned autoFlush; /* 1 == always flush (reduce need for tmp buffer) */
|
||||
unsigned reserved[4]; /* must be zero for forward compatibility */
|
||||
} LZ5F_preferences_t;
|
||||
|
||||
|
||||
/***********************************
|
||||
* Simple compression function
|
||||
***********************************/
|
||||
size_t LZ5F_compressFrameBound(size_t srcSize, const LZ5F_preferences_t* preferencesPtr);
|
||||
|
||||
size_t LZ5F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_preferences_t* preferencesPtr);
|
||||
/* LZ5F_compressFrame()
|
||||
* Compress an entire srcBuffer into a valid LZ5 frame, as defined by specification v1.5.1
|
||||
* 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 LZ5F_compressFrameBound()
|
||||
* If this condition is not respected, LZ5F_compressFrame() will fail (result is an errorCode)
|
||||
* The LZ5F_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 LZ5F_isError())
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* Advanced compression functions
|
||||
**********************************/
|
||||
typedef struct LZ5F_cctx_s* LZ5F_compressionContext_t; /* must be aligned on 8-bytes */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableSrc; /* 1 == src content will remain available on future calls to LZ5F_compress(); avoid saving src content within tmp buffer as future dictionary */
|
||||
unsigned reserved[3];
|
||||
} LZ5F_compressOptions_t;
|
||||
|
||||
/* Resource Management */
|
||||
|
||||
#define LZ5F_VERSION 100
|
||||
LZ5F_errorCode_t LZ5F_createCompressionContext(LZ5F_compressionContext_t* cctxPtr, unsigned version);
|
||||
LZ5F_errorCode_t LZ5F_freeCompressionContext(LZ5F_compressionContext_t cctx);
|
||||
/* LZ5F_createCompressionContext() :
|
||||
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
|
||||
* This is achieved using LZ5F_createCompressionContext(), which takes as argument a version and an LZ5F_preferences_t structure.
|
||||
* The version provided MUST be LZ5F_VERSION. It is intended to track potential version differences between different binaries.
|
||||
* The function will provide a pointer to a fully allocated LZ5F_compressionContext_t object.
|
||||
* If the result LZ5F_errorCode_t is not zero, there was an error during context creation.
|
||||
* Object can release its memory using LZ5F_freeCompressionContext();
|
||||
*/
|
||||
|
||||
|
||||
/* Compression */
|
||||
|
||||
size_t LZ5F_compressBegin(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_preferences_t* prefsPtr);
|
||||
/* LZ5F_compressBegin() :
|
||||
* will write the frame header into dstBuffer.
|
||||
* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
|
||||
* The LZ5F_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 LZ5F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ5F_compressBound(size_t srcSize, const LZ5F_preferences_t* prefsPtr);
|
||||
/* LZ5F_compressBound() :
|
||||
* Provides the minimum size of Dst buffer given srcSize to handle worst case situations.
|
||||
* Different preferences can produce different results.
|
||||
* prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to cover worst case.
|
||||
* This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)
|
||||
*/
|
||||
|
||||
size_t LZ5F_compressUpdate(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_compressOptions_t* cOptPtr);
|
||||
/* LZ5F_compressUpdate()
|
||||
* LZ5F_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.
|
||||
* You can get the minimum value of dstMaxSize by using LZ5F_compressBound().
|
||||
* If this condition is not respected, LZ5F_compress() will fail (result is an errorCode).
|
||||
* LZ5F_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
|
||||
* The LZ5F_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 LZ5F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ5F_flush(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* cOptPtr);
|
||||
/* LZ5F_flush()
|
||||
* Should you need to generate compressed data immediately, without waiting for the current block to be filled,
|
||||
* you can call LZ5_flush(), which will immediately compress any remaining data buffered within cctx.
|
||||
* Note that dstMaxSize must be large enough to ensure the operation will be successful.
|
||||
* LZ5F_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 cctx)
|
||||
* The function outputs an error code if it fails (can be tested using LZ5F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ5F_compressEnd(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* cOptPtr);
|
||||
/* LZ5F_compressEnd()
|
||||
* When you want to properly finish the compressed frame, just call LZ5F_compressEnd().
|
||||
* It will flush whatever data remained within compressionContext (like LZ5_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), or 8 if optional frame checksum is enabled)
|
||||
* The function outputs an error code if it fails (can be tested using LZ5F_isError())
|
||||
* The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* A successful call to LZ5F_compressEnd() makes cctx available again for next compression task.
|
||||
*/
|
||||
|
||||
|
||||
/***********************************
|
||||
* Decompression functions
|
||||
***********************************/
|
||||
|
||||
typedef struct LZ5F_dctx_s* LZ5F_decompressionContext_t; /* must be aligned on 8-bytes */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableDst; /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */
|
||||
unsigned reserved[3];
|
||||
} LZ5F_decompressOptions_t;
|
||||
|
||||
|
||||
/* Resource management */
|
||||
|
||||
LZ5F_errorCode_t LZ5F_createDecompressionContext(LZ5F_decompressionContext_t* dctxPtr, unsigned version);
|
||||
LZ5F_errorCode_t LZ5F_freeDecompressionContext(LZ5F_decompressionContext_t dctx);
|
||||
/* LZ5F_createDecompressionContext() :
|
||||
* The first thing to do is to create an LZ5F_decompressionContext_t object, which will be used in all decompression operations.
|
||||
* This is achieved using LZ5F_createDecompressionContext().
|
||||
* The version provided MUST be LZ5F_VERSION. It is intended to track potential breaking differences between different versions.
|
||||
* The function will provide a pointer to a fully allocated and initialized LZ5F_decompressionContext_t object.
|
||||
* The result is an errorCode, which can be tested using LZ5F_isError().
|
||||
* dctx memory can be released using LZ5F_freeDecompressionContext();
|
||||
* The result of LZ5F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
|
||||
* That is, it should be == 0 if decompression has been completed fully and correctly.
|
||||
*/
|
||||
|
||||
|
||||
/* Decompression */
|
||||
|
||||
size_t LZ5F_getFrameInfo(LZ5F_decompressionContext_t dctx,
|
||||
LZ5F_frameInfo_t* frameInfoPtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr);
|
||||
/* LZ5F_getFrameInfo()
|
||||
* This function decodes frame header information (such as max blockSize, frame checksum, etc.).
|
||||
* Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.
|
||||
* A header size is variable and can be from 7 to 15 bytes. It's also possible to input more bytes than that.
|
||||
* The number of bytes read from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
|
||||
* (note that LZ5F_getFrameInfo() can also be used anytime *after* starting decompression, in this case 0 input byte is enough)
|
||||
* Frame header info is *copied into* an already allocated LZ5F_frameInfo_t structure.
|
||||
* The function result is an hint about how many srcSize bytes LZ5F_decompress() expects for next call,
|
||||
* or an error code which can be tested using LZ5F_isError()
|
||||
* (typically, when there is not enough src bytes to fully decode the frame header)
|
||||
* Decompression is expected to resume from where it stopped (srcBuffer + *srcSizePtr)
|
||||
*/
|
||||
|
||||
size_t LZ5F_decompress(LZ5F_decompressionContext_t dctx,
|
||||
void* dstBuffer, size_t* dstSizePtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr,
|
||||
const LZ5F_decompressOptions_t* dOptPtr);
|
||||
/* LZ5F_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 read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* If number of bytes read is < number of bytes provided, then decompression operation is not completed.
|
||||
* It typically happens when dstBuffer is not large enough to contain all decoded data.
|
||||
* LZ5F_decompress() must 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 each call to the function, since its content will be overwritten.
|
||||
* dst arguments can be changed at will with each consecutive call to the function.
|
||||
*
|
||||
* The function result is an hint of how many srcSize bytes LZ5F_decompress() expects for next call.
|
||||
* Schematically, 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 does skip intermediate buffers.
|
||||
* 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 (no more data expected).
|
||||
* If decompression failed, function result is an error code, which can be tested using LZ5F_isError().
|
||||
*
|
||||
* After a frame is fully decoded, dctx can be used again to decompress another frame.
|
||||
*/
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
81
C/lz5/lz5frame_static.h
Normal file
81
C/lz5/lz5frame_static.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
LZ5 auto-framing library
|
||||
Header File for static linking only
|
||||
Copyright (C) 2011-2015, 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 :
|
||||
- LZ5 source repository : https://github.com/inikep/lz5
|
||||
- LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* lz5frame_static.h should be used solely in the context of static linking.
|
||||
* It contains definitions which may still change overtime.
|
||||
* Never use it in the context of DLL linking.
|
||||
* */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include "lz5frame.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* Error management
|
||||
* ************************************/
|
||||
#define LZ5F_LIST_ERRORS(ITEM) \
|
||||
ITEM(OK_NoError) ITEM(ERROR_GENERIC) \
|
||||
ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \
|
||||
ITEM(ERROR_compressionLevel_invalid) \
|
||||
ITEM(ERROR_headerVersion_wrong) ITEM(ERROR_blockChecksum_unsupported) ITEM(ERROR_reservedFlag_set) \
|
||||
ITEM(ERROR_allocation_failed) \
|
||||
ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \
|
||||
ITEM(ERROR_frameHeader_incomplete) ITEM(ERROR_frameType_unknown) ITEM(ERROR_frameSize_wrong) \
|
||||
ITEM(ERROR_srcPtr_wrong) \
|
||||
ITEM(ERROR_decompressionFailed) \
|
||||
ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \
|
||||
ITEM(ERROR_maxCode)
|
||||
|
||||
//#define LZ5F_DISABLE_OLD_ENUMS
|
||||
#ifndef LZ5F_DISABLE_OLD_ENUMS
|
||||
#define LZ5F_GENERATE_ENUM(ENUM) LZ5F_##ENUM, ENUM = LZ5F_##ENUM,
|
||||
#else
|
||||
#define LZ5F_GENERATE_ENUM(ENUM) LZ5F_##ENUM,
|
||||
#endif
|
||||
typedef enum { LZ5F_LIST_ERRORS(LZ5F_GENERATE_ENUM) } LZ5F_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
1929
C/lz5/lz5hc.c
Normal file
1929
C/lz5/lz5hc.c
Normal file
File diff suppressed because it is too large
Load Diff
178
C/lz5/lz5hc.h
Normal file
178
C/lz5/lz5hc.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
LZ5 HC - High Compression Mode of LZ5
|
||||
Header File
|
||||
Copyright (C) 2011-2015, 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 :
|
||||
- LZ5 source repository : https://github.com/inikep/lz5
|
||||
- LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************
|
||||
* Includes
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Block Compression
|
||||
**************************************/
|
||||
int LZ5_compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
/*
|
||||
LZ5_compress_HC :
|
||||
Destination buffer 'dst' must be already allocated.
|
||||
Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible)
|
||||
Worst size evaluation is provided by function LZ5_compressBound() (see "lz5.h")
|
||||
srcSize : Max supported value is LZ5_MAX_INPUT_SIZE (see "lz5.h")
|
||||
compressionLevel : Recommended values are between 4 and 9, although any value between 0 and LZ5HC_MAX_CLEVEL (equal to 15) will work.
|
||||
0 means "use default value" (see lz5hc.c).
|
||||
Values >LZ5HC_MAX_CLEVEL behave the same as LZ5HC_MAX_CLEVEL.
|
||||
return : the number of bytes written into buffer 'dst'
|
||||
or 0 if compression fails.
|
||||
*/
|
||||
|
||||
|
||||
/* Note :
|
||||
Decompression functions are provided within LZ5 source code (see "lz5.h") (BSD license)
|
||||
*/
|
||||
|
||||
typedef struct LZ5HC_Data_s LZ5HC_Data_Structure;
|
||||
|
||||
int LZ5_alloc_mem_HC(LZ5HC_Data_Structure* statePtr, int compressionLevel);
|
||||
void LZ5_free_mem_HC(LZ5HC_Data_Structure* statePtr);
|
||||
|
||||
int LZ5_sizeofStateHC(void);
|
||||
int LZ5_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
/*
|
||||
LZ5_compress_HC_extStateHC() :
|
||||
Use this function if you prefer to manually allocate memory for compression tables.
|
||||
To know how much memory must be allocated for the compression tables, use :
|
||||
int LZ5_sizeofStateHC();
|
||||
|
||||
Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).
|
||||
|
||||
The allocated memory can then be provided to the compression functions using 'void* state' parameter.
|
||||
LZ5_compress_HC_extStateHC() is equivalent to previously described function.
|
||||
It just uses externally allocated memory for stateHC.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Streaming Compression
|
||||
**************************************/
|
||||
#define LZ5_STREAMHCSIZE 262192
|
||||
#define LZ5_STREAMHCSIZE_SIZET (LZ5_STREAMHCSIZE / sizeof(size_t))
|
||||
typedef struct { size_t table[LZ5_STREAMHCSIZE_SIZET]; } LZ5_streamHC_t;
|
||||
/*
|
||||
LZ5_streamHC_t
|
||||
This structure allows static allocation of LZ5 HC streaming state.
|
||||
State must then be initialized using LZ5_resetStreamHC() before first use.
|
||||
|
||||
Static allocation should only be used in combination with static linking.
|
||||
If you want to use LZ5 as a DLL, please use construction functions below, which are future-proof.
|
||||
*/
|
||||
|
||||
|
||||
LZ5_streamHC_t* LZ5_createStreamHC(int compressionLevel);
|
||||
int LZ5_freeStreamHC (LZ5_streamHC_t* streamHCPtr);
|
||||
/*
|
||||
These functions create and release memory for LZ5 HC streaming state.
|
||||
Newly created states are already initialized.
|
||||
Existing state space can be re-used anytime using LZ5_resetStreamHC().
|
||||
If you use LZ5 as a DLL, use these functions instead of static structure allocation,
|
||||
to avoid size mismatch between different versions.
|
||||
*/
|
||||
|
||||
void LZ5_resetStreamHC (LZ5_streamHC_t* streamHCPtr);
|
||||
int LZ5_loadDictHC (LZ5_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
|
||||
|
||||
int LZ5_compress_HC_continue (LZ5_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
|
||||
int LZ5_saveDictHC (LZ5_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
|
||||
|
||||
/*
|
||||
These functions compress data in successive blocks of any size, using previous blocks as dictionary.
|
||||
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
|
||||
There is an exception for ring buffers, which can be smaller 64 KB.
|
||||
Such case is automatically detected and correctly handled by LZ5_compress_HC_continue().
|
||||
|
||||
Before starting compression, state must be properly initialized, using LZ5_resetStreamHC().
|
||||
A first "fictional block" can then be designated as initial dictionary, using LZ5_loadDictHC() (Optional).
|
||||
|
||||
Then, use LZ5_compress_HC_continue() to compress each successive block.
|
||||
It works like LZ5_compress_HC(), but use previous memory blocks as dictionary to improve compression.
|
||||
Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.
|
||||
As a reminder, size 'dst' buffer to handle worst cases, using LZ5_compressBound(), to ensure success of compression operation.
|
||||
|
||||
If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,
|
||||
you must save it to a safer memory space, using LZ5_saveDictHC().
|
||||
Return value of LZ5_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Deprecated Functions
|
||||
**************************************/
|
||||
/* Deprecate Warnings */
|
||||
/* Should these warnings messages be a problem,
|
||||
it is generally possible to disable them,
|
||||
with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual for example.
|
||||
You can also define LZ5_DEPRECATE_WARNING_DEFBLOCK. */
|
||||
#ifndef LZ5_DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ5_DEPRECATE_WARNING_DEFBLOCK
|
||||
# if (LZ5_GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ5_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ5_GCC_VERSION >= 301)
|
||||
# define LZ5_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ5_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ5_DEPRECATED for this compiler")
|
||||
# define LZ5_DEPRECATED(message)
|
||||
# endif
|
||||
#endif // LZ5_DEPRECATE_WARNING_DEFBLOCK
|
||||
|
||||
/* compression functions */
|
||||
/* these functions are planned to trigger warning messages by r132 approximately */
|
||||
int LZ5_compressHC (const char* source, char* dest, int inputSize);
|
||||
int LZ5_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ5_compressHC_continue (LZ5_streamHC_t* LZ5_streamHCPtr, const char* source, char* dest, int inputSize);
|
||||
int LZ5_compressHC_limitedOutput_continue (LZ5_streamHC_t* LZ5_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ5_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ5_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
915
C/lz5/lz5xxhash.c
Normal file
915
C/lz5/lz5xxhash.c
Normal file
@@ -0,0 +1,915 @@
|
||||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
Copyright (C) 2012-2015, 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 : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Tuning parameters
|
||||
**************************************/
|
||||
/* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
|
||||
* For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
|
||||
* If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
|
||||
* You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
|
||||
*/
|
||||
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_USE_UNALIGNED_ACCESS 1
|
||||
#endif
|
||||
|
||||
/* XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
* If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
* When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
* By default, this option is disabled. To enable it, uncomment below define :
|
||||
*/
|
||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||
|
||||
/* XXH_FORCE_NATIVE_FORMAT :
|
||||
* By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
||||
* Results are therefore identical for little-endian and big-endian CPU.
|
||||
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
* Should endian-independance be of no importance for your application, you may set the #define below to 1.
|
||||
* It will improve speed for Big-endian CPU.
|
||||
* This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
#define XXH_FORCE_NATIVE_FORMAT 0
|
||||
|
||||
|
||||
/**************************************
|
||||
* Compiler Specific Options
|
||||
***************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes & Memory related functions
|
||||
***************************************/
|
||||
#include "xxhash.h"
|
||||
/* Modify the local functions below should you wish to use some other memory routines */
|
||||
/* for malloc(), free() */
|
||||
#include <stdlib.h>
|
||||
static void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
static void XXH_free (void* p) { free(p); }
|
||||
/* for memcpy() */
|
||||
#include <string.h>
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
|
||||
|
||||
/**************************************
|
||||
* 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
|
||||
|
||||
static U32 XXH_read32(const void* memPtr)
|
||||
{
|
||||
U32 val32;
|
||||
memcpy(&val32, memPtr, 4);
|
||||
return val32;
|
||||
}
|
||||
|
||||
static U64 XXH_read64(const void* memPtr)
|
||||
{
|
||||
U64 val64;
|
||||
memcpy(&val64, memPtr, 8);
|
||||
return val64;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************
|
||||
* Compiler-specific Functions and Macros
|
||||
******************************************/
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
static U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************
|
||||
* Architecture Macros
|
||||
***************************************/
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example using a compiler switch */
|
||||
static const int one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one))
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Memory reads
|
||||
*****************************/
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* Macros
|
||||
***************************************/
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/***************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
#define PRIME32_1 2654435761U
|
||||
#define PRIME32_2 2246822519U
|
||||
#define PRIME32_3 3266489917U
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
#define PRIME64_1 11400714785074694791ULL
|
||||
#define PRIME64_2 14029467366897019727ULL
|
||||
#define PRIME64_3 1609587929392839161ULL
|
||||
#define PRIME64_4 9650029242287828579ULL
|
||||
#define PRIME64_5 2870177450012600261ULL
|
||||
|
||||
|
||||
/*****************************
|
||||
* Simple Hash Functions
|
||||
*****************************/
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get32bits(p) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_get32bits(p) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_get32bits(p) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_get32bits(p) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
unsigned XXH32 (const void* input, size_t len, unsigned seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH32_state_t state;
|
||||
XXH32_reset(&state, seed);
|
||||
XXH32_update(&state, input, len);
|
||||
return XXH32_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 3) == 0) /* Input is 4-bytes aligned, leverage the speed benefit */
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=32)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
v2 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
v3 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
v4 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_get64bits(p);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH64_state_t state;
|
||||
XXH64_reset(&state, seed);
|
||||
XXH64_update(&state, input, len);
|
||||
return XXH64_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 7)==0) /* Input is aligned, let's leverage the speed advantage */
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Advanced Hash Functions
|
||||
****************************************************/
|
||||
|
||||
/*** Allocation ***/
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U32 seed;
|
||||
U32 v1;
|
||||
U32 v2;
|
||||
U32 v3;
|
||||
U32 v4;
|
||||
U32 mem32[4]; /* defined as U32 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U64 seed;
|
||||
U64 v1;
|
||||
U64 v2;
|
||||
U64 v3;
|
||||
U64 v4;
|
||||
U64 mem64[4]; /* defined as U64 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate64_t;
|
||||
|
||||
|
||||
XXH32_state_t* XXH32_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t)); /* A compilation error here means XXH32_state_t is not large enough */
|
||||
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
|
||||
}
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH64_state_t* XXH64_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t)); /* A compilation error here means XXH64_state_t is not large enough */
|
||||
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
|
||||
}
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
/*** Hash feed ***/
|
||||
|
||||
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state->v2 = seed + PRIME32_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME32_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, unsigned long long seed)
|
||||
{
|
||||
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state->v2 = seed + PRIME64_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME64_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 16) /* fill in tmp buffer */
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) /* some data left from previous update */
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{
|
||||
const U32* p32 = state->mem32;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v1 = XXH_rotl32(state->v1, 13);
|
||||
state->v1 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v2 = XXH_rotl32(state->v2, 13);
|
||||
state->v2 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v3 = XXH_rotl32(state->v3, 13);
|
||||
state->v3 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v4 = XXH_rotl32(state->v4, 13);
|
||||
state->v4 *= PRIME32_1;
|
||||
p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem32, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
const XXH_istate32_t* state = (const XXH_istate32_t*) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
const BYTE* bEnd = (const BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->total_len >= 16)
|
||||
{
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = state->seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) state->total_len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_digest (const XXH32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) /* fill in tmp buffer */
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) /* some data left from previous update */
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
{
|
||||
const U64* p64 = state->mem64;
|
||||
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v1 = XXH_rotl64(state->v1, 31);
|
||||
state->v1 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v2 = XXH_rotl64(state->v2, 31);
|
||||
state->v2 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v3 = XXH_rotl64(state->v3, 31);
|
||||
state->v3 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v4 = XXH_rotl64(state->v4, 31);
|
||||
state->v4 *= PRIME64_1;
|
||||
p64++;
|
||||
}
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
p+=8;
|
||||
v2 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
p+=8;
|
||||
v3 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
p+=8;
|
||||
v4 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
p+=8;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem64, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
const XXH_istate64_t * state = (const XXH_istate64_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
const BYTE* bEnd = (const BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32)
|
||||
{
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = state->seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_readLE64(p, endian);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XXH64_digest (const XXH64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
452
C/lz5/mem.h
Normal file
452
C/lz5/mem.h
Normal file
@@ -0,0 +1,452 @@
|
||||
/* ******************************************************************
|
||||
mem.h
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, 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 :
|
||||
- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
****************************************************************** */
|
||||
#ifndef MEM_H_MODULE
|
||||
#define MEM_H_MODULE
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************
|
||||
* Includes
|
||||
******************************************/
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
|
||||
|
||||
/******************************************
|
||||
* Compiler-specific
|
||||
******************************************/
|
||||
#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define MEM_STATIC static inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define MEM_STATIC static __inline
|
||||
#elif defined(__GNUC__)
|
||||
# define MEM_STATIC static __attribute__((unused))
|
||||
#else
|
||||
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets generating assembly depending on alignment.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
||||
# elif defined(__INTEL_COMPILER) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
|
||||
|
||||
MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
{
|
||||
const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr)
|
||||
{
|
||||
U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
}
|
||||
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr)
|
||||
{
|
||||
U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
{
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value)
|
||||
{
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value)
|
||||
{
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#endif // MEM_FORCE_MEMORY_ACCESS
|
||||
|
||||
|
||||
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_read16(memPtr);
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U16)(p[0] + (p[1]<<8));
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
MEM_write16(memPtr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE)val;
|
||||
p[1] = (BYTE)(val>>8);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
U32 val32 = 0;
|
||||
memcpy(&val32, memPtr, 3);
|
||||
return val32;
|
||||
}
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U32)(p[0] + (p[1]<<8) + (p[2]<<16));
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 value)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
memcpy(memPtr, &value, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE) value;
|
||||
p[1] = (BYTE)(value>>8);
|
||||
p[2] = (BYTE)(value>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_read32(memPtr);
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
MEM_write32(memPtr, val32);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE)val32;
|
||||
p[1] = (BYTE)(val32>>8);
|
||||
p[2] = (BYTE)(val32>>16);
|
||||
p[3] = (BYTE)(val32>>24);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC U64 MEM_readLE64(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_read64(memPtr);
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)
|
||||
+ ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
MEM_write64(memPtr, val64);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE)val64;
|
||||
p[1] = (BYTE)(val64>>8);
|
||||
p[2] = (BYTE)(val64>>16);
|
||||
p[3] = (BYTE)(val64>>24);
|
||||
p[4] = (BYTE)(val64>>32);
|
||||
p[5] = (BYTE)(val64>>40);
|
||||
p[6] = (BYTE)(val64>>48);
|
||||
p[7] = (BYTE)(val64>>56);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
{
|
||||
if (MEM_32bits())
|
||||
return (size_t)MEM_readLE32(memPtr);
|
||||
else
|
||||
return (size_t)MEM_readLE64(memPtr);
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)
|
||||
{
|
||||
if (MEM_32bits())
|
||||
MEM_writeLE32(memPtr, (U32)val);
|
||||
else
|
||||
MEM_writeLE64(memPtr, (U64)val);
|
||||
}
|
||||
|
||||
|
||||
#if MINMATCH == 3
|
||||
#define MEM_read24(ptr) (U32)(MEM_read32(ptr)<<8)
|
||||
#else
|
||||
#define MEM_read24(ptr) (U32)(MEM_read32(ptr))
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************
|
||||
* Function body to include for inlining
|
||||
****************************************/
|
||||
static size_t MEM_read_ARCH(const void* p) { size_t r; memcpy(&r, p, sizeof(r)); return r; }
|
||||
|
||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
|
||||
|
||||
/*static unsigned MEM_highbit(U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) // Visual
|
||||
unsigned long r=0;
|
||||
_BitScanReverse(&r, val);
|
||||
return (unsigned)r;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) // GCC Intrinsic
|
||||
return 31 - __builtin_clz(val);
|
||||
# else // Software version
|
||||
static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
|
||||
U32 v = val;
|
||||
int r;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
|
||||
return r;
|
||||
# endif
|
||||
}*/
|
||||
|
||||
|
||||
MEM_STATIC unsigned MEM_NbCommonBytes (register size_t val)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
{
|
||||
if (MEM_64bits())
|
||||
{
|
||||
# if defined(_MSC_VER) && defined(_WIN64)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward64( &r, (U64)val );
|
||||
return (int)(r>>3);
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (__builtin_ctzll((U64)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
|
||||
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
||||
# endif
|
||||
}
|
||||
else /* 32 bits */
|
||||
{
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r=0;
|
||||
_BitScanForward( &r, (U32)val );
|
||||
return (int)(r>>3);
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (__builtin_ctz((U32)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
|
||||
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else /* Big Endian CPU */
|
||||
{
|
||||
if (MEM_32bits())
|
||||
{
|
||||
# if defined(_MSC_VER) && defined(_WIN64)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (__builtin_clzll(val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
|
||||
if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
|
||||
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
}
|
||||
else /* 32 bits */
|
||||
{
|
||||
# if defined(_MSC_VER)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
return (__builtin_clz((U32)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MEM_STATIC size_t MEM_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
|
||||
{
|
||||
const BYTE* const pStart = pIn;
|
||||
|
||||
while ((pIn<pInLimit-(sizeof(size_t)-1)))
|
||||
{
|
||||
size_t diff = MEM_read_ARCH(pMatch) ^ MEM_read_ARCH(pIn);
|
||||
if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
|
||||
pIn += MEM_NbCommonBytes(diff);
|
||||
return (size_t)(pIn - pStart);
|
||||
}
|
||||
|
||||
if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
|
||||
if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
|
||||
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
|
||||
return (size_t)(pIn - pStart);
|
||||
}
|
||||
|
||||
|
||||
static void MEM_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
|
||||
|
||||
#define COPY8(d,s) { MEM_copy8(d,s); d+=8; s+=8; }
|
||||
|
||||
|
||||
/*! MEM_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */
|
||||
/*static void MEM_wildcopy(void* dst, const void* src, size_t length)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + length;
|
||||
do
|
||||
COPY8(op, ip)
|
||||
while (op < oend);
|
||||
} */
|
||||
|
||||
/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
|
||||
static void MEM_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
|
||||
{
|
||||
BYTE* d = (BYTE*)dstPtr;
|
||||
const BYTE* s = (const BYTE*)srcPtr;
|
||||
BYTE* const e = (BYTE*)dstEnd;
|
||||
|
||||
do { MEM_copy8(d,s); d+=8; s+=8; } while (d<e);
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEM_H_MODULE */
|
||||
|
||||
192
C/lz5/xxhash.h
Normal file
192
C/lz5/xxhash.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2015, 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 : https://github.com/Cyan4973/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.
|
||||
|
||||
A 64-bits version, named XXH64, is available since r35.
|
||||
It offers much better speed, but for 64-bits applications only.
|
||||
Name Speed on 64 bits Speed on 32 bits
|
||||
XXH64 13.8 GB/s 1.9 GB/s
|
||||
XXH32 6.8 GB/s 6.0 GB/s
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Definitions
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
/*****************************
|
||||
* Namespace Emulation
|
||||
*****************************/
|
||||
/* Motivations :
|
||||
|
||||
If you need to include xxHash into your library,
|
||||
but wish to avoid xxHash symbols to be present on your library interface
|
||||
in an effort to avoid potential name collision if another library also includes xxHash,
|
||||
|
||||
you can use XXH_NAMESPACE, which will automatically prefix any symbol from xxHash
|
||||
with the value of XXH_NAMESPACE (so avoid to keep it NULL, and avoid numeric values).
|
||||
|
||||
Note that no change is required within the calling program :
|
||||
it can still call xxHash functions using their regular name.
|
||||
They will be automatically translated by this header.
|
||||
*/
|
||||
#ifdef XXH_NAMESPACE
|
||||
# define XXH_CAT(A,B) A##B
|
||||
# define XXH_NAME2(A,B) XXH_CAT(A,B)
|
||||
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
|
||||
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
|
||||
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
|
||||
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
|
||||
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
|
||||
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
|
||||
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
|
||||
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
|
||||
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
|
||||
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
|
||||
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
|
||||
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
unsigned int XXH32 (const void* input, size_t length, unsigned seed);
|
||||
unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
|
||||
|
||||
/*
|
||||
XXH32() :
|
||||
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
||||
The memory between input & input+length 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
|
||||
XXH64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
Faster on 64-bits systems. Slower on 32-bits systems.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
* Advanced Hash Functions
|
||||
*****************************/
|
||||
typedef struct { long long ll[ 6]; } XXH32_state_t;
|
||||
typedef struct { long long ll[11]; } XXH64_state_t;
|
||||
|
||||
/*
|
||||
These structures allow static allocation of XXH states.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
|
||||
If you prefer dynamic allocation, please refer to functions below.
|
||||
*/
|
||||
|
||||
XXH32_state_t* XXH32_createState(void);
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
|
||||
|
||||
XXH64_state_t* XXH64_createState(void);
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions create and release memory for XXH state.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
*/
|
||||
|
||||
|
||||
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned int XXH32_digest (const XXH32_state_t* statePtr);
|
||||
|
||||
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned long long XXH64_digest (const XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions calculate the xxHash of an input provided in multiple smaller packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
XXH state space must first be allocated, using either static or dynamic method provided above.
|
||||
|
||||
Start a new hash by initializing state with a seed, using XXHnn_reset().
|
||||
|
||||
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
|
||||
Obviously, input must be valid, meaning allocated and read accessible.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
|
||||
Finally, you can produce a hash anytime, by using XXHnn_digest().
|
||||
This function returns the final nn-bits hash.
|
||||
You can nonetheless continue feeding the hash state with more input,
|
||||
and therefore get some new hashes, by calling again XXHnn_digest().
|
||||
|
||||
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
|
||||
*/
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user