mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 09:15:00 -06:00
major Lizard fixes
- changed to real Lizard code v1.0 (I used LZ5 v2.0) - add Lizard file handling, so '.liz' files can be used in windows - changed CompressDialog (Lizard has 4 entries in the methods now) - added Lizard icon
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#define MY_VER_MAJOR 17
|
||||
#define MY_VER_MINOR 00
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "17.00 ZS v1.2.0 R4"
|
||||
#define MY_VERSION_NUMBERS "17.00 ZS v1.2.0 R5"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
@@ -10,7 +10,7 @@
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2017-05-27"
|
||||
#define MY_DATE "2017-05-28"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov, Tino Reichardt"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#define MY_VER_MAJOR 1
|
||||
#define MY_VER_MINOR 2
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "1.2.0 R4"
|
||||
#define MY_VERSION_NUMBERS "1.2.0 R5"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
#define MY_DATE "2017-05-27"
|
||||
#define MY_DATE "2017-05-28"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Tino Reichardt"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
LZ5 Library
|
||||
Lizard Library
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
Copyright (C) 2015-2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
# C/lizard/*
|
||||
# /TR 2017-05-25
|
||||
|
||||
for i in *.c *.h; do
|
||||
sed -i 's/LZ5_/LIZ_/g' "$i"
|
||||
sed -i 's/LZ5F_/LIZF_/g' "$i"
|
||||
sed -i 's/"lz5_/"liz_/g' "$i"
|
||||
done
|
||||
|
||||
for f in lz5*; do
|
||||
l=`echo $f|sed -e 's/lz5/liz/g'`
|
||||
mv $f $l
|
||||
done
|
||||
@@ -1,95 +1,76 @@
|
||||
LZ5 - efficient compression with very fast decompression
|
||||
--------------------------------------------------------
|
||||
Lizard - Library Files
|
||||
================================
|
||||
|
||||
LZ5 is a lossless compression algorithm which contains 4 compression methods:
|
||||
- fastLZ4 : compression levels -10...-19 are designed to give better decompression speed than [LZ4] i.e. over 2000 MB/s
|
||||
- LZ5v2 : compression levels -20...-29 are designed to give better ratio than [LZ4] keeping 75% decompression speed
|
||||
- fastLZ4 + Huffman : compression levels -30...-39 add Huffman coding to fastLZ4
|
||||
- LZ5v2 + Huffman : compression levels -40...-49 give the best ratio (comparable to [zlib] and low levels of [zstd]/[brotli]) at decompression speed of 1000 MB/s
|
||||
|
||||
LZ5 library is based on frequently used [LZ4] library by Yann Collet.
|
||||
LZ5 library is provided as open-source software using BSD 2-Clause license.
|
||||
The high compression/decompression speed is achieved without any SSE and AVX extensions.
|
||||
The __lib__ directory contains several directories.
|
||||
Depending on target use case, it's enough to include only files from relevant directories.
|
||||
|
||||
|
||||
|Branch |Status |
|
||||
|------------|---------|
|
||||
|lz5_v1.5 | [![Build Status][travis15Badge]][travisLink] [![Build status][Appveyor15Badge]][AppveyorLink] |
|
||||
|lz5_v2.0 | [![Build Status][travis20Badge]][travisLink] [![Build status][Appveyor20Badge]][AppveyorLink] |
|
||||
#### API
|
||||
|
||||
[travis15Badge]: https://travis-ci.org/inikep/lz5.svg?branch=lz5_v1.5 "Continuous Integration test suite"
|
||||
[travis20Badge]: https://travis-ci.org/inikep/lz5.svg?branch=lz5_v2.0 "Continuous Integration test suite"
|
||||
[travisLink]: https://travis-ci.org/inikep/lz5
|
||||
[Appveyor15Badge]: https://ci.appveyor.com/api/projects/status/o0ib75nwokjiui36/branch/lz5_v1.5?svg=true "Visual test suite"
|
||||
[Appveyor20Badge]: https://ci.appveyor.com/api/projects/status/o0ib75nwokjiui36/branch/lz5_v2.0?svg=true "Visual test suite"
|
||||
[AppveyorLink]: https://ci.appveyor.com/project/inikep/lz5
|
||||
[LZ4]: https://github.com/lz4/lz4
|
||||
[zlib]: https://github.com/madler/zlib
|
||||
[zstd]: https://github.com/facebook/zstd
|
||||
[brotli]: https://github.com/google/brotli
|
||||
Lizard stable API is exposed within [lizard_compress.h](lizard_compress.h) and [lizard_decompress.h](lizard_decompress.h),
|
||||
at the root of `lib` directory.
|
||||
|
||||
|
||||
Benchmarks
|
||||
-------------------------
|
||||
|
||||
The following results are obtained with [lzbench](https://github.com/inikep/lzbench) and `-t16,16`
|
||||
using 1 core of Intel Core i5-4300U, Windows 10 64-bit (MinGW-w64 compilation under gcc 6.2.0)
|
||||
with [silesia.tar] which contains tarred files from [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia).
|
||||
|
||||
| Compressor name | Compression| Decompress.| Compr. size | Ratio |
|
||||
| --------------- | -----------| -----------| ----------- | ----- |
|
||||
| memcpy | 7332 MB/s | 8719 MB/s | 211947520 |100.00 |
|
||||
| lz4 1.7.3 | 440 MB/s | 2318 MB/s | 100880800 | 47.60 |
|
||||
| lz4hc 1.7.3 -1 | 98 MB/s | 2121 MB/s | 87591763 | 41.33 |
|
||||
| lz4hc 1.7.3 -4 | 55 MB/s | 2259 MB/s | 79807909 | 37.65 |
|
||||
| lz4hc 1.7.3 -9 | 22 MB/s | 2315 MB/s | 77892285 | 36.75 |
|
||||
| lz4hc 1.7.3 -12 | 17 MB/s | 2323 MB/s | 77849762 | 36.73 |
|
||||
| lz4hc 1.7.3 -16 | 10 MB/s | 2323 MB/s | 77841782 | 36.73 |
|
||||
| lz5 2.0 -10 | 346 MB/s | 2610 MB/s | 103402971 | 48.79 |
|
||||
| lz5 2.0 -12 | 103 MB/s | 2458 MB/s | 86232422 | 40.69 |
|
||||
| lz5 2.0 -15 | 50 MB/s | 2552 MB/s | 81187330 | 38.31 |
|
||||
| lz5 2.0 -19 | 3.04 MB/s | 2497 MB/s | 77416400 | 36.53 |
|
||||
| lz5 2.0 -21 | 157 MB/s | 1795 MB/s | 89239174 | 42.10 |
|
||||
| lz5 2.0 -23 | 30 MB/s | 1778 MB/s | 81097176 | 38.26 |
|
||||
| lz5 2.0 -26 | 6.63 MB/s | 1734 MB/s | 74503695 | 35.15 |
|
||||
| lz5 2.0 -29 | 1.37 MB/s | 1634 MB/s | 68694227 | 32.41 |
|
||||
| lz5 2.0 -30 | 246 MB/s | 909 MB/s | 85727429 | 40.45 |
|
||||
| lz5 2.0 -32 | 94 MB/s | 1244 MB/s | 76929454 | 36.30 |
|
||||
| lz5 2.0 -35 | 47 MB/s | 1435 MB/s | 73850400 | 34.84 |
|
||||
| lz5 2.0 -39 | 2.94 MB/s | 1502 MB/s | 69807522 | 32.94 |
|
||||
| lz5 2.0 -41 | 126 MB/s | 961 MB/s | 76100661 | 35.91 |
|
||||
| lz5 2.0 -43 | 28 MB/s | 1101 MB/s | 70955653 | 33.48 |
|
||||
| lz5 2.0 -46 | 6.25 MB/s | 1073 MB/s | 65413061 | 30.86 |
|
||||
| lz5 2.0 -49 | 1.27 MB/s | 1064 MB/s | 60679215 | 28.63 |
|
||||
| zlib 1.2.8 -1 | 66 MB/s | 244 MB/s | 77259029 | 36.45 |
|
||||
| zlib 1.2.8 -6 | 20 MB/s | 263 MB/s | 68228431 | 32.19 |
|
||||
| zlib 1.2.8 -9 | 8.37 MB/s | 266 MB/s | 67644548 | 31.92 |
|
||||
| zstd 1.1.1 -1 | 235 MB/s | 645 MB/s | 73659468 | 34.75 |
|
||||
| zstd 1.1.1 -2 | 181 MB/s | 600 MB/s | 70168955 | 33.11 |
|
||||
| zstd 1.1.1 -5 | 88 MB/s | 565 MB/s | 65002208 | 30.67 |
|
||||
| zstd 1.1.1 -8 | 31 MB/s | 619 MB/s | 61026497 | 28.79 |
|
||||
| zstd 1.1.1 -11 | 16 MB/s | 613 MB/s | 59523167 | 28.08 |
|
||||
| zstd 1.1.1 -15 | 4.97 MB/s | 639 MB/s | 58007773 | 27.37 |
|
||||
| zstd 1.1.1 -18 | 2.87 MB/s | 583 MB/s | 55294241 | 26.09 |
|
||||
| zstd 1.1.1 -22 | 1.44 MB/s | 505 MB/s | 52731930 | 24.88 |
|
||||
| brotli 0.5.2 -0 | 217 MB/s | 244 MB/s | 78226979 | 36.91 |
|
||||
| brotli 0.5.2 -2 | 96 MB/s | 283 MB/s | 68066621 | 32.11 |
|
||||
| brotli 0.5.2 -5 | 24 MB/s | 312 MB/s | 60801716 | 28.69 |
|
||||
| brotli 0.5.2 -8 | 5.56 MB/s | 324 MB/s | 57382470 | 27.07 |
|
||||
| brotli 0.5.2 -11 | 0.39 MB/s | 266 MB/s | 51138054 | 24.13 |
|
||||
|
||||
[silesia.tar]: https://drive.google.com/file/d/0BwX7dtyRLxThenZpYU9zLTZhR1k/view?usp=sharing
|
||||
|
||||
|
||||
Documentation
|
||||
-------------------------
|
||||
|
||||
The raw LZ5 block compression format is detailed within [lz5_Block_format].
|
||||
#### Compatibility issues
|
||||
|
||||
The raw Lizard block compression format is detailed within [lizard_Block_format].
|
||||
To compress an arbitrarily long file or data stream, multiple blocks are required.
|
||||
Organizing these blocks and providing a common header format to handle their content
|
||||
is the purpose of the Frame format, defined into [lz5_Frame_format].
|
||||
Interoperable versions of LZ5 must respect this frame format.
|
||||
is the purpose of the Frame format, defined in [lizard_Frame_format].
|
||||
`lizard` command line utility produces files or streams compatible with the Frame format.
|
||||
(_Advanced stuff_ : It's possible to hide xxhash symbols into a local namespace.
|
||||
This is what `liblizard` does, to avoid symbol duplication
|
||||
in case a user program would link to several libraries containing xxhash symbols.)
|
||||
|
||||
[lz5_Block_format]: doc/lz5_Block_format.md
|
||||
[lz5_Frame_format]: doc/lz5_Frame_format.md
|
||||
[lizard_Block_format]: ../doc/lizard_Block_format.md
|
||||
[lizard_Frame_format]: ../doc/lizard_Frame_format.md
|
||||
|
||||
|
||||
#### Various Lizard builds
|
||||
|
||||
Files `lizard_common.h`, `lizard_compress*`, `lizard_parser_*.h`, `lizard_decompress*`, and `entropy\mem.h` are required in all circumstances.
|
||||
|
||||
To compile:
|
||||
- Lizard_raw only with levels 10...29 : use the `-DLIZARD_NO_HUFFMAN` compiler flag
|
||||
- Lizard_raw with levels 10...49 : include also all files from `entropy` directory
|
||||
- Lizard_frame with levels 10...49 : `lizard_frame*` and all files from `entropy` and `xxhash` directories
|
||||
|
||||
|
||||
#### Advanced API
|
||||
|
||||
A more complex `lizard_frame_static.h` is also provided.
|
||||
It contains definitions which are not guaranteed to remain stable within future versions.
|
||||
It must be used with static linking ***only***.
|
||||
|
||||
|
||||
#### Using MinGW+MSYS to create DLL
|
||||
|
||||
DLL can be created using MinGW+MSYS with the `make liblizard` command.
|
||||
This command creates `dll\liblizard.dll` and the import library `dll\liblizard.lib`.
|
||||
The import library is only required with Visual C++.
|
||||
The header files `lizard.h`, `lizardhc.h`, `lizard_frame.h` and the dynamic library
|
||||
`dll\liblizard.dll` are required to compile a project using gcc/MinGW.
|
||||
The dynamic library has to be added to linking options.
|
||||
It means that if a project that uses Lizard consists of a single `test-dll.c`
|
||||
file it should be compiled with `liblizard.lib`. For example:
|
||||
```
|
||||
gcc $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\liblizard.dll
|
||||
```
|
||||
The compiled executable will require Lizard DLL which is available at `dll\liblizard.dll`.
|
||||
|
||||
|
||||
#### Miscellaneous
|
||||
|
||||
Other files present in the directory are not source code. There are :
|
||||
|
||||
- LICENSE : contains the BSD license text
|
||||
- Makefile : script to compile or install lizard library (static or dynamic)
|
||||
- liblizard.pc.in : for pkg-config (make install)
|
||||
- README.md : this file
|
||||
|
||||
|
||||
#### License
|
||||
|
||||
All source material within __lib__ directory are BSD 2-Clause licensed.
|
||||
See [LICENSE](LICENSE) for details.
|
||||
The license is also repeated at the top of each source file.
|
||||
|
||||
@@ -1,414 +0,0 @@
|
||||
/* ******************************************************************
|
||||
bitstream
|
||||
Part of FSE library
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2016, 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 :
|
||||
- Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
****************************************************************** */
|
||||
#ifndef BITSTREAM_H_MODULE
|
||||
#define BITSTREAM_H_MODULE
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This API consists of small unitary functions, which must be inlined for best performance.
|
||||
* Since link-time-optimization is not available for all compilers,
|
||||
* these functions are defined into a .h to be included.
|
||||
*/
|
||||
|
||||
/*-****************************************
|
||||
* Dependencies
|
||||
******************************************/
|
||||
#include "mem.h" /* unaligned access routines */
|
||||
#include "error_private.h" /* error codes and messages */
|
||||
|
||||
|
||||
/*=========================================
|
||||
* Target specific
|
||||
=========================================*/
|
||||
#if defined(__BMI__) && defined(__GNUC__)
|
||||
# include <immintrin.h> /* support for bextr (experimental) */
|
||||
#endif
|
||||
|
||||
|
||||
/*-******************************************
|
||||
* bitStream encoding API (write forward)
|
||||
********************************************/
|
||||
/* bitStream can mix input from multiple sources.
|
||||
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
size_t bitContainer;
|
||||
int bitPos;
|
||||
char* startPtr;
|
||||
char* ptr;
|
||||
char* endPtr;
|
||||
} BIT_CStream_t;
|
||||
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
|
||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
|
||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
|
||||
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
|
||||
|
||||
/* Start with initCStream, providing the size of buffer to write into.
|
||||
* bitStream will never write outside of this buffer.
|
||||
* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
|
||||
*
|
||||
* bits are first added to a local register.
|
||||
* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
|
||||
* Writing data into memory is an explicit operation, performed by the flushBits function.
|
||||
* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
|
||||
* After a flushBits, a maximum of 7 bits might still be stored into local register.
|
||||
*
|
||||
* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
|
||||
*
|
||||
* Last operation is to close the bitStream.
|
||||
* The function returns the final size of CStream in bytes.
|
||||
* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
|
||||
*/
|
||||
|
||||
|
||||
/*-********************************************
|
||||
* bitStream decoding API (read backward)
|
||||
**********************************************/
|
||||
typedef struct
|
||||
{
|
||||
size_t bitContainer;
|
||||
unsigned bitsConsumed;
|
||||
const char* ptr;
|
||||
const char* start;
|
||||
} BIT_DStream_t;
|
||||
|
||||
typedef enum { BIT_DStream_unfinished = 0,
|
||||
BIT_DStream_endOfBuffer = 1,
|
||||
BIT_DStream_completed = 2,
|
||||
BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
|
||||
/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
|
||||
|
||||
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
|
||||
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
|
||||
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
|
||||
|
||||
|
||||
/* Start by invoking BIT_initDStream().
|
||||
* A chunk of the bitStream is then stored into a local register.
|
||||
* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||
* You can then retrieve bitFields stored into the local register, **in reverse order**.
|
||||
* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
|
||||
* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
|
||||
* Otherwise, it can be less than that, so proceed accordingly.
|
||||
* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
|
||||
*/
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* unsafe API
|
||||
******************************************/
|
||||
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
|
||||
/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
|
||||
|
||||
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
|
||||
/* unsafe version; does not check buffer overflow */
|
||||
|
||||
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
/* faster, but works only if nbBits >= 1 */
|
||||
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* Internal functions
|
||||
****************************************************************/
|
||||
MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
||||
{
|
||||
# if defined(_MSC_VER) /* Visual */
|
||||
unsigned long r=0;
|
||||
_BitScanReverse ( &r, val );
|
||||
return (unsigned) r;
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||
return 31 - __builtin_clz (val);
|
||||
# else /* Software version */
|
||||
static const unsigned 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;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
|
||||
# endif
|
||||
}
|
||||
|
||||
/*===== Local Constants =====*/
|
||||
static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* bitStream encoding
|
||||
****************************************************************/
|
||||
/*! BIT_initCStream() :
|
||||
* `dstCapacity` must be > sizeof(void*)
|
||||
* @return : 0 if success,
|
||||
otherwise an error code (can be tested using ERR_isError() ) */
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
|
||||
{
|
||||
bitC->bitContainer = 0;
|
||||
bitC->bitPos = 0;
|
||||
bitC->startPtr = (char*)startPtr;
|
||||
bitC->ptr = bitC->startPtr;
|
||||
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
|
||||
if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! BIT_addBits() :
|
||||
can add up to 26 bits into `bitC`.
|
||||
Does not check for register overflow ! */
|
||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
||||
{
|
||||
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
|
||||
bitC->bitPos += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_addBitsFast() :
|
||||
* works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
|
||||
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
||||
{
|
||||
bitC->bitContainer |= value << bitC->bitPos;
|
||||
bitC->bitPos += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_flushBitsFast() :
|
||||
* unsafe version; does not check buffer overflow */
|
||||
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||
bitC->ptr += nbBytes;
|
||||
bitC->bitPos &= 7;
|
||||
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
|
||||
}
|
||||
|
||||
/*! BIT_flushBits() :
|
||||
* safe version; check for buffer overflow, and prevents it.
|
||||
* note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
|
||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||
bitC->ptr += nbBytes;
|
||||
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
|
||||
bitC->bitPos &= 7;
|
||||
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
|
||||
}
|
||||
|
||||
/*! BIT_closeCStream() :
|
||||
* @return : size of CStream, in bytes,
|
||||
or 0 if it could not fit into dstBuffer */
|
||||
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
||||
{
|
||||
BIT_addBitsFast(bitC, 1, 1); /* endMark */
|
||||
BIT_flushBits(bitC);
|
||||
|
||||
if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */
|
||||
|
||||
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
|
||||
}
|
||||
|
||||
|
||||
/*-********************************************************
|
||||
* bitStream decoding
|
||||
**********************************************************/
|
||||
/*! BIT_initDStream() :
|
||||
* Initialize a BIT_DStream_t.
|
||||
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
||||
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
||||
* @return : size of stream (== srcSize) or an errorCode if a problem is detected
|
||||
*/
|
||||
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
|
||||
{
|
||||
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||
|
||||
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
||||
bitD->start = (const char*)srcBuffer;
|
||||
bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
||||
} else {
|
||||
bitD->start = (const char*)srcBuffer;
|
||||
bitD->ptr = bitD->start;
|
||||
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
||||
switch(srcSize)
|
||||
{
|
||||
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
|
||||
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
||||
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
||||
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
||||
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
||||
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
||||
default:;
|
||||
}
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
||||
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
|
||||
}
|
||||
|
||||
return srcSize;
|
||||
}
|
||||
|
||||
MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
|
||||
{
|
||||
return bitContainer >> start;
|
||||
}
|
||||
|
||||
MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
|
||||
{
|
||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental */
|
||||
# if defined(__x86_64__)
|
||||
if (sizeof(bitContainer)==8)
|
||||
return _bextr_u64(bitContainer, start, nbBits);
|
||||
else
|
||||
# endif
|
||||
return _bextr_u32(bitContainer, start, nbBits);
|
||||
#else
|
||||
return (bitContainer >> start) & BIT_mask[nbBits];
|
||||
#endif
|
||||
}
|
||||
|
||||
MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
||||
{
|
||||
return bitContainer & BIT_mask[nbBits];
|
||||
}
|
||||
|
||||
/*! BIT_lookBits() :
|
||||
* Provides next n bits from local register.
|
||||
* local register is not modified.
|
||||
* On 32-bits, maxNbBits==24.
|
||||
* On 64-bits, maxNbBits==56.
|
||||
* @return : value extracted
|
||||
*/
|
||||
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
|
||||
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
||||
#else
|
||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! BIT_lookBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
|
||||
}
|
||||
|
||||
MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
bitD->bitsConsumed += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_readBits() :
|
||||
* Read (consume) next n bits from local register and update.
|
||||
* Pay attention to not read more than nbBits contained into local register.
|
||||
* @return : extracted value.
|
||||
*/
|
||||
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t const value = BIT_lookBits(bitD, nbBits);
|
||||
BIT_skipBits(bitD, nbBits);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*! BIT_readBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
||||
BIT_skipBits(bitD, nbBits);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*! BIT_reloadDStream() :
|
||||
* Refill `BIT_DStream_t` from src buffer previously defined (see BIT_initDStream() ).
|
||||
* This function is safe, it guarantees it will not read beyond src buffer.
|
||||
* @return : status of `BIT_DStream_t` internal register.
|
||||
if status == unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
|
||||
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
{
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
|
||||
return BIT_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
|
||||
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||
bitD->bitsConsumed &= 7;
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||
return BIT_DStream_unfinished;
|
||||
}
|
||||
if (bitD->ptr == bitD->start) {
|
||||
if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
|
||||
return BIT_DStream_completed;
|
||||
}
|
||||
{ U32 nbBytes = bitD->bitsConsumed >> 3;
|
||||
BIT_DStream_status result = BIT_DStream_unfinished;
|
||||
if (bitD->ptr - nbBytes < bitD->start) {
|
||||
nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
|
||||
result = BIT_DStream_endOfBuffer;
|
||||
}
|
||||
bitD->ptr -= nbBytes;
|
||||
bitD->bitsConsumed -= nbBytes*8;
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*! BIT_endOfDStream() :
|
||||
* @return Tells if DStream has exactly reached its end (all bits consumed).
|
||||
*/
|
||||
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
{
|
||||
return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BITSTREAM_H_MODULE */
|
||||
@@ -1,125 +0,0 @@
|
||||
/* ******************************************************************
|
||||
Error codes and messages
|
||||
Copyright (C) 2013-2016, 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 :
|
||||
- Homepage : http://www.zstd.net
|
||||
****************************************************************** */
|
||||
/* Note : this module is expected to remain private, do not expose it */
|
||||
|
||||
#ifndef ERROR_H_MODULE
|
||||
#define ERROR_H_MODULE
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Dependencies
|
||||
******************************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
#include "error_public.h" /* enum list */
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Compiler-specific
|
||||
******************************************/
|
||||
#if defined(__GNUC__)
|
||||
# define ERR_STATIC static __attribute__((unused))
|
||||
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define ERR_STATIC static inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define ERR_STATIC static __inline
|
||||
#else
|
||||
# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
#endif
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Customization (error_public.h)
|
||||
******************************************/
|
||||
typedef ZSTD_ErrorCode ERR_enum;
|
||||
#define PREFIX(name) ZSTD_error_##name
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Error codes handling
|
||||
******************************************/
|
||||
#ifdef ERROR
|
||||
# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
|
||||
#endif
|
||||
#define ERROR(name) ((size_t)-PREFIX(name))
|
||||
|
||||
ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
|
||||
|
||||
ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Error Strings
|
||||
******************************************/
|
||||
|
||||
ERR_STATIC const char* ERR_getErrorString(ERR_enum code)
|
||||
{
|
||||
static const char* notErrorCode = "Unspecified error code";
|
||||
switch( code )
|
||||
{
|
||||
case PREFIX(no_error): return "No error detected";
|
||||
case PREFIX(GENERIC): return "Error (generic)";
|
||||
case PREFIX(prefix_unknown): return "Unknown frame descriptor";
|
||||
case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
|
||||
case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
|
||||
case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
|
||||
case PREFIX(init_missing): return "Context should be init first";
|
||||
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
|
||||
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
|
||||
case PREFIX(srcSize_wrong): return "Src size incorrect";
|
||||
case PREFIX(corruption_detected): return "Corrupted block detected";
|
||||
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
|
||||
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
|
||||
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
|
||||
case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
|
||||
case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
|
||||
case PREFIX(dictionary_wrong): return "Dictionary mismatch";
|
||||
case PREFIX(maxCode):
|
||||
default: return notErrorCode;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_STATIC const char* ERR_getErrorName(size_t code)
|
||||
{
|
||||
return ERR_getErrorString(ERR_getErrorCode(code));
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ERROR_H_MODULE */
|
||||
@@ -1,77 +0,0 @@
|
||||
/* ******************************************************************
|
||||
Error codes list
|
||||
Copyright (C) 2016, 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 :
|
||||
- Homepage : http://www.zstd.net
|
||||
****************************************************************** */
|
||||
#ifndef ERROR_PUBLIC_H_MODULE
|
||||
#define ERROR_PUBLIC_H_MODULE
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* error codes list
|
||||
******************************************/
|
||||
typedef enum {
|
||||
ZSTD_error_no_error,
|
||||
ZSTD_error_GENERIC,
|
||||
ZSTD_error_prefix_unknown,
|
||||
ZSTD_error_frameParameter_unsupported,
|
||||
ZSTD_error_frameParameter_unsupportedBy32bits,
|
||||
ZSTD_error_compressionParameter_unsupported,
|
||||
ZSTD_error_init_missing,
|
||||
ZSTD_error_memory_allocation,
|
||||
ZSTD_error_stage_wrong,
|
||||
ZSTD_error_dstSize_tooSmall,
|
||||
ZSTD_error_srcSize_wrong,
|
||||
ZSTD_error_corruption_detected,
|
||||
ZSTD_error_checksum_wrong,
|
||||
ZSTD_error_tableLog_tooLarge,
|
||||
ZSTD_error_maxSymbolValue_tooLarge,
|
||||
ZSTD_error_maxSymbolValue_tooSmall,
|
||||
ZSTD_error_dictionary_corrupted,
|
||||
ZSTD_error_dictionary_wrong,
|
||||
ZSTD_error_maxCode
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
/*! ZSTD_getErrorCode() :
|
||||
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
||||
which can be used to compare directly with enum list published into "error_public.h" */
|
||||
ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
|
||||
const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ERROR_PUBLIC_H_MODULE */
|
||||
628
C/lizard/fse.h
628
C/lizard/fse.h
@@ -1,628 +0,0 @@
|
||||
/* ******************************************************************
|
||||
FSE : Finite State Entropy codec
|
||||
Public Prototypes declaration
|
||||
Copyright (C) 2013-2016, 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 :
|
||||
- Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
****************************************************************** */
|
||||
#ifndef LIZFSE_H
|
||||
#define LIZFSE_H
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* Dependencies
|
||||
******************************************/
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* FSE simple functions
|
||||
******************************************/
|
||||
/*! LIZFSE_compress() :
|
||||
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
||||
'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= LIZFSE_compressBound(srcSize).
|
||||
@return : size of compressed data (<= dstCapacity).
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
|
||||
if LIZFSE_isError(return), compression failed (more details using LIZFSE_getErrorName())
|
||||
*/
|
||||
size_t LIZFSE_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/*! LIZFSE_decompress():
|
||||
Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
|
||||
into already allocated destination buffer 'dst', of size 'dstCapacity'.
|
||||
@return : size of regenerated data (<= maxDstSize),
|
||||
or an error code, which can be tested using LIZFSE_isError() .
|
||||
|
||||
** Important ** : LIZFSE_decompress() does not decompress non-compressible nor RLE data !!!
|
||||
Why ? : making this distinction requires a header.
|
||||
Header management is intentionally delegated to the user layer, which can better manage special cases.
|
||||
*/
|
||||
size_t LIZFSE_decompress(void* dst, size_t dstCapacity,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* Tool functions
|
||||
******************************************/
|
||||
size_t LIZFSE_compressBound(size_t size); /* maximum compressed size */
|
||||
|
||||
/* Error Management */
|
||||
unsigned LIZFSE_isError(size_t code); /* tells if a return value is an error code */
|
||||
const char* LIZFSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* FSE advanced functions
|
||||
******************************************/
|
||||
/*! LIZFSE_compress2() :
|
||||
Same as LIZFSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
|
||||
Both parameters can be defined as '0' to mean : use default value
|
||||
@return : size of compressed data
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
|
||||
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
|
||||
if LIZFSE_isError(return), it's an error code.
|
||||
*/
|
||||
size_t LIZFSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* FSE detailed API
|
||||
******************************************/
|
||||
/*!
|
||||
LIZFSE_compress() does the following:
|
||||
1. count symbol occurrence from source[] into table count[]
|
||||
2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
|
||||
3. save normalized counters to memory buffer using writeNCount()
|
||||
4. build encoding table 'CTable' from normalized counters
|
||||
5. encode the data stream using encoding table 'CTable'
|
||||
|
||||
LIZFSE_decompress() does the following:
|
||||
1. read normalized counters with readNCount()
|
||||
2. build decoding table 'DTable' from normalized counters
|
||||
3. decode the data stream using decoding table 'DTable'
|
||||
|
||||
The following API allows targeting specific sub-functions for advanced tasks.
|
||||
For example, it's possible to compress several blocks using the same 'CTable',
|
||||
or to save and provide normalized distribution using external method.
|
||||
*/
|
||||
|
||||
/* *** COMPRESSION *** */
|
||||
|
||||
/*! LIZFSE_count():
|
||||
Provides the precise count of each byte within a table 'count'.
|
||||
'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).
|
||||
*maxSymbolValuePtr will be updated if detected smaller than initial value.
|
||||
@return : the count of the most frequent symbol (which is not identified).
|
||||
if return == srcSize, there is only one symbol.
|
||||
Can also return an error code, which can be tested with LIZFSE_isError(). */
|
||||
size_t LIZFSE_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
|
||||
|
||||
/*! LIZFSE_optimalTableLog():
|
||||
dynamically downsize 'tableLog' when conditions are met.
|
||||
It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
|
||||
@return : recommended tableLog (necessarily <= 'maxTableLog') */
|
||||
unsigned LIZFSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
|
||||
|
||||
/*! LIZFSE_normalizeCount():
|
||||
normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
|
||||
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
|
||||
@return : tableLog,
|
||||
or an errorCode, which can be tested using LIZFSE_isError() */
|
||||
size_t LIZFSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t srcSize, unsigned maxSymbolValue);
|
||||
|
||||
/*! LIZFSE_NCountWriteBound():
|
||||
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
|
||||
Typically useful for allocation purpose. */
|
||||
size_t LIZFSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/*! LIZFSE_writeNCount():
|
||||
Compactly save 'normalizedCounter' into 'buffer'.
|
||||
@return : size of the compressed table,
|
||||
or an errorCode, which can be tested using LIZFSE_isError(). */
|
||||
size_t LIZFSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
|
||||
/*! Constructor and Destructor of LIZFSE_CTable.
|
||||
Note that LIZFSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
|
||||
typedef unsigned LIZFSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
|
||||
LIZFSE_CTable* LIZFSE_createCTable (unsigned tableLog, unsigned maxSymbolValue);
|
||||
void LIZFSE_freeCTable (LIZFSE_CTable* ct);
|
||||
|
||||
/*! LIZFSE_buildCTable():
|
||||
Builds `ct`, which must be already allocated, using LIZFSE_createCTable().
|
||||
@return : 0, or an errorCode, which can be tested using LIZFSE_isError() */
|
||||
size_t LIZFSE_buildCTable(LIZFSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/*! LIZFSE_compress_usingCTable():
|
||||
Compress `src` using `ct` into `dst` which must be already allocated.
|
||||
@return : size of compressed data (<= `dstCapacity`),
|
||||
or 0 if compressed data could not fit into `dst`,
|
||||
or an errorCode, which can be tested using LIZFSE_isError() */
|
||||
size_t LIZFSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const LIZFSE_CTable* ct);
|
||||
|
||||
/*!
|
||||
Tutorial :
|
||||
----------
|
||||
The first step is to count all symbols. LIZFSE_count() does this job very fast.
|
||||
Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
|
||||
'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
|
||||
maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
|
||||
LIZFSE_count() will return the number of occurrence of the most frequent symbol.
|
||||
This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
|
||||
If there is an error, the function will return an ErrorCode (which can be tested using LIZFSE_isError()).
|
||||
|
||||
The next step is to normalize the frequencies.
|
||||
LIZFSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
|
||||
It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
|
||||
You can use 'tableLog'==0 to mean "use default tableLog value".
|
||||
If you are unsure of which tableLog value to use, you can ask LIZFSE_optimalTableLog(),
|
||||
which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
|
||||
|
||||
The result of LIZFSE_normalizeCount() will be saved into a table,
|
||||
called 'normalizedCounter', which is a table of signed short.
|
||||
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
|
||||
The return value is tableLog if everything proceeded as expected.
|
||||
It is 0 if there is a single symbol within distribution.
|
||||
If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using LIZFSE_isError()).
|
||||
|
||||
'normalizedCounter' can be saved in a compact manner to a memory area using LIZFSE_writeNCount().
|
||||
'buffer' must be already allocated.
|
||||
For guaranteed success, buffer size must be at least LIZFSE_headerBound().
|
||||
The result of the function is the number of bytes written into 'buffer'.
|
||||
If there is an error, the function will return an ErrorCode (which can be tested using LIZFSE_isError(); ex : buffer size too small).
|
||||
|
||||
'normalizedCounter' can then be used to create the compression table 'CTable'.
|
||||
The space required by 'CTable' must be already allocated, using LIZFSE_createCTable().
|
||||
You can then use LIZFSE_buildCTable() to fill 'CTable'.
|
||||
If there is an error, both functions will return an ErrorCode (which can be tested using LIZFSE_isError()).
|
||||
|
||||
'CTable' can then be used to compress 'src', with LIZFSE_compress_usingCTable().
|
||||
Similar to LIZFSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
|
||||
The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
|
||||
If it returns '0', compressed data could not fit into 'dst'.
|
||||
If there is an error, the function will return an ErrorCode (which can be tested using LIZFSE_isError()).
|
||||
*/
|
||||
|
||||
|
||||
/* *** DECOMPRESSION *** */
|
||||
|
||||
/*! LIZFSE_readNCount():
|
||||
Read compactly saved 'normalizedCounter' from 'rBuffer'.
|
||||
@return : size read from 'rBuffer',
|
||||
or an errorCode, which can be tested using LIZFSE_isError().
|
||||
maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
|
||||
size_t LIZFSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
|
||||
|
||||
/*! Constructor and Destructor of LIZFSE_DTable.
|
||||
Note that its size depends on 'tableLog' */
|
||||
typedef unsigned LIZFSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
|
||||
LIZFSE_DTable* LIZFSE_createDTable(unsigned tableLog);
|
||||
void LIZFSE_freeDTable(LIZFSE_DTable* dt);
|
||||
|
||||
/*! LIZFSE_buildDTable():
|
||||
Builds 'dt', which must be already allocated, using LIZFSE_createDTable().
|
||||
return : 0, or an errorCode, which can be tested using LIZFSE_isError() */
|
||||
size_t LIZFSE_buildDTable (LIZFSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/*! LIZFSE_decompress_usingDTable():
|
||||
Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
|
||||
into `dst` which must be already allocated.
|
||||
@return : size of regenerated data (necessarily <= `dstCapacity`),
|
||||
or an errorCode, which can be tested using LIZFSE_isError() */
|
||||
size_t LIZFSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const LIZFSE_DTable* dt);
|
||||
|
||||
/*!
|
||||
Tutorial :
|
||||
----------
|
||||
(Note : these functions only decompress FSE-compressed blocks.
|
||||
If block is uncompressed, use memcpy() instead
|
||||
If block is a single repeated byte, use memset() instead )
|
||||
|
||||
The first step is to obtain the normalized frequencies of symbols.
|
||||
This can be performed by LIZFSE_readNCount() if it was saved using LIZFSE_writeNCount().
|
||||
'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
|
||||
In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
|
||||
or size the table to handle worst case situations (typically 256).
|
||||
LIZFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
|
||||
The result of LIZFSE_readNCount() is the number of bytes read from 'rBuffer'.
|
||||
Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
|
||||
If there is an error, the function will return an error code, which can be tested using LIZFSE_isError().
|
||||
|
||||
The next step is to build the decompression tables 'LIZFSE_DTable' from 'normalizedCounter'.
|
||||
This is performed by the function LIZFSE_buildDTable().
|
||||
The space required by 'LIZFSE_DTable' must be already allocated using LIZFSE_createDTable().
|
||||
If there is an error, the function will return an error code, which can be tested using LIZFSE_isError().
|
||||
|
||||
`LIZFSE_DTable` can then be used to decompress `cSrc`, with LIZFSE_decompress_usingDTable().
|
||||
`cSrcSize` must be strictly correct, otherwise decompression will fail.
|
||||
LIZFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
|
||||
If there is an error, the function will return an error code, which can be tested using LIZFSE_isError(). (ex: dst buffer too small)
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LIZFSE_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependency *** */
|
||||
#include "bitstream.h"
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* Static allocation
|
||||
*******************************************/
|
||||
/* FSE buffer bounds */
|
||||
#define LIZFSE_NCOUNTBOUND 512
|
||||
#define LIZFSE_BLOCKBOUND(size) (size + (size>>7))
|
||||
#define LIZFSE_COMPRESSBOUND(size) (LIZFSE_NCOUNTBOUND + LIZFSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
|
||||
|
||||
/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */
|
||||
#define LIZFSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
|
||||
#define LIZFSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* FSE advanced API
|
||||
*******************************************/
|
||||
size_t LIZFSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
|
||||
/**< same as LIZFSE_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */
|
||||
|
||||
unsigned LIZFSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
|
||||
/**< same as LIZFSE_optimalTableLog(), which used `minus==2` */
|
||||
|
||||
size_t LIZFSE_buildCTable_raw (LIZFSE_CTable* ct, unsigned nbBits);
|
||||
/**< build a fake LIZFSE_CTable, designed to not compress an input, where each symbol uses nbBits */
|
||||
|
||||
size_t LIZFSE_buildCTable_rle (LIZFSE_CTable* ct, unsigned char symbolValue);
|
||||
/**< build a fake LIZFSE_CTable, designed to compress always the same symbolValue */
|
||||
|
||||
size_t LIZFSE_buildDTable_raw (LIZFSE_DTable* dt, unsigned nbBits);
|
||||
/**< build a fake LIZFSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
|
||||
|
||||
size_t LIZFSE_buildDTable_rle (LIZFSE_DTable* dt, unsigned char symbolValue);
|
||||
/**< build a fake LIZFSE_DTable, designed to always generate the same symbolValue */
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* FSE symbol compression API
|
||||
*******************************************/
|
||||
/*!
|
||||
This API consists of small unitary functions, which highly benefit from being inlined.
|
||||
You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary.
|
||||
Visual seems to do it automatically.
|
||||
For gcc or clang, you'll need to add -flto flag at compilation and linking stages.
|
||||
If none of these solutions is applicable, include "fse.c" directly.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ptrdiff_t value;
|
||||
const void* stateTable;
|
||||
const void* symbolTT;
|
||||
unsigned stateLog;
|
||||
} LIZFSE_CState_t;
|
||||
|
||||
static void LIZFSE_initCState(LIZFSE_CState_t* CStatePtr, const LIZFSE_CTable* ct);
|
||||
|
||||
static void LIZFSE_encodeSymbol(BIT_CStream_t* bitC, LIZFSE_CState_t* CStatePtr, unsigned symbol);
|
||||
|
||||
static void LIZFSE_flushCState(BIT_CStream_t* bitC, const LIZFSE_CState_t* CStatePtr);
|
||||
|
||||
/**<
|
||||
These functions are inner components of LIZFSE_compress_usingCTable().
|
||||
They allow the creation of custom streams, mixing multiple tables and bit sources.
|
||||
|
||||
A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
|
||||
So the first symbol you will encode is the last you will decode, like a LIFO stack.
|
||||
|
||||
You will need a few variables to track your CStream. They are :
|
||||
|
||||
LIZFSE_CTable ct; // Provided by LIZFSE_buildCTable()
|
||||
BIT_CStream_t bitStream; // bitStream tracking structure
|
||||
LIZFSE_CState_t state; // State tracking structure (can have several)
|
||||
|
||||
|
||||
The first thing to do is to init bitStream and state.
|
||||
size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
|
||||
LIZFSE_initCState(&state, ct);
|
||||
|
||||
Note that BIT_initCStream() can produce an error code, so its result should be tested, using LIZFSE_isError();
|
||||
You can then encode your input data, byte after byte.
|
||||
LIZFSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
|
||||
Remember decoding will be done in reverse direction.
|
||||
LIZFSE_encodeByte(&bitStream, &state, symbol);
|
||||
|
||||
At any time, you can also add any bit sequence.
|
||||
Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
|
||||
BIT_addBits(&bitStream, bitField, nbBits);
|
||||
|
||||
The above methods don't commit data to memory, they just store it into local register, for speed.
|
||||
Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||
Writing data to memory is a manual operation, performed by the flushBits function.
|
||||
BIT_flushBits(&bitStream);
|
||||
|
||||
Your last FSE encoding operation shall be to flush your last state value(s).
|
||||
LIZFSE_flushState(&bitStream, &state);
|
||||
|
||||
Finally, you must close the bitStream.
|
||||
The function returns the size of CStream in bytes.
|
||||
If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
|
||||
If there is an error, it returns an errorCode (which can be tested using LIZFSE_isError()).
|
||||
size_t size = BIT_closeCStream(&bitStream);
|
||||
*/
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* FSE symbol decompression API
|
||||
*******************************************/
|
||||
typedef struct
|
||||
{
|
||||
size_t state;
|
||||
const void* table; /* precise table may vary, depending on U16 */
|
||||
} LIZFSE_DState_t;
|
||||
|
||||
|
||||
static void LIZFSE_initDState(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const LIZFSE_DTable* dt);
|
||||
|
||||
static unsigned char LIZFSE_decodeSymbol(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
|
||||
|
||||
static unsigned LIZFSE_endOfDState(const LIZFSE_DState_t* DStatePtr);
|
||||
|
||||
/**<
|
||||
Let's now decompose LIZFSE_decompress_usingDTable() into its unitary components.
|
||||
You will decode FSE-encoded symbols from the bitStream,
|
||||
and also any other bitFields you put in, **in reverse order**.
|
||||
|
||||
You will need a few variables to track your bitStream. They are :
|
||||
|
||||
BIT_DStream_t DStream; // Stream context
|
||||
LIZFSE_DState_t DState; // State context. Multiple ones are possible
|
||||
LIZFSE_DTable* DTablePtr; // Decoding table, provided by LIZFSE_buildDTable()
|
||||
|
||||
The first thing to do is to init the bitStream.
|
||||
errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
|
||||
|
||||
You should then retrieve your initial state(s)
|
||||
(in reverse flushing order if you have several ones) :
|
||||
errorCode = LIZFSE_initDState(&DState, &DStream, DTablePtr);
|
||||
|
||||
You can then decode your data, symbol after symbol.
|
||||
For information the maximum number of bits read by LIZFSE_decodeSymbol() is 'tableLog'.
|
||||
Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
|
||||
unsigned char symbol = LIZFSE_decodeSymbol(&DState, &DStream);
|
||||
|
||||
You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
|
||||
Note : maximum allowed nbBits is 25, for 32-bits compatibility
|
||||
size_t bitField = BIT_readBits(&DStream, nbBits);
|
||||
|
||||
All above operations only read from local register (which size depends on size_t).
|
||||
Refueling the register from memory is manually performed by the reload method.
|
||||
endSignal = LIZFSE_reloadDStream(&DStream);
|
||||
|
||||
BIT_reloadDStream() result tells if there is still some more data to read from DStream.
|
||||
BIT_DStream_unfinished : there is still some data left into the DStream.
|
||||
BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
|
||||
BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
|
||||
BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
|
||||
|
||||
When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
|
||||
to properly detect the exact end of stream.
|
||||
After each decoded symbol, check if DStream is fully consumed using this simple test :
|
||||
BIT_reloadDStream(&DStream) >= BIT_DStream_completed
|
||||
|
||||
When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
|
||||
Checking if DStream has reached its end is performed by :
|
||||
BIT_endOfDStream(&DStream);
|
||||
Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
|
||||
LIZFSE_endOfDState(&DState);
|
||||
*/
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* FSE unsafe API
|
||||
*******************************************/
|
||||
static unsigned char LIZFSE_decodeSymbolFast(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
|
||||
/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* Implementation of inlined functions
|
||||
*******************************************/
|
||||
typedef struct {
|
||||
int deltaFindState;
|
||||
U32 deltaNbBits;
|
||||
} LIZFSE_symbolCompressionTransform; /* total 8 bytes */
|
||||
|
||||
MEM_STATIC void LIZFSE_initCState(LIZFSE_CState_t* statePtr, const LIZFSE_CTable* ct)
|
||||
{
|
||||
const void* ptr = ct;
|
||||
const U16* u16ptr = (const U16*) ptr;
|
||||
const U32 tableLog = MEM_read16(ptr);
|
||||
statePtr->value = (ptrdiff_t)1<<tableLog;
|
||||
statePtr->stateTable = u16ptr+2;
|
||||
statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1));
|
||||
statePtr->stateLog = tableLog;
|
||||
}
|
||||
|
||||
|
||||
/*! LIZFSE_initCState2() :
|
||||
* Same as LIZFSE_initCState(), but the first symbol to include (which will be the last to be read)
|
||||
* uses the smallest state value possible, saving the cost of this symbol */
|
||||
MEM_STATIC void LIZFSE_initCState2(LIZFSE_CState_t* statePtr, const LIZFSE_CTable* ct, U32 symbol)
|
||||
{
|
||||
LIZFSE_initCState(statePtr, ct);
|
||||
{ const LIZFSE_symbolCompressionTransform symbolTT = ((const LIZFSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||
const U16* stateTable = (const U16*)(statePtr->stateTable);
|
||||
U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
|
||||
statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
|
||||
statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||
}
|
||||
}
|
||||
|
||||
MEM_STATIC void LIZFSE_encodeSymbol(BIT_CStream_t* bitC, LIZFSE_CState_t* statePtr, U32 symbol)
|
||||
{
|
||||
const LIZFSE_symbolCompressionTransform symbolTT = ((const LIZFSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||
const U16* const stateTable = (const U16*)(statePtr->stateTable);
|
||||
U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
|
||||
BIT_addBits(bitC, statePtr->value, nbBitsOut);
|
||||
statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||
}
|
||||
|
||||
MEM_STATIC void LIZFSE_flushCState(BIT_CStream_t* bitC, const LIZFSE_CState_t* statePtr)
|
||||
{
|
||||
BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
|
||||
BIT_flushBits(bitC);
|
||||
}
|
||||
|
||||
/* ====== Decompression ====== */
|
||||
|
||||
typedef struct {
|
||||
U16 tableLog;
|
||||
U16 fastMode;
|
||||
} LIZFSE_DTableHeader; /* sizeof U32 */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short newState;
|
||||
unsigned char symbol;
|
||||
unsigned char nbBits;
|
||||
} LIZFSE_decode_t; /* size == U32 */
|
||||
|
||||
MEM_STATIC void LIZFSE_initDState(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const LIZFSE_DTable* dt)
|
||||
{
|
||||
const void* ptr = dt;
|
||||
const LIZFSE_DTableHeader* const DTableH = (const LIZFSE_DTableHeader*)ptr;
|
||||
DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
|
||||
BIT_reloadDStream(bitD);
|
||||
DStatePtr->table = dt + 1;
|
||||
}
|
||||
|
||||
MEM_STATIC BYTE LIZFSE_peekSymbol(const LIZFSE_DState_t* DStatePtr)
|
||||
{
|
||||
LIZFSE_decode_t const DInfo = ((const LIZFSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
return DInfo.symbol;
|
||||
}
|
||||
|
||||
MEM_STATIC void LIZFSE_updateState(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
LIZFSE_decode_t const DInfo = ((const LIZFSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
}
|
||||
|
||||
MEM_STATIC BYTE LIZFSE_decodeSymbol(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
LIZFSE_decode_t const DInfo = ((const LIZFSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
BYTE const symbol = DInfo.symbol;
|
||||
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/*! LIZFSE_decodeSymbolFast() :
|
||||
unsafe, only works if no symbol has a probability > 50% */
|
||||
MEM_STATIC BYTE LIZFSE_decodeSymbolFast(LIZFSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
LIZFSE_decode_t const DInfo = ((const LIZFSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
BYTE const symbol = DInfo.symbol;
|
||||
size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
|
||||
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
MEM_STATIC unsigned LIZFSE_endOfDState(const LIZFSE_DState_t* DStatePtr)
|
||||
{
|
||||
return DStatePtr->state == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef LIZFSE_COMMONDEFS_ONLY
|
||||
|
||||
/* **************************************************************
|
||||
* Tuning parameters
|
||||
****************************************************************/
|
||||
/*!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
|
||||
* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
|
||||
#define LIZFSE_MAX_MEMORY_USAGE 14
|
||||
#define LIZFSE_DEFAULT_MEMORY_USAGE 13
|
||||
|
||||
/*!LIZFSE_MAX_SYMBOL_VALUE :
|
||||
* Maximum symbol value authorized.
|
||||
* Required for proper stack allocation */
|
||||
#define LIZFSE_MAX_SYMBOL_VALUE 255
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* template functions type & suffix
|
||||
****************************************************************/
|
||||
#define LIZFSE_FUNCTION_TYPE BYTE
|
||||
#define LIZFSE_FUNCTION_EXTENSION
|
||||
#define LIZFSE_DECODE_TYPE LIZFSE_decode_t
|
||||
|
||||
|
||||
#endif /* !LIZFSE_COMMONDEFS_ONLY */
|
||||
|
||||
|
||||
/* ***************************************************************
|
||||
* Constants
|
||||
*****************************************************************/
|
||||
#define LIZFSE_MAX_TABLELOG (LIZFSE_MAX_MEMORY_USAGE-2)
|
||||
#define LIZFSE_MAX_TABLESIZE (1U<<LIZFSE_MAX_TABLELOG)
|
||||
#define LIZFSE_MAXTABLESIZE_MASK (LIZFSE_MAX_TABLESIZE-1)
|
||||
#define LIZFSE_DEFAULT_TABLELOG (LIZFSE_DEFAULT_MEMORY_USAGE-2)
|
||||
#define LIZFSE_MIN_TABLELOG 5
|
||||
|
||||
#define LIZFSE_TABLELOG_ABSOLUTE_MAX 15
|
||||
#if LIZFSE_MAX_TABLELOG > LIZFSE_TABLELOG_ABSOLUTE_MAX
|
||||
# error "LIZFSE_MAX_TABLELOG > LIZFSE_TABLELOG_ABSOLUTE_MAX is not supported"
|
||||
#endif
|
||||
|
||||
#define LIZFSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)
|
||||
|
||||
|
||||
#endif /* LIZFSE_STATIC_LINKING_ONLY */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZFSE_H */
|
||||
228
C/lizard/huf.h
228
C/lizard/huf.h
@@ -1,228 +0,0 @@
|
||||
/* ******************************************************************
|
||||
Huffman coder, part of New Generation Entropy library
|
||||
header file
|
||||
Copyright (C) 2013-2016, 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 :
|
||||
- Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
****************************************************************** */
|
||||
#ifndef LIZHUF_H_298734234
|
||||
#define LIZHUF_H_298734234
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/* *** simple functions *** */
|
||||
/**
|
||||
LIZHUF_compress() :
|
||||
Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
|
||||
'dst' buffer must be already allocated.
|
||||
Compression runs faster if `dstCapacity` >= LIZHUF_compressBound(srcSize).
|
||||
`srcSize` must be <= `LIZHUF_BLOCKSIZE_MAX` == 128 KB.
|
||||
@return : size of compressed data (<= `dstCapacity`).
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||
if return == 1, srcData is a single repeated byte symbol (RLE compression).
|
||||
if LIZHUF_isError(return), compression failed (more details using LIZHUF_getErrorName())
|
||||
*/
|
||||
size_t LIZHUF_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/**
|
||||
LIZHUF_decompress() :
|
||||
Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
|
||||
into already allocated buffer 'dst', of minimum size 'dstSize'.
|
||||
`dstSize` : **must** be the ***exact*** size of original (uncompressed) data.
|
||||
Note : in contrast with FSE, LIZHUF_decompress can regenerate
|
||||
RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
|
||||
because it knows size to regenerate.
|
||||
@return : size of regenerated data (== dstSize),
|
||||
or an error code, which can be tested using LIZHUF_isError()
|
||||
*/
|
||||
size_t LIZHUF_decompress(void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Tool functions
|
||||
******************************************/
|
||||
#define LIZHUF_BLOCKSIZE_MAX (128 * 1024)
|
||||
size_t LIZHUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||
|
||||
/* Error Management */
|
||||
unsigned LIZHUF_isError(size_t code); /**< tells if a return value is an error code */
|
||||
const char* LIZHUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
/* *** Advanced function *** */
|
||||
|
||||
/** LIZHUF_compress2() :
|
||||
* Same as LIZHUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog` */
|
||||
size_t LIZHUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
|
||||
#ifdef LIZHUF_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include "mem.h" /* U32 */
|
||||
|
||||
|
||||
/* *** Constants *** */
|
||||
#define LIZHUF_TABLELOG_ABSOLUTEMAX 16 /* absolute limit of LIZHUF_MAX_TABLELOG. Beyond that value, code does not work */
|
||||
#define LIZHUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to LIZHUF_ABSOLUTEMAX_TABLELOG */
|
||||
#define LIZHUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
|
||||
#define LIZHUF_SYMBOLVALUE_MAX 255
|
||||
#if (LIZHUF_TABLELOG_MAX > LIZHUF_TABLELOG_ABSOLUTEMAX)
|
||||
# error "LIZHUF_TABLELOG_MAX is too large !"
|
||||
#endif
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Static allocation
|
||||
******************************************/
|
||||
/* HUF buffer bounds */
|
||||
#define LIZHUF_CTABLEBOUND 129
|
||||
#define LIZHUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */
|
||||
#define LIZHUF_COMPRESSBOUND(size) (LIZHUF_CTABLEBOUND + LIZHUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
|
||||
|
||||
/* static allocation of HUF's Compression Table */
|
||||
#define LIZHUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
|
||||
U32 name##hb[maxSymbolValue+1]; \
|
||||
void* name##hv = &(name##hb); \
|
||||
LIZHUF_CElt* name = (LIZHUF_CElt*)(name##hv) /* no final ; */
|
||||
|
||||
/* static allocation of HUF's DTable */
|
||||
typedef U32 LIZHUF_DTable;
|
||||
#define LIZHUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))
|
||||
#define LIZHUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
|
||||
LIZHUF_DTable DTable[LIZHUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }
|
||||
#define LIZHUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
|
||||
LIZHUF_DTable DTable[LIZHUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Advanced decompression functions
|
||||
******************************************/
|
||||
size_t LIZHUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
size_t LIZHUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
|
||||
size_t LIZHUF_decompress4X_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
|
||||
size_t LIZHUF_decompress4X_hufOnly(LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
|
||||
size_t LIZHUF_decompress4X2_DCtx(LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
size_t LIZHUF_decompress4X4_DCtx(LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
|
||||
size_t LIZHUF_decompress1X_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
|
||||
size_t LIZHUF_decompress1X2_DCtx(LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
size_t LIZHUF_decompress1X4_DCtx(LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* HUF detailed API
|
||||
******************************************/
|
||||
/*!
|
||||
LIZHUF_compress() does the following:
|
||||
1. count symbol occurrence from source[] into table count[] using LIZFSE_count()
|
||||
2. (optional) refine tableLog using LIZHUF_optimalTableLog()
|
||||
3. build Huffman table from count using LIZHUF_buildCTable()
|
||||
4. save Huffman table to memory buffer using LIZHUF_writeCTable()
|
||||
5. encode the data stream using LIZHUF_compress4X_usingCTable()
|
||||
|
||||
The following API allows targeting specific sub-functions for advanced tasks.
|
||||
For example, it's possible to compress several blocks using the same 'CTable',
|
||||
or to save and regenerate 'CTable' using external methods.
|
||||
*/
|
||||
/* LIZFSE_count() : find it within "fse.h" */
|
||||
unsigned LIZHUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
|
||||
typedef struct LIZHUF_CElt_s LIZHUF_CElt; /* incomplete type */
|
||||
size_t LIZHUF_buildCTable (LIZHUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);
|
||||
size_t LIZHUF_writeCTable (void* dst, size_t maxDstSize, const LIZHUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
|
||||
size_t LIZHUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const LIZHUF_CElt* CTable);
|
||||
|
||||
|
||||
/*! LIZHUF_readStats() :
|
||||
Read compact Huffman tree, saved by LIZHUF_writeCTable().
|
||||
`huffWeight` is destination buffer.
|
||||
@return : size read from `src` , or an error Code .
|
||||
Note : Needed by LIZHUF_readCTable() and LIZHUF_readDTableXn() . */
|
||||
size_t LIZHUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/** LIZHUF_readCTable() :
|
||||
* Loading a CTable saved with LIZHUF_writeCTable() */
|
||||
size_t LIZHUF_readCTable (LIZHUF_CElt* CTable, unsigned maxSymbolValue, const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/*
|
||||
LIZHUF_decompress() does the following:
|
||||
1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
|
||||
2. build Huffman table from save, using LIZHUF_readDTableXn()
|
||||
3. decode 1 or 4 segments in parallel using LIZHUF_decompressSXn_usingDTable
|
||||
*/
|
||||
|
||||
/** LIZHUF_selectDecoder() :
|
||||
* Tells which decoder is likely to decode faster,
|
||||
* based on a set of pre-determined metrics.
|
||||
* @return : 0==LIZHUF_decompress4X2, 1==LIZHUF_decompress4X4 .
|
||||
* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
|
||||
U32 LIZHUF_selectDecoder (size_t dstSize, size_t cSrcSize);
|
||||
|
||||
size_t LIZHUF_readDTableX2 (LIZHUF_DTable* DTable, const void* src, size_t srcSize);
|
||||
size_t LIZHUF_readDTableX4 (LIZHUF_DTable* DTable, const void* src, size_t srcSize);
|
||||
|
||||
size_t LIZHUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
size_t LIZHUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
size_t LIZHUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
|
||||
|
||||
/* single stream variants */
|
||||
|
||||
size_t LIZHUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
size_t LIZHUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const LIZHUF_CElt* CTable);
|
||||
|
||||
size_t LIZHUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
|
||||
size_t LIZHUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
|
||||
|
||||
size_t LIZHUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
size_t LIZHUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
size_t LIZHUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const LIZHUF_DTable* DTable);
|
||||
|
||||
|
||||
#endif /* LIZHUF_STATIC_LINKING_ONLY */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZHUF_H_298734234 */
|
||||
@@ -1,497 +0,0 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
Copyright (C) 2015-2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef LIZ_COMMON_H_2983
|
||||
#define LIZ_COMMON_H_2983
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Memory routines
|
||||
**************************************/
|
||||
#include <stdlib.h> /* malloc, calloc, free */
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#include <stdint.h> /* intptr_t */
|
||||
#include "mem.h"
|
||||
#include "liz_compress.h" /* LIZ_GCC_VERSION */
|
||||
|
||||
//#define LIZ_USE_LOGS
|
||||
#define LIZ_LOG_COMPRESS(...) //printf(__VA_ARGS__)
|
||||
#define LIZ_LOG_DECOMPRESS(...) //printf(__VA_ARGS__)
|
||||
|
||||
#define LIZ_LOG_COMPRESS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define COMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define LIZ_LOG_DECOMPRESS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define DECOMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)
|
||||
|
||||
#define LIZ_LOG_COMPRESS_LZ5v2(...) //printf(__VA_ARGS__)
|
||||
#define COMPLOG_CODEWORDS_LZ5v2(...) //printf(__VA_ARGS__)
|
||||
#define LIZ_LOG_DECOMPRESS_LZ5v2(...) //printf(__VA_ARGS__)
|
||||
#define DECOMPLOG_CODEWORDS_LZ5v2(...) //printf(__VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common Constants
|
||||
**************************************/
|
||||
#define MINMATCH 4
|
||||
//#define USE_LZ4_ONLY
|
||||
//#define LIZ_USE_TEST
|
||||
|
||||
#define LIZ_DICT_SIZE (1<<24)
|
||||
#define WILDCOPYLENGTH 16
|
||||
#define LASTLITERALS WILDCOPYLENGTH
|
||||
#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
|
||||
|
||||
#define LIZ_MAX_PRICE (1<<28)
|
||||
#define LIZ_INIT_LAST_OFFSET 0
|
||||
#define LIZ_MAX_16BIT_OFFSET (1<<16)
|
||||
#define MM_LONGOFF 16
|
||||
#define LIZ_BLOCK_SIZE_PAD (LIZ_BLOCK_SIZE+32)
|
||||
#define LIZ_COMPRESS_ADD_BUF (5*LIZ_BLOCK_SIZE_PAD)
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#define LIZ_COMPRESS_ADD_HUF LIZHUF_compressBound(LIZ_BLOCK_SIZE_PAD)
|
||||
#define LIZ_LIZHUF_BLOCK_SIZE LIZ_BLOCK_SIZE
|
||||
#else
|
||||
#define LIZ_COMPRESS_ADD_HUF 0
|
||||
#define LIZ_LIZHUF_BLOCK_SIZE 1
|
||||
#endif
|
||||
|
||||
/* LZ4 codewords */
|
||||
#define ML_BITS_LZ4 4
|
||||
#define ML_MASK_LZ4 ((1U<<ML_BITS_LZ4)-1)
|
||||
#define RUN_BITS_LZ4 (8-ML_BITS_LZ4)
|
||||
#define RUN_MASK_LZ4 ((1U<<RUN_BITS_LZ4)-1)
|
||||
|
||||
/* LZ5v2 codewords */
|
||||
#define ML_BITS_LZ5v2 4
|
||||
#define RUN_BITS_LZ5v2 3
|
||||
#define ML_RUN_BITS (ML_BITS_LZ5v2 + RUN_BITS_LZ5v2)
|
||||
#define MAX_SHORT_LITLEN 7
|
||||
#define MAX_SHORT_MATCHLEN 15
|
||||
#define LIZ_LAST_LONG_OFF 31
|
||||
|
||||
/* header byte */
|
||||
#define LIZ_FLAG_LITERALS 1
|
||||
#define LIZ_FLAG_FLAGS 2
|
||||
#define LIZ_FLAG_OFFSET16 4
|
||||
#define LIZ_FLAG_OFFSET24 8
|
||||
#define LIZ_FLAG_LEN 16
|
||||
#define LIZ_FLAG_UNCOMPRESSED 128
|
||||
|
||||
/* stream numbers */
|
||||
#define LIZ_STREAM_LITERALS 0
|
||||
#define LIZ_STREAM_FLAGS 1
|
||||
#define LIZ_STREAM_OFFSET16 2
|
||||
#define LIZ_STREAM_OFFSET24 3
|
||||
#define LIZ_STREAM_LEN 4
|
||||
#define LIZ_STREAM_UNCOMPRESSED 5
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum { LIZ_parser_fastSmall, LIZ_parser_fast, LIZ_parser_fastBig, LIZ_parser_noChain, LIZ_parser_hashChain, LIZ_parser_priceFast, LIZ_parser_lowestPrice, LIZ_parser_optimalPrice, LIZ_parser_optimalPriceBT } LIZ_parser_type; /* from faster to stronger */
|
||||
typedef enum { LIZ_coderwords_LZ4, LIZ_coderwords_LZ5v2 } LIZ_decompress_type;
|
||||
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 minMatchLongOff; /* min match size with offsets >= 1<<16 */
|
||||
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 */
|
||||
LIZ_parser_type parserType;
|
||||
LIZ_decompress_type decompressType;
|
||||
} LIZ_parameters;
|
||||
|
||||
|
||||
struct LIZ_stream_s
|
||||
{
|
||||
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 */
|
||||
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 allocatedMemory;
|
||||
int compressionLevel;
|
||||
LIZ_parameters params;
|
||||
U32 hashTableSize;
|
||||
U32 chainTableSize;
|
||||
U32* chainTable;
|
||||
U32* hashTable;
|
||||
int last_off;
|
||||
const BYTE* off24pos;
|
||||
U32 huffType;
|
||||
U32 comprStreamLen;
|
||||
|
||||
BYTE* huffBase;
|
||||
BYTE* huffEnd;
|
||||
BYTE* offset16Base;
|
||||
BYTE* offset24Base;
|
||||
BYTE* lenBase;
|
||||
BYTE* literalsBase;
|
||||
BYTE* flagsBase;
|
||||
BYTE* offset16Ptr;
|
||||
BYTE* offset24Ptr;
|
||||
BYTE* lenPtr;
|
||||
BYTE* literalsPtr;
|
||||
BYTE* flagsPtr;
|
||||
BYTE* offset16End;
|
||||
BYTE* offset24End;
|
||||
BYTE* lenEnd;
|
||||
BYTE* literalsEnd;
|
||||
BYTE* flagsEnd;
|
||||
U32 flagFreq[256];
|
||||
U32 litFreq[256];
|
||||
U32 litSum, flagSum;
|
||||
U32 litPriceSum, log2LitSum, log2FlagSum;
|
||||
U32 cachedPrice;
|
||||
U32 cachedLitLength;
|
||||
const BYTE* cachedLiterals;
|
||||
const BYTE* diffBase;
|
||||
const BYTE* srcBase;
|
||||
const BYTE* destBase;
|
||||
};
|
||||
|
||||
struct LIZ_dstream_s
|
||||
{
|
||||
const BYTE* offset16Ptr;
|
||||
const BYTE* offset24Ptr;
|
||||
const BYTE* lenPtr;
|
||||
const BYTE* literalsPtr;
|
||||
const BYTE* flagsPtr;
|
||||
const BYTE* offset16End;
|
||||
const BYTE* offset24End;
|
||||
const BYTE* lenEnd;
|
||||
const BYTE* literalsEnd;
|
||||
const BYTE* flagsEnd;
|
||||
const BYTE* diffBase;
|
||||
intptr_t last_off;
|
||||
};
|
||||
|
||||
typedef struct LIZ_dstream_s LIZ_dstream_t;
|
||||
|
||||
/* *************************************
|
||||
* HC Pre-defined compression levels
|
||||
***************************************/
|
||||
#define LIZ_WINDOWLOG_LZ4 16
|
||||
#define LIZ_CHAINLOG_LZ4 LIZ_WINDOWLOG_LZ4
|
||||
#define LIZ_HASHLOG_LZ4 18
|
||||
#define LIZ_HASHLOG_LZ4SM 12
|
||||
|
||||
#define LIZ_WINDOWLOG_LZ5v2 22
|
||||
#define LIZ_CHAINLOG_LZ5v2 LIZ_WINDOWLOG_LZ5v2
|
||||
#define LIZ_HASHLOG_LZ5v2 18
|
||||
|
||||
|
||||
|
||||
static const LIZ_parameters LIZ_defaultParameters[LIZ_MAX_CLEVEL+1-LIZ_MIN_CLEVEL] =
|
||||
{
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4SM, 0, 0, 0, 0, 0, 0, LIZ_parser_fastSmall, LIZ_coderwords_LZ4 }, // level 10
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, LIZ_parser_fast, LIZ_coderwords_LZ4 }, // level 11
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, LIZ_parser_noChain, LIZ_coderwords_LZ4 }, // level 12
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 2, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 13
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 4, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 14
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 8, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 15
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 16, 4, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 16
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 256, 4, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 17
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_WINDOWLOG_LZ4+1, LIZ_HASHLOG_LZ4, 16, 16, 4, 0, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ4 }, // level 18
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_WINDOWLOG_LZ4+1, 23, 16, 256, 4, 0, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ4 }, // level 19
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZ_WINDOWLOG_LZ5v2, 0, 14, 0, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_fastBig, LIZ_coderwords_LZ5v2 }, // level 20
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 14, 13, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_priceFast, LIZ_coderwords_LZ5v2 }, // level 21
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, LIZ_HASHLOG_LZ5v2, 13, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_priceFast, LIZ_coderwords_LZ5v2 }, // level 22
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, LIZ_HASHLOG_LZ5v2, 13, 1, 5, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 23
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 23, 16, 2, 5, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 24
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 23, 16, 8, 4, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 25
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2+1, 23, 16, 8, 4, MM_LONGOFF, 64, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 26
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2+1, 23, 16, 128, 4, MM_LONGOFF, 64, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 27
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2+1, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 28
|
||||
{ 24, 25, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 29
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4SM, 0, 0, 0, 0, 0, 0, LIZ_parser_fastSmall, LIZ_coderwords_LZ4 }, // level 30
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, LIZ_parser_fast, LIZ_coderwords_LZ4 }, // level 31
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, 14, 0, 0, 0, 0, 0, 0, LIZ_parser_noChain, LIZ_coderwords_LZ4 }, // level 32
|
||||
{ LIZ_WINDOWLOG_LZ4, 0, LIZ_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, LIZ_parser_noChain, LIZ_coderwords_LZ4 }, // level 33
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 2, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 34
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 4, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 35
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 8, 5, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 36
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 16, 4, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 37
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_CHAINLOG_LZ4, LIZ_HASHLOG_LZ4, 0, 256, 4, 0, 0, 0, LIZ_parser_hashChain, LIZ_coderwords_LZ4 }, // level 38
|
||||
{ LIZ_WINDOWLOG_LZ4, LIZ_WINDOWLOG_LZ4+1, 23, 16, 256, 4, 0, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ4 }, // level 39
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZ_WINDOWLOG_LZ5v2, 0, 14, 0, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_fastBig, LIZ_coderwords_LZ5v2 }, // level 40
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 14, 13, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_priceFast, LIZ_coderwords_LZ5v2 }, // level 41
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, LIZ_HASHLOG_LZ5v2, 13, 1, 5, MM_LONGOFF, 0, 0, LIZ_parser_priceFast, LIZ_coderwords_LZ5v2 }, // level 42
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, LIZ_HASHLOG_LZ5v2, 13, 1, 5, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 43
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 23, 16, 2, 5, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 44
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 23, 16, 8, 4, MM_LONGOFF, 64, 0, LIZ_parser_lowestPrice, LIZ_coderwords_LZ5v2 }, // level 45
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2, 23, 16, 8, 4, MM_LONGOFF, 64, 0, LIZ_parser_optimalPrice, LIZ_coderwords_LZ5v2 }, // level 46
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2+1, 23, 16, 8, 4, MM_LONGOFF, 64, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 47
|
||||
{ LIZ_WINDOWLOG_LZ5v2, LIZ_CHAINLOG_LZ5v2+1, 23, 16, 128, 4, MM_LONGOFF, 64, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 48
|
||||
{ 24, 25, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, LIZ_parser_optimalPriceBT, LIZ_coderwords_LZ5v2 }, // level 49
|
||||
#endif
|
||||
// { 10, 10, 10, 0, 0, 4, 0, 0, 0, LIZ_fast }, // min values
|
||||
// { 24, 24, 28, 24, 1<<24, 7, 0, 1<<24, 2, LIZ_optimal_price }, // max values
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* 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 LIZ_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#if (LIZ_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)
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define ALLOCATOR(n,s) calloc(n,s)
|
||||
#define FREEMEM free
|
||||
#define MEM_INIT memset
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b))?(a):(b)
|
||||
#endif
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#if MINMATCH == 3
|
||||
#define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr)<<8)
|
||||
#else
|
||||
#define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Reading and writing into memory
|
||||
**************************************/
|
||||
#define STEPSIZE sizeof(size_t)
|
||||
|
||||
|
||||
MEM_STATIC void LIZ_copy8(void* dst, const void* src)
|
||||
{
|
||||
memcpy(dst,src,8);
|
||||
}
|
||||
|
||||
/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
|
||||
MEM_STATIC void LIZ_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
|
||||
{
|
||||
BYTE* d = (BYTE*)dstPtr;
|
||||
const BYTE* s = (const BYTE*)srcPtr;
|
||||
BYTE* const e = (BYTE*)dstEnd;
|
||||
|
||||
#if 0
|
||||
const size_t l2 = 8 - (((size_t)d) & (sizeof(void*)-1));
|
||||
LIZ_copy8(d,s); if (d>e-9) return;
|
||||
d+=l2; s+=l2;
|
||||
#endif /* join to align */
|
||||
|
||||
do { LIZ_copy8(d,s); d+=8; s+=8; } while (d<e);
|
||||
}
|
||||
|
||||
MEM_STATIC void LIZ_wildCopy16(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd)
|
||||
{
|
||||
do {
|
||||
LIZ_copy8(dstPtr, srcPtr);
|
||||
LIZ_copy8(dstPtr+8, srcPtr+8);
|
||||
dstPtr += 16;
|
||||
srcPtr += 16;
|
||||
}
|
||||
while (dstPtr < dstEnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* LIZ_FORCE_SW_BITCOUNT
|
||||
* Define this parameter if your target system or compiler does not support hardware bit count
|
||||
*/
|
||||
#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
|
||||
# define LIZ_FORCE_SW_BITCOUNT
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************
|
||||
* Function body to include for inlining
|
||||
****************************************/
|
||||
MEM_STATIC U32 LIZ_highbit32(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
|
||||
}
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common functions
|
||||
**************************************/
|
||||
MEM_STATIC unsigned LIZ_NbCommonBytes (register size_t val)
|
||||
{
|
||||
if (MEM_isLittleEndian()) {
|
||||
if (MEM_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward64( &r, (U64)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZ_GCC_VERSION >= 304)) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
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) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
unsigned long r;
|
||||
_BitScanForward( &r, (U32)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZ_GCC_VERSION >= 304)) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
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_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZ_GCC_VERSION >= 304)) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
return (__builtin_clzll((U64)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
|
||||
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
} else /* 32 bits */ {
|
||||
# if defined(_MSC_VER) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZ_GCC_VERSION >= 304)) && !defined(LIZ_FORCE_SW_BITCOUNT)
|
||||
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 unsigned LIZ_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
|
||||
{
|
||||
const BYTE* const pStart = pIn;
|
||||
|
||||
while (likely(pIn<pInLimit-(STEPSIZE-1))) {
|
||||
size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
|
||||
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
|
||||
pIn += LIZ_NbCommonBytes(diff);
|
||||
return (unsigned)(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 (unsigned)(pIn - pStart);
|
||||
}
|
||||
|
||||
/* alias to functions with compressionLevel=1 */
|
||||
int LIZ_sizeofState_MinLevel(void);
|
||||
int LIZ_compress_MinLevel(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
int LIZ_compress_extState_MinLevel (void* state, const char* source, char* dest, int inputSize, int maxDestSize);
|
||||
LIZ_stream_t* LIZ_resetStream_MinLevel (LIZ_stream_t* streamPtr);
|
||||
LIZ_stream_t* LIZ_createStream_MinLevel(void);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZ_COMMON_H_2983827168210 */
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
Copyright (C) 2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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
|
||||
*/
|
||||
#ifndef LIZ_H_2983
|
||||
#define LIZ_H_2983
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lz5_compress.h provides block compression functions. It gives full buffer control to user.
|
||||
* Block compression functions are not-enough to send information,
|
||||
* since it's still necessary to provide metadata (such as compressed size),
|
||||
* and each application can do it in whichever way it wants.
|
||||
* For interoperability, there is LZ5 frame specification (lz5_Frame_format.md).
|
||||
* A library is provided to take care of it, see lz5frame.h.
|
||||
*/
|
||||
|
||||
|
||||
/*^***************************************************************
|
||||
* Export parameters
|
||||
*****************************************************************/
|
||||
/*
|
||||
* LIZ_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
*/
|
||||
#if defined(LIZ_DLL_EXPORT) && (LIZ_DLL_EXPORT==1)
|
||||
# define LZ5LIB_API __declspec(dllexport)
|
||||
#elif defined(LIZ_DLL_IMPORT) && (LIZ_DLL_IMPORT==1)
|
||||
# define LZ5LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define LZ5LIB_API
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Version
|
||||
**************************************/
|
||||
#define LIZ_VERSION_MAJOR 2 /* for breaking interface changes */
|
||||
#define LIZ_VERSION_MINOR 0 /* for new (non-breaking) interface capabilities */
|
||||
#define LIZ_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
|
||||
|
||||
#define LIZ_VERSION_NUMBER (LIZ_VERSION_MAJOR *100*100 + LIZ_VERSION_MINOR *100 + LIZ_VERSION_RELEASE)
|
||||
int LIZ_versionNumber (void);
|
||||
|
||||
#define LIZ_LIB_VERSION LIZ_VERSION_MAJOR.LIZ_VERSION_MINOR.LIZ_VERSION_RELEASE
|
||||
#define LIZ_QUOTE(str) #str
|
||||
#define LIZ_EXPAND_AND_QUOTE(str) LIZ_QUOTE(str)
|
||||
#define LIZ_VERSION_STRING LIZ_EXPAND_AND_QUOTE(LIZ_LIB_VERSION)
|
||||
const char* LIZ_versionString (void);
|
||||
|
||||
typedef struct LIZ_stream_s LIZ_stream_t;
|
||||
|
||||
#define LIZ_MIN_CLEVEL 10 /* minimum compression level */
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#define LIZ_MAX_CLEVEL 49 /* maximum compression level */
|
||||
#else
|
||||
#define LIZ_MAX_CLEVEL 29 /* maximum compression level */
|
||||
#endif
|
||||
#define LIZ_DEFAULT_CLEVEL 17
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
|
||||
LZ5LIB_API int LIZ_compress (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
|
||||
/*
|
||||
LIZ_compress() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= LIZ_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 LIZ_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
|
||||
*/
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LIZ_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LIZ_BLOCK_SIZE (1<<17)
|
||||
#define LIZ_BLOCK64K_SIZE (1<<16)
|
||||
#define LIZ_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LIZ_MAX_INPUT_SIZE ? 0 : (isize) + 1 + 1 + ((isize/LIZ_BLOCK_SIZE)+1)*4)
|
||||
|
||||
|
||||
/*!
|
||||
LIZ_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 LIZ_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that LIZ_compress() compress faster when dest buffer size is >= LIZ_compressBound(srcSize)
|
||||
inputSize : max supported value is LIZ_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LIZ_MAX_INPUT_SIZE)
|
||||
*/
|
||||
LZ5LIB_API int LIZ_compressBound(int inputSize);
|
||||
|
||||
|
||||
/*!
|
||||
LIZ_compress_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LIZ_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.
|
||||
*/
|
||||
LZ5LIB_API int LIZ_sizeofState(int compressionLevel);
|
||||
|
||||
LZ5LIB_API int LIZ_compress_extState(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
|
||||
|
||||
|
||||
/*-*********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
|
||||
/*! LIZ_createStream() will allocate and initialize an `LIZ_stream_t` structure.
|
||||
* LIZ_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 `LIZ_stream_t` size.
|
||||
*/
|
||||
LZ5LIB_API LIZ_stream_t* LIZ_createStream(int compressionLevel);
|
||||
LZ5LIB_API int LIZ_freeStream (LIZ_stream_t* streamPtr);
|
||||
|
||||
|
||||
/*! LIZ_resetStream() :
|
||||
* Use this function to reset/reuse an allocated `LIZ_stream_t` structure
|
||||
*/
|
||||
LZ5LIB_API LIZ_stream_t* LIZ_resetStream (LIZ_stream_t* streamPtr, int compressionLevel);
|
||||
|
||||
|
||||
/*! LIZ_loadDict() :
|
||||
* Use this function to load a static dictionary into LIZ_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 <= LIZ_DICT_SIZE)
|
||||
*/
|
||||
LZ5LIB_API int LIZ_loadDict (LIZ_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
|
||||
/*! LIZ_compress_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 >= LIZ_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.
|
||||
*/
|
||||
LZ5LIB_API int LIZ_compress_continue (LIZ_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
|
||||
|
||||
/*! LIZ_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 LIZ_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call LIZ_compress_continue().
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
|
||||
*/
|
||||
LZ5LIB_API int LIZ_saveDict (LIZ_stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZ_H_2983827168210 */
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
Common functions of New Generation Entropy library
|
||||
Copyright (C) 2016, 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+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*************************************************************************** */
|
||||
|
||||
/* *************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#include "mem.h"
|
||||
#include "error_private.h" /* ERR_*, ERROR */
|
||||
#define LIZFSE_STATIC_LINKING_ONLY /* LIZFSE_MIN_TABLELOG */
|
||||
#include "fse.h"
|
||||
#define LIZHUF_STATIC_LINKING_ONLY /* LIZHUF_TABLELOG_ABSOLUTEMAX */
|
||||
#include "huf.h"
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* FSE Error Management
|
||||
******************************************/
|
||||
unsigned LIZFSE_isError(size_t code) { return ERR_isError(code); }
|
||||
|
||||
const char* LIZFSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* HUF Error Management
|
||||
****************************************************************/
|
||||
unsigned LIZHUF_isError(size_t code) { return ERR_isError(code); }
|
||||
|
||||
const char* LIZHUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* FSE NCount encoding-decoding
|
||||
****************************************************************/
|
||||
static short LIZFSE_abs(short a) { return (short)(a<0 ? -a : a); }
|
||||
|
||||
size_t LIZFSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
|
||||
const void* headerBuffer, size_t hbSize)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) headerBuffer;
|
||||
const BYTE* const iend = istart + hbSize;
|
||||
const BYTE* ip = istart;
|
||||
int nbBits;
|
||||
int remaining;
|
||||
int threshold;
|
||||
U32 bitStream;
|
||||
int bitCount;
|
||||
unsigned charnum = 0;
|
||||
int previous0 = 0;
|
||||
|
||||
if (hbSize < 4) return ERROR(srcSize_wrong);
|
||||
bitStream = MEM_readLE32(ip);
|
||||
nbBits = (bitStream & 0xF) + LIZFSE_MIN_TABLELOG; /* extract tableLog */
|
||||
if (nbBits > LIZFSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
|
||||
bitStream >>= 4;
|
||||
bitCount = 4;
|
||||
*tableLogPtr = nbBits;
|
||||
remaining = (1<<nbBits)+1;
|
||||
threshold = 1<<nbBits;
|
||||
nbBits++;
|
||||
|
||||
while ((remaining>1) & (charnum<=*maxSVPtr)) {
|
||||
if (previous0) {
|
||||
unsigned n0 = charnum;
|
||||
while ((bitStream & 0xFFFF) == 0xFFFF) {
|
||||
n0 += 24;
|
||||
if (ip < iend-5) {
|
||||
ip += 2;
|
||||
bitStream = MEM_readLE32(ip) >> bitCount;
|
||||
} else {
|
||||
bitStream >>= 16;
|
||||
bitCount += 16;
|
||||
} }
|
||||
while ((bitStream & 3) == 3) {
|
||||
n0 += 3;
|
||||
bitStream >>= 2;
|
||||
bitCount += 2;
|
||||
}
|
||||
n0 += bitStream & 3;
|
||||
bitCount += 2;
|
||||
if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
|
||||
while (charnum < n0) normalizedCounter[charnum++] = 0;
|
||||
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
|
||||
ip += bitCount>>3;
|
||||
bitCount &= 7;
|
||||
bitStream = MEM_readLE32(ip) >> bitCount;
|
||||
} else {
|
||||
bitStream >>= 2;
|
||||
} }
|
||||
{ short const max = (short)((2*threshold-1)-remaining);
|
||||
short count;
|
||||
|
||||
if ((bitStream & (threshold-1)) < (U32)max) {
|
||||
count = (short)(bitStream & (threshold-1));
|
||||
bitCount += nbBits-1;
|
||||
} else {
|
||||
count = (short)(bitStream & (2*threshold-1));
|
||||
if (count >= threshold) count -= max;
|
||||
bitCount += nbBits;
|
||||
}
|
||||
|
||||
count--; /* extra accuracy */
|
||||
remaining -= LIZFSE_abs(count);
|
||||
normalizedCounter[charnum++] = count;
|
||||
previous0 = !count;
|
||||
while (remaining < threshold) {
|
||||
nbBits--;
|
||||
threshold >>= 1;
|
||||
}
|
||||
|
||||
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
|
||||
ip += bitCount>>3;
|
||||
bitCount &= 7;
|
||||
} else {
|
||||
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||
ip = iend - 4;
|
||||
}
|
||||
bitStream = MEM_readLE32(ip) >> (bitCount & 31);
|
||||
} } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
|
||||
if (remaining != 1) return ERROR(corruption_detected);
|
||||
if (bitCount > 32) return ERROR(corruption_detected);
|
||||
*maxSVPtr = charnum-1;
|
||||
|
||||
ip += (bitCount+7)>>3;
|
||||
return ip-istart;
|
||||
}
|
||||
|
||||
|
||||
/*! LIZHUF_readStats() :
|
||||
Read compact Huffman tree, saved by LIZHUF_writeCTable().
|
||||
`huffWeight` is destination buffer.
|
||||
@return : size read from `src` , or an error Code .
|
||||
Note : Needed by LIZHUF_readCTable() and LIZHUF_readDTableX?() .
|
||||
*/
|
||||
size_t LIZHUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 weightTotal;
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
size_t iSize = ip[0];
|
||||
size_t oSize;
|
||||
|
||||
/* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
if (iSize >= 128) { /* special header */
|
||||
oSize = iSize - 127;
|
||||
iSize = ((oSize+1)/2);
|
||||
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||
if (oSize >= hwSize) return ERROR(corruption_detected);
|
||||
ip += 1;
|
||||
{ U32 n;
|
||||
for (n=0; n<oSize; n+=2) {
|
||||
huffWeight[n] = ip[n/2] >> 4;
|
||||
huffWeight[n+1] = ip[n/2] & 15;
|
||||
} } }
|
||||
else { /* header compressed with FSE (normal case) */
|
||||
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||
oSize = LIZFSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */
|
||||
if (LIZFSE_isError(oSize)) return oSize;
|
||||
}
|
||||
|
||||
/* collect weight stats */
|
||||
memset(rankStats, 0, (LIZHUF_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));
|
||||
weightTotal = 0;
|
||||
{ U32 n; for (n=0; n<oSize; n++) {
|
||||
if (huffWeight[n] >= LIZHUF_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
|
||||
rankStats[huffWeight[n]]++;
|
||||
weightTotal += (1 << huffWeight[n]) >> 1;
|
||||
} }
|
||||
|
||||
/* get last non-null symbol weight (implied, total must be 2^n) */
|
||||
{ U32 const tableLog = BIT_highbit32(weightTotal) + 1;
|
||||
if (tableLog > LIZHUF_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);
|
||||
*tableLogPtr = tableLog;
|
||||
/* determine last weight */
|
||||
{ U32 const total = 1 << tableLog;
|
||||
U32 const rest = total - weightTotal;
|
||||
U32 const verif = 1 << BIT_highbit32(rest);
|
||||
U32 const lastWeight = BIT_highbit32(rest) + 1;
|
||||
if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
|
||||
huffWeight[oSize] = (BYTE)lastWeight;
|
||||
rankStats[lastWeight]++;
|
||||
} }
|
||||
|
||||
/* check tree construction validity */
|
||||
if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
|
||||
|
||||
/* results */
|
||||
*nbSymbolsPtr = (U32)(oSize+1);
|
||||
return iSize+1;
|
||||
}
|
||||
@@ -1,810 +0,0 @@
|
||||
/* ******************************************************************
|
||||
FSE : Finite State Entropy encoder
|
||||
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
|
||||
****************************************************************** */
|
||||
|
||||
/* **************************************************************
|
||||
* Compiler specifics
|
||||
****************************************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
||||
#else
|
||||
# if defined (__cplusplus) || 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
|
||||
****************************************************************/
|
||||
#include <stdlib.h> /* malloc, free, qsort */
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include <stdio.h> /* printf (debug) */
|
||||
#include "bitstream.h"
|
||||
#define LIZFSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Error Management
|
||||
****************************************************************/
|
||||
#define LIZFSE_STATIC_ASSERT(c) { enum { LIZFSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Complex types
|
||||
****************************************************************/
|
||||
typedef U32 CTable_max_t[LIZFSE_CTABLE_SIZE_U32(LIZFSE_MAX_TABLELOG, LIZFSE_MAX_SYMBOL_VALUE)];
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Templates
|
||||
****************************************************************/
|
||||
/*
|
||||
designed to be included
|
||||
for type-specific functions (template emulation in C)
|
||||
Objective is to write these functions only once, for improved maintenance
|
||||
*/
|
||||
|
||||
/* safety checks */
|
||||
#ifndef LIZFSE_FUNCTION_EXTENSION
|
||||
# error "LIZFSE_FUNCTION_EXTENSION must be defined"
|
||||
#endif
|
||||
#ifndef LIZFSE_FUNCTION_TYPE
|
||||
# error "LIZFSE_FUNCTION_TYPE must be defined"
|
||||
#endif
|
||||
|
||||
/* Function names */
|
||||
#define LIZFSE_CAT(X,Y) X##Y
|
||||
#define LIZFSE_FUNCTION_NAME(X,Y) LIZFSE_CAT(X,Y)
|
||||
#define LIZFSE_TYPE_NAME(X,Y) LIZFSE_CAT(X,Y)
|
||||
|
||||
|
||||
/* Function templates */
|
||||
size_t LIZFSE_buildCTable(LIZFSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
U32 const tableSize = 1 << tableLog;
|
||||
U32 const tableMask = tableSize - 1;
|
||||
void* const ptr = ct;
|
||||
U16* const tableU16 = ( (U16*) ptr) + 2;
|
||||
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
|
||||
LIZFSE_symbolCompressionTransform* const symbolTT = (LIZFSE_symbolCompressionTransform*) (FSCT);
|
||||
U32 const step = LIZFSE_TABLESTEP(tableSize);
|
||||
U32 cumul[LIZFSE_MAX_SYMBOL_VALUE+2];
|
||||
|
||||
LIZFSE_FUNCTION_TYPE tableSymbol[LIZFSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */
|
||||
U32 highThreshold = tableSize-1;
|
||||
|
||||
/* CTable header */
|
||||
tableU16[-2] = (U16) tableLog;
|
||||
tableU16[-1] = (U16) maxSymbolValue;
|
||||
|
||||
/* For explanations on how to distribute symbol values over the table :
|
||||
* http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
|
||||
|
||||
/* symbol start positions */
|
||||
{ U32 u;
|
||||
cumul[0] = 0;
|
||||
for (u=1; u<=maxSymbolValue+1; u++) {
|
||||
if (normalizedCounter[u-1]==-1) { /* Low proba symbol */
|
||||
cumul[u] = cumul[u-1] + 1;
|
||||
tableSymbol[highThreshold--] = (LIZFSE_FUNCTION_TYPE)(u-1);
|
||||
} else {
|
||||
cumul[u] = cumul[u-1] + normalizedCounter[u-1];
|
||||
} }
|
||||
cumul[maxSymbolValue+1] = tableSize+1;
|
||||
}
|
||||
|
||||
/* Spread symbols */
|
||||
{ U32 position = 0;
|
||||
U32 symbol;
|
||||
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
||||
int nbOccurences;
|
||||
for (nbOccurences=0; nbOccurences<normalizedCounter[symbol]; nbOccurences++) {
|
||||
tableSymbol[position] = (LIZFSE_FUNCTION_TYPE)symbol;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* Low proba area */
|
||||
} }
|
||||
|
||||
if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */
|
||||
}
|
||||
|
||||
/* Build table */
|
||||
{ U32 u; for (u=0; u<tableSize; u++) {
|
||||
LIZFSE_FUNCTION_TYPE s = tableSymbol[u]; /* note : static analyzer may not understand tableSymbol is properly initialized */
|
||||
tableU16[cumul[s]++] = (U16) (tableSize+u); /* TableU16 : sorted by symbol order; gives next state value */
|
||||
} }
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
{ unsigned total = 0;
|
||||
unsigned s;
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
switch (normalizedCounter[s])
|
||||
{
|
||||
case 0: break;
|
||||
|
||||
case -1:
|
||||
case 1:
|
||||
symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);
|
||||
symbolTT[s].deltaFindState = total - 1;
|
||||
total ++;
|
||||
break;
|
||||
default :
|
||||
{
|
||||
U32 const maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
|
||||
U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;
|
||||
symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
|
||||
symbolTT[s].deltaFindState = total - normalizedCounter[s];
|
||||
total += normalizedCounter[s];
|
||||
} } } }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef LIZFSE_COMMONDEFS_ONLY
|
||||
|
||||
/*-**************************************************************
|
||||
* FSE NCount encoding-decoding
|
||||
****************************************************************/
|
||||
size_t LIZFSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
size_t maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3;
|
||||
return maxSymbolValue ? maxHeaderSize : LIZFSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
|
||||
}
|
||||
|
||||
static short LIZFSE_abs(short a) { return (short)(a<0 ? -a : a); }
|
||||
|
||||
static size_t LIZFSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
|
||||
unsigned writeIsSafe)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*) header;
|
||||
BYTE* out = ostart;
|
||||
BYTE* const oend = ostart + headerBufferSize;
|
||||
int nbBits;
|
||||
const int tableSize = 1 << tableLog;
|
||||
int remaining;
|
||||
int threshold;
|
||||
U32 bitStream;
|
||||
int bitCount;
|
||||
unsigned charnum = 0;
|
||||
int previous0 = 0;
|
||||
|
||||
bitStream = 0;
|
||||
bitCount = 0;
|
||||
/* Table Size */
|
||||
bitStream += (tableLog-LIZFSE_MIN_TABLELOG) << bitCount;
|
||||
bitCount += 4;
|
||||
|
||||
/* Init */
|
||||
remaining = tableSize+1; /* +1 for extra accuracy */
|
||||
threshold = tableSize;
|
||||
nbBits = tableLog+1;
|
||||
|
||||
while (remaining>1) { /* stops at 1 */
|
||||
if (previous0) {
|
||||
unsigned start = charnum;
|
||||
while (!normalizedCounter[charnum]) charnum++;
|
||||
while (charnum >= start+24) {
|
||||
start+=24;
|
||||
bitStream += 0xFFFFU << bitCount;
|
||||
if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
|
||||
out[0] = (BYTE) bitStream;
|
||||
out[1] = (BYTE)(bitStream>>8);
|
||||
out+=2;
|
||||
bitStream>>=16;
|
||||
}
|
||||
while (charnum >= start+3) {
|
||||
start+=3;
|
||||
bitStream += 3 << bitCount;
|
||||
bitCount += 2;
|
||||
}
|
||||
bitStream += (charnum-start) << bitCount;
|
||||
bitCount += 2;
|
||||
if (bitCount>16) {
|
||||
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
|
||||
out[0] = (BYTE)bitStream;
|
||||
out[1] = (BYTE)(bitStream>>8);
|
||||
out += 2;
|
||||
bitStream >>= 16;
|
||||
bitCount -= 16;
|
||||
} }
|
||||
{ short count = normalizedCounter[charnum++];
|
||||
const short max = (short)((2*threshold-1)-remaining);
|
||||
remaining -= LIZFSE_abs(count);
|
||||
if (remaining<1) return ERROR(GENERIC);
|
||||
count++; /* +1 for extra accuracy */
|
||||
if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
|
||||
bitStream += count << bitCount;
|
||||
bitCount += nbBits;
|
||||
bitCount -= (count<max);
|
||||
previous0 = (count==1);
|
||||
while (remaining<threshold) nbBits--, threshold>>=1;
|
||||
}
|
||||
if (bitCount>16) {
|
||||
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
|
||||
out[0] = (BYTE)bitStream;
|
||||
out[1] = (BYTE)(bitStream>>8);
|
||||
out += 2;
|
||||
bitStream >>= 16;
|
||||
bitCount -= 16;
|
||||
} }
|
||||
|
||||
/* flush remaining bitStream */
|
||||
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
|
||||
out[0] = (BYTE)bitStream;
|
||||
out[1] = (BYTE)(bitStream>>8);
|
||||
out+= (bitCount+7) /8;
|
||||
|
||||
if (charnum > maxSymbolValue + 1) return ERROR(GENERIC);
|
||||
|
||||
return (out-ostart);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
if (tableLog > LIZFSE_MAX_TABLELOG) return ERROR(GENERIC); /* Unsupported */
|
||||
if (tableLog < LIZFSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */
|
||||
|
||||
if (bufferSize < LIZFSE_NCountWriteBound(maxSymbolValue, tableLog))
|
||||
return LIZFSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);
|
||||
|
||||
return LIZFSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* Counting histogram
|
||||
****************************************************************/
|
||||
/*! LIZFSE_count_simple
|
||||
This function just counts byte values within `src`,
|
||||
and store the histogram into table `count`.
|
||||
This function is unsafe : it doesn't check that all values within `src` can fit into `count`.
|
||||
For this reason, prefer using a table `count` with 256 elements.
|
||||
@return : count of most numerous element
|
||||
*/
|
||||
static size_t LIZFSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
const BYTE* const end = ip + srcSize;
|
||||
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
||||
unsigned max=0;
|
||||
|
||||
|
||||
memset(count, 0, (maxSymbolValue+1)*sizeof(*count));
|
||||
if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
|
||||
|
||||
while (ip<end) count[*ip++]++;
|
||||
|
||||
while (!count[maxSymbolValue]) maxSymbolValue--;
|
||||
*maxSymbolValuePtr = maxSymbolValue;
|
||||
|
||||
{ U32 s; for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s]; }
|
||||
|
||||
return (size_t)max;
|
||||
}
|
||||
|
||||
|
||||
static size_t LIZFSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const void* source, size_t sourceSize,
|
||||
unsigned checkMax)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)source;
|
||||
const BYTE* const iend = ip+sourceSize;
|
||||
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
||||
unsigned max=0;
|
||||
|
||||
|
||||
U32 Counting1[256] = { 0 };
|
||||
U32 Counting2[256] = { 0 };
|
||||
U32 Counting3[256] = { 0 };
|
||||
U32 Counting4[256] = { 0 };
|
||||
|
||||
/* safety checks */
|
||||
if (!sourceSize) {
|
||||
memset(count, 0, maxSymbolValue + 1);
|
||||
*maxSymbolValuePtr = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
|
||||
|
||||
/* by stripes of 16 bytes */
|
||||
{ U32 cached = MEM_read32(ip); ip += 4;
|
||||
while (ip < iend-15) {
|
||||
U32 c = cached; cached = MEM_read32(ip); ip += 4;
|
||||
Counting1[(BYTE) c ]++;
|
||||
Counting2[(BYTE)(c>>8) ]++;
|
||||
Counting3[(BYTE)(c>>16)]++;
|
||||
Counting4[ c>>24 ]++;
|
||||
c = cached; cached = MEM_read32(ip); ip += 4;
|
||||
Counting1[(BYTE) c ]++;
|
||||
Counting2[(BYTE)(c>>8) ]++;
|
||||
Counting3[(BYTE)(c>>16)]++;
|
||||
Counting4[ c>>24 ]++;
|
||||
c = cached; cached = MEM_read32(ip); ip += 4;
|
||||
Counting1[(BYTE) c ]++;
|
||||
Counting2[(BYTE)(c>>8) ]++;
|
||||
Counting3[(BYTE)(c>>16)]++;
|
||||
Counting4[ c>>24 ]++;
|
||||
c = cached; cached = MEM_read32(ip); ip += 4;
|
||||
Counting1[(BYTE) c ]++;
|
||||
Counting2[(BYTE)(c>>8) ]++;
|
||||
Counting3[(BYTE)(c>>16)]++;
|
||||
Counting4[ c>>24 ]++;
|
||||
}
|
||||
ip-=4;
|
||||
}
|
||||
|
||||
/* finish last symbols */
|
||||
while (ip<iend) Counting1[*ip++]++;
|
||||
|
||||
if (checkMax) { /* verify stats will fit into destination table */
|
||||
U32 s; for (s=255; s>maxSymbolValue; s--) {
|
||||
Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
|
||||
if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
|
||||
} }
|
||||
|
||||
{ U32 s; for (s=0; s<=maxSymbolValue; s++) {
|
||||
count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
|
||||
if (count[s] > max) max = count[s];
|
||||
}}
|
||||
|
||||
while (!count[maxSymbolValue]) maxSymbolValue--;
|
||||
*maxSymbolValuePtr = maxSymbolValue;
|
||||
return (size_t)max;
|
||||
}
|
||||
|
||||
/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
|
||||
size_t LIZFSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const void* source, size_t sourceSize)
|
||||
{
|
||||
if (sourceSize < 1500) return LIZFSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
|
||||
return LIZFSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 0);
|
||||
}
|
||||
|
||||
size_t LIZFSE_count(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const void* source, size_t sourceSize)
|
||||
{
|
||||
if (*maxSymbolValuePtr <255)
|
||||
return LIZFSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 1);
|
||||
*maxSymbolValuePtr = 255;
|
||||
return LIZFSE_countFast(count, maxSymbolValuePtr, source, sourceSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* FSE Compression Code
|
||||
****************************************************************/
|
||||
/*! LIZFSE_sizeof_CTable() :
|
||||
LIZFSE_CTable is a variable size structure which contains :
|
||||
`U16 tableLog;`
|
||||
`U16 maxSymbolValue;`
|
||||
`U16 nextStateNumber[1 << tableLog];` // This size is variable
|
||||
`LIZFSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable
|
||||
Allocation is manual (C standard does not support variable-size structures).
|
||||
*/
|
||||
|
||||
size_t LIZFSE_sizeof_CTable (unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
size_t size;
|
||||
LIZFSE_STATIC_ASSERT((size_t)LIZFSE_CTABLE_SIZE_U32(LIZFSE_MAX_TABLELOG, LIZFSE_MAX_SYMBOL_VALUE)*4 >= sizeof(CTable_max_t)); /* A compilation error here means LIZFSE_CTABLE_SIZE_U32 is not large enough */
|
||||
if (tableLog > LIZFSE_MAX_TABLELOG) return ERROR(GENERIC);
|
||||
size = LIZFSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
|
||||
return size;
|
||||
}
|
||||
|
||||
LIZFSE_CTable* LIZFSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
size_t size;
|
||||
if (tableLog > LIZFSE_TABLELOG_ABSOLUTE_MAX) tableLog = LIZFSE_TABLELOG_ABSOLUTE_MAX;
|
||||
size = LIZFSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
|
||||
return (LIZFSE_CTable*)malloc(size);
|
||||
}
|
||||
|
||||
void LIZFSE_freeCTable (LIZFSE_CTable* ct) { free(ct); }
|
||||
|
||||
/* provides the minimum logSize to safely represent a distribution */
|
||||
static unsigned LIZFSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
|
||||
{
|
||||
U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
|
||||
U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
|
||||
U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
|
||||
return minBits;
|
||||
}
|
||||
|
||||
unsigned LIZFSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)
|
||||
{
|
||||
U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
|
||||
U32 tableLog = maxTableLog;
|
||||
U32 minBits = LIZFSE_minTableLog(srcSize, maxSymbolValue);
|
||||
if (tableLog==0) tableLog = LIZFSE_DEFAULT_TABLELOG;
|
||||
if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */
|
||||
if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
|
||||
if (tableLog < LIZFSE_MIN_TABLELOG) tableLog = LIZFSE_MIN_TABLELOG;
|
||||
if (tableLog > LIZFSE_MAX_TABLELOG) tableLog = LIZFSE_MAX_TABLELOG;
|
||||
return tableLog;
|
||||
}
|
||||
|
||||
unsigned LIZFSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
|
||||
{
|
||||
return LIZFSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);
|
||||
}
|
||||
|
||||
|
||||
/* Secondary normalization method.
|
||||
To be used when primary method fails. */
|
||||
|
||||
static size_t LIZFSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue)
|
||||
{
|
||||
U32 s;
|
||||
U32 distributed = 0;
|
||||
U32 ToDistribute;
|
||||
|
||||
/* Init */
|
||||
U32 lowThreshold = (U32)(total >> tableLog);
|
||||
U32 lowOne = (U32)((total * 3) >> (tableLog + 1));
|
||||
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
if (count[s] == 0) {
|
||||
norm[s]=0;
|
||||
continue;
|
||||
}
|
||||
if (count[s] <= lowThreshold) {
|
||||
norm[s] = -1;
|
||||
distributed++;
|
||||
total -= count[s];
|
||||
continue;
|
||||
}
|
||||
if (count[s] <= lowOne) {
|
||||
norm[s] = 1;
|
||||
distributed++;
|
||||
total -= count[s];
|
||||
continue;
|
||||
}
|
||||
norm[s]=-2;
|
||||
}
|
||||
ToDistribute = (1 << tableLog) - distributed;
|
||||
|
||||
if ((total / ToDistribute) > lowOne) {
|
||||
/* risk of rounding to zero */
|
||||
lowOne = (U32)((total * 3) / (ToDistribute * 2));
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
if ((norm[s] == -2) && (count[s] <= lowOne)) {
|
||||
norm[s] = 1;
|
||||
distributed++;
|
||||
total -= count[s];
|
||||
continue;
|
||||
} }
|
||||
ToDistribute = (1 << tableLog) - distributed;
|
||||
}
|
||||
|
||||
if (distributed == maxSymbolValue+1) {
|
||||
/* all values are pretty poor;
|
||||
probably incompressible data (should have already been detected);
|
||||
find max, then give all remaining points to max */
|
||||
U32 maxV = 0, maxC = 0;
|
||||
for (s=0; s<=maxSymbolValue; s++)
|
||||
if (count[s] > maxC) maxV=s, maxC=count[s];
|
||||
norm[maxV] += (short)ToDistribute;
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
U64 const vStepLog = 62 - tableLog;
|
||||
U64 const mid = (1ULL << (vStepLog-1)) - 1;
|
||||
U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */
|
||||
U64 tmpTotal = mid;
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
if (norm[s]==-2) {
|
||||
U64 end = tmpTotal + (count[s] * rStep);
|
||||
U32 sStart = (U32)(tmpTotal >> vStepLog);
|
||||
U32 sEnd = (U32)(end >> vStepLog);
|
||||
U32 weight = sEnd - sStart;
|
||||
if (weight < 1)
|
||||
return ERROR(GENERIC);
|
||||
norm[s] = (short)weight;
|
||||
tmpTotal = end;
|
||||
} } }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
|
||||
const unsigned* count, size_t total,
|
||||
unsigned maxSymbolValue)
|
||||
{
|
||||
/* Sanity checks */
|
||||
if (tableLog==0) tableLog = LIZFSE_DEFAULT_TABLELOG;
|
||||
if (tableLog < LIZFSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */
|
||||
if (tableLog > LIZFSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
|
||||
if (tableLog < LIZFSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
|
||||
|
||||
{ U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
|
||||
|
||||
U64 const scale = 62 - tableLog;
|
||||
U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
|
||||
U64 const vStep = 1ULL<<(scale-20);
|
||||
int stillToDistribute = 1<<tableLog;
|
||||
unsigned s;
|
||||
unsigned largest=0;
|
||||
short largestP=0;
|
||||
U32 lowThreshold = (U32)(total >> tableLog);
|
||||
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
if (count[s] == total) return 0; /* rle special case */
|
||||
if (count[s] == 0) { normalizedCounter[s]=0; continue; }
|
||||
if (count[s] <= lowThreshold) {
|
||||
normalizedCounter[s] = -1;
|
||||
stillToDistribute--;
|
||||
} else {
|
||||
short proba = (short)((count[s]*step) >> scale);
|
||||
if (proba<8) {
|
||||
U64 restToBeat = vStep * rtbTable[proba];
|
||||
proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;
|
||||
}
|
||||
if (proba > largestP) largestP=proba, largest=s;
|
||||
normalizedCounter[s] = proba;
|
||||
stillToDistribute -= proba;
|
||||
} }
|
||||
if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {
|
||||
/* corner case, need another normalization method */
|
||||
size_t errorCode = LIZFSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);
|
||||
if (LIZFSE_isError(errorCode)) return errorCode;
|
||||
}
|
||||
else normalizedCounter[largest] += (short)stillToDistribute;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{ /* Print Table (debug) */
|
||||
U32 s;
|
||||
U32 nTotal = 0;
|
||||
for (s=0; s<=maxSymbolValue; s++)
|
||||
printf("%3i: %4i \n", s, normalizedCounter[s]);
|
||||
for (s=0; s<=maxSymbolValue; s++)
|
||||
nTotal += abs(normalizedCounter[s]);
|
||||
if (nTotal != (1U<<tableLog))
|
||||
printf("Warning !!! Total == %u != %u !!!", nTotal, 1U<<tableLog);
|
||||
getchar();
|
||||
}
|
||||
#endif
|
||||
|
||||
return tableLog;
|
||||
}
|
||||
|
||||
|
||||
/* fake LIZFSE_CTable, for raw (uncompressed) input */
|
||||
size_t LIZFSE_buildCTable_raw (LIZFSE_CTable* ct, unsigned nbBits)
|
||||
{
|
||||
const unsigned tableSize = 1 << nbBits;
|
||||
const unsigned tableMask = tableSize - 1;
|
||||
const unsigned maxSymbolValue = tableMask;
|
||||
void* const ptr = ct;
|
||||
U16* const tableU16 = ( (U16*) ptr) + 2;
|
||||
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableSize>>1); /* assumption : tableLog >= 1 */
|
||||
LIZFSE_symbolCompressionTransform* const symbolTT = (LIZFSE_symbolCompressionTransform*) (FSCT);
|
||||
unsigned s;
|
||||
|
||||
/* Sanity checks */
|
||||
if (nbBits < 1) return ERROR(GENERIC); /* min size */
|
||||
|
||||
/* header */
|
||||
tableU16[-2] = (U16) nbBits;
|
||||
tableU16[-1] = (U16) maxSymbolValue;
|
||||
|
||||
/* Build table */
|
||||
for (s=0; s<tableSize; s++)
|
||||
tableU16[s] = (U16)(tableSize + s);
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
{ const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);
|
||||
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
symbolTT[s].deltaNbBits = deltaNbBits;
|
||||
symbolTT[s].deltaFindState = s-1;
|
||||
} }
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fake LIZFSE_CTable, for rle (100% always same symbol) input */
|
||||
size_t LIZFSE_buildCTable_rle (LIZFSE_CTable* ct, BYTE symbolValue)
|
||||
{
|
||||
void* ptr = ct;
|
||||
U16* tableU16 = ( (U16*) ptr) + 2;
|
||||
void* FSCTptr = (U32*)ptr + 2;
|
||||
LIZFSE_symbolCompressionTransform* symbolTT = (LIZFSE_symbolCompressionTransform*) FSCTptr;
|
||||
|
||||
/* header */
|
||||
tableU16[-2] = (U16) 0;
|
||||
tableU16[-1] = (U16) symbolValue;
|
||||
|
||||
/* Build table */
|
||||
tableU16[0] = 0;
|
||||
tableU16[1] = 0; /* just in case */
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
symbolTT[symbolValue].deltaNbBits = 0;
|
||||
symbolTT[symbolValue].deltaFindState = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static size_t LIZFSE_compress_usingCTable_generic (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const LIZFSE_CTable* ct, const unsigned fast)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) src;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* ip=iend;
|
||||
|
||||
|
||||
BIT_CStream_t bitC;
|
||||
LIZFSE_CState_t CState1, CState2;
|
||||
|
||||
/* init */
|
||||
if (srcSize <= 2) return 0;
|
||||
{ size_t const errorCode = BIT_initCStream(&bitC, dst, dstSize);
|
||||
if (LIZFSE_isError(errorCode)) return 0; }
|
||||
|
||||
#define LIZFSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
|
||||
|
||||
if (srcSize & 1) {
|
||||
LIZFSE_initCState2(&CState1, ct, *--ip);
|
||||
LIZFSE_initCState2(&CState2, ct, *--ip);
|
||||
LIZFSE_encodeSymbol(&bitC, &CState1, *--ip);
|
||||
LIZFSE_FLUSHBITS(&bitC);
|
||||
} else {
|
||||
LIZFSE_initCState2(&CState2, ct, *--ip);
|
||||
LIZFSE_initCState2(&CState1, ct, *--ip);
|
||||
}
|
||||
|
||||
/* join to mod 4 */
|
||||
srcSize -= 2;
|
||||
if ((sizeof(bitC.bitContainer)*8 > LIZFSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) { /* test bit 2 */
|
||||
LIZFSE_encodeSymbol(&bitC, &CState2, *--ip);
|
||||
LIZFSE_encodeSymbol(&bitC, &CState1, *--ip);
|
||||
LIZFSE_FLUSHBITS(&bitC);
|
||||
}
|
||||
|
||||
/* 2 or 4 encoding per loop */
|
||||
for ( ; ip>istart ; ) {
|
||||
|
||||
LIZFSE_encodeSymbol(&bitC, &CState2, *--ip);
|
||||
|
||||
if (sizeof(bitC.bitContainer)*8 < LIZFSE_MAX_TABLELOG*2+7 ) /* this test must be static */
|
||||
LIZFSE_FLUSHBITS(&bitC);
|
||||
|
||||
LIZFSE_encodeSymbol(&bitC, &CState1, *--ip);
|
||||
|
||||
if (sizeof(bitC.bitContainer)*8 > LIZFSE_MAX_TABLELOG*4+7 ) { /* this test must be static */
|
||||
LIZFSE_encodeSymbol(&bitC, &CState2, *--ip);
|
||||
LIZFSE_encodeSymbol(&bitC, &CState1, *--ip);
|
||||
}
|
||||
|
||||
LIZFSE_FLUSHBITS(&bitC);
|
||||
}
|
||||
|
||||
LIZFSE_flushCState(&bitC, &CState2);
|
||||
LIZFSE_flushCState(&bitC, &CState1);
|
||||
return BIT_closeCStream(&bitC);
|
||||
}
|
||||
|
||||
size_t LIZFSE_compress_usingCTable (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const LIZFSE_CTable* ct)
|
||||
{
|
||||
const unsigned fast = (dstSize >= LIZFSE_BLOCKBOUND(srcSize));
|
||||
|
||||
if (fast)
|
||||
return LIZFSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);
|
||||
else
|
||||
return LIZFSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_compressBound(size_t size) { return LIZFSE_COMPRESSBOUND(size); }
|
||||
|
||||
size_t LIZFSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) src;
|
||||
const BYTE* ip = istart;
|
||||
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
|
||||
U32 count[LIZFSE_MAX_SYMBOL_VALUE+1];
|
||||
S16 norm[LIZFSE_MAX_SYMBOL_VALUE+1];
|
||||
CTable_max_t ct;
|
||||
size_t errorCode;
|
||||
|
||||
/* init conditions */
|
||||
if (srcSize <= 1) return 0; /* Uncompressible */
|
||||
if (!maxSymbolValue) maxSymbolValue = LIZFSE_MAX_SYMBOL_VALUE;
|
||||
if (!tableLog) tableLog = LIZFSE_DEFAULT_TABLELOG;
|
||||
|
||||
/* Scan input and build symbol stats */
|
||||
errorCode = LIZFSE_count (count, &maxSymbolValue, ip, srcSize);
|
||||
if (LIZFSE_isError(errorCode)) return errorCode;
|
||||
if (errorCode == srcSize) return 1;
|
||||
if (errorCode == 1) return 0; /* each symbol only present once */
|
||||
if (errorCode < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */
|
||||
|
||||
tableLog = LIZFSE_optimalTableLog(tableLog, srcSize, maxSymbolValue);
|
||||
errorCode = LIZFSE_normalizeCount (norm, tableLog, count, srcSize, maxSymbolValue);
|
||||
if (LIZFSE_isError(errorCode)) return errorCode;
|
||||
|
||||
/* Write table description header */
|
||||
errorCode = LIZFSE_writeNCount (op, oend-op, norm, maxSymbolValue, tableLog);
|
||||
if (LIZFSE_isError(errorCode)) return errorCode;
|
||||
op += errorCode;
|
||||
|
||||
/* Compress */
|
||||
errorCode = LIZFSE_buildCTable (ct, norm, maxSymbolValue, tableLog);
|
||||
if (LIZFSE_isError(errorCode)) return errorCode;
|
||||
errorCode = LIZFSE_compress_usingCTable(op, oend - op, ip, srcSize, ct);
|
||||
if (errorCode == 0) return 0; /* not enough space for compressed data */
|
||||
op += errorCode;
|
||||
|
||||
/* check compressibility */
|
||||
if ( (size_t)(op-ostart) >= srcSize-1 )
|
||||
return 0;
|
||||
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
size_t LIZFSE_compress (void* dst, size_t dstSize, const void* src, size_t srcSize)
|
||||
{
|
||||
return LIZFSE_compress2(dst, dstSize, src, (U32)srcSize, LIZFSE_MAX_SYMBOL_VALUE, LIZFSE_DEFAULT_TABLELOG);
|
||||
}
|
||||
|
||||
|
||||
#endif /* LIZFSE_COMMONDEFS_ONLY */
|
||||
@@ -1,329 +0,0 @@
|
||||
/* ******************************************************************
|
||||
FSE : Finite State Entropy decoder
|
||||
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
|
||||
****************************************************************** */
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Compiler specifics
|
||||
****************************************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
||||
#else
|
||||
# if defined (__cplusplus) || 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
|
||||
****************************************************************/
|
||||
#include <stdlib.h> /* malloc, free, qsort */
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include <stdio.h> /* printf (debug) */
|
||||
#include "bitstream.h"
|
||||
#define LIZFSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Error Management
|
||||
****************************************************************/
|
||||
#define LIZFSE_isError ERR_isError
|
||||
#define LIZFSE_STATIC_ASSERT(c) { enum { LIZFSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
/* check and forward error code */
|
||||
#define CHECK_F(f) { size_t const e = f; if (LIZFSE_isError(e)) return e; }
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Complex types
|
||||
****************************************************************/
|
||||
typedef U32 DTable_max_t[LIZFSE_DTABLE_SIZE_U32(LIZFSE_MAX_TABLELOG)];
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Templates
|
||||
****************************************************************/
|
||||
/*
|
||||
designed to be included
|
||||
for type-specific functions (template emulation in C)
|
||||
Objective is to write these functions only once, for improved maintenance
|
||||
*/
|
||||
|
||||
/* safety checks */
|
||||
#ifndef LIZFSE_FUNCTION_EXTENSION
|
||||
# error "LIZFSE_FUNCTION_EXTENSION must be defined"
|
||||
#endif
|
||||
#ifndef LIZFSE_FUNCTION_TYPE
|
||||
# error "LIZFSE_FUNCTION_TYPE must be defined"
|
||||
#endif
|
||||
|
||||
/* Function names */
|
||||
#define LIZFSE_CAT(X,Y) X##Y
|
||||
#define LIZFSE_FUNCTION_NAME(X,Y) LIZFSE_CAT(X,Y)
|
||||
#define LIZFSE_TYPE_NAME(X,Y) LIZFSE_CAT(X,Y)
|
||||
|
||||
|
||||
/* Function templates */
|
||||
LIZFSE_DTable* LIZFSE_createDTable (unsigned tableLog)
|
||||
{
|
||||
if (tableLog > LIZFSE_TABLELOG_ABSOLUTE_MAX) tableLog = LIZFSE_TABLELOG_ABSOLUTE_MAX;
|
||||
return (LIZFSE_DTable*)malloc( LIZFSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
|
||||
}
|
||||
|
||||
void LIZFSE_freeDTable (LIZFSE_DTable* dt)
|
||||
{
|
||||
free(dt);
|
||||
}
|
||||
|
||||
size_t LIZFSE_buildDTable(LIZFSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
|
||||
LIZFSE_DECODE_TYPE* const tableDecode = (LIZFSE_DECODE_TYPE*) (tdPtr);
|
||||
U16 symbolNext[LIZFSE_MAX_SYMBOL_VALUE+1];
|
||||
|
||||
U32 const maxSV1 = maxSymbolValue + 1;
|
||||
U32 const tableSize = 1 << tableLog;
|
||||
U32 highThreshold = tableSize-1;
|
||||
|
||||
/* Sanity Checks */
|
||||
if (maxSymbolValue > LIZFSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
|
||||
if (tableLog > LIZFSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
|
||||
|
||||
/* Init, lay down lowprob symbols */
|
||||
{ LIZFSE_DTableHeader DTableH;
|
||||
DTableH.tableLog = (U16)tableLog;
|
||||
DTableH.fastMode = 1;
|
||||
{ S16 const largeLimit= (S16)(1 << (tableLog-1));
|
||||
U32 s;
|
||||
for (s=0; s<maxSV1; s++) {
|
||||
if (normalizedCounter[s]==-1) {
|
||||
tableDecode[highThreshold--].symbol = (LIZFSE_FUNCTION_TYPE)s;
|
||||
symbolNext[s] = 1;
|
||||
} else {
|
||||
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
|
||||
symbolNext[s] = normalizedCounter[s];
|
||||
} } }
|
||||
memcpy(dt, &DTableH, sizeof(DTableH));
|
||||
}
|
||||
|
||||
/* Spread symbols */
|
||||
{ U32 const tableMask = tableSize-1;
|
||||
U32 const step = LIZFSE_TABLESTEP(tableSize);
|
||||
U32 s, position = 0;
|
||||
for (s=0; s<maxSV1; s++) {
|
||||
int i;
|
||||
for (i=0; i<normalizedCounter[s]; i++) {
|
||||
tableDecode[position].symbol = (LIZFSE_FUNCTION_TYPE)s;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
|
||||
} }
|
||||
if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
|
||||
}
|
||||
|
||||
/* Build Decoding table */
|
||||
{ U32 u;
|
||||
for (u=0; u<tableSize; u++) {
|
||||
LIZFSE_FUNCTION_TYPE const symbol = (LIZFSE_FUNCTION_TYPE)(tableDecode[u].symbol);
|
||||
U16 nextState = symbolNext[symbol]++;
|
||||
tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
|
||||
tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
|
||||
} }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef LIZFSE_COMMONDEFS_ONLY
|
||||
|
||||
/*-*******************************************************
|
||||
* Decompression (Byte symbols)
|
||||
*********************************************************/
|
||||
size_t LIZFSE_buildDTable_rle (LIZFSE_DTable* dt, BYTE symbolValue)
|
||||
{
|
||||
void* ptr = dt;
|
||||
LIZFSE_DTableHeader* const DTableH = (LIZFSE_DTableHeader*)ptr;
|
||||
void* dPtr = dt + 1;
|
||||
LIZFSE_decode_t* const cell = (LIZFSE_decode_t*)dPtr;
|
||||
|
||||
DTableH->tableLog = 0;
|
||||
DTableH->fastMode = 0;
|
||||
|
||||
cell->newState = 0;
|
||||
cell->symbol = symbolValue;
|
||||
cell->nbBits = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_buildDTable_raw (LIZFSE_DTable* dt, unsigned nbBits)
|
||||
{
|
||||
void* ptr = dt;
|
||||
LIZFSE_DTableHeader* const DTableH = (LIZFSE_DTableHeader*)ptr;
|
||||
void* dPtr = dt + 1;
|
||||
LIZFSE_decode_t* const dinfo = (LIZFSE_decode_t*)dPtr;
|
||||
const unsigned tableSize = 1 << nbBits;
|
||||
const unsigned tableMask = tableSize - 1;
|
||||
const unsigned maxSV1 = tableMask+1;
|
||||
unsigned s;
|
||||
|
||||
/* Sanity checks */
|
||||
if (nbBits < 1) return ERROR(GENERIC); /* min size */
|
||||
|
||||
/* Build Decoding Table */
|
||||
DTableH->tableLog = (U16)nbBits;
|
||||
DTableH->fastMode = 1;
|
||||
for (s=0; s<maxSV1; s++) {
|
||||
dinfo[s].newState = 0;
|
||||
dinfo[s].symbol = (BYTE)s;
|
||||
dinfo[s].nbBits = (BYTE)nbBits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t LIZFSE_decompress_usingDTable_generic(
|
||||
void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZFSE_DTable* dt, const unsigned fast)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const omax = op + maxDstSize;
|
||||
BYTE* const olimit = omax-3;
|
||||
|
||||
BIT_DStream_t bitD;
|
||||
LIZFSE_DState_t state1;
|
||||
LIZFSE_DState_t state2;
|
||||
|
||||
/* Init */
|
||||
CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
|
||||
|
||||
LIZFSE_initDState(&state1, &bitD, dt);
|
||||
LIZFSE_initDState(&state2, &bitD, dt);
|
||||
|
||||
#define LIZFSE_GETSYMBOL(statePtr) fast ? LIZFSE_decodeSymbolFast(statePtr, &bitD) : LIZFSE_decodeSymbol(statePtr, &bitD)
|
||||
|
||||
/* 4 symbols per loop */
|
||||
for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {
|
||||
op[0] = LIZFSE_GETSYMBOL(&state1);
|
||||
|
||||
if (LIZFSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||
BIT_reloadDStream(&bitD);
|
||||
|
||||
op[1] = LIZFSE_GETSYMBOL(&state2);
|
||||
|
||||
if (LIZFSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||
{ if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
|
||||
|
||||
op[2] = LIZFSE_GETSYMBOL(&state1);
|
||||
|
||||
if (LIZFSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
|
||||
BIT_reloadDStream(&bitD);
|
||||
|
||||
op[3] = LIZFSE_GETSYMBOL(&state2);
|
||||
}
|
||||
|
||||
/* tail */
|
||||
/* note : BIT_reloadDStream(&bitD) >= LIZFSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
|
||||
while (1) {
|
||||
if (op>(omax-2)) return ERROR(dstSize_tooSmall);
|
||||
*op++ = LIZFSE_GETSYMBOL(&state1);
|
||||
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
|
||||
*op++ = LIZFSE_GETSYMBOL(&state2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (op>(omax-2)) return ERROR(dstSize_tooSmall);
|
||||
*op++ = LIZFSE_GETSYMBOL(&state2);
|
||||
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
|
||||
*op++ = LIZFSE_GETSYMBOL(&state1);
|
||||
break;
|
||||
} }
|
||||
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_decompress_usingDTable(void* dst, size_t originalSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZFSE_DTable* dt)
|
||||
{
|
||||
const void* ptr = dt;
|
||||
const LIZFSE_DTableHeader* DTableH = (const LIZFSE_DTableHeader*)ptr;
|
||||
const U32 fastMode = DTableH->fastMode;
|
||||
|
||||
/* select fast mode (static) */
|
||||
if (fastMode) return LIZFSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
|
||||
return LIZFSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZFSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*)cSrc;
|
||||
const BYTE* ip = istart;
|
||||
short counting[LIZFSE_MAX_SYMBOL_VALUE+1];
|
||||
DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */
|
||||
unsigned tableLog;
|
||||
unsigned maxSymbolValue = LIZFSE_MAX_SYMBOL_VALUE;
|
||||
|
||||
if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */
|
||||
|
||||
/* normal FSE decoding mode */
|
||||
{ size_t const NCountLength = LIZFSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
|
||||
if (LIZFSE_isError(NCountLength)) return NCountLength;
|
||||
if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */
|
||||
ip += NCountLength;
|
||||
cSrcSize -= NCountLength;
|
||||
}
|
||||
|
||||
CHECK_F( LIZFSE_buildDTable (dt, counting, maxSymbolValue, tableLog) );
|
||||
|
||||
return LIZFSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); /* always return, even if it is an error code */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* LIZFSE_COMMONDEFS_ONLY */
|
||||
@@ -1,532 +0,0 @@
|
||||
/* ******************************************************************
|
||||
Huffman encoder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2016, 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+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
****************************************************************** */
|
||||
|
||||
/* **************************************************************
|
||||
* Compiler specifics
|
||||
****************************************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Includes
|
||||
****************************************************************/
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include <stdio.h> /* printf (debug) */
|
||||
#include "bitstream.h"
|
||||
#define LIZFSE_STATIC_LINKING_ONLY /* LIZFSE_optimalTableLog_internal */
|
||||
#include "fse.h" /* header compression */
|
||||
#define LIZHUF_STATIC_LINKING_ONLY
|
||||
#include "huf.h"
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Error Management
|
||||
****************************************************************/
|
||||
#define LIZHUF_STATIC_ASSERT(c) { enum { LIZHUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Utils
|
||||
****************************************************************/
|
||||
unsigned LIZHUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
|
||||
{
|
||||
return LIZFSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);
|
||||
}
|
||||
|
||||
|
||||
/* *******************************************************
|
||||
* HUF : Huffman block compression
|
||||
*********************************************************/
|
||||
struct LIZHUF_CElt_s {
|
||||
U16 val;
|
||||
BYTE nbBits;
|
||||
}; /* typedef'd to LIZHUF_CElt within "huf.h" */
|
||||
|
||||
typedef struct nodeElt_s {
|
||||
U32 count;
|
||||
U16 parent;
|
||||
BYTE byte;
|
||||
BYTE nbBits;
|
||||
} nodeElt;
|
||||
|
||||
/*! LIZHUF_writeCTable() :
|
||||
`CTable` : huffman tree to save, using huf representation.
|
||||
@return : size of saved CTable */
|
||||
size_t LIZHUF_writeCTable (void* dst, size_t maxDstSize,
|
||||
const LIZHUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
|
||||
{
|
||||
BYTE bitsToWeight[LIZHUF_TABLELOG_MAX + 1];
|
||||
BYTE huffWeight[LIZHUF_SYMBOLVALUE_MAX];
|
||||
BYTE* op = (BYTE*)dst;
|
||||
U32 n;
|
||||
|
||||
/* check conditions */
|
||||
if (maxSymbolValue > LIZHUF_SYMBOLVALUE_MAX) return ERROR(GENERIC);
|
||||
|
||||
/* convert to weight */
|
||||
bitsToWeight[0] = 0;
|
||||
for (n=1; n<huffLog+1; n++)
|
||||
bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
|
||||
for (n=0; n<maxSymbolValue; n++)
|
||||
huffWeight[n] = bitsToWeight[CTable[n].nbBits];
|
||||
|
||||
{ size_t const size = LIZFSE_compress(op+1, maxDstSize-1, huffWeight, maxSymbolValue);
|
||||
if (LIZFSE_isError(size)) return size;
|
||||
if ((size>1) & (size < maxSymbolValue/2)) { /* FSE compressed */
|
||||
op[0] = (BYTE)size;
|
||||
return size+1;
|
||||
}
|
||||
}
|
||||
|
||||
/* raw values */
|
||||
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen */
|
||||
if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
|
||||
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
|
||||
huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause issue in final combination */
|
||||
for (n=0; n<maxSymbolValue; n+=2)
|
||||
op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
|
||||
return ((maxSymbolValue+1)/2) + 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_readCTable (LIZHUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE huffWeight[LIZHUF_SYMBOLVALUE_MAX + 1];
|
||||
U32 rankVal[LIZHUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
|
||||
U32 tableLog = 0;
|
||||
size_t readSize;
|
||||
U32 nbSymbols = 0;
|
||||
/*memset(huffWeight, 0, sizeof(huffWeight));*/ /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
/* get symbol weights */
|
||||
readSize = LIZHUF_readStats(huffWeight, LIZHUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize);
|
||||
if (LIZHUF_isError(readSize)) return readSize;
|
||||
|
||||
/* check result */
|
||||
if (tableLog > LIZHUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
||||
if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall);
|
||||
|
||||
/* Prepare base value per rank */
|
||||
{ U32 n, nextRankStart = 0;
|
||||
for (n=1; n<=tableLog; n++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += (rankVal[n] << (n-1));
|
||||
rankVal[n] = current;
|
||||
} }
|
||||
|
||||
/* fill nbBits */
|
||||
{ U32 n; for (n=0; n<nbSymbols; n++) {
|
||||
const U32 w = huffWeight[n];
|
||||
CTable[n].nbBits = (BYTE)(tableLog + 1 - w);
|
||||
} }
|
||||
|
||||
/* fill val */
|
||||
{ U16 nbPerRank[LIZHUF_TABLELOG_MAX+1] = {0};
|
||||
U16 valPerRank[LIZHUF_TABLELOG_MAX+1] = {0};
|
||||
{ U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; }
|
||||
/* determine stating value per rank */
|
||||
{ U16 min = 0;
|
||||
U32 n; for (n=LIZHUF_TABLELOG_MAX; n>0; n--) {
|
||||
valPerRank[n] = min; /* get starting value within each rank */
|
||||
min += nbPerRank[n];
|
||||
min >>= 1;
|
||||
} }
|
||||
/* assign value within rank, symbol order */
|
||||
{ U32 n; for (n=0; n<=maxSymbolValue; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
|
||||
static U32 LIZHUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
{
|
||||
const U32 largestBits = huffNode[lastNonNull].nbBits;
|
||||
if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */
|
||||
|
||||
/* there are several too large elements (at least >= 2) */
|
||||
{ int totalCost = 0;
|
||||
const U32 baseCost = 1 << (largestBits - maxNbBits);
|
||||
U32 n = lastNonNull;
|
||||
|
||||
while (huffNode[n].nbBits > maxNbBits) {
|
||||
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
|
||||
huffNode[n].nbBits = (BYTE)maxNbBits;
|
||||
n --;
|
||||
} /* n stops at huffNode[n].nbBits <= maxNbBits */
|
||||
while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */
|
||||
|
||||
/* renorm totalCost */
|
||||
totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */
|
||||
|
||||
/* repay normalized cost */
|
||||
{ U32 const noSymbol = 0xF0F0F0F0;
|
||||
U32 rankLast[LIZHUF_TABLELOG_MAX+2];
|
||||
int pos;
|
||||
|
||||
/* Get pos of last (smallest) symbol per rank */
|
||||
memset(rankLast, 0xF0, sizeof(rankLast));
|
||||
{ U32 currentNbBits = maxNbBits;
|
||||
for (pos=n ; pos >= 0; pos--) {
|
||||
if (huffNode[pos].nbBits >= currentNbBits) continue;
|
||||
currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */
|
||||
rankLast[maxNbBits-currentNbBits] = pos;
|
||||
} }
|
||||
|
||||
while (totalCost > 0) {
|
||||
U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1;
|
||||
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {
|
||||
U32 highPos = rankLast[nBitsToDecrease];
|
||||
U32 lowPos = rankLast[nBitsToDecrease-1];
|
||||
if (highPos == noSymbol) continue;
|
||||
if (lowPos == noSymbol) break;
|
||||
{ U32 const highTotal = huffNode[highPos].count;
|
||||
U32 const lowTotal = 2 * huffNode[lowPos].count;
|
||||
if (highTotal <= lowTotal) break;
|
||||
} }
|
||||
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
|
||||
while ((nBitsToDecrease<=LIZHUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) /* LIZHUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
|
||||
nBitsToDecrease ++;
|
||||
totalCost -= 1 << (nBitsToDecrease-1);
|
||||
if (rankLast[nBitsToDecrease-1] == noSymbol)
|
||||
rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */
|
||||
huffNode[rankLast[nBitsToDecrease]].nbBits ++;
|
||||
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */
|
||||
rankLast[nBitsToDecrease] = noSymbol;
|
||||
else {
|
||||
rankLast[nBitsToDecrease]--;
|
||||
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)
|
||||
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
|
||||
} } /* while (totalCost > 0) */
|
||||
|
||||
while (totalCost < 0) { /* Sometimes, cost correction overshoot */
|
||||
if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */
|
||||
while (huffNode[n].nbBits == maxNbBits) n--;
|
||||
huffNode[n+1].nbBits--;
|
||||
rankLast[1] = n+1;
|
||||
totalCost++;
|
||||
continue;
|
||||
}
|
||||
huffNode[ rankLast[1] + 1 ].nbBits--;
|
||||
rankLast[1]++;
|
||||
totalCost ++;
|
||||
} } } /* there are several too large elements (at least >= 2) */
|
||||
|
||||
return maxNbBits;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
U32 base;
|
||||
U32 current;
|
||||
} rankPos;
|
||||
|
||||
static void LIZHUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
|
||||
{
|
||||
rankPos rank[32];
|
||||
U32 n;
|
||||
|
||||
memset(rank, 0, sizeof(rank));
|
||||
for (n=0; n<=maxSymbolValue; n++) {
|
||||
U32 r = BIT_highbit32(count[n] + 1);
|
||||
rank[r].base ++;
|
||||
}
|
||||
for (n=30; n>0; n--) rank[n-1].base += rank[n].base;
|
||||
for (n=0; n<32; n++) rank[n].current = rank[n].base;
|
||||
for (n=0; n<=maxSymbolValue; n++) {
|
||||
U32 const c = count[n];
|
||||
U32 const r = BIT_highbit32(c+1) + 1;
|
||||
U32 pos = rank[r].current++;
|
||||
while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) huffNode[pos]=huffNode[pos-1], pos--;
|
||||
huffNode[pos].count = c;
|
||||
huffNode[pos].byte = (BYTE)n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define STARTNODE (LIZHUF_SYMBOLVALUE_MAX+1)
|
||||
size_t LIZHUF_buildCTable (LIZHUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits)
|
||||
{
|
||||
nodeElt huffNode0[2*LIZHUF_SYMBOLVALUE_MAX+1 +1];
|
||||
nodeElt* huffNode = huffNode0 + 1;
|
||||
U32 n, nonNullRank;
|
||||
int lowS, lowN;
|
||||
U16 nodeNb = STARTNODE;
|
||||
U32 nodeRoot;
|
||||
|
||||
/* safety checks */
|
||||
if (maxNbBits == 0) maxNbBits = LIZHUF_TABLELOG_DEFAULT;
|
||||
if (maxSymbolValue > LIZHUF_SYMBOLVALUE_MAX) return ERROR(GENERIC);
|
||||
memset(huffNode0, 0, sizeof(huffNode0));
|
||||
|
||||
/* sort, decreasing order */
|
||||
LIZHUF_sort(huffNode, count, maxSymbolValue);
|
||||
|
||||
/* init for parents */
|
||||
nonNullRank = maxSymbolValue;
|
||||
while(huffNode[nonNullRank].count == 0) nonNullRank--;
|
||||
lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;
|
||||
huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;
|
||||
huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb;
|
||||
nodeNb++; lowS-=2;
|
||||
for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);
|
||||
huffNode0[0].count = (U32)(1U<<31);
|
||||
|
||||
/* create parents */
|
||||
while (nodeNb <= nodeRoot) {
|
||||
U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
|
||||
U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;
|
||||
huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;
|
||||
huffNode[n1].parent = huffNode[n2].parent = nodeNb;
|
||||
nodeNb++;
|
||||
}
|
||||
|
||||
/* distribute weights (unlimited tree height) */
|
||||
huffNode[nodeRoot].nbBits = 0;
|
||||
for (n=nodeRoot-1; n>=STARTNODE; n--)
|
||||
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
|
||||
for (n=0; n<=nonNullRank; n++)
|
||||
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
|
||||
|
||||
/* enforce maxTableLog */
|
||||
maxNbBits = LIZHUF_setMaxHeight(huffNode, nonNullRank, maxNbBits);
|
||||
|
||||
/* fill result into tree (val, nbBits) */
|
||||
{ U16 nbPerRank[LIZHUF_TABLELOG_MAX+1] = {0};
|
||||
U16 valPerRank[LIZHUF_TABLELOG_MAX+1] = {0};
|
||||
if (maxNbBits > LIZHUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
|
||||
for (n=0; n<=nonNullRank; n++)
|
||||
nbPerRank[huffNode[n].nbBits]++;
|
||||
/* determine stating value per rank */
|
||||
{ U16 min = 0;
|
||||
for (n=maxNbBits; n>0; n--) {
|
||||
valPerRank[n] = min; /* get starting value within each rank */
|
||||
min += nbPerRank[n];
|
||||
min >>= 1;
|
||||
} }
|
||||
for (n=0; n<=maxSymbolValue; n++)
|
||||
tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
|
||||
for (n=0; n<=maxSymbolValue; n++)
|
||||
tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */
|
||||
}
|
||||
|
||||
return maxNbBits;
|
||||
}
|
||||
|
||||
static void LIZHUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const LIZHUF_CElt* CTable)
|
||||
{
|
||||
BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
|
||||
}
|
||||
|
||||
size_t LIZHUF_compressBound(size_t size) { return LIZHUF_COMPRESSBOUND(size); }
|
||||
|
||||
#define LIZHUF_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
|
||||
|
||||
#define LIZHUF_FLUSHBITS_1(stream) \
|
||||
if (sizeof((stream)->bitContainer)*8 < LIZHUF_TABLELOG_MAX*2+7) LIZHUF_FLUSHBITS(stream)
|
||||
|
||||
#define LIZHUF_FLUSHBITS_2(stream) \
|
||||
if (sizeof((stream)->bitContainer)*8 < LIZHUF_TABLELOG_MAX*4+7) LIZHUF_FLUSHBITS(stream)
|
||||
|
||||
size_t LIZHUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const LIZHUF_CElt* CTable)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
size_t n;
|
||||
const unsigned fast = (dstSize >= LIZHUF_BLOCKBOUND(srcSize));
|
||||
BIT_CStream_t bitC;
|
||||
|
||||
/* init */
|
||||
if (dstSize < 8) return 0; /* not enough space to compress */
|
||||
{ size_t const errorCode = BIT_initCStream(&bitC, op, oend-op);
|
||||
if (LIZHUF_isError(errorCode)) return 0; }
|
||||
|
||||
n = srcSize & ~3; /* join to mod 4 */
|
||||
switch (srcSize & 3)
|
||||
{
|
||||
case 3 : LIZHUF_encodeSymbol(&bitC, ip[n+ 2], CTable);
|
||||
LIZHUF_FLUSHBITS_2(&bitC);
|
||||
case 2 : LIZHUF_encodeSymbol(&bitC, ip[n+ 1], CTable);
|
||||
LIZHUF_FLUSHBITS_1(&bitC);
|
||||
case 1 : LIZHUF_encodeSymbol(&bitC, ip[n+ 0], CTable);
|
||||
LIZHUF_FLUSHBITS(&bitC);
|
||||
case 0 :
|
||||
default: ;
|
||||
}
|
||||
|
||||
for (; n>0; n-=4) { /* note : n&3==0 at this stage */
|
||||
LIZHUF_encodeSymbol(&bitC, ip[n- 1], CTable);
|
||||
LIZHUF_FLUSHBITS_1(&bitC);
|
||||
LIZHUF_encodeSymbol(&bitC, ip[n- 2], CTable);
|
||||
LIZHUF_FLUSHBITS_2(&bitC);
|
||||
LIZHUF_encodeSymbol(&bitC, ip[n- 3], CTable);
|
||||
LIZHUF_FLUSHBITS_1(&bitC);
|
||||
LIZHUF_encodeSymbol(&bitC, ip[n- 4], CTable);
|
||||
LIZHUF_FLUSHBITS(&bitC);
|
||||
}
|
||||
|
||||
return BIT_closeCStream(&bitC);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const LIZHUF_CElt* CTable)
|
||||
{
|
||||
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
const BYTE* const iend = ip + srcSize;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
|
||||
if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */
|
||||
if (srcSize < 12) return 0; /* no saving possible : too small input */
|
||||
op += 6; /* jumpTable */
|
||||
|
||||
{ size_t const cSize = LIZHUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable);
|
||||
if (LIZHUF_isError(cSize)) return cSize;
|
||||
if (cSize==0) return 0;
|
||||
MEM_writeLE16(ostart, (U16)cSize);
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
ip += segmentSize;
|
||||
{ size_t const cSize = LIZHUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable);
|
||||
if (LIZHUF_isError(cSize)) return cSize;
|
||||
if (cSize==0) return 0;
|
||||
MEM_writeLE16(ostart+2, (U16)cSize);
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
ip += segmentSize;
|
||||
{ size_t const cSize = LIZHUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable);
|
||||
if (LIZHUF_isError(cSize)) return cSize;
|
||||
if (cSize==0) return 0;
|
||||
MEM_writeLE16(ostart+4, (U16)cSize);
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
ip += segmentSize;
|
||||
{ size_t const cSize = LIZHUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable);
|
||||
if (LIZHUF_isError(cSize)) return cSize;
|
||||
if (cSize==0) return 0;
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
|
||||
static size_t LIZHUF_compress_internal (
|
||||
void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
unsigned singleStream)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
|
||||
U32 count[LIZHUF_SYMBOLVALUE_MAX+1];
|
||||
LIZHUF_CElt CTable[LIZHUF_SYMBOLVALUE_MAX+1];
|
||||
|
||||
/* checks & inits */
|
||||
if (!srcSize) return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */
|
||||
if (!dstSize) return 0; /* cannot fit within dst budget */
|
||||
if (srcSize > LIZHUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
|
||||
if (huffLog > LIZHUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
||||
if (!maxSymbolValue) maxSymbolValue = LIZHUF_SYMBOLVALUE_MAX;
|
||||
if (!huffLog) huffLog = LIZHUF_TABLELOG_DEFAULT;
|
||||
|
||||
/* Scan input and build symbol stats */
|
||||
{ size_t const largest = LIZFSE_count (count, &maxSymbolValue, (const BYTE*)src, srcSize);
|
||||
if (LIZHUF_isError(largest)) return largest;
|
||||
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
|
||||
if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */
|
||||
}
|
||||
|
||||
/* Build Huffman Tree */
|
||||
huffLog = LIZHUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
||||
{ size_t const maxBits = LIZHUF_buildCTable (CTable, count, maxSymbolValue, huffLog);
|
||||
if (LIZHUF_isError(maxBits)) return maxBits;
|
||||
huffLog = (U32)maxBits;
|
||||
}
|
||||
|
||||
/* Write table description header */
|
||||
{ size_t const hSize = LIZHUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog);
|
||||
if (LIZHUF_isError(hSize)) return hSize;
|
||||
if (hSize + 12 >= srcSize) return 0; /* not useful to try compression */
|
||||
op += hSize;
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
{ size_t const cSize = (singleStream) ?
|
||||
LIZHUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) : /* single segment */
|
||||
LIZHUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable);
|
||||
if (LIZHUF_isError(cSize)) return cSize;
|
||||
if (cSize==0) return 0; /* uncompressible */
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
/* check compressibility */
|
||||
if ((size_t)(op-ostart) >= srcSize-1)
|
||||
return 0;
|
||||
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_compress1X (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
{
|
||||
return LIZHUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1);
|
||||
}
|
||||
|
||||
size_t LIZHUF_compress2 (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
{
|
||||
return LIZHUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
{
|
||||
return LIZHUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, LIZHUF_TABLELOG_DEFAULT);
|
||||
}
|
||||
@@ -1,883 +0,0 @@
|
||||
/* ******************************************************************
|
||||
Huffman decoder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2016, 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+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
****************************************************************** */
|
||||
|
||||
/* **************************************************************
|
||||
* Compiler specifics
|
||||
****************************************************************/
|
||||
#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
/* inline is defined */
|
||||
#elif defined(_MSC_VER) || defined(__GNUC__)
|
||||
# define inline __inline
|
||||
#else
|
||||
# define inline /* disable inline */
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Dependencies
|
||||
****************************************************************/
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include "bitstream.h" /* BIT_* */
|
||||
#include "fse.h" /* header compression */
|
||||
#define LIZHUF_STATIC_LINKING_ONLY
|
||||
#include "huf.h"
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Error Management
|
||||
****************************************************************/
|
||||
#define LIZHUF_STATIC_ASSERT(c) { enum { LIZHUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/*-***************************/
|
||||
/* generic DTableDesc */
|
||||
/*-***************************/
|
||||
|
||||
typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
|
||||
|
||||
static DTableDesc LIZHUF_getDTableDesc(const LIZHUF_DTable* table)
|
||||
{
|
||||
DTableDesc dtd;
|
||||
memcpy(&dtd, table, sizeof(dtd));
|
||||
return dtd;
|
||||
}
|
||||
|
||||
|
||||
/*-***************************/
|
||||
/* single-symbol decoding */
|
||||
/*-***************************/
|
||||
|
||||
typedef struct { BYTE byte; BYTE nbBits; } LIZHUF_DEltX2; /* single-symbol decoding */
|
||||
|
||||
size_t LIZHUF_readDTableX2 (LIZHUF_DTable* DTable, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE huffWeight[LIZHUF_SYMBOLVALUE_MAX + 1];
|
||||
U32 rankVal[LIZHUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
|
||||
U32 tableLog = 0;
|
||||
U32 nbSymbols = 0;
|
||||
size_t iSize;
|
||||
void* const dtPtr = DTable + 1;
|
||||
LIZHUF_DEltX2* const dt = (LIZHUF_DEltX2*)dtPtr;
|
||||
|
||||
LIZHUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(LIZHUF_DTable));
|
||||
/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
iSize = LIZHUF_readStats(huffWeight, LIZHUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
|
||||
if (LIZHUF_isError(iSize)) return iSize;
|
||||
|
||||
/* Table header */
|
||||
{ DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, huffman tree cannot fit in */
|
||||
dtd.tableType = 0;
|
||||
dtd.tableLog = (BYTE)tableLog;
|
||||
memcpy(DTable, &dtd, sizeof(dtd));
|
||||
}
|
||||
|
||||
/* Prepare ranks */
|
||||
{ U32 n, nextRankStart = 0;
|
||||
for (n=1; n<tableLog+1; n++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += (rankVal[n] << (n-1));
|
||||
rankVal[n] = current;
|
||||
} }
|
||||
|
||||
/* fill DTable */
|
||||
{ U32 n;
|
||||
for (n=0; n<nbSymbols; n++) {
|
||||
U32 const w = huffWeight[n];
|
||||
U32 const length = (1 << w) >> 1;
|
||||
U32 i;
|
||||
LIZHUF_DEltX2 D;
|
||||
D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
|
||||
for (i = rankVal[w]; i < rankVal[w] + length; i++)
|
||||
dt[i] = D;
|
||||
rankVal[w] += length;
|
||||
} }
|
||||
|
||||
return iSize;
|
||||
}
|
||||
|
||||
|
||||
static BYTE LIZHUF_decodeSymbolX2(BIT_DStream_t* Dstream, const LIZHUF_DEltX2* dt, const U32 dtLog)
|
||||
{
|
||||
size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
|
||||
BYTE const c = dt[val].byte;
|
||||
BIT_skipBits(Dstream, dt[val].nbBits);
|
||||
return c;
|
||||
}
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
|
||||
*ptr++ = LIZHUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
|
||||
if (MEM_64bits() || (LIZHUF_TABLELOG_MAX<=12)) \
|
||||
LIZHUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
|
||||
if (MEM_64bits()) \
|
||||
LIZHUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
|
||||
|
||||
static inline size_t LIZHUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const LIZHUF_DEltX2* const dt, const U32 dtLog)
|
||||
{
|
||||
BYTE* const pStart = p;
|
||||
|
||||
/* up to 4 symbols at a time */
|
||||
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) {
|
||||
LIZHUF_DECODE_SYMBOLX2_2(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX2_1(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX2_0(p, bitDPtr);
|
||||
}
|
||||
|
||||
/* closer to the end */
|
||||
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
|
||||
LIZHUF_DECODE_SYMBOLX2_0(p, bitDPtr);
|
||||
|
||||
/* no more data to retrieve from bitstream, hence no need to reload */
|
||||
while (p < pEnd)
|
||||
LIZHUF_DECODE_SYMBOLX2_0(p, bitDPtr);
|
||||
|
||||
return pEnd-pStart;
|
||||
}
|
||||
|
||||
static size_t LIZHUF_decompress1X2_usingDTable_internal(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + dstSize;
|
||||
const void* dtPtr = DTable + 1;
|
||||
const LIZHUF_DEltX2* const dt = (const LIZHUF_DEltX2*)dtPtr;
|
||||
BIT_DStream_t bitD;
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
U32 const dtLog = dtd.tableLog;
|
||||
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
|
||||
LIZHUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
|
||||
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X2_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 0) return ERROR(GENERIC);
|
||||
return LIZHUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X2_DCtx (LIZHUF_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = LIZHUF_readDTableX2 (DCtx, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return LIZHUF_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
LIZHUF_CREATE_STATIC_DTABLEX2(DTable, LIZHUF_TABLELOG_MAX);
|
||||
return LIZHUF_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
|
||||
|
||||
static size_t LIZHUF_decompress4X2_usingDTable_internal(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
/* Check */
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable + 1;
|
||||
const LIZHUF_DEltX2* const dt = (const LIZHUF_DEltX2*)dtPtr;
|
||||
|
||||
/* Init */
|
||||
BIT_DStream_t bitD1;
|
||||
BIT_DStream_t bitD2;
|
||||
BIT_DStream_t bitD3;
|
||||
BIT_DStream_t bitD4;
|
||||
size_t const length1 = MEM_readLE16(istart);
|
||||
size_t const length2 = MEM_readLE16(istart+2);
|
||||
size_t const length3 = MEM_readLE16(istart+4);
|
||||
size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
|
||||
const BYTE* const istart1 = istart + 6; /* jumpTable */
|
||||
const BYTE* const istart2 = istart1 + length1;
|
||||
const BYTE* const istart3 = istart2 + length2;
|
||||
const BYTE* const istart4 = istart3 + length3;
|
||||
const size_t segmentSize = (dstSize+3) / 4;
|
||||
BYTE* const opStart2 = ostart + segmentSize;
|
||||
BYTE* const opStart3 = opStart2 + segmentSize;
|
||||
BYTE* const opStart4 = opStart3 + segmentSize;
|
||||
BYTE* op1 = ostart;
|
||||
BYTE* op2 = opStart2;
|
||||
BYTE* op3 = opStart3;
|
||||
BYTE* op4 = opStart4;
|
||||
U32 endSignal;
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
U32 const dtLog = dtd.tableLog;
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
|
||||
/* 16-32 symbols per loop (4-8 symbols per stream) */
|
||||
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
|
||||
for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) {
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX2_1(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX2_1(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX2_1(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX2_1(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX2_2(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX2_0(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX2_0(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX2_0(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX2_0(op4, &bitD4);
|
||||
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
|
||||
}
|
||||
|
||||
/* check corruption */
|
||||
if (op1 > opStart2) return ERROR(corruption_detected);
|
||||
if (op2 > opStart3) return ERROR(corruption_detected);
|
||||
if (op3 > opStart4) return ERROR(corruption_detected);
|
||||
/* note : op4 supposed already verified within main loop */
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
LIZHUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
|
||||
LIZHUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
|
||||
LIZHUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
|
||||
LIZHUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
|
||||
if (!endSignal) return ERROR(corruption_detected);
|
||||
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_decompress4X2_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 0) return ERROR(GENERIC);
|
||||
return LIZHUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_decompress4X2_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = LIZHUF_readDTableX2 (dctx, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return LIZHUF_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
LIZHUF_CREATE_STATIC_DTABLEX2(DTable, LIZHUF_TABLELOG_MAX);
|
||||
return LIZHUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
|
||||
|
||||
/* *************************/
|
||||
/* double-symbols decoding */
|
||||
/* *************************/
|
||||
typedef struct { U16 sequence; BYTE nbBits; BYTE length; } LIZHUF_DEltX4; /* double-symbols decoding */
|
||||
|
||||
typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
|
||||
|
||||
static void LIZHUF_fillDTableX4Level2(LIZHUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,
|
||||
const U32* rankValOrigin, const int minWeight,
|
||||
const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
|
||||
U32 nbBitsBaseline, U16 baseSeq)
|
||||
{
|
||||
LIZHUF_DEltX4 DElt;
|
||||
U32 rankVal[LIZHUF_TABLELOG_ABSOLUTEMAX + 1];
|
||||
|
||||
/* get pre-calculated rankVal */
|
||||
memcpy(rankVal, rankValOrigin, sizeof(rankVal));
|
||||
|
||||
/* fill skipped values */
|
||||
if (minWeight>1) {
|
||||
U32 i, skipSize = rankVal[minWeight];
|
||||
MEM_writeLE16(&(DElt.sequence), baseSeq);
|
||||
DElt.nbBits = (BYTE)(consumed);
|
||||
DElt.length = 1;
|
||||
for (i = 0; i < skipSize; i++)
|
||||
DTable[i] = DElt;
|
||||
}
|
||||
|
||||
/* fill DTable */
|
||||
{ U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
|
||||
const U32 symbol = sortedSymbols[s].symbol;
|
||||
const U32 weight = sortedSymbols[s].weight;
|
||||
const U32 nbBits = nbBitsBaseline - weight;
|
||||
const U32 length = 1 << (sizeLog-nbBits);
|
||||
const U32 start = rankVal[weight];
|
||||
U32 i = start;
|
||||
const U32 end = start + length;
|
||||
|
||||
MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
|
||||
DElt.nbBits = (BYTE)(nbBits + consumed);
|
||||
DElt.length = 2;
|
||||
do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */
|
||||
|
||||
rankVal[weight] += length;
|
||||
} }
|
||||
}
|
||||
|
||||
typedef U32 rankVal_t[LIZHUF_TABLELOG_ABSOLUTEMAX][LIZHUF_TABLELOG_ABSOLUTEMAX + 1];
|
||||
|
||||
static void LIZHUF_fillDTableX4(LIZHUF_DEltX4* DTable, const U32 targetLog,
|
||||
const sortedSymbol_t* sortedList, const U32 sortedListSize,
|
||||
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
|
||||
const U32 nbBitsBaseline)
|
||||
{
|
||||
U32 rankVal[LIZHUF_TABLELOG_ABSOLUTEMAX + 1];
|
||||
const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
|
||||
const U32 minBits = nbBitsBaseline - maxWeight;
|
||||
U32 s;
|
||||
|
||||
memcpy(rankVal, rankValOrigin, sizeof(rankVal));
|
||||
|
||||
/* fill DTable */
|
||||
for (s=0; s<sortedListSize; s++) {
|
||||
const U16 symbol = sortedList[s].symbol;
|
||||
const U32 weight = sortedList[s].weight;
|
||||
const U32 nbBits = nbBitsBaseline - weight;
|
||||
const U32 start = rankVal[weight];
|
||||
const U32 length = 1 << (targetLog-nbBits);
|
||||
|
||||
if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */
|
||||
U32 sortedRank;
|
||||
int minWeight = nbBits + scaleLog;
|
||||
if (minWeight < 1) minWeight = 1;
|
||||
sortedRank = rankStart[minWeight];
|
||||
LIZHUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
|
||||
rankValOrigin[nbBits], minWeight,
|
||||
sortedList+sortedRank, sortedListSize-sortedRank,
|
||||
nbBitsBaseline, symbol);
|
||||
} else {
|
||||
LIZHUF_DEltX4 DElt;
|
||||
MEM_writeLE16(&(DElt.sequence), symbol);
|
||||
DElt.nbBits = (BYTE)(nbBits);
|
||||
DElt.length = 1;
|
||||
{ U32 const end = start + length;
|
||||
U32 u;
|
||||
for (u = start; u < end; u++) DTable[u] = DElt;
|
||||
} }
|
||||
rankVal[weight] += length;
|
||||
}
|
||||
}
|
||||
|
||||
size_t LIZHUF_readDTableX4 (LIZHUF_DTable* DTable, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE weightList[LIZHUF_SYMBOLVALUE_MAX + 1];
|
||||
sortedSymbol_t sortedSymbol[LIZHUF_SYMBOLVALUE_MAX + 1];
|
||||
U32 rankStats[LIZHUF_TABLELOG_ABSOLUTEMAX + 1] = { 0 };
|
||||
U32 rankStart0[LIZHUF_TABLELOG_ABSOLUTEMAX + 2] = { 0 };
|
||||
U32* const rankStart = rankStart0+1;
|
||||
rankVal_t rankVal;
|
||||
U32 tableLog, maxW, sizeOfSort, nbSymbols;
|
||||
DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
U32 const maxTableLog = dtd.maxTableLog;
|
||||
size_t iSize;
|
||||
void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */
|
||||
LIZHUF_DEltX4* const dt = (LIZHUF_DEltX4*)dtPtr;
|
||||
|
||||
LIZHUF_STATIC_ASSERT(sizeof(LIZHUF_DEltX4) == sizeof(LIZHUF_DTable)); /* if compilation fails here, assertion is false */
|
||||
if (maxTableLog > LIZHUF_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);
|
||||
/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
iSize = LIZHUF_readStats(weightList, LIZHUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
|
||||
if (LIZHUF_isError(iSize)) return iSize;
|
||||
|
||||
/* check result */
|
||||
if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
|
||||
|
||||
/* find maxWeight */
|
||||
for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
|
||||
|
||||
/* Get start index of each weight */
|
||||
{ U32 w, nextRankStart = 0;
|
||||
for (w=1; w<maxW+1; w++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += rankStats[w];
|
||||
rankStart[w] = current;
|
||||
}
|
||||
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
|
||||
sizeOfSort = nextRankStart;
|
||||
}
|
||||
|
||||
/* sort symbols by weight */
|
||||
{ U32 s;
|
||||
for (s=0; s<nbSymbols; s++) {
|
||||
U32 const w = weightList[s];
|
||||
U32 const r = rankStart[w]++;
|
||||
sortedSymbol[r].symbol = (BYTE)s;
|
||||
sortedSymbol[r].weight = (BYTE)w;
|
||||
}
|
||||
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
{ U32* const rankVal0 = rankVal[0];
|
||||
{ int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
|
||||
U32 nextRankVal = 0;
|
||||
U32 w;
|
||||
for (w=1; w<maxW+1; w++) {
|
||||
U32 current = nextRankVal;
|
||||
nextRankVal += rankStats[w] << (w+rescale);
|
||||
rankVal0[w] = current;
|
||||
} }
|
||||
{ U32 const minBits = tableLog+1 - maxW;
|
||||
U32 consumed;
|
||||
for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
|
||||
U32* const rankValPtr = rankVal[consumed];
|
||||
U32 w;
|
||||
for (w = 1; w < maxW+1; w++) {
|
||||
rankValPtr[w] = rankVal0[w] >> consumed;
|
||||
} } } }
|
||||
|
||||
LIZHUF_fillDTableX4(dt, maxTableLog,
|
||||
sortedSymbol, sizeOfSort,
|
||||
rankStart0, rankVal, maxW,
|
||||
tableLog+1);
|
||||
|
||||
dtd.tableLog = (BYTE)maxTableLog;
|
||||
dtd.tableType = 1;
|
||||
memcpy(DTable, &dtd, sizeof(dtd));
|
||||
return iSize;
|
||||
}
|
||||
|
||||
|
||||
static U32 LIZHUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const LIZHUF_DEltX4* dt, const U32 dtLog)
|
||||
{
|
||||
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
|
||||
memcpy(op, dt+val, 2);
|
||||
BIT_skipBits(DStream, dt[val].nbBits);
|
||||
return dt[val].length;
|
||||
}
|
||||
|
||||
static U32 LIZHUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const LIZHUF_DEltX4* dt, const U32 dtLog)
|
||||
{
|
||||
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
|
||||
memcpy(op, dt+val, 1);
|
||||
if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
|
||||
else {
|
||||
if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
|
||||
BIT_skipBits(DStream, dt[val].nbBits);
|
||||
if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
|
||||
DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
|
||||
} }
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
|
||||
ptr += LIZHUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
|
||||
if (MEM_64bits() || (LIZHUF_TABLELOG_MAX<=12)) \
|
||||
ptr += LIZHUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
|
||||
|
||||
#define LIZHUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
|
||||
if (MEM_64bits()) \
|
||||
ptr += LIZHUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
|
||||
|
||||
static inline size_t LIZHUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const LIZHUF_DEltX4* const dt, const U32 dtLog)
|
||||
{
|
||||
BYTE* const pStart = p;
|
||||
|
||||
/* up to 8 symbols at a time */
|
||||
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
|
||||
LIZHUF_DECODE_SYMBOLX4_2(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX4_1(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(p, bitDPtr);
|
||||
LIZHUF_DECODE_SYMBOLX4_0(p, bitDPtr);
|
||||
}
|
||||
|
||||
/* closer to end : up to 2 symbols at a time */
|
||||
while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
|
||||
LIZHUF_DECODE_SYMBOLX4_0(p, bitDPtr);
|
||||
|
||||
while (p <= pEnd-2)
|
||||
LIZHUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
|
||||
|
||||
if (p < pEnd)
|
||||
p += LIZHUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
|
||||
|
||||
return p-pStart;
|
||||
}
|
||||
|
||||
|
||||
static size_t LIZHUF_decompress1X4_usingDTable_internal(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
BIT_DStream_t bitD;
|
||||
|
||||
/* Init */
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode;
|
||||
}
|
||||
|
||||
/* decode */
|
||||
{ BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
|
||||
const LIZHUF_DEltX4* const dt = (const LIZHUF_DEltX4*)dtPtr;
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
LIZHUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
|
||||
}
|
||||
|
||||
/* check */
|
||||
if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
|
||||
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X4_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 1) return ERROR(GENERIC);
|
||||
return LIZHUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X4_DCtx (LIZHUF_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = LIZHUF_readDTableX4 (DCtx, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return LIZHUF_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
LIZHUF_CREATE_STATIC_DTABLEX4(DTable, LIZHUF_TABLELOG_MAX);
|
||||
return LIZHUF_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
|
||||
static size_t LIZHUF_decompress4X4_usingDTable_internal(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable+1;
|
||||
const LIZHUF_DEltX4* const dt = (const LIZHUF_DEltX4*)dtPtr;
|
||||
|
||||
/* Init */
|
||||
BIT_DStream_t bitD1;
|
||||
BIT_DStream_t bitD2;
|
||||
BIT_DStream_t bitD3;
|
||||
BIT_DStream_t bitD4;
|
||||
size_t const length1 = MEM_readLE16(istart);
|
||||
size_t const length2 = MEM_readLE16(istart+2);
|
||||
size_t const length3 = MEM_readLE16(istart+4);
|
||||
size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
|
||||
const BYTE* const istart1 = istart + 6; /* jumpTable */
|
||||
const BYTE* const istart2 = istart1 + length1;
|
||||
const BYTE* const istart3 = istart2 + length2;
|
||||
const BYTE* const istart4 = istart3 + length3;
|
||||
size_t const segmentSize = (dstSize+3) / 4;
|
||||
BYTE* const opStart2 = ostart + segmentSize;
|
||||
BYTE* const opStart3 = opStart2 + segmentSize;
|
||||
BYTE* const opStart4 = opStart3 + segmentSize;
|
||||
BYTE* op1 = ostart;
|
||||
BYTE* op2 = opStart2;
|
||||
BYTE* op3 = opStart3;
|
||||
BYTE* op4 = opStart4;
|
||||
U32 endSignal;
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
U32 const dtLog = dtd.tableLog;
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
|
||||
if (LIZHUF_isError(errorCode)) return errorCode; }
|
||||
|
||||
/* 16-32 symbols per loop (4-8 symbols per stream) */
|
||||
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
|
||||
for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX4_1(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX4_1(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX4_1(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX4_1(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX4_2(op4, &bitD4);
|
||||
LIZHUF_DECODE_SYMBOLX4_0(op1, &bitD1);
|
||||
LIZHUF_DECODE_SYMBOLX4_0(op2, &bitD2);
|
||||
LIZHUF_DECODE_SYMBOLX4_0(op3, &bitD3);
|
||||
LIZHUF_DECODE_SYMBOLX4_0(op4, &bitD4);
|
||||
|
||||
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
|
||||
}
|
||||
|
||||
/* check corruption */
|
||||
if (op1 > opStart2) return ERROR(corruption_detected);
|
||||
if (op2 > opStart3) return ERROR(corruption_detected);
|
||||
if (op3 > opStart4) return ERROR(corruption_detected);
|
||||
/* note : op4 already verified within main loop */
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
LIZHUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
|
||||
LIZHUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
|
||||
LIZHUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
|
||||
LIZHUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
{ U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
|
||||
if (!endCheck) return ERROR(corruption_detected); }
|
||||
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_decompress4X4_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = LIZHUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 1) return ERROR(GENERIC);
|
||||
return LIZHUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
|
||||
size_t LIZHUF_decompress4X4_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t hSize = LIZHUF_readDTableX4 (dctx, cSrc, cSrcSize);
|
||||
if (LIZHUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return LIZHUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
LIZHUF_CREATE_STATIC_DTABLEX4(DTable, LIZHUF_TABLELOG_MAX);
|
||||
return LIZHUF_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
|
||||
|
||||
/* ********************************/
|
||||
/* Generic decompression selector */
|
||||
/* ********************************/
|
||||
|
||||
size_t LIZHUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
return dtd.tableType ? LIZHUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
|
||||
LIZHUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const LIZHUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc const dtd = LIZHUF_getDTableDesc(DTable);
|
||||
return dtd.tableType ? LIZHUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
|
||||
LIZHUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
|
||||
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
|
||||
static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
|
||||
{
|
||||
/* single, double, quad */
|
||||
{{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */
|
||||
{{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */
|
||||
{{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
|
||||
{{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
|
||||
{{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
|
||||
{{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
|
||||
{{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
|
||||
{{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
|
||||
{{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
|
||||
{{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
|
||||
{{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
|
||||
{{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
|
||||
{{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
|
||||
{{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */
|
||||
{{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */
|
||||
{{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */
|
||||
};
|
||||
|
||||
/** LIZHUF_selectDecoder() :
|
||||
* Tells which decoder is likely to decode faster,
|
||||
* based on a set of pre-determined metrics.
|
||||
* @return : 0==LIZHUF_decompress4X2, 1==LIZHUF_decompress4X4 .
|
||||
* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
|
||||
U32 LIZHUF_selectDecoder (size_t dstSize, size_t cSrcSize)
|
||||
{
|
||||
/* decoder timing evaluation */
|
||||
U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
|
||||
U32 const D256 = (U32)(dstSize >> 8);
|
||||
U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
|
||||
U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
|
||||
DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
|
||||
|
||||
return DTime1 < DTime0;
|
||||
}
|
||||
|
||||
|
||||
typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
|
||||
|
||||
size_t LIZHUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
static const decompressionAlgo decompress[2] = { LIZHUF_decompress4X2, LIZHUF_decompress4X4 };
|
||||
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
|
||||
if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
|
||||
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
|
||||
|
||||
{ U32 const algoNb = LIZHUF_selectDecoder(dstSize, cSrcSize);
|
||||
return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress4X_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
|
||||
if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
|
||||
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
|
||||
|
||||
{ U32 const algoNb = LIZHUF_selectDecoder(dstSize, cSrcSize);
|
||||
return algoNb ? LIZHUF_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
|
||||
LIZHUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
|
||||
}
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress4X_hufOnly (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected); /* invalid */
|
||||
|
||||
{ U32 const algoNb = LIZHUF_selectDecoder(dstSize, cSrcSize);
|
||||
return algoNb ? LIZHUF_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
|
||||
LIZHUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
|
||||
}
|
||||
}
|
||||
|
||||
size_t LIZHUF_decompress1X_DCtx (LIZHUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
|
||||
if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
|
||||
if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
|
||||
|
||||
{ U32 const algoNb = LIZHUF_selectDecoder(dstSize, cSrcSize);
|
||||
return algoNb ? LIZHUF_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
|
||||
LIZHUF_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
|
||||
}
|
||||
}
|
||||
@@ -1,637 +0,0 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
Copyright (C) 2015-2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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 NOTLIZ_hash4Ptr
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Includes
|
||||
***************************************/
|
||||
#include "liz_compress.h"
|
||||
#include "liz_common.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h> // intptr_t
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#ifdef LIZ_USE_TEST
|
||||
#include "test/lz5_common_test.h"
|
||||
#include "test/lz5_compress_test.h"
|
||||
#else
|
||||
#include "liz_compress_lz5v2.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "liz_compress_lz4.h"
|
||||
#include "huf.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Local Macros
|
||||
***************************************/
|
||||
#define DELTANEXT(p) chainTable[(p) & contentMask]
|
||||
#define LIZ_MINIMAL_HUFF_GAIN(comprSize) (comprSize + (comprSize/8) + 512)
|
||||
#define LIZ_MINIMAL_BLOCK_GAIN(comprSize) (comprSize + (comprSize/32) + 512)
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Local Utils
|
||||
**************************************/
|
||||
int LIZ_versionNumber (void) { return LIZ_VERSION_NUMBER; }
|
||||
int LIZ_compressBound(int isize) { return LIZ_COMPRESSBOUND(isize); }
|
||||
int LIZ_sizeofState_MinLevel() { return LIZ_sizeofState(LIZ_MIN_CLEVEL); }
|
||||
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Hash functions
|
||||
***************************************/
|
||||
#define HASH_UPDATE_LIMIT 8 /* equal to MEM_read64 */
|
||||
static const U32 prime4bytes = 2654435761U;
|
||||
static const U64 prime5bytes = 889523592379ULL;
|
||||
static const U64 prime6bytes = 227718039650203ULL;
|
||||
static const U64 prime7bytes = 58295818150454627ULL;
|
||||
|
||||
#if MINMATCH == 3
|
||||
static const U32 prime3bytes = 506832829U;
|
||||
static U32 LIZ_hash3(U32 u, U32 h) { return (u * prime3bytes) << (32-24) >> (32-h) ; }
|
||||
static size_t LIZ_hash3Ptr(const void* ptr, U32 h) { return LIZ_hash3(MEM_read32(ptr), h); }
|
||||
#endif
|
||||
|
||||
static U32 LIZ_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
|
||||
static size_t LIZ_hash4Ptr(const void* ptr, U32 h) { return LIZ_hash4(MEM_read32(ptr), h); }
|
||||
|
||||
static size_t LIZ_hash5(U64 u, U32 h) { return (size_t)((u * prime5bytes) << (64-40) >> (64-h)) ; }
|
||||
static size_t LIZ_hash5Ptr(const void* p, U32 h) { return LIZ_hash5(MEM_read64(p), h); }
|
||||
|
||||
static size_t LIZ_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; }
|
||||
static size_t LIZ_hash6Ptr(const void* p, U32 h) { return LIZ_hash6(MEM_read64(p), h); }
|
||||
|
||||
static size_t LIZ_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }
|
||||
static size_t LIZ_hash7Ptr(const void* p, U32 h) { return LIZ_hash7(MEM_read64(p), h); }
|
||||
|
||||
static size_t LIZ_hashPtr(const void* p, U32 hBits, U32 mls)
|
||||
{
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
case 4: return LIZ_hash4Ptr(p, hBits);
|
||||
case 5: return LIZ_hash5Ptr(p, hBits);
|
||||
case 6: return LIZ_hash6Ptr(p, hBits);
|
||||
case 7: return LIZ_hash7Ptr(p, hBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Internal functions
|
||||
**************************************/
|
||||
/** LIZ_count_2segments() :
|
||||
* can count match length with `ip` & `match` in 2 different segments.
|
||||
* convention : on reaching mEnd, match count continue starting from iStart
|
||||
*/
|
||||
static size_t LIZ_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
|
||||
{
|
||||
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
|
||||
size_t const matchLength = LIZ_count(ip, match, vEnd);
|
||||
if (match + matchLength != mEnd) return matchLength;
|
||||
return matchLength + LIZ_count(ip+matchLength, iStart, iEnd);
|
||||
}
|
||||
|
||||
|
||||
void LIZ_initBlock(LIZ_stream_t* ctx)
|
||||
{
|
||||
ctx->offset16Ptr = ctx->offset16Base;
|
||||
ctx->offset24Ptr = ctx->offset24Base;
|
||||
ctx->lenPtr = ctx->lenBase;
|
||||
ctx->literalsPtr = ctx->literalsBase;
|
||||
ctx->flagsPtr = ctx->flagsBase;
|
||||
ctx->last_off = LIZ_INIT_LAST_OFFSET; /* reset last offset */
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_writeStream(int useHuff, LIZ_stream_t* ctx, BYTE* streamPtr, uint32_t streamLen, BYTE** op, BYTE* oend)
|
||||
{
|
||||
if (useHuff && streamLen > 1024) {
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
int useHuffBuf;
|
||||
if (*op + 6 > oend) { LIZ_LOG_COMPRESS("*op[%p] + 6 > oend[%p]\n", *op, oend); return -1; }
|
||||
|
||||
useHuffBuf = ((size_t)(oend - (*op + 6)) < LIZHUF_compressBound(streamLen));
|
||||
if (useHuffBuf) {
|
||||
if (streamLen > LIZ_BLOCK_SIZE) { LIZ_LOG_COMPRESS("streamLen[%d] > LIZ_BLOCK_SIZE\n", streamLen); return -1; }
|
||||
ctx->comprStreamLen = (U32)LIZHUF_compress(ctx->huffBase, ctx->huffEnd - ctx->huffBase, streamPtr, streamLen);
|
||||
} else {
|
||||
ctx->comprStreamLen = (U32)LIZHUF_compress(*op + 6, oend - (*op + 6), streamPtr, streamLen);
|
||||
}
|
||||
|
||||
if (!LIZHUF_isError(ctx->comprStreamLen)) {
|
||||
if (ctx->comprStreamLen > 0 && (LIZ_MINIMAL_HUFF_GAIN(ctx->comprStreamLen) < streamLen)) { /* compressible */
|
||||
MEM_writeLE24(*op, streamLen);
|
||||
MEM_writeLE24(*op+3, ctx->comprStreamLen);
|
||||
if (useHuffBuf) {
|
||||
if ((size_t)(oend - (*op + 6)) < ctx->comprStreamLen) { LIZ_LOG_COMPRESS("*op[%p] oend[%p] comprStreamLen[%d]\n", *op, oend, (int)ctx->comprStreamLen); return -1; }
|
||||
memcpy(*op + 6, ctx->huffBase, ctx->comprStreamLen);
|
||||
}
|
||||
*op += ctx->comprStreamLen + 6;
|
||||
LIZ_LOG_COMPRESS("LIZHUF_compress streamLen=%d comprStreamLen=%d\n", (int)streamLen, (int)ctx->comprStreamLen);
|
||||
return 1;
|
||||
} else { LIZ_LOG_COMPRESS("LIZHUF_compress ERROR comprStreamLen=%d streamLen=%d\n", (int)ctx->comprStreamLen, (int)streamLen); }
|
||||
} else { LIZ_LOG_COMPRESS("LIZHUF_compress ERROR %d: %s\n", (int)ctx->comprStreamLen, LIZHUF_getErrorName(ctx->comprStreamLen)); }
|
||||
#else
|
||||
LIZ_LOG_COMPRESS("compiled with LIZ_NO_HUFFMAN\n");
|
||||
(void)ctx;
|
||||
return -1;
|
||||
#endif
|
||||
} else ctx->comprStreamLen = 0;
|
||||
|
||||
if (*op + 3 + streamLen > oend) { LIZ_LOG_COMPRESS("*op[%p] + 3 + streamLen[%d] > oend[%p]\n", *op, streamLen, oend); return -1; }
|
||||
MEM_writeLE24(*op, streamLen);
|
||||
*op += 3;
|
||||
memcpy(*op, streamPtr, streamLen);
|
||||
*op += streamLen;
|
||||
LIZ_LOG_COMPRESS("Uncompressed streamLen=%d\n", (int)streamLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_writeBlock(LIZ_stream_t* ctx, const BYTE* ip, uint32_t inputSize, BYTE** op, BYTE* oend)
|
||||
{
|
||||
int res;
|
||||
uint32_t flagsLen = (uint32_t)(ctx->flagsPtr - ctx->flagsBase);
|
||||
uint32_t literalsLen = (uint32_t)(ctx->literalsPtr - ctx->literalsBase);
|
||||
uint32_t lenLen = (uint32_t)(ctx->lenPtr - ctx->lenBase);
|
||||
uint32_t offset16Len = (uint32_t)(ctx->offset16Ptr - ctx->offset16Base);
|
||||
uint32_t offset24Len = (uint32_t)(ctx->offset24Ptr - ctx->offset24Base);
|
||||
uint32_t sum = flagsLen + literalsLen + lenLen + offset16Len + offset24Len;
|
||||
#ifdef LIZ_USE_LOGS
|
||||
uint32_t comprFlagsLen, comprLiteralsLen;
|
||||
#endif
|
||||
|
||||
BYTE* start = *op;
|
||||
|
||||
if ((literalsLen < WILDCOPYLENGTH) || (sum+5*3+1 > inputSize)) goto _write_uncompressed;
|
||||
|
||||
*start = 0;
|
||||
*op += 1;
|
||||
|
||||
res = LIZ_writeStream(0, ctx, ctx->lenBase, lenLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZ_FLAG_LEN);
|
||||
|
||||
res = LIZ_writeStream(ctx->huffType&LIZ_FLAG_OFFSET16, ctx, ctx->offset16Base, offset16Len, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZ_FLAG_OFFSET16);
|
||||
|
||||
res = LIZ_writeStream(ctx->huffType&LIZ_FLAG_OFFSET24, ctx, ctx->offset24Base, offset24Len, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZ_FLAG_OFFSET24);
|
||||
|
||||
res = LIZ_writeStream(ctx->huffType&LIZ_FLAG_FLAGS, ctx, ctx->flagsBase, flagsLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZ_FLAG_FLAGS);
|
||||
#ifdef LIZ_USE_LOGS
|
||||
comprFlagsLen = ctx->comprStreamLen;
|
||||
#endif
|
||||
|
||||
res = LIZ_writeStream(ctx->huffType&LIZ_FLAG_LITERALS, ctx, ctx->literalsBase, literalsLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZ_FLAG_LITERALS);
|
||||
#ifdef LIZ_USE_LOGS
|
||||
comprLiteralsLen = ctx->comprStreamLen;
|
||||
sum = (int)(*op-start);
|
||||
#endif
|
||||
|
||||
if (LIZ_MINIMAL_BLOCK_GAIN((uint32_t)(*op-start)) > inputSize) goto _write_uncompressed;
|
||||
|
||||
LIZ_LOG_COMPRESS("%d: total=%d block=%d flagsLen[%.2f%%]=%d comprFlagsLen[%.2f%%]=%d literalsLen[%.2f%%]=%d comprLiteralsLen[%.2f%%]=%d lenLen=%d offset16Len[%.2f%%]=%d offset24Len[%.2f%%]=%d\n", (int)(ip - ctx->srcBase),
|
||||
(int)(*op - ctx->destBase), sum, (flagsLen*100.0)/sum, flagsLen, (comprFlagsLen*100.0)/sum, comprFlagsLen, (literalsLen*100.0)/sum, literalsLen, (comprLiteralsLen*100.0)/sum, comprLiteralsLen,
|
||||
lenLen, (offset16Len*100.0)/sum, offset16Len, (offset24Len*100.0)/sum, offset24Len);
|
||||
return 0;
|
||||
|
||||
_write_uncompressed:
|
||||
LIZ_LOG_COMPRESS("%d: total=%d block=%d UNCOMPRESSED inputSize=%u outSize=%d\n", (int)(ip - ctx->srcBase),
|
||||
(int)(*op - ctx->destBase), (int)(*op-start), inputSize, (int)(oend-start));
|
||||
if ((uint32_t)(oend - start) < inputSize + 4) goto _output_error;
|
||||
*start = LIZ_FLAG_UNCOMPRESSED;
|
||||
*op = start + 1;
|
||||
MEM_writeLE24(*op, inputSize);
|
||||
*op += 3;
|
||||
memcpy(*op, ip, inputSize);
|
||||
*op += inputSize;
|
||||
return 0;
|
||||
|
||||
_output_error:
|
||||
LIZ_LOG_COMPRESS("LIZ_writeBlock ERROR size=%d/%d flagsLen=%d literalsLen=%d lenLen=%d offset16Len=%d offset24Len=%d\n", (int)(*op-start), (int)(oend-start), flagsLen, literalsLen, lenLen, offset16Len, offset24Len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_encodeSequence (
|
||||
LIZ_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor,
|
||||
size_t matchLength,
|
||||
const BYTE* const match)
|
||||
{
|
||||
#ifdef USE_LZ4_ONLY
|
||||
return LIZ_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);
|
||||
#else
|
||||
if (ctx->params.decompressType == LIZ_coderwords_LZ4)
|
||||
return LIZ_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);
|
||||
|
||||
return LIZ_encodeSequence_LZ5v2(ctx, ip, anchor, matchLength, match);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_encodeLastLiterals (
|
||||
LIZ_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor)
|
||||
{
|
||||
LIZ_LOG_COMPRESS("LIZ_encodeLastLiterals LIZ_coderwords_LZ4=%d\n", ctx->params.decompressType == LIZ_coderwords_LZ4);
|
||||
#ifdef USE_LZ4_ONLY
|
||||
return LIZ_encodeLastLiterals_LZ4(ctx, ip, anchor);
|
||||
#else
|
||||
if (ctx->params.decompressType == LIZ_coderwords_LZ4)
|
||||
return LIZ_encodeLastLiterals_LZ4(ctx, ip, anchor);
|
||||
|
||||
return LIZ_encodeLastLiterals_LZ5v2(ctx, ip, anchor);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Include parsers
|
||||
**************************************/
|
||||
#include "liz_parser_hashchain.h"
|
||||
#include "liz_parser_nochain.h"
|
||||
#include "liz_parser_fast.h"
|
||||
#include "liz_parser_fastsmall.h"
|
||||
#include "liz_parser_fastbig.h"
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#include "liz_parser_optimal.h"
|
||||
#include "liz_parser_lowestprice.h"
|
||||
#include "liz_parser_pricefast.h"
|
||||
#endif
|
||||
|
||||
|
||||
int LIZ_verifyCompressionLevel(int compressionLevel)
|
||||
{
|
||||
(void)LIZ_hashPtr;
|
||||
(void)LIZ_wildCopy16;
|
||||
if (compressionLevel > LIZ_MAX_CLEVEL) compressionLevel = LIZ_MAX_CLEVEL;
|
||||
if (compressionLevel < LIZ_MIN_CLEVEL) compressionLevel = LIZ_DEFAULT_CLEVEL;
|
||||
return compressionLevel;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_sizeofState(int compressionLevel)
|
||||
{
|
||||
LIZ_parameters params;
|
||||
U32 hashTableSize, chainTableSize;
|
||||
|
||||
compressionLevel = LIZ_verifyCompressionLevel(compressionLevel);
|
||||
params = LIZ_defaultParameters[compressionLevel - LIZ_MIN_CLEVEL];
|
||||
// hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));
|
||||
hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));
|
||||
chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));
|
||||
|
||||
return sizeof(LIZ_stream_t) + hashTableSize + chainTableSize + LIZ_COMPRESS_ADD_BUF + (int)LIZ_COMPRESS_ADD_HUF;
|
||||
}
|
||||
|
||||
|
||||
static void LIZ_init(LIZ_stream_t* ctx, const BYTE* start)
|
||||
{
|
||||
MEM_INIT((void*)ctx->hashTable, 0, ctx->hashTableSize);
|
||||
MEM_INIT(ctx->chainTable, 0x01, ctx->chainTableSize);
|
||||
// printf("memset hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\n", ctx->hashTable, ((BYTE*)ctx->hashTable) + ctx->hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+ctx->chainTableSize);
|
||||
ctx->nextToUpdate = LIZ_DICT_SIZE;
|
||||
ctx->base = start - LIZ_DICT_SIZE;
|
||||
ctx->end = start;
|
||||
ctx->dictBase = start - LIZ_DICT_SIZE;
|
||||
ctx->dictLimit = LIZ_DICT_SIZE;
|
||||
ctx->lowLimit = LIZ_DICT_SIZE;
|
||||
ctx->last_off = LIZ_INIT_LAST_OFFSET;
|
||||
ctx->litSum = 0;
|
||||
}
|
||||
|
||||
|
||||
/* if ctx==NULL memory is allocated and returned as value */
|
||||
LIZ_stream_t* LIZ_initStream(LIZ_stream_t* ctx, int compressionLevel)
|
||||
{
|
||||
LIZ_parameters params;
|
||||
U32 hashTableSize, chainTableSize;
|
||||
void *tempPtr;
|
||||
|
||||
compressionLevel = LIZ_verifyCompressionLevel(compressionLevel);
|
||||
params = LIZ_defaultParameters[compressionLevel - LIZ_MIN_CLEVEL];
|
||||
// hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));
|
||||
hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));
|
||||
chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
ctx = (LIZ_stream_t*)malloc(sizeof(LIZ_stream_t) + hashTableSize + chainTableSize + LIZ_COMPRESS_ADD_BUF + LIZ_COMPRESS_ADD_HUF);
|
||||
if (!ctx) { printf("ERROR: Cannot allocate %d MB (compressionLevel=%d)\n", (int)(sizeof(LIZ_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel); return 0; }
|
||||
LIZ_LOG_COMPRESS("Allocated %d MB (compressionLevel=%d)\n", (int)(sizeof(LIZ_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel);
|
||||
ctx->allocatedMemory = sizeof(LIZ_stream_t) + hashTableSize + chainTableSize + LIZ_COMPRESS_ADD_BUF + (U32)LIZ_COMPRESS_ADD_HUF;
|
||||
// printf("malloc from=%p to=%p hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\n", ctx, ((BYTE*)ctx)+sizeof(LIZ_stream_t) + hashTableSize + chainTableSize, ctx->hashTable, ((BYTE*)ctx->hashTable) + hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+chainTableSize);
|
||||
}
|
||||
|
||||
tempPtr = ctx;
|
||||
ctx->hashTable = (U32*)(tempPtr) + sizeof(LIZ_stream_t)/4;
|
||||
ctx->hashTableSize = hashTableSize;
|
||||
ctx->chainTable = ctx->hashTable + hashTableSize/4;
|
||||
ctx->chainTableSize = chainTableSize;
|
||||
ctx->params = params;
|
||||
ctx->compressionLevel = (unsigned)compressionLevel;
|
||||
if (compressionLevel < 30)
|
||||
ctx->huffType = 0;
|
||||
else
|
||||
ctx->huffType = LIZ_FLAG_LITERALS + LIZ_FLAG_FLAGS; // + LIZ_FLAG_OFFSET16 + LIZ_FLAG_OFFSET24;
|
||||
|
||||
ctx->literalsBase = (BYTE*)ctx->hashTable + ctx->hashTableSize + ctx->chainTableSize;
|
||||
ctx->flagsBase = ctx->literalsEnd = ctx->literalsBase + LIZ_BLOCK_SIZE_PAD;
|
||||
ctx->lenBase = ctx->flagsEnd = ctx->flagsBase + LIZ_BLOCK_SIZE_PAD;
|
||||
ctx->offset16Base = ctx->lenEnd = ctx->lenBase + LIZ_BLOCK_SIZE_PAD;
|
||||
ctx->offset24Base = ctx->offset16End = ctx->offset16Base + LIZ_BLOCK_SIZE_PAD;
|
||||
ctx->huffBase = ctx->offset24End = ctx->offset24Base + LIZ_BLOCK_SIZE_PAD;
|
||||
ctx->huffEnd = ctx->huffBase + LIZ_COMPRESS_ADD_HUF;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LIZ_stream_t* LIZ_createStream(int compressionLevel)
|
||||
{
|
||||
LIZ_stream_t* ctx = LIZ_initStream(NULL, compressionLevel);
|
||||
// if (ctx) printf("LIZ_createStream ctx=%p ctx->compressionLevel=%d\n", ctx, ctx->compressionLevel);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
/* initialization */
|
||||
LIZ_stream_t* LIZ_resetStream(LIZ_stream_t* ctx, int compressionLevel)
|
||||
{
|
||||
size_t wanted = LIZ_sizeofState(compressionLevel);
|
||||
|
||||
// printf("LIZ_resetStream ctx=%p cLevel=%d have=%d wanted=%d min=%d\n", ctx, compressionLevel, (int)have, (int)wanted, (int)sizeof(LIZ_stream_t));
|
||||
if (ctx->allocatedMemory < wanted)
|
||||
{
|
||||
// printf("REALLOC ctx=%p cLevel=%d have=%d wanted=%d\n", ctx, compressionLevel, (int)have, (int)wanted);
|
||||
LIZ_freeStream(ctx);
|
||||
ctx = LIZ_createStream(compressionLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIZ_initStream(ctx, compressionLevel);
|
||||
}
|
||||
|
||||
if (ctx) ctx->base = NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_freeStream(LIZ_stream_t* ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
// printf("LIZ_freeStream ctx=%p ctx->compressionLevel=%d\n", ctx, ctx->compressionLevel);
|
||||
free(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_loadDict(LIZ_stream_t* LIZ_streamPtr, const char* dictionary, int dictSize)
|
||||
{
|
||||
LIZ_stream_t* ctxPtr = (LIZ_stream_t*) LIZ_streamPtr;
|
||||
if (dictSize > LIZ_DICT_SIZE) {
|
||||
dictionary += dictSize - LIZ_DICT_SIZE;
|
||||
dictSize = LIZ_DICT_SIZE;
|
||||
}
|
||||
LIZ_init (ctxPtr, (const BYTE*)dictionary);
|
||||
if (dictSize >= HASH_UPDATE_LIMIT) LIZ_Insert (ctxPtr, (const BYTE*)dictionary + (dictSize - (HASH_UPDATE_LIMIT-1)));
|
||||
ctxPtr->end = (const BYTE*)dictionary + dictSize;
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
static void LIZ_setExternalDict(LIZ_stream_t* ctxPtr, const BYTE* newBlock)
|
||||
{
|
||||
if (ctxPtr->end >= ctxPtr->base + HASH_UPDATE_LIMIT) LIZ_Insert (ctxPtr, ctxPtr->end - (HASH_UPDATE_LIMIT-1)); /* Referencing remaining dictionary content */
|
||||
/* Only one memory segment for extDict, so any previous extDict is lost at this stage */
|
||||
ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
|
||||
ctxPtr->dictBase = ctxPtr->base;
|
||||
ctxPtr->base = newBlock - ctxPtr->dictLimit;
|
||||
ctxPtr->end = newBlock;
|
||||
ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
|
||||
}
|
||||
|
||||
|
||||
/* dictionary saving */
|
||||
int LIZ_saveDict (LIZ_stream_t* LIZ_streamPtr, char* safeBuffer, int dictSize)
|
||||
{
|
||||
LIZ_stream_t* const ctx = (LIZ_stream_t*)LIZ_streamPtr;
|
||||
int const prefixSize = (int)(ctx->end - (ctx->base + ctx->dictLimit));
|
||||
//printf("LIZ_saveDict dictSize=%d prefixSize=%d ctx->dictLimit=%d\n", dictSize, prefixSize, (int)ctx->dictLimit);
|
||||
if (dictSize > LIZ_DICT_SIZE) dictSize = LIZ_DICT_SIZE;
|
||||
if (dictSize < 4) dictSize = 0;
|
||||
if (dictSize > prefixSize) dictSize = prefixSize;
|
||||
memmove(safeBuffer, ctx->end - dictSize, dictSize);
|
||||
{ U32 const endIndex = (U32)(ctx->end - ctx->base);
|
||||
ctx->end = (const BYTE*)safeBuffer + dictSize;
|
||||
ctx->base = ctx->end - endIndex;
|
||||
ctx->dictLimit = endIndex - dictSize;
|
||||
ctx->lowLimit = endIndex - dictSize;
|
||||
if (ctx->nextToUpdate < ctx->dictLimit) ctx->nextToUpdate = ctx->dictLimit;
|
||||
}
|
||||
//printf("2LIZ_saveDict dictSize=%d\n", dictSize);
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
FORCE_INLINE int LIZ_compress_generic (
|
||||
void* ctxvoid,
|
||||
const char* source,
|
||||
char* dest,
|
||||
int inputSize,
|
||||
int maxOutputSize)
|
||||
{
|
||||
LIZ_stream_t* ctx = (LIZ_stream_t*) ctxvoid;
|
||||
size_t dictSize = (size_t)(ctx->end - ctx->base) - ctx->dictLimit;
|
||||
const BYTE* ip = (const BYTE*) source;
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + maxOutputSize;
|
||||
int res;
|
||||
|
||||
(void)dictSize;
|
||||
LIZ_LOG_COMPRESS("LIZ_compress_generic source=%p inputSize=%d dest=%p maxOutputSize=%d cLevel=%d dictBase=%p dictSize=%d\n", source, inputSize, dest, maxOutputSize, ctx->compressionLevel, ctx->dictBase, (int)dictSize);
|
||||
*op++ = (BYTE)ctx->compressionLevel;
|
||||
maxOutputSize--; // can be lower than 0
|
||||
ctx->end += inputSize;
|
||||
ctx->srcBase = ctx->off24pos = ip;
|
||||
ctx->destBase = (BYTE*)dest;
|
||||
|
||||
while (inputSize > 0)
|
||||
{
|
||||
int inputPart = MIN(LIZ_BLOCK_SIZE, inputSize);
|
||||
|
||||
if (ctx->huffType) LIZ_rescaleFreqs(ctx);
|
||||
LIZ_initBlock(ctx);
|
||||
ctx->diffBase = ip;
|
||||
|
||||
switch(ctx->params.parserType)
|
||||
{
|
||||
default:
|
||||
case LIZ_parser_fastSmall:
|
||||
res = LIZ_compress_fastSmall(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_fast:
|
||||
res = LIZ_compress_fast(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_noChain:
|
||||
res = LIZ_compress_noChain(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_hashChain:
|
||||
res = LIZ_compress_hashChain(ctx, ip, ip+inputPart); break;
|
||||
#ifndef USE_LZ4_ONLY
|
||||
case LIZ_parser_fastBig:
|
||||
res = LIZ_compress_fastBig(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_priceFast:
|
||||
res = LIZ_compress_priceFast(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_lowestPrice:
|
||||
res = LIZ_compress_lowestPrice(ctx, ip, ip+inputPart); break;
|
||||
case LIZ_parser_optimalPrice:
|
||||
case LIZ_parser_optimalPriceBT:
|
||||
res = LIZ_compress_optimalPrice(ctx, ip, ip+inputPart); break;
|
||||
#else
|
||||
case LIZ_parser_priceFast:
|
||||
case LIZ_parser_lowestPrice:
|
||||
case LIZ_parser_optimalPrice:
|
||||
case LIZ_parser_optimalPriceBT:
|
||||
res = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LIZ_LOG_COMPRESS("LIZ_compress_generic res=%d inputPart=%d \n", res, inputPart);
|
||||
if (res <= 0) return res;
|
||||
|
||||
if (LIZ_writeBlock(ctx, ip, inputPart, &op, oend)) goto _output_error;
|
||||
|
||||
ip += inputPart;
|
||||
inputSize -= inputPart;
|
||||
LIZ_LOG_COMPRESS("LIZ_compress_generic in=%d out=%d\n", (int)(ip-(const BYTE*)source), (int)(op-(BYTE*)dest));
|
||||
}
|
||||
|
||||
LIZ_LOG_COMPRESS("LIZ_compress_generic total=%d\n", (int)(op-(BYTE*)dest));
|
||||
return (int)(op-(BYTE*)dest);
|
||||
_output_error:
|
||||
LIZ_LOG_COMPRESS("LIZ_compress_generic ERROR\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_compress_continue (LIZ_stream_t* ctxPtr,
|
||||
const char* source, char* dest,
|
||||
int inputSize, int maxOutputSize)
|
||||
{
|
||||
/* auto-init if forgotten */
|
||||
if (ctxPtr->base == NULL) LIZ_init (ctxPtr, (const BYTE*) source);
|
||||
|
||||
/* Check overflow */
|
||||
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
|
||||
size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
|
||||
if (dictSize > LIZ_DICT_SIZE) dictSize = LIZ_DICT_SIZE;
|
||||
LIZ_loadDict((LIZ_stream_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
|
||||
}
|
||||
|
||||
/* Check if blocks follow each other */
|
||||
if ((const BYTE*)source != ctxPtr->end)
|
||||
LIZ_setExternalDict(ctxPtr, (const BYTE*)source);
|
||||
|
||||
/* Check overlapping input/dictionary space */
|
||||
{ const BYTE* sourceEnd = (const BYTE*) source + inputSize;
|
||||
const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
|
||||
const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
|
||||
if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) {
|
||||
if (sourceEnd > dictEnd) sourceEnd = dictEnd;
|
||||
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
|
||||
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return LIZ_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize);
|
||||
}
|
||||
|
||||
|
||||
int LIZ_compress_extState (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
LIZ_stream_t* ctx = (LIZ_stream_t*) state;
|
||||
if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
|
||||
|
||||
/* initialize stream */
|
||||
LIZ_initStream(ctx, compressionLevel);
|
||||
LIZ_init ((LIZ_stream_t*)state, (const BYTE*)src);
|
||||
|
||||
return LIZ_compress_generic (state, src, dst, srcSize, maxDstSize);
|
||||
}
|
||||
|
||||
|
||||
int LIZ_compress(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
int cSize;
|
||||
LIZ_stream_t* statePtr = LIZ_createStream(compressionLevel);
|
||||
|
||||
if (!statePtr) return 0;
|
||||
cSize = LIZ_compress_extState(statePtr, src, dst, srcSize, maxDstSize, compressionLevel);
|
||||
|
||||
LIZ_freeStream(statePtr);
|
||||
return cSize;
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Level1 functions
|
||||
**************************************/
|
||||
int LIZ_compress_extState_MinLevel(void* state, const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
return LIZ_compress_extState(state, source, dest, inputSize, maxOutputSize, LIZ_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
int LIZ_compress_MinLevel(const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
return LIZ_compress(source, dest, inputSize, maxOutputSize, LIZ_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
LIZ_stream_t* LIZ_createStream_MinLevel(void)
|
||||
{
|
||||
return LIZ_createStream(LIZ_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
LIZ_stream_t* LIZ_resetStream_MinLevel(LIZ_stream_t* LIZ_stream)
|
||||
{
|
||||
return LIZ_resetStream (LIZ_stream, LIZ_MIN_CLEVEL);
|
||||
}
|
||||
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
Copyright (C) 2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
//#define LIZ_STATS 1 // 0=simple stats, 1=more, 2=full
|
||||
#ifdef LIZ_STATS
|
||||
#include "test/lz5_stats.h"
|
||||
#endif
|
||||
#include "liz_compress.h"
|
||||
#include "liz_decompress.h"
|
||||
#include "liz_common.h"
|
||||
#include <stdio.h> // printf
|
||||
#include <stdint.h> // intptr_t
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Local Structures and types
|
||||
**************************************/
|
||||
typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
|
||||
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
|
||||
|
||||
#include "liz_decompress_lz4.h"
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#ifdef LIZ_USE_TEST
|
||||
#include "test/lz5_common_test.h"
|
||||
#include "test/lz5_decompress_test.h"
|
||||
#else
|
||||
#include "liz_decompress_lz5v2.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "huf.h"
|
||||
|
||||
|
||||
/*-*****************************
|
||||
* Decompression functions
|
||||
*******************************/
|
||||
|
||||
FORCE_INLINE size_t LIZ_readStream(int flag, const BYTE** ip, const BYTE* const iend, BYTE* op, BYTE* const oend, const BYTE** streamPtr, const BYTE** streamEnd, int streamFlag)
|
||||
{
|
||||
if (!flag) {
|
||||
if (*ip > iend - 3) return 0;
|
||||
*streamPtr = *ip + 3;
|
||||
*streamEnd = *streamPtr + MEM_readLE24(*ip);
|
||||
if (*streamEnd < *streamPtr) return 0;
|
||||
*ip = *streamEnd;
|
||||
#ifdef LIZ_STATS
|
||||
uncompr_stream[streamFlag] += *streamEnd-*streamPtr;
|
||||
#else
|
||||
(void)streamFlag;
|
||||
#endif
|
||||
return 1;
|
||||
} else {
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
size_t res, streamLen, comprStreamLen;
|
||||
|
||||
if (*ip > iend - 6) return 0;
|
||||
streamLen = MEM_readLE24(*ip);
|
||||
comprStreamLen = MEM_readLE24(*ip + 3);
|
||||
|
||||
// printf("LIZ_readStream ip=%p iout=%p iend=%p streamLen=%d comprStreamLen=%d\n", *ip, *ip + 6 + comprStreamLen, iend, (int)streamLen, (int)comprStreamLen);
|
||||
|
||||
if ((op > oend - streamLen) || (*ip + comprStreamLen > iend - 6)) return 0;
|
||||
res = LIZHUF_decompress(op, streamLen, *ip + 6, comprStreamLen);
|
||||
if (LIZHUF_isError(res) || (res != streamLen)) return 0;
|
||||
|
||||
*ip += comprStreamLen + 6;
|
||||
*streamPtr = op;
|
||||
*streamEnd = *streamPtr + streamLen;
|
||||
#ifdef LIZ_STATS
|
||||
compr_stream[streamFlag] += comprStreamLen + 6;
|
||||
decompr_stream[streamFlag] += *streamEnd-*streamPtr;
|
||||
#endif
|
||||
return 1;
|
||||
#else
|
||||
fprintf(stderr, "compiled with LIZ_NO_HUFFMAN\n");
|
||||
(void)op; (void)oend;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_decompress_generic(
|
||||
const char* source,
|
||||
char* const dest,
|
||||
int inputSize,
|
||||
int outputSize, /* this value is the max size of Output Buffer. */
|
||||
int partialDecoding, /* full, partial */
|
||||
int targetOutputSize, /* only used if partialDecoding==partial */
|
||||
int dict, /* noDict, withPrefix64k, usingExtDict */
|
||||
const BYTE* const lowPrefix, /* == dest if dict == noDict */
|
||||
const BYTE* const dictStart, /* only if dict==usingExtDict */
|
||||
const size_t dictSize /* note : = 0 if noDict */
|
||||
)
|
||||
{
|
||||
/* Local Variables */
|
||||
const BYTE* ip = (const BYTE*) source, *istart = (const BYTE*) source;
|
||||
const BYTE* const iend = ip + inputSize;
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + outputSize;
|
||||
BYTE* oexit = op + targetOutputSize;
|
||||
LIZ_parameters params;
|
||||
LIZ_dstream_t ctx;
|
||||
BYTE* decompFlagsBase, *decompOff24Base, *decompOff16Base, *decompLiteralsBase = NULL;
|
||||
int res, compressionLevel;
|
||||
|
||||
if (inputSize < 1) { LIZ_LOG_DECOMPRESS("inputSize=%d outputSize=%d targetOutputSize=%d partialDecoding=%d\n", inputSize, outputSize, targetOutputSize, partialDecoding); return 0; }
|
||||
|
||||
compressionLevel = *ip++;
|
||||
|
||||
if (compressionLevel < LIZ_MIN_CLEVEL || compressionLevel > LIZ_MAX_CLEVEL) {
|
||||
LIZ_LOG_DECOMPRESS("ERROR LIZ_decompress_generic inputSize=%d compressionLevel=%d\n", inputSize, compressionLevel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LIZ_LOG_DECOMPRESS("LIZ_decompress_generic ip=%p inputSize=%d targetOutputSize=%d dest=%p outputSize=%d cLevel=%d dict=%d dictSize=%d dictStart=%p partialDecoding=%d\n", ip, inputSize, targetOutputSize, dest, outputSize, compressionLevel, dict, (int)dictSize, dictStart, partialDecoding);
|
||||
|
||||
decompLiteralsBase = (BYTE*)malloc(4*LIZ_LIZHUF_BLOCK_SIZE);
|
||||
if (!decompLiteralsBase) return -1;
|
||||
decompFlagsBase = decompLiteralsBase + LIZ_LIZHUF_BLOCK_SIZE;
|
||||
decompOff24Base = decompFlagsBase + LIZ_LIZHUF_BLOCK_SIZE;
|
||||
decompOff16Base = decompOff24Base + LIZ_LIZHUF_BLOCK_SIZE;
|
||||
|
||||
#ifdef LIZ_STATS
|
||||
init_stats();
|
||||
#endif
|
||||
(void)istart;
|
||||
|
||||
while (ip < iend)
|
||||
{
|
||||
res = *ip++;
|
||||
if (res == LIZ_FLAG_UNCOMPRESSED) /* uncompressed */
|
||||
{
|
||||
uint32_t length;
|
||||
if (ip > iend - 3) { LIZ_LOG_DECOMPRESS("UNCOMPRESSED ip[%p] > iend[%p] - 3\n", ip, iend); goto _output_error; }
|
||||
length = MEM_readLE24(ip);
|
||||
ip += 3;
|
||||
// printf("%d: total=%d block=%d UNCOMPRESSED op=%p oexit=%p oend=%p\n", (int)(op-(BYTE*)dest) ,(int)(ip-istart), length, op, oexit, oend);
|
||||
if (ip + length > iend || op + length > oend) { LIZ_LOG_DECOMPRESS("UNCOMPRESSED ip[%p]+length[%d] > iend[%p]\n", ip, length, iend); goto _output_error; }
|
||||
memcpy(op, ip, length);
|
||||
op += length;
|
||||
ip += length;
|
||||
if ((partialDecoding) && (op >= oexit)) break;
|
||||
#ifdef LIZ_STATS
|
||||
uncompr_stream[LIZ_STREAM_UNCOMPRESSED] += length;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (res&LIZ_FLAG_LEN) {
|
||||
LIZ_LOG_DECOMPRESS("res=%d\n", res); goto _output_error;
|
||||
}
|
||||
|
||||
if (ip > iend - 5*3) goto _output_error;
|
||||
ctx.lenPtr = (const BYTE*)ip + 3;
|
||||
ctx.lenEnd = ctx.lenPtr + MEM_readLE24(ip);
|
||||
if (ctx.lenEnd < ctx.lenPtr || (ctx.lenEnd > iend - 3)) goto _output_error;
|
||||
#ifdef LIZ_STATS
|
||||
uncompr_stream[LIZ_STREAM_LEN] += ctx.lenEnd-ctx.lenPtr + 3;
|
||||
#endif
|
||||
ip = ctx.lenEnd;
|
||||
|
||||
{ size_t streamLen;
|
||||
#ifdef LIZ_USE_LOGS
|
||||
const BYTE* ipos;
|
||||
size_t comprFlagsLen, comprLiteralsLen, total;
|
||||
#endif
|
||||
streamLen = LIZ_readStream(res&LIZ_FLAG_OFFSET16, &ip, iend, decompOff16Base, decompOff16Base + LIZ_LIZHUF_BLOCK_SIZE, &ctx.offset16Ptr, &ctx.offset16End, LIZ_STREAM_OFFSET16);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
|
||||
streamLen = LIZ_readStream(res&LIZ_FLAG_OFFSET24, &ip, iend, decompOff24Base, decompOff24Base + LIZ_LIZHUF_BLOCK_SIZE, &ctx.offset24Ptr, &ctx.offset24End, LIZ_STREAM_OFFSET24);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
|
||||
#ifdef LIZ_USE_LOGS
|
||||
ipos = ip;
|
||||
streamLen = LIZ_readStream(res&LIZ_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZ_LIZHUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZ_STREAM_FLAGS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
streamLen = (size_t)(ctx.flagsEnd-ctx.flagsPtr);
|
||||
comprFlagsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);
|
||||
ipos = ip;
|
||||
#else
|
||||
streamLen = LIZ_readStream(res&LIZ_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZ_LIZHUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZ_STREAM_FLAGS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
#endif
|
||||
|
||||
streamLen = LIZ_readStream(res&LIZ_FLAG_LITERALS, &ip, iend, decompLiteralsBase, decompLiteralsBase + LIZ_LIZHUF_BLOCK_SIZE, &ctx.literalsPtr, &ctx.literalsEnd, LIZ_STREAM_LITERALS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
#ifdef LIZ_USE_LOGS
|
||||
streamLen = (size_t)(ctx.literalsEnd-ctx.literalsPtr);
|
||||
comprLiteralsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);
|
||||
total = (size_t)(ip-(ctx.lenEnd-1));
|
||||
#endif
|
||||
|
||||
if (ip > iend) goto _output_error;
|
||||
|
||||
LIZ_LOG_DECOMPRESS("%d: total=%d block=%d flagsLen=%d(HUF=%d) literalsLen=%d(HUF=%d) offset16Len=%d offset24Len=%d lengthsLen=%d \n", (int)(op-(BYTE*)dest) ,(int)(ip-istart), (int)total,
|
||||
(int)(ctx.flagsEnd-ctx.flagsPtr), (int)comprFlagsLen, (int)(ctx.literalsEnd-ctx.literalsPtr), (int)comprLiteralsLen,
|
||||
(int)(ctx.offset16End-ctx.offset16Ptr), (int)(ctx.offset24End-ctx.offset24Ptr), (int)(ctx.lenEnd-ctx.lenPtr));
|
||||
}
|
||||
|
||||
ctx.last_off = -LIZ_INIT_LAST_OFFSET;
|
||||
params = LIZ_defaultParameters[compressionLevel - LIZ_MIN_CLEVEL];
|
||||
if (params.decompressType == LIZ_coderwords_LZ4)
|
||||
res = LIZ_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
else
|
||||
#ifdef USE_LZ4_ONLY
|
||||
res = LIZ_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
#else
|
||||
res = LIZ_decompress_LZ5v2(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
#endif
|
||||
LIZ_LOG_DECOMPRESS("LIZ_decompress_generic res=%d inputSize=%d\n", res, (int)(ctx.literalsEnd-ctx.lenEnd));
|
||||
|
||||
if (res <= 0) { free(decompLiteralsBase); return res; }
|
||||
|
||||
op += res;
|
||||
outputSize -= res;
|
||||
if ((partialDecoding) && (op >= oexit)) break;
|
||||
}
|
||||
|
||||
#ifdef LIZ_STATS
|
||||
print_stats();
|
||||
#endif
|
||||
|
||||
LIZ_LOG_DECOMPRESS("LIZ_decompress_generic total=%d\n", (int)(op-(BYTE*)dest));
|
||||
free(decompLiteralsBase);
|
||||
return (int)(op-(BYTE*)dest);
|
||||
|
||||
_output_error:
|
||||
LIZ_LOG_DECOMPRESS("LIZ_decompress_generic ERROR\n");
|
||||
free(decompLiteralsBase);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int LIZ_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
|
||||
{
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxDecompressedSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
|
||||
}
|
||||
|
||||
int LIZ_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
|
||||
{
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxDecompressedSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*===== streaming decompression functions =====*/
|
||||
|
||||
|
||||
/*
|
||||
* If you prefer dynamic allocation methods,
|
||||
* LIZ_createStreamDecode()
|
||||
* provides a pointer (void*) towards an initialized LIZ_streamDecode_t structure.
|
||||
*/
|
||||
LIZ_streamDecode_t* LIZ_createStreamDecode(void)
|
||||
{
|
||||
LIZ_streamDecode_t* lz5s = (LIZ_streamDecode_t*) ALLOCATOR(1, sizeof(LIZ_streamDecode_t));
|
||||
(void)LIZ_count; /* unused function 'LIZ_count' */
|
||||
return lz5s;
|
||||
}
|
||||
|
||||
int LIZ_freeStreamDecode (LIZ_streamDecode_t* LIZ_stream)
|
||||
{
|
||||
FREEMEM(LIZ_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* LIZ_setStreamDecode() :
|
||||
* Use this function to instruct where to find the dictionary.
|
||||
* This function is not necessary if previous data is still available where it was decoded.
|
||||
* Loading a size of 0 is allowed (same effect as no dictionary).
|
||||
* Return : 1 if OK, 0 if error
|
||||
*/
|
||||
int LIZ_setStreamDecode (LIZ_streamDecode_t* LIZ_streamDecode, const char* dictionary, int dictSize)
|
||||
{
|
||||
LIZ_streamDecode_t* lz5sd = (LIZ_streamDecode_t*) LIZ_streamDecode;
|
||||
lz5sd->prefixSize = (size_t) dictSize;
|
||||
lz5sd->prefixEnd = (const BYTE*) dictionary + dictSize;
|
||||
lz5sd->externalDict = NULL;
|
||||
lz5sd->extDictSize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks must still be available at the memory position where they were decoded.
|
||||
If it's not possible, save the relevant part of decoded data into a safe buffer,
|
||||
and indicate where it stands using LIZ_setStreamDecode()
|
||||
*/
|
||||
int LIZ_decompress_safe_continue (LIZ_streamDecode_t* LIZ_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
|
||||
{
|
||||
LIZ_streamDecode_t* lz5sd = (LIZ_streamDecode_t*) LIZ_streamDecode;
|
||||
int result;
|
||||
|
||||
if (lz5sd->prefixEnd == (BYTE*)dest) {
|
||||
result = LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
||||
full, 0, usingExtDict, lz5sd->prefixEnd - lz5sd->prefixSize, lz5sd->externalDict, lz5sd->extDictSize);
|
||||
if (result <= 0) return result;
|
||||
lz5sd->prefixSize += result;
|
||||
lz5sd->prefixEnd += result;
|
||||
} else {
|
||||
lz5sd->extDictSize = lz5sd->prefixSize;
|
||||
lz5sd->externalDict = lz5sd->prefixEnd - lz5sd->extDictSize;
|
||||
result = LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
||||
full, 0, usingExtDict, (BYTE*)dest, lz5sd->externalDict, lz5sd->extDictSize);
|
||||
if (result <= 0) return result;
|
||||
lz5sd->prefixSize = result;
|
||||
lz5sd->prefixEnd = (BYTE*)dest + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as "_continue" ones,
|
||||
the dictionary must be explicitly provided within parameters
|
||||
*/
|
||||
|
||||
int LIZ_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
if (dictSize==0)
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
|
||||
if (dictStart+dictSize == dest)
|
||||
{
|
||||
if (dictSize >= (int)(LIZ_DICT_SIZE - 1))
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, withPrefix64k, (BYTE*)dest-LIZ_DICT_SIZE, NULL, 0);
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
|
||||
}
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
||||
}
|
||||
|
||||
/* debug function */
|
||||
int LIZ_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
return LIZ_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
#define LIZ_FAST_MIN_OFFSET 8
|
||||
#define LIZ_FAST_LONGOFF_MM 0 /* not used with offsets > 1<<16 */
|
||||
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t LIZ_hashPosition(const void* p)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return LIZ_hash5Ptr(p, LIZ_HASHLOG_LZ4);
|
||||
return LIZ_hash4Ptr(p, LIZ_HASHLOG_LZ4);
|
||||
}
|
||||
|
||||
static void LIZ_putPositionOnHash(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void LIZ_putPosition(const BYTE* p, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
size_t const h = LIZ_hashPosition(p);
|
||||
LIZ_putPositionOnHash(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 LIZ_getPositionOnHash(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 LIZ_getPosition(const BYTE* p, U32* hashTable)
|
||||
{
|
||||
size_t const h = LIZ_hashPosition(p);
|
||||
return LIZ_getPositionOnHash(h, hashTable);
|
||||
}
|
||||
|
||||
|
||||
static const U32 LIZ_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
|
||||
static const U32 LIZ_minLength = (MFLIMIT+1);
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_fast(
|
||||
LIZ_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 lowLimit = ctx->lowLimit;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
|
||||
// fprintf(stderr, "base=%p LIZ_stream_t=%d inputSize=%d maxOutputSize=%d\n", base, sizeof(LIZ_stream_t), inputSize, maxOutputSize);
|
||||
// fprintf(stderr, "ip=%d base=%p lowPrefixPtr=%p dictBase=%d lowLimit=%p op=%p\n", ip, base, lowPrefixPtr, lowLimit, dictBase, op);
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZ_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < LIZ_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
LIZ_putPosition(ip, ctx->hashTable, base);
|
||||
ip++; forwardH = LIZ_hashPosition(ip);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
// BYTE* token;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << LIZ_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> LIZ_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = LIZ_getPositionOnHash(h, ctx->hashTable);
|
||||
forwardH = LIZ_hashPosition(forwardIp);
|
||||
LIZ_putPositionOnHash(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
LIZ_putPosition(ip-2, ctx->hashTable, base);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = LIZ_getPosition(ip, ctx->hashTable);
|
||||
LIZ_putPosition(ip, ctx->hashTable, base);
|
||||
if (matchIndex >= lowLimit && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = LIZ_hashPosition(++ip);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
#define LIZ_FASTBIG_LONGOFF_MM MM_LONGOFF
|
||||
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t LIZ_hashPositionHLog(const void* p, int hashLog)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return LIZ_hash5Ptr(p, hashLog);
|
||||
return LIZ_hash4Ptr(p, hashLog);
|
||||
}
|
||||
|
||||
static void LIZ_putPositionOnHashHLog(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void LIZ_putPositionHLog(const BYTE* p, U32* hashTable, const BYTE* srcBase, int hashLog)
|
||||
{
|
||||
size_t const h = LIZ_hashPositionHLog(p, hashLog);
|
||||
LIZ_putPositionOnHashHLog(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 LIZ_getPositionOnHashHLog(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 LIZ_getPositionHLog(const BYTE* p, U32* hashTable, int hashLog)
|
||||
{
|
||||
size_t const h = LIZ_hashPositionHLog(p, hashLog);
|
||||
return LIZ_getPositionOnHashHLog(h, hashTable);
|
||||
}
|
||||
|
||||
FORCE_INLINE int LIZ_compress_fastBig(
|
||||
LIZ_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 lowLimit = ctx->lowLimit;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
|
||||
// fprintf(stderr, "base=%p LIZ_stream_t=%d inputSize=%d maxOutputSize=%d\n", base, sizeof(LIZ_stream_t), inputSize, maxOutputSize);
|
||||
// fprintf(stderr, "ip=%d base=%p lowPrefixPtr=%p dictBase=%d lowLimit=%p op=%p\n", ip, base, lowPrefixPtr, lowLimit, dictBase, op);
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZ_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < LIZ_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
LIZ_putPositionHLog(ip, ctx->hashTable, base, hashLog);
|
||||
ip++; forwardH = LIZ_hashPositionHLog(ip, hashLog);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
// BYTE* token;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << LIZ_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> LIZ_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = LIZ_getPositionOnHashHLog(h, ctx->hashTable);
|
||||
forwardH = LIZ_hashPositionHLog(forwardIp, hashLog);
|
||||
LIZ_putPositionOnHashHLog(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
if ((matchLength >= LIZ_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
if ((matchLength >= LIZ_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (LIZ_encodeSequence_LZ5v2(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
LIZ_putPositionHLog(ip-2, ctx->hashTable, base, hashLog);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = LIZ_getPositionHLog(ip, ctx->hashTable, hashLog);
|
||||
LIZ_putPositionHLog(ip, ctx->hashTable, base, hashLog);
|
||||
if (matchIndex >= lowLimit && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
if ((matchLength >= LIZ_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
if ((matchLength >= LIZ_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = LIZ_hashPositionHLog(++ip, hashLog);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ5v2(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t LIZ_hashPositionSmall(const void* p)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return LIZ_hash5Ptr(p, LIZ_HASHLOG_LZ4SM);
|
||||
return LIZ_hash4Ptr(p, LIZ_HASHLOG_LZ4SM);
|
||||
}
|
||||
|
||||
static void LIZ_putPositionOnHashSmall(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void LIZ_putPositionSmall(const BYTE* p, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
size_t const h = LIZ_hashPositionSmall(p);
|
||||
LIZ_putPositionOnHashSmall(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 LIZ_getPositionOnHashSmall(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 LIZ_getPositionSmall(const BYTE* p, U32* hashTable)
|
||||
{
|
||||
size_t const h = LIZ_hashPositionSmall(p);
|
||||
return LIZ_getPositionOnHashSmall(h, hashTable);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_fastSmall(
|
||||
LIZ_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 lowLimit = ctx->lowLimit;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
|
||||
// fprintf(stderr, "base=%p LIZ_stream_t=%d inputSize=%d maxOutputSize=%d\n", base, sizeof(LIZ_stream_t), inputSize, maxOutputSize);
|
||||
// fprintf(stderr, "ip=%d base=%p lowPrefixPtr=%p dictBase=%d lowLimit=%p op=%p\n", ip, base, lowPrefixPtr, lowLimit, dictBase, op);
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZ_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < LIZ_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
LIZ_putPositionSmall(ip, ctx->hashTable, base);
|
||||
ip++; forwardH = LIZ_hashPositionSmall(ip);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
// BYTE* token;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << LIZ_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> LIZ_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = LIZ_getPositionOnHashSmall(h, ctx->hashTable);
|
||||
forwardH = LIZ_hashPositionSmall(forwardIp);
|
||||
LIZ_putPositionOnHashSmall(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
LIZ_putPositionSmall(ip-2, ctx->hashTable, base);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = LIZ_getPositionSmall(ip, ctx->hashTable);
|
||||
LIZ_putPositionSmall(ip, ctx->hashTable, base);
|
||||
if (matchIndex >= lowLimit && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = LIZ_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZ_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
#if LIZ_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZ_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = LIZ_hashPositionSmall(++ip);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
497
C/lizard/lizard_common.h
Normal file
497
C/lizard/lizard_common.h
Normal file
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
Lizard - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2015, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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 :
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
|
||||
#ifndef LIZARD_COMMON_H_2983
|
||||
#define LIZARD_COMMON_H_2983
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Memory routines
|
||||
**************************************/
|
||||
#include <stdlib.h> /* malloc, calloc, free */
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#include <stdint.h> /* intptr_t */
|
||||
#include "../zstd/mem.h"
|
||||
#include "lizard_compress.h" /* LIZARD_GCC_VERSION */
|
||||
|
||||
//#define LIZARD_USE_LOGS
|
||||
#define LIZARD_LOG_COMPRESS(...) //printf(__VA_ARGS__)
|
||||
#define LIZARD_LOG_DECOMPRESS(...) //printf(__VA_ARGS__)
|
||||
|
||||
#define LIZARD_LOG_COMPRESS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define COMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define LIZARD_LOG_DECOMPRESS_LZ4(...) //printf(__VA_ARGS__)
|
||||
#define DECOMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)
|
||||
|
||||
#define LIZARD_LOG_COMPRESS_LIZv1(...) //printf(__VA_ARGS__)
|
||||
#define COMPLOG_CODEWORDS_LIZv1(...) //printf(__VA_ARGS__)
|
||||
#define LIZARD_LOG_DECOMPRESS_LIZv1(...) //printf(__VA_ARGS__)
|
||||
#define DECOMPLOG_CODEWORDS_LIZv1(...) //printf(__VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common Constants
|
||||
**************************************/
|
||||
#define MINMATCH 4
|
||||
//#define USE_LZ4_ONLY
|
||||
//#define LIZARD_USE_TEST
|
||||
|
||||
#define LIZARD_DICT_SIZE (1<<24)
|
||||
#define WILDCOPYLENGTH 16
|
||||
#define LASTLITERALS WILDCOPYLENGTH
|
||||
#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
|
||||
|
||||
#define LIZARD_MAX_PRICE (1<<28)
|
||||
#define LIZARD_INIT_LAST_OFFSET 0
|
||||
#define LIZARD_MAX_16BIT_OFFSET (1<<16)
|
||||
#define MM_LONGOFF 16
|
||||
#define LIZARD_BLOCK_SIZE_PAD (LIZARD_BLOCK_SIZE+32)
|
||||
#define LIZARD_COMPRESS_ADD_BUF (5*LIZARD_BLOCK_SIZE_PAD)
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
#define LIZARD_COMPRESS_ADD_HUF HUF_compressBound(LIZARD_BLOCK_SIZE_PAD)
|
||||
#define LIZARD_HUF_BLOCK_SIZE LIZARD_BLOCK_SIZE
|
||||
#else
|
||||
#define LIZARD_COMPRESS_ADD_HUF 0
|
||||
#define LIZARD_HUF_BLOCK_SIZE 1
|
||||
#endif
|
||||
|
||||
/* LZ4 codewords */
|
||||
#define ML_BITS_LZ4 4
|
||||
#define ML_MASK_LZ4 ((1U<<ML_BITS_LZ4)-1)
|
||||
#define RUN_BITS_LZ4 (8-ML_BITS_LZ4)
|
||||
#define RUN_MASK_LZ4 ((1U<<RUN_BITS_LZ4)-1)
|
||||
|
||||
/* LIZv1 codewords */
|
||||
#define ML_BITS_LIZv1 4
|
||||
#define RUN_BITS_LIZv1 3
|
||||
#define ML_RUN_BITS (ML_BITS_LIZv1 + RUN_BITS_LIZv1)
|
||||
#define MAX_SHORT_LITLEN 7
|
||||
#define MAX_SHORT_MATCHLEN 15
|
||||
#define LIZARD_LAST_LONG_OFF 31
|
||||
|
||||
/* header byte */
|
||||
#define LIZARD_FLAG_LITERALS 1
|
||||
#define LIZARD_FLAG_FLAGS 2
|
||||
#define LIZARD_FLAG_OFFSET16 4
|
||||
#define LIZARD_FLAG_OFFSET24 8
|
||||
#define LIZARD_FLAG_LEN 16
|
||||
#define LIZARD_FLAG_UNCOMPRESSED 128
|
||||
|
||||
/* stream numbers */
|
||||
#define LIZARD_STREAM_LITERALS 0
|
||||
#define LIZARD_STREAM_FLAGS 1
|
||||
#define LIZARD_STREAM_OFFSET16 2
|
||||
#define LIZARD_STREAM_OFFSET24 3
|
||||
#define LIZARD_STREAM_LEN 4
|
||||
#define LIZARD_STREAM_UNCOMPRESSED 5
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum { Lizard_parser_fastSmall, Lizard_parser_fast, Lizard_parser_fastBig, Lizard_parser_noChain, Lizard_parser_hashChain, Lizard_parser_priceFast, Lizard_parser_lowestPrice, Lizard_parser_optimalPrice, Lizard_parser_optimalPriceBT } Lizard_parser_type; /* from faster to stronger */
|
||||
typedef enum { Lizard_coderwords_LZ4, Lizard_coderwords_LIZv1 } Lizard_decompress_type;
|
||||
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 minMatchLongOff; /* min match size with offsets >= 1<<16 */
|
||||
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 */
|
||||
Lizard_parser_type parserType;
|
||||
Lizard_decompress_type decompressType;
|
||||
} Lizard_parameters;
|
||||
|
||||
|
||||
struct Lizard_stream_s
|
||||
{
|
||||
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 */
|
||||
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 allocatedMemory;
|
||||
int compressionLevel;
|
||||
Lizard_parameters params;
|
||||
U32 hashTableSize;
|
||||
U32 chainTableSize;
|
||||
U32* chainTable;
|
||||
U32* hashTable;
|
||||
int last_off;
|
||||
const BYTE* off24pos;
|
||||
U32 huffType;
|
||||
U32 comprStreamLen;
|
||||
|
||||
BYTE* huffBase;
|
||||
BYTE* huffEnd;
|
||||
BYTE* offset16Base;
|
||||
BYTE* offset24Base;
|
||||
BYTE* lenBase;
|
||||
BYTE* literalsBase;
|
||||
BYTE* flagsBase;
|
||||
BYTE* offset16Ptr;
|
||||
BYTE* offset24Ptr;
|
||||
BYTE* lenPtr;
|
||||
BYTE* literalsPtr;
|
||||
BYTE* flagsPtr;
|
||||
BYTE* offset16End;
|
||||
BYTE* offset24End;
|
||||
BYTE* lenEnd;
|
||||
BYTE* literalsEnd;
|
||||
BYTE* flagsEnd;
|
||||
U32 flagFreq[256];
|
||||
U32 litFreq[256];
|
||||
U32 litSum, flagSum;
|
||||
U32 litPriceSum, log2LitSum, log2FlagSum;
|
||||
U32 cachedPrice;
|
||||
U32 cachedLitLength;
|
||||
const BYTE* cachedLiterals;
|
||||
const BYTE* diffBase;
|
||||
const BYTE* srcBase;
|
||||
const BYTE* destBase;
|
||||
};
|
||||
|
||||
struct Lizard_dstream_s
|
||||
{
|
||||
const BYTE* offset16Ptr;
|
||||
const BYTE* offset24Ptr;
|
||||
const BYTE* lenPtr;
|
||||
const BYTE* literalsPtr;
|
||||
const BYTE* flagsPtr;
|
||||
const BYTE* offset16End;
|
||||
const BYTE* offset24End;
|
||||
const BYTE* lenEnd;
|
||||
const BYTE* literalsEnd;
|
||||
const BYTE* flagsEnd;
|
||||
const BYTE* diffBase;
|
||||
intptr_t last_off;
|
||||
};
|
||||
|
||||
typedef struct Lizard_dstream_s Lizard_dstream_t;
|
||||
|
||||
/* *************************************
|
||||
* HC Pre-defined compression levels
|
||||
***************************************/
|
||||
#define LIZARD_WINDOWLOG_LZ4 16
|
||||
#define LIZARD_CHAINLOG_LZ4 LIZARD_WINDOWLOG_LZ4
|
||||
#define LIZARD_HASHLOG_LZ4 18
|
||||
#define LIZARD_HASHLOG_LZ4SM 12
|
||||
|
||||
#define LIZARD_WINDOWLOG_LIZv1 22
|
||||
#define LIZARD_CHAINLOG_LIZv1 LIZARD_WINDOWLOG_LIZv1
|
||||
#define LIZARD_HASHLOG_LIZv1 18
|
||||
|
||||
|
||||
|
||||
static const Lizard_parameters Lizard_defaultParameters[LIZARD_MAX_CLEVEL+1-LIZARD_MIN_CLEVEL] =
|
||||
{
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4SM, 0, 0, 0, 0, 0, 0, Lizard_parser_fastSmall, Lizard_coderwords_LZ4 }, // level 10
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, Lizard_parser_fast, Lizard_coderwords_LZ4 }, // level 11
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, Lizard_parser_noChain, Lizard_coderwords_LZ4 }, // level 12
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 2, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 13
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 4, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 14
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 8, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 15
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 16, 4, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 16
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 256, 4, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 17
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_WINDOWLOG_LZ4+1, LIZARD_HASHLOG_LZ4, 16, 16, 4, 0, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4 }, // level 18
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_WINDOWLOG_LZ4+1, 23, 16, 256, 4, 0, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4 }, // level 19
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZARD_WINDOWLOG_LIZv1, 0, 14, 0, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_fastBig, Lizard_coderwords_LIZv1 }, // level 20
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 14, 13, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_priceFast, Lizard_coderwords_LIZv1 }, // level 21
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1, 13, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_priceFast, Lizard_coderwords_LIZv1 }, // level 22
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1, 13, 1, 5, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 23
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 23, 16, 2, 5, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 24
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 23, 16, 8, 4, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 25
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1+1, 23, 16, 8, 4, MM_LONGOFF, 64, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 26
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1+1, 23, 16, 128, 4, MM_LONGOFF, 64, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 27
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1+1, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 28
|
||||
{ 24, 25, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 29
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4SM, 0, 0, 0, 0, 0, 0, Lizard_parser_fastSmall, Lizard_coderwords_LZ4 }, // level 30
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, Lizard_parser_fast, Lizard_coderwords_LZ4 }, // level 31
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, 14, 0, 0, 0, 0, 0, 0, Lizard_parser_noChain, Lizard_coderwords_LZ4 }, // level 32
|
||||
{ LIZARD_WINDOWLOG_LZ4, 0, LIZARD_HASHLOG_LZ4, 0, 0, 0, 0, 0, 0, Lizard_parser_noChain, Lizard_coderwords_LZ4 }, // level 33
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 2, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 34
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 4, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 35
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 8, 5, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 36
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 16, 4, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 37
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_CHAINLOG_LZ4, LIZARD_HASHLOG_LZ4, 0, 256, 4, 0, 0, 0, Lizard_parser_hashChain, Lizard_coderwords_LZ4 }, // level 38
|
||||
{ LIZARD_WINDOWLOG_LZ4, LIZARD_WINDOWLOG_LZ4+1, 23, 16, 256, 4, 0, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4 }, // level 39
|
||||
/* windLog, contentLog, HashLog, H3, Snum, SL, MMLongOff, SuffL, FS, Parser function, Decompressor type */
|
||||
{ LIZARD_WINDOWLOG_LIZv1, 0, 14, 0, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_fastBig, Lizard_coderwords_LIZv1 }, // level 40
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 14, 13, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_priceFast, Lizard_coderwords_LIZv1 }, // level 41
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1, 13, 1, 5, MM_LONGOFF, 0, 0, Lizard_parser_priceFast, Lizard_coderwords_LIZv1 }, // level 42
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1, 13, 1, 5, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 43
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 23, 16, 2, 5, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 44
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 23, 16, 8, 4, MM_LONGOFF, 64, 0, Lizard_parser_lowestPrice, Lizard_coderwords_LIZv1 }, // level 45
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1, 23, 16, 8, 4, MM_LONGOFF, 64, 0, Lizard_parser_optimalPrice, Lizard_coderwords_LIZv1 }, // level 46
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1+1, 23, 16, 8, 4, MM_LONGOFF, 64, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 47
|
||||
{ LIZARD_WINDOWLOG_LIZv1, LIZARD_CHAINLOG_LIZv1+1, 23, 16, 128, 4, MM_LONGOFF, 64, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 48
|
||||
{ 24, 25, 23, 24, 1<<10, 4, MM_LONGOFF, 1<<10, 1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 49
|
||||
#endif
|
||||
// { 10, 10, 10, 0, 0, 4, 0, 0, 0, Lizard_fast }, // min values
|
||||
// { 24, 24, 28, 24, 1<<24, 7, 0, 1<<24, 2, Lizard_optimal_price }, // max values
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* 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 LIZARD_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#if (LIZARD_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)
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define ALLOCATOR(n,s) calloc(n,s)
|
||||
#define FREEMEM free
|
||||
#define MEM_INIT memset
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b))?(a):(b)
|
||||
#endif
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#if MINMATCH == 3
|
||||
#define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr)<<8)
|
||||
#else
|
||||
#define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Reading and writing into memory
|
||||
**************************************/
|
||||
#define STEPSIZE sizeof(size_t)
|
||||
|
||||
|
||||
MEM_STATIC void Lizard_copy8(void* dst, const void* src)
|
||||
{
|
||||
memcpy(dst,src,8);
|
||||
}
|
||||
|
||||
/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
|
||||
MEM_STATIC void Lizard_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
|
||||
{
|
||||
BYTE* d = (BYTE*)dstPtr;
|
||||
const BYTE* s = (const BYTE*)srcPtr;
|
||||
BYTE* const e = (BYTE*)dstEnd;
|
||||
|
||||
#if 0
|
||||
const size_t l2 = 8 - (((size_t)d) & (sizeof(void*)-1));
|
||||
Lizard_copy8(d,s); if (d>e-9) return;
|
||||
d+=l2; s+=l2;
|
||||
#endif /* join to align */
|
||||
|
||||
do { Lizard_copy8(d,s); d+=8; s+=8; } while (d<e);
|
||||
}
|
||||
|
||||
MEM_STATIC void Lizard_wildCopy16(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd)
|
||||
{
|
||||
do {
|
||||
Lizard_copy8(dstPtr, srcPtr);
|
||||
Lizard_copy8(dstPtr+8, srcPtr+8);
|
||||
dstPtr += 16;
|
||||
srcPtr += 16;
|
||||
}
|
||||
while (dstPtr < dstEnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* LIZARD_FORCE_SW_BITCOUNT
|
||||
* Define this parameter if your target system or compiler does not support hardware bit count
|
||||
*/
|
||||
#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
|
||||
# define LIZARD_FORCE_SW_BITCOUNT
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************
|
||||
* Function body to include for inlining
|
||||
****************************************/
|
||||
MEM_STATIC U32 Lizard_highbit32(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
|
||||
}
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Common functions
|
||||
**************************************/
|
||||
MEM_STATIC unsigned Lizard_NbCommonBytes (register size_t val)
|
||||
{
|
||||
if (MEM_isLittleEndian()) {
|
||||
if (MEM_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward64( &r, (U64)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
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) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
unsigned long r;
|
||||
_BitScanForward( &r, (U32)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
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_64bits()) {
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
return (__builtin_clzll((U64)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
|
||||
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
} else /* 32 bits */ {
|
||||
# if defined(_MSC_VER) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)
|
||||
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 unsigned Lizard_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
|
||||
{
|
||||
const BYTE* const pStart = pIn;
|
||||
|
||||
while (likely(pIn<pInLimit-(STEPSIZE-1))) {
|
||||
size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
|
||||
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
|
||||
pIn += Lizard_NbCommonBytes(diff);
|
||||
return (unsigned)(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 (unsigned)(pIn - pStart);
|
||||
}
|
||||
|
||||
/* alias to functions with compressionLevel=1 */
|
||||
int Lizard_sizeofState_MinLevel(void);
|
||||
int Lizard_compress_MinLevel(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
int Lizard_compress_extState_MinLevel (void* state, const char* source, char* dest, int inputSize, int maxDestSize);
|
||||
Lizard_stream_t* Lizard_resetStream_MinLevel (Lizard_stream_t* streamPtr);
|
||||
Lizard_stream_t* Lizard_createStream_MinLevel(void);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZARD_COMMON_H_2983827168210 */
|
||||
629
C/lizard/lizard_compress.c
Normal file
629
C/lizard/lizard_compress.c
Normal file
@@ -0,0 +1,629 @@
|
||||
/*
|
||||
Lizard - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2015, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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 NOTLizard_hash4Ptr
|
||||
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 :
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Includes
|
||||
***************************************/
|
||||
#include "lizard_compress.h"
|
||||
#include "lizard_common.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h> // intptr_t
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#ifdef LIZARD_USE_TEST
|
||||
#include "test/lizard_common_test.h"
|
||||
#include "test/lizard_compress_test.h"
|
||||
#else
|
||||
#include "lizard_compress_liz.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "lizard_compress_lz4.h"
|
||||
#include "../zstd/huf.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Local Macros
|
||||
***************************************/
|
||||
#define DELTANEXT(p) chainTable[(p) & contentMask]
|
||||
#define LIZARD_MINIMAL_HUFF_GAIN(comprSize) (comprSize + (comprSize/8) + 512)
|
||||
#define LIZARD_MINIMAL_BLOCK_GAIN(comprSize) (comprSize + (comprSize/32) + 512)
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Local Utils
|
||||
**************************************/
|
||||
int Lizard_versionNumber (void) { return LIZARD_VERSION_NUMBER; }
|
||||
int Lizard_compressBound(int isize) { return LIZARD_COMPRESSBOUND(isize); }
|
||||
int Lizard_sizeofState_MinLevel() { return Lizard_sizeofState(LIZARD_MIN_CLEVEL); }
|
||||
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Hash functions
|
||||
***************************************/
|
||||
#define HASH_UPDATE_LIMIT 8 /* equal to MEM_read64 */
|
||||
static const U32 prime4bytes = 2654435761U;
|
||||
static const U64 prime5bytes = 889523592379ULL;
|
||||
static const U64 prime6bytes = 227718039650203ULL;
|
||||
static const U64 prime7bytes = 58295818150454627ULL;
|
||||
|
||||
#if MINMATCH == 3
|
||||
static const U32 prime3bytes = 506832829U;
|
||||
static U32 Lizard_hash3(U32 u, U32 h) { return (u * prime3bytes) << (32-24) >> (32-h) ; }
|
||||
static size_t Lizard_hash3Ptr(const void* ptr, U32 h) { return Lizard_hash3(MEM_read32(ptr), h); }
|
||||
#endif
|
||||
|
||||
static U32 Lizard_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
|
||||
static size_t Lizard_hash4Ptr(const void* ptr, U32 h) { return Lizard_hash4(MEM_read32(ptr), h); }
|
||||
|
||||
static size_t Lizard_hash5(U64 u, U32 h) { return (size_t)((u * prime5bytes) << (64-40) >> (64-h)) ; }
|
||||
static size_t Lizard_hash5Ptr(const void* p, U32 h) { return Lizard_hash5(MEM_read64(p), h); }
|
||||
|
||||
static size_t Lizard_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; }
|
||||
static size_t Lizard_hash6Ptr(const void* p, U32 h) { return Lizard_hash6(MEM_read64(p), h); }
|
||||
|
||||
static size_t Lizard_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }
|
||||
static size_t Lizard_hash7Ptr(const void* p, U32 h) { return Lizard_hash7(MEM_read64(p), h); }
|
||||
|
||||
static size_t Lizard_hashPtr(const void* p, U32 hBits, U32 mls)
|
||||
{
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
case 4: return Lizard_hash4Ptr(p, hBits);
|
||||
case 5: return Lizard_hash5Ptr(p, hBits);
|
||||
case 6: return Lizard_hash6Ptr(p, hBits);
|
||||
case 7: return Lizard_hash7Ptr(p, hBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Internal functions
|
||||
**************************************/
|
||||
/** Lizard_count_2segments() :
|
||||
* can count match length with `ip` & `match` in 2 different segments.
|
||||
* convention : on reaching mEnd, match count continue starting from iStart
|
||||
*/
|
||||
static size_t Lizard_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
|
||||
{
|
||||
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
|
||||
size_t const matchLength = Lizard_count(ip, match, vEnd);
|
||||
if (match + matchLength != mEnd) return matchLength;
|
||||
return matchLength + Lizard_count(ip+matchLength, iStart, iEnd);
|
||||
}
|
||||
|
||||
|
||||
void Lizard_initBlock(Lizard_stream_t* ctx)
|
||||
{
|
||||
ctx->offset16Ptr = ctx->offset16Base;
|
||||
ctx->offset24Ptr = ctx->offset24Base;
|
||||
ctx->lenPtr = ctx->lenBase;
|
||||
ctx->literalsPtr = ctx->literalsBase;
|
||||
ctx->flagsPtr = ctx->flagsBase;
|
||||
ctx->last_off = LIZARD_INIT_LAST_OFFSET; /* reset last offset */
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_writeStream(int useHuff, Lizard_stream_t* ctx, BYTE* streamPtr, uint32_t streamLen, BYTE** op, BYTE* oend)
|
||||
{
|
||||
if (useHuff && streamLen > 1024) {
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
int useHuffBuf;
|
||||
if (*op + 6 > oend) { LIZARD_LOG_COMPRESS("*op[%p] + 6 > oend[%p]\n", *op, oend); return -1; }
|
||||
|
||||
useHuffBuf = ((size_t)(oend - (*op + 6)) < HUF_compressBound(streamLen));
|
||||
if (useHuffBuf) {
|
||||
if (streamLen > LIZARD_BLOCK_SIZE) { LIZARD_LOG_COMPRESS("streamLen[%d] > LIZARD_BLOCK_SIZE\n", streamLen); return -1; }
|
||||
ctx->comprStreamLen = (U32)HUF_compress(ctx->huffBase, ctx->huffEnd - ctx->huffBase, streamPtr, streamLen);
|
||||
} else {
|
||||
ctx->comprStreamLen = (U32)HUF_compress(*op + 6, oend - (*op + 6), streamPtr, streamLen);
|
||||
}
|
||||
|
||||
if (!HUF_isError(ctx->comprStreamLen)) {
|
||||
if (ctx->comprStreamLen > 0 && (LIZARD_MINIMAL_HUFF_GAIN(ctx->comprStreamLen) < streamLen)) { /* compressible */
|
||||
MEM_writeLE24(*op, streamLen);
|
||||
MEM_writeLE24(*op+3, ctx->comprStreamLen);
|
||||
if (useHuffBuf) {
|
||||
if ((size_t)(oend - (*op + 6)) < ctx->comprStreamLen) { LIZARD_LOG_COMPRESS("*op[%p] oend[%p] comprStreamLen[%d]\n", *op, oend, (int)ctx->comprStreamLen); return -1; }
|
||||
memcpy(*op + 6, ctx->huffBase, ctx->comprStreamLen);
|
||||
}
|
||||
*op += ctx->comprStreamLen + 6;
|
||||
LIZARD_LOG_COMPRESS("HUF_compress streamLen=%d comprStreamLen=%d\n", (int)streamLen, (int)ctx->comprStreamLen);
|
||||
return 1;
|
||||
} else { LIZARD_LOG_COMPRESS("HUF_compress ERROR comprStreamLen=%d streamLen=%d\n", (int)ctx->comprStreamLen, (int)streamLen); }
|
||||
} else { LIZARD_LOG_COMPRESS("HUF_compress ERROR %d: %s\n", (int)ctx->comprStreamLen, HUF_getErrorName(ctx->comprStreamLen)); }
|
||||
#else
|
||||
LIZARD_LOG_COMPRESS("compiled with LIZARD_NO_HUFFMAN\n");
|
||||
(void)ctx;
|
||||
return -1;
|
||||
#endif
|
||||
} else ctx->comprStreamLen = 0;
|
||||
|
||||
if (*op + 3 + streamLen > oend) { LIZARD_LOG_COMPRESS("*op[%p] + 3 + streamLen[%d] > oend[%p]\n", *op, streamLen, oend); return -1; }
|
||||
MEM_writeLE24(*op, streamLen);
|
||||
*op += 3;
|
||||
memcpy(*op, streamPtr, streamLen);
|
||||
*op += streamLen;
|
||||
LIZARD_LOG_COMPRESS("Uncompressed streamLen=%d\n", (int)streamLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_writeBlock(Lizard_stream_t* ctx, const BYTE* ip, uint32_t inputSize, BYTE** op, BYTE* oend)
|
||||
{
|
||||
int res;
|
||||
uint32_t flagsLen = (uint32_t)(ctx->flagsPtr - ctx->flagsBase);
|
||||
uint32_t literalsLen = (uint32_t)(ctx->literalsPtr - ctx->literalsBase);
|
||||
uint32_t lenLen = (uint32_t)(ctx->lenPtr - ctx->lenBase);
|
||||
uint32_t offset16Len = (uint32_t)(ctx->offset16Ptr - ctx->offset16Base);
|
||||
uint32_t offset24Len = (uint32_t)(ctx->offset24Ptr - ctx->offset24Base);
|
||||
uint32_t sum = flagsLen + literalsLen + lenLen + offset16Len + offset24Len;
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
uint32_t comprFlagsLen, comprLiteralsLen;
|
||||
#endif
|
||||
|
||||
BYTE* start = *op;
|
||||
|
||||
if ((literalsLen < WILDCOPYLENGTH) || (sum+5*3+1 > inputSize)) goto _write_uncompressed;
|
||||
|
||||
*start = 0;
|
||||
*op += 1;
|
||||
|
||||
res = Lizard_writeStream(0, ctx, ctx->lenBase, lenLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_LEN);
|
||||
|
||||
res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_OFFSET16, ctx, ctx->offset16Base, offset16Len, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_OFFSET16);
|
||||
|
||||
res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_OFFSET24, ctx, ctx->offset24Base, offset24Len, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_OFFSET24);
|
||||
|
||||
res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_FLAGS, ctx, ctx->flagsBase, flagsLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_FLAGS);
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
comprFlagsLen = ctx->comprStreamLen;
|
||||
#endif
|
||||
|
||||
res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_LITERALS, ctx, ctx->literalsBase, literalsLen, op, oend);
|
||||
if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_LITERALS);
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
comprLiteralsLen = ctx->comprStreamLen;
|
||||
sum = (int)(*op-start);
|
||||
#endif
|
||||
|
||||
if (LIZARD_MINIMAL_BLOCK_GAIN((uint32_t)(*op-start)) > inputSize) goto _write_uncompressed;
|
||||
|
||||
LIZARD_LOG_COMPRESS("%d: total=%d block=%d flagsLen[%.2f%%]=%d comprFlagsLen[%.2f%%]=%d literalsLen[%.2f%%]=%d comprLiteralsLen[%.2f%%]=%d lenLen=%d offset16Len[%.2f%%]=%d offset24Len[%.2f%%]=%d\n", (int)(ip - ctx->srcBase),
|
||||
(int)(*op - ctx->destBase), sum, (flagsLen*100.0)/sum, flagsLen, (comprFlagsLen*100.0)/sum, comprFlagsLen, (literalsLen*100.0)/sum, literalsLen, (comprLiteralsLen*100.0)/sum, comprLiteralsLen,
|
||||
lenLen, (offset16Len*100.0)/sum, offset16Len, (offset24Len*100.0)/sum, offset24Len);
|
||||
return 0;
|
||||
|
||||
_write_uncompressed:
|
||||
LIZARD_LOG_COMPRESS("%d: total=%d block=%d UNCOMPRESSED inputSize=%u outSize=%d\n", (int)(ip - ctx->srcBase),
|
||||
(int)(*op - ctx->destBase), (int)(*op-start), inputSize, (int)(oend-start));
|
||||
if ((uint32_t)(oend - start) < inputSize + 4) goto _output_error;
|
||||
*start = LIZARD_FLAG_UNCOMPRESSED;
|
||||
*op = start + 1;
|
||||
MEM_writeLE24(*op, inputSize);
|
||||
*op += 3;
|
||||
memcpy(*op, ip, inputSize);
|
||||
*op += inputSize;
|
||||
return 0;
|
||||
|
||||
_output_error:
|
||||
LIZARD_LOG_COMPRESS("Lizard_writeBlock ERROR size=%d/%d flagsLen=%d literalsLen=%d lenLen=%d offset16Len=%d offset24Len=%d\n", (int)(*op-start), (int)(oend-start), flagsLen, literalsLen, lenLen, offset16Len, offset24Len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_encodeSequence (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor,
|
||||
size_t matchLength,
|
||||
const BYTE* const match)
|
||||
{
|
||||
#ifdef USE_LZ4_ONLY
|
||||
return Lizard_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);
|
||||
#else
|
||||
if (ctx->params.decompressType == Lizard_coderwords_LZ4)
|
||||
return Lizard_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);
|
||||
|
||||
return Lizard_encodeSequence_LIZv1(ctx, ip, anchor, matchLength, match);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_encodeLastLiterals (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor)
|
||||
{
|
||||
LIZARD_LOG_COMPRESS("Lizard_encodeLastLiterals Lizard_coderwords_LZ4=%d\n", ctx->params.decompressType == Lizard_coderwords_LZ4);
|
||||
#ifdef USE_LZ4_ONLY
|
||||
return Lizard_encodeLastLiterals_LZ4(ctx, ip, anchor);
|
||||
#else
|
||||
if (ctx->params.decompressType == Lizard_coderwords_LZ4)
|
||||
return Lizard_encodeLastLiterals_LZ4(ctx, ip, anchor);
|
||||
|
||||
return Lizard_encodeLastLiterals_LIZv1(ctx, ip, anchor);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Include parsers
|
||||
**************************************/
|
||||
#include "lizard_parser_hashchain.h"
|
||||
#include "lizard_parser_nochain.h"
|
||||
#include "lizard_parser_fast.h"
|
||||
#include "lizard_parser_fastsmall.h"
|
||||
#include "lizard_parser_fastbig.h"
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#include "lizard_parser_optimal.h"
|
||||
#include "lizard_parser_lowestprice.h"
|
||||
#include "lizard_parser_pricefast.h"
|
||||
#endif
|
||||
|
||||
|
||||
int Lizard_verifyCompressionLevel(int compressionLevel)
|
||||
{
|
||||
if (compressionLevel > LIZARD_MAX_CLEVEL) compressionLevel = LIZARD_MAX_CLEVEL;
|
||||
if (compressionLevel < LIZARD_MIN_CLEVEL) compressionLevel = LIZARD_DEFAULT_CLEVEL;
|
||||
return compressionLevel;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_sizeofState(int compressionLevel)
|
||||
{
|
||||
Lizard_parameters params;
|
||||
U32 hashTableSize, chainTableSize;
|
||||
|
||||
compressionLevel = Lizard_verifyCompressionLevel(compressionLevel);
|
||||
params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];
|
||||
// hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));
|
||||
hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));
|
||||
chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));
|
||||
|
||||
return sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + (int)LIZARD_COMPRESS_ADD_HUF;
|
||||
}
|
||||
|
||||
|
||||
static void Lizard_init(Lizard_stream_t* ctx, const BYTE* start)
|
||||
{
|
||||
// No need to use memset() on tables as values are always bound checked
|
||||
#ifdef LIZARD_RESET_MEM
|
||||
MEM_INIT((void*)ctx->hashTable, 0, ctx->hashTableSize);
|
||||
MEM_INIT(ctx->chainTable, 0x01, ctx->chainTableSize);
|
||||
#endif
|
||||
// printf("memset hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\n", ctx->hashTable, ((BYTE*)ctx->hashTable) + ctx->hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+ctx->chainTableSize);
|
||||
ctx->nextToUpdate = LIZARD_DICT_SIZE;
|
||||
ctx->base = start - LIZARD_DICT_SIZE;
|
||||
ctx->end = start;
|
||||
ctx->dictBase = start - LIZARD_DICT_SIZE;
|
||||
ctx->dictLimit = LIZARD_DICT_SIZE;
|
||||
ctx->lowLimit = LIZARD_DICT_SIZE;
|
||||
ctx->last_off = LIZARD_INIT_LAST_OFFSET;
|
||||
ctx->litSum = 0;
|
||||
}
|
||||
|
||||
|
||||
/* if ctx==NULL memory is allocated and returned as value */
|
||||
Lizard_stream_t* Lizard_initStream(Lizard_stream_t* ctx, int compressionLevel)
|
||||
{
|
||||
Lizard_parameters params;
|
||||
U32 hashTableSize, chainTableSize;
|
||||
void *tempPtr;
|
||||
|
||||
compressionLevel = Lizard_verifyCompressionLevel(compressionLevel);
|
||||
params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];
|
||||
// hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));
|
||||
hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));
|
||||
chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
ctx = (Lizard_stream_t*)malloc(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + LIZARD_COMPRESS_ADD_HUF);
|
||||
if (!ctx) { printf("ERROR: Cannot allocate %d MB (compressionLevel=%d)\n", (int)(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel); return 0; }
|
||||
LIZARD_LOG_COMPRESS("Allocated %d MB (compressionLevel=%d)\n", (int)(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel);
|
||||
ctx->allocatedMemory = sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + (U32)LIZARD_COMPRESS_ADD_HUF;
|
||||
// printf("malloc from=%p to=%p hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\n", ctx, ((BYTE*)ctx)+sizeof(Lizard_stream_t) + hashTableSize + chainTableSize, ctx->hashTable, ((BYTE*)ctx->hashTable) + hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+chainTableSize);
|
||||
}
|
||||
|
||||
tempPtr = ctx;
|
||||
ctx->hashTable = (U32*)(tempPtr) + sizeof(Lizard_stream_t)/4;
|
||||
ctx->hashTableSize = hashTableSize;
|
||||
ctx->chainTable = ctx->hashTable + hashTableSize/4;
|
||||
ctx->chainTableSize = chainTableSize;
|
||||
ctx->params = params;
|
||||
ctx->compressionLevel = (unsigned)compressionLevel;
|
||||
if (compressionLevel < 30)
|
||||
ctx->huffType = 0;
|
||||
else
|
||||
ctx->huffType = LIZARD_FLAG_LITERALS + LIZARD_FLAG_FLAGS; // + LIZARD_FLAG_OFFSET16 + LIZARD_FLAG_OFFSET24;
|
||||
|
||||
ctx->literalsBase = (BYTE*)ctx->hashTable + ctx->hashTableSize + ctx->chainTableSize;
|
||||
ctx->flagsBase = ctx->literalsEnd = ctx->literalsBase + LIZARD_BLOCK_SIZE_PAD;
|
||||
ctx->lenBase = ctx->flagsEnd = ctx->flagsBase + LIZARD_BLOCK_SIZE_PAD;
|
||||
ctx->offset16Base = ctx->lenEnd = ctx->lenBase + LIZARD_BLOCK_SIZE_PAD;
|
||||
ctx->offset24Base = ctx->offset16End = ctx->offset16Base + LIZARD_BLOCK_SIZE_PAD;
|
||||
ctx->huffBase = ctx->offset24End = ctx->offset24Base + LIZARD_BLOCK_SIZE_PAD;
|
||||
ctx->huffEnd = ctx->huffBase + LIZARD_COMPRESS_ADD_HUF;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Lizard_stream_t* Lizard_createStream(int compressionLevel)
|
||||
{
|
||||
Lizard_stream_t* ctx = Lizard_initStream(NULL, compressionLevel);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
/* initialization */
|
||||
Lizard_stream_t* Lizard_resetStream(Lizard_stream_t* ctx, int compressionLevel)
|
||||
{
|
||||
size_t wanted = Lizard_sizeofState(compressionLevel);
|
||||
|
||||
if (ctx->allocatedMemory < wanted) {
|
||||
Lizard_freeStream(ctx);
|
||||
ctx = Lizard_createStream(compressionLevel);
|
||||
} else {
|
||||
Lizard_initStream(ctx, compressionLevel);
|
||||
}
|
||||
|
||||
if (ctx) ctx->base = NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_freeStream(Lizard_stream_t* ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_loadDict(Lizard_stream_t* Lizard_streamPtr, const char* dictionary, int dictSize)
|
||||
{
|
||||
Lizard_stream_t* ctxPtr = (Lizard_stream_t*) Lizard_streamPtr;
|
||||
if (dictSize > LIZARD_DICT_SIZE) {
|
||||
dictionary += dictSize - LIZARD_DICT_SIZE;
|
||||
dictSize = LIZARD_DICT_SIZE;
|
||||
}
|
||||
Lizard_init (ctxPtr, (const BYTE*)dictionary);
|
||||
if (dictSize >= HASH_UPDATE_LIMIT) Lizard_Insert (ctxPtr, (const BYTE*)dictionary + (dictSize - (HASH_UPDATE_LIMIT-1)));
|
||||
ctxPtr->end = (const BYTE*)dictionary + dictSize;
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
static void Lizard_setExternalDict(Lizard_stream_t* ctxPtr, const BYTE* newBlock)
|
||||
{
|
||||
if (ctxPtr->end >= ctxPtr->base + HASH_UPDATE_LIMIT) Lizard_Insert (ctxPtr, ctxPtr->end - (HASH_UPDATE_LIMIT-1)); /* Referencing remaining dictionary content */
|
||||
/* Only one memory segment for extDict, so any previous extDict is lost at this stage */
|
||||
ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
|
||||
ctxPtr->dictBase = ctxPtr->base;
|
||||
ctxPtr->base = newBlock - ctxPtr->dictLimit;
|
||||
ctxPtr->end = newBlock;
|
||||
ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
|
||||
}
|
||||
|
||||
|
||||
/* dictionary saving */
|
||||
int Lizard_saveDict (Lizard_stream_t* Lizard_streamPtr, char* safeBuffer, int dictSize)
|
||||
{
|
||||
Lizard_stream_t* const ctx = (Lizard_stream_t*)Lizard_streamPtr;
|
||||
int const prefixSize = (int)(ctx->end - (ctx->base + ctx->dictLimit));
|
||||
if (dictSize > LIZARD_DICT_SIZE) dictSize = LIZARD_DICT_SIZE;
|
||||
if (dictSize < 4) dictSize = 0;
|
||||
if (dictSize > prefixSize) dictSize = prefixSize;
|
||||
memmove(safeBuffer, ctx->end - dictSize, dictSize);
|
||||
{ U32 const endIndex = (U32)(ctx->end - ctx->base);
|
||||
ctx->end = (const BYTE*)safeBuffer + dictSize;
|
||||
ctx->base = ctx->end - endIndex;
|
||||
ctx->dictLimit = endIndex - dictSize;
|
||||
ctx->lowLimit = endIndex - dictSize;
|
||||
if (ctx->nextToUpdate < ctx->dictLimit) ctx->nextToUpdate = ctx->dictLimit;
|
||||
}
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
FORCE_INLINE int Lizard_compress_generic (
|
||||
void* ctxvoid,
|
||||
const char* source,
|
||||
char* dest,
|
||||
int inputSize,
|
||||
int maxOutputSize)
|
||||
{
|
||||
Lizard_stream_t* ctx = (Lizard_stream_t*) ctxvoid;
|
||||
size_t dictSize = (size_t)(ctx->end - ctx->base) - ctx->dictLimit;
|
||||
const BYTE* ip = (const BYTE*) source;
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + maxOutputSize;
|
||||
int res;
|
||||
|
||||
(void)dictSize;
|
||||
LIZARD_LOG_COMPRESS("Lizard_compress_generic source=%p inputSize=%d dest=%p maxOutputSize=%d cLevel=%d dictBase=%p dictSize=%d\n", source, inputSize, dest, maxOutputSize, ctx->compressionLevel, ctx->dictBase, (int)dictSize);
|
||||
*op++ = (BYTE)ctx->compressionLevel;
|
||||
maxOutputSize--; // can be lower than 0
|
||||
ctx->end += inputSize;
|
||||
ctx->srcBase = ctx->off24pos = ip;
|
||||
ctx->destBase = (BYTE*)dest;
|
||||
|
||||
while (inputSize > 0)
|
||||
{
|
||||
int inputPart = MIN(LIZARD_BLOCK_SIZE, inputSize);
|
||||
|
||||
if (ctx->huffType) Lizard_rescaleFreqs(ctx);
|
||||
Lizard_initBlock(ctx);
|
||||
ctx->diffBase = ip;
|
||||
|
||||
switch(ctx->params.parserType)
|
||||
{
|
||||
default:
|
||||
case Lizard_parser_fastSmall:
|
||||
res = Lizard_compress_fastSmall(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_fast:
|
||||
res = Lizard_compress_fast(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_noChain:
|
||||
res = Lizard_compress_noChain(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_hashChain:
|
||||
res = Lizard_compress_hashChain(ctx, ip, ip+inputPart); break;
|
||||
#ifndef USE_LZ4_ONLY
|
||||
case Lizard_parser_fastBig:
|
||||
res = Lizard_compress_fastBig(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_priceFast:
|
||||
res = Lizard_compress_priceFast(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_lowestPrice:
|
||||
res = Lizard_compress_lowestPrice(ctx, ip, ip+inputPart); break;
|
||||
case Lizard_parser_optimalPrice:
|
||||
case Lizard_parser_optimalPriceBT:
|
||||
res = Lizard_compress_optimalPrice(ctx, ip, ip+inputPart); break;
|
||||
#else
|
||||
case Lizard_parser_priceFast:
|
||||
case Lizard_parser_lowestPrice:
|
||||
case Lizard_parser_optimalPrice:
|
||||
case Lizard_parser_optimalPriceBT:
|
||||
res = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LIZARD_LOG_COMPRESS("Lizard_compress_generic res=%d inputPart=%d \n", res, inputPart);
|
||||
if (res <= 0) return res;
|
||||
|
||||
if (Lizard_writeBlock(ctx, ip, inputPart, &op, oend)) goto _output_error;
|
||||
|
||||
ip += inputPart;
|
||||
inputSize -= inputPart;
|
||||
LIZARD_LOG_COMPRESS("Lizard_compress_generic in=%d out=%d\n", (int)(ip-(const BYTE*)source), (int)(op-(BYTE*)dest));
|
||||
}
|
||||
|
||||
LIZARD_LOG_COMPRESS("Lizard_compress_generic total=%d\n", (int)(op-(BYTE*)dest));
|
||||
return (int)(op-(BYTE*)dest);
|
||||
_output_error:
|
||||
LIZARD_LOG_COMPRESS("Lizard_compress_generic ERROR\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_compress_continue (Lizard_stream_t* ctxPtr,
|
||||
const char* source, char* dest,
|
||||
int inputSize, int maxOutputSize)
|
||||
{
|
||||
/* auto-init if forgotten */
|
||||
if (ctxPtr->base == NULL) Lizard_init (ctxPtr, (const BYTE*) source);
|
||||
|
||||
/* Check overflow */
|
||||
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
|
||||
size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
|
||||
if (dictSize > LIZARD_DICT_SIZE) dictSize = LIZARD_DICT_SIZE;
|
||||
Lizard_loadDict((Lizard_stream_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
|
||||
}
|
||||
|
||||
/* Check if blocks follow each other */
|
||||
if ((const BYTE*)source != ctxPtr->end)
|
||||
Lizard_setExternalDict(ctxPtr, (const BYTE*)source);
|
||||
|
||||
/* Check overlapping input/dictionary space */
|
||||
{ const BYTE* sourceEnd = (const BYTE*) source + inputSize;
|
||||
const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
|
||||
const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
|
||||
if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) {
|
||||
if (sourceEnd > dictEnd) sourceEnd = dictEnd;
|
||||
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
|
||||
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return Lizard_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize);
|
||||
}
|
||||
|
||||
|
||||
int Lizard_compress_extState (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
Lizard_stream_t* ctx = (Lizard_stream_t*) state;
|
||||
if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
|
||||
|
||||
/* initialize stream */
|
||||
Lizard_initStream(ctx, compressionLevel);
|
||||
Lizard_init ((Lizard_stream_t*)state, (const BYTE*)src);
|
||||
|
||||
return Lizard_compress_generic (state, src, dst, srcSize, maxDstSize);
|
||||
}
|
||||
|
||||
|
||||
int Lizard_compress(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
int cSize;
|
||||
Lizard_stream_t* statePtr = Lizard_createStream(compressionLevel);
|
||||
|
||||
if (!statePtr) return 0;
|
||||
cSize = Lizard_compress_extState(statePtr, src, dst, srcSize, maxDstSize, compressionLevel);
|
||||
|
||||
Lizard_freeStream(statePtr);
|
||||
return cSize;
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Level1 functions
|
||||
**************************************/
|
||||
int Lizard_compress_extState_MinLevel(void* state, const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
return Lizard_compress_extState(state, source, dest, inputSize, maxOutputSize, LIZARD_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
int Lizard_compress_MinLevel(const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
return Lizard_compress(source, dest, inputSize, maxOutputSize, LIZARD_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
Lizard_stream_t* Lizard_createStream_MinLevel(void)
|
||||
{
|
||||
return Lizard_createStream(LIZARD_MIN_CLEVEL);
|
||||
}
|
||||
|
||||
Lizard_stream_t* Lizard_resetStream_MinLevel(Lizard_stream_t* Lizard_stream)
|
||||
{
|
||||
return Lizard_resetStream (Lizard_stream, LIZARD_MIN_CLEVEL);
|
||||
}
|
||||
208
C/lizard/lizard_compress.h
Normal file
208
C/lizard/lizard_compress.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Lizard - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2016, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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 :
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
#ifndef LIZARD_H_2983
|
||||
#define LIZARD_H_2983
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lizard_compress.h provides block compression functions. It gives full buffer control to user.
|
||||
* Block compression functions are not-enough to send information,
|
||||
* since it's still necessary to provide metadata (such as compressed size),
|
||||
* and each application can do it in whichever way it wants.
|
||||
* For interoperability, there is Lizard frame specification (lizard_Frame_format.md).
|
||||
* A library is provided to take care of it, see lizard_frame.h.
|
||||
*/
|
||||
|
||||
|
||||
/*^***************************************************************
|
||||
* Export parameters
|
||||
*****************************************************************/
|
||||
/*
|
||||
* LIZARD_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
*/
|
||||
#if defined(LIZARD_DLL_EXPORT) && (LIZARD_DLL_EXPORT==1)
|
||||
# define LIZARDLIB_API __declspec(dllexport)
|
||||
#elif defined(LIZARD_DLL_IMPORT) && (LIZARD_DLL_IMPORT==1)
|
||||
# define LIZARDLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define LIZARDLIB_API
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Version
|
||||
**************************************/
|
||||
#define LIZARD_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LIZARD_VERSION_MINOR 0 /* for new (non-breaking) interface capabilities */
|
||||
#define LIZARD_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
|
||||
|
||||
#define LIZARD_VERSION_NUMBER (LIZARD_VERSION_MAJOR *100*100 + LIZARD_VERSION_MINOR *100 + LIZARD_VERSION_RELEASE)
|
||||
int Lizard_versionNumber (void);
|
||||
|
||||
#define LIZARD_LIB_VERSION LIZARD_VERSION_MAJOR.LIZARD_VERSION_MINOR.LIZARD_VERSION_RELEASE
|
||||
#define LIZARD_QUOTE(str) #str
|
||||
#define LIZARD_EXPAND_AND_QUOTE(str) LIZARD_QUOTE(str)
|
||||
#define LIZARD_VERSION_STRING LIZARD_EXPAND_AND_QUOTE(LIZARD_LIB_VERSION)
|
||||
const char* Lizard_versionString (void);
|
||||
|
||||
typedef struct Lizard_stream_s Lizard_stream_t;
|
||||
|
||||
#define LIZARD_MIN_CLEVEL 10 /* minimum compression level */
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
#define LIZARD_MAX_CLEVEL 49 /* maximum compression level */
|
||||
#else
|
||||
#define LIZARD_MAX_CLEVEL 29 /* maximum compression level */
|
||||
#endif
|
||||
#define LIZARD_DEFAULT_CLEVEL 17
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
|
||||
LIZARDLIB_API int Lizard_compress (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
|
||||
/*
|
||||
Lizard_compress() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= Lizard_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 LIZARD_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
|
||||
*/
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LIZARD_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LIZARD_BLOCK_SIZE (1<<17)
|
||||
#define LIZARD_BLOCK64K_SIZE (1<<16)
|
||||
#define LIZARD_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LIZARD_MAX_INPUT_SIZE ? 0 : (isize) + 1 + 1 + ((isize/LIZARD_BLOCK_SIZE)+1)*4)
|
||||
|
||||
|
||||
/*!
|
||||
Lizard_compressBound() :
|
||||
Provides the maximum size that Lizard 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 LIZARD_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that Lizard_compress() compress faster when dest buffer size is >= Lizard_compressBound(srcSize)
|
||||
inputSize : max supported value is LIZARD_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LIZARD_MAX_INPUT_SIZE)
|
||||
*/
|
||||
LIZARDLIB_API int Lizard_compressBound(int inputSize);
|
||||
|
||||
|
||||
/*!
|
||||
Lizard_compress_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use Lizard_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.
|
||||
*/
|
||||
LIZARDLIB_API int Lizard_sizeofState(int compressionLevel);
|
||||
|
||||
LIZARDLIB_API int Lizard_compress_extState(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
|
||||
|
||||
|
||||
/*-*********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
|
||||
/*! Lizard_createStream() will allocate and initialize an `Lizard_stream_t` structure.
|
||||
* Lizard_freeStream() releases its memory.
|
||||
* In the context of a DLL (liblizard), please use these methods rather than the static struct.
|
||||
* They are more future proof, in case of a change of `Lizard_stream_t` size.
|
||||
*/
|
||||
LIZARDLIB_API Lizard_stream_t* Lizard_createStream(int compressionLevel);
|
||||
LIZARDLIB_API int Lizard_freeStream (Lizard_stream_t* streamPtr);
|
||||
|
||||
|
||||
/*! Lizard_resetStream() :
|
||||
* Use this function to reset/reuse an allocated `Lizard_stream_t` structure
|
||||
*/
|
||||
LIZARDLIB_API Lizard_stream_t* Lizard_resetStream (Lizard_stream_t* streamPtr, int compressionLevel);
|
||||
|
||||
|
||||
/*! Lizard_loadDict() :
|
||||
* Use this function to load a static dictionary into Lizard_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 <= LIZARD_DICT_SIZE)
|
||||
*/
|
||||
LIZARDLIB_API int Lizard_loadDict (Lizard_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
|
||||
/*! Lizard_compress_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 >= Lizard_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.
|
||||
*/
|
||||
LIZARDLIB_API int Lizard_compress_continue (Lizard_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
|
||||
|
||||
/*! Lizard_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 Lizard_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call Lizard_compress_continue().
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
|
||||
*/
|
||||
LIZARDLIB_API int Lizard_saveDict (Lizard_stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZARD_H_2983827168210 */
|
||||
@@ -1,13 +1,13 @@
|
||||
#define LIZ_FREQ_DIV 5
|
||||
#define LIZARD_FREQ_DIV 5
|
||||
|
||||
FORCE_INLINE void LIZ_setLog2Prices(LIZ_stream_t* ctx)
|
||||
FORCE_INLINE void Lizard_setLog2Prices(Lizard_stream_t* ctx)
|
||||
{
|
||||
ctx->log2LitSum = LIZ_highbit32(ctx->litSum+1);
|
||||
ctx->log2FlagSum = LIZ_highbit32(ctx->flagSum+1);
|
||||
ctx->log2LitSum = Lizard_highbit32(ctx->litSum+1);
|
||||
ctx->log2FlagSum = Lizard_highbit32(ctx->flagSum+1);
|
||||
}
|
||||
|
||||
|
||||
MEM_STATIC void LIZ_rescaleFreqs(LIZ_stream_t* ctx)
|
||||
MEM_STATIC void Lizard_rescaleFreqs(Lizard_stream_t* ctx)
|
||||
{
|
||||
unsigned u;
|
||||
|
||||
@@ -29,19 +29,19 @@ MEM_STATIC void LIZ_rescaleFreqs(LIZ_stream_t* ctx)
|
||||
ctx->flagSum = 0;
|
||||
|
||||
for (u=0; u < 256; u++) {
|
||||
ctx->litFreq[u] = 1 + (ctx->litFreq[u]>>LIZ_FREQ_DIV);
|
||||
ctx->litFreq[u] = 1 + (ctx->litFreq[u]>>LIZARD_FREQ_DIV);
|
||||
ctx->litSum += ctx->litFreq[u];
|
||||
ctx->flagFreq[u] = 1 + (ctx->flagFreq[u]>>LIZ_FREQ_DIV);
|
||||
ctx->flagFreq[u] = 1 + (ctx->flagFreq[u]>>LIZARD_FREQ_DIV);
|
||||
ctx->flagSum += ctx->flagFreq[u];
|
||||
}
|
||||
}
|
||||
|
||||
LIZ_setLog2Prices(ctx);
|
||||
Lizard_setLog2Prices(ctx);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_encodeSequence_LIZv1 (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor,
|
||||
size_t matchLength,
|
||||
@@ -51,9 +51,9 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
size_t length = (size_t)(*ip - *anchor);
|
||||
BYTE* token = (ctx->flagsPtr)++;
|
||||
|
||||
if (length > 0 || offset < LIZ_MAX_16BIT_OFFSET) {
|
||||
if (length > 0 || offset < LIZARD_MAX_16BIT_OFFSET) {
|
||||
/* Encode Literal length */
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - length - LIZ_LENGTH_SIZE_LZ5v2(length) - WILDCOPYLENGTH)) { LIZ_LOG_COMPRESS_LZ5v2("encodeSequence overflow1\n"); return 1; } /* Check output limit */
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - length - LIZARD_LENGTH_SIZE_LIZv1(length) - WILDCOPYLENGTH)) { LIZARD_LOG_COMPRESS_LIZv1("encodeSequence overflow1\n"); return 1; } /* Check output limit */
|
||||
if (length >= MAX_SHORT_LITLEN)
|
||||
{ size_t len;
|
||||
*token = MAX_SHORT_LITLEN;
|
||||
@@ -65,14 +65,14 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
else *token = (BYTE)length;
|
||||
|
||||
/* Copy Literals */
|
||||
LIZ_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
Lizard_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
if (ctx->huffType) {
|
||||
ctx->litSum += (U32)length;
|
||||
ctx->litPriceSum += (U32)(length * ctx->log2LitSum);
|
||||
{ U32 u;
|
||||
for (u=0; u < length; u++) {
|
||||
ctx->litPriceSum -= LIZ_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);
|
||||
ctx->litPriceSum -= Lizard_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);
|
||||
ctx->litFreq[ctx->literalsPtr[u]]++;
|
||||
} }
|
||||
}
|
||||
@@ -80,10 +80,10 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
ctx->literalsPtr += length;
|
||||
|
||||
|
||||
if (offset >= LIZ_MAX_16BIT_OFFSET) {
|
||||
COMPLOG_CODEWORDS_LZ5v2("T32+ literal=%u match=%u offset=%d\n", (U32)length, 0, 0);
|
||||
if (offset >= LIZARD_MAX_16BIT_OFFSET) {
|
||||
COMPLOG_CODEWORDS_LIZv1("T32+ literal=%u match=%u offset=%d\n", (U32)length, 0, 0);
|
||||
*token+=(1<<ML_RUN_BITS);
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
if (ctx->huffType) {
|
||||
ctx->flagFreq[*token]++;
|
||||
ctx->flagSum++;
|
||||
@@ -94,23 +94,23 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
}
|
||||
|
||||
/* Encode Offset */
|
||||
if (offset >= LIZ_MAX_16BIT_OFFSET) // 24-bit offset
|
||||
if (offset >= LIZARD_MAX_16BIT_OFFSET) // 24-bit offset
|
||||
{
|
||||
if (matchLength < MM_LONGOFF) printf("ERROR matchLength=%d/%d\n", (int)matchLength, MM_LONGOFF), exit(0);
|
||||
if (matchLength < MM_LONGOFF) printf("ERROR matchLength=%d/%d\n", (int)matchLength, MM_LONGOFF), exit(1);
|
||||
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 8 /*LIZ_LENGTH_SIZE_LZ5v2(length)*/)) { LIZ_LOG_COMPRESS_LZ5v2("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
if (matchLength - MM_LONGOFF >= LIZ_LAST_LONG_OFF)
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 8 /*LIZARD_LENGTH_SIZE_LIZv1(length)*/)) { LIZARD_LOG_COMPRESS_LIZv1("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
if (matchLength - MM_LONGOFF >= LIZARD_LAST_LONG_OFF)
|
||||
{
|
||||
size_t len = matchLength - MM_LONGOFF - LIZ_LAST_LONG_OFF;
|
||||
*token = LIZ_LAST_LONG_OFF;
|
||||
size_t len = matchLength - MM_LONGOFF - LIZARD_LAST_LONG_OFF;
|
||||
*token = LIZARD_LAST_LONG_OFF;
|
||||
if (len >= (1<<16)) { *(ctx->literalsPtr) = 255; MEM_writeLE24(ctx->literalsPtr+1, (U32)(len)); ctx->literalsPtr += 4; }
|
||||
else if (len >= 254) { *(ctx->literalsPtr) = 254; MEM_writeLE16(ctx->literalsPtr+1, (U16)(len)); ctx->literalsPtr += 3; }
|
||||
else *(ctx->literalsPtr)++ = (BYTE)len;
|
||||
COMPLOG_CODEWORDS_LZ5v2("T31 literal=%u match=%u offset=%d\n", 0, (U32)matchLength, offset);
|
||||
COMPLOG_CODEWORDS_LIZv1("T31 literal=%u match=%u offset=%d\n", 0, (U32)matchLength, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
COMPLOG_CODEWORDS_LZ5v2("T0-30 literal=%u match=%u offset=%d\n", 0, (U32)matchLength, offset);
|
||||
COMPLOG_CODEWORDS_LIZv1("T0-30 literal=%u match=%u offset=%d\n", 0, (U32)matchLength, offset);
|
||||
*token = (BYTE)(matchLength - MM_LONGOFF);
|
||||
}
|
||||
|
||||
@@ -121,15 +121,16 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
}
|
||||
else
|
||||
{
|
||||
COMPLOG_CODEWORDS_LZ5v2("T32+ literal=%u match=%u offset=%d\n", (U32)length, (U32)matchLength, offset);
|
||||
COMPLOG_CODEWORDS_LIZv1("T32+ literal=%u match=%u offset=%d\n", (U32)length, (U32)matchLength, offset);
|
||||
if (offset == 0)
|
||||
{
|
||||
*token+=(1<<ML_RUN_BITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset < 8) printf("ERROR offset=%d\n", (int)offset);
|
||||
if (matchLength < MINMATCH) { printf("matchLength[%d] < MINMATCH offset=%d\n", (int)matchLength, (int)ctx->last_off); exit(1); }
|
||||
// it should never happen
|
||||
if (offset < 8) { printf("ERROR offset=%d\n", (int)offset); exit(1); }
|
||||
if (matchLength < MINMATCH) { printf("ERROR matchLength[%d] < MINMATCH offset=%d\n", (int)matchLength, (int)ctx->last_off); exit(1); }
|
||||
|
||||
ctx->last_off = offset;
|
||||
MEM_writeLE16(ctx->offset16Ptr, (U16)ctx->last_off); ctx->offset16Ptr += 2;
|
||||
@@ -137,22 +138,22 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
|
||||
/* Encode MatchLength */
|
||||
length = matchLength;
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 5 /*LIZ_LENGTH_SIZE_LZ5v2(length)*/)) { LIZ_LOG_COMPRESS_LZ5v2("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
// if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 5 /*LIZARD_LENGTH_SIZE_LIZv1(length)*/)) { LIZARD_LOG_COMPRESS_LIZv1("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
if (length >= MAX_SHORT_MATCHLEN) {
|
||||
*token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LZ5v2);
|
||||
*token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LIZv1);
|
||||
length -= MAX_SHORT_MATCHLEN;
|
||||
if (length >= (1<<16)) { *(ctx->literalsPtr) = 255; MEM_writeLE24(ctx->literalsPtr+1, (U32)(length)); ctx->literalsPtr += 4; }
|
||||
else if (length >= 254) { *(ctx->literalsPtr) = 254; MEM_writeLE16(ctx->literalsPtr+1, (U16)(length)); ctx->literalsPtr += 3; }
|
||||
else *(ctx->literalsPtr)++ = (BYTE)length;
|
||||
}
|
||||
else *token += (BYTE)(length<<RUN_BITS_LZ5v2);
|
||||
else *token += (BYTE)(length<<RUN_BITS_LIZv1);
|
||||
}
|
||||
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
if (ctx->huffType) {
|
||||
ctx->flagFreq[*token]++;
|
||||
ctx->flagSum++;
|
||||
LIZ_setLog2Prices(ctx);
|
||||
Lizard_setLog2Prices(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -164,8 +165,8 @@ FORCE_INLINE int LIZ_encodeSequence_LZ5v2 (
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_encodeLastLiterals_LZ5v2 (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_encodeLastLiterals_LIZv1 (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor)
|
||||
{
|
||||
@@ -178,31 +179,30 @@ FORCE_INLINE int LIZ_encodeLastLiterals_LZ5v2 (
|
||||
}
|
||||
|
||||
|
||||
#define LIZ_PRICE_MULT 1
|
||||
#define LIZ_GET_TOKEN_PRICE_LZ5v2(token) (LIZ_PRICE_MULT * (ctx->log2FlagSum - LIZ_highbit32(ctx->flagFreq[token]+1)))
|
||||
#define LIZARD_PRICE_MULT 1
|
||||
#define LIZARD_GET_TOKEN_PRICE_LIZv1(token) (LIZARD_PRICE_MULT * (ctx->log2FlagSum - Lizard_highbit32(ctx->flagFreq[token]+1)))
|
||||
|
||||
|
||||
FORCE_INLINE size_t LIZ_get_price_LZ5v2(LIZ_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength)
|
||||
FORCE_INLINE size_t Lizard_get_price_LIZv1(Lizard_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength)
|
||||
{
|
||||
size_t price = 0;
|
||||
BYTE token = 0;
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
const BYTE* literals = ip - litLength;
|
||||
U32 u;
|
||||
if ((ctx->huffType) && (ctx->params.parserType != LIZ_parser_lowestPrice)) {
|
||||
if ((ctx->huffType) && (ctx->params.parserType != Lizard_parser_lowestPrice)) {
|
||||
if (ctx->cachedLiterals == literals && litLength >= ctx->cachedLitLength) {
|
||||
size_t const additional = litLength - ctx->cachedLitLength;
|
||||
// printf("%d ", (int)litLength - (int)ctx->cachedLitLength);
|
||||
const BYTE* literals2 = ctx->cachedLiterals + ctx->cachedLitLength;
|
||||
price = ctx->cachedPrice + LIZ_PRICE_MULT * additional * ctx->log2LitSum;
|
||||
price = ctx->cachedPrice + LIZARD_PRICE_MULT * additional * ctx->log2LitSum;
|
||||
for (u=0; u < additional; u++)
|
||||
price -= LIZ_PRICE_MULT * LIZ_highbit32(ctx->litFreq[literals2[u]]+1);
|
||||
price -= LIZARD_PRICE_MULT * Lizard_highbit32(ctx->litFreq[literals2[u]]+1);
|
||||
ctx->cachedPrice = (U32)price;
|
||||
ctx->cachedLitLength = (U32)litLength;
|
||||
} else {
|
||||
price = LIZ_PRICE_MULT * litLength * ctx->log2LitSum;
|
||||
price = LIZARD_PRICE_MULT * litLength * ctx->log2LitSum;
|
||||
for (u=0; u < litLength; u++)
|
||||
price -= LIZ_PRICE_MULT * LIZ_highbit32(ctx->litFreq[literals[u]]+1);
|
||||
price -= LIZARD_PRICE_MULT * Lizard_highbit32(ctx->litFreq[literals[u]]+1);
|
||||
|
||||
if (litLength >= 12) {
|
||||
ctx->cachedLiterals = literals;
|
||||
@@ -222,7 +222,7 @@ FORCE_INLINE size_t LIZ_get_price_LZ5v2(LIZ_stream_t* const ctx, int rep, const
|
||||
(void)off24pos;
|
||||
(void)rep;
|
||||
|
||||
if (litLength > 0 || offset < LIZ_MAX_16BIT_OFFSET) {
|
||||
if (litLength > 0 || offset < LIZARD_MAX_16BIT_OFFSET) {
|
||||
/* Encode Literal length */
|
||||
if (litLength >= MAX_SHORT_LITLEN)
|
||||
{ size_t len = litLength - MAX_SHORT_LITLEN;
|
||||
@@ -233,22 +233,22 @@ FORCE_INLINE size_t LIZ_get_price_LZ5v2(LIZ_stream_t* const ctx, int rep, const
|
||||
}
|
||||
else token = (BYTE)litLength;
|
||||
|
||||
if (offset >= LIZ_MAX_16BIT_OFFSET) {
|
||||
if (offset >= LIZARD_MAX_16BIT_OFFSET) {
|
||||
token+=(1<<ML_RUN_BITS);
|
||||
if (ctx->huffType && ctx->params.parserType != LIZ_parser_lowestPrice)
|
||||
price += LIZ_GET_TOKEN_PRICE_LZ5v2(token);
|
||||
if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)
|
||||
price += LIZARD_GET_TOKEN_PRICE_LIZv1(token);
|
||||
else
|
||||
price += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode Offset */
|
||||
if (offset >= LIZ_MAX_16BIT_OFFSET) { // 24-bit offset
|
||||
if (matchLength < MM_LONGOFF) return LIZ_MAX_PRICE; // error
|
||||
if (offset >= LIZARD_MAX_16BIT_OFFSET) { // 24-bit offset
|
||||
if (matchLength < MM_LONGOFF) return LIZARD_MAX_PRICE; // error
|
||||
|
||||
if (matchLength - MM_LONGOFF >= LIZ_LAST_LONG_OFF) {
|
||||
size_t len = matchLength - MM_LONGOFF - LIZ_LAST_LONG_OFF;
|
||||
token = LIZ_LAST_LONG_OFF;
|
||||
if (matchLength - MM_LONGOFF >= LIZARD_LAST_LONG_OFF) {
|
||||
size_t len = matchLength - MM_LONGOFF - LIZARD_LAST_LONG_OFF;
|
||||
token = LIZARD_LAST_LONG_OFF;
|
||||
if (len >= (1<<16)) price += 32;
|
||||
else if (len >= 254) price += 24;
|
||||
else price += 8;
|
||||
@@ -262,25 +262,25 @@ FORCE_INLINE size_t LIZ_get_price_LZ5v2(LIZ_stream_t* const ctx, int rep, const
|
||||
if (offset == 0) {
|
||||
token+=(1<<ML_RUN_BITS);
|
||||
} else {
|
||||
if (offset < 8) return LIZ_MAX_PRICE; // error
|
||||
if (matchLength < MINMATCH) return LIZ_MAX_PRICE; // error
|
||||
if (offset < 8) return LIZARD_MAX_PRICE; // error
|
||||
if (matchLength < MINMATCH) return LIZARD_MAX_PRICE; // error
|
||||
price += 16;
|
||||
}
|
||||
|
||||
/* Encode MatchLength */
|
||||
length = matchLength;
|
||||
if (length >= MAX_SHORT_MATCHLEN) {
|
||||
token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LZ5v2);
|
||||
token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LIZv1);
|
||||
length -= MAX_SHORT_MATCHLEN;
|
||||
if (length >= (1<<16)) price += 32;
|
||||
else if (length >= 254) price += 24;
|
||||
else price += 8;
|
||||
}
|
||||
else token += (BYTE)(length<<RUN_BITS_LZ5v2);
|
||||
else token += (BYTE)(length<<RUN_BITS_LIZv1);
|
||||
}
|
||||
|
||||
if (offset > 0 || matchLength > 0) {
|
||||
int offset_load = LIZ_highbit32(offset);
|
||||
int offset_load = Lizard_highbit32(offset);
|
||||
if (ctx->huffType) {
|
||||
price += ((offset_load>=20) ? ((offset_load-19)*4) : 0);
|
||||
price += 4 + (matchLength==1);
|
||||
@@ -288,13 +288,13 @@ FORCE_INLINE size_t LIZ_get_price_LZ5v2(LIZ_stream_t* const ctx, int rep, const
|
||||
price += ((offset_load>=16) ? ((offset_load-15)*4) : 0);
|
||||
price += 6 + (matchLength==1);
|
||||
}
|
||||
if (ctx->huffType && ctx->params.parserType != LIZ_parser_lowestPrice)
|
||||
price += LIZ_GET_TOKEN_PRICE_LZ5v2(token);
|
||||
if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)
|
||||
price += LIZARD_GET_TOKEN_PRICE_LIZv1(token);
|
||||
else
|
||||
price += 8;
|
||||
} else {
|
||||
if (ctx->huffType && ctx->params.parserType != LIZ_parser_lowestPrice)
|
||||
price += LIZ_GET_TOKEN_PRICE_LZ5v2(token); // 1=better ratio
|
||||
if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)
|
||||
price += LIZARD_GET_TOKEN_PRICE_LIZv1(token); // 1=better ratio
|
||||
}
|
||||
|
||||
return price;
|
||||
@@ -1,7 +1,7 @@
|
||||
#define LIZ_LENGTH_SIZE_LZ4(len) ((len >= (1<<16)+RUN_MASK_LZ4) ? 5 : ((len >= 254+RUN_MASK_LZ4) ? 3 : ((len >= RUN_MASK_LZ4) ? 1 : 0)))
|
||||
#define LIZARD_LENGTH_SIZE_LZ4(len) ((len >= (1<<16)+RUN_MASK_LZ4) ? 5 : ((len >= 254+RUN_MASK_LZ4) ? 3 : ((len >= RUN_MASK_LZ4) ? 1 : 0)))
|
||||
|
||||
FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_encodeSequence_LZ4 (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor,
|
||||
size_t matchLength,
|
||||
@@ -14,7 +14,7 @@ FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
COMPLOG_CODEWORDS_LZ4("literal : %u -- match : %u -- offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
|
||||
|
||||
/* Encode Literal length */
|
||||
// if (ctx->literalsPtr > ctx->literalsEnd - length - LIZ_LENGTH_SIZE_LZ4(length) - 2 - WILDCOPYLENGTH) { LIZ_LOG_COMPRESS_LZ4("encodeSequence overflow1\n"); return 1; } /* Check output limit */
|
||||
// if (ctx->literalsPtr > ctx->literalsEnd - length - LIZARD_LENGTH_SIZE_LZ4(length) - 2 - WILDCOPYLENGTH) { LIZARD_LOG_COMPRESS_LZ4("encodeSequence overflow1\n"); return 1; } /* Check output limit */
|
||||
if (length >= RUN_MASK_LZ4)
|
||||
{ size_t len = length - RUN_MASK_LZ4;
|
||||
*token = RUN_MASK_LZ4;
|
||||
@@ -26,13 +26,13 @@ FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
|
||||
/* Copy Literals */
|
||||
if (length > 0) {
|
||||
LIZ_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);
|
||||
#if 0 //def LIZ_USE_HUFFMAN
|
||||
Lizard_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);
|
||||
#if 0 //def LIZARD_USE_HUFFMAN
|
||||
ctx->litSum += (U32)length;
|
||||
ctx->litPriceSum += (U32)(length * ctx->log2LitSum);
|
||||
{ U32 u;
|
||||
for (u=0; u < length; u++) {
|
||||
ctx->litPriceSum -= LIZ_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);
|
||||
ctx->litPriceSum -= Lizard_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);
|
||||
ctx->litFreq[ctx->literalsPtr[u]]++;
|
||||
} }
|
||||
#endif
|
||||
@@ -40,14 +40,12 @@ FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
}
|
||||
|
||||
/* Encode Offset */
|
||||
// if (match > *ip) printf("match > *ip\n"), exit(1);
|
||||
// if ((U32)(*ip-match) >= (1<<16)) printf("off=%d\n", (U32)(*ip-match)), exit(1);
|
||||
MEM_writeLE16(ctx->literalsPtr, (U16)(*ip-match));
|
||||
ctx->literalsPtr+=2;
|
||||
|
||||
/* Encode MatchLength */
|
||||
length = matchLength - MINMATCH;
|
||||
// if (ctx->literalsPtr > ctx->literalsEnd - 5 /*LIZ_LENGTH_SIZE_LZ4(length)*/) { LIZ_LOG_COMPRESS_LZ4("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
// if (ctx->literalsPtr > ctx->literalsEnd - 5 /*LIZARD_LENGTH_SIZE_LZ4(length)*/) { LIZARD_LOG_COMPRESS_LZ4("encodeSequence overflow2\n"); return 1; } /* Check output limit */
|
||||
if (length >= ML_MASK_LZ4) {
|
||||
*token += (BYTE)(ML_MASK_LZ4<<RUN_BITS_LZ4);
|
||||
length -= ML_MASK_LZ4;
|
||||
@@ -57,11 +55,11 @@ FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
}
|
||||
else *token += (BYTE)(length<<RUN_BITS_LZ4);
|
||||
|
||||
#ifndef LIZ_NO_HUFFMAN
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
if (ctx->huffType) {
|
||||
ctx->flagFreq[*token]++;
|
||||
ctx->flagSum++;
|
||||
LIZ_setLog2Prices(ctx);
|
||||
Lizard_setLog2Prices(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,8 +71,8 @@ FORCE_INLINE int LIZ_encodeSequence_LZ4 (
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_encodeLastLiterals_LZ4 (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_encodeLastLiterals_LZ4 (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE** ip,
|
||||
const BYTE** anchor)
|
||||
{
|
||||
@@ -88,29 +86,28 @@ FORCE_INLINE int LIZ_encodeLastLiterals_LZ4 (
|
||||
}
|
||||
|
||||
|
||||
#define LIZ_GET_TOKEN_PRICE_LZ4(token) (ctx->log2FlagSum - LIZ_highbit32(ctx->flagFreq[token]+1))
|
||||
#define LIZARD_GET_TOKEN_PRICE_LZ4(token) (ctx->log2FlagSum - Lizard_highbit32(ctx->flagFreq[token]+1))
|
||||
|
||||
FORCE_INLINE size_t LIZ_get_price_LZ4(LIZ_stream_t* const ctx, const BYTE *ip, const size_t litLength, U32 offset, size_t matchLength)
|
||||
FORCE_INLINE size_t Lizard_get_price_LZ4(Lizard_stream_t* const ctx, const BYTE *ip, const size_t litLength, U32 offset, size_t matchLength)
|
||||
{
|
||||
size_t price = 0;
|
||||
BYTE token = 0;
|
||||
#if 0 //def LIZ_USE_HUFFMAN
|
||||
#if 0 //def LIZARD_USE_HUFFMAN
|
||||
const BYTE* literals = ip - litLength;
|
||||
U32 u;
|
||||
|
||||
if (ctx->cachedLiterals == literals && litLength >= ctx->cachedLitLength) {
|
||||
size_t const additional = litLength - ctx->cachedLitLength;
|
||||
// printf("%d ", (int)litLength - (int)ctx->cachedLitLength);
|
||||
const BYTE* literals2 = ctx->cachedLiterals + ctx->cachedLitLength;
|
||||
price = ctx->cachedPrice + additional * ctx->log2LitSum;
|
||||
for (u=0; u < additional; u++)
|
||||
price -= LIZ_highbit32(ctx->litFreq[literals2[u]]+1);
|
||||
price -= Lizard_highbit32(ctx->litFreq[literals2[u]]+1);
|
||||
ctx->cachedPrice = (U32)price;
|
||||
ctx->cachedLitLength = (U32)litLength;
|
||||
} else {
|
||||
price = litLength * ctx->log2LitSum;
|
||||
for (u=0; u < litLength; u++)
|
||||
price -= LIZ_highbit32(ctx->litFreq[literals[u]]+1);
|
||||
price -= Lizard_highbit32(ctx->litFreq[literals[u]]+1);
|
||||
|
||||
if (litLength >= 12) {
|
||||
ctx->cachedLiterals = literals;
|
||||
@@ -140,8 +137,8 @@ FORCE_INLINE size_t LIZ_get_price_LZ4(LIZ_stream_t* const ctx, const BYTE *ip, c
|
||||
size_t length;
|
||||
price += 16; /* Encode Offset */
|
||||
|
||||
if (offset < 8) return LIZ_MAX_PRICE; // error
|
||||
if (matchLength < MINMATCH) return LIZ_MAX_PRICE; // error
|
||||
if (offset < 8) return LIZARD_MAX_PRICE; // error
|
||||
if (matchLength < MINMATCH) return LIZARD_MAX_PRICE; // error
|
||||
|
||||
length = matchLength - MINMATCH;
|
||||
if (length >= ML_MASK_LZ4) {
|
||||
@@ -156,7 +153,7 @@ FORCE_INLINE size_t LIZ_get_price_LZ4(LIZ_stream_t* const ctx, const BYTE *ip, c
|
||||
|
||||
if (ctx->huffType) {
|
||||
if (offset > 0 || matchLength > 0) price += 2;
|
||||
price += LIZ_GET_TOKEN_PRICE_LZ4(token);
|
||||
price += LIZARD_GET_TOKEN_PRICE_LZ4(token);
|
||||
} else {
|
||||
price += 8; // token
|
||||
}
|
||||
372
C/lizard/lizard_decompress.c
Normal file
372
C/lizard/lizard_decompress.c
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
Lizard - Fast LZ compression algorithm
|
||||
Copyright (C) 2011-2016, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
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 :
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
//#define LIZARD_STATS 1 // 0=simple stats, 1=more, 2=full
|
||||
#ifdef LIZARD_STATS
|
||||
#include "test/lizard_stats.h"
|
||||
#endif
|
||||
#include "lizard_compress.h"
|
||||
#include "lizard_decompress.h"
|
||||
#include "lizard_common.h"
|
||||
#include <stdio.h> // printf
|
||||
#include <stdint.h> // intptr_t
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Local Structures and types
|
||||
**************************************/
|
||||
typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
|
||||
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
|
||||
|
||||
#include "lizard_decompress_lz4.h"
|
||||
#ifndef USE_LZ4_ONLY
|
||||
#ifdef LIZARD_USE_TEST
|
||||
#include "test/lizard_common_test.h"
|
||||
#include "test/lizard_decompress_test.h"
|
||||
#else
|
||||
#include "lizard_decompress_liz.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "../zstd/huf.h"
|
||||
|
||||
|
||||
/*-*****************************
|
||||
* Decompression functions
|
||||
*******************************/
|
||||
|
||||
FORCE_INLINE size_t Lizard_readStream(int flag, const BYTE** ip, const BYTE* const iend, BYTE* op, BYTE* const oend, const BYTE** streamPtr, const BYTE** streamEnd, int streamFlag)
|
||||
{
|
||||
if (!flag) {
|
||||
if (*ip > iend - 3) return 0;
|
||||
*streamPtr = *ip + 3;
|
||||
*streamEnd = *streamPtr + MEM_readLE24(*ip);
|
||||
if (*streamEnd < *streamPtr) return 0;
|
||||
*ip = *streamEnd;
|
||||
#ifdef LIZARD_STATS
|
||||
uncompr_stream[streamFlag] += *streamEnd-*streamPtr;
|
||||
#else
|
||||
(void)streamFlag;
|
||||
#endif
|
||||
return 1;
|
||||
} else {
|
||||
#ifndef LIZARD_NO_HUFFMAN
|
||||
size_t res, streamLen, comprStreamLen;
|
||||
|
||||
if (*ip > iend - 6) return 0;
|
||||
streamLen = MEM_readLE24(*ip);
|
||||
comprStreamLen = MEM_readLE24(*ip + 3);
|
||||
|
||||
if ((op > oend - streamLen) || (*ip + comprStreamLen > iend - 6)) return 0;
|
||||
res = HUF_decompress(op, streamLen, *ip + 6, comprStreamLen);
|
||||
if (HUF_isError(res) || (res != streamLen)) return 0;
|
||||
|
||||
*ip += comprStreamLen + 6;
|
||||
*streamPtr = op;
|
||||
*streamEnd = *streamPtr + streamLen;
|
||||
#ifdef LIZARD_STATS
|
||||
compr_stream[streamFlag] += comprStreamLen + 6;
|
||||
decompr_stream[streamFlag] += *streamEnd-*streamPtr;
|
||||
#endif
|
||||
return 1;
|
||||
#else
|
||||
fprintf(stderr, "compiled with LIZARD_NO_HUFFMAN\n");
|
||||
(void)op; (void)oend;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_decompress_generic(
|
||||
const char* source,
|
||||
char* const dest,
|
||||
int inputSize,
|
||||
int outputSize, /* this value is the max size of Output Buffer. */
|
||||
int partialDecoding, /* full, partial */
|
||||
int targetOutputSize, /* only used if partialDecoding==partial */
|
||||
int dict, /* noDict, withPrefix64k, usingExtDict */
|
||||
const BYTE* const lowPrefix, /* == dest if dict == noDict */
|
||||
const BYTE* const dictStart, /* only if dict==usingExtDict */
|
||||
const size_t dictSize /* note : = 0 if noDict */
|
||||
)
|
||||
{
|
||||
/* Local Variables */
|
||||
const BYTE* ip = (const BYTE*) source, *istart = (const BYTE*) source;
|
||||
const BYTE* const iend = ip + inputSize;
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + outputSize;
|
||||
BYTE* oexit = op + targetOutputSize;
|
||||
Lizard_parameters params;
|
||||
Lizard_dstream_t ctx;
|
||||
BYTE* decompFlagsBase, *decompOff24Base, *decompOff16Base, *decompLiteralsBase = NULL;
|
||||
int res, compressionLevel;
|
||||
|
||||
if (inputSize < 1) { LIZARD_LOG_DECOMPRESS("inputSize=%d outputSize=%d targetOutputSize=%d partialDecoding=%d\n", inputSize, outputSize, targetOutputSize, partialDecoding); return 0; }
|
||||
|
||||
compressionLevel = *ip++;
|
||||
|
||||
if (compressionLevel < LIZARD_MIN_CLEVEL || compressionLevel > LIZARD_MAX_CLEVEL) {
|
||||
LIZARD_LOG_DECOMPRESS("ERROR Lizard_decompress_generic inputSize=%d compressionLevel=%d\n", inputSize, compressionLevel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LIZARD_LOG_DECOMPRESS("Lizard_decompress_generic ip=%p inputSize=%d targetOutputSize=%d dest=%p outputSize=%d cLevel=%d dict=%d dictSize=%d dictStart=%p partialDecoding=%d\n", ip, inputSize, targetOutputSize, dest, outputSize, compressionLevel, dict, (int)dictSize, dictStart, partialDecoding);
|
||||
|
||||
decompLiteralsBase = (BYTE*)malloc(4*LIZARD_HUF_BLOCK_SIZE);
|
||||
if (!decompLiteralsBase) return -1;
|
||||
decompFlagsBase = decompLiteralsBase + LIZARD_HUF_BLOCK_SIZE;
|
||||
decompOff24Base = decompFlagsBase + LIZARD_HUF_BLOCK_SIZE;
|
||||
decompOff16Base = decompOff24Base + LIZARD_HUF_BLOCK_SIZE;
|
||||
|
||||
#ifdef LIZARD_STATS
|
||||
init_stats();
|
||||
#endif
|
||||
(void)istart;
|
||||
|
||||
while (ip < iend)
|
||||
{
|
||||
res = *ip++;
|
||||
if (res == LIZARD_FLAG_UNCOMPRESSED) /* uncompressed */
|
||||
{
|
||||
uint32_t length;
|
||||
if (ip > iend - 3) { LIZARD_LOG_DECOMPRESS("UNCOMPRESSED ip[%p] > iend[%p] - 3\n", ip, iend); goto _output_error; }
|
||||
length = MEM_readLE24(ip);
|
||||
ip += 3;
|
||||
// printf("%d: total=%d block=%d UNCOMPRESSED op=%p oexit=%p oend=%p\n", (int)(op-(BYTE*)dest) ,(int)(ip-istart), length, op, oexit, oend);
|
||||
if (ip + length > iend || op + length > oend) { LIZARD_LOG_DECOMPRESS("UNCOMPRESSED ip[%p]+length[%d] > iend[%p]\n", ip, length, iend); goto _output_error; }
|
||||
memcpy(op, ip, length);
|
||||
op += length;
|
||||
ip += length;
|
||||
if ((partialDecoding) && (op >= oexit)) break;
|
||||
#ifdef LIZARD_STATS
|
||||
uncompr_stream[LIZARD_STREAM_UNCOMPRESSED] += length;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (res&LIZARD_FLAG_LEN) {
|
||||
LIZARD_LOG_DECOMPRESS("res=%d\n", res); goto _output_error;
|
||||
}
|
||||
|
||||
if (ip > iend - 5*3) goto _output_error;
|
||||
ctx.lenPtr = (const BYTE*)ip + 3;
|
||||
ctx.lenEnd = ctx.lenPtr + MEM_readLE24(ip);
|
||||
if (ctx.lenEnd < ctx.lenPtr || (ctx.lenEnd > iend - 3)) goto _output_error;
|
||||
#ifdef LIZARD_STATS
|
||||
uncompr_stream[LIZARD_STREAM_LEN] += ctx.lenEnd-ctx.lenPtr + 3;
|
||||
#endif
|
||||
ip = ctx.lenEnd;
|
||||
|
||||
{ size_t streamLen;
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
const BYTE* ipos;
|
||||
size_t comprFlagsLen, comprLiteralsLen, total;
|
||||
#endif
|
||||
streamLen = Lizard_readStream(res&LIZARD_FLAG_OFFSET16, &ip, iend, decompOff16Base, decompOff16Base + LIZARD_HUF_BLOCK_SIZE, &ctx.offset16Ptr, &ctx.offset16End, LIZARD_STREAM_OFFSET16);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
|
||||
streamLen = Lizard_readStream(res&LIZARD_FLAG_OFFSET24, &ip, iend, decompOff24Base, decompOff24Base + LIZARD_HUF_BLOCK_SIZE, &ctx.offset24Ptr, &ctx.offset24End, LIZARD_STREAM_OFFSET24);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
ipos = ip;
|
||||
streamLen = Lizard_readStream(res&LIZARD_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZARD_STREAM_FLAGS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
streamLen = (size_t)(ctx.flagsEnd-ctx.flagsPtr);
|
||||
comprFlagsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);
|
||||
ipos = ip;
|
||||
#else
|
||||
streamLen = Lizard_readStream(res&LIZARD_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZARD_STREAM_FLAGS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
#endif
|
||||
|
||||
streamLen = Lizard_readStream(res&LIZARD_FLAG_LITERALS, &ip, iend, decompLiteralsBase, decompLiteralsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.literalsPtr, &ctx.literalsEnd, LIZARD_STREAM_LITERALS);
|
||||
if (streamLen == 0) goto _output_error;
|
||||
#ifdef LIZARD_USE_LOGS
|
||||
streamLen = (size_t)(ctx.literalsEnd-ctx.literalsPtr);
|
||||
comprLiteralsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);
|
||||
total = (size_t)(ip-(ctx.lenEnd-1));
|
||||
#endif
|
||||
|
||||
if (ip > iend) goto _output_error;
|
||||
|
||||
LIZARD_LOG_DECOMPRESS("%d: total=%d block=%d flagsLen=%d(HUF=%d) literalsLen=%d(HUF=%d) offset16Len=%d offset24Len=%d lengthsLen=%d \n", (int)(op-(BYTE*)dest) ,(int)(ip-istart), (int)total,
|
||||
(int)(ctx.flagsEnd-ctx.flagsPtr), (int)comprFlagsLen, (int)(ctx.literalsEnd-ctx.literalsPtr), (int)comprLiteralsLen,
|
||||
(int)(ctx.offset16End-ctx.offset16Ptr), (int)(ctx.offset24End-ctx.offset24Ptr), (int)(ctx.lenEnd-ctx.lenPtr));
|
||||
}
|
||||
|
||||
ctx.last_off = -LIZARD_INIT_LAST_OFFSET;
|
||||
params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];
|
||||
if (params.decompressType == Lizard_coderwords_LZ4)
|
||||
res = Lizard_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
else
|
||||
#ifdef USE_LZ4_ONLY
|
||||
res = Lizard_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
#else
|
||||
res = Lizard_decompress_LIZv1(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);
|
||||
#endif
|
||||
LIZARD_LOG_DECOMPRESS("Lizard_decompress_generic res=%d inputSize=%d\n", res, (int)(ctx.literalsEnd-ctx.lenEnd));
|
||||
|
||||
if (res <= 0) { free(decompLiteralsBase); return res; }
|
||||
|
||||
op += res;
|
||||
outputSize -= res;
|
||||
if ((partialDecoding) && (op >= oexit)) break;
|
||||
}
|
||||
|
||||
#ifdef LIZARD_STATS
|
||||
print_stats();
|
||||
#endif
|
||||
|
||||
LIZARD_LOG_DECOMPRESS("Lizard_decompress_generic total=%d\n", (int)(op-(BYTE*)dest));
|
||||
free(decompLiteralsBase);
|
||||
return (int)(op-(BYTE*)dest);
|
||||
|
||||
_output_error:
|
||||
LIZARD_LOG_DECOMPRESS("Lizard_decompress_generic ERROR ip=%p iend=%p\n", ip, iend);
|
||||
free(decompLiteralsBase);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Lizard_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
|
||||
{
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxDecompressedSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
|
||||
}
|
||||
|
||||
int Lizard_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
|
||||
{
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxDecompressedSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*===== streaming decompression functions =====*/
|
||||
|
||||
|
||||
/*
|
||||
* If you prefer dynamic allocation methods,
|
||||
* Lizard_createStreamDecode()
|
||||
* provides a pointer (void*) towards an initialized Lizard_streamDecode_t structure.
|
||||
*/
|
||||
Lizard_streamDecode_t* Lizard_createStreamDecode(void)
|
||||
{
|
||||
Lizard_streamDecode_t* lizards = (Lizard_streamDecode_t*) ALLOCATOR(1, sizeof(Lizard_streamDecode_t));
|
||||
return lizards;
|
||||
}
|
||||
|
||||
int Lizard_freeStreamDecode (Lizard_streamDecode_t* Lizard_stream)
|
||||
{
|
||||
FREEMEM(Lizard_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Lizard_setStreamDecode() :
|
||||
* Use this function to instruct where to find the dictionary.
|
||||
* This function is not necessary if previous data is still available where it was decoded.
|
||||
* Loading a size of 0 is allowed (same effect as no dictionary).
|
||||
* Return : 1 if OK, 0 if error
|
||||
*/
|
||||
int Lizard_setStreamDecode (Lizard_streamDecode_t* Lizard_streamDecode, const char* dictionary, int dictSize)
|
||||
{
|
||||
Lizard_streamDecode_t* lizardsd = (Lizard_streamDecode_t*) Lizard_streamDecode;
|
||||
lizardsd->prefixSize = (size_t) dictSize;
|
||||
lizardsd->prefixEnd = (const BYTE*) dictionary + dictSize;
|
||||
lizardsd->externalDict = NULL;
|
||||
lizardsd->extDictSize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks must still be available at the memory position where they were decoded.
|
||||
If it's not possible, save the relevant part of decoded data into a safe buffer,
|
||||
and indicate where it stands using Lizard_setStreamDecode()
|
||||
*/
|
||||
int Lizard_decompress_safe_continue (Lizard_streamDecode_t* Lizard_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
|
||||
{
|
||||
Lizard_streamDecode_t* lizardsd = (Lizard_streamDecode_t*) Lizard_streamDecode;
|
||||
int result;
|
||||
|
||||
if (lizardsd->prefixEnd == (BYTE*)dest) {
|
||||
result = Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
||||
full, 0, usingExtDict, lizardsd->prefixEnd - lizardsd->prefixSize, lizardsd->externalDict, lizardsd->extDictSize);
|
||||
if (result <= 0) return result;
|
||||
lizardsd->prefixSize += result;
|
||||
lizardsd->prefixEnd += result;
|
||||
} else {
|
||||
lizardsd->extDictSize = lizardsd->prefixSize;
|
||||
lizardsd->externalDict = lizardsd->prefixEnd - lizardsd->extDictSize;
|
||||
result = Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize,
|
||||
full, 0, usingExtDict, (BYTE*)dest, lizardsd->externalDict, lizardsd->extDictSize);
|
||||
if (result <= 0) return result;
|
||||
lizardsd->prefixSize = result;
|
||||
lizardsd->prefixEnd = (BYTE*)dest + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as "_continue" ones,
|
||||
the dictionary must be explicitly provided within parameters
|
||||
*/
|
||||
|
||||
int Lizard_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
if (dictSize==0)
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
|
||||
if (dictStart+dictSize == dest)
|
||||
{
|
||||
if (dictSize >= (int)(LIZARD_DICT_SIZE - 1))
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, withPrefix64k, (BYTE*)dest-LIZARD_DICT_SIZE, NULL, 0);
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
|
||||
}
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
||||
}
|
||||
|
||||
/* debug function */
|
||||
int Lizard_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
|
||||
{
|
||||
return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
LZ5 - Fast LZ compression algorithm
|
||||
Lizard - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
Copyright (C) 2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
Copyright (C) 2011-2016, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
@@ -30,31 +30,31 @@
|
||||
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
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
#ifndef LIZ_DECOMPRESS_H_2983
|
||||
#define LIZ_DECOMPRESS_H_2983
|
||||
#ifndef LIZARD_DECOMPRESS_H_2983
|
||||
#define LIZARD_DECOMPRESS_H_2983
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mem.h" /* U32 */
|
||||
#include "../zstd/mem.h" /* U32 */
|
||||
|
||||
|
||||
/*^***************************************************************
|
||||
* Export parameters
|
||||
*****************************************************************/
|
||||
/*
|
||||
* LIZ_DLL_EXPORT :
|
||||
* LIZARD_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
*/
|
||||
#if defined(LIZ_DLL_EXPORT) && (LIZ_DLL_EXPORT==1)
|
||||
# define LZ5DLIB_API __declspec(dllexport)
|
||||
#elif defined(LIZ_DLL_IMPORT) && (LIZ_DLL_IMPORT==1)
|
||||
# define LZ5DLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#if defined(LIZARD_DLL_EXPORT) && (LIZARD_DLL_EXPORT==1)
|
||||
# define LIZARDDLIB_API __declspec(dllexport)
|
||||
#elif defined(LIZARD_DLL_IMPORT) && (LIZARD_DLL_IMPORT==1)
|
||||
# define LIZARDDLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define LZ5DLIB_API
|
||||
# define LIZARDDLIB_API
|
||||
#endif
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ extern "C" {
|
||||
**************************************/
|
||||
|
||||
/*
|
||||
LIZ_decompress_safe() :
|
||||
Lizard_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)
|
||||
@@ -72,12 +72,12 @@ LIZ_decompress_safe() :
|
||||
This function is protected against buffer overflow exploits, including malicious data packets.
|
||||
It never writes outside output buffer, nor reads outside input buffer.
|
||||
*/
|
||||
LZ5DLIB_API int LIZ_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
LIZARDDLIB_API int Lizard_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
LIZ_decompress_safe_partial() :
|
||||
Lizard_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,
|
||||
@@ -88,7 +88,7 @@ LIZ_decompress_safe_partial() :
|
||||
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
|
||||
*/
|
||||
LZ5DLIB_API int LIZ_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
|
||||
LIZARDDLIB_API int Lizard_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
|
||||
@@ -100,60 +100,60 @@ typedef struct {
|
||||
size_t extDictSize;
|
||||
const BYTE* prefixEnd;
|
||||
size_t prefixSize;
|
||||
} LIZ_streamDecode_t;
|
||||
} Lizard_streamDecode_t;
|
||||
|
||||
/*
|
||||
* LIZ_streamDecode_t
|
||||
* information structure to track an LZ5 stream.
|
||||
* init this structure content using LIZ_setStreamDecode or memset() before first use !
|
||||
* Lizard_streamDecode_t
|
||||
* information structure to track an Lizard stream.
|
||||
* init this structure content using Lizard_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 LIZ_streamDecode_t size in the future.
|
||||
* LIZ_createStreamDecode will allocate and initialize an LIZ_streamDecode_t structure
|
||||
* LIZ_freeStreamDecode releases its memory.
|
||||
* In the context of a DLL (liblizard) please prefer usage of construction methods below.
|
||||
* They are more future proof, in case of a change of Lizard_streamDecode_t size in the future.
|
||||
* Lizard_createStreamDecode will allocate and initialize an Lizard_streamDecode_t structure
|
||||
* Lizard_freeStreamDecode releases its memory.
|
||||
*/
|
||||
LZ5DLIB_API LIZ_streamDecode_t* LIZ_createStreamDecode(void);
|
||||
LZ5DLIB_API int LIZ_freeStreamDecode (LIZ_streamDecode_t* LIZ_stream);
|
||||
LIZARDDLIB_API Lizard_streamDecode_t* Lizard_createStreamDecode(void);
|
||||
LIZARDDLIB_API int Lizard_freeStreamDecode (Lizard_streamDecode_t* Lizard_stream);
|
||||
|
||||
/*! LIZ_setStreamDecode() :
|
||||
/*! Lizard_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
|
||||
*/
|
||||
LZ5DLIB_API int LIZ_setStreamDecode (LIZ_streamDecode_t* LIZ_streamDecode, const char* dictionary, int dictSize);
|
||||
LIZARDDLIB_API int Lizard_setStreamDecode (Lizard_streamDecode_t* Lizard_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 LIZ_DICT_SIZE)
|
||||
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to LIZARD_DICT_SIZE)
|
||||
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 small ones ( < LIZ_DICT_SIZE).
|
||||
In which case, the decoding & encoding ring buffer can have any size, including small ones ( < LIZARD_DICT_SIZE).
|
||||
- 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 ( < LIZ_DICT_SIZE).
|
||||
- _At least_ LIZ_DICT_SIZE + 8 bytes + maxBlockSize.
|
||||
and encoding ring buffer can have any size, including small ones ( < LIZARD_DICT_SIZE).
|
||||
- _At least_ LIZARD_DICT_SIZE + 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 LIZ_DICT_SIZE of decoded data into a safe buffer,
|
||||
and indicate where it is saved using LIZ_setStreamDecode()
|
||||
Whenever these conditions are not possible, save the last LIZARD_DICT_SIZE of decoded data into a safe buffer,
|
||||
and indicate where it is saved using Lizard_setStreamDecode()
|
||||
*/
|
||||
LZ5DLIB_API int LIZ_decompress_safe_continue (LIZ_streamDecode_t* LIZ_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
LIZARDDLIB_API int Lizard_decompress_safe_continue (Lizard_streamDecode_t* Lizard_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
/*
|
||||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as
|
||||
a combination of LIZ_setStreamDecode() followed by LIZ_decompress_x_continue()
|
||||
They are stand-alone. They don't need nor update an LIZ_streamDecode_t structure.
|
||||
a combination of Lizard_setStreamDecode() followed by Lizard_decompress_x_continue()
|
||||
They are stand-alone. They don't need nor update an Lizard_streamDecode_t structure.
|
||||
*/
|
||||
LZ5DLIB_API int LIZ_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
LIZARDDLIB_API int Lizard_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIZ_DECOMPRESS_H_2983827168210 */
|
||||
#endif /* LIZARD_DECOMPRESS_H_2983827168210 */
|
||||
@@ -5,14 +5,14 @@
|
||||
flag 0-30 - 24-bit offset, 31 match lengths (16-46), no literal length
|
||||
*/
|
||||
|
||||
/*! LIZ_decompress_LZ5v2() :
|
||||
/*! Lizard_decompress_LIZv1() :
|
||||
* This generic decompression function cover all use cases.
|
||||
* It shall be instantiated several times, using different sets of directives
|
||||
* Note that it is important this generic function is really inlined,
|
||||
* in order to remove useless branches during compilation optimization.
|
||||
*/
|
||||
FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
LIZ_dstream_t* ctx,
|
||||
FORCE_INLINE int Lizard_decompress_LIZv1(
|
||||
Lizard_dstream_t* ctx,
|
||||
BYTE* const dest,
|
||||
int outputSize, /* this value is the max size of Output Buffer. */
|
||||
|
||||
@@ -37,12 +37,11 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
const BYTE* const lowLimit = lowPrefix - dictSize;
|
||||
const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
|
||||
|
||||
const int checkOffset = (dictSize < (int)(LIZ_DICT_SIZE));
|
||||
const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));
|
||||
|
||||
intptr_t last_off = ctx->last_off;
|
||||
intptr_t length = 0;
|
||||
(void)compressionLevel;
|
||||
(void)LIZ_wildCopy;
|
||||
|
||||
/* Special cases */
|
||||
if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1; /* Empty output buffer */
|
||||
@@ -58,11 +57,10 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
/* get literal length */
|
||||
token = *ctx->flagsPtr++;
|
||||
|
||||
// LIZ_LOG_DECOMPRESS_LZ5v2("token : %u\n", (U32)token);
|
||||
if (token >= 32)
|
||||
{
|
||||
if ((length=(token & MAX_SHORT_LITLEN)) == MAX_SHORT_LITLEN) {
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZ_LOG_DECOMPRESS_LZ5v2("1"); goto _output_error; }
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("1"); goto _output_error; }
|
||||
length = *ctx->literalsPtr;
|
||||
if unlikely(length >= 254) {
|
||||
if (length == 254) {
|
||||
@@ -75,28 +73,28 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
}
|
||||
length += MAX_SHORT_LITLEN;
|
||||
ctx->literalsPtr++;
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZ_LOG_DECOMPRESS_LZ5v2("2"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZ_LOG_DECOMPRESS_LZ5v2("3"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1("2"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LIZv1("3"); goto _output_error; } /* overflow detection */
|
||||
}
|
||||
|
||||
/* copy literals */
|
||||
cpy = op + length;
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr > iend - WILDCOPYLENGTH)) { LIZ_LOG_DECOMPRESS_LZ5v2("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr > iend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
|
||||
#if 1
|
||||
LIZ_wildCopy16(op, ctx->literalsPtr, cpy);
|
||||
Lizard_wildCopy16(op, ctx->literalsPtr, cpy);
|
||||
op = cpy;
|
||||
ctx->literalsPtr += length;
|
||||
#else
|
||||
LIZ_copy8(op, ctx->literalsPtr);
|
||||
LIZ_copy8(op+8, ctx->literalsPtr+8);
|
||||
Lizard_copy8(op, ctx->literalsPtr);
|
||||
Lizard_copy8(op+8, ctx->literalsPtr+8);
|
||||
if (length > 16)
|
||||
LIZ_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
|
||||
Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
|
||||
op = cpy;
|
||||
ctx->literalsPtr += length;
|
||||
#endif
|
||||
|
||||
/* get offset */
|
||||
if (unlikely(ctx->offset16Ptr > ctx->offset16End)) { LIZ_LOG_DECOMPRESS_LZ5v2("(ctx->offset16Ptr > ctx->offset16End\n"); goto _output_error; }
|
||||
if (unlikely(ctx->offset16Ptr > ctx->offset16End)) { LIZARD_LOG_DECOMPRESS_LIZv1("(ctx->offset16Ptr > ctx->offset16End\n"); goto _output_error; }
|
||||
#if 1
|
||||
{ /* branchless */
|
||||
intptr_t new_off = MEM_readLE16(ctx->offset16Ptr);
|
||||
@@ -105,19 +103,17 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
ctx->offset16Ptr = (BYTE*)((uintptr_t)ctx->offset16Ptr + (not_repCode & 2));
|
||||
}
|
||||
#else
|
||||
if ((token >> ML_RUN_BITS_LZ5v2) == 0)
|
||||
if ((token >> ML_RUN_BITS_LIZv1) == 0)
|
||||
{
|
||||
last_off = -(intptr_t)MEM_readLE16(ctx->offset16Ptr);
|
||||
ctx->offset16Ptr += 2;
|
||||
// LZ5v2_DEBUG("MEM_readLE16 offset=%d\n", (int)offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get matchlength */
|
||||
length = (token >> RUN_BITS_LZ5v2) & MAX_SHORT_MATCHLEN;
|
||||
// printf("length=%d token=%d\n", (int)length, (int)token);
|
||||
length = (token >> RUN_BITS_LIZv1) & MAX_SHORT_MATCHLEN;
|
||||
if (length == MAX_SHORT_MATCHLEN) {
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZ_LOG_DECOMPRESS_LZ5v2("6"); goto _output_error; }
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("6"); goto _output_error; }
|
||||
length = *ctx->literalsPtr;
|
||||
if unlikely(length >= 254) {
|
||||
if (length == 254) {
|
||||
@@ -130,23 +126,23 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
}
|
||||
length += MAX_SHORT_MATCHLEN;
|
||||
ctx->literalsPtr++;
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZ_LOG_DECOMPRESS_LZ5v2("7"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1("7"); goto _output_error; } /* overflow detection */
|
||||
}
|
||||
|
||||
DECOMPLOG_CODEWORDS_LZ5v2("T32+ literal=%u match=%u offset=%d ipos=%d opos=%d\n", (U32)litLength, (U32)length, (int)-last_off, (U32)(ctx->flagsPtr-blockBase), (U32)(op-dest));
|
||||
DECOMPLOG_CODEWORDS_LIZv1("T32+ literal=%u match=%u offset=%d ipos=%d opos=%d\n", (U32)litLength, (U32)length, (int)-last_off, (U32)(ctx->flagsPtr-blockBase), (U32)(op-dest));
|
||||
}
|
||||
else
|
||||
if (token < LIZ_LAST_LONG_OFF)
|
||||
if (token < LIZARD_LAST_LONG_OFF)
|
||||
{
|
||||
if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZ_LOG_DECOMPRESS_LZ5v2("8"); goto _output_error; }
|
||||
if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1("8"); goto _output_error; }
|
||||
length = token + MM_LONGOFF;
|
||||
last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr);
|
||||
ctx->offset24Ptr += 3;
|
||||
DECOMPLOG_CODEWORDS_LZ5v2("T0-30 literal=%u match=%u offset=%d\n", 0, (U32)length, (int)-last_off);
|
||||
DECOMPLOG_CODEWORDS_LIZv1("T0-30 literal=%u match=%u offset=%d\n", 0, (U32)length, (int)-last_off);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZ_LOG_DECOMPRESS_LZ5v2("9"); goto _output_error; }
|
||||
if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("9"); goto _output_error; }
|
||||
length = *ctx->literalsPtr;
|
||||
if unlikely(length >= 254) {
|
||||
if (length == 254) {
|
||||
@@ -158,20 +154,20 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
}
|
||||
}
|
||||
ctx->literalsPtr++;
|
||||
length += LIZ_LAST_LONG_OFF + MM_LONGOFF;
|
||||
length += LIZARD_LAST_LONG_OFF + MM_LONGOFF;
|
||||
|
||||
if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZ_LOG_DECOMPRESS_LZ5v2("10"); goto _output_error; }
|
||||
if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1("10"); goto _output_error; }
|
||||
last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr);
|
||||
ctx->offset24Ptr += 3;
|
||||
}
|
||||
|
||||
|
||||
match = op + last_off;
|
||||
if ((checkOffset) && ((unlikely((uintptr_t)(-last_off) > (uintptr_t)op) || (match < lowLimit)))) { LIZ_LOG_DECOMPRESS_LZ5v2("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-last_off[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)last_off); goto _output_error; } /* Error : offset outside buffers */
|
||||
if ((checkOffset) && ((unlikely((uintptr_t)(-last_off) > (uintptr_t)op) || (match < lowLimit)))) { LIZARD_LOG_DECOMPRESS_LIZv1("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-last_off[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)last_off); goto _output_error; } /* Error : offset outside buffers */
|
||||
|
||||
/* check external dictionary */
|
||||
if ((dict==usingExtDict) && (match < lowPrefix)) {
|
||||
if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZ_LOG_DECOMPRESS_LZ5v2("12"); goto _output_error; } /* doesn't respect parsing restriction */
|
||||
if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("12"); goto _output_error; } /* doesn't respect parsing restriction */
|
||||
|
||||
if (length <= (intptr_t)(lowPrefix - match)) {
|
||||
/* match can be copied as a single segment from external dictionary */
|
||||
@@ -196,18 +192,18 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
|
||||
/* copy match within block */
|
||||
cpy = op + length;
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZ_LOG_DECOMPRESS_LZ5v2("13match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
|
||||
LIZ_copy8(op, match);
|
||||
LIZ_copy8(op+8, match+8);
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("13match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
|
||||
Lizard_copy8(op, match);
|
||||
Lizard_copy8(op+8, match+8);
|
||||
if (length > 16)
|
||||
LIZ_wildCopy16(op + 16, match + 16, cpy);
|
||||
Lizard_wildCopy16(op + 16, match + 16, cpy);
|
||||
op = cpy;
|
||||
}
|
||||
|
||||
/* last literals */
|
||||
length = ctx->literalsEnd - ctx->literalsPtr;
|
||||
cpy = op + length;
|
||||
if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZ_LOG_DECOMPRESS_LZ5v2("14"); goto _output_error; } /* Error : input must be consumed */
|
||||
if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LIZv1("14"); goto _output_error; } /* Error : input must be consumed */
|
||||
memcpy(op, ctx->literalsPtr, length);
|
||||
ctx->literalsPtr += length;
|
||||
op += length;
|
||||
@@ -218,7 +214,7 @@ FORCE_INLINE int LIZ_decompress_LZ5v2(
|
||||
|
||||
/* Overflow error detected */
|
||||
_output_error:
|
||||
LIZ_LOG_DECOMPRESS_LZ5v2("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
|
||||
LIZ_LOG_DECOMPRESS_LZ5v2("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
|
||||
LIZARD_LOG_DECOMPRESS_LIZv1("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
|
||||
LIZARD_LOG_DECOMPRESS_LIZv1("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
|
||||
return (int) (-(ctx->flagsPtr-blockBase))-1;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*! LIZ_decompress_LZ4() :
|
||||
/*! Lizard_decompress_LZ4() :
|
||||
* This generic decompression function cover all use cases.
|
||||
* It shall be instantiated several times, using different sets of directives
|
||||
* Note that it is important this generic function is really inlined,
|
||||
* in order to remove useless branches during compilation optimization.
|
||||
*/
|
||||
FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
LIZ_dstream_t* ctx,
|
||||
FORCE_INLINE int Lizard_decompress_LZ4(
|
||||
Lizard_dstream_t* ctx,
|
||||
BYTE* const dest,
|
||||
int outputSize, /* this value is the max size of Output Buffer. */
|
||||
|
||||
@@ -29,11 +29,10 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
const BYTE* const lowLimit = lowPrefix - dictSize;
|
||||
const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
|
||||
|
||||
const int checkOffset = (dictSize < (int)(LIZ_DICT_SIZE));
|
||||
const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));
|
||||
|
||||
intptr_t length = 0;
|
||||
(void)compressionLevel;
|
||||
(void)LIZ_wildCopy;
|
||||
|
||||
/* Special cases */
|
||||
if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1; /* Empty output buffer */
|
||||
@@ -47,7 +46,7 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
/* get literal length */
|
||||
token = *ctx->flagsPtr++;
|
||||
if ((length=(token & RUN_MASK_LZ4)) == RUN_MASK_LZ4) {
|
||||
if (unlikely(ctx->literalsPtr > iend - 5)) { LIZ_LOG_DECOMPRESS_LZ4("0"); goto _output_error; }
|
||||
if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4("0"); goto _output_error; }
|
||||
length = *ctx->literalsPtr;
|
||||
if unlikely(length >= 254) {
|
||||
if (length == 254) {
|
||||
@@ -60,23 +59,23 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
}
|
||||
length += RUN_MASK_LZ4;
|
||||
ctx->literalsPtr++;
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZ_LOG_DECOMPRESS_LZ4("1"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZ_LOG_DECOMPRESS_LZ4("2"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4("1"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LZ4("2"); goto _output_error; } /* overflow detection */
|
||||
}
|
||||
|
||||
/* copy literals */
|
||||
cpy = op + length;
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr + length > iend - (2 + WILDCOPYLENGTH))) { LIZ_LOG_DECOMPRESS_LZ4("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr + length > iend - (2 + WILDCOPYLENGTH))) { LIZARD_LOG_DECOMPRESS_LZ4("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
|
||||
|
||||
#if 1
|
||||
LIZ_wildCopy16(op, ctx->literalsPtr, cpy);
|
||||
Lizard_wildCopy16(op, ctx->literalsPtr, cpy);
|
||||
op = cpy;
|
||||
ctx->literalsPtr += length;
|
||||
#else
|
||||
LIZ_copy8(op, ctx->literalsPtr);
|
||||
LIZ_copy8(op+8, ctx->literalsPtr+8);
|
||||
Lizard_copy8(op, ctx->literalsPtr);
|
||||
Lizard_copy8(op+8, ctx->literalsPtr+8);
|
||||
if (length > 16)
|
||||
LIZ_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
|
||||
Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
|
||||
op = cpy;
|
||||
ctx->literalsPtr += length;
|
||||
#endif
|
||||
@@ -87,12 +86,12 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
ctx->literalsPtr += 2;
|
||||
|
||||
match = op - offset;
|
||||
if ((checkOffset) && (unlikely(match < lowLimit))) { LIZ_LOG_DECOMPRESS_LZ4("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-offset[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)offset); goto _output_error; } /* Error : offset outside buffers */
|
||||
if ((checkOffset) && (unlikely(match < lowLimit))) { LIZARD_LOG_DECOMPRESS_LZ4("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-offset[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)offset); goto _output_error; } /* Error : offset outside buffers */
|
||||
|
||||
/* get matchlength */
|
||||
length = token >> RUN_BITS_LZ4;
|
||||
if (length == ML_MASK_LZ4) {
|
||||
if (unlikely(ctx->literalsPtr > iend - 5)) { LIZ_LOG_DECOMPRESS_LZ4("4"); goto _output_error; }
|
||||
if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4("4"); goto _output_error; }
|
||||
length = *ctx->literalsPtr;
|
||||
if unlikely(length >= 254) {
|
||||
if (length == 254) {
|
||||
@@ -105,13 +104,13 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
}
|
||||
length += ML_MASK_LZ4;
|
||||
ctx->literalsPtr++;
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZ_LOG_DECOMPRESS_LZ4("5"); goto _output_error; } /* overflow detection */
|
||||
if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4("5"); goto _output_error; } /* overflow detection */
|
||||
}
|
||||
length += MINMATCH;
|
||||
|
||||
/* check external dictionary */
|
||||
if ((dict==usingExtDict) && (match < lowPrefix)) {
|
||||
if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZ_LOG_DECOMPRESS_LZ4("6"); goto _output_error; } /* doesn't respect parsing restriction */
|
||||
if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4("6"); goto _output_error; } /* doesn't respect parsing restriction */
|
||||
|
||||
if (length <= (intptr_t)(lowPrefix - match)) {
|
||||
/* match can be copied as a single segment from external dictionary */
|
||||
@@ -136,11 +135,11 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
|
||||
/* copy match within block */
|
||||
cpy = op + length;
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZ_LOG_DECOMPRESS_LZ4("1match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
|
||||
LIZ_copy8(op, match);
|
||||
LIZ_copy8(op+8, match+8);
|
||||
if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4("1match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
|
||||
Lizard_copy8(op, match);
|
||||
Lizard_copy8(op+8, match+8);
|
||||
if (length > 16)
|
||||
LIZ_wildCopy16(op + 16, match + 16, cpy);
|
||||
Lizard_wildCopy16(op + 16, match + 16, cpy);
|
||||
op = cpy;
|
||||
if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);
|
||||
}
|
||||
@@ -148,7 +147,7 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
/* last literals */
|
||||
length = ctx->literalsEnd - ctx->literalsPtr;
|
||||
cpy = op + length;
|
||||
if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZ_LOG_DECOMPRESS_LZ4("9"); goto _output_error; } /* Error : input must be consumed */
|
||||
if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LZ4("9"); goto _output_error; } /* Error : input must be consumed */
|
||||
memcpy(op, ctx->literalsPtr, length);
|
||||
ctx->literalsPtr += length;
|
||||
op += length;
|
||||
@@ -158,7 +157,7 @@ FORCE_INLINE int LIZ_decompress_LZ4(
|
||||
|
||||
/* Overflow error detected */
|
||||
_output_error:
|
||||
LIZ_LOG_DECOMPRESS_LZ4("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
|
||||
LIZ_LOG_DECOMPRESS_LZ4("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
|
||||
LIZARD_LOG_DECOMPRESS_LZ4("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
|
||||
LIZARD_LOG_DECOMPRESS_LZ4("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
|
||||
return (int) (-(ctx->flagsPtr-blockBase))-1;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
LZ5 auto-framing library
|
||||
Lizard auto-framing library
|
||||
Header File
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
Copyright (C) 2011-2015, Yann Collet
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,13 +30,13 @@
|
||||
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
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
|
||||
/* LZ5F is a stand-alone API to create LZ5-compressed frames
|
||||
/* LizardF is a stand-alone API to create Lizard-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_compress.h when using lz5frame.h.
|
||||
* You don't need lizard_compress.h when using lizard_frame.h.
|
||||
* */
|
||||
|
||||
#pragma once
|
||||
@@ -52,171 +54,171 @@ extern "C" {
|
||||
/*-************************************
|
||||
* Error management
|
||||
**************************************/
|
||||
typedef size_t LIZF_errorCode_t;
|
||||
typedef size_t LizardF_errorCode_t;
|
||||
|
||||
unsigned LIZF_isError(LIZF_errorCode_t code);
|
||||
const char* LIZF_getErrorName(LIZF_errorCode_t code); /* return error code string; useful for debugging */
|
||||
unsigned LizardF_isError(LizardF_errorCode_t code);
|
||||
const char* LizardF_getErrorName(LizardF_errorCode_t code); /* return error code string; useful for debugging */
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Frame compression types
|
||||
**************************************/
|
||||
//#define LIZF_DISABLE_OBSOLETE_ENUMS
|
||||
#ifndef LIZF_DISABLE_OBSOLETE_ENUMS
|
||||
# define LIZF_OBSOLETE_ENUM(x) ,x
|
||||
//#define LIZARDF_DISABLE_OBSOLETE_ENUMS
|
||||
#ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS
|
||||
# define LIZARDF_OBSOLETE_ENUM(x) ,x
|
||||
#else
|
||||
# define LIZF_OBSOLETE_ENUM(x)
|
||||
# define LIZARDF_OBSOLETE_ENUM(x)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LIZF_default=0,
|
||||
LIZF_max128KB=1,
|
||||
LIZF_max256KB=2,
|
||||
LIZF_max1MB=3,
|
||||
LIZF_max4MB=4,
|
||||
LIZF_max16MB=5,
|
||||
LIZF_max64MB=6,
|
||||
LIZF_max256MB=7
|
||||
} LIZF_blockSizeID_t;
|
||||
LizardF_default=0,
|
||||
LizardF_max128KB=1,
|
||||
LizardF_max256KB=2,
|
||||
LizardF_max1MB=3,
|
||||
LizardF_max4MB=4,
|
||||
LizardF_max16MB=5,
|
||||
LizardF_max64MB=6,
|
||||
LizardF_max256MB=7
|
||||
} LizardF_blockSizeID_t;
|
||||
|
||||
typedef enum {
|
||||
LIZF_blockLinked=0,
|
||||
LIZF_blockIndependent
|
||||
LIZF_OBSOLETE_ENUM(blockLinked = LIZF_blockLinked)
|
||||
LIZF_OBSOLETE_ENUM(blockIndependent = LIZF_blockIndependent)
|
||||
} LIZF_blockMode_t;
|
||||
LizardF_blockLinked=0,
|
||||
LizardF_blockIndependent
|
||||
LIZARDF_OBSOLETE_ENUM(blockLinked = LizardF_blockLinked)
|
||||
LIZARDF_OBSOLETE_ENUM(blockIndependent = LizardF_blockIndependent)
|
||||
} LizardF_blockMode_t;
|
||||
|
||||
typedef enum {
|
||||
LIZF_noContentChecksum=0,
|
||||
LIZF_contentChecksumEnabled
|
||||
LIZF_OBSOLETE_ENUM(noContentChecksum = LIZF_noContentChecksum)
|
||||
LIZF_OBSOLETE_ENUM(contentChecksumEnabled = LIZF_contentChecksumEnabled)
|
||||
} LIZF_contentChecksum_t;
|
||||
LizardF_noContentChecksum=0,
|
||||
LizardF_contentChecksumEnabled
|
||||
LIZARDF_OBSOLETE_ENUM(noContentChecksum = LizardF_noContentChecksum)
|
||||
LIZARDF_OBSOLETE_ENUM(contentChecksumEnabled = LizardF_contentChecksumEnabled)
|
||||
} LizardF_contentChecksum_t;
|
||||
|
||||
typedef enum {
|
||||
LIZF_frame=0,
|
||||
LIZF_skippableFrame
|
||||
LIZF_OBSOLETE_ENUM(skippableFrame = LIZF_skippableFrame)
|
||||
} LIZF_frameType_t;
|
||||
LizardF_frame=0,
|
||||
LizardF_skippableFrame
|
||||
LIZARDF_OBSOLETE_ENUM(skippableFrame = LizardF_skippableFrame)
|
||||
} LizardF_frameType_t;
|
||||
|
||||
#ifndef LIZF_DISABLE_OBSOLETE_ENUMS
|
||||
typedef LIZF_blockSizeID_t blockSizeID_t;
|
||||
typedef LIZF_blockMode_t blockMode_t;
|
||||
typedef LIZF_frameType_t frameType_t;
|
||||
typedef LIZF_contentChecksum_t contentChecksum_t;
|
||||
#ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS
|
||||
typedef LizardF_blockSizeID_t blockSizeID_t;
|
||||
typedef LizardF_blockMode_t blockMode_t;
|
||||
typedef LizardF_frameType_t frameType_t;
|
||||
typedef LizardF_contentChecksum_t contentChecksum_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
LIZF_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
LIZF_blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
LIZF_contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
LIZF_frameType_t frameType; /* LIZF_frame, skippableFrame ; 0 == default */
|
||||
LizardF_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
LizardF_blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
LizardF_contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
LizardF_frameType_t frameType; /* LizardF_frame, skippableFrame ; 0 == default */
|
||||
unsigned long long contentSize; /* Size of uncompressed (original) content ; 0 == unknown */
|
||||
unsigned reserved[2]; /* must be zero for forward compatibility */
|
||||
} LIZF_frameInfo_t;
|
||||
} LizardF_frameInfo_t;
|
||||
|
||||
typedef struct {
|
||||
LIZF_frameInfo_t frameInfo;
|
||||
LizardF_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 */
|
||||
} LIZF_preferences_t;
|
||||
} LizardF_preferences_t;
|
||||
|
||||
|
||||
/*-*********************************
|
||||
* Simple compression function
|
||||
***********************************/
|
||||
size_t LIZF_compressFrameBound(size_t srcSize, const LIZF_preferences_t* preferencesPtr);
|
||||
size_t LizardF_compressFrameBound(size_t srcSize, const LizardF_preferences_t* preferencesPtr);
|
||||
|
||||
/*!LIZF_compressFrame() :
|
||||
* Compress an entire srcBuffer into a valid LZ5 frame, as defined by specification v1.5.1
|
||||
/*!LizardF_compressFrame() :
|
||||
* Compress an entire srcBuffer into a valid Lizard 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 LIZF_compressFrameBound()
|
||||
* If this condition is not respected, LIZF_compressFrame() will fail (result is an errorCode)
|
||||
* The LIZF_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
|
||||
* You can get the minimum value of dstMaxSize by using LizardF_compressFrameBound()
|
||||
* If this condition is not respected, LizardF_compressFrame() will fail (result is an errorCode)
|
||||
* The LizardF_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 LIZF_isError())
|
||||
* The function outputs an error code if it fails (can be tested using LizardF_isError())
|
||||
*/
|
||||
size_t LIZF_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LIZF_preferences_t* preferencesPtr);
|
||||
size_t LizardF_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_preferences_t* preferencesPtr);
|
||||
|
||||
|
||||
|
||||
/*-***********************************
|
||||
* Advanced compression functions
|
||||
*************************************/
|
||||
typedef struct LIZF_cctx_s* LIZF_compressionContext_t; /* must be aligned on 8-bytes */
|
||||
typedef struct LizardF_cctx_s* LizardF_compressionContext_t; /* must be aligned on 8-bytes */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableSrc; /* 1 == src content will remain available on future calls to LIZF_compress(); avoid saving src content within tmp buffer as future dictionary */
|
||||
unsigned stableSrc; /* 1 == src content will remain available on future calls to LizardF_compress(); avoid saving src content within tmp buffer as future dictionary */
|
||||
unsigned reserved[3];
|
||||
} LIZF_compressOptions_t;
|
||||
} LizardF_compressOptions_t;
|
||||
|
||||
/* Resource Management */
|
||||
|
||||
#define LIZF_VERSION 100
|
||||
LIZF_errorCode_t LIZF_createCompressionContext(LIZF_compressionContext_t* cctxPtr, unsigned version);
|
||||
LIZF_errorCode_t LIZF_freeCompressionContext(LIZF_compressionContext_t cctx);
|
||||
/* LIZF_createCompressionContext() :
|
||||
#define LIZARDF_VERSION 100
|
||||
LizardF_errorCode_t LizardF_createCompressionContext(LizardF_compressionContext_t* cctxPtr, unsigned version);
|
||||
LizardF_errorCode_t LizardF_freeCompressionContext(LizardF_compressionContext_t cctx);
|
||||
/* LizardF_createCompressionContext() :
|
||||
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
|
||||
* This is achieved using LIZF_createCompressionContext(), which takes as argument a version and an LIZF_preferences_t structure.
|
||||
* The version provided MUST be LIZF_VERSION. It is intended to track potential version differences between different binaries.
|
||||
* The function will provide a pointer to a fully allocated LIZF_compressionContext_t object.
|
||||
* If the result LIZF_errorCode_t is not zero, there was an error during context creation.
|
||||
* Object can release its memory using LIZF_freeCompressionContext();
|
||||
* This is achieved using LizardF_createCompressionContext(), which takes as argument a version and an LizardF_preferences_t structure.
|
||||
* The version provided MUST be LIZARDF_VERSION. It is intended to track potential version differences between different binaries.
|
||||
* The function will provide a pointer to a fully allocated LizardF_compressionContext_t object.
|
||||
* If the result LizardF_errorCode_t is not zero, there was an error during context creation.
|
||||
* Object can release its memory using LizardF_freeCompressionContext();
|
||||
*/
|
||||
|
||||
|
||||
/* Compression */
|
||||
|
||||
size_t LIZF_compressBegin(LIZF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LIZF_preferences_t* prefsPtr);
|
||||
/* LIZF_compressBegin() :
|
||||
size_t LizardF_compressBegin(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_preferences_t* prefsPtr);
|
||||
/* LizardF_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 LIZF_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.
|
||||
* The LizardF_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 LIZF_isError())
|
||||
* or an error code (can be tested using LizardF_isError())
|
||||
*/
|
||||
|
||||
size_t LIZF_compressBound(size_t srcSize, const LIZF_preferences_t* prefsPtr);
|
||||
/* LIZF_compressBound() :
|
||||
size_t LizardF_compressBound(size_t srcSize, const LizardF_preferences_t* prefsPtr);
|
||||
/* LizardF_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 LIZF_compressUpdate(LIZF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LIZF_compressOptions_t* cOptPtr);
|
||||
/* LIZF_compressUpdate()
|
||||
* LIZF_compressUpdate() can be called repetitively to compress as much data as necessary.
|
||||
size_t LizardF_compressUpdate(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_compressOptions_t* cOptPtr);
|
||||
/* LizardF_compressUpdate()
|
||||
* LizardF_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 LIZF_compressBound().
|
||||
* If this condition is not respected, LIZF_compress() will fail (result is an errorCode).
|
||||
* LIZF_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
|
||||
* The LIZF_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* You can get the minimum value of dstMaxSize by using LizardF_compressBound().
|
||||
* If this condition is not respected, LizardF_compress() will fail (result is an errorCode).
|
||||
* LizardF_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
|
||||
* The LizardF_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 LIZF_isError())
|
||||
* The function outputs an error code if it fails (can be tested using LizardF_isError())
|
||||
*/
|
||||
|
||||
size_t LIZF_flush(LIZF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LIZF_compressOptions_t* cOptPtr);
|
||||
/* LIZF_flush()
|
||||
size_t LizardF_flush(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);
|
||||
/* LizardF_flush()
|
||||
* Should you need to generate compressed data immediately, without waiting for the current block to be filled,
|
||||
* you can call LIZ_flush(), which will immediately compress any remaining data buffered within cctx.
|
||||
* you can call Lizard_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.
|
||||
* LIZF_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* LizardF_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 LIZF_isError())
|
||||
* The function outputs an error code if it fails (can be tested using LizardF_isError())
|
||||
*/
|
||||
|
||||
size_t LIZF_compressEnd(LIZF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LIZF_compressOptions_t* cOptPtr);
|
||||
/* LIZF_compressEnd()
|
||||
* When you want to properly finish the compressed frame, just call LIZF_compressEnd().
|
||||
* It will flush whatever data remained within compressionContext (like LIZ_flush())
|
||||
size_t LizardF_compressEnd(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);
|
||||
/* LizardF_compressEnd()
|
||||
* When you want to properly finish the compressed frame, just call LizardF_compressEnd().
|
||||
* It will flush whatever data remained within compressionContext (like Lizard_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 LIZF_isError())
|
||||
* The LIZF_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* A successful call to LIZF_compressEnd() makes cctx available again for next compression task.
|
||||
* The function outputs an error code if it fails (can be tested using LizardF_isError())
|
||||
* The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* A successful call to LizardF_compressEnd() makes cctx available again for next compression task.
|
||||
*/
|
||||
|
||||
|
||||
@@ -224,48 +226,48 @@ size_t LIZF_compressEnd(LIZF_compressionContext_t cctx, void* dstBuffer, size_t
|
||||
* Decompression functions
|
||||
***********************************/
|
||||
|
||||
typedef struct LIZF_dctx_s* LIZF_decompressionContext_t; /* must be aligned on 8-bytes */
|
||||
typedef struct LizardF_dctx_s* LizardF_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];
|
||||
} LIZF_decompressOptions_t;
|
||||
} LizardF_decompressOptions_t;
|
||||
|
||||
|
||||
/* Resource management */
|
||||
|
||||
/*!LIZF_createDecompressionContext() :
|
||||
* Create an LIZF_decompressionContext_t object, which will be used to track all decompression operations.
|
||||
* The version provided MUST be LIZF_VERSION. It is intended to track potential breaking differences between different versions.
|
||||
* The function will provide a pointer to a fully allocated and initialized LIZF_decompressionContext_t object.
|
||||
* The result is an errorCode, which can be tested using LIZF_isError().
|
||||
* dctx memory can be released using LIZF_freeDecompressionContext();
|
||||
* The result of LIZF_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
|
||||
/*!LizardF_createDecompressionContext() :
|
||||
* Create an LizardF_decompressionContext_t object, which will be used to track all decompression operations.
|
||||
* The version provided MUST be LIZARDF_VERSION. It is intended to track potential breaking differences between different versions.
|
||||
* The function will provide a pointer to a fully allocated and initialized LizardF_decompressionContext_t object.
|
||||
* The result is an errorCode, which can be tested using LizardF_isError().
|
||||
* dctx memory can be released using LizardF_freeDecompressionContext();
|
||||
* The result of LizardF_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.
|
||||
*/
|
||||
LIZF_errorCode_t LIZF_createDecompressionContext(LIZF_decompressionContext_t* dctxPtr, unsigned version);
|
||||
LIZF_errorCode_t LIZF_freeDecompressionContext(LIZF_decompressionContext_t dctx);
|
||||
LizardF_errorCode_t LizardF_createDecompressionContext(LizardF_decompressionContext_t* dctxPtr, unsigned version);
|
||||
LizardF_errorCode_t LizardF_freeDecompressionContext(LizardF_decompressionContext_t dctx);
|
||||
|
||||
|
||||
/*====== Decompression ======*/
|
||||
|
||||
/*!LIZF_getFrameInfo() :
|
||||
/*!LizardF_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 LIZF_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 LIZF_frameInfo_t structure.
|
||||
* The function result is an hint about how many srcSize bytes LIZF_decompress() expects for next call,
|
||||
* or an error code which can be tested using LIZF_isError()
|
||||
* (note that LizardF_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 LizardF_frameInfo_t structure.
|
||||
* The function result is an hint about how many srcSize bytes LizardF_decompress() expects for next call,
|
||||
* or an error code which can be tested using LizardF_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 LIZF_getFrameInfo(LIZF_decompressionContext_t dctx,
|
||||
LIZF_frameInfo_t* frameInfoPtr,
|
||||
size_t LizardF_getFrameInfo(LizardF_decompressionContext_t dctx,
|
||||
LizardF_frameInfo_t* frameInfoPtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr);
|
||||
|
||||
/*!LIZF_decompress() :
|
||||
/*!LizardF_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.
|
||||
*
|
||||
@@ -274,25 +276,25 @@ size_t LIZF_getFrameInfo(LIZF_decompressionContext_t dctx,
|
||||
* 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.
|
||||
* LIZF_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)
|
||||
* LizardF_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 expected to be flushed between each call to the function, its content will be overwritten.
|
||||
* `dst` arguments can be changed at will at each consecutive call to the function.
|
||||
*
|
||||
* The function result is an hint of how many `srcSize` bytes LIZF_decompress() expects for next call.
|
||||
* The function result is an hint of how many `srcSize` bytes LizardF_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 though, it's always possible to provide any srcSize.
|
||||
* 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 LIZF_isError().
|
||||
* If decompression failed, function result is an error code, which can be tested using LizardF_isError().
|
||||
*
|
||||
* After a frame is fully decoded, dctx can be used again to decompress another frame.
|
||||
*/
|
||||
size_t LIZF_decompress(LIZF_decompressionContext_t dctx,
|
||||
size_t LizardF_decompress(LizardF_decompressionContext_t dctx,
|
||||
void* dstBuffer, size_t* dstSizePtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr,
|
||||
const LIZF_decompressOptions_t* dOptPtr);
|
||||
const LizardF_decompressOptions_t* dOptPtr);
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
LZ5 auto-framing library
|
||||
Lizard auto-framing library
|
||||
Header File for static linking only
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
Copyright (C) 2016-2017, Przemyslaw Skibinski
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
@@ -29,7 +30,7 @@
|
||||
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
|
||||
- Lizard source repository : https://github.com/inikep/lizard
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -38,7 +39,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* lz5frame_static.h should be used solely in the context of static linking.
|
||||
/* lizard_frame_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.
|
||||
* */
|
||||
@@ -47,13 +48,13 @@ extern "C" {
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include "lizframe.h"
|
||||
#include "lizard_frame.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* Error management
|
||||
* ************************************/
|
||||
#define LIZF_LIST_ERRORS(ITEM) \
|
||||
#define LIZARDF_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) \
|
||||
@@ -66,13 +67,13 @@ extern "C" {
|
||||
ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \
|
||||
ITEM(ERROR_maxCode)
|
||||
|
||||
//#define LIZF_DISABLE_OLD_ENUMS
|
||||
#ifndef LIZF_DISABLE_OLD_ENUMS
|
||||
#define LIZF_GENERATE_ENUM(ENUM) LIZF_##ENUM, ENUM = LIZF_##ENUM,
|
||||
//#define LIZARDF_DISABLE_OLD_ENUMS
|
||||
#ifndef LIZARDF_DISABLE_OLD_ENUMS
|
||||
#define LIZARDF_GENERATE_ENUM(ENUM) LizardF_##ENUM, ENUM = LizardF_##ENUM,
|
||||
#else
|
||||
#define LIZF_GENERATE_ENUM(ENUM) LIZF_##ENUM,
|
||||
#define LIZARDF_GENERATE_ENUM(ENUM) LizardF_##ENUM,
|
||||
#endif
|
||||
typedef enum { LIZF_LIST_ERRORS(LIZF_GENERATE_ENUM) } LIZF_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
|
||||
typedef enum { LIZARDF_LIST_ERRORS(LIZARDF_GENERATE_ENUM) } LizardF_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
196
C/lizard/lizard_parser_fast.h
Normal file
196
C/lizard/lizard_parser_fast.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#define LIZARD_FAST_MIN_OFFSET 8
|
||||
#define LIZARD_FAST_LONGOFF_MM 0 /* not used with offsets > 1<<16 */
|
||||
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t Lizard_hashPosition(const void* p)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return Lizard_hash5Ptr(p, LIZARD_HASHLOG_LZ4);
|
||||
return Lizard_hash4Ptr(p, LIZARD_HASHLOG_LZ4);
|
||||
}
|
||||
|
||||
static void Lizard_putPositionOnHash(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void Lizard_putPosition(const BYTE* p, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
size_t const h = Lizard_hashPosition(p);
|
||||
Lizard_putPositionOnHash(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 Lizard_getPositionOnHash(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 Lizard_getPosition(const BYTE* p, U32* hashTable)
|
||||
{
|
||||
size_t const h = Lizard_hashPosition(p);
|
||||
return Lizard_getPositionOnHash(h, hashTable);
|
||||
}
|
||||
|
||||
|
||||
static const U32 Lizard_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
|
||||
static const U32 Lizard_minLength = (MFLIMIT+1);
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_compress_fast(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
Lizard_putPosition(ip, ctx->hashTable, base);
|
||||
ip++; forwardH = Lizard_hashPosition(ip);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << Lizard_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> Lizard_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = Lizard_getPositionOnHash(h, ctx->hashTable);
|
||||
forwardH = Lizard_hashPosition(forwardIp);
|
||||
Lizard_putPositionOnHash(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
Lizard_putPosition(ip-2, ctx->hashTable, base);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = Lizard_getPosition(ip, ctx->hashTable);
|
||||
Lizard_putPosition(ip, ctx->hashTable, base);
|
||||
if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = Lizard_hashPosition(++ip);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
175
C/lizard/lizard_parser_fastbig.h
Normal file
175
C/lizard/lizard_parser_fastbig.h
Normal file
@@ -0,0 +1,175 @@
|
||||
#define LIZARD_FASTBIG_LONGOFF_MM MM_LONGOFF
|
||||
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t Lizard_hashPositionHLog(const void* p, int hashLog)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return Lizard_hash5Ptr(p, hashLog);
|
||||
return Lizard_hash4Ptr(p, hashLog);
|
||||
}
|
||||
|
||||
static void Lizard_putPositionOnHashHLog(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void Lizard_putPositionHLog(const BYTE* p, U32* hashTable, const BYTE* srcBase, int hashLog)
|
||||
{
|
||||
size_t const h = Lizard_hashPositionHLog(p, hashLog);
|
||||
Lizard_putPositionOnHashHLog(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 Lizard_getPositionOnHashHLog(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 Lizard_getPositionHLog(const BYTE* p, U32* hashTable, int hashLog)
|
||||
{
|
||||
size_t const h = Lizard_hashPositionHLog(p, hashLog);
|
||||
return Lizard_getPositionOnHashHLog(h, hashTable);
|
||||
}
|
||||
|
||||
FORCE_INLINE int Lizard_compress_fastBig(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
Lizard_putPositionHLog(ip, ctx->hashTable, base, hashLog);
|
||||
ip++; forwardH = Lizard_hashPositionHLog(ip, hashLog);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << Lizard_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> Lizard_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = Lizard_getPositionOnHashHLog(h, ctx->hashTable);
|
||||
forwardH = Lizard_hashPositionHLog(forwardIp, hashLog);
|
||||
Lizard_putPositionOnHashHLog(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
Lizard_putPositionHLog(ip-2, ctx->hashTable, base, hashLog);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = Lizard_getPositionHLog(ip, ctx->hashTable, hashLog);
|
||||
Lizard_putPositionHLog(ip, ctx->hashTable, base, hashLog);
|
||||
if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = Lizard_hashPositionHLog(++ip, hashLog);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
189
C/lizard/lizard_parser_fastsmall.h
Normal file
189
C/lizard/lizard_parser_fastsmall.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/**************************************
|
||||
* Hash Functions
|
||||
**************************************/
|
||||
static size_t Lizard_hashPositionSmall(const void* p)
|
||||
{
|
||||
if (MEM_64bits())
|
||||
return Lizard_hash5Ptr(p, LIZARD_HASHLOG_LZ4SM);
|
||||
return Lizard_hash4Ptr(p, LIZARD_HASHLOG_LZ4SM);
|
||||
}
|
||||
|
||||
static void Lizard_putPositionOnHashSmall(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
hashTable[h] = (U32)(p-srcBase);
|
||||
}
|
||||
|
||||
static void Lizard_putPositionSmall(const BYTE* p, U32* hashTable, const BYTE* srcBase)
|
||||
{
|
||||
size_t const h = Lizard_hashPositionSmall(p);
|
||||
Lizard_putPositionOnHashSmall(p, h, hashTable, srcBase);
|
||||
}
|
||||
|
||||
static U32 Lizard_getPositionOnHashSmall(size_t h, U32* hashTable)
|
||||
{
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
static U32 Lizard_getPositionSmall(const BYTE* p, U32* hashTable)
|
||||
{
|
||||
size_t const h = Lizard_hashPositionSmall(p);
|
||||
return Lizard_getPositionOnHashSmall(h, hashTable);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int Lizard_compress_fastSmall(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
const U32 acceleration = 1;
|
||||
const BYTE* base = ctx->base;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = iend - LASTLITERALS;
|
||||
const BYTE* anchor = ip;
|
||||
|
||||
size_t forwardH, matchIndex;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
|
||||
/* Init conditions */
|
||||
if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
|
||||
|
||||
if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
|
||||
/* First Byte */
|
||||
Lizard_putPositionSmall(ip, ctx->hashTable, base);
|
||||
ip++; forwardH = Lizard_hashPositionSmall(ip);
|
||||
|
||||
/* Main Loop */
|
||||
for ( ; ; ) {
|
||||
const BYTE* match;
|
||||
size_t matchLength;
|
||||
|
||||
/* Find a match */
|
||||
{ const BYTE* forwardIp = ip;
|
||||
unsigned step = 1;
|
||||
unsigned searchMatchNb = acceleration << Lizard_skipTrigger;
|
||||
while (1) {
|
||||
size_t const h = forwardH;
|
||||
ip = forwardIp;
|
||||
forwardIp += step;
|
||||
step = (searchMatchNb++ >> Lizard_skipTrigger);
|
||||
|
||||
if (unlikely(forwardIp > mflimit)) goto _last_literals;
|
||||
|
||||
matchIndex = Lizard_getPositionOnHashSmall(h, ctx->hashTable);
|
||||
forwardH = Lizard_hashPositionSmall(forwardIp);
|
||||
Lizard_putPositionOnHashSmall(ip, h, ctx->hashTable, base);
|
||||
|
||||
if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;
|
||||
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
int back = 0;
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
|
||||
while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
match += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
|
||||
int back = 0;
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
|
||||
while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
matchLength -= back;
|
||||
match = base + matchIndex + back;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
{
|
||||
ip += back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
_next_match:
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
|
||||
/* Fill table */
|
||||
Lizard_putPositionSmall(ip-2, ctx->hashTable, base);
|
||||
|
||||
/* Test next position */
|
||||
matchIndex = Lizard_getPositionSmall(ip, ctx->hashTable);
|
||||
Lizard_putPositionSmall(ip, ctx->hashTable, base);
|
||||
if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))
|
||||
{
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if (MEM_read32(match) == MEM_read32(ip))
|
||||
{
|
||||
matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
#if LIZARD_FAST_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
|
||||
match = base + matchIndex;
|
||||
#if LIZARD_FAST_LONGOFF_MM > 0
|
||||
if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
goto _next_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
forwardH = Lizard_hashPositionSmall(++ip);
|
||||
}
|
||||
|
||||
_last_literals:
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
_output_error:
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#define LIZ_HC_MIN_OFFSET 8
|
||||
#define LIZ_HC_LONGOFF_MM 0 /* not used with offsets > 1<<16 */
|
||||
#define LIZARD_HC_MIN_OFFSET 8
|
||||
#define LIZARD_HC_LONGOFF_MM 0 /* not used with offsets > 1<<16 */
|
||||
#define OPTIMAL_ML (int)((ML_MASK_LZ4-1)+MINMATCH)
|
||||
#define GET_MINMATCH(offset) (MINMATCH)
|
||||
|
||||
#if 1
|
||||
#define LIZ_HC_HASH_FUNCTION(ip, hashLog) LIZ_hashPtr(ip, hashLog, ctx->params.searchLength)
|
||||
#define LIZARD_HC_HASH_FUNCTION(ip, hashLog) Lizard_hashPtr(ip, hashLog, ctx->params.searchLength)
|
||||
#else
|
||||
#define LIZ_HC_HASH_FUNCTION(ip, hashLog) LIZ_hash5Ptr(ip, hashLog)
|
||||
#define LIZARD_HC_HASH_FUNCTION(ip, hashLog) Lizard_hash5Ptr(ip, hashLog)
|
||||
#endif
|
||||
|
||||
/* Update chains up to ip (excluded) */
|
||||
FORCE_INLINE void LIZ_Insert (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
FORCE_INLINE void Lizard_Insert (Lizard_stream_t* ctx, const BYTE* ip)
|
||||
{
|
||||
U32* const chainTable = ctx->chainTable;
|
||||
U32* const hashTable = ctx->hashTable;
|
||||
@@ -25,14 +25,14 @@ FORCE_INLINE void LIZ_Insert (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
|
||||
while (idx < target) {
|
||||
size_t const h = LIZ_hashPtr(base+idx, hashLog, ctx->params.searchLength);
|
||||
size_t const h = Lizard_hashPtr(base+idx, hashLog, ctx->params.searchLength);
|
||||
size_t delta = idx - hashTable[h];
|
||||
if (delta>maxDistance) delta = maxDistance;
|
||||
DELTANEXT(idx) = (U32)delta;
|
||||
if (idx >= hashTable[h] + LIZ_HC_MIN_OFFSET)
|
||||
if ((hashTable[h] >= idx) || (idx >= hashTable[h] + LIZARD_HC_MIN_OFFSET))
|
||||
hashTable[h] = idx;
|
||||
#if MINMATCH == 3
|
||||
HashTable3[LIZ_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;
|
||||
HashTable3[Lizard_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;
|
||||
#endif
|
||||
idx++;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ FORCE_INLINE void LIZ_Insert (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_InsertAndFindBestMatch (LIZ_stream_t* ctx, /* Index table will be updated */
|
||||
FORCE_INLINE int Lizard_InsertAndFindBestMatch (Lizard_stream_t* ctx, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos)
|
||||
{
|
||||
@@ -60,39 +60,39 @@ FORCE_INLINE int LIZ_InsertAndFindBestMatch (LIZ_stream_t* ctx, /* Index table
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 contentMask = (1 << ctx->params.contentLog) - 1;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip-base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
const U32 current = (U32)(ip - base);
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;
|
||||
|
||||
/* HC4 match finder */
|
||||
LIZ_Insert(ctx, ip);
|
||||
matchIndex = HashTable[LIZ_HC_HASH_FUNCTION(ip, hashLog)];
|
||||
Lizard_Insert(ctx, ip);
|
||||
matchIndex = HashTable[LIZARD_HC_HASH_FUNCTION(ip, hashLog)];
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts)) {
|
||||
while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_HC_MIN_OFFSET)
|
||||
#if LIZARD_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_HC_MIN_OFFSET)
|
||||
#endif
|
||||
if (*(match+ml) == *(ip+ml)
|
||||
&& (MEM_read32(match) == MEM_read32(ip)))
|
||||
{
|
||||
size_t const mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
#if LIZ_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZ_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
size_t const mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
#if LIZARD_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
if (mlt > ml) { ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
// fprintf(stderr, "dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\n", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));
|
||||
#if LIZ_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_HC_MIN_OFFSET)
|
||||
#if LIZARD_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_HC_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
size_t mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
#if LIZ_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZ_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZ_MAX_16BIT_OFFSET))
|
||||
size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
#if LIZARD_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
|
||||
}
|
||||
@@ -106,8 +106,8 @@ FORCE_INLINE int LIZ_InsertAndFindBestMatch (LIZ_stream_t* ctx, /* Index table
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_InsertAndGetWiderMatch (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_InsertAndGetWiderMatch (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
@@ -128,28 +128,29 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatch (
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 contentMask = (1 << ctx->params.contentLog) - 1;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip-base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
|
||||
/* First Match */
|
||||
LIZ_Insert(ctx, ip);
|
||||
matchIndex = HashTable[LIZ_HC_HASH_FUNCTION(ip, hashLog)];
|
||||
const U32 current = (U32)(ip - base);
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts)) {
|
||||
/* First Match */
|
||||
Lizard_Insert(ctx, ip);
|
||||
matchIndex = HashTable[LIZARD_HC_HASH_FUNCTION(ip, hashLog)];
|
||||
|
||||
while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit) {
|
||||
const BYTE* match = base + matchIndex;
|
||||
#if LIZ_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_HC_MIN_OFFSET)
|
||||
#if LIZARD_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_HC_MIN_OFFSET)
|
||||
#endif
|
||||
if (*(iLowLimit + longest) == *(match - LLdelta + longest)) {
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
int mlt = MINMATCH + LIZ_count(ip+MINMATCH, match+MINMATCH, iHighLimit);
|
||||
int mlt = MINMATCH + Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit);
|
||||
int back = 0;
|
||||
while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
#if LIZ_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZ_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
#if LIZARD_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
if (mlt > longest) {
|
||||
longest = (int)mlt;
|
||||
@@ -160,17 +161,17 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatch (
|
||||
}
|
||||
} else {
|
||||
const BYTE* match = dictBase + matchIndex;
|
||||
#if LIZ_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_HC_MIN_OFFSET)
|
||||
#if LIZARD_HC_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_HC_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
int back=0;
|
||||
size_t mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
#if LIZ_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZ_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZ_MAX_16BIT_OFFSET))
|
||||
#if LIZARD_HC_LONGOFF_MM > 0
|
||||
if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZARD_MAX_16BIT_OFFSET))
|
||||
#endif
|
||||
if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
|
||||
}
|
||||
@@ -184,8 +185,8 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatch (
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_hashChain (
|
||||
LIZ_stream_t* const ctx,
|
||||
FORCE_INLINE int Lizard_compress_hashChain (
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
@@ -207,7 +208,7 @@ FORCE_INLINE int LIZ_compress_hashChain (
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit) {
|
||||
ml = LIZ_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref));
|
||||
ml = Lizard_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref));
|
||||
if (!ml) { ip++; continue; }
|
||||
|
||||
/* saved, in case we would skip too much */
|
||||
@@ -217,11 +218,11 @@ FORCE_INLINE int LIZ_compress_hashChain (
|
||||
|
||||
_Search2:
|
||||
if (ip+ml < mflimit)
|
||||
ml2 = LIZ_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
|
||||
ml2 = Lizard_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
|
||||
else ml2 = ml;
|
||||
|
||||
if (ml2 == ml) { /* No better match */
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -254,7 +255,7 @@ _Search3:
|
||||
if (ip+new_ml > start2 + ml2 - GET_MINMATCH((U32)(start2 - ref2))) {
|
||||
new_ml = (int)(start2 - ip) + ml2 - GET_MINMATCH((U32)(start2 - ref2));
|
||||
if (new_ml < GET_MINMATCH((U32)(ip - ref))) { // match2 doesn't fit
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -268,16 +269,16 @@ _Search3:
|
||||
/* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
|
||||
|
||||
if (start2 + ml2 < mflimit)
|
||||
ml3 = LIZ_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
|
||||
ml3 = Lizard_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
|
||||
else ml3 = ml2;
|
||||
|
||||
if (ml3 == ml2) { /* No better match : 2 sequences to encode */
|
||||
/* ip & ref are known; Now for ml */
|
||||
if (start2 < ip+ml) ml = (int)(start2 - ip);
|
||||
/* Now, encode 2 sequences */
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start2;
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -295,7 +296,7 @@ _Search3:
|
||||
}
|
||||
}
|
||||
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
@@ -323,7 +324,7 @@ _Search3:
|
||||
if (ip + ml > start2 + ml2 - GET_MINMATCH((U32)(start2 - ref2))) {
|
||||
ml = (int)(start2 - ip) + ml2 - GET_MINMATCH((U32)(start2 - ref2));
|
||||
if (ml < GET_MINMATCH((U32)(ip - ref))) { // match2 doesn't fit, remove it
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
@@ -344,7 +345,7 @@ _Search3:
|
||||
ml = (int)(start2 - ip);
|
||||
}
|
||||
}
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
|
||||
ip = start2;
|
||||
ref = ref2;
|
||||
@@ -359,7 +360,7 @@ _Search3:
|
||||
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
@@ -1,7 +1,7 @@
|
||||
#define LIZ_LOWESTPRICE_MIN_OFFSET 8
|
||||
#define LIZARD_LOWESTPRICE_MIN_OFFSET 8
|
||||
|
||||
|
||||
FORCE_INLINE size_t LIZ_more_profitable(LIZ_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, size_t literals, int last_off)
|
||||
FORCE_INLINE size_t Lizard_more_profitable(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, size_t literals, int last_off)
|
||||
{
|
||||
size_t sum;
|
||||
|
||||
@@ -13,20 +13,20 @@ FORCE_INLINE size_t LIZ_more_profitable(LIZ_stream_t* const ctx, const BYTE *bes
|
||||
if ((int)off == last_off) off = 0; // rep code
|
||||
if ((int)best_off == last_off) best_off = 0;
|
||||
|
||||
return LIZ_get_price_LZ5v2(ctx, last_off, ip, ctx->off24pos, sum - common, (U32)off, common) <= LIZ_get_price_LZ5v2(ctx, last_off, best_ip, ctx->off24pos, sum - best_common, (U32)best_off, best_common);
|
||||
return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, sum - common, (U32)off, common) <= Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, sum - best_common, (U32)best_off, best_common);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE size_t LIZ_better_price(LIZ_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, int last_off)
|
||||
FORCE_INLINE size_t Lizard_better_price(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, int last_off)
|
||||
{
|
||||
if ((int)off == last_off) off = 0; // rep code
|
||||
if ((int)best_off == last_off) best_off = 0;
|
||||
|
||||
return LIZ_get_price_LZ5v2(ctx, last_off, ip, ctx->off24pos, 0, (U32)off, common) < LIZ_get_price_LZ5v2(ctx, last_off, best_ip, ctx->off24pos, common - best_common, (U32)best_off, best_common);
|
||||
return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, 0, (U32)off, common) < Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, common - best_common, (U32)best_off, best_common);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table will be updated */
|
||||
FORCE_INLINE int Lizard_FindMatchLowestPrice (Lizard_stream_t* ctx, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos)
|
||||
{
|
||||
@@ -47,15 +47,15 @@ FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table w
|
||||
int nbAttempts=ctx->params.searchNum;
|
||||
size_t ml=0, mlt;
|
||||
|
||||
matchIndex = HashTable[LIZ_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
|
||||
if (ctx->last_off >= LIZ_LOWESTPRICE_MIN_OFFSET) {
|
||||
if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
|
||||
intptr_t matchIndexLO = (ip - ctx->last_off) - base;
|
||||
if (matchIndexLO >= lowLimit) {
|
||||
if (matchIndexLO >= dictLimit) {
|
||||
match = base + matchIndexLO;
|
||||
mlt = LIZ_count(ip, match, iLimit);// + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count(ip, match, iLimit);// + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlt > REPMINMATCH) {
|
||||
*matchpos = match;
|
||||
return (int)mlt;
|
||||
@@ -63,8 +63,8 @@ FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table w
|
||||
} else {
|
||||
match = dictBase + matchIndexLO;
|
||||
if ((U32)((dictLimit-1) - matchIndexLO) >= 3) { /* intentional overflow */
|
||||
mlt = LIZ_count_2segments(ip, match, iLimit, dictEnd, lowPrefixPtr);
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count_2segments(ip, match, iLimit, dictEnd, lowPrefixPtr);
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlt > REPMINMATCH) {
|
||||
*matchpos = base + matchIndexLO; /* virtual matchpos */
|
||||
return (int)mlt;
|
||||
@@ -77,16 +77,16 @@ FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table w
|
||||
|
||||
#if MINMATCH == 3
|
||||
{
|
||||
U32 matchIndex3 = ctx->hashTable3[LIZ_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
if (matchIndex3 < current && matchIndex3 >= lowLimit)
|
||||
{
|
||||
size_t offset = (size_t)current - matchIndex3;
|
||||
if (offset < LIZ_MAX_8BIT_OFFSET)
|
||||
if (offset < LIZARD_MAX_8BIT_OFFSET)
|
||||
{
|
||||
match = ip - offset;
|
||||
if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match))
|
||||
{
|
||||
ml = 3;//LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
ml = 3;//Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
*matchpos = match;
|
||||
}
|
||||
}
|
||||
@@ -96,22 +96,21 @@ FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table w
|
||||
while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_LOWESTPRICE_MIN_OFFSET) {
|
||||
if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip))) {
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml && LIZ_better_price(ctx, ip, (ip - *matchpos), ml, ip, (ip - match), mlt, ctx->last_off)))
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (ip - match), mlt, ctx->last_off)))
|
||||
{ ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
matchDict = dictBase + matchIndex;
|
||||
// fprintf(stderr, "dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\n", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(matchDict) == MEM_read32(ip)) {
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml && LIZ_better_price(ctx, ip, (ip - *matchpos), ml, ip, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
{ ml = mlt; *matchpos = match; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
@@ -123,8 +122,8 @@ FORCE_INLINE int LIZ_FindMatchLowestPrice (LIZ_stream_t* ctx, /* Index table w
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE size_t Lizard_GetWiderMatch (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
@@ -150,21 +149,21 @@ FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
size_t mlt;
|
||||
|
||||
/* First Match */
|
||||
matchIndex = HashTable[LIZ_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
|
||||
if (ctx->last_off >= LIZ_LOWESTPRICE_MIN_OFFSET) {
|
||||
if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
|
||||
intptr_t matchIndexLO = (ip - ctx->last_off) - base;
|
||||
if (matchIndexLO >= lowLimit) {
|
||||
if (matchIndexLO >= dictLimit) {
|
||||
match = base + matchIndexLO;
|
||||
if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
|
||||
int back = 0;
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if (mlt > longest)
|
||||
if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET)) {
|
||||
if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {
|
||||
*matchpos = match+back;
|
||||
*startpos = ip+back;
|
||||
longest = mlt;
|
||||
@@ -175,12 +174,12 @@ FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
if ((U32)((dictLimit-1) - matchIndexLO) >= 3) /* intentional overflow */
|
||||
if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
|
||||
int back=0;
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (matchIndexLO+back > lowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if (mlt > longest)
|
||||
if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET)) {
|
||||
if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {
|
||||
*matchpos = base + matchIndexLO + back; /* virtual matchpos */
|
||||
*startpos = ip+back;
|
||||
longest = mlt;
|
||||
@@ -192,19 +191,19 @@ FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
|
||||
#if MINMATCH == 3
|
||||
{
|
||||
U32 matchIndex3 = ctx->hashTable3[LIZ_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
if (matchIndex3 < current && matchIndex3 >= lowLimit) {
|
||||
size_t offset = (size_t)current - matchIndex3;
|
||||
if (offset < LIZ_MAX_8BIT_OFFSET) {
|
||||
if (offset < LIZARD_MAX_8BIT_OFFSET) {
|
||||
match = ip - offset;
|
||||
if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {
|
||||
mlt = LIZ_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
|
||||
int back = 0;
|
||||
while ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if (!longest || (mlt > longest && LIZ_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off))) {
|
||||
if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off))) {
|
||||
*matchpos = match + back;
|
||||
*startpos = ip + back;
|
||||
longest = mlt;
|
||||
@@ -218,30 +217,29 @@ FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_LOWESTPRICE_MIN_OFFSET) {
|
||||
if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
int back = 0;
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!longest || (mlt > longest && LIZ_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off)))
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off)))
|
||||
{ longest = mlt; *startpos = ip+back; *matchpos = match+back; }
|
||||
}
|
||||
} else {
|
||||
matchDict = dictBase + matchIndex;
|
||||
// fprintf(stderr, "dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\n", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(matchDict) == MEM_read32(ip)) {
|
||||
int back=0;
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchDict[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!longest || (mlt > longest && LIZ_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
{ longest = mlt; *startpos = ip+back; *matchpos = match+back; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
@@ -255,8 +253,8 @@ FORCE_INLINE size_t LIZ_GetWiderMatch (
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_lowestPrice(
|
||||
LIZ_stream_t* const ctx,
|
||||
FORCE_INLINE int Lizard_compress_lowestPrice(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
@@ -277,8 +275,8 @@ FORCE_INLINE int LIZ_compress_lowestPrice(
|
||||
/* Main Loop */
|
||||
while (ip < mflimit)
|
||||
{
|
||||
LIZ_Insert(ctx, ip);
|
||||
ml = LIZ_FindMatchLowestPrice (ctx, ip, matchlimit, (&ref));
|
||||
Lizard_Insert(ctx, ip);
|
||||
ml = Lizard_FindMatchLowestPrice (ctx, ip, matchlimit, (&ref));
|
||||
if (!ml) { ip++; continue; }
|
||||
|
||||
{
|
||||
@@ -299,8 +297,8 @@ _Search:
|
||||
if (ip+ml >= mflimit) { goto _Encode; }
|
||||
if (ml >= sufficient_len) { goto _Encode; }
|
||||
|
||||
LIZ_Insert(ctx, ip);
|
||||
ml2 = (int)LIZ_GetWiderMatch(ctx, ip + ml - 2, anchor, matchlimit, 0, &ref2, &start2);
|
||||
Lizard_Insert(ctx, ip);
|
||||
ml2 = (int)Lizard_GetWiderMatch(ctx, ip + ml - 2, anchor, matchlimit, 0, &ref2, &start2);
|
||||
if (!ml2) goto _Encode;
|
||||
|
||||
{
|
||||
@@ -310,7 +308,7 @@ _Search:
|
||||
|
||||
// find the lowest price for encoding ml bytes
|
||||
best_pos = ip;
|
||||
best_price = LIZ_MAX_PRICE;
|
||||
best_price = LIZARD_MAX_PRICE;
|
||||
off0 = (int)(ip - ref);
|
||||
off1 = (int)(start2 - ref2);
|
||||
|
||||
@@ -318,14 +316,14 @@ _Search:
|
||||
{
|
||||
int common0 = (int)(pos - ip);
|
||||
if (common0 >= MINMATCH) {
|
||||
price = (int)LIZ_get_price_LZ5v2(ctx, ctx->last_off, ip, ctx->off24pos, ip - anchor, (off0 == ctx->last_off) ? 0 : off0, common0);
|
||||
price = (int)Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, ip - anchor, (off0 == ctx->last_off) ? 0 : off0, common0);
|
||||
|
||||
{
|
||||
int common1 = (int)(start2 + ml2 - pos);
|
||||
if (common1 >= MINMATCH)
|
||||
price += LIZ_get_price_LZ5v2(ctx, ctx->last_off, pos, ctx->off24pos, 0, (off1 == off0) ? 0 : (off1), common1);
|
||||
price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, 0, (off1 == off0) ? 0 : (off1), common1);
|
||||
else
|
||||
price += LIZ_get_price_LZ5v2(ctx, ctx->last_off, pos, ctx->off24pos, common1, 0, 0);
|
||||
price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, common1, 0, 0);
|
||||
}
|
||||
|
||||
if (price < best_price) {
|
||||
@@ -333,19 +331,18 @@ _Search:
|
||||
best_pos = pos;
|
||||
}
|
||||
} else {
|
||||
price = LIZ_get_price_LZ5v2(ctx, ctx->last_off, ip, ctx->off24pos, start2 - anchor, (off1 == ctx->last_off) ? 0 : off1, ml2);
|
||||
price = Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, start2 - anchor, (off1 == ctx->last_off) ? 0 : off1, ml2);
|
||||
|
||||
if (price < best_price)
|
||||
best_pos = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// LIZ_DEBUG("%u: TRY last_off=%d literals=%u off=%u mlen=%u literals2=%u off2=%u mlen2=%u best=%d\n", (U32)(ip - ctx->inputBuffer), ctx->last_off, (U32)(ip - anchor), off0, (U32)ml, (U32)(start2 - anchor), off1, ml2, (U32)(best_pos - ip));
|
||||
ml = (int)(best_pos - ip);
|
||||
}
|
||||
|
||||
|
||||
if ((ml < MINMATCH) || ((ml < minMatchLongOff) && ((U32)(ip-ref) >= LIZ_MAX_16BIT_OFFSET)))
|
||||
if ((ml < MINMATCH) || ((ml < minMatchLongOff) && ((U32)(ip-ref) >= LIZARD_MAX_16BIT_OFFSET)))
|
||||
{
|
||||
ip = start2;
|
||||
ref = ref2;
|
||||
@@ -356,7 +353,7 @@ _Search:
|
||||
_Encode:
|
||||
if (start0 < ip)
|
||||
{
|
||||
if (LIZ_more_profitable(ctx, ip, (ip - ref), ml, start0, (start0 - ref0), ml0, (ref0 - ref), ctx->last_off))
|
||||
if (Lizard_more_profitable(ctx, ip, (ip - ref), ml, start0, (start0 - ref0), ml0, (ref0 - ref), ctx->last_off))
|
||||
{
|
||||
ip = start0;
|
||||
ref = ref0;
|
||||
@@ -364,13 +361,12 @@ _Encode:
|
||||
}
|
||||
}
|
||||
|
||||
// if ((ml < minMatchLongOff) && ((U32)(ip-ref) >= LIZ_MAX_16BIT_OFFSET)) { printf("LIZ_encodeSequence ml=%d off=%d\n", ml, (U32)(ip-ref)); exit(0); }
|
||||
if (LIZ_encodeSequence_LZ5v2(ctx, &ip, &anchor, ml, ((ip - ref == ctx->last_off) ? ip : ref))) return 0;
|
||||
if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, ml, ((ip - ref == ctx->last_off) ? ip : ref))) return 0;
|
||||
}
|
||||
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ5v2(ctx, &ip, &anchor)) goto _output_error;
|
||||
if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
@@ -1,11 +1,11 @@
|
||||
#define OPTIMAL_ML (int)((ML_MASK_LZ4-1)+MINMATCH)
|
||||
|
||||
//#define LIZ_NOCHAIN_HASH_FUNCTION(ip, hashLog) LIZ_hashPtr(ip, hashLog, ctx->params.searchLength)
|
||||
#define LIZ_NOCHAIN_HASH_FUNCTION(ip, hashLog) LIZ_hash5Ptr(ip, hashLog)
|
||||
#define LIZ_NOCHAIN_MIN_OFFSET 8
|
||||
//#define LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog) Lizard_hashPtr(ip, hashLog, ctx->params.searchLength)
|
||||
#define LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog) Lizard_hash5Ptr(ip, hashLog)
|
||||
#define LIZARD_NOCHAIN_MIN_OFFSET 8
|
||||
|
||||
/* Update chains up to ip (excluded) */
|
||||
FORCE_INLINE void LIZ_InsertNoChain (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
FORCE_INLINE void Lizard_InsertNoChain (Lizard_stream_t* ctx, const BYTE* ip)
|
||||
{
|
||||
U32* const hashTable = ctx->hashTable;
|
||||
const BYTE* const base = ctx->base;
|
||||
@@ -14,8 +14,8 @@ FORCE_INLINE void LIZ_InsertNoChain (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
|
||||
while (idx < target) {
|
||||
size_t const h = LIZ_NOCHAIN_HASH_FUNCTION(base+idx, hashLog);
|
||||
if (idx >= hashTable[h] + LIZ_NOCHAIN_MIN_OFFSET)
|
||||
size_t const h = LIZARD_NOCHAIN_HASH_FUNCTION(base+idx, hashLog);
|
||||
if ((hashTable[h] >= idx) || (idx >= hashTable[h] + LIZARD_NOCHAIN_MIN_OFFSET))
|
||||
hashTable[h] = idx;
|
||||
idx++;
|
||||
}
|
||||
@@ -24,8 +24,7 @@ FORCE_INLINE void LIZ_InsertNoChain (LIZ_stream_t* ctx, const BYTE* ip)
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_InsertAndFindBestMatchNoChain (LIZ_stream_t* ctx, /* Index table will be updated */
|
||||
FORCE_INLINE int Lizard_InsertAndFindBestMatchNoChain (Lizard_stream_t* ctx, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos)
|
||||
{
|
||||
@@ -40,32 +39,32 @@ FORCE_INLINE int LIZ_InsertAndFindBestMatchNoChain (LIZ_stream_t* ctx, /* Inde
|
||||
size_t ml=0;
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip-base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
const U32 current = (U32)(ip - base);
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;
|
||||
|
||||
/* HC4 match finder */
|
||||
LIZ_InsertNoChain(ctx, ip);
|
||||
matchIndex = HashTable[LIZ_NOCHAIN_HASH_FUNCTION(ip, hashLog)];
|
||||
Lizard_InsertNoChain(ctx, ip);
|
||||
matchIndex = HashTable[LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog)];
|
||||
|
||||
if (matchIndex >= lowLimit) {
|
||||
if ((matchIndex < current) && (matchIndex >= lowLimit)) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
#if LIZ_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_NOCHAIN_MIN_OFFSET)
|
||||
#if LIZARD_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_NOCHAIN_MIN_OFFSET)
|
||||
#endif
|
||||
if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))
|
||||
{
|
||||
size_t const mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
size_t const mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if (mlt > ml) { ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
// fprintf(stderr, "dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\n", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));
|
||||
#if LIZ_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_NOCHAIN_MIN_OFFSET)
|
||||
#if LIZARD_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_NOCHAIN_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
size_t mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
@@ -75,8 +74,8 @@ FORCE_INLINE int LIZ_InsertAndFindBestMatchNoChain (LIZ_stream_t* ctx, /* Inde
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_InsertAndGetWiderMatchNoChain (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_InsertAndGetWiderMatchNoChain (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
@@ -94,21 +93,22 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatchNoChain (
|
||||
int LLdelta = (int)(ip-iLowLimit);
|
||||
const int hashLog = ctx->params.hashLog;
|
||||
const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip-base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
|
||||
|
||||
/* First Match */
|
||||
LIZ_InsertNoChain(ctx, ip);
|
||||
matchIndex = HashTable[LIZ_NOCHAIN_HASH_FUNCTION(ip, hashLog)];
|
||||
const U32 current = (U32)(ip - base);
|
||||
const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;
|
||||
|
||||
if (matchIndex>=lowLimit) {
|
||||
/* First Match */
|
||||
Lizard_InsertNoChain(ctx, ip);
|
||||
matchIndex = HashTable[LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog)];
|
||||
|
||||
if ((matchIndex < current) && (matchIndex >= lowLimit)) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
const BYTE* match = base + matchIndex;
|
||||
#if LIZ_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZ_NOCHAIN_MIN_OFFSET)
|
||||
#if LIZARD_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - match) >= LIZARD_NOCHAIN_MIN_OFFSET)
|
||||
#endif
|
||||
if (*(iLowLimit + longest) == *(match - LLdelta + longest)) {
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
int mlt = MINMATCH + LIZ_count(ip+MINMATCH, match+MINMATCH, iHighLimit);
|
||||
int mlt = MINMATCH + Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit);
|
||||
int back = 0;
|
||||
while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
@@ -122,13 +122,13 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatchNoChain (
|
||||
}
|
||||
} else {
|
||||
const BYTE* match = dictBase + matchIndex;
|
||||
#if LIZ_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZ_NOCHAIN_MIN_OFFSET)
|
||||
#if LIZARD_NOCHAIN_MIN_OFFSET > 0
|
||||
if ((U32)(ip - (base + matchIndex)) >= LIZARD_NOCHAIN_MIN_OFFSET)
|
||||
#endif
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
int back=0;
|
||||
size_t mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
|
||||
@@ -140,8 +140,8 @@ FORCE_INLINE int LIZ_InsertAndGetWiderMatchNoChain (
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_noChain (
|
||||
LIZ_stream_t* const ctx,
|
||||
FORCE_INLINE int Lizard_compress_noChain (
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
@@ -163,7 +163,7 @@ FORCE_INLINE int LIZ_compress_noChain (
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit) {
|
||||
ml = LIZ_InsertAndFindBestMatchNoChain (ctx, ip, matchlimit, (&ref));
|
||||
ml = Lizard_InsertAndFindBestMatchNoChain (ctx, ip, matchlimit, (&ref));
|
||||
if (!ml) { ip++; continue; }
|
||||
|
||||
/* saved, in case we would skip too much */
|
||||
@@ -173,11 +173,11 @@ FORCE_INLINE int LIZ_compress_noChain (
|
||||
|
||||
_Search2:
|
||||
if (ip+ml < mflimit)
|
||||
ml2 = LIZ_InsertAndGetWiderMatchNoChain(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
|
||||
ml2 = Lizard_InsertAndGetWiderMatchNoChain(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
|
||||
else ml2 = ml;
|
||||
|
||||
if (ml2 == ml) { /* No better match */
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -218,16 +218,16 @@ _Search3:
|
||||
/* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
|
||||
|
||||
if (start2 + ml2 < mflimit)
|
||||
ml3 = LIZ_InsertAndGetWiderMatchNoChain(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
|
||||
ml3 = Lizard_InsertAndGetWiderMatchNoChain(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
|
||||
else ml3 = ml2;
|
||||
|
||||
if (ml3 == ml2) { /* No better match : 2 sequences to encode */
|
||||
/* ip & ref are known; Now for ml */
|
||||
if (start2 < ip+ml) ml = (int)(start2 - ip);
|
||||
/* Now, encode 2 sequences */
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start2;
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ _Search3:
|
||||
}
|
||||
}
|
||||
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
@@ -273,7 +273,7 @@ _Search3:
|
||||
if (ip + ml > start2 + ml2 - MINMATCH) {
|
||||
ml = (int)(start2 - ip) + ml2 - MINMATCH;
|
||||
if (ml < MINMATCH) { // match2 doesn't fit, remove it
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
@@ -294,7 +294,7 @@ _Search3:
|
||||
ml = (int)(start2 - ip);
|
||||
}
|
||||
}
|
||||
if (LIZ_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;
|
||||
|
||||
ip = start2;
|
||||
ref = ref2;
|
||||
@@ -309,7 +309,7 @@ _Search3:
|
||||
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
@@ -1,18 +1,18 @@
|
||||
#define LIZ_LOG_PARSER(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LIZ_LOG_PRICE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LIZ_LOG_ENCODE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LIZARD_LOG_PARSER(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LIZARD_LOG_PRICE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
#define LIZARD_LOG_ENCODE(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||
|
||||
#define LIZ_OPTIMAL_MIN_OFFSET 8
|
||||
#define LIZ_OPT_NUM (1<<12)
|
||||
#define LIZARD_OPTIMAL_MIN_OFFSET 8
|
||||
#define LIZARD_OPT_NUM (1<<12)
|
||||
#define REPMINMATCH 1
|
||||
|
||||
|
||||
FORCE_INLINE size_t LIZ_get_price(LIZ_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength)
|
||||
FORCE_INLINE size_t Lizard_get_price(Lizard_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength)
|
||||
{
|
||||
if (ctx->params.decompressType == LIZ_coderwords_LZ4)
|
||||
return LIZ_get_price_LZ4(ctx, ip, litLength, offset, matchLength);
|
||||
if (ctx->params.decompressType == Lizard_coderwords_LZ4)
|
||||
return Lizard_get_price_LZ4(ctx, ip, litLength, offset, matchLength);
|
||||
|
||||
return LIZ_get_price_LZ5v2(ctx, rep, ip, off24pos, litLength, offset, matchLength);
|
||||
return Lizard_get_price_LIZv1(ctx, rep, ip, off24pos, litLength, offset, matchLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ typedef struct
|
||||
int off;
|
||||
int len;
|
||||
int back;
|
||||
} LIZ_match_t;
|
||||
} Lizard_match_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -32,11 +32,11 @@ typedef struct
|
||||
int litlen;
|
||||
int rep;
|
||||
const BYTE* off24pos;
|
||||
} LIZ_optimal_t;
|
||||
} Lizard_optimal_t;
|
||||
|
||||
|
||||
/* Update chains up to ip (excluded) */
|
||||
FORCE_INLINE void LIZ_BinTree_Insert(LIZ_stream_t* ctx, const BYTE* ip)
|
||||
FORCE_INLINE void Lizard_BinTree_Insert(Lizard_stream_t* ctx, const BYTE* ip)
|
||||
{
|
||||
#if MINMATCH == 3
|
||||
U32* HashTable3 = ctx->hashTable3;
|
||||
@@ -45,7 +45,7 @@ FORCE_INLINE void LIZ_BinTree_Insert(LIZ_stream_t* ctx, const BYTE* ip)
|
||||
U32 idx = ctx->nextToUpdate;
|
||||
|
||||
while(idx < target) {
|
||||
HashTable3[LIZ_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;
|
||||
HashTable3[Lizard_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;
|
||||
idx++;
|
||||
}
|
||||
|
||||
@@ -57,13 +57,13 @@ FORCE_INLINE void LIZ_BinTree_Insert(LIZ_stream_t* ctx, const BYTE* ip)
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_GetAllMatches (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_GetAllMatches (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
size_t best_mlen,
|
||||
LIZ_match_t* matches)
|
||||
Lizard_match_t* matches)
|
||||
{
|
||||
U32* const chainTable = ctx->chainTable;
|
||||
U32* const HashTable = ctx->hashTable;
|
||||
@@ -88,19 +88,19 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
if (ip + MINMATCH > iHighLimit) return 0;
|
||||
|
||||
/* First Match */
|
||||
HashPos = &HashTable[LIZ_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
matchIndex = *HashPos;
|
||||
#if MINMATCH == 3
|
||||
{
|
||||
U32* const HashTable3 = ctx->hashTable3;
|
||||
U32* HashPos3 = &HashTable3[LIZ_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
U32* HashPos3 = &HashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
|
||||
if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) {
|
||||
size_t offset = current - *HashPos3;
|
||||
if (offset < LIZ_MAX_8BIT_OFFSET) {
|
||||
if (offset < LIZARD_MAX_8BIT_OFFSET) {
|
||||
match = ip - offset;
|
||||
if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {
|
||||
size_t mlt = LIZ_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
size_t mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
|
||||
int back = 0;
|
||||
while ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;
|
||||
@@ -127,15 +127,15 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_OPTIMAL_MIN_OFFSET) {
|
||||
if ((U32)(ip - match) >= LIZARD_OPTIMAL_MIN_OFFSET) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
if ((/*fullSearch ||*/ ip[best_mlen] == match[best_mlen]) && (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip))) {
|
||||
int back = 0;
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlt > best_mlen) {
|
||||
best_mlen = mlt;
|
||||
matches[mnum].off = (int)(ip - match);
|
||||
@@ -143,7 +143,7 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
matches[mnum].back = -back;
|
||||
mnum++;
|
||||
|
||||
if (best_mlen > LIZ_OPT_NUM) break;
|
||||
if (best_mlen > LIZARD_OPT_NUM) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -152,11 +152,11 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_readMINMATCH(matchDict) == MEM_readMINMATCH(ip)) {
|
||||
int back=0;
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchDict[back-1])) back--;
|
||||
mlt -= back;
|
||||
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlt > best_mlen) {
|
||||
best_mlen = mlt;
|
||||
matches[mnum].off = (int)(ip - match);
|
||||
@@ -164,7 +164,7 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
matches[mnum].back = -back;
|
||||
mnum++;
|
||||
|
||||
if (best_mlen > LIZ_OPT_NUM) break;
|
||||
if (best_mlen > LIZARD_OPT_NUM) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,12 +178,12 @@ FORCE_INLINE int LIZ_GetAllMatches (
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
LIZ_stream_t* ctx,
|
||||
FORCE_INLINE int Lizard_BinTree_GetAllMatches (
|
||||
Lizard_stream_t* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iHighLimit,
|
||||
size_t best_mlen,
|
||||
LIZ_match_t* matches)
|
||||
Lizard_match_t* matches)
|
||||
{
|
||||
U32* const chainTable = ctx->chainTable;
|
||||
U32* const HashTable = ctx->hashTable;
|
||||
@@ -208,21 +208,21 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
if (ip + MINMATCH > iHighLimit) return 0;
|
||||
|
||||
/* First Match */
|
||||
HashPos = &HashTable[LIZ_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
matchIndex = *HashPos;
|
||||
|
||||
|
||||
#if MINMATCH == 3
|
||||
{
|
||||
U32* HashPos3 = &ctx->hashTable3[LIZ_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
U32* HashPos3 = &ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
|
||||
if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) {
|
||||
size_t offset = current - *HashPos3;
|
||||
if (offset < LIZ_MAX_8BIT_OFFSET) {
|
||||
if (offset < LIZARD_MAX_8BIT_OFFSET) {
|
||||
match = ip - offset;
|
||||
if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match))
|
||||
{
|
||||
mlt = LIZ_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
|
||||
|
||||
matches[mnum].off = (int)offset;
|
||||
matches[mnum].len = (int)mlt;
|
||||
@@ -250,16 +250,16 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
// if (ip[mlt] == match[mlt])
|
||||
mlt = LIZ_count(ip, match, iHighLimit);
|
||||
mlt = Lizard_count(ip, match, iHighLimit);
|
||||
} else {
|
||||
match = dictBase + matchIndex;
|
||||
mlt = LIZ_count_2segments(ip, match, iHighLimit, dictEnd, lowPrefixPtr);
|
||||
mlt = Lizard_count_2segments(ip, match, iHighLimit, dictEnd, lowPrefixPtr);
|
||||
if (matchIndex + (int)mlt >= dictLimit)
|
||||
match = base + matchIndex; /* to prepare for next usage of match[mlt] */
|
||||
}
|
||||
|
||||
if ((U32)(current - matchIndex) >= LIZ_OPTIMAL_MIN_OFFSET) {
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(current - matchIndex) < LIZ_MAX_16BIT_OFFSET))
|
||||
if ((U32)(current - matchIndex) >= LIZARD_OPTIMAL_MIN_OFFSET) {
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(current - matchIndex) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlt > best_mlen) {
|
||||
best_mlen = mlt;
|
||||
matches[mnum].off = (int)(current - matchIndex);
|
||||
@@ -267,7 +267,7 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
matches[mnum].back = 0;
|
||||
mnum++;
|
||||
|
||||
if (mlt > LIZ_OPT_NUM) break;
|
||||
if (mlt > LIZARD_OPT_NUM) break;
|
||||
if (ip + mlt >= iHighLimit) break;
|
||||
}
|
||||
} else {
|
||||
@@ -276,9 +276,9 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
size_t newml = 0, newoff = 0;
|
||||
do {
|
||||
newoff += (int)(current - matchIndex);
|
||||
} while (newoff < LIZ_OPTIMAL_MIN_OFFSET);
|
||||
} while (newoff < LIZARD_OPTIMAL_MIN_OFFSET);
|
||||
newMatchIndex = current - newoff;
|
||||
if (newMatchIndex >= dictLimit) newml = LIZ_count(ip, base + newMatchIndex, iHighLimit);
|
||||
if (newMatchIndex >= dictLimit) newml = Lizard_count(ip, base + newMatchIndex, iHighLimit);
|
||||
|
||||
// printf("%d: off=%d mlt=%d\n", (U32)current, (U32)(current - matchIndex), (int)mlt);
|
||||
// printf("%d: newoff=%d newml=%d\n", (U32)current, (int)newoff, (int)newml);
|
||||
@@ -290,7 +290,7 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
matches[mnum].back = 0;
|
||||
mnum++;
|
||||
|
||||
if (newml > LIZ_OPT_NUM) break;
|
||||
if (newml > LIZARD_OPT_NUM) break;
|
||||
if (ip + newml >= iHighLimit) break;
|
||||
}
|
||||
#endif
|
||||
@@ -322,22 +322,22 @@ FORCE_INLINE int LIZ_BinTree_GetAllMatches (
|
||||
|
||||
#define SET_PRICE(pos, mlen, offset, litlen, price) \
|
||||
{ \
|
||||
while (last_pos < pos) { opt[last_pos+1].price = LIZ_MAX_PRICE; last_pos++; } \
|
||||
while (last_pos < pos) { opt[last_pos+1].price = LIZARD_MAX_PRICE; last_pos++; } \
|
||||
opt[pos].mlen = (int)mlen; \
|
||||
opt[pos].off = (int)offset; \
|
||||
opt[pos].litlen = (int)litlen; \
|
||||
opt[pos].price = (int)price; \
|
||||
LIZ_LOG_PARSER("%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\n", (int)(inr-source), pos, last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \
|
||||
LIZARD_LOG_PARSER("%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\n", (int)(inr-source), pos, last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
LIZ_stream_t* const ctx,
|
||||
FORCE_INLINE int Lizard_compress_optimalPrice(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
LIZ_optimal_t opt[LIZ_OPT_NUM + 4];
|
||||
LIZ_match_t matches[LIZ_OPT_NUM + 1];
|
||||
Lizard_optimal_t opt[LIZARD_OPT_NUM + 4];
|
||||
Lizard_match_t matches[LIZARD_OPT_NUM + 1];
|
||||
const BYTE *inr;
|
||||
size_t res, cur, cur2, skip_num = 0;
|
||||
size_t i, llen, litlen, mlen, best_mlen, price, offset, best_off, match_num, last_pos;
|
||||
@@ -356,29 +356,29 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
const size_t sufficient_len = ctx->params.sufficientLength;
|
||||
const int faster_get_matches = (ctx->params.fullSearch == 0);
|
||||
const size_t minMatchLongOff = ctx->params.minMatchLongOff;
|
||||
const int lz5OptimalMinOffset = (ctx->params.decompressType == LIZ_coderwords_LZ4) ? (1<<30) : LIZ_OPTIMAL_MIN_OFFSET;
|
||||
const size_t repMinMatch = (ctx->params.decompressType == LIZ_coderwords_LZ4) ? MINMATCH : REPMINMATCH;
|
||||
const int lizardOptimalMinOffset = (ctx->params.decompressType == Lizard_coderwords_LZ4) ? (1<<30) : LIZARD_OPTIMAL_MIN_OFFSET;
|
||||
const size_t repMinMatch = (ctx->params.decompressType == Lizard_coderwords_LZ4) ? MINMATCH : REPMINMATCH;
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit) {
|
||||
memset(opt, 0, sizeof(LIZ_optimal_t));
|
||||
memset(opt, 0, sizeof(Lizard_optimal_t));
|
||||
last_pos = 0;
|
||||
llen = ip - anchor;
|
||||
|
||||
/* check rep code */
|
||||
|
||||
if (ctx->last_off >= lz5OptimalMinOffset) {
|
||||
if (ctx->last_off >= lizardOptimalMinOffset) {
|
||||
intptr_t matchIndexLO = (ip - ctx->last_off) - base;
|
||||
mlen = 0;
|
||||
if ((matchIndexLO >= lowLimit) && (base + matchIndexLO + maxDistance >= ip)) {
|
||||
if (matchIndexLO >= dictLimit) {
|
||||
mlen = LIZ_count(ip, base + matchIndexLO, matchlimit);
|
||||
mlen = Lizard_count(ip, base + matchIndexLO, matchlimit);
|
||||
} else {
|
||||
mlen = LIZ_count_2segments(ip, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);
|
||||
mlen = Lizard_count_2segments(ip, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);
|
||||
}
|
||||
}
|
||||
if (mlen >= REPMINMATCH) {
|
||||
if (mlen > sufficient_len || mlen >= LIZ_OPT_NUM) {
|
||||
if (mlen > sufficient_len || mlen >= LIZARD_OPT_NUM) {
|
||||
best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;
|
||||
goto encode;
|
||||
}
|
||||
@@ -386,7 +386,7 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
do
|
||||
{
|
||||
litlen = 0;
|
||||
price = LIZ_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen, 0, mlen);
|
||||
price = Lizard_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen, 0, mlen);
|
||||
if (mlen > last_pos || price < (size_t)opt[mlen].price)
|
||||
SET_PRICE(mlen, mlen, 0, litlen, price);
|
||||
mlen--;
|
||||
@@ -399,16 +399,16 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
match_num = 0;
|
||||
else
|
||||
{
|
||||
if (ctx->params.parserType == LIZ_parser_optimalPrice) {
|
||||
LIZ_Insert(ctx, ip);
|
||||
match_num = LIZ_GetAllMatches(ctx, ip, ip, matchlimit, last_pos, matches);
|
||||
if (ctx->params.parserType == Lizard_parser_optimalPrice) {
|
||||
Lizard_Insert(ctx, ip);
|
||||
match_num = Lizard_GetAllMatches(ctx, ip, ip, matchlimit, last_pos, matches);
|
||||
} else {
|
||||
LIZ_BinTree_Insert(ctx, ip);
|
||||
match_num = LIZ_BinTree_GetAllMatches(ctx, ip, matchlimit, last_pos, matches);
|
||||
Lizard_BinTree_Insert(ctx, ip);
|
||||
match_num = Lizard_BinTree_GetAllMatches(ctx, ip, matchlimit, last_pos, matches);
|
||||
}
|
||||
}
|
||||
|
||||
LIZ_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-source), match_num, last_pos);
|
||||
LIZARD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-source), match_num, last_pos);
|
||||
if (!last_pos && !match_num) { ip++; continue; }
|
||||
|
||||
if (match_num && (size_t)matches[match_num-1].len > sufficient_len) {
|
||||
@@ -424,13 +424,13 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
|
||||
for (i = 0; i < match_num; i++) {
|
||||
mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;
|
||||
best_mlen = (matches[i].len < LIZ_OPT_NUM) ? matches[i].len : LIZ_OPT_NUM;
|
||||
LIZ_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-source), matches[i].len, matches[i].off, best_mlen, last_pos);
|
||||
best_mlen = (matches[i].len < LIZARD_OPT_NUM) ? matches[i].len : LIZARD_OPT_NUM;
|
||||
LIZARD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-source), matches[i].len, matches[i].off, best_mlen, last_pos);
|
||||
while (mlen <= best_mlen){
|
||||
litlen = 0;
|
||||
price = LIZ_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen + litlen, matches[i].off, mlen);
|
||||
price = Lizard_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen + litlen, matches[i].off, mlen);
|
||||
|
||||
if ((mlen >= minMatchLongOff) || (matches[i].off < LIZ_MAX_16BIT_OFFSET))
|
||||
if ((mlen >= minMatchLongOff) || (matches[i].off < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (mlen > last_pos || price < (size_t)opt[mlen].price)
|
||||
SET_PRICE(mlen, mlen, matches[i].off, litlen, price);
|
||||
mlen++;
|
||||
@@ -453,21 +453,21 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
litlen = opt[cur-1].litlen + 1;
|
||||
|
||||
if (cur != litlen) {
|
||||
price = opt[cur - litlen].price + LIZ_get_price(ctx, opt[cur-litlen].rep, inr, ctx->off24pos, litlen, 0, 0);
|
||||
LIZ_LOG_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
|
||||
price = opt[cur - litlen].price + Lizard_get_price(ctx, opt[cur-litlen].rep, inr, ctx->off24pos, litlen, 0, 0);
|
||||
LIZARD_LOG_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
|
||||
} else {
|
||||
price = LIZ_get_price(ctx, ctx->last_off, inr, ctx->off24pos, llen + litlen, 0, 0);
|
||||
LIZ_LOG_PRICE("%d: TRY2 price=%d cur=%d litlen=%d llen=%d\n", (int)(inr-source), price, cur, litlen, llen);
|
||||
price = Lizard_get_price(ctx, ctx->last_off, inr, ctx->off24pos, llen + litlen, 0, 0);
|
||||
LIZARD_LOG_PRICE("%d: TRY2 price=%d cur=%d litlen=%d llen=%d\n", (int)(inr-source), price, cur, litlen, llen);
|
||||
}
|
||||
} else {
|
||||
litlen = 1;
|
||||
price = opt[cur - 1].price + LIZ_get_price(ctx, opt[cur-1].rep, inr, ctx->off24pos, litlen, 0, 0);
|
||||
LIZ_LOG_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-source), price, cur, litlen, LIZ_get_price(ctx, rep, inr, ctx->off24pos, litlen, 0, 0));
|
||||
price = opt[cur - 1].price + Lizard_get_price(ctx, opt[cur-1].rep, inr, ctx->off24pos, litlen, 0, 0);
|
||||
LIZARD_LOG_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-source), price, cur, litlen, Lizard_get_price(ctx, rep, inr, ctx->off24pos, litlen, 0, 0));
|
||||
}
|
||||
|
||||
mlen = 1;
|
||||
best_mlen = 0;
|
||||
LIZ_LOG_PARSER("%d: TRY price=%d opt[%d].price=%d\n", (int)(inr-source), price, cur, opt[cur].price);
|
||||
LIZARD_LOG_PARSER("%d: TRY price=%d opt[%d].price=%d\n", (int)(inr-source), price, cur, opt[cur].price);
|
||||
|
||||
if (cur > last_pos || price <= (size_t)opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
|
||||
SET_PRICE(cur, mlen, -1, litlen, price);
|
||||
@@ -483,11 +483,11 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
if (offset < 1) {
|
||||
opt[cur].rep = opt[cur-mlen].rep;
|
||||
opt[cur].off24pos = opt[cur-mlen].off24pos;
|
||||
LIZ_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d\n", (int)(inr-source), cur, mlen, opt[cur-mlen].rep);
|
||||
LIZARD_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d\n", (int)(inr-source), cur, mlen, opt[cur-mlen].rep);
|
||||
} else {
|
||||
opt[cur].rep = (int)offset;
|
||||
opt[cur].off24pos = (offset >= LIZ_MAX_16BIT_OFFSET) ? inr : opt[cur-mlen].off24pos;
|
||||
LIZ_LOG_PARSER("%d: COPYREP2 cur=%d offset=%d rep=%d\n", (int)(inr-source), cur, offset, opt[cur].rep);
|
||||
opt[cur].off24pos = (offset >= LIZARD_MAX_16BIT_OFFSET) ? inr : opt[cur-mlen].off24pos;
|
||||
LIZARD_LOG_PARSER("%d: COPYREP2 cur=%d offset=%d rep=%d\n", (int)(inr-source), cur, offset, opt[cur].rep);
|
||||
}
|
||||
} else {
|
||||
opt[cur].rep = opt[cur-1].rep; // copy rep
|
||||
@@ -495,28 +495,28 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
}
|
||||
|
||||
rep = opt[cur].rep;
|
||||
LIZ_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(inr-source), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep);
|
||||
LIZARD_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(inr-source), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep);
|
||||
|
||||
|
||||
/* check rep code */
|
||||
if (opt[cur].rep >= lz5OptimalMinOffset) {
|
||||
if (opt[cur].rep >= lizardOptimalMinOffset) {
|
||||
intptr_t matchIndexLO = (inr - opt[cur].rep) - base;
|
||||
mlen = 0;
|
||||
if ((matchIndexLO >= lowLimit) && (base + matchIndexLO + maxDistance >= inr)) {
|
||||
if (matchIndexLO >= dictLimit) {
|
||||
mlen = LIZ_count(inr, base + matchIndexLO, matchlimit);
|
||||
mlen = Lizard_count(inr, base + matchIndexLO, matchlimit);
|
||||
} else {
|
||||
mlen = LIZ_count_2segments(inr, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);
|
||||
mlen = Lizard_count_2segments(inr, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);
|
||||
}
|
||||
}
|
||||
if (mlen >= REPMINMATCH/* && mlen > best_mlen*/) {
|
||||
LIZ_LOG_PARSER("%d: try REP rep=%d mlen=%d\n", (int)(inr-source), opt[cur].rep, mlen);
|
||||
LIZ_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-source), mlen, 0, opt[cur].rep, cur, opt[cur].off);
|
||||
LIZARD_LOG_PARSER("%d: try REP rep=%d mlen=%d\n", (int)(inr-source), opt[cur].rep, mlen);
|
||||
LIZARD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-source), mlen, 0, opt[cur].rep, cur, opt[cur].off);
|
||||
|
||||
if (mlen > sufficient_len || cur + mlen >= LIZ_OPT_NUM) {
|
||||
if (mlen > sufficient_len || cur + mlen >= LIZARD_OPT_NUM) {
|
||||
best_mlen = mlen;
|
||||
best_off = 0;
|
||||
LIZ_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-source), sufficient_len, best_mlen, best_off, last_pos);
|
||||
LIZARD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-source), sufficient_len, best_mlen, best_off, last_pos);
|
||||
last_pos = cur + 1;
|
||||
goto encode;
|
||||
}
|
||||
@@ -532,19 +532,19 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
litlen = opt[cur].litlen;
|
||||
|
||||
if (cur != litlen) {
|
||||
price = opt[cur - litlen].price + LIZ_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);
|
||||
LIZ_LOG_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
|
||||
price = opt[cur - litlen].price + Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);
|
||||
LIZARD_LOG_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
|
||||
} else {
|
||||
price = LIZ_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, 0, mlen);
|
||||
LIZ_LOG_PRICE("%d: TRY2 price=%d cur=%d litlen=%d llen=%d\n", (int)(inr-source), price, cur, litlen, llen);
|
||||
price = Lizard_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, 0, mlen);
|
||||
LIZARD_LOG_PRICE("%d: TRY2 price=%d cur=%d litlen=%d llen=%d\n", (int)(inr-source), price, cur, litlen, llen);
|
||||
}
|
||||
} else {
|
||||
litlen = 0;
|
||||
price = opt[cur].price + LIZ_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);
|
||||
LIZ_LOG_PRICE("%d: TRY3 price=%d cur=%d litlen=%d getprice=%d\n", (int)(inr-source), price, cur, litlen, LIZ_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen - MINMATCH));
|
||||
price = opt[cur].price + Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);
|
||||
LIZARD_LOG_PRICE("%d: TRY3 price=%d cur=%d litlen=%d getprice=%d\n", (int)(inr-source), price, cur, litlen, Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen - MINMATCH));
|
||||
}
|
||||
|
||||
LIZ_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-source), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);
|
||||
LIZARD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-source), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);
|
||||
|
||||
if (cur + mlen > last_pos || price <= (size_t)opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH
|
||||
SET_PRICE(cur + mlen, mlen, 0, litlen, price);
|
||||
@@ -559,14 +559,14 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->params.parserType == LIZ_parser_optimalPrice) {
|
||||
LIZ_Insert(ctx, inr);
|
||||
match_num = LIZ_GetAllMatches(ctx, inr, ip, matchlimit, best_mlen, matches);
|
||||
LIZ_LOG_PARSER("%d: LIZ_GetAllMatches match_num=%d\n", (int)(inr-source), match_num);
|
||||
if (ctx->params.parserType == Lizard_parser_optimalPrice) {
|
||||
Lizard_Insert(ctx, inr);
|
||||
match_num = Lizard_GetAllMatches(ctx, inr, ip, matchlimit, best_mlen, matches);
|
||||
LIZARD_LOG_PARSER("%d: Lizard_GetAllMatches match_num=%d\n", (int)(inr-source), match_num);
|
||||
} else {
|
||||
LIZ_BinTree_Insert(ctx, inr);
|
||||
match_num = LIZ_BinTree_GetAllMatches(ctx, inr, matchlimit, best_mlen, matches);
|
||||
LIZ_LOG_PARSER("%d: LIZ_BinTree_GetAllMatches match_num=%d\n", (int)(inr-source), match_num);
|
||||
Lizard_BinTree_Insert(ctx, inr);
|
||||
match_num = Lizard_BinTree_GetAllMatches(ctx, inr, matchlimit, best_mlen, matches);
|
||||
LIZARD_LOG_PARSER("%d: Lizard_BinTree_GetAllMatches match_num=%d\n", (int)(inr-source), match_num);
|
||||
}
|
||||
|
||||
|
||||
@@ -584,8 +584,8 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
for (i = 0; i < match_num; i++) {
|
||||
mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;
|
||||
cur2 = cur - matches[i].back;
|
||||
best_mlen = (cur2 + matches[i].len < LIZ_OPT_NUM) ? (size_t)matches[i].len : LIZ_OPT_NUM - cur2;
|
||||
LIZ_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-source), cur, cur2, matches[i].len, matches[i].off, best_mlen, last_pos);
|
||||
best_mlen = (cur2 + matches[i].len < LIZARD_OPT_NUM) ? (size_t)matches[i].len : LIZARD_OPT_NUM - cur2;
|
||||
LIZARD_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-source), cur, cur2, matches[i].len, matches[i].off, best_mlen, last_pos);
|
||||
|
||||
if (mlen < (size_t)matches[i].back + 1)
|
||||
mlen = matches[i].back + 1;
|
||||
@@ -597,18 +597,18 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
litlen = opt[cur2].litlen;
|
||||
|
||||
if (cur2 != litlen)
|
||||
price = opt[cur2 - litlen].price + LIZ_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);
|
||||
price = opt[cur2 - litlen].price + Lizard_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);
|
||||
else
|
||||
price = LIZ_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, matches[i].off, mlen);
|
||||
price = Lizard_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, matches[i].off, mlen);
|
||||
} else {
|
||||
litlen = 0;
|
||||
price = opt[cur2].price + LIZ_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);
|
||||
price = opt[cur2].price + Lizard_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);
|
||||
}
|
||||
|
||||
LIZ_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-source), matches[i].back, mlen, best_mlen, matches[i].off, price, litlen, cur - litlen, opt[cur - litlen].price);
|
||||
LIZARD_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-source), matches[i].back, mlen, best_mlen, matches[i].off, price, litlen, cur - litlen, opt[cur - litlen].price);
|
||||
// if (cur2 + mlen > last_pos || ((matches[i].off != opt[cur2 + mlen].off) && (price < opt[cur2 + mlen].price)))
|
||||
|
||||
if ((mlen >= minMatchLongOff) || (matches[i].off < LIZ_MAX_16BIT_OFFSET))
|
||||
if ((mlen >= minMatchLongOff) || (matches[i].off < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (cur2 + mlen > last_pos || price < (size_t)opt[cur2 + mlen].price)
|
||||
{
|
||||
SET_PRICE(cur2 + mlen, mlen, matches[i].off, litlen, price);
|
||||
@@ -626,10 +626,10 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
|
||||
encode: // cur, last_pos, best_mlen, best_off have to be set
|
||||
for (i = 1; i <= last_pos; i++) {
|
||||
LIZ_LOG_PARSER("%d: price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep);
|
||||
LIZARD_LOG_PARSER("%d: price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep);
|
||||
}
|
||||
|
||||
LIZ_LOG_PARSER("%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\n", (int)(ip-source+cur), cur, last_pos, best_mlen, best_off, opt[cur].rep);
|
||||
LIZARD_LOG_PARSER("%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\n", (int)(ip-source+cur), cur, last_pos, best_mlen, best_off, opt[cur].rep);
|
||||
|
||||
opt[0].mlen = 1;
|
||||
|
||||
@@ -645,31 +645,31 @@ FORCE_INLINE int LIZ_compress_optimalPrice(
|
||||
}
|
||||
|
||||
for (i = 0; i <= last_pos;) {
|
||||
LIZ_LOG_PARSER("%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep);
|
||||
LIZARD_LOG_PARSER("%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep);
|
||||
i += opt[i].mlen;
|
||||
}
|
||||
|
||||
cur = 0;
|
||||
|
||||
while (cur < last_pos) {
|
||||
LIZ_LOG_PARSER("%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep);
|
||||
LIZARD_LOG_PARSER("%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\n", (int)(ip-source+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep);
|
||||
mlen = opt[cur].mlen;
|
||||
// if (mlen == 1) { ip++; cur++; continue; }
|
||||
if (opt[cur].off == -1) { ip++; cur++; continue; }
|
||||
offset = opt[cur].off;
|
||||
cur += mlen;
|
||||
|
||||
LIZ_LOG_ENCODE("%d: ENCODE literals=%d off=%d mlen=%d ", (int)(ip-source), (int)(ip-anchor), (int)(offset), mlen);
|
||||
res = LIZ_encodeSequence(ctx, &ip, &anchor, mlen, ip - offset);
|
||||
LIZARD_LOG_ENCODE("%d: ENCODE literals=%d off=%d mlen=%d ", (int)(ip-source), (int)(ip-anchor), (int)(offset), mlen);
|
||||
res = Lizard_encodeSequence(ctx, &ip, &anchor, mlen, ip - offset);
|
||||
if (res) return 0;
|
||||
|
||||
LIZ_LOG_PARSER("%d: offset=%d rep=%d\n", (int)(ip-source), offset, ctx->last_off);
|
||||
LIZARD_LOG_PARSER("%d: offset=%d rep=%d\n", (int)(ip-source), offset, ctx->last_off);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals(ctx, &ip, &anchor)) goto _output_error;
|
||||
if (Lizard_encodeLastLiterals(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
@@ -1,6 +1,6 @@
|
||||
#define LIZ_PRICEFAST_MIN_OFFSET 8
|
||||
#define LIZARD_PRICEFAST_MIN_OFFSET 8
|
||||
|
||||
FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intptr_t matchIndex3, /* Index table will be updated */
|
||||
FORCE_INLINE int Lizard_FindMatchFast(Lizard_stream_t* ctx, intptr_t matchIndex, intptr_t matchIndex3, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos)
|
||||
{
|
||||
@@ -16,14 +16,14 @@ FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intpt
|
||||
const BYTE* match, *matchDict;
|
||||
size_t ml=0, mlt;
|
||||
|
||||
if (ctx->last_off >= LIZ_PRICEFAST_MIN_OFFSET) {
|
||||
if (ctx->last_off >= LIZARD_PRICEFAST_MIN_OFFSET) {
|
||||
intptr_t matchIndexLO = (ip - ctx->last_off) - base;
|
||||
if (matchIndexLO >= lowLimit) {
|
||||
if (matchIndexLO >= dictLimit) {
|
||||
match = base + matchIndexLO;
|
||||
if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
|
||||
{
|
||||
*matchpos = match;
|
||||
return (int)mlt;
|
||||
@@ -33,8 +33,8 @@ FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intpt
|
||||
match = dictBase + matchIndexLO;
|
||||
if ((U32)((dictLimit-1) - matchIndexLO) >= 3) /* intentional overflow */
|
||||
if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
// if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
|
||||
{
|
||||
*matchpos = base + matchIndexLO; /* virtual matchpos */
|
||||
return (int)mlt;
|
||||
@@ -48,10 +48,10 @@ FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intpt
|
||||
#if MINMATCH == 3
|
||||
if (matchIndex3 < current && matchIndex3 >= lowLimit) {
|
||||
intptr_t offset = current - matchIndex3;
|
||||
if (offset < LIZ_MAX_8BIT_OFFSET) {
|
||||
if (offset < LIZARD_MAX_8BIT_OFFSET) {
|
||||
match = ip - offset;
|
||||
if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {
|
||||
ml = 3;//LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
ml = 3;//Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
*matchpos = match;
|
||||
}
|
||||
}
|
||||
@@ -62,22 +62,21 @@ FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intpt
|
||||
|
||||
if ((matchIndex < current) && (matchIndex >= lowLimit)) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_PRICEFAST_MIN_OFFSET) {
|
||||
if ((U32)(ip - match) >= LIZARD_PRICEFAST_MIN_OFFSET) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip))) {
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml)) // && LIZ_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml)) // && Lizard_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))
|
||||
{ ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
matchDict = dictBase + matchIndex;
|
||||
// fprintf(stderr, "dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\n", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(matchDict) == MEM_read32(ip)) {
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml)) // && LIZ_better_price((ip - *matchpos), ml, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
if (!ml || (mlt > ml)) // && Lizard_better_price((ip - *matchpos), ml, (U32)(ip - match), mlt, ctx->last_off)))
|
||||
{ ml = mlt; *matchpos = match; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
@@ -88,7 +87,7 @@ FORCE_INLINE int LIZ_FindMatchFast(LIZ_stream_t* ctx, intptr_t matchIndex, intpt
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_FindMatchFaster (LIZ_stream_t* ctx, U32 matchIndex, /* Index table will be updated */
|
||||
FORCE_INLINE int Lizard_FindMatchFaster (Lizard_stream_t* ctx, U32 matchIndex, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos)
|
||||
{
|
||||
@@ -106,19 +105,19 @@ FORCE_INLINE int LIZ_FindMatchFaster (LIZ_stream_t* ctx, U32 matchIndex, /* Ind
|
||||
|
||||
if (matchIndex < current && matchIndex >= lowLimit) {
|
||||
match = base + matchIndex;
|
||||
if ((U32)(ip - match) >= LIZ_PRICEFAST_MIN_OFFSET) {
|
||||
if ((U32)(ip - match) >= LIZARD_PRICEFAST_MIN_OFFSET) {
|
||||
if (matchIndex >= dictLimit) {
|
||||
if (MEM_read32(match) == MEM_read32(ip)) {
|
||||
mlt = LIZ_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
{ ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
matchDict = dictBase + matchIndex;
|
||||
if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
|
||||
if (MEM_read32(matchDict) == MEM_read32(ip)) {
|
||||
mlt = LIZ_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZ_MAX_16BIT_OFFSET))
|
||||
mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
|
||||
if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
|
||||
{ ml = mlt; *matchpos = match; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
@@ -130,8 +129,8 @@ FORCE_INLINE int LIZ_FindMatchFaster (LIZ_stream_t* ctx, U32 matchIndex, /* Ind
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE int LIZ_compress_priceFast(
|
||||
LIZ_stream_t* const ctx,
|
||||
FORCE_INLINE int Lizard_compress_priceFast(
|
||||
Lizard_stream_t* const ctx,
|
||||
const BYTE* ip,
|
||||
const BYTE* const iend)
|
||||
{
|
||||
@@ -158,17 +157,17 @@ FORCE_INLINE int LIZ_compress_priceFast(
|
||||
/* Main Loop */
|
||||
while (ip < mflimit)
|
||||
{
|
||||
HashPos = &HashTable[LIZ_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
#if MINMATCH == 3
|
||||
{
|
||||
U32* HashPos3 = &HashTable3[LIZ_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
ml = LIZ_FindMatchFast (ctx, *HashPos, *HashPos3, ip, matchlimit, (&ref));
|
||||
U32* HashPos3 = &HashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
|
||||
ml = Lizard_FindMatchFast (ctx, *HashPos, *HashPos3, ip, matchlimit, (&ref));
|
||||
*HashPos3 = (U32)(ip - base);
|
||||
}
|
||||
#else
|
||||
ml = LIZ_FindMatchFast (ctx, *HashPos, 0, ip, matchlimit, (&ref));
|
||||
ml = Lizard_FindMatchFast (ctx, *HashPos, 0, ip, matchlimit, (&ref));
|
||||
#endif
|
||||
if ((U32)(ip - base) >= *HashPos + LIZ_PRICEFAST_MIN_OFFSET)
|
||||
if ((*HashPos >= (U32)(ip - base)) || ((U32)(ip - base) >= *HashPos + LIZARD_PRICEFAST_MIN_OFFSET))
|
||||
*HashPos = (U32)(ip - base);
|
||||
|
||||
if (!ml) { ip++; continue; }
|
||||
@@ -186,9 +185,9 @@ _Search:
|
||||
if (ip+ml >= mflimit) goto _Encode;
|
||||
|
||||
start2 = ip + ml - 2;
|
||||
HashPos = &HashTable[LIZ_hashPtr(start2, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
ml2 = LIZ_FindMatchFaster(ctx, *HashPos, start2, matchlimit, (&ref2));
|
||||
if ((U32)(start2 - base) >= *HashPos + LIZ_PRICEFAST_MIN_OFFSET)
|
||||
HashPos = &HashTable[Lizard_hashPtr(start2, ctx->params.hashLog, ctx->params.searchLength)];
|
||||
ml2 = Lizard_FindMatchFaster(ctx, *HashPos, start2, matchlimit, (&ref2));
|
||||
if ((*HashPos >= (U32)(start2 - base)) || ((U32)(start2 - base) >= *HashPos + LIZARD_PRICEFAST_MIN_OFFSET))
|
||||
*HashPos = (U32)(start2 - base);
|
||||
|
||||
if (!ml2) goto _Encode;
|
||||
@@ -201,8 +200,6 @@ _Search:
|
||||
ref2 += back;
|
||||
}
|
||||
|
||||
// LIZ_DEBUG("%u: TRY last_off=%d literals=%u off=%u mlen=%u literals2=%u off2=%u mlen2=%u best=%d\n", (U32)(ip - ctx->inputBuffer), ctx->last_off, (U32)(ip - anchor), off0, (U32)ml, (U32)(start2 - anchor), off1, ml2, (U32)(best_pos - ip));
|
||||
|
||||
if (ml2 <= ml) { ml2 = 0; goto _Encode; }
|
||||
|
||||
if (start2 <= ip)
|
||||
@@ -227,11 +224,11 @@ _Search:
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
if (ml2 < 3) { ml2 = 0; }
|
||||
if ((ml2 < minMatchLongOff) && ((U32)(start2 - ref2) >= LIZ_MAX_16BIT_OFFSET)) { ml2 = 0; }
|
||||
if ((ml2 < minMatchLongOff) && ((U32)(start2 - ref2) >= LIZARD_MAX_16BIT_OFFSET)) { ml2 = 0; }
|
||||
}
|
||||
|
||||
_Encode:
|
||||
if (LIZ_encodeSequence_LZ5v2(ctx, &ip, &anchor, ml, ref)) goto _output_error;
|
||||
if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, ml, ref)) goto _output_error;
|
||||
|
||||
if (ml2)
|
||||
{
|
||||
@@ -243,7 +240,7 @@ _Encode:
|
||||
|
||||
/* Encode Last Literals */
|
||||
ip = iend;
|
||||
if (LIZ_encodeLastLiterals_LZ5v2(ctx, &ip, &anchor)) goto _output_error;
|
||||
if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;
|
||||
|
||||
/* End */
|
||||
return 1;
|
||||
394
C/lizard/mem.h
394
C/lizard/mem.h
@@ -1,394 +0,0 @@
|
||||
/* ******************************************************************
|
||||
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
|
||||
****************************************************************** */
|
||||
#ifndef MEM_H_MODULE
|
||||
#define MEM_H_MODULE
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-****************************************
|
||||
* Dependencies
|
||||
******************************************/
|
||||
#include <stddef.h> /* size_t, ptrdiff_t */
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Compiler specifics
|
||||
******************************************/
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# include <stdlib.h> /* _byteswap_ulong */
|
||||
# include <intrin.h> /* _byteswap_* */
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
# define MEM_STATIC static __inline __attribute__((unused))
|
||||
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define MEM_STATIC static inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define MEM_STATIC static __inline
|
||||
#else
|
||||
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
#endif
|
||||
|
||||
/* code only tested on 32 and 64 bits systems */
|
||||
#define MEM_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; }
|
||||
MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* Basic Types
|
||||
*****************************************************************/
|
||||
#if !defined (__VMS) && (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
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* 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 depending on alignment.
|
||||
* 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(_MSC_VER)*/ || \
|
||||
(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(size_t)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==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, by lying 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 U64 MEM_readST(const void* memPtr) { return *(const size_t*) 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 */
|
||||
#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
|
||||
__pragma( pack(push, 1) )
|
||||
typedef union { U16 u16; U32 u32; U64 u64; size_t st; } unalign;
|
||||
__pragma( pack(pop) )
|
||||
#else
|
||||
typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
|
||||
#endif
|
||||
|
||||
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 U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
|
||||
|
||||
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 size_t MEM_readST(const void* memPtr)
|
||||
{
|
||||
size_t 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 U32 MEM_swap32(U32 in)
|
||||
{
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
return _byteswap_ulong(in);
|
||||
#elif defined (__GNUC__)
|
||||
return __builtin_bswap32(in);
|
||||
#else
|
||||
return ((in << 24) & 0xff000000 ) |
|
||||
((in << 8) & 0x00ff0000 ) |
|
||||
((in >> 8) & 0x0000ff00 ) |
|
||||
((in >> 24) & 0x000000ff );
|
||||
#endif
|
||||
}
|
||||
|
||||
MEM_STATIC U64 MEM_swap64(U64 in)
|
||||
{
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
return _byteswap_uint64(in);
|
||||
#elif defined (__GNUC__)
|
||||
return __builtin_bswap64(in);
|
||||
#else
|
||||
return ((in << 56) & 0xff00000000000000ULL) |
|
||||
((in << 40) & 0x00ff000000000000ULL) |
|
||||
((in << 24) & 0x0000ff0000000000ULL) |
|
||||
((in << 8) & 0x000000ff00000000ULL) |
|
||||
((in >> 8) & 0x00000000ff000000ULL) |
|
||||
((in >> 24) & 0x0000000000ff0000ULL) |
|
||||
((in >> 40) & 0x000000000000ff00ULL) |
|
||||
((in >> 56) & 0x00000000000000ffULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
MEM_STATIC size_t MEM_swapST(size_t in)
|
||||
{
|
||||
if (MEM_32bits())
|
||||
return (size_t)MEM_swap32((U32)in);
|
||||
else
|
||||
return (size_t)MEM_swap64((U64)in);
|
||||
}
|
||||
|
||||
/*=== Little endian r/w ===*/
|
||||
|
||||
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)
|
||||
{
|
||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
|
||||
{
|
||||
MEM_writeLE16(memPtr, (U16)val);
|
||||
((BYTE*)memPtr)[2] = (BYTE)(val>>16);
|
||||
}
|
||||
|
||||
MEM_STATIC U32 MEM_readLE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_read32(memPtr);
|
||||
else
|
||||
return MEM_swap32(MEM_read32(memPtr));
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
MEM_write32(memPtr, val32);
|
||||
else
|
||||
MEM_write32(memPtr, MEM_swap32(val32));
|
||||
}
|
||||
|
||||
MEM_STATIC U64 MEM_readLE64(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_read64(memPtr);
|
||||
else
|
||||
return MEM_swap64(MEM_read64(memPtr));
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
MEM_write64(memPtr, val64);
|
||||
else
|
||||
MEM_write64(memPtr, MEM_swap64(val64));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*=== Big endian r/w ===*/
|
||||
|
||||
MEM_STATIC U32 MEM_readBE32(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_swap32(MEM_read32(memPtr));
|
||||
else
|
||||
return MEM_read32(memPtr);
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
MEM_write32(memPtr, MEM_swap32(val32));
|
||||
else
|
||||
MEM_write32(memPtr, val32);
|
||||
}
|
||||
|
||||
MEM_STATIC U64 MEM_readBE64(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
return MEM_swap64(MEM_read64(memPtr));
|
||||
else
|
||||
return MEM_read64(memPtr);
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
MEM_write64(memPtr, MEM_swap64(val64));
|
||||
else
|
||||
MEM_write64(memPtr, val64);
|
||||
}
|
||||
|
||||
MEM_STATIC size_t MEM_readBEST(const void* memPtr)
|
||||
{
|
||||
if (MEM_32bits())
|
||||
return (size_t)MEM_readBE32(memPtr);
|
||||
else
|
||||
return (size_t)MEM_readBE64(memPtr);
|
||||
}
|
||||
|
||||
MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
|
||||
{
|
||||
if (MEM_32bits())
|
||||
MEM_writeBE32(memPtr, (U32)val);
|
||||
else
|
||||
MEM_writeBE64(memPtr, (U64)val);
|
||||
}
|
||||
|
||||
|
||||
/* function safe only for comparisons */
|
||||
MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
default :
|
||||
case 4 : return MEM_read32(memPtr);
|
||||
case 3 : if (MEM_isLittleEndian())
|
||||
return MEM_read32(memPtr)<<8;
|
||||
else
|
||||
return MEM_read32(memPtr)>>8;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEM_H_MODULE */
|
||||
@@ -9,7 +9,7 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "lizframe.h"
|
||||
#include "lizard_frame.h"
|
||||
#include "lizard-mt.h"
|
||||
|
||||
/* will be used for lib errors */
|
||||
@@ -32,8 +32,8 @@ unsigned LIZARDMT_isError(size_t code)
|
||||
*/
|
||||
const char *LIZARDMT_getErrorString(size_t code)
|
||||
{
|
||||
if (LIZF_isError(lizardmt_errcode))
|
||||
return LIZF_getErrorName(lizardmt_errcode);
|
||||
if (LizardF_isError(lizardmt_errcode))
|
||||
return LizardF_getErrorName(lizardmt_errcode);
|
||||
|
||||
static const char *noErrorCode = "Unspecified lizardmt error code";
|
||||
switch ((LIZARDMT_ErrorCode) (0 - code)) {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LIZF_DISABLE_OBSOLETE_ENUMS
|
||||
#include "lizframe.h"
|
||||
#define LizardF_DISABLE_OBSOLETE_ENUMS
|
||||
#include "lizard_frame.h"
|
||||
|
||||
#include "memmt.h"
|
||||
#include "threading.h"
|
||||
@@ -38,7 +38,7 @@
|
||||
/* worker for compression */
|
||||
typedef struct {
|
||||
LIZARDMT_CCtx *ctx;
|
||||
LIZF_preferences_t zpref;
|
||||
LizardF_preferences_t zpref;
|
||||
pthread_t pthread;
|
||||
} cwork_t;
|
||||
|
||||
@@ -138,12 +138,12 @@ LIZARDMT_CCtx *LIZARDMT_createCCtx(int threads, int level, int inputsize)
|
||||
w->ctx = ctx;
|
||||
|
||||
/* setup preferences for that thread */
|
||||
memset(&w->zpref, 0, sizeof(LIZF_preferences_t));
|
||||
memset(&w->zpref, 0, sizeof(LizardF_preferences_t));
|
||||
w->zpref.compressionLevel = level;
|
||||
w->zpref.frameInfo.blockMode = LIZF_blockLinked;
|
||||
w->zpref.frameInfo.blockMode = LizardF_blockLinked;
|
||||
w->zpref.frameInfo.contentSize = 1;
|
||||
w->zpref.frameInfo.contentChecksumFlag =
|
||||
LIZF_contentChecksumEnabled;
|
||||
LizardF_contentChecksumEnabled;
|
||||
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ static void *pt_compress(void *arg)
|
||||
entry = list_first(&ctx->writelist_free);
|
||||
wl = list_entry(entry, struct writelist, node);
|
||||
wl->out.size =
|
||||
LIZF_compressFrameBound(ctx->inputsize,
|
||||
LizardF_compressFrameBound(ctx->inputsize,
|
||||
&w->zpref) + 12;
|
||||
list_move(entry, &ctx->writelist_busy);
|
||||
} else {
|
||||
@@ -241,7 +241,7 @@ static void *pt_compress(void *arg)
|
||||
return (void *)ERROR(memory_allocation);
|
||||
}
|
||||
wl->out.size =
|
||||
LIZF_compressFrameBound(ctx->inputsize,
|
||||
LizardF_compressFrameBound(ctx->inputsize,
|
||||
&w->zpref) + 12;;
|
||||
wl->out.buf = malloc(wl->out.size);
|
||||
if (!wl->out.buf) {
|
||||
@@ -278,10 +278,10 @@ static void *pt_compress(void *arg)
|
||||
|
||||
/* compress whole frame */
|
||||
result =
|
||||
LIZF_compressFrame((unsigned char *)wl->out.buf + 12,
|
||||
LizardF_compressFrame((unsigned char *)wl->out.buf + 12,
|
||||
wl->out.size - 12, in.buf, in.size,
|
||||
&w->zpref);
|
||||
if (LIZF_isError(result)) {
|
||||
if (LizardF_isError(result)) {
|
||||
pthread_mutex_lock(&ctx->write_mutex);
|
||||
list_move(&wl->node, &ctx->writelist_free);
|
||||
pthread_mutex_unlock(&ctx->write_mutex);
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LIZF_DISABLE_OBSOLETE_ENUMS
|
||||
#include "lizframe.h"
|
||||
#define LizardF_DISABLE_OBSOLETE_ENUMS
|
||||
#include "lizard_frame.h"
|
||||
|
||||
#include "memmt.h"
|
||||
#include "threading.h"
|
||||
@@ -40,7 +40,7 @@ typedef struct {
|
||||
LIZARDMT_DCtx *ctx;
|
||||
pthread_t pthread;
|
||||
LIZARDMT_Buffer in;
|
||||
LIZF_decompressionContext_t dctx;
|
||||
LizardF_decompressionContext_t dctx;
|
||||
} cwork_t;
|
||||
|
||||
struct writelist;
|
||||
@@ -130,7 +130,7 @@ LIZARDMT_DCtx *LIZARDMT_createDCtx(int threads, int inputsize)
|
||||
w->ctx = ctx;
|
||||
|
||||
/* setup thread work */
|
||||
LIZF_createDecompressionContext(&w->dctx, LIZF_VERSION);
|
||||
LizardF_createDecompressionContext(&w->dctx, LIZARDF_VERSION);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
@@ -348,10 +348,10 @@ static void *pt_decompress(void *arg)
|
||||
}
|
||||
|
||||
result =
|
||||
LIZF_decompress(w->dctx, out->buf, &out->size,
|
||||
LizardF_decompress(w->dctx, out->buf, &out->size,
|
||||
in->buf, &in->size, 0);
|
||||
|
||||
if (LIZF_isError(result)) {
|
||||
if (LizardF_isError(result)) {
|
||||
lizardmt_errcode = result;
|
||||
result = ERROR(compression_library);
|
||||
goto error_lock;
|
||||
@@ -392,7 +392,7 @@ static void *pt_decompress(void *arg)
|
||||
static size_t st_decompress(void *arg)
|
||||
{
|
||||
LIZARDMT_DCtx *ctx = (LIZARDMT_DCtx *) arg;
|
||||
LIZF_errorCode_t nextToLoad = 0;
|
||||
LizardF_errorCode_t nextToLoad = 0;
|
||||
cwork_t *w = &ctx->cwork[0];
|
||||
LIZARDMT_Buffer Out;
|
||||
LIZARDMT_Buffer *out = &Out;
|
||||
@@ -420,8 +420,8 @@ static size_t st_decompress(void *arg)
|
||||
memcpy(in->buf, magic, in->size);
|
||||
|
||||
nextToLoad =
|
||||
LIZF_decompress(w->dctx, out->buf, &pos, in->buf, &in->size, 0);
|
||||
if (LIZF_isError(nextToLoad)) {
|
||||
LizardF_decompress(w->dctx, out->buf, &pos, in->buf, &in->size, 0);
|
||||
if (LizardF_isError(nextToLoad)) {
|
||||
free(in->buf);
|
||||
free(out->buf);
|
||||
return ERROR(compression_library);
|
||||
@@ -451,10 +451,10 @@ static size_t st_decompress(void *arg)
|
||||
|
||||
/* decompress */
|
||||
nextToLoad =
|
||||
LIZF_decompress(w->dctx, out->buf, &out->size,
|
||||
LizardF_decompress(w->dctx, out->buf, &out->size,
|
||||
(unsigned char *)in->buf + pos,
|
||||
&remaining, NULL);
|
||||
if (LIZF_isError(nextToLoad)) {
|
||||
if (LizardF_isError(nextToLoad)) {
|
||||
free(in->buf);
|
||||
free(out->buf);
|
||||
return ERROR(compression_library);
|
||||
@@ -603,7 +603,7 @@ void LIZARDMT_freeDCtx(LIZARDMT_DCtx * ctx)
|
||||
|
||||
for (t = 0; t < ctx->threads; t++) {
|
||||
cwork_t *w = &ctx->cwork[t];
|
||||
LIZF_freeDecompressionContext(w->dctx);
|
||||
LizardF_freeDecompressionContext(w->dctx);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&ctx->read_mutex);
|
||||
|
||||
BIN
CPP/7zip/Archive/Icons/liz.ico
Normal file
BIN
CPP/7zip/Archive/Icons/liz.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
366
CPP/7zip/Archive/LizardHandler.cpp
Normal file
366
CPP/7zip/Archive/LizardHandler.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
// LizardHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/LizardDecoder.h"
|
||||
#include "../Compress/LizardEncoder.h"
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "Common/DummyOutStream.h"
|
||||
#include "Common/HandlerOut.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NLIZARD {
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveOpenSeq,
|
||||
public IOutArchive,
|
||||
public ISetProperties,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
|
||||
bool _isArc;
|
||||
bool _dataAfterEnd;
|
||||
bool _needMoreInput;
|
||||
|
||||
bool _packSize_Defined;
|
||||
bool _unpackSize_Defined;
|
||||
|
||||
UInt64 _packSize;
|
||||
UInt64 _unpackSize;
|
||||
UInt64 _numStreams;
|
||||
UInt64 _numBlocks;
|
||||
|
||||
CSingleMethodProps _props;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP4(
|
||||
IInArchive,
|
||||
IArchiveOpenSeq,
|
||||
IOutArchive,
|
||||
ISetProperties)
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
CHandler() { }
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidPackSize
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidNumStreams,
|
||||
kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
|
||||
case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const unsigned kSignatureCheckSize = 4;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_lizard(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < 4)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
|
||||
UInt32 magic = GetUi32(p);
|
||||
|
||||
// skippable frames
|
||||
if (magic >= 0x184D2A50 && magic <= 0x184D2A5F) {
|
||||
if (size < 16)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
magic = GetUi32(p+12);
|
||||
}
|
||||
|
||||
// Lizard Magic
|
||||
if (magic == 0x184D2206)
|
||||
return k_IsArc_Res_YES;
|
||||
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
{
|
||||
Byte buf[kSignatureCheckSize];
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));
|
||||
if (IsArc_lizard(buf, kSignatureCheckSize) == k_IsArc_Res_NO)
|
||||
return S_FALSE;
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
_seqStream = stream;
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
{
|
||||
Close();
|
||||
_isArc = true;
|
||||
_seqStream = stream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_isArc = false;
|
||||
_dataAfterEnd = false;
|
||||
_needMoreInput = false;
|
||||
|
||||
_packSize_Defined = false;
|
||||
_unpackSize_Defined = false;
|
||||
|
||||
_packSize = 0;
|
||||
|
||||
_seqStream.Release();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_packSize_Defined)
|
||||
extractCallback->SetTotal(_packSize);
|
||||
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
|
||||
if (!testMode && !realOutStream)
|
||||
return S_OK;
|
||||
|
||||
extractCallback->PrepareOperation(askMode);
|
||||
|
||||
Int32 opRes;
|
||||
|
||||
{
|
||||
|
||||
NCompress::NLIZARD::CDecoder *decoderSpec = new NCompress::NLIZARD::CDecoder;
|
||||
CMyComPtr<ICompressCoder> decoder = decoderSpec;
|
||||
decoderSpec->SetInStream(_seqStream);
|
||||
|
||||
CDummyOutStream *outStreamSpec = new CDummyOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init();
|
||||
|
||||
realOutStream.Release();
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, true);
|
||||
|
||||
UInt64 packSize = 0;
|
||||
UInt64 unpackedSize = 0;
|
||||
|
||||
HRESULT result = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
lps->InSize = packSize;
|
||||
lps->OutSize = unpackedSize;
|
||||
|
||||
RINOK(lps->SetCur());
|
||||
result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);
|
||||
UInt64 streamSize = decoderSpec->GetInputProcessedSize();
|
||||
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
|
||||
if (unpackedSize == 0)
|
||||
break;
|
||||
|
||||
if (streamSize == packSize)
|
||||
{
|
||||
// no new bytes in input stream, So it's good end of archive.
|
||||
result = S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (packSize > streamSize)
|
||||
return E_FAIL;
|
||||
|
||||
if (result != S_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
decoderSpec->ReleaseInStream();
|
||||
outStream.Release();
|
||||
|
||||
if (!_isArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (_needMoreInput)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (_dataAfterEnd)
|
||||
opRes = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (result == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (result == S_OK)
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
else
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static HRESULT UpdateArchive(
|
||||
UInt64 unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
const CProps &props,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
RINOK(updateCallback->SetTotal(unpackSize));
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
RINOK(updateCallback->GetStream(0, &fileInStream));
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
localProgressSpec->Init(updateCallback, true);
|
||||
NCompress::NLIZARD::CEncoder *encoderSpec = new NCompress::NLIZARD::CEncoder;
|
||||
CMyComPtr<ICompressCoder> encoder = encoderSpec;
|
||||
RINOK(props.SetCoderProps(encoderSpec, NULL));
|
||||
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
|
||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
{
|
||||
*type = NFileTimeType::kUnix;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
Int32 newData, newProps;
|
||||
UInt32 indexInArchive;
|
||||
if (!updateCallback)
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
|
||||
|
||||
if ((newProps))
|
||||
{
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
|
||||
if (prop.vt != VT_EMPTY)
|
||||
if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
if ((newData))
|
||||
{
|
||||
UInt64 size;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
}
|
||||
return UpdateArchive(size, outStream, _props, updateCallback);
|
||||
}
|
||||
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
|
||||
if (opCallback)
|
||||
{
|
||||
RINOK(opCallback->ReportOperation(
|
||||
NEventIndexType::kInArcIndex, 0,
|
||||
NUpdateNotifyOp::kReplicate))
|
||||
}
|
||||
|
||||
if (_stream)
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, progress);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = "0x184D2206";
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"liz", "liz tliz", "* .tar", 0x11,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
IsArc_lizard)
|
||||
|
||||
}}
|
||||
@@ -1,4 +1,4 @@
|
||||
// ZstdHandler.cpp
|
||||
// Lz4Handler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ZstdHandler.cpp
|
||||
// Lz5Handler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
|
||||
@@ -260,14 +260,9 @@ BROTLI_OBJS = \
|
||||
$O/br_utf8_util.obj \
|
||||
|
||||
LIZARD_OBJS = \
|
||||
$O/liz_entropy_common.obj \
|
||||
$O/liz_fse_compress.obj \
|
||||
$O/liz_fse_decompress.obj \
|
||||
$O/liz_huf_compress.obj \
|
||||
$O/liz_huf_decompress.obj \
|
||||
$O/liz_lz5_compress.obj \
|
||||
$O/liz_lz5_decompress.obj \
|
||||
$O/liz_lz5frame.obj \
|
||||
$O/lizard_compress.obj \
|
||||
$O/lizard_decompress.obj \
|
||||
$O/lizard_frame.obj \
|
||||
|
||||
LZ4_OBJS = \
|
||||
$O\lz4.obj \
|
||||
|
||||
@@ -22,17 +22,18 @@ COMPRESS_OBJS = $(COMPRESS_OBJS) \
|
||||
$O\LizardRegister.obj \
|
||||
|
||||
LIZARD_OBJS = \
|
||||
$O/liz_entropy_common.obj \
|
||||
$O/liz_fse_compress.obj \
|
||||
$O/liz_fse_decompress.obj \
|
||||
$O/liz_huf_compress.obj \
|
||||
$O/liz_huf_decompress.obj \
|
||||
$O/liz_lz5_compress.obj \
|
||||
$O/liz_lz5_decompress.obj \
|
||||
$O/liz_lz5frame.obj \
|
||||
$O/lizard_compress.obj \
|
||||
$O/lizard_decompress.obj \
|
||||
$O/lizard_frame.obj \
|
||||
|
||||
ZSTD_OBJS = \
|
||||
$O\xxhash.obj \
|
||||
$O\entropy_common.obj \
|
||||
$O\fse_decompress.obj \
|
||||
$O\fse_compress.obj \
|
||||
$O\huf_compress.obj \
|
||||
$O\huf_decompress.obj \
|
||||
$O\error_private.obj \
|
||||
|
||||
ZSTDMT_OBJS = \
|
||||
$O\threading.obj \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "../../../../C/7zVersionTr.h"
|
||||
#include "../../../../C/7zVersion.rc"
|
||||
|
||||
MY_VERSION_INFO_DLL("7-Zip Lizard Plugin v2.0", "Lizard")
|
||||
MY_VERSION_INFO_DLL("7-Zip Lizard Plugin v1.0", "Lizard")
|
||||
|
||||
101 ICON "../../Archive/Icons/7z.ico"
|
||||
101 ICON "../../Archive/Icons/liz.ico"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
MY_VERSION_INFO_DLL("7-Zip LZ4 Plugin v1.7.5", "Lz4")
|
||||
|
||||
101 ICON "../../Archive/Icons/7z.ico"
|
||||
101 ICON "../../Archive/Icons/lz5.ico"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
MY_VERSION_INFO_DLL("7-Zip LZ5 Plugin v1.5", "Lz5")
|
||||
|
||||
101 ICON "../../Archive/Icons/7z.ico"
|
||||
101 ICON "../../Archive/Icons/lz5.ico"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
MY_VERSION_INFO_DLL("7-Zip ZStandard Plugin v1.2.0", "zstd")
|
||||
|
||||
101 ICON "../../Archive/Icons/7z.ico"
|
||||
101 ICON "../../Archive/Icons/zstd.ico"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
MY_VERSION_INFO_DLL("7-Zip ZStandard Plugin v1.2.0", "zstd")
|
||||
|
||||
101 ICON "../../Archive/Icons/7z.ico"
|
||||
101 ICON "../../Archive/Icons/zstd.ico"
|
||||
|
||||
@@ -178,14 +178,9 @@ BROTLI_OBJS = \
|
||||
$O/br_utf8_util.obj \
|
||||
|
||||
LIZARD_OBJS = \
|
||||
$O/liz_entropy_common.obj \
|
||||
$O/liz_fse_compress.obj \
|
||||
$O/liz_fse_decompress.obj \
|
||||
$O/liz_huf_compress.obj \
|
||||
$O/liz_huf_decompress.obj \
|
||||
$O/liz_lz5_compress.obj \
|
||||
$O/liz_lz5_decompress.obj \
|
||||
$O/liz_lz5frame.obj \
|
||||
$O/lizard_compress.obj \
|
||||
$O/lizard_decompress.obj \
|
||||
$O/lizard_frame.obj \
|
||||
|
||||
LZ4_OBJS = \
|
||||
$O\lz4.obj \
|
||||
|
||||
@@ -73,6 +73,7 @@ AR_OBJS = \
|
||||
$O\LzHandler.obj \
|
||||
$O\Lz4Handler.obj \
|
||||
$O\Lz5Handler.obj \
|
||||
$O\LizardHandler.obj \
|
||||
$O\LzhHandler.obj \
|
||||
$O\LzmaHandler.obj \
|
||||
$O\MachoHandler.obj \
|
||||
|
||||
@@ -58,14 +58,9 @@ BROTLI_OBJS = \
|
||||
$O/br_utf8_util.obj \
|
||||
|
||||
LIZARD_OBJS = \
|
||||
$O/liz_entropy_common.obj \
|
||||
$O/liz_fse_compress.obj \
|
||||
$O/liz_fse_decompress.obj \
|
||||
$O/liz_huf_compress.obj \
|
||||
$O/liz_huf_decompress.obj \
|
||||
$O/liz_lz5_compress.obj \
|
||||
$O/liz_lz5_decompress.obj \
|
||||
$O/liz_lz5frame.obj \
|
||||
$O/lizard_compress.obj \
|
||||
$O/lizard_decompress.obj \
|
||||
$O/lizard_frame.obj \
|
||||
|
||||
LZ4_OBJS = \
|
||||
$O\lz4.obj \
|
||||
|
||||
@@ -31,9 +31,10 @@ MY_VERSION_INFO_DLL("7z Plugin" , "7z")
|
||||
25 ICON "../../Archive/Icons/zst.ico"
|
||||
26 ICON "../../Archive/Icons/lz4.ico"
|
||||
27 ICON "../../Archive/Icons/lz5.ico"
|
||||
28 ICON "../../Archive/Icons/liz.ico"
|
||||
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lz:16 tlz:16 lz4:26 lz5:27 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24 zst:25"
|
||||
100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lz:16 tlz:16 liz:28 lz4:26 lz5:27 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24 zst:25"
|
||||
END
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
#define LIZARD_STATIC_LINKING_ONLY
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/Threads.h"
|
||||
#include "../../../C/lizard/liz_compress.h"
|
||||
#include "../../../C/lizard/lizframe.h"
|
||||
#include "../../../C/lizard/lizard_compress.h"
|
||||
#include "../../../C/lizard/lizard_decompress.h"
|
||||
#include "../../../C/lizard/lizard_frame.h"
|
||||
#include "../../../C/zstdmt/lizard-mt.h"
|
||||
|
||||
#include "../../Windows/System.h"
|
||||
@@ -37,8 +38,8 @@ struct DProps
|
||||
void clear ()
|
||||
{
|
||||
memset(this, 0, sizeof (*this));
|
||||
_ver_major = LIZ_VERSION_MAJOR;
|
||||
_ver_minor = LIZ_VERSION_MINOR;
|
||||
_ver_major = LIZARD_VERSION_MAJOR;
|
||||
_ver_minor = LIZARD_VERSION_MINOR;
|
||||
_level = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#define LIZARD_STATIC_LINKING_ONLY
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/Threads.h"
|
||||
#include "../../../C/lizard/liz_compress.h"
|
||||
#include "../../../C/lizard/lizframe.h"
|
||||
#include "../../../C/lizard/lizard_compress.h"
|
||||
#include "../../../C/lizard/lizard_frame.h"
|
||||
#include "../../../C/zstdmt/lizard-mt.h"
|
||||
|
||||
#include "../../Common/Common.h"
|
||||
@@ -22,8 +22,8 @@ struct CProps
|
||||
void clear ()
|
||||
{
|
||||
memset(this, 0, sizeof (*this));
|
||||
_ver_major = LIZ_VERSION_MAJOR;
|
||||
_ver_minor = LIZ_VERSION_MINOR;
|
||||
_ver_major = LIZARD_VERSION_MAJOR;
|
||||
_ver_minor = LIZARD_VERSION_MINOR;
|
||||
_level = 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ Handler GUIDs:
|
||||
0E zstd
|
||||
0F lz4
|
||||
10 lz5
|
||||
11 liz
|
||||
|
||||
C6 Lzip
|
||||
C7 Ext
|
||||
|
||||
@@ -99,9 +99,12 @@ enum EMethodID
|
||||
kCopy,
|
||||
kZSTD,
|
||||
kBROTLI,
|
||||
kLIZARD,
|
||||
kLZ4,
|
||||
kLZ5,
|
||||
kLIZARD_M1,
|
||||
kLIZARD_M2,
|
||||
kLIZARD_M3,
|
||||
kLIZARD_M4,
|
||||
kLZMA,
|
||||
kLZMA2,
|
||||
kPPMd,
|
||||
@@ -111,14 +114,37 @@ enum EMethodID
|
||||
kPPMdZip
|
||||
};
|
||||
|
||||
static LPCSTR const kMethodsLongnames[] =
|
||||
{
|
||||
"Copy"
|
||||
, "ZStandard"
|
||||
, "Brotli"
|
||||
, "LZ4"
|
||||
, "LZ5"
|
||||
, "Lizard, FastLZ4"
|
||||
, "Lizard, LIZv1"
|
||||
, "Lizard, FastLZ4 + Huffman"
|
||||
, "Lizard, LIZv1 + Huffman"
|
||||
, "LZMA"
|
||||
, "LZMA2"
|
||||
, "PPMd"
|
||||
, "BZip2"
|
||||
, "Deflate"
|
||||
, "Deflate64"
|
||||
, "PPMd"
|
||||
};
|
||||
|
||||
static LPCSTR const kMethodsNames[] =
|
||||
{
|
||||
"Copy"
|
||||
, "ZSTD"
|
||||
, "BROTLI"
|
||||
, "LIZARD"
|
||||
, "zstd"
|
||||
, "Brotli"
|
||||
, "LZ4"
|
||||
, "LZ5"
|
||||
, "Lizard"
|
||||
, "Lizard"
|
||||
, "Lizard"
|
||||
, "Lizard"
|
||||
, "LZMA"
|
||||
, "LZMA2"
|
||||
, "PPMd"
|
||||
@@ -140,7 +166,10 @@ static const EMethodID g_BrotliMethods[] =
|
||||
|
||||
static const EMethodID g_LizardMethods[] =
|
||||
{
|
||||
kLIZARD
|
||||
kLIZARD_M1,
|
||||
kLIZARD_M2,
|
||||
kLIZARD_M3,
|
||||
kLIZARD_M4
|
||||
};
|
||||
|
||||
static const EMethodID g_Lz4Methods[] =
|
||||
@@ -157,9 +186,12 @@ static const EMethodID g_7zMethods[] =
|
||||
{
|
||||
kZSTD,
|
||||
kBROTLI,
|
||||
kLIZARD,
|
||||
kLZ4,
|
||||
kLZ5,
|
||||
kLIZARD_M1,
|
||||
kLIZARD_M2,
|
||||
kLIZARD_M3,
|
||||
kLIZARD_M4,
|
||||
kLZMA2,
|
||||
kLZMA,
|
||||
kPPMd,
|
||||
@@ -269,25 +301,25 @@ static const CFormatInfo g_Formats[] =
|
||||
false, false, true, false, false, false
|
||||
},
|
||||
{
|
||||
"Brotli",
|
||||
"Brotli", /* 7 */
|
||||
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 6) | (1 << 9) | (1 << 11),
|
||||
METHODS_PAIR(g_BrotliMethods),
|
||||
false, false, true, false, false, false
|
||||
},
|
||||
{
|
||||
"Lizard", /* 10..19 / 20..29 / .... */
|
||||
"Lizard", /* 8 */
|
||||
(1 << 10) | (1 << 11) | (1 << 13) | (1 << 15) | (1 << 17) | (1 << 19),
|
||||
METHODS_PAIR(g_LizardMethods),
|
||||
false, false, true, false, false, false
|
||||
},
|
||||
{
|
||||
"LZ4",
|
||||
"LZ4", /* 9 */
|
||||
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 6) | (1 << 9) | (1 << 12),
|
||||
METHODS_PAIR(g_Lz4Methods),
|
||||
false, false, true, false, false, false
|
||||
},
|
||||
{
|
||||
"LZ5",
|
||||
"LZ5", /* 10 */
|
||||
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 7) | (1 << 11) | (1 << 15),
|
||||
METHODS_PAIR(g_Lz5Methods),
|
||||
false, false, true, false, false, false
|
||||
@@ -1082,6 +1114,7 @@ void CCompressDialog::SetLevel()
|
||||
UInt32 level = GetLevel2();
|
||||
UInt32 LevelsMask;
|
||||
UInt32 LevelsStart = 0;
|
||||
UInt32 LevelsEnd = 22;
|
||||
UInt32 langID = 0;
|
||||
unsigned i, ir;
|
||||
|
||||
@@ -1104,9 +1137,22 @@ void CCompressDialog::SetLevel()
|
||||
LevelsMask = g_Formats[6].LevelsMask;
|
||||
else if (GetMethodID() == kBROTLI)
|
||||
LevelsMask = g_Formats[7].LevelsMask;
|
||||
else if (GetMethodID() == kLIZARD) {
|
||||
else if (GetMethodID() == kLIZARD_M1) {
|
||||
LevelsMask = g_Formats[8].LevelsMask;
|
||||
LevelsStart = 10;
|
||||
LevelsEnd = 19;
|
||||
} else if (GetMethodID() == kLIZARD_M2) {
|
||||
LevelsMask = g_Formats[8].LevelsMask;
|
||||
LevelsStart = 20;
|
||||
LevelsEnd = 29;
|
||||
} else if (GetMethodID() == kLIZARD_M3) {
|
||||
LevelsMask = g_Formats[8].LevelsMask;
|
||||
LevelsStart = 30;
|
||||
LevelsEnd = 39;
|
||||
} else if (GetMethodID() == kLIZARD_M4) {
|
||||
LevelsMask = g_Formats[8].LevelsMask;
|
||||
LevelsStart = 40;
|
||||
LevelsEnd = 49;
|
||||
} else if (GetMethodID() == kLZ4)
|
||||
LevelsMask = g_Formats[9].LevelsMask;
|
||||
else if (GetMethodID() == kLZ5)
|
||||
@@ -1114,13 +1160,13 @@ void CCompressDialog::SetLevel()
|
||||
else
|
||||
LevelsMask = g_Formats[GetStaticFormatIndex()].LevelsMask;
|
||||
|
||||
for (i = LevelsStart; i <= 49; i++)
|
||||
for (i = LevelsStart; i <= LevelsEnd; i++)
|
||||
{
|
||||
TCHAR s[40];
|
||||
TCHAR t[50] = { TEXT('L'), TEXT('e'), TEXT('v'), TEXT('e'), TEXT('l'), TEXT(' '), 0 };
|
||||
|
||||
// lizard needs extra handling
|
||||
if (GetMethodID() == kLIZARD) {
|
||||
if (GetMethodID() >= kLIZARD_M1 && GetMethodID() <= kLIZARD_M4) {
|
||||
ir = i;
|
||||
if (ir % 10 == 0) langID = 0;
|
||||
while (ir > 19) { ir -= 10; }
|
||||
@@ -1153,7 +1199,6 @@ void CCompressDialog::SetLevel()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
|
||||
{
|
||||
return cb.AddString((CSysString)s);
|
||||
@@ -1174,33 +1219,56 @@ void CCompressDialog::SetMethod(int keepMethodId)
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
int index = FindRegistryFormat(ai.Name);
|
||||
UString defaultMethod;
|
||||
if (index >= 0)
|
||||
{
|
||||
int defaultLevel = 5;
|
||||
if (index >= 0) {
|
||||
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
||||
defaultMethod = fo.Method;
|
||||
defaultLevel = fo.Level;
|
||||
}
|
||||
|
||||
bool isSfx = IsSFX();
|
||||
bool weUseSameMethod = false;
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
wchar_t buf[2000];
|
||||
wsprintf(buf, L"keep=%d level = %d method=%s", keepMethodId, defaultLevel, (LPCWSTR)defaultMethod);
|
||||
ShowErrorMessage(*this, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for (unsigned m = 0; m < fi.NumMethods; m++)
|
||||
{
|
||||
EMethodID methodID = fi.MathodIDs[m];
|
||||
if (isSfx)
|
||||
if (!IsMethodSupportedBySfx(methodID))
|
||||
continue;
|
||||
|
||||
const char *methodLong = kMethodsLongnames[methodID];
|
||||
const char *method = kMethodsNames[methodID];
|
||||
int itemIndex = (int)ComboBox_AddStringAscii(m_Method, method);
|
||||
int itemIndex = (int)ComboBox_AddStringAscii(m_Method, methodLong);
|
||||
m_Method.SetItemData(itemIndex, methodID);
|
||||
if (keepMethodId == methodID)
|
||||
{
|
||||
m_Method.SetCurSel(itemIndex);
|
||||
|
||||
if (keepMethodId == methodID) {
|
||||
weUseSameMethod = true;
|
||||
m_Method.SetCurSel(itemIndex);
|
||||
continue;
|
||||
}
|
||||
if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod)
|
||||
|
||||
// Lizard :/
|
||||
if (defaultMethod.IsEqualTo_Ascii_NoCase("lizard") && keepMethodId == -1) {
|
||||
if (defaultLevel >= 10 && defaultLevel <= 19) m_Method.SetCurSel(kLIZARD_M1 - 1);
|
||||
if (defaultLevel >= 20 && defaultLevel <= 29) m_Method.SetCurSel(kLIZARD_M2 - 1);
|
||||
if (defaultLevel >= 30 && defaultLevel <= 39) m_Method.SetCurSel(kLIZARD_M3 - 1);
|
||||
if (defaultLevel >= 40 && defaultLevel <= 49) m_Method.SetCurSel(kLIZARD_M4 - 1);
|
||||
}
|
||||
|
||||
if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod) {
|
||||
m_Method.SetCurSel(itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!weUseSameMethod)
|
||||
{
|
||||
SetDictionary();
|
||||
@@ -1672,7 +1740,10 @@ void CCompressDialog::SetNumThreads()
|
||||
case kBROTLI: numAlgoThreadsMax = 128; break;
|
||||
case kLZ4: numAlgoThreadsMax = 128; break;
|
||||
case kLZ5: numAlgoThreadsMax = 128; break;
|
||||
case kLIZARD: numAlgoThreadsMax = 128; break;
|
||||
case kLIZARD_M1: numAlgoThreadsMax = 128; break;
|
||||
case kLIZARD_M2: numAlgoThreadsMax = 128; break;
|
||||
case kLIZARD_M3: numAlgoThreadsMax = 128; break;
|
||||
case kLIZARD_M4: numAlgoThreadsMax = 128; break;
|
||||
case kLZMA: numAlgoThreadsMax = 2; break;
|
||||
case kLZMA2: numAlgoThreadsMax = 32; break;
|
||||
case kBZip2: numAlgoThreadsMax = 32; break;
|
||||
|
||||
@@ -62,9 +62,9 @@ License:
|
||||
Zstandard library is provided as open source software using the BSD license.
|
||||
|
||||
7-Zip Container Header:
|
||||
This header is mandatory and must be exact 5 bytes. The data within that header
|
||||
is for informational purposes only and not used by the decoder. If the header
|
||||
is not there, or has another size, the decoder will not decompress the content.
|
||||
|
||||
This header is for informational purposes only. It's not mandatory for
|
||||
decompressing the data.
|
||||
``` C
|
||||
Byte _ver_major; // currently 1
|
||||
Byte _ver_minor; // currently 2
|
||||
@@ -119,9 +119,9 @@ License:
|
||||
The Brotli library is provided as open source software using the MIT license.
|
||||
|
||||
7-Zip Container Header (3 bytes):
|
||||
This header is mandatory and must be exact 3 bytes. The data within that header
|
||||
is for informational purposes only and not used by the decoder. If the header
|
||||
is not there, or has another size, the decoder will not decompress the content.
|
||||
|
||||
This header is for informational purposes only. It's not mandatory for
|
||||
decompressing the data.
|
||||
``` C
|
||||
Byte _ver_major; // currently 0
|
||||
Byte _ver_minor; // currently 6
|
||||
@@ -164,9 +164,9 @@ License:
|
||||
LZ4 library is provided as open source software using the BSD license.
|
||||
|
||||
7-Zip Container Header:
|
||||
This header is mandatory and must be exact 5 bytes. The data within that header
|
||||
is for informational purposes only and not used by the decoder. If the header
|
||||
is not there, or has another size, the decoder will not decompress the content.
|
||||
|
||||
This header is for informational purposes only. It's not mandatory for
|
||||
decompressing the data.
|
||||
``` C
|
||||
Byte _ver_major; // currently 1
|
||||
Byte _ver_minor; // currently 7
|
||||
@@ -215,9 +215,9 @@ License:
|
||||
LZ5 library is provided as open source software using the BSD license.
|
||||
|
||||
7-Zip Container Header:
|
||||
This header is mandatory and must be exact 5 bytes. The data within that header
|
||||
is for informational purposes only and not used by the decoder. If the header
|
||||
is not there, or has another size, the decoder will not decompress the content.
|
||||
|
||||
This header is for informational purposes only. It's not mandatory for
|
||||
decompressing the data.
|
||||
``` C
|
||||
Byte _ver_major; // currently 1
|
||||
Byte _ver_minor; // currently 5
|
||||
@@ -264,9 +264,9 @@ License:
|
||||
Lizard library is provided as open source software using the BSD license.
|
||||
|
||||
7-Zip Container Header:
|
||||
This header is mandatory and must be exact 3 bytes. The data within that header
|
||||
is for informational purposes only and not used by the decoder. If the header
|
||||
is not there, or has another size, the decoder will not decompress the content.
|
||||
|
||||
This header is for informational purposes only. It's not mandatory for
|
||||
decompressing the data.
|
||||
``` C
|
||||
Byte _ver_major; // currently 2
|
||||
Byte _ver_minor; // currently 0
|
||||
|
||||
Reference in New Issue
Block a user